converted tabs for C, JS, BASH to 4 spaces
Costa Tsaousis committed
Aug 13, 2016 at 22:08 UTC
c50ec4efef94710302a2da98b78d8a2bfc567c35
68 files changed
+22674
-22674
netdata-installer.sh
+698
-698
@@ -26,18 +26,18 @@ printf "\n" >>netdata-installer.log
26
service="$(which service 2>/dev/null || command -v service 2>/dev/null)"
27
systemctl="$(which systemctl 2>/dev/null || command -v systemctl 2>/dev/null)"
28
service() {
29
- local cmd="${1}" action="${2}"
30
-
31
- if [ ! -z "${service}" ]
32
- then
33
- run "${service}" "${cmd}" "${action}"
34
- return $?
35
- elif [ ! -z "${systemctl}" ]
36
- then
37
- run "${systemctl}" "${action}" "${cmd}"
38
- return $?
39
- fi
40
- return 1
29
+ local cmd="${1}" action="${2}"
30
+
31
+ if [ ! -z "${service}" ]
32
+ then
33
+ run "${service}" "${cmd}" "${action}"
34
+ return $?
35
+ elif [ ! -z "${systemctl}" ]
36
+ then
37
+ run "${systemctl}" "${action}" "${cmd}"
38
+ return $?
39
+ fi
40
+ return 1
41
}
42
43
ME="$0"
@@ -47,353 +47,353 @@ NETDATA_PREFIX=
47
LIBS_ARE_HERE=0
48
49
usage() {
50
- cat <<-USAGE
50
+ cat <<-USAGE
51
52
- ${ME} <installer options>
52
+ ${ME} <installer options>
53
54
- Valid <installer options> are:
54
+ Valid <installer options> are:
55
56
- --install /PATH/TO/INSTALL
56
+ --install /PATH/TO/INSTALL
57
58
- If your give: --install /opt
59
- netdata will be installed in /opt/netdata
58
+ If your give: --install /opt
59
+ netdata will be installed in /opt/netdata
60
61
- --dont-start-it
61
+ --dont-start-it
62
63
- Do not (re)start netdata.
64
- Just install it.
63
+ Do not (re)start netdata.
64
+ Just install it.
65
66
- --dont-wait
66
+ --dont-wait
67
68
- Do not wait for the user to press ENTER.
69
- Start immediately building it.
68
+ Do not wait for the user to press ENTER.
69
+ Start immediately building it.
70
71
- --zlib-is-really-here
72
- --libs-are-really-here
71
+ --zlib-is-really-here
72
+ --libs-are-really-here
73
74
- If you get errors about missing zlib,
75
- or libuuid but you know it is available,
76
- you have a broken pkg-config.
77
- Use this option to allow it continue
78
- without checking pkg-config.
74
+ If you get errors about missing zlib,
75
+ or libuuid but you know it is available,
76
+ you have a broken pkg-config.
77
+ Use this option to allow it continue
78
+ without checking pkg-config.
79
80
- Netdata will by default be compiled with gcc optimization -O3
81
- If you need to pass different CFLAGS, use something like this:
80
+ Netdata will by default be compiled with gcc optimization -O3
81
+ If you need to pass different CFLAGS, use something like this:
82
83
- CFLAGS="<gcc options>" ${ME} <installer options>
83
+ CFLAGS="<gcc options>" ${ME} <installer options>
84
85
- For the installer to complete successfully, you will need
86
- these packages installed:
85
+ For the installer to complete successfully, you will need
86
+ these packages installed:
87
88
- gcc make autoconf automake pkg-config zlib1g-dev (or zlib-devel)
89
- uuid-dev (or libuuid-devel)
88
+ gcc make autoconf automake pkg-config zlib1g-dev (or zlib-devel)
89
+ uuid-dev (or libuuid-devel)
90
91
- For the plugins, you will at least need:
91
+ For the plugins, you will at least need:
92
93
- curl nodejs
93
+ curl nodejs
94
95
USAGE
96
}
97
98
md5sum="$(which md5sum 2>/dev/null || command -v md5sum 2>/dev/null)"
99
get_git_config_signatures() {
100
- local x s file md5
101
-
102
- [ ! -d "conf.d" ] && echo >&2 "Wrong directory." && return 1
103
- [ -z "${md5sum}" -o ! -x "${md5sum}" ] && echo >&2 "No md5sum command." && return 1
104
-
105
- echo >configs.signatures.tmp
106
-
107
- for x in $(find conf.d -name \*.conf)
108
- do
109
- x="${x/conf.d\//}"
110
- echo "${x}"
111
- for c in $(git log --follow "conf.d/${x}" | grep ^commit | cut -d ' ' -f 2)
112
- do
113
- git checkout ${c} "conf.d/${x}" || continue
114
- s="$(cat "conf.d/${x}" | md5sum | cut -d ' ' -f 1)"
115
- echo >>configs.signatures.tmp "${x}:${s}"
116
- echo " ${s}"
117
- done
118
- git checkout HEAD "conf.d/${x}" || break
119
- done
120
-
121
- cat configs.signatures.tmp |\
122
- grep -v "^$" |\
123
- sort -u |\
124
- {
125
- echo "declare -A configs_signatures=("
126
- IFS=":"
127
- while read file md5
128
- do
129
- echo " ['${md5}']='${file}'"
130
- done
131
- echo ")"
132
- } >configs.signatures
133
-
134
- rm configs.signatures.tmp
135
-
136
- return 0
100
+ local x s file md5
101
+
102
+ [ ! -d "conf.d" ] && echo >&2 "Wrong directory." && return 1
103
+ [ -z "${md5sum}" -o ! -x "${md5sum}" ] && echo >&2 "No md5sum command." && return 1
104
+
105
+ echo >configs.signatures.tmp
106
+
107
+ for x in $(find conf.d -name \*.conf)
108
+ do
109
+ x="${x/conf.d\//}"
110
+ echo "${x}"
111
+ for c in $(git log --follow "conf.d/${x}" | grep ^commit | cut -d ' ' -f 2)
112
+ do
113
+ git checkout ${c} "conf.d/${x}" || continue
114
+ s="$(cat "conf.d/${x}" | md5sum | cut -d ' ' -f 1)"
115
+ echo >>configs.signatures.tmp "${x}:${s}"
116
+ echo " ${s}"
117
+ done
118
+ git checkout HEAD "conf.d/${x}" || break
119
+ done
120
+
121
+ cat configs.signatures.tmp |\
122
+ grep -v "^$" |\
123
+ sort -u |\
124
+ {
125
+ echo "declare -A configs_signatures=("
126
+ IFS=":"
127
+ while read file md5
128
+ do
129
+ echo " ['${md5}']='${file}'"
130
+ done
131
+ echo ")"
132
+ } >configs.signatures
133
+
134
+ rm configs.signatures.tmp
135
+
136
+ return 0
137
}
138
139
140
while [ ! -z "${1}" ]
141
do
142
- if [ "$1" = "--install" ]
143
- then
144
- NETDATA_PREFIX="${2}/netdata"
145
- shift 2
146
- elif [ "$1" = "--zlib-is-really-here" -o "$1" = "--libs-are-really-here" ]
147
- then
148
- LIBS_ARE_HERE=1
149
- shift 1
150
- elif [ "$1" = "--dont-start-it" ]
151
- then
152
- DONOTSTART=1
153
- shift 1
154
- elif [ "$1" = "--dont-wait" ]
155
- then
156
- DONOTWAIT=1
157
- shift 1
158
- elif [ "$1" = "--help" -o "$1" = "-h" ]
159
- then
160
- usage
161
- exit 1
162
- elif [ "$1" = "get_git_config_signatures" ]
163
- then
164
- get_git_config_signatures && exit 0
165
- exit 1
166
- else
167
- echo >&2
168
- echo >&2 "ERROR:"
169
- echo >&2 "I cannot understand option '$1'."
170
- usage
171
- exit 1
172
- fi
142
+ if [ "$1" = "--install" ]
143
+ then
144
+ NETDATA_PREFIX="${2}/netdata"
145
+ shift 2
146
+ elif [ "$1" = "--zlib-is-really-here" -o "$1" = "--libs-are-really-here" ]
147
+ then
148
+ LIBS_ARE_HERE=1
149
+ shift 1
150
+ elif [ "$1" = "--dont-start-it" ]
151
+ then
152
+ DONOTSTART=1
153
+ shift 1
154
+ elif [ "$1" = "--dont-wait" ]
155
+ then
156
+ DONOTWAIT=1
157
+ shift 1
158
+ elif [ "$1" = "--help" -o "$1" = "-h" ]
159
+ then
160
+ usage
161
+ exit 1
162
+ elif [ "$1" = "get_git_config_signatures" ]
163
+ then
164
+ get_git_config_signatures && exit 0
165
+ exit 1
166
+ else
167
+ echo >&2
168
+ echo >&2 "ERROR:"
169
+ echo >&2 "I cannot understand option '$1'."
170
+ usage
171
+ exit 1
172
+ fi
173
done
174
175
cat <<-BANNER
176
177
- Welcome to netdata!
178
- Nice to see you are giving it a try!
177
+ Welcome to netdata!
178
+ Nice to see you are giving it a try!
179
180
- You are about to build and install netdata to your system.
180
+ You are about to build and install netdata to your system.
181
182
- It will be installed at these locations:
182
+ It will be installed at these locations:
183
184
- - the daemon at ${NETDATA_PREFIX}/usr/sbin/netdata
185
- - config files at ${NETDATA_PREFIX}/etc/netdata
186
- - web files at ${NETDATA_PREFIX}/usr/share/netdata
187
- - plugins at ${NETDATA_PREFIX}/usr/libexec/netdata
188
- - cache files at ${NETDATA_PREFIX}/var/cache/netdata
189
- - db files at ${NETDATA_PREFIX}/var/lib/netdata
190
- - log files at ${NETDATA_PREFIX}/var/log/netdata
191
- - pid file at ${NETDATA_PREFIX}/var/run
184
+ - the daemon at ${NETDATA_PREFIX}/usr/sbin/netdata
185
+ - config files at ${NETDATA_PREFIX}/etc/netdata
186
+ - web files at ${NETDATA_PREFIX}/usr/share/netdata
187
+ - plugins at ${NETDATA_PREFIX}/usr/libexec/netdata
188
+ - cache files at ${NETDATA_PREFIX}/var/cache/netdata
189
+ - db files at ${NETDATA_PREFIX}/var/lib/netdata
190
+ - log files at ${NETDATA_PREFIX}/var/log/netdata
191
+ - pid file at ${NETDATA_PREFIX}/var/run
192
193
- This installer allows you to change the installation path.
194
- Press Control-C and run the same command with --help for help.
193
+ This installer allows you to change the installation path.
194
+ Press Control-C and run the same command with --help for help.
195
196
BANNER
197
198
if [ "${UID}" -ne 0 ]
199
- then
200
- if [ -z "${NETDATA_PREFIX}" ]
201
- then
202
- cat <<-NONROOTNOPREFIX
199
+ then
200
+ if [ -z "${NETDATA_PREFIX}" ]
201
+ then
202
+ cat <<-NONROOTNOPREFIX
203
204
- Sorry! This will fail!
204
+ Sorry! This will fail!
205
206
- You are attempting to install netdata as non-root, but you plan to install it
207
- in system paths.
206
+ You are attempting to install netdata as non-root, but you plan to install it
207
+ in system paths.
208
209
- Please set an installation prefix, like this:
209
+ Please set an installation prefix, like this:
210
211
- $0 ${@} --install /tmp
211
+ $0 ${@} --install /tmp
212
213
- or, run the installer as root:
213
+ or, run the installer as root:
214
215
- sudo $0 ${@}
215
+ sudo $0 ${@}
216
217
- We suggest to install it as root, or certain data collectors will not be able
218
- to work. Netdata drops root privileges when running. So, if you plan to keep
219
- it, install it as root to get the full functionality.
217
+ We suggest to install it as root, or certain data collectors will not be able
218
+ to work. Netdata drops root privileges when running. So, if you plan to keep
219
+ it, install it as root to get the full functionality.
220
221
NONROOTNOPREFIX
222
- exit 1
222
+ exit 1
223
224
- else
225
- cat <<-NONROOT
224
+ else
225
+ cat <<-NONROOT
226
227
- IMPORTANT:
228
- You are about to install netdata as a non-root user.
229
- Netdata will work, but a few data collection modules that
230
- require root access will fail.
227
+ IMPORTANT:
228
+ You are about to install netdata as a non-root user.
229
+ Netdata will work, but a few data collection modules that
230
+ require root access will fail.
231
232
- If you installing permanently on your system, run the
233
- installer like this:
232
+ If you installing permanently on your system, run the
233
+ installer like this:
234
235
- sudo $0 ${@}
235
+ sudo $0 ${@}
236
237
NONROOT
238
- fi
238
+ fi
239
fi
240
241
have_autotools=
242
if [ "$(type autoreconf 2> /dev/null)" ]
243
then
244
- autoconf_maj_min() {
245
- local maj min IFS=.-
246
-
247
- maj=$1
248
- min=$2
249
-
250
- set -- $(autoreconf -V | sed -ne '1s/.* \([^ ]*\)$/\1/p')
251
- eval $maj=\$1 $min=\$2
252
- }
253
- autoconf_maj_min AMAJ AMIN
254
-
255
- if [ "$AMAJ" -gt 2 ]
256
- then
257
- have_autotools=Y
258
- elif [ "$AMAJ" -eq 2 -a "$AMIN" -ge 60 ]
259
- then
260
- have_autotools=Y
261
- else
262
- echo "Found autotools $AMAJ.$AMIN"
263
- fi
244
+ autoconf_maj_min() {
245
+ local maj min IFS=.-
246
+
247
+ maj=$1
248
+ min=$2
249
+
250
+ set -- $(autoreconf -V | sed -ne '1s/.* \([^ ]*\)$/\1/p')
251
+ eval $maj=\$1 $min=\$2
252
+ }
253
+ autoconf_maj_min AMAJ AMIN
254
+
255
+ if [ "$AMAJ" -gt 2 ]
256
+ then
257
+ have_autotools=Y
258
+ elif [ "$AMAJ" -eq 2 -a "$AMIN" -ge 60 ]
259
+ then
260
+ have_autotools=Y
261
+ else
262
+ echo "Found autotools $AMAJ.$AMIN"
263
+ fi
264
else
265
- echo "No autotools found"
265
+ echo "No autotools found"
266
fi
267
268
if [ ! "$have_autotools" ]
269
then
270
- if [ -f configure ]
271
- then
272
- echo "Will skip autoreconf step"
273
- else
274
- cat <<-"EOF"
270
+ if [ -f configure ]
271
+ then
272
+ echo "Will skip autoreconf step"
273
+ else
274
+ cat <<-"EOF"
275
276
- -------------------------------------------------------------------------------
277
- autotools 2.60 or later is required
276
+ -------------------------------------------------------------------------------
277
+ autotools 2.60 or later is required
278
279
- Sorry, you do not seem to have autotools 2.60 or later, which is
280
- required to build from the git sources of netdata.
279
+ Sorry, you do not seem to have autotools 2.60 or later, which is
280
+ required to build from the git sources of netdata.
281
282
- You can either install a suitable version of autotools and automake
283
- or download a netdata package which does not have these dependencies.
282
+ You can either install a suitable version of autotools and automake
283
+ or download a netdata package which does not have these dependencies.
284
285
- Source packages where autotools have already been run are available
286
- here:
287
- https://firehol.org/download/netdata/
285
+ Source packages where autotools have already been run are available
286
+ here:
287
+ https://firehol.org/download/netdata/
288
289
- The unsigned/master folder tracks the head of the git tree and released
290
- packages are also available.
289
+ The unsigned/master folder tracks the head of the git tree and released
290
+ packages are also available.
291
EOF
292
- exit 1
293
- fi
292
+ exit 1
293
+ fi
294
fi
295
296
if [ ${DONOTWAIT} -eq 0 ]
297
- then
298
- if [ ! -z "${NETDATA_PREFIX}" ]
299
- then
300
- read -p "Press ENTER to build and install netdata to '${NETDATA_PREFIX}' > "
301
- else
302
- read -p "Press ENTER to build and install netdata to your system > "
303
- fi
297
+ then
298
+ if [ ! -z "${NETDATA_PREFIX}" ]
299
+ then
300
+ read -p "Press ENTER to build and install netdata to '${NETDATA_PREFIX}' > "
301
+ else
302
+ read -p "Press ENTER to build and install netdata to your system > "
303
+ fi
304
fi
305
306
build_error() {
307
- cat <<-EOF
307
+ cat <<-EOF
308
309
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
309
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
310
311
- Sorry! NetData failed to build...
311
+ Sorry! NetData failed to build...
312
313
- You many need to check these:
313
+ You many need to check these:
314
315
- 1. The package uuid-dev (or libuuid-devel) has to be installed.
315
+ 1. The package uuid-dev (or libuuid-devel) has to be installed.
316
317
- If your system cannot find libuuid, although it is installed
318
- run me with the option: --libs-are-really-here
317
+ If your system cannot find libuuid, although it is installed
318
+ run me with the option: --libs-are-really-here
319
320
- 2. The package zlib1g-dev (or zlib-devel) has to be installed.
320
+ 2. The package zlib1g-dev (or zlib-devel) has to be installed.
321
322
- If your system cannot find zlib, although it is installed
323
- run me with the option: --libs-are-really-here
322
+ If your system cannot find zlib, although it is installed
323
+ run me with the option: --libs-are-really-here
324
325
- 3. You need basic build tools installed, like:
325
+ 3. You need basic build tools installed, like:
326
327
- gcc make autoconf automake pkg-config
327
+ gcc make autoconf automake pkg-config
328
329
- Autoconf version 2.60 or higher is required.
329
+ Autoconf version 2.60 or higher is required.
330
331
- If you still cannot get it to build, ask for help at github:
331
+ If you still cannot get it to build, ask for help at github:
332
333
- https://github.com/firehol/netdata/issues
333
+ https://github.com/firehol/netdata/issues
334
335
336
EOF
337
- trap - EXIT
338
- exit 1
337
+ trap - EXIT
338
+ exit 1
339
}
340
341
run() {
342
- printf >>netdata-installer.log "# "
343
- printf >>netdata-installer.log "%q " "${@}"
344
- printf >>netdata-installer.log " ... "
345
-
346
- printf >&2 "\n"
347
- printf >&2 ":-----------------------------------------------------------------------------\n"
348
- printf >&2 "Running command:\n"
349
- printf >&2 "\n"
350
- printf >&2 "%q " "${@}"
351
- printf >&2 "\n"
352
-
353
- "${@}"
354
-
355
- local ret=$?
356
- if [ ${ret} -ne 0 ]
357
- then
358
- printf >>netdata-installer.log "FAILED!\n"
359
- else
360
- printf >>netdata-installer.log "OK\n"
361
- fi
362
-
363
- return ${ret}
342
+ printf >>netdata-installer.log "# "
343
+ printf >>netdata-installer.log "%q " "${@}"
344
+ printf >>netdata-installer.log " ... "
345
+
346
+ printf >&2 "\n"
347
+ printf >&2 ":-----------------------------------------------------------------------------\n"
348
+ printf >&2 "Running command:\n"
349
+ printf >&2 "\n"
350
+ printf >&2 "%q " "${@}"
351
+ printf >&2 "\n"
352
+
353
+ "${@}"
354
+
355
+ local ret=$?
356
+ if [ ${ret} -ne 0 ]
357
+ then
358
+ printf >>netdata-installer.log "FAILED!\n"
359
+ else
360
+ printf >>netdata-installer.log "OK\n"
361
+ fi
362
+
363
+ return ${ret}
364
}
365
366
if [ ${LIBS_ARE_HERE} -eq 1 ]
367
- then
368
- shift
369
- echo >&2 "ok, assuming libs are really installed."
370
- export ZLIB_CFLAGS=" "
371
- export ZLIB_LIBS="-lz"
372
- export UUID_CFLAGS=" "
373
- export UUID_LIBS="-luuid"
367
+ then
368
+ shift
369
+ echo >&2 "ok, assuming libs are really installed."
370
+ export ZLIB_CFLAGS=" "
371
+ export ZLIB_LIBS="-lz"
372
+ export UUID_CFLAGS=" "
373
+ export UUID_LIBS="-luuid"
374
fi
375
376
trap build_error EXIT
377
378
if [ "$have_autotools" ]
379
then
380
- run ./autogen.sh || exit 1
380
+ run ./autogen.sh || exit 1
381
fi
382
383
run ./configure \
384
- --prefix="${NETDATA_PREFIX}/usr" \
385
- --sysconfdir="${NETDATA_PREFIX}/etc" \
386
- --localstatedir="${NETDATA_PREFIX}/var" \
387
- --with-zlib --with-math --with-user=netdata \
388
- CFLAGS="${CFLAGS}" || exit 1
384
+ --prefix="${NETDATA_PREFIX}/usr" \
385
+ --sysconfdir="${NETDATA_PREFIX}/etc" \
386
+ --localstatedir="${NETDATA_PREFIX}/var" \
387
+ --with-zlib --with-math --with-user=netdata \
388
+ CFLAGS="${CFLAGS}" || exit 1
389
390
# remove the build_error hook
391
trap - EXIT
392
393
if [ -f src/netdata ]
394
- then
395
- echo >&2 "Cleaning a possibly old compilation ..."
396
- run make clean
394
+ then
395
+ echo >&2 "Cleaning a possibly old compilation ..."
396
+ run make clean
397
fi
398
399
echo >&2 "Compiling netdata ..."
@@ -401,101 +401,101 @@ run make || exit 1
401
402
if [ "${BASH_VERSINFO[0]}" -ge "4" ]
403
then
404
- declare -A configs_signatures=()
405
- if [ -f "configs.signatures" ]
406
- then
407
- source "configs.signatures" || echo >&2 "ERROR: Failed to load configs.signatures !"
408
- fi
404
+ declare -A configs_signatures=()
405
+ if [ -f "configs.signatures" ]
406
+ then
407
+ source "configs.signatures" || echo >&2 "ERROR: Failed to load configs.signatures !"
408
+ fi
409
fi
410
411
# migrate existing configuration files
412
# for node.d and charts.d
413
if [ -d "${NETDATA_PREFIX}/etc/netdata" ]
414
- then
415
- # the configuration directory exists
416
-
417
- if [ ! -d "${NETDATA_PREFIX}/etc/netdata/charts.d" ]
418
- then
419
- run mkdir "${NETDATA_PREFIX}/etc/netdata/charts.d"
420
- fi
421
-
422
- # move the charts.d config files
423
- for x in apache ap cpu_apps cpufreq example exim hddtemp load_average mem_apps mysql nginx nut opensips phpfpm postfix sensors squid tomcat
424
- do
425
- for y in "" ".old" ".orig"
426
- do
427
- if [ -f "${NETDATA_PREFIX}/etc/netdata/${x}.conf${y}" -a ! -f "${NETDATA_PREFIX}/etc/netdata/charts.d/${x}.conf${y}" ]
428
- then
429
- run mv -f "${NETDATA_PREFIX}/etc/netdata/${x}.conf${y}" "${NETDATA_PREFIX}/etc/netdata/charts.d/${x}.conf${y}"
430
- fi
431
- done
432
- done
433
-
434
- if [ ! -d "${NETDATA_PREFIX}/etc/netdata/node.d" ]
435
- then
436
- run mkdir "${NETDATA_PREFIX}/etc/netdata/node.d"
437
- fi
438
-
439
- # move the node.d config files
440
- for x in named sma_webbox snmp
441
- do
442
- for y in "" ".old" ".orig"
443
- do
444
- if [ -f "${NETDATA_PREFIX}/etc/netdata/${x}.conf${y}" -a ! -f "${NETDATA_PREFIX}/etc/netdata/node.d/${x}.conf${y}" ]
445
- then
446
- run mv -f "${NETDATA_PREFIX}/etc/netdata/${x}.conf${y}" "${NETDATA_PREFIX}/etc/netdata/node.d/${x}.conf${y}"
447
- fi
448
- done
449
- done
414
+ then
415
+ # the configuration directory exists
416
+
417
+ if [ ! -d "${NETDATA_PREFIX}/etc/netdata/charts.d" ]
418
+ then
419
+ run mkdir "${NETDATA_PREFIX}/etc/netdata/charts.d"
420
+ fi
421
+
422
+ # move the charts.d config files
423
+ for x in apache ap cpu_apps cpufreq example exim hddtemp load_average mem_apps mysql nginx nut opensips phpfpm postfix sensors squid tomcat
424
+ do
425
+ for y in "" ".old" ".orig"
426
+ do
427
+ if [ -f "${NETDATA_PREFIX}/etc/netdata/${x}.conf${y}" -a ! -f "${NETDATA_PREFIX}/etc/netdata/charts.d/${x}.conf${y}" ]
428
+ then
429
+ run mv -f "${NETDATA_PREFIX}/etc/netdata/${x}.conf${y}" "${NETDATA_PREFIX}/etc/netdata/charts.d/${x}.conf${y}"
430
+ fi
431
+ done
432
+ done
433
+
434
+ if [ ! -d "${NETDATA_PREFIX}/etc/netdata/node.d" ]
435
+ then
436
+ run mkdir "${NETDATA_PREFIX}/etc/netdata/node.d"
437
+ fi
438
+
439
+ # move the node.d config files
440
+ for x in named sma_webbox snmp
441
+ do
442
+ for y in "" ".old" ".orig"
443
+ do
444
+ if [ -f "${NETDATA_PREFIX}/etc/netdata/${x}.conf${y}" -a ! -f "${NETDATA_PREFIX}/etc/netdata/node.d/${x}.conf${y}" ]
445
+ then
446
+ run mv -f "${NETDATA_PREFIX}/etc/netdata/${x}.conf${y}" "${NETDATA_PREFIX}/etc/netdata/node.d/${x}.conf${y}"
447
+ fi
448
+ done
449
+ done
450
fi
451
452
# backup user configurations
453
installer_backup_suffix="${PID}.${RANDOM}"
454
for x in $(find "${NETDATA_PREFIX}/etc/netdata/" -name '*.conf' -type f)
455
do
456
- if [ -f "${x}" ]
457
- then
458
- # make a backup of the configuration file
459
- cp -p "${x}" "${x}.old"
460
-
461
- if [ -z "${md5sum}" -o ! -x "${md5sum}" ]
462
- then
463
- # we don't have md5sum - keep it
464
- cp -p "${x}" "${x}.installer_backup.${installer_backup_suffix}"
465
- else
466
- # find it relative filename
467
- f="${x/*\/etc\/netdata\//}"
468
-
469
- # find its checksum
470
- md5="$(cat "${x}" | ${md5sum} | cut -d ' ' -f 1)"
471
-
472
- # copy the original
473
- if [ -f "conf.d/${f}" ]
474
- then
475
- cp "conf.d/${f}" "${x}.orig"
476
- fi
477
-
478
- if [ "${BASH_VERSINFO[0]}" -ge "4" ]
479
- then
480
- if [ "${configs_signatures[${md5}]}" = "${f}" ]
481
- then
482
- # it is a stock version - don't keep it
483
- echo >&2 "File '${x}' is stock version."
484
- else
485
- # edited by user - keep it
486
- echo >&2 "File '${x}' has been edited by user."
487
- cp -p "${x}" "${x}.installer_backup.${installer_backup_suffix}"
488
- fi
489
- else
490
- echo >&2 "File '${x}' cannot be check for custom edits."
491
- cp -p "${x}" "${x}.installer_backup.${installer_backup_suffix}"
492
- fi
493
- fi
494
-
495
- elif [ -f "${x}.installer_backup.${installer_backup_suffix}" ]
496
- then
497
- rm -f "${x}.installer_backup.${installer_backup_suffix}"
498
- fi
456
+ if [ -f "${x}" ]
457
+ then
458
+ # make a backup of the configuration file
459
+ cp -p "${x}" "${x}.old"
460
+
461
+ if [ -z "${md5sum}" -o ! -x "${md5sum}" ]
462
+ then
463
+ # we don't have md5sum - keep it
464
+ cp -p "${x}" "${x}.installer_backup.${installer_backup_suffix}"
465
+ else
466
+ # find it relative filename
467
+ f="${x/*\/etc\/netdata\//}"
468
+
469
+ # find its checksum
470
+ md5="$(cat "${x}" | ${md5sum} | cut -d ' ' -f 1)"
471
+
472
+ # copy the original
473
+ if [ -f "conf.d/${f}" ]
474
+ then
475
+ cp "conf.d/${f}" "${x}.orig"
476
+ fi
477
+
478
+ if [ "${BASH_VERSINFO[0]}" -ge "4" ]
479
+ then
480
+ if [ "${configs_signatures[${md5}]}" = "${f}" ]
481
+ then
482
+ # it is a stock version - don't keep it
483
+ echo >&2 "File '${x}' is stock version."
484
+ else
485
+ # edited by user - keep it
486
+ echo >&2 "File '${x}' has been edited by user."
487
+ cp -p "${x}" "${x}.installer_backup.${installer_backup_suffix}"
488
+ fi
489
+ else
490
+ echo >&2 "File '${x}' cannot be check for custom edits."
491
+ cp -p "${x}" "${x}.installer_backup.${installer_backup_suffix}"
492
+ fi
493
+ fi
494
+
495
+ elif [ -f "${x}.installer_backup.${installer_backup_suffix}" ]
496
+ then
497
+ rm -f "${x}.installer_backup.${installer_backup_suffix}"
498
+ fi
499
done
500
501
echo >&2 "Installing netdata ..."
@@ -504,53 +504,53 @@ run make install || exit 1
504
# restore user configurations
505
for x in $(find "${NETDATA_PREFIX}/etc/netdata/" -name '*.conf' -type f)
506
do
507
- if [ -f "${x}.installer_backup.${installer_backup_suffix}" ]
508
- then
509
- cp -p "${x}.installer_backup.${installer_backup_suffix}" "${x}"
510
- rm -f "${x}.installer_backup.${installer_backup_suffix}"
511
- fi
507
+ if [ -f "${x}.installer_backup.${installer_backup_suffix}" ]
508
+ then
509
+ cp -p "${x}.installer_backup.${installer_backup_suffix}" "${x}"
510
+ rm -f "${x}.installer_backup.${installer_backup_suffix}"
511
+ fi
512
done
513
514
NETDATA_ADDED_TO_DOCKER=0
515
if [ ${UID} -eq 0 ]
516
- then
517
- getent group netdata > /dev/null
518
- if [ $? -ne 0 ]
519
- then
520
- echo >&2 "Adding netdata user group ..."
521
- run groupadd -r netdata
522
- fi
523
-
524
- getent passwd netdata > /dev/null
525
- if [ $? -ne 0 ]
526
- then
527
- echo >&2 "Adding netdata user account ..."
528
- run useradd -r -g netdata -c netdata -s $(which nologin || echo '/bin/false') -d / netdata
529
- fi
530
-
531
- getent group docker > /dev/null
532
- if [ $? -eq 0 ]
533
- then
534
- # find the users in the docker group
535
- docker=$(getent group docker | cut -d ':' -f 4)
536
- if [[ ",${docker}," =~ ,netdata, ]]
537
- then
538
- # netdata is already there
539
- :
540
- else
541
- # netdata is not in docker group
542
- echo >&2 "Adding netdata user to the docker group (needed to get container names) ..."
543
- run usermod -a -G docker netdata
544
- fi
545
- # let the uninstall script know
546
- NETDATA_ADDED_TO_DOCKER=1
547
- fi
548
-
549
- if [ -d /etc/logrotate.d -a ! -f /etc/logrotate.d/netdata ]
550
- then
551
- echo >&2 "Adding netdata logrotate configuration ..."
552
- run cp system/netdata.logrotate /etc/logrotate.d/netdata
553
- fi
516
+ then
517
+ getent group netdata > /dev/null
518
+ if [ $? -ne 0 ]
519
+ then
520
+ echo >&2 "Adding netdata user group ..."
521
+ run groupadd -r netdata
522
+ fi
523
+
524
+ getent passwd netdata > /dev/null
525
+ if [ $? -ne 0 ]
526
+ then
527
+ echo >&2 "Adding netdata user account ..."
528
+ run useradd -r -g netdata -c netdata -s $(which nologin || echo '/bin/false') -d / netdata
529
+ fi
530
+
531
+ getent group docker > /dev/null
532
+ if [ $? -eq 0 ]
533
+ then
534
+ # find the users in the docker group
535
+ docker=$(getent group docker | cut -d ':' -f 4)
536
+ if [[ ",${docker}," =~ ,netdata, ]]
537
+ then
538
+ # netdata is already there
539
+ :
540
+ else
541
+ # netdata is not in docker group
542
+ echo >&2 "Adding netdata user to the docker group (needed to get container names) ..."
543
+ run usermod -a -G docker netdata
544
+ fi
545
+ # let the uninstall script know
546
+ NETDATA_ADDED_TO_DOCKER=1
547
+ fi
548
+
549
+ if [ -d /etc/logrotate.d -a ! -f /etc/logrotate.d/netdata ]
550
+ then
551
+ echo >&2 "Adding netdata logrotate configuration ..."
552
+ run cp system/netdata.logrotate /etc/logrotate.d/netdata
553
+ fi
554
fi
555
556
@@ -562,15 +562,15 @@ fi
562
563
# function to extract values from the config file
564
config_option() {
565
- local key="${1}" value="${2}" line=
565
+ local key="${1}" value="${2}" line=
566
567
- if [ -s "${NETDATA_PREFIX}/etc/netdata/netdata.conf" ]
568
- then
569
- line="$( grep "^[[:space:]]*${key}[[:space:]]*=[[:space:]]*" "${NETDATA_PREFIX}/etc/netdata/netdata.conf" | head -n 1 )"
570
- [ ! -z "${line}" ] && value="$( echo "${line}" | cut -d '=' -f 2 | sed -e "s/^[[:space:]]\+//g" -e "s/[[:space:]]\+$//g" )"
571
- fi
567
+ if [ -s "${NETDATA_PREFIX}/etc/netdata/netdata.conf" ]
568
+ then
569
+ line="$( grep "^[[:space:]]*${key}[[:space:]]*=[[:space:]]*" "${NETDATA_PREFIX}/etc/netdata/netdata.conf" | head -n 1 )"
570
+ [ ! -z "${line}" ] && value="$( echo "${line}" | cut -d '=' -f 2 | sed -e "s/^[[:space:]]\+//g" -e "s/[[:space:]]\+$//g" )"
571
+ fi
572
573
- echo "${value}"
573
+ echo "${value}"
574
}
575
576
# user
@@ -612,304 +612,304 @@ NETDATA_RUN_DIR="${NETDATA_PREFIX}/var/run"
612
613
# this is needed if NETDATA_PREFIX is not empty
614
if [ ! -d "${NETDATA_RUN_DIR}" ]
615
- then
616
- mkdir -p "${NETDATA_RUN_DIR}" || exit 1
615
+ then
616
+ mkdir -p "${NETDATA_RUN_DIR}" || exit 1
617
fi
618
619
echo >&2
620
echo >&2 "Fixing directories (user: ${NETDATA_USER})..."
621
for x in "${NETDATA_WEB_DIR}" "${NETDATA_CONF_DIR}" "${NETDATA_CACHE_DIR}" "${NETDATA_LOG_DIR}" "${NETDATA_LIB_DIR}" "${NETDATA_CONF_DIR}/python.d" "${NETDATA_CONF_DIR}/charts.d" "${NETDATA_CONF_DIR}/node.d"
622
do
623
- if [ ! -d "${x}" ]
624
- then
625
- echo >&2 "Creating directory '${x}'"
626
- run mkdir -p "${x}" || exit 1
627
- fi
628
-
629
- if [ ${UID} -eq 0 ]
630
- then
631
- if [ "${x}" = "${NETDATA_WEB_DIR}" ]
632
- then
633
- run chown -R "${NETDATA_WEB_USER}:${NETDATA_WEB_GROUP}" "${x}" || echo >&2 "WARNING: Cannot change the ownership of the files in directory ${x} to ${NETDATA_WEB_USER}:${NETDATA_WEB_GROUP}..."
634
- else
635
- run chown -R "${NETDATA_USER}:${NETDATA_USER}" "${x}" || echo >&2 "WARNING: Cannot change the ownership of the files in directory ${x} to ${NETDATA_USER}..."
636
- fi
637
- fi
638
-
639
- run chmod 0755 "${x}" || echo >&2 "WARNING: Cannot change the permissions of the directory ${x} to 0755..."
623
+ if [ ! -d "${x}" ]
624
+ then
625
+ echo >&2 "Creating directory '${x}'"
626
+ run mkdir -p "${x}" || exit 1
627
+ fi
628
+
629
+ if [ ${UID} -eq 0 ]
630
+ then
631
+ if [ "${x}" = "${NETDATA_WEB_DIR}" ]
632
+ then
633
+ run chown -R "${NETDATA_WEB_USER}:${NETDATA_WEB_GROUP}" "${x}" || echo >&2 "WARNING: Cannot change the ownership of the files in directory ${x} to ${NETDATA_WEB_USER}:${NETDATA_WEB_GROUP}..."
634
+ else
635
+ run chown -R "${NETDATA_USER}:${NETDATA_USER}" "${x}" || echo >&2 "WARNING: Cannot change the ownership of the files in directory ${x} to ${NETDATA_USER}..."
636
+ fi
637
+ fi
638
+
639
+ run chmod 0755 "${x}" || echo >&2 "WARNING: Cannot change the permissions of the directory ${x} to 0755..."
640
done
641
642
if [ ${UID} -eq 0 ]
643
- then
644
- run chown root "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/apps.plugin"
645
- run chmod 0755 "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/apps.plugin"
646
- run setcap cap_dac_read_search,cap_sys_ptrace+ep "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/apps.plugin"
647
- if [ $? -ne 0 ]
648
- then
649
- # fix apps.plugin to be setuid to root
650
- run chown root "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/apps.plugin"
651
- run chmod 4755 "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/apps.plugin"
652
- fi
643
+ then
644
+ run chown root "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/apps.plugin"
645
+ run chmod 0755 "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/apps.plugin"
646
+ run setcap cap_dac_read_search,cap_sys_ptrace+ep "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/apps.plugin"
647
+ if [ $? -ne 0 ]
648
+ then
649
+ # fix apps.plugin to be setuid to root
650
+ run chown root "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/apps.plugin"
651
+ run chmod 4755 "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/apps.plugin"
652
+ fi
653
fi
654
655
# -----------------------------------------------------------------------------
656
# check if we can re-start netdata
657
658
if [ ${DONOTSTART} -eq 1 ]
659
- then
660
- if [ ! -s "${NETDATA_PREFIX}/etc/netdata/netdata.conf" ]
661
- then
662
- echo >&2 "Generating empty config file in: ${NETDATA_PREFIX}/etc/netdata/netdata.conf"
663
- echo "# Get config from http://127.0.0.1:${NETDATA_PORT}/netdata.conf" >"${NETDATA_PREFIX}/etc/netdata/netdata.conf"
664
-
665
- if [ "${UID}" -eq 0 ]
666
- then
667
- chown "${NETDATA_USER}" "${NETDATA_PREFIX}/etc/netdata/netdata.conf"
668
- fi
669
- chmod 0664 "${NETDATA_PREFIX}/etc/netdata/netdata.conf"
670
- fi
671
- echo >&2 "OK. It is now installed and ready."
672
- exit 0
659
+ then
660
+ if [ ! -s "${NETDATA_PREFIX}/etc/netdata/netdata.conf" ]
661
+ then
662
+ echo >&2 "Generating empty config file in: ${NETDATA_PREFIX}/etc/netdata/netdata.conf"
663
+ echo "# Get config from http://127.0.0.1:${NETDATA_PORT}/netdata.conf" >"${NETDATA_PREFIX}/etc/netdata/netdata.conf"
664
+
665
+ if [ "${UID}" -eq 0 ]
666
+ then
667
+ chown "${NETDATA_USER}" "${NETDATA_PREFIX}/etc/netdata/netdata.conf"
668
+ fi
669
+ chmod 0664 "${NETDATA_PREFIX}/etc/netdata/netdata.conf"
670
+ fi
671
+ echo >&2 "OK. It is now installed and ready."
672
+ exit 0
673
fi
674
675
# -----------------------------------------------------------------------------
676
# stop a running netdata
677
678
isnetdata() {
679
- [ -z "$1" -o ! -f "/proc/$1/stat" ] && return 1
680
- [ "$(cat "/proc/$1/stat" | cut -d '(' -f 2 | cut -d ')' -f 1)" = "netdata" ] && return 0
681
- return 1
679
+ [ -z "$1" -o ! -f "/proc/$1/stat" ] && return 1
680
+ [ "$(cat "/proc/$1/stat" | cut -d '(' -f 2 | cut -d ')' -f 1)" = "netdata" ] && return 0
681
+ return 1
682
}
683
684
stop_netdata_on_pid() {
685
- local pid="$1" ret=0 count=0
685
+ local pid="$1" ret=0 count=0
686
687
- isnetdata $pid || return 0
687
+ isnetdata $pid || return 0
688
689
- printf >&2 "Stopping netdata on pid $pid ..."
690
- while [ ! -z "$pid" -a $ret -eq 0 ]
691
- do
692
- if [ $count -gt 45 ]
693
- then
694
- echo >&2 "Cannot stop the running netdata on pid $pid."
695
- return 1
696
- fi
689
+ printf >&2 "Stopping netdata on pid $pid ..."
690
+ while [ ! -z "$pid" -a $ret -eq 0 ]
691
+ do
692
+ if [ $count -gt 45 ]
693
+ then
694
+ echo >&2 "Cannot stop the running netdata on pid $pid."
695
+ return 1
696
+ fi
697
698
- count=$(( count + 1 ))
698
+ count=$(( count + 1 ))
699
700
- run kill $pid 2>/dev/null
701
- ret=$?
700
+ run kill $pid 2>/dev/null
701
+ ret=$?
702
703
- test $ret -eq 0 && printf >&2 "." && sleep 2
704
- done
703
+ test $ret -eq 0 && printf >&2 "." && sleep 2
704
+ done
705
706
- echo >&2
707
- if [ $ret -eq 0 ]
708
- then
709
- echo >&2 "SORRY! CANNOT STOP netdata ON PID $pid !"
710
- return 1
711
- fi
706
+ echo >&2
707
+ if [ $ret -eq 0 ]
708
+ then
709
+ echo >&2 "SORRY! CANNOT STOP netdata ON PID $pid !"
710
+ return 1
711
+ fi
712
713
- echo >&2 "netdata on pid $pid stopped."
714
- return 0
713
+ echo >&2 "netdata on pid $pid stopped."
714
+ return 0
715
}
716
717
stop_all_netdata() {
718
- local p
718
+ local p
719
720
- echo >&2 "Stopping a (possibly) running netdata..."
720
+ echo >&2 "Stopping a (possibly) running netdata..."
721
722
- for p in $(cat "${NETDATA_RUN_DIR}/netdata.pid" 2>/dev/null) \
723
- $(cat /var/run/netdata.pid 2>/dev/null) \
724
- $(cat /var/run/netdata/netdata.pid 2>/dev/null) \
725
- $(pidof netdata 2>/dev/null)
726
- do
727
- stop_netdata_on_pid $p
728
- done
722
+ for p in $(cat "${NETDATA_RUN_DIR}/netdata.pid" 2>/dev/null) \
723
+ $(cat /var/run/netdata.pid 2>/dev/null) \
724
+ $(cat /var/run/netdata/netdata.pid 2>/dev/null) \
725
+ $(pidof netdata 2>/dev/null)
726
+ do
727
+ stop_netdata_on_pid $p
728
+ done
729
}
730
731
# -----------------------------------------------------------------------------
732
# check netdata for systemd
733
734
issystemd() {
735
- # if the directory /etc/systemd/system does not exit, it is not systemd
736
- [ ! -d /etc/systemd/system ] && return 1
735
+ # if the directory /etc/systemd/system does not exit, it is not systemd
736
+ [ ! -d /etc/systemd/system ] && return 1
737
738
- # if pid 1 is systemd, it is systemd
739
- [ "$(basename $(readlink /proc/1/exe) 2>/dev/null)" = "systemd" ] && return 0
738
+ # if pid 1 is systemd, it is systemd
739
+ [ "$(basename $(readlink /proc/1/exe) 2>/dev/null)" = "systemd" ] && return 0
740
741
- # if systemd is running, it is systemd
742
- pidof systemd >/dev/null 2>&1 && return 0
741
+ # if systemd is running, it is systemd
742
+ pidof systemd >/dev/null 2>&1 && return 0
743
744
- # else, it is not systemd
745
- return 1
744
+ # else, it is not systemd
745
+ return 1
746
}
747
748
started=0
749
if [ "${UID}" -eq 0 ]
750
- then
751
-
752
- if issystemd
753
- then
754
- # systemd is running on this system
755
-
756
- if [ ! -f /etc/systemd/system/netdata.service ]
757
- then
758
- echo >&2 "Installing systemd service..."
759
- run cp system/netdata.service /etc/systemd/system/netdata.service && \
760
- run systemctl daemon-reload && \
761
- run systemctl enable netdata
762
- else
763
- service netdata stop
764
- fi
765
-
766
- stop_all_netdata
767
- service netdata restart && started=1
768
- fi
769
-
770
- if [ ${started} -eq 0 ]
771
- then
772
- # check if we can use the system service
773
- service netdata stop
774
- stop_all_netdata
775
- service netdata restart && started=1
776
- if [ ${started} -eq 0 ]
777
- then
778
- service netdata start && started=1
779
- fi
780
- fi
750
+ then
751
+
752
+ if issystemd
753
+ then
754
+ # systemd is running on this system
755
+
756
+ if [ ! -f /etc/systemd/system/netdata.service ]
757
+ then
758
+ echo >&2 "Installing systemd service..."
759
+ run cp system/netdata.service /etc/systemd/system/netdata.service && \
760
+ run systemctl daemon-reload && \
761
+ run systemctl enable netdata
762
+ else
763
+ service netdata stop
764
+ fi
765
+
766
+ stop_all_netdata
767
+ service netdata restart && started=1
768
+ fi
769
+
770
+ if [ ${started} -eq 0 ]
771
+ then
772
+ # check if we can use the system service
773
+ service netdata stop
774
+ stop_all_netdata
775
+ service netdata restart && started=1
776
+ if [ ${started} -eq 0 ]
777
+ then
778
+ service netdata start && started=1
779
+ fi
780
+ fi
781
fi
782
783
if [ ${started} -eq 0 ]
784
then
785
- # still not started...
786
-
787
- stop_all_netdata
788
-
789
- echo >&2 "Starting netdata..."
790
- run ${NETDATA_PREFIX}/usr/sbin/netdata -P ${NETDATA_RUN_DIR}/netdata.pid "${@}"
791
- if [ $? -ne 0 ]
792
- then
793
- echo >&2
794
- echo >&2 "SORRY! FAILED TO START NETDATA!"
795
- exit 1
796
- else
797
- echo >&2 "OK. NetData Started!"
798
- fi
799
-
800
- echo >&2
785
+ # still not started...
786
+
787
+ stop_all_netdata
788
+
789
+ echo >&2 "Starting netdata..."
790
+ run ${NETDATA_PREFIX}/usr/sbin/netdata -P ${NETDATA_RUN_DIR}/netdata.pid "${@}"
791
+ if [ $? -ne 0 ]
792
+ then
793
+ echo >&2
794
+ echo >&2 "SORRY! FAILED TO START NETDATA!"
795
+ exit 1
796
+ else
797
+ echo >&2 "OK. NetData Started!"
798
+ fi
799
+
800
+ echo >&2
801
fi
802
803
# -----------------------------------------------------------------------------
804
# save a config file, if it is not already there
805
806
if [ ! -s "${NETDATA_PREFIX}/etc/netdata/netdata.conf" ]
807
- then
808
- echo >&2
809
- echo >&2 "-------------------------------------------------------------------------------"
810
- echo >&2
811
- echo >&2 "Downloading default configuration from netdata..."
812
- sleep 5
813
-
814
- # remove a possibly obsolete download
815
- [ -f "${NETDATA_PREFIX}/etc/netdata/netdata.conf.new" ] && rm "${NETDATA_PREFIX}/etc/netdata/netdata.conf.new"
816
-
817
- # disable a proxy to get data from the local netdata
818
- export http_proxy=
819
- export https_proxy=
820
-
821
- # try wget
822
- wget 2>/dev/null -O "${NETDATA_PREFIX}/etc/netdata/netdata.conf.new" "http://localhost:${NETDATA_PORT}/netdata.conf"
823
- ret=$?
824
-
825
- # try curl
826
- if [ $ret -ne 0 -o ! -s "${NETDATA_PREFIX}/etc/netdata/netdata.conf.new" ]
827
- then
828
- curl -s -o "${NETDATA_PREFIX}/etc/netdata/netdata.conf.new" "http://localhost:${NETDATA_PORT}/netdata.conf"
829
- ret=$?
830
- fi
831
-
832
- if [ $ret -eq 0 -a -s "${NETDATA_PREFIX}/etc/netdata/netdata.conf.new" ]
833
- then
834
- mv "${NETDATA_PREFIX}/etc/netdata/netdata.conf.new" "${NETDATA_PREFIX}/etc/netdata/netdata.conf"
835
- echo >&2 "New configuration saved for you to edit at ${NETDATA_PREFIX}/etc/netdata/netdata.conf"
836
-
837
- if [ "${UID}" -eq 0 ]
838
- then
839
- chown "${NETDATA_USER}" "${NETDATA_PREFIX}/etc/netdata/netdata.conf"
840
- fi
841
- chmod 0664 "${NETDATA_PREFIX}/etc/netdata/netdata.conf"
842
- else
843
- echo >&2 "Cannnot download configuration from netdata daemon using url 'http://localhost:${NETDATA_PORT}/netdata.conf'"
844
- [ -f "${NETDATA_PREFIX}/etc/netdata/netdata.conf.new" ] && rm "${NETDATA_PREFIX}/etc/netdata/netdata.conf.new"
845
- fi
807
+ then
808
+ echo >&2
809
+ echo >&2 "-------------------------------------------------------------------------------"
810
+ echo >&2
811
+ echo >&2 "Downloading default configuration from netdata..."
812
+ sleep 5
813
+
814
+ # remove a possibly obsolete download
815
+ [ -f "${NETDATA_PREFIX}/etc/netdata/netdata.conf.new" ] && rm "${NETDATA_PREFIX}/etc/netdata/netdata.conf.new"
816
+
817
+ # disable a proxy to get data from the local netdata
818
+ export http_proxy=
819
+ export https_proxy=
820
+
821
+ # try wget
822
+ wget 2>/dev/null -O "${NETDATA_PREFIX}/etc/netdata/netdata.conf.new" "http://localhost:${NETDATA_PORT}/netdata.conf"
823
+ ret=$?
824
+
825
+ # try curl
826
+ if [ $ret -ne 0 -o ! -s "${NETDATA_PREFIX}/etc/netdata/netdata.conf.new" ]
827
+ then
828
+ curl -s -o "${NETDATA_PREFIX}/etc/netdata/netdata.conf.new" "http://localhost:${NETDATA_PORT}/netdata.conf"
829
+ ret=$?
830
+ fi
831
+
832
+ if [ $ret -eq 0 -a -s "${NETDATA_PREFIX}/etc/netdata/netdata.conf.new" ]
833
+ then
834
+ mv "${NETDATA_PREFIX}/etc/netdata/netdata.conf.new" "${NETDATA_PREFIX}/etc/netdata/netdata.conf"
835
+ echo >&2 "New configuration saved for you to edit at ${NETDATA_PREFIX}/etc/netdata/netdata.conf"
836
+
837
+ if [ "${UID}" -eq 0 ]
838
+ then
839
+ chown "${NETDATA_USER}" "${NETDATA_PREFIX}/etc/netdata/netdata.conf"
840
+ fi
841
+ chmod 0664 "${NETDATA_PREFIX}/etc/netdata/netdata.conf"
842
+ else
843
+ echo >&2 "Cannnot download configuration from netdata daemon using url 'http://localhost:${NETDATA_PORT}/netdata.conf'"
844
+ [ -f "${NETDATA_PREFIX}/etc/netdata/netdata.conf.new" ] && rm "${NETDATA_PREFIX}/etc/netdata/netdata.conf.new"
845
+ fi
846
fi
847
848
# -----------------------------------------------------------------------------
849
# Check for KSM
850
851
ksm_is_available_but_disabled() {
852
- cat <<-KSM1
852
+ cat <<-KSM1
853
854
- -------------------------------------------------------------------------------
855
- Memory de-duplication instructions
854
+ -------------------------------------------------------------------------------
855
+ Memory de-duplication instructions
856
857
- You have kernel memory de-duper (called Kernel Same-page Merging,
858
- or KSM) available, but it is not currently enabled.
857
+ You have kernel memory de-duper (called Kernel Same-page Merging,
858
+ or KSM) available, but it is not currently enabled.
859
860
- To enable it run:
860
+ To enable it run:
861
862
- echo 1 >/sys/kernel/mm/ksm/run
863
- echo 1000 >/sys/kernel/mm/ksm/sleep_millisecs
862
+ echo 1 >/sys/kernel/mm/ksm/run
863
+ echo 1000 >/sys/kernel/mm/ksm/sleep_millisecs
864
865
- If you enable it, you will save 40-60% of netdata memory.
865
+ If you enable it, you will save 40-60% of netdata memory.
866
867
KSM1
868
}
869
870
ksm_is_not_available() {
871
- cat <<-KSM2
871
+ cat <<-KSM2
872
873
- -------------------------------------------------------------------------------
874
- Memory de-duplication not present in your kernel
873
+ -------------------------------------------------------------------------------
874
+ Memory de-duplication not present in your kernel
875
876
- It seems you do not have kernel memory de-duper (called Kernel Same-page
877
- Merging, or KSM) available.
876
+ It seems you do not have kernel memory de-duper (called Kernel Same-page
877
+ Merging, or KSM) available.
878
879
- To enable it, you need a kernel built with CONFIG_KSM=y
879
+ To enable it, you need a kernel built with CONFIG_KSM=y
880
881
- If you can have it, you will save 40-60% of netdata memory.
881
+ If you can have it, you will save 40-60% of netdata memory.
882
883
KSM2
884
}
885
886
if [ -f "/sys/kernel/mm/ksm/run" ]
887
- then
888
- if [ $(cat "/sys/kernel/mm/ksm/run") != "1" ]
889
- then
890
- ksm_is_available_but_disabled
891
- fi
887
+ then
888
+ if [ $(cat "/sys/kernel/mm/ksm/run") != "1" ]
889
+ then
890
+ ksm_is_available_but_disabled
891
+ fi
892
else
893
- ksm_is_not_available
893
+ ksm_is_not_available
894
fi
895
896
# -----------------------------------------------------------------------------
897
# Check for version.txt
898
899
if [ ! -s web/version.txt ]
900
- then
901
- cat <<-VERMSG
900
+ then
901
+ cat <<-VERMSG
902
903
- -------------------------------------------------------------------------------
904
- Version update check warning
903
+ -------------------------------------------------------------------------------
904
+ Version update check warning
905
906
- The way you downloaded netdata, we cannot find its version. This means the
907
- Update check on the dashboard, will not work.
906
+ The way you downloaded netdata, we cannot find its version. This means the
907
+ Update check on the dashboard, will not work.
908
909
- If you want to have version update check, please re-install it
910
- following the procedure in:
909
+ If you want to have version update check, please re-install it
910
+ following the procedure in:
911
912
- https://github.com/firehol/netdata/wiki/Installation
912
+ https://github.com/firehol/netdata/wiki/Installation
913
914
VERMSG
915
fi
@@ -918,30 +918,30 @@ fi
918
# apps.plugin warning
919
920
if [ "${UID}" -ne 0 ]
921
- then
922
- cat <<-SETUID_WARNING
921
+ then
922
+ cat <<-SETUID_WARNING
923
924
- -------------------------------------------------------------------------------
925
- apps.plugin needs privileges
924
+ -------------------------------------------------------------------------------
925
+ apps.plugin needs privileges
926
927
- Since you have installed netdata as a normal user, to have apps.plugin collect
928
- all the needed data, you have to give it the access rights it needs, by running
929
- either of the following sets of commands:
927
+ Since you have installed netdata as a normal user, to have apps.plugin collect
928
+ all the needed data, you have to give it the access rights it needs, by running
929
+ either of the following sets of commands:
930
931
- To run apps.plugin with escalated capabilities:
931
+ To run apps.plugin with escalated capabilities:
932
933
- sudo chown root:${NETDATA_USER} "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/apps.plugin"
934
- sudo chmod 0750 "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/apps.plugin"
935
- sudo setcap cap_dac_read_search,cap_sys_ptrace+ep "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/apps.plugin"
933
+ sudo chown root:${NETDATA_USER} "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/apps.plugin"
934
+ sudo chmod 0750 "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/apps.plugin"
935
+ sudo setcap cap_dac_read_search,cap_sys_ptrace+ep "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/apps.plugin"
936
937
- or, to run apps.plugin as root:
937
+ or, to run apps.plugin as root:
938
939
- sudo chown root "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/apps.plugin"
940
- sudo chmod 4755 "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/apps.plugin"
939
+ sudo chown root "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/apps.plugin"
940
+ sudo chmod 4755 "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/apps.plugin"
941
942
- apps.plugin is performing a hard-coded function of data collection for all
943
- running processes. It cannot be instructed from the netdata daemon to perform
944
- any task, so it is pretty safe to do this.
942
+ apps.plugin is performing a hard-coded function of data collection for all
943
+ running processes. It cannot be instructed from the netdata daemon to perform
944
+ any task, so it is pretty safe to do this.
945
946
SETUID_WARNING
947
fi
@@ -950,91 +950,91 @@ fi
950
# Keep un-install info
951
952
cat >netdata-uninstaller.sh <<-UNINSTALL
953
- #!/bin/bash
954
-
955
- # this script will uninstall netdata
956
-
957
- if [ "\$1" != "--force" ]
958
- then
959
- echo >&2 "This script will REMOVE netdata from your system."
960
- echo >&2 "Run it again with --force to do it."
961
- exit 1
962
- fi
963
-
964
- echo >&2 "Stopping a possibly running netdata..."
965
- for p in \$(pidof netdata); do kill \$p; done
966
- sleep 2
967
-
968
- deletedir() {
969
- if [ ! -z "\$1" -a -d "\$1" ]
970
- then
971
- echo
972
- echo "Deleting directory '\$1' ..."
973
- rm -I -R "\$1"
974
- fi
975
- }
976
-
977
- if [ ! -z "${NETDATA_PREFIX}" -a -d "${NETDATA_PREFIX}" ]
978
- then
979
- # installation prefix was given
980
-
981
- deletedir "${NETDATA_PREFIX}"
982
-
983
- else
984
- # installation prefix was NOT given
985
-
986
- if [ -f "${NETDATA_PREFIX}/usr/sbin/netdata" ]
987
- then
988
- echo "Deleting ${NETDATA_PREFIX}/usr/sbin/netdata ..."
989
- rm -i "${NETDATA_PREFIX}/usr/sbin/netdata"
990
- fi
991
-
992
- deletedir "${NETDATA_PREFIX}/etc/netdata"
993
- deletedir "${NETDATA_PREFIX}/usr/share/netdata"
994
- deletedir "${NETDATA_PREFIX}/usr/libexec/netdata"
995
- deletedir "${NETDATA_PREFIX}/var/lib/netdata"
996
- deletedir "${NETDATA_PREFIX}/var/cache/netdata"
997
- deletedir "${NETDATA_PREFIX}/var/log/netdata"
998
- fi
999
-
1000
- if [ -f /etc/logrotate.d/netdata ]
1001
- then
1002
- echo "Deleting /etc/logrotate.d/netdata ..."
1003
- rm -i /etc/logrotate.d/netdata
1004
- fi
1005
-
1006
- if [ -f /etc/systemd/system/netdata.service ]
1007
- then
1008
- echo "Deleting /etc/systemd/system/netdata.service ..."
1009
- rm -i /etc/systemd/system/netdata.service
1010
- fi
1011
-
1012
- getent passwd netdata > /dev/null
1013
- if [ $? -eq 0 ]
1014
- then
1015
- echo
1016
- echo "You may also want to remove the user netdata"
1017
- echo "by running:"
1018
- echo " userdel netdata"
1019
- fi
1020
-
1021
- getent group netdata > /dev/null
1022
- if [ $? -eq 0 ]
1023
- then
1024
- echo
1025
- echo "You may also want to remove the group netdata"
1026
- echo "by running:"
1027
- echo " groupdel netdata"
1028
- fi
1029
-
1030
- getent group docker > /dev/null
1031
- if [ $? -eq 0 -a "${NETDATA_ADDED_TO_DOCKER}" = "1" ]
1032
- then
1033
- echo
1034
- echo "You may also want to remove the netdata user from the docker group"
1035
- echo "by running:"
1036
- echo " gpasswd -d netdata docker"
1037
- fi
953
+ #!/bin/bash
954
+
955
+ # this script will uninstall netdata
956
+
957
+ if [ "\$1" != "--force" ]
958
+ then
959
+ echo >&2 "This script will REMOVE netdata from your system."
960
+ echo >&2 "Run it again with --force to do it."
961
+ exit 1
962
+ fi
963
+
964
+ echo >&2 "Stopping a possibly running netdata..."
965
+ for p in \$(pidof netdata); do kill \$p; done
966
+ sleep 2
967
+
968
+ deletedir() {
969
+ if [ ! -z "\$1" -a -d "\$1" ]
970
+ then
971
+ echo
972
+ echo "Deleting directory '\$1' ..."
973
+ rm -I -R "\$1"
974
+ fi
975
+ }
976
+
977
+ if [ ! -z "${NETDATA_PREFIX}" -a -d "${NETDATA_PREFIX}" ]
978
+ then
979
+ # installation prefix was given
980
+
981
+ deletedir "${NETDATA_PREFIX}"
982
+
983
+ else
984
+ # installation prefix was NOT given
985
+
986
+ if [ -f "${NETDATA_PREFIX}/usr/sbin/netdata" ]
987
+ then
988
+ echo "Deleting ${NETDATA_PREFIX}/usr/sbin/netdata ..."
989
+ rm -i "${NETDATA_PREFIX}/usr/sbin/netdata"
990
+ fi
991
+
992
+ deletedir "${NETDATA_PREFIX}/etc/netdata"
993
+ deletedir "${NETDATA_PREFIX}/usr/share/netdata"
994
+ deletedir "${NETDATA_PREFIX}/usr/libexec/netdata"
995
+ deletedir "${NETDATA_PREFIX}/var/lib/netdata"
996
+ deletedir "${NETDATA_PREFIX}/var/cache/netdata"
997
+ deletedir "${NETDATA_PREFIX}/var/log/netdata"
998
+ fi
999
+
1000
+ if [ -f /etc/logrotate.d/netdata ]
1001
+ then
1002
+ echo "Deleting /etc/logrotate.d/netdata ..."
1003
+ rm -i /etc/logrotate.d/netdata
1004
+ fi
1005
+
1006
+ if [ -f /etc/systemd/system/netdata.service ]
1007
+ then
1008
+ echo "Deleting /etc/systemd/system/netdata.service ..."
1009
+ rm -i /etc/systemd/system/netdata.service
1010
+ fi
1011
+
1012
+ getent passwd netdata > /dev/null
1013
+ if [ $? -eq 0 ]
1014
+ then
1015
+ echo
1016
+ echo "You may also want to remove the user netdata"
1017
+ echo "by running:"
1018
+ echo " userdel netdata"
1019
+ fi
1020
+
1021
+ getent group netdata > /dev/null
1022
+ if [ $? -eq 0 ]
1023
+ then
1024
+ echo
1025
+ echo "You may also want to remove the group netdata"
1026
+ echo "by running:"
1027
+ echo " groupdel netdata"
1028
+ fi
1029
+
1030
+ getent group docker > /dev/null
1031
+ if [ $? -eq 0 -a "${NETDATA_ADDED_TO_DOCKER}" = "1" ]
1032
+ then
1033
+ echo
1034
+ echo "You may also want to remove the netdata user from the docker group"
1035
+ echo "by running:"
1036
+ echo " gpasswd -d netdata docker"
1037
+ fi
1038
1039
UNINSTALL
1040
chmod 750 netdata-uninstaller.sh
@@ -1044,27 +1044,27 @@ chmod 750 netdata-uninstaller.sh
1044
cat <<-END
1045
1046
1047
- -------------------------------------------------------------------------------
1047
+ -------------------------------------------------------------------------------
1048
1049
- OK. NetData is installed and it is running.
1049
+ OK. NetData is installed and it is running.
1050
1051
- -------------------------------------------------------------------------------
1051
+ -------------------------------------------------------------------------------
1052
1053
- By default netdata listens on all IPs on port ${NETDATA_PORT},
1054
- so you can access it with:
1053
+ By default netdata listens on all IPs on port ${NETDATA_PORT},
1054
+ so you can access it with:
1055
1056
- http://this.machine.ip:${NETDATA_PORT}/
1056
+ http://this.machine.ip:${NETDATA_PORT}/
1057
1058
- To stop netdata, just kill it, with:
1058
+ To stop netdata, just kill it, with:
1059
1060
- killall netdata
1060
+ killall netdata
1061
1062
- To start it, just run it:
1062
+ To start it, just run it:
1063
1064
- ${NETDATA_PREFIX}/usr/sbin/netdata
1064
+ ${NETDATA_PREFIX}/usr/sbin/netdata
1065
1066
1067
- Enjoy!
1067
+ Enjoy!
1068
1069
END
1070
echo >&2 "Uninstall script generated: ./netdata-uninstaller.sh"
node.d/named.node.js
+551
-551
@@ -11,20 +11,20 @@
11
12
/*
13
{
14
- "enable_autodetect": true,
15
- "update_every": 5,
16
- "servers": [
17
- {
18
- "name": "bind1",
19
- "url": "http://127.0.0.1:8888/json/v1/server",
20
- "update_every": 1
21
- },
22
- {
23
- "name": "bind2",
24
- "url": "http://10.0.0.1:8888/xml/v3/server",
25
- "update_every": 2
26
- }
27
- ]
14
+ "enable_autodetect": true,
15
+ "update_every": 5,
16
+ "servers": [
17
+ {
18
+ "name": "bind1",
19
+ "url": "http://127.0.0.1:8888/json/v1/server",
20
+ "update_every": 1
21
+ },
22
+ {
23
+ "name": "bind2",
24
+ "url": "http://10.0.0.1:8888/xml/v3/server",
25
+ "update_every": 2
26
+ }
27
+ ]
28
}
29
*/
30
@@ -44,543 +44,543 @@ var netdata = require('netdata');
44
if(netdata.options.DEBUG === true) netdata.debug('loaded ' + __filename + ' plugin');
45
46
var named = {
47
- name: __filename,
48
- enable_autodetect: true,
49
- update_every: 1,
50
- base_priority: 60000,
51
- charts: {},
52
-
53
- chartFromMembersCreate: function(service, obj, id, title_suffix, units, family, context, type, priority, algorithm, multiplier, divisor) {
54
- var chart = {
55
- id: id, // the unique id of the chart
56
- name: '', // the unique name of the chart
57
- title: service.name + ' ' + title_suffix, // the title of the chart
58
- units: units, // the units of the chart dimensions
59
- family: family, // the family of the chart
60
- context: context, // the context of the chart
61
- type: type, // the type of the chart
62
- priority: priority, // the priority relative to others in the same family
63
- update_every: service.update_every, // the expected update frequency of the chart
64
- dimensions: {}
65
- }
66
-
67
- var found = 0;
68
- for(var x in obj) {
69
- if(typeof(obj[x]) !== 'undefined' && obj[x] !== 0) {
70
- found++;
71
- chart.dimensions[x] = {
72
- id: x, // the unique id of the dimension
73
- name: x, // the name of the dimension
74
- algorithm: algorithm, // the id of the netdata algorithm
75
- multiplier: multiplier, // the multiplier
76
- divisor: divisor, // the divisor
77
- hidden: false // is hidden (boolean)
78
- }
79
- }
80
- }
81
-
82
- if(found === false)
83
- return null;
84
-
85
- chart = service.chart(id, chart);
86
- this.charts[id] = chart;
87
- return chart;
88
- },
89
-
90
- chartFromMembers: function(service, obj, id_suffix, title_suffix, units, family, context, type, priority, algorithm, multiplier, divisor) {
91
- var id = 'named_' + service.name + '.' + id_suffix;
92
- var chart = this.charts[id];
93
-
94
- if(typeof chart === 'undefined') {
95
- chart = this.chartFromMembersCreate(service, obj, id, title_suffix, units, family, context, type, priority, algorithm, multiplier, divisor);
96
- if(chart === null) return false;
97
- }
98
- else {
99
- // check if we need to re-generate the chart
100
- for(var x in obj) {
101
- if(typeof(chart.dimensions[x]) === 'undefined') {
102
- chart = this.chartFromMembersCreate(service, obj, id, title_suffix, units, family, context, type, priority, algorithm, multiplier, divisor);
103
- if(chart === null) return false;
104
- break;
105
- }
106
- }
107
- }
108
-
109
- var found = 0;
110
- service.begin(chart);
111
- for(var x in obj) {
112
- if(typeof(chart.dimensions[x]) !== 'undefined') {
113
- found++;
114
- service.set(x, obj[x]);
115
- }
116
- }
117
- service.end();
118
-
119
- if(found > 0) return true;
120
- return false;
121
- },
122
-
123
- // an index to map values to different charts
124
- lookups: {
125
- nsstats: {},
126
- resolver_stats: {},
127
- numfetch: {}
128
- },
129
-
130
- // transform the XML response of bind
131
- // to the JSON response of bind
132
- xml2js: function(service, data_xml) {
133
- var d = XML.parse(data_xml);
134
- if(d === null) return null;
135
-
136
- var data = {};
137
- var len = d.server.counters.length;
138
- while(len--) {
139
- var a = d.server.counters[len];
140
- if(typeof a.counter === 'undefined') continue;
141
- if(a.type === 'opcode') a.type = 'opcodes';
142
- else if(a.type === 'qtype') a.type = 'qtypes';
143
- else if(a.type === 'nsstat') a.type = 'nsstats';
144
- var aa = data[a.type] = {};
145
- var alen = 0
146
- var alen2 = a.counter.length;
147
- while(alen < alen2) {
148
- aa[a.counter[alen].name] = parseInt(a.counter[alen]._Data);
149
- alen++;
150
- }
151
- }
152
-
153
- data.views = {};
154
- var vlen = d.views.view.length;
155
- while(vlen--) {
156
- var vname = d.views.view[vlen].name;
157
- data.views[vname] = { resolver: {} };
158
- var len = d.views.view[vlen].counters.length;
159
- while(len--) {
160
- var a = d.views.view[vlen].counters[len];
161
- if(typeof a.counter === 'undefined') continue;
162
- if(a.type === 'resstats') a.type = 'stats';
163
- else if(a.type === 'resqtype') a.type = 'qtypes';
164
- else if(a.type === 'adbstat') a.type = 'adb';
165
- var aa = data.views[vname].resolver[a.type] = {};
166
- var alen = 0;
167
- var alen2 = a.counter.length;
168
- while(alen < alen2) {
169
- aa[a.counter[alen].name] = parseInt(a.counter[alen]._Data);
170
- alen++;
171
- }
172
- }
173
- }
174
-
175
- return data;
176
- },
177
-
178
- processResponse: function(service, data) {
179
- if(data !== null) {
180
- var r;
181
-
182
- // parse XML or JSON
183
- // pepending on the URL given
184
- if(service.request.path.match(/^\/xml/) !== null)
185
- r = named.xml2js(service, data);
186
- else
187
- r = JSON.parse(data);
188
-
189
- if(typeof r === 'undefined' || r === null) {
190
- netdata.serviceError(service, "Cannot parse these data: " + data);
191
- return;
192
- }
193
-
194
- if(service.added !== true)
195
- service.commit();
196
-
197
- if(typeof r.nsstats !== 'undefined') {
198
- // we split the nsstats object to several others
199
- var global_requests = {}, global_requests_enable = false;
200
- var global_failures = {}, global_failures_enable = false;
201
- var global_failures_detail = {}, global_failures_detail_enable = false;
202
- var global_updates = {}, global_updates_enable = false;
203
- var protocol_queries = {}, protocol_queries_enable = false;
204
- var global_queries = {}, global_queries_enable = false;
205
- var global_queries_success = {}, global_queries_success_enable = false;
206
- var default_enable = false;
207
- var RecursClients = 0;
208
-
209
- // RecursClients is an absolute value
210
- if(typeof r.nsstats['RecursClients'] !== 'undefined') {
211
- RecursClients = r.nsstats['RecursClients'];
212
- delete r.nsstats['RecursClients'];
213
- }
214
-
215
- for( var x in r.nsstats ) {
216
- // we maintain an index of the values found
217
- // mapping them to objects splitted
218
-
219
- var look = named.lookups.nsstats[x];
220
- if(typeof look === 'undefined') {
221
- // a new value, not found in the index
222
- // index it:
223
- if(x === 'Requestv4') {
224
- named.lookups.nsstats[x] = {
225
- name: 'IPv4',
226
- type: 'global_requests'
227
- };
228
- }
229
- else if(x === 'Requestv6') {
230
- named.lookups.nsstats[x] = {
231
- name: 'IPv6',
232
- type: 'global_requests'
233
- };
234
- }
235
- else if(x === 'QryFailure') {
236
- named.lookups.nsstats[x] = {
237
- name: 'failures',
238
- type: 'global_failures'
239
- };
240
- }
241
- else if(x === 'QryUDP') {
242
- named.lookups.nsstats[x] = {
243
- name: 'UDP',
244
- type: 'protocol_queries'
245
- };
246
- }
247
- else if(x === 'QryTCP') {
248
- named.lookups.nsstats[x] = {
249
- name: 'TCP',
250
- type: 'protocol_queries'
251
- };
252
- }
253
- else if(x === 'QrySuccess') {
254
- named.lookups.nsstats[x] = {
255
- name: 'queries',
256
- type: 'global_queries_success'
257
- };
258
- }
259
- else if(x.match(/QryRej$/) !== null) {
260
- named.lookups.nsstats[x] = {
261
- name: x,
262
- type: 'global_failures_detail'
263
- };
264
- }
265
- else if(x.match(/^Qry/) !== null) {
266
- named.lookups.nsstats[x] = {
267
- name: x,
268
- type: 'global_queries'
269
- };
270
- }
271
- else if(x.match(/^Update/) !== null) {
272
- named.lookups.nsstats[x] = {
273
- name: x,
274
- type: 'global_updates'
275
- };
276
- }
277
- else {
278
- // values not mapped, will remain
279
- // in the default map
280
- named.lookups.nsstats[x] = {
281
- name: x,
282
- type: 'default'
283
- };
284
- }
285
-
286
- look = named.lookups.nsstats[x];
287
- // netdata.error('lookup nsstats value: ' + x + ' >>> ' + named.lookups.nsstats[x].type);
288
- }
289
-
290
- switch(look.type) {
291
- case 'global_requests': global_requests[look.name] = r.nsstats[x]; delete r.nsstats[x]; global_requests_enable = true; break;
292
- case 'global_queries': global_queries[look.name] = r.nsstats[x]; delete r.nsstats[x]; global_queries_enable = true; break;
293
- case 'global_queries_success': global_queries_success[look.name] = r.nsstats[x]; delete r.nsstats[x]; global_queries_success_enable = true; break;
294
- case 'global_updates': global_updates[look.name] = r.nsstats[x]; delete r.nsstats[x]; global_updates_enable = true; break;
295
- case 'protocol_queries': protocol_queries[look.name] = r.nsstats[x]; delete r.nsstats[x]; protocol_queries_enable = true; break;
296
- case 'global_failures': global_failures[look.name] = r.nsstats[x]; delete r.nsstats[x]; global_failures_enable = true; break;
297
- case 'global_failures_detail': global_failures_detail[look.name] = r.nsstats[x]; delete r.nsstats[x]; global_failures_detail_enable = true; break;
298
- default: default_enable = true; break;
299
- }
300
- }
301
-
302
- if(global_requests_enable == true)
303
- service.module.chartFromMembers(service, global_requests, 'received_requests', 'Bind, Global Received Requests by IP version', 'requests/s', 'requests', 'named.requests', netdata.chartTypes.stacked, named.base_priority + 1, netdata.chartAlgorithms.incremental, 1, 1);
304
-
305
- if(global_queries_success_enable == true)
306
- service.module.chartFromMembers(service, global_queries_success, 'global_queries_success', 'Bind, Global Successful Queries', 'queries/s', 'queries', 'named.queries.succcess', netdata.chartTypes.line, named.base_priority + 2, netdata.chartAlgorithms.incremental, 1, 1);
307
-
308
- if(protocol_queries_enable == true)
309
- service.module.chartFromMembers(service, protocol_queries, 'protocols_queries', 'Bind, Global Queries by IP Protocol', 'queries/s', 'queries', 'named.protocol.queries', netdata.chartTypes.stacked, named.base_priority + 3, netdata.chartAlgorithms.incremental, 1, 1);
310
-
311
- if(global_queries_enable == true)
312
- service.module.chartFromMembers(service, global_queries, 'global_queries', 'Bind, Global Queries Analysis', 'queries/s', 'queries', 'named.global.queries', netdata.chartTypes.stacked, named.base_priority + 4, netdata.chartAlgorithms.incremental, 1, 1);
313
-
314
- if(global_updates_enable == true)
315
- service.module.chartFromMembers(service, global_updates, 'received_updates', 'Bind, Global Received Updates', 'updates/s', 'updates', 'named.global.updates', netdata.chartTypes.stacked, named.base_priority + 5, netdata.chartAlgorithms.incremental, 1, 1);
316
-
317
- if(global_failures_enable == true)
318
- service.module.chartFromMembers(service, global_failures, 'query_failures', 'Bind, Global Query Failures', 'failures/s', 'failures', 'named.global.failures', netdata.chartTypes.line, named.base_priority + 6, netdata.chartAlgorithms.incremental, 1, 1);
319
-
320
- if(global_failures_detail_enable == true)
321
- service.module.chartFromMembers(service, global_failures_detail, 'query_failures_detail', 'Bind, Global Query Failures Analysis', 'failures/s', 'failures', 'named.global.failures.detail', netdata.chartTypes.stacked, named.base_priority + 7, netdata.chartAlgorithms.incremental, 1, 1);
322
-
323
- if(default_enable === true)
324
- service.module.chartFromMembers(service, r.nsstats, 'nsstats', 'Bind, Other Global Server Statistics', 'operations/s', 'other', 'named.nsstats', netdata.chartTypes.line, named.base_priority + 8, netdata.chartAlgorithms.incremental, 1, 1);
325
-
326
- // RecursClients chart
327
- {
328
- var id = 'named_' + service.name + '.recursive_clients';
329
- var chart = named.charts[id];
330
-
331
- if(typeof chart === 'undefined') {
332
- chart = {
333
- id: id, // the unique id of the chart
334
- name: '', // the unique name of the chart
335
- title: service.name + ' Bind, Current Recursive Clients', // the title of the chart
336
- units: 'clients', // the units of the chart dimensions
337
- family: 'clients', // the family of the chart
338
- context: 'named.recursive.clients', // the context of the chart
339
- type: netdata.chartTypes.line, // the type of the chart
340
- priority: named.base_priority + 1, // the priority relative to others in the same family
341
- update_every: service.update_every, // the expected update frequency of the chart
342
- dimensions: {
343
- 'clients': {
344
- id: 'clients', // the unique id of the dimension
345
- name: '', // the name of the dimension
346
- algorithm: netdata.chartAlgorithms.absolute,// the id of the netdata algorithm
347
- multiplier: 1, // the multiplier
348
- divisor: 1, // the divisor
349
- hidden: false // is hidden (boolean)
350
- }
351
- }
352
- };
353
-
354
- chart = service.chart(id, chart);
355
- named.charts[id] = chart;
356
- }
357
-
358
- service.begin(chart);
359
- service.set('clients', RecursClients);
360
- service.end();
361
- }
362
- }
363
-
364
- if(typeof r.opcodes !== 'undefined')
365
- service.module.chartFromMembers(service, r.opcodes, 'in_opcodes', 'Bind, Global Incoming Requests by OpCode', 'requests/s', 'requests', 'named.in.opcodes', netdata.chartTypes.stacked, named.base_priority + 9, netdata.chartAlgorithms.incremental, 1, 1);
366
-
367
- if(typeof r.qtypes !== 'undefined')
368
- service.module.chartFromMembers(service, r.qtypes, 'in_qtypes', 'Bind, Global Incoming Requests by Query Type', 'requests/s', 'requests', 'named.in.qtypes', netdata.chartTypes.stacked, named.base_priority + 10, netdata.chartAlgorithms.incremental, 1, 1);
369
-
370
- if(typeof r.sockstats !== 'undefined')
371
- service.module.chartFromMembers(service, r.sockstats, 'in_sockstats', 'Bind, Global Socket Statistics', 'operations/s', 'sockets', 'named.in.sockstats', netdata.chartTypes.line, named.base_priority + 11, netdata.chartAlgorithms.incremental, 1, 1);
372
-
373
- if(typeof r.views !== 'undefined') {
374
- for( var x in r.views ) {
375
- var resolver = r.views[x].resolver;
376
-
377
- if(typeof resolver !== 'undefined') {
378
- if(typeof resolver.stats !== 'undefined') {
379
- var NumFetch = 0;
380
- var key = service.name + '.' + x;
381
- var default_enable = false;
382
- var rtt = {}, rtt_enable = false;
383
-
384
- // NumFetch is an absolute value
385
- if(typeof resolver.stats['NumFetch'] !== 'undefined') {
386
- named.lookups.numfetch[key] = true;
387
- NumFetch = resolver.stats['NumFetch'];
388
- delete resolver.stats['NumFetch'];
389
- }
390
- if(typeof resolver.stats['BucketSize'] !== 'undefined') {
391
- delete resolver.stats['BucketSize'];
392
- }
393
-
394
- // split the QryRTT* from the main chart
395
- for( var y in resolver.stats ) {
396
- // we maintain an index of the values found
397
- // mapping them to objects splitted
398
-
399
- var look = named.lookups.resolver_stats[y];
400
- if(typeof look === 'undefined') {
401
- if(y.match(/^QryRTT/) !== null) {
402
- named.lookups.resolver_stats[y] = {
403
- name: y,
404
- type: 'rtt'
405
- };
406
- }
407
- else {
408
- named.lookups.resolver_stats[y] = {
409
- name: y,
410
- type: 'default'
411
- };
412
- }
413
-
414
- look = named.lookups.resolver_stats[y];
415
- // netdata.error('lookup resolver stats value: ' + y + ' >>> ' + look.type);
416
- }
417
-
418
- switch(look.type) {
419
- case 'rtt': rtt[look.name] = resolver.stats[y]; delete resolver.stats[y]; rtt_enable = true; break;
420
- default: default_enable = true; break;
421
- }
422
- }
423
-
424
- if(rtt_enable)
425
- service.module.chartFromMembers(service, rtt, 'view_resolver_rtt_' + x, 'Bind, ' + x + ' View, Resolver Round Trip Timings', 'queries/s', 'view_' + x, 'named.resolver.rtt', netdata.chartTypes.stacked, named.base_priority + 12, netdata.chartAlgorithms.incremental, 1, 1);
426
-
427
- if(default_enable)
428
- service.module.chartFromMembers(service, resolver.stats, 'view_resolver_stats_' + x, 'Bind, ' + x + ' View, Resolver Statistics', 'operations/s', 'view_' + x, 'named.resolver.stats', netdata.chartTypes.line, named.base_priority + 13, netdata.chartAlgorithms.incremental, 1, 1);
429
-
430
- // NumFetch chart
431
- if(typeof named.lookups.numfetch[key] !== 'undefined') {
432
- var id = 'named_' + service.name + '.view_resolver_numfetch_' + x;
433
- var chart = named.charts[id];
434
-
435
- if(typeof chart === 'undefined') {
436
- chart = {
437
- id: id, // the unique id of the chart
438
- name: '', // the unique name of the chart
439
- title: service.name + ' Bind, ' + x + ' View, Resolver Active Queries', // the title of the chart
440
- units: 'queries', // the units of the chart dimensions
441
- family: 'view_' + x, // the family of the chart
442
- context: 'named.resolver.active.queries', // the context of the chart
443
- type: netdata.chartTypes.line, // the type of the chart
444
- priority: named.base_priority + 1001, // the priority relative to others in the same family
445
- update_every: service.update_every, // the expected update frequency of the chart
446
- dimensions: {
447
- 'queries': {
448
- id: 'queries', // the unique id of the dimension
449
- name: '', // the name of the dimension
450
- algorithm: netdata.chartAlgorithms.absolute,// the id of the netdata algorithm
451
- multiplier: 1, // the multiplier
452
- divisor: 1, // the divisor
453
- hidden: false // is hidden (boolean)
454
- }
455
- }
456
- };
457
-
458
- chart = service.chart(id, chart);
459
- named.charts[id] = chart;
460
- }
461
-
462
- service.begin(chart);
463
- service.set('queries', NumFetch);
464
- service.end();
465
- }
466
- }
467
- }
468
-
469
- if(typeof resolver.qtypes !== 'undefined')
470
- service.module.chartFromMembers(service, resolver.qtypes, 'view_resolver_qtypes_' + x, 'Bind, ' + x + ' View, Requests by Query Type', 'requests/s', 'view_' + x, 'named.resolver.qtypes', netdata.chartTypes.stacked, named.base_priority + 14, netdata.chartAlgorithms.incremental, 1, 1);
471
-
472
- //if(typeof resolver.cache !== 'undefined')
473
- // service.module.chartFromMembers(service, resolver.cache, 'view_resolver_cache_' + x, 'Bind, ' + x + ' View, Cache Entries', 'entries', 'view_' + x, 'named.resolver.cache', netdata.chartTypes.stacked, named.base_priority + 15, netdata.chartAlgorithms.absolute, 1, 1);
474
-
475
- if(typeof resolver.cachestats['CacheHits'] !== 'undefined' && resolver.cachestats['CacheHits'] > 0) {
476
- var id = 'named_' + service.name + '.view_resolver_cachehits_' + x;
477
- var chart = named.charts[id];
478
-
479
- if(typeof chart === 'undefined') {
480
- chart = {
481
- id: id, // the unique id of the chart
482
- name: '', // the unique name of the chart
483
- title: service.name + ' Bind, ' + x + ' View, Resolver Cache Hits', // the title of the chart
484
- units: 'operations/s', // the units of the chart dimensions
485
- family: 'view_' + x, // the family of the chart
486
- context: 'named.resolver.cache.hits', // the context of the chart
487
- type: netdata.chartTypes.area, // the type of the chart
488
- priority: named.base_priority + 1100, // the priority relative to others in the same family
489
- update_every: service.update_every, // the expected update frequency of the chart
490
- dimensions: {
491
- 'CacheHits': {
492
- id: 'CacheHits', // the unique id of the dimension
493
- name: 'hits', // the name of the dimension
494
- algorithm: netdata.chartAlgorithms.incremental,// the id of the netdata algorithm
495
- multiplier: 1, // the multiplier
496
- divisor: 1, // the divisor
497
- hidden: false // is hidden (boolean)
498
- },
499
- 'CacheMisses': {
500
- id: 'CacheMisses', // the unique id of the dimension
501
- name: 'misses', // the name of the dimension
502
- algorithm: netdata.chartAlgorithms.incremental,// the id of the netdata algorithm
503
- multiplier: -1, // the multiplier
504
- divisor: 1, // the divisor
505
- hidden: false // is hidden (boolean)
506
- }
507
- }
508
- };
509
-
510
- chart = service.chart(id, chart);
511
- named.charts[id] = chart;
512
- }
513
-
514
- service.begin(chart);
515
- service.set('CacheHits', resolver.cachestats['CacheHits']);
516
- service.set('CacheMisses', resolver.cachestats['CacheMisses']);
517
- service.end();
518
- }
519
-
520
- // this is wrong, it contains many types of info:
521
- // 1. CacheHits, CacheMisses - incremental (added above)
522
- // 2. QueryHits, QueryMisses - incremental
523
- // 3. DeleteLRU, DeleteTTL - incremental
524
- // 4. CacheNodes, CacheBuckets - absolute
525
- // 5. TreeMemTotal, TreeMemInUse - absolute
526
- // 6. HeapMemMax, HeapMemTotal, HeapMemInUse - absolute
527
- //if(typeof resolver.cachestats !== 'undefined')
528
- // service.module.chartFromMembers(service, resolver.cachestats, 'view_resolver_cachestats_' + x, 'Bind, ' + x + ' View, Cache Statistics', 'requests/s', 'view_' + x, 'named.resolver.cache.stats', netdata.chartTypes.line, named.base_priority + 1001, netdata.chartAlgorithms.incremental, 1, 1);
529
-
530
- //if(typeof resolver.adb !== 'undefined')
531
- // service.module.chartFromMembers(service, resolver.adb, 'view_resolver_adb_' + x, 'Bind, ' + x + ' View, ADB Statistics', 'entries', 'view_' + x, 'named.resolver.adb', netdata.chartTypes.line, named.base_priority + 1002, netdata.chartAlgorithms.absolute, 1, 1);
532
- }
533
- }
534
- }
535
- },
536
-
537
- // module.serviceExecute()
538
- // this function is called only from this module
539
- // its purpose is to prepare the request and call
540
- // netdata.serviceExecute()
541
- serviceExecute: function(name, a_url, update_every) {
542
- if(netdata.options.DEBUG === true) netdata.debug(this.name + ': ' + name + ': url: ' + a_url + ', update_every: ' + update_every);
543
- var service = netdata.service({
544
- name: name,
545
- request: netdata.requestFromURL(a_url),
546
- update_every: update_every,
547
- module: this
548
- });
549
-
550
- service.execute(this.processResponse);
551
- },
552
-
553
- configure: function(config) {
554
- var added = 0;
555
-
556
- if(this.enable_autodetect === true) {
557
- this.serviceExecute('local', 'http://localhost:8888/json/v1/server', this.update_every);
558
- added++;
559
- }
560
-
561
- if(typeof(config.servers) !== 'undefined') {
562
- var len = config.servers.length;
563
- while(len--) {
564
- if(typeof config.servers[len].update_every === 'undefined')
565
- config.servers[len].update_every = this.update_every;
566
-
567
- this.serviceExecute(config.servers[len].name, config.servers[len].url, config.servers[len].update_every);
568
- added++;
569
- }
570
- }
571
-
572
- return added;
573
- },
574
-
575
- // module.update()
576
- // this is called repeatidly to collect data, by calling
577
- // netdata.serviceExecute()
578
- update: function(service, callback) {
579
- service.execute(function(serv, data) {
580
- service.module.processResponse(serv, data);
581
- callback();
582
- });
583
- },
47
+ name: __filename,
48
+ enable_autodetect: true,
49
+ update_every: 1,
50
+ base_priority: 60000,
51
+ charts: {},
52
+
53
+ chartFromMembersCreate: function(service, obj, id, title_suffix, units, family, context, type, priority, algorithm, multiplier, divisor) {
54
+ var chart = {
55
+ id: id, // the unique id of the chart
56
+ name: '', // the unique name of the chart
57
+ title: service.name + ' ' + title_suffix, // the title of the chart
58
+ units: units, // the units of the chart dimensions
59
+ family: family, // the family of the chart
60
+ context: context, // the context of the chart
61
+ type: type, // the type of the chart
62
+ priority: priority, // the priority relative to others in the same family
63
+ update_every: service.update_every, // the expected update frequency of the chart
64
+ dimensions: {}
65
+ }
66
+
67
+ var found = 0;
68
+ for(var x in obj) {
69
+ if(typeof(obj[x]) !== 'undefined' && obj[x] !== 0) {
70
+ found++;
71
+ chart.dimensions[x] = {
72
+ id: x, // the unique id of the dimension
73
+ name: x, // the name of the dimension
74
+ algorithm: algorithm, // the id of the netdata algorithm
75
+ multiplier: multiplier, // the multiplier
76
+ divisor: divisor, // the divisor
77
+ hidden: false // is hidden (boolean)
78
+ }
79
+ }
80
+ }
81
+
82
+ if(found === false)
83
+ return null;
84
+
85
+ chart = service.chart(id, chart);
86
+ this.charts[id] = chart;
87
+ return chart;
88
+ },
89
+
90
+ chartFromMembers: function(service, obj, id_suffix, title_suffix, units, family, context, type, priority, algorithm, multiplier, divisor) {
91
+ var id = 'named_' + service.name + '.' + id_suffix;
92
+ var chart = this.charts[id];
93
+
94
+ if(typeof chart === 'undefined') {
95
+ chart = this.chartFromMembersCreate(service, obj, id, title_suffix, units, family, context, type, priority, algorithm, multiplier, divisor);
96
+ if(chart === null) return false;
97
+ }
98
+ else {
99
+ // check if we need to re-generate the chart
100
+ for(var x in obj) {
101
+ if(typeof(chart.dimensions[x]) === 'undefined') {
102
+ chart = this.chartFromMembersCreate(service, obj, id, title_suffix, units, family, context, type, priority, algorithm, multiplier, divisor);
103
+ if(chart === null) return false;
104
+ break;
105
+ }
106
+ }
107
+ }
108
+
109
+ var found = 0;
110
+ service.begin(chart);
111
+ for(var x in obj) {
112
+ if(typeof(chart.dimensions[x]) !== 'undefined') {
113
+ found++;
114
+ service.set(x, obj[x]);
115
+ }
116
+ }
117
+ service.end();
118
+
119
+ if(found > 0) return true;
120
+ return false;
121
+ },
122
+
123
+ // an index to map values to different charts
124
+ lookups: {
125
+ nsstats: {},
126
+ resolver_stats: {},
127
+ numfetch: {}
128
+ },
129
+
130
+ // transform the XML response of bind
131
+ // to the JSON response of bind
132
+ xml2js: function(service, data_xml) {
133
+ var d = XML.parse(data_xml);
134
+ if(d === null) return null;
135
+
136
+ var data = {};
137
+ var len = d.server.counters.length;
138
+ while(len--) {
139
+ var a = d.server.counters[len];
140
+ if(typeof a.counter === 'undefined') continue;
141
+ if(a.type === 'opcode') a.type = 'opcodes';
142
+ else if(a.type === 'qtype') a.type = 'qtypes';
143
+ else if(a.type === 'nsstat') a.type = 'nsstats';
144
+ var aa = data[a.type] = {};
145
+ var alen = 0
146
+ var alen2 = a.counter.length;
147
+ while(alen < alen2) {
148
+ aa[a.counter[alen].name] = parseInt(a.counter[alen]._Data);
149
+ alen++;
150
+ }
151
+ }
152
+
153
+ data.views = {};
154
+ var vlen = d.views.view.length;
155
+ while(vlen--) {
156
+ var vname = d.views.view[vlen].name;
157
+ data.views[vname] = { resolver: {} };
158
+ var len = d.views.view[vlen].counters.length;
159
+ while(len--) {
160
+ var a = d.views.view[vlen].counters[len];
161
+ if(typeof a.counter === 'undefined') continue;
162
+ if(a.type === 'resstats') a.type = 'stats';
163
+ else if(a.type === 'resqtype') a.type = 'qtypes';
164
+ else if(a.type === 'adbstat') a.type = 'adb';
165
+ var aa = data.views[vname].resolver[a.type] = {};
166
+ var alen = 0;
167
+ var alen2 = a.counter.length;
168
+ while(alen < alen2) {
169
+ aa[a.counter[alen].name] = parseInt(a.counter[alen]._Data);
170
+ alen++;
171
+ }
172
+ }
173
+ }
174
+
175
+ return data;
176
+ },
177
+
178
+ processResponse: function(service, data) {
179
+ if(data !== null) {
180
+ var r;
181
+
182
+ // parse XML or JSON
183
+ // pepending on the URL given
184
+ if(service.request.path.match(/^\/xml/) !== null)
185
+ r = named.xml2js(service, data);
186
+ else
187
+ r = JSON.parse(data);
188
+
189
+ if(typeof r === 'undefined' || r === null) {
190
+ netdata.serviceError(service, "Cannot parse these data: " + data);
191
+ return;
192
+ }
193
+
194
+ if(service.added !== true)
195
+ service.commit();
196
+
197
+ if(typeof r.nsstats !== 'undefined') {
198
+ // we split the nsstats object to several others
199
+ var global_requests = {}, global_requests_enable = false;
200
+ var global_failures = {}, global_failures_enable = false;
201
+ var global_failures_detail = {}, global_failures_detail_enable = false;
202
+ var global_updates = {}, global_updates_enable = false;
203
+ var protocol_queries = {}, protocol_queries_enable = false;
204
+ var global_queries = {}, global_queries_enable = false;
205
+ var global_queries_success = {}, global_queries_success_enable = false;
206
+ var default_enable = false;
207
+ var RecursClients = 0;
208
+
209
+ // RecursClients is an absolute value
210
+ if(typeof r.nsstats['RecursClients'] !== 'undefined') {
211
+ RecursClients = r.nsstats['RecursClients'];
212
+ delete r.nsstats['RecursClients'];
213
+ }
214
+
215
+ for( var x in r.nsstats ) {
216
+ // we maintain an index of the values found
217
+ // mapping them to objects splitted
218
+
219
+ var look = named.lookups.nsstats[x];
220
+ if(typeof look === 'undefined') {
221
+ // a new value, not found in the index
222
+ // index it:
223
+ if(x === 'Requestv4') {
224
+ named.lookups.nsstats[x] = {
225
+ name: 'IPv4',
226
+ type: 'global_requests'
227
+ };
228
+ }
229
+ else if(x === 'Requestv6') {
230
+ named.lookups.nsstats[x] = {
231
+ name: 'IPv6',
232
+ type: 'global_requests'
233
+ };
234
+ }
235
+ else if(x === 'QryFailure') {
236
+ named.lookups.nsstats[x] = {
237
+ name: 'failures',
238
+ type: 'global_failures'
239
+ };
240
+ }
241
+ else if(x === 'QryUDP') {
242
+ named.lookups.nsstats[x] = {
243
+ name: 'UDP',
244
+ type: 'protocol_queries'
245
+ };
246
+ }
247
+ else if(x === 'QryTCP') {
248
+ named.lookups.nsstats[x] = {
249
+ name: 'TCP',
250
+ type: 'protocol_queries'
251
+ };
252
+ }
253
+ else if(x === 'QrySuccess') {
254
+ named.lookups.nsstats[x] = {
255
+ name: 'queries',
256
+ type: 'global_queries_success'
257
+ };
258
+ }
259
+ else if(x.match(/QryRej$/) !== null) {
260
+ named.lookups.nsstats[x] = {
261
+ name: x,
262
+ type: 'global_failures_detail'
263
+ };
264
+ }
265
+ else if(x.match(/^Qry/) !== null) {
266
+ named.lookups.nsstats[x] = {
267
+ name: x,
268
+ type: 'global_queries'
269
+ };
270
+ }
271
+ else if(x.match(/^Update/) !== null) {
272
+ named.lookups.nsstats[x] = {
273
+ name: x,
274
+ type: 'global_updates'
275
+ };
276
+ }
277
+ else {
278
+ // values not mapped, will remain
279
+ // in the default map
280
+ named.lookups.nsstats[x] = {
281
+ name: x,
282
+ type: 'default'
283
+ };
284
+ }
285
+
286
+ look = named.lookups.nsstats[x];
287
+ // netdata.error('lookup nsstats value: ' + x + ' >>> ' + named.lookups.nsstats[x].type);
288
+ }
289
+
290
+ switch(look.type) {
291
+ case 'global_requests': global_requests[look.name] = r.nsstats[x]; delete r.nsstats[x]; global_requests_enable = true; break;
292
+ case 'global_queries': global_queries[look.name] = r.nsstats[x]; delete r.nsstats[x]; global_queries_enable = true; break;
293
+ case 'global_queries_success': global_queries_success[look.name] = r.nsstats[x]; delete r.nsstats[x]; global_queries_success_enable = true; break;
294
+ case 'global_updates': global_updates[look.name] = r.nsstats[x]; delete r.nsstats[x]; global_updates_enable = true; break;
295
+ case 'protocol_queries': protocol_queries[look.name] = r.nsstats[x]; delete r.nsstats[x]; protocol_queries_enable = true; break;
296
+ case 'global_failures': global_failures[look.name] = r.nsstats[x]; delete r.nsstats[x]; global_failures_enable = true; break;
297
+ case 'global_failures_detail': global_failures_detail[look.name] = r.nsstats[x]; delete r.nsstats[x]; global_failures_detail_enable = true; break;
298
+ default: default_enable = true; break;
299
+ }
300
+ }
301
+
302
+ if(global_requests_enable == true)
303
+ service.module.chartFromMembers(service, global_requests, 'received_requests', 'Bind, Global Received Requests by IP version', 'requests/s', 'requests', 'named.requests', netdata.chartTypes.stacked, named.base_priority + 1, netdata.chartAlgorithms.incremental, 1, 1);
304
+
305
+ if(global_queries_success_enable == true)
306
+ service.module.chartFromMembers(service, global_queries_success, 'global_queries_success', 'Bind, Global Successful Queries', 'queries/s', 'queries', 'named.queries.succcess', netdata.chartTypes.line, named.base_priority + 2, netdata.chartAlgorithms.incremental, 1, 1);
307
+
308
+ if(protocol_queries_enable == true)
309
+ service.module.chartFromMembers(service, protocol_queries, 'protocols_queries', 'Bind, Global Queries by IP Protocol', 'queries/s', 'queries', 'named.protocol.queries', netdata.chartTypes.stacked, named.base_priority + 3, netdata.chartAlgorithms.incremental, 1, 1);
310
+
311
+ if(global_queries_enable == true)
312
+ service.module.chartFromMembers(service, global_queries, 'global_queries', 'Bind, Global Queries Analysis', 'queries/s', 'queries', 'named.global.queries', netdata.chartTypes.stacked, named.base_priority + 4, netdata.chartAlgorithms.incremental, 1, 1);
313
+
314
+ if(global_updates_enable == true)
315
+ service.module.chartFromMembers(service, global_updates, 'received_updates', 'Bind, Global Received Updates', 'updates/s', 'updates', 'named.global.updates', netdata.chartTypes.stacked, named.base_priority + 5, netdata.chartAlgorithms.incremental, 1, 1);
316
+
317
+ if(global_failures_enable == true)
318
+ service.module.chartFromMembers(service, global_failures, 'query_failures', 'Bind, Global Query Failures', 'failures/s', 'failures', 'named.global.failures', netdata.chartTypes.line, named.base_priority + 6, netdata.chartAlgorithms.incremental, 1, 1);
319
+
320
+ if(global_failures_detail_enable == true)
321
+ service.module.chartFromMembers(service, global_failures_detail, 'query_failures_detail', 'Bind, Global Query Failures Analysis', 'failures/s', 'failures', 'named.global.failures.detail', netdata.chartTypes.stacked, named.base_priority + 7, netdata.chartAlgorithms.incremental, 1, 1);
322
+
323
+ if(default_enable === true)
324
+ service.module.chartFromMembers(service, r.nsstats, 'nsstats', 'Bind, Other Global Server Statistics', 'operations/s', 'other', 'named.nsstats', netdata.chartTypes.line, named.base_priority + 8, netdata.chartAlgorithms.incremental, 1, 1);
325
+
326
+ // RecursClients chart
327
+ {
328
+ var id = 'named_' + service.name + '.recursive_clients';
329
+ var chart = named.charts[id];
330
+
331
+ if(typeof chart === 'undefined') {
332
+ chart = {
333
+ id: id, // the unique id of the chart
334
+ name: '', // the unique name of the chart
335
+ title: service.name + ' Bind, Current Recursive Clients', // the title of the chart
336
+ units: 'clients', // the units of the chart dimensions
337
+ family: 'clients', // the family of the chart
338
+ context: 'named.recursive.clients', // the context of the chart
339
+ type: netdata.chartTypes.line, // the type of the chart
340
+ priority: named.base_priority + 1, // the priority relative to others in the same family
341
+ update_every: service.update_every, // the expected update frequency of the chart
342
+ dimensions: {
343
+ 'clients': {
344
+ id: 'clients', // the unique id of the dimension
345
+ name: '', // the name of the dimension
346
+ algorithm: netdata.chartAlgorithms.absolute,// the id of the netdata algorithm
347
+ multiplier: 1, // the multiplier
348
+ divisor: 1, // the divisor
349
+ hidden: false // is hidden (boolean)
350
+ }
351
+ }
352
+ };
353
+
354
+ chart = service.chart(id, chart);
355
+ named.charts[id] = chart;
356
+ }
357
+
358
+ service.begin(chart);
359
+ service.set('clients', RecursClients);
360
+ service.end();
361
+ }
362
+ }
363
+
364
+ if(typeof r.opcodes !== 'undefined')
365
+ service.module.chartFromMembers(service, r.opcodes, 'in_opcodes', 'Bind, Global Incoming Requests by OpCode', 'requests/s', 'requests', 'named.in.opcodes', netdata.chartTypes.stacked, named.base_priority + 9, netdata.chartAlgorithms.incremental, 1, 1);
366
+
367
+ if(typeof r.qtypes !== 'undefined')
368
+ service.module.chartFromMembers(service, r.qtypes, 'in_qtypes', 'Bind, Global Incoming Requests by Query Type', 'requests/s', 'requests', 'named.in.qtypes', netdata.chartTypes.stacked, named.base_priority + 10, netdata.chartAlgorithms.incremental, 1, 1);
369
+
370
+ if(typeof r.sockstats !== 'undefined')
371
+ service.module.chartFromMembers(service, r.sockstats, 'in_sockstats', 'Bind, Global Socket Statistics', 'operations/s', 'sockets', 'named.in.sockstats', netdata.chartTypes.line, named.base_priority + 11, netdata.chartAlgorithms.incremental, 1, 1);
372
+
373
+ if(typeof r.views !== 'undefined') {
374
+ for( var x in r.views ) {
375
+ var resolver = r.views[x].resolver;
376
+
377
+ if(typeof resolver !== 'undefined') {
378
+ if(typeof resolver.stats !== 'undefined') {
379
+ var NumFetch = 0;
380
+ var key = service.name + '.' + x;
381
+ var default_enable = false;
382
+ var rtt = {}, rtt_enable = false;
383
+
384
+ // NumFetch is an absolute value
385
+ if(typeof resolver.stats['NumFetch'] !== 'undefined') {
386
+ named.lookups.numfetch[key] = true;
387
+ NumFetch = resolver.stats['NumFetch'];
388
+ delete resolver.stats['NumFetch'];
389
+ }
390
+ if(typeof resolver.stats['BucketSize'] !== 'undefined') {
391
+ delete resolver.stats['BucketSize'];
392
+ }
393
+
394
+ // split the QryRTT* from the main chart
395
+ for( var y in resolver.stats ) {
396
+ // we maintain an index of the values found
397
+ // mapping them to objects splitted
398
+
399
+ var look = named.lookups.resolver_stats[y];
400
+ if(typeof look === 'undefined') {
401
+ if(y.match(/^QryRTT/) !== null) {
402
+ named.lookups.resolver_stats[y] = {
403
+ name: y,
404
+ type: 'rtt'
405
+ };
406
+ }
407
+ else {
408
+ named.lookups.resolver_stats[y] = {
409
+ name: y,
410
+ type: 'default'
411
+ };
412
+ }
413
+
414
+ look = named.lookups.resolver_stats[y];
415
+ // netdata.error('lookup resolver stats value: ' + y + ' >>> ' + look.type);
416
+ }
417
+
418
+ switch(look.type) {
419
+ case 'rtt': rtt[look.name] = resolver.stats[y]; delete resolver.stats[y]; rtt_enable = true; break;
420
+ default: default_enable = true; break;
421
+ }
422
+ }
423
+
424
+ if(rtt_enable)
425
+ service.module.chartFromMembers(service, rtt, 'view_resolver_rtt_' + x, 'Bind, ' + x + ' View, Resolver Round Trip Timings', 'queries/s', 'view_' + x, 'named.resolver.rtt', netdata.chartTypes.stacked, named.base_priority + 12, netdata.chartAlgorithms.incremental, 1, 1);
426
+
427
+ if(default_enable)
428
+ service.module.chartFromMembers(service, resolver.stats, 'view_resolver_stats_' + x, 'Bind, ' + x + ' View, Resolver Statistics', 'operations/s', 'view_' + x, 'named.resolver.stats', netdata.chartTypes.line, named.base_priority + 13, netdata.chartAlgorithms.incremental, 1, 1);
429
+
430
+ // NumFetch chart
431
+ if(typeof named.lookups.numfetch[key] !== 'undefined') {
432
+ var id = 'named_' + service.name + '.view_resolver_numfetch_' + x;
433
+ var chart = named.charts[id];
434
+
435
+ if(typeof chart === 'undefined') {
436
+ chart = {
437
+ id: id, // the unique id of the chart
438
+ name: '', // the unique name of the chart
439
+ title: service.name + ' Bind, ' + x + ' View, Resolver Active Queries', // the title of the chart
440
+ units: 'queries', // the units of the chart dimensions
441
+ family: 'view_' + x, // the family of the chart
442
+ context: 'named.resolver.active.queries', // the context of the chart
443
+ type: netdata.chartTypes.line, // the type of the chart
444
+ priority: named.base_priority + 1001, // the priority relative to others in the same family
445
+ update_every: service.update_every, // the expected update frequency of the chart
446
+ dimensions: {
447
+ 'queries': {
448
+ id: 'queries', // the unique id of the dimension
449
+ name: '', // the name of the dimension
450
+ algorithm: netdata.chartAlgorithms.absolute,// the id of the netdata algorithm
451
+ multiplier: 1, // the multiplier
452
+ divisor: 1, // the divisor
453
+ hidden: false // is hidden (boolean)
454
+ }
455
+ }
456
+ };
457
+
458
+ chart = service.chart(id, chart);
459
+ named.charts[id] = chart;
460
+ }
461
+
462
+ service.begin(chart);
463
+ service.set('queries', NumFetch);
464
+ service.end();
465
+ }
466
+ }
467
+ }
468
+
469
+ if(typeof resolver.qtypes !== 'undefined')
470
+ service.module.chartFromMembers(service, resolver.qtypes, 'view_resolver_qtypes_' + x, 'Bind, ' + x + ' View, Requests by Query Type', 'requests/s', 'view_' + x, 'named.resolver.qtypes', netdata.chartTypes.stacked, named.base_priority + 14, netdata.chartAlgorithms.incremental, 1, 1);
471
+
472
+ //if(typeof resolver.cache !== 'undefined')
473
+ // service.module.chartFromMembers(service, resolver.cache, 'view_resolver_cache_' + x, 'Bind, ' + x + ' View, Cache Entries', 'entries', 'view_' + x, 'named.resolver.cache', netdata.chartTypes.stacked, named.base_priority + 15, netdata.chartAlgorithms.absolute, 1, 1);
474
+
475
+ if(typeof resolver.cachestats['CacheHits'] !== 'undefined' && resolver.cachestats['CacheHits'] > 0) {
476
+ var id = 'named_' + service.name + '.view_resolver_cachehits_' + x;
477
+ var chart = named.charts[id];
478
+
479
+ if(typeof chart === 'undefined') {
480
+ chart = {
481
+ id: id, // the unique id of the chart
482
+ name: '', // the unique name of the chart
483
+ title: service.name + ' Bind, ' + x + ' View, Resolver Cache Hits', // the title of the chart
484
+ units: 'operations/s', // the units of the chart dimensions
485
+ family: 'view_' + x, // the family of the chart
486
+ context: 'named.resolver.cache.hits', // the context of the chart
487
+ type: netdata.chartTypes.area, // the type of the chart
488
+ priority: named.base_priority + 1100, // the priority relative to others in the same family
489
+ update_every: service.update_every, // the expected update frequency of the chart
490
+ dimensions: {
491
+ 'CacheHits': {
492
+ id: 'CacheHits', // the unique id of the dimension
493
+ name: 'hits', // the name of the dimension
494
+ algorithm: netdata.chartAlgorithms.incremental,// the id of the netdata algorithm
495
+ multiplier: 1, // the multiplier
496
+ divisor: 1, // the divisor
497
+ hidden: false // is hidden (boolean)
498
+ },
499
+ 'CacheMisses': {
500
+ id: 'CacheMisses', // the unique id of the dimension
501
+ name: 'misses', // the name of the dimension
502
+ algorithm: netdata.chartAlgorithms.incremental,// the id of the netdata algorithm
503
+ multiplier: -1, // the multiplier
504
+ divisor: 1, // the divisor
505
+ hidden: false // is hidden (boolean)
506
+ }
507
+ }
508
+ };
509
+
510
+ chart = service.chart(id, chart);
511
+ named.charts[id] = chart;
512
+ }
513
+
514
+ service.begin(chart);
515
+ service.set('CacheHits', resolver.cachestats['CacheHits']);
516
+ service.set('CacheMisses', resolver.cachestats['CacheMisses']);
517
+ service.end();
518
+ }
519
+
520
+ // this is wrong, it contains many types of info:
521
+ // 1. CacheHits, CacheMisses - incremental (added above)
522
+ // 2. QueryHits, QueryMisses - incremental
523
+ // 3. DeleteLRU, DeleteTTL - incremental
524
+ // 4. CacheNodes, CacheBuckets - absolute
525
+ // 5. TreeMemTotal, TreeMemInUse - absolute
526
+ // 6. HeapMemMax, HeapMemTotal, HeapMemInUse - absolute
527
+ //if(typeof resolver.cachestats !== 'undefined')
528
+ // service.module.chartFromMembers(service, resolver.cachestats, 'view_resolver_cachestats_' + x, 'Bind, ' + x + ' View, Cache Statistics', 'requests/s', 'view_' + x, 'named.resolver.cache.stats', netdata.chartTypes.line, named.base_priority + 1001, netdata.chartAlgorithms.incremental, 1, 1);
529
+
530
+ //if(typeof resolver.adb !== 'undefined')
531
+ // service.module.chartFromMembers(service, resolver.adb, 'view_resolver_adb_' + x, 'Bind, ' + x + ' View, ADB Statistics', 'entries', 'view_' + x, 'named.resolver.adb', netdata.chartTypes.line, named.base_priority + 1002, netdata.chartAlgorithms.absolute, 1, 1);
532
+ }
533
+ }
534
+ }
535
+ },
536
+
537
+ // module.serviceExecute()
538
+ // this function is called only from this module
539
+ // its purpose is to prepare the request and call
540
+ // netdata.serviceExecute()
541
+ serviceExecute: function(name, a_url, update_every) {
542
+ if(netdata.options.DEBUG === true) netdata.debug(this.name + ': ' + name + ': url: ' + a_url + ', update_every: ' + update_every);
543
+ var service = netdata.service({
544
+ name: name,
545
+ request: netdata.requestFromURL(a_url),
546
+ update_every: update_every,
547
+ module: this
548
+ });
549
+
550
+ service.execute(this.processResponse);
551
+ },
552
+
553
+ configure: function(config) {
554
+ var added = 0;
555
+
556
+ if(this.enable_autodetect === true) {
557
+ this.serviceExecute('local', 'http://localhost:8888/json/v1/server', this.update_every);
558
+ added++;
559
+ }
560
+
561
+ if(typeof(config.servers) !== 'undefined') {
562
+ var len = config.servers.length;
563
+ while(len--) {
564
+ if(typeof config.servers[len].update_every === 'undefined')
565
+ config.servers[len].update_every = this.update_every;
566
+
567
+ this.serviceExecute(config.servers[len].name, config.servers[len].url, config.servers[len].update_every);
568
+ added++;
569
+ }
570
+ }
571
+
572
+ return added;
573
+ },
574
+
575
+ // module.update()
576
+ // this is called repeatidly to collect data, by calling
577
+ // netdata.serviceExecute()
578
+ update: function(service, callback) {
579
+ service.execute(function(serv, data) {
580
+ service.module.processResponse(serv, data);
581
+ callback();
582
+ });
583
+ },
584
};
585
586
module.exports = named;
node.d/sma_webbox.node.js
+216
-216
@@ -6,20 +6,20 @@
6
// example configuration in /etc/netdata/sma_webbox.conf
7
/*
8
{
9
- "enable_autodetect": false,
10
- "update_every": 5,
11
- "servers": [
12
- {
13
- "name": "plant1",
14
- "hostname": "10.0.1.1",
15
- "update_every": 10
16
- },
17
- {
18
- "name": "plant2",
19
- "hostname": "10.0.2.1",
20
- "update_every": 15
21
- }
22
- ]
9
+ "enable_autodetect": false,
10
+ "update_every": 5,
11
+ "servers": [
12
+ {
13
+ "name": "plant1",
14
+ "hostname": "10.0.1.1",
15
+ "update_every": 10
16
+ },
17
+ {
18
+ "name": "plant2",
19
+ "hostname": "10.0.2.1",
20
+ "update_every": 15
21
+ }
22
+ ]
23
}
24
*/
25
@@ -30,208 +30,208 @@ var netdata = require('netdata');
30
if(netdata.options.DEBUG === true) netdata.debug('loaded ' + __filename + ' plugin');
31
32
var webbox = {
33
- name: __filename,
34
- enable_autodetect: true,
35
- update_every: 1,
36
- base_priority: 60000,
37
- charts: {},
38
-
39
- processResponse: function(service, data) {
40
- if(data !== null) {
41
- var r = JSON.parse(data);
42
-
43
- var d = {
44
- 'GriPwr': {
45
- unit: null,
46
- value: null
47
- },
48
- 'GriEgyTdy': {
49
- unit: null,
50
- value: null
51
- },
52
- 'GriEgyTot': {
53
- unit: null,
54
- value: null
55
- }
56
- };
57
-
58
- // parse the webbox response
59
- // and put it in our d object
60
- var found = 0;
61
- var len = r.result.overview.length;
62
- while(len--) {
63
- var e = r.result.overview[len];
64
- if(typeof(d[e.meta]) !== 'undefined') {
65
- found++;
66
- d[e.meta].value = e.value;
67
- d[e.meta].unit = e.unit;
68
- }
69
- }
70
-
71
- // add the service
72
- if(found > 0 && service.added !== true)
73
- service.commit();
74
-
75
- // Grid Current Power Chart
76
- if(d['GriPwr'].value !== null) {
77
- var id = 'sma_webbox_' + service.name + '.current';
78
- var chart = webbox.charts[id];
79
-
80
- if(typeof chart === 'undefined') {
81
- chart = {
82
- id: id, // the unique id of the chart
83
- name: '', // the unique name of the chart
84
- title: service.name + ' Current Grid Power', // the title of the chart
85
- units: d['GriPwr'].unit, // the units of the chart dimensions
86
- family: 'now', // the family of the chart
87
- context: 'sma_webbox.grid.power', // the context of the chart
88
- type: netdata.chartTypes.area, // the type of the chart
89
- priority: webbox.base_priority + 1, // the priority relative to others in the same family
90
- update_every: service.update_every, // the expected update frequency of the chart
91
- dimensions: {
92
- 'GriPwr': {
93
- id: 'GriPwr', // the unique id of the dimension
94
- name: 'power', // the name of the dimension
95
- algorithm: netdata.chartAlgorithms.absolute,// the id of the netdata algorithm
96
- multiplier: 1, // the multiplier
97
- divisor: 1, // the divisor
98
- hidden: false // is hidden (boolean)
99
- }
100
- }
101
- };
102
-
103
- chart = service.chart(id, chart);
104
- webbox.charts[id] = chart;
105
- }
106
-
107
- service.begin(chart);
108
- service.set('GriPwr', Math.round(d['GriPwr'].value));
109
- service.end();
110
- }
111
-
112
- if(d['GriEgyTdy'].value !== null) {
113
- var id = 'sma_webbox_' + service.name + '.today';
114
- var chart = webbox.charts[id];
115
-
116
- if(typeof chart === 'undefined') {
117
- chart = {
118
- id: id, // the unique id of the chart
119
- name: '', // the unique name of the chart
120
- title: service.name + ' Today Grid Power', // the title of the chart
121
- units: d['GriEgyTdy'].unit, // the units of the chart dimensions
122
- family: 'today', // the family of the chart
123
- context: 'sma_webbox.grid.power.today', // the context of the chart
124
- type: netdata.chartTypes.area, // the type of the chart
125
- priority: webbox.base_priority + 2, // the priority relative to others in the same family
126
- update_every: service.update_every, // the expected update frequency of the chart
127
- dimensions: {
128
- 'GriEgyTdy': {
129
- id: 'GriEgyTdy', // the unique id of the dimension
130
- name: 'power', // the name of the dimension
131
- algorithm: netdata.chartAlgorithms.absolute,// the id of the netdata algorithm
132
- multiplier: 1, // the multiplier
133
- divisor: 1000, // the divisor
134
- hidden: false // is hidden (boolean)
135
- }
136
- }
137
- };
138
-
139
- chart = service.chart(id, chart);
140
- webbox.charts[id] = chart;
141
- }
142
-
143
- service.begin(chart);
144
- service.set('GriEgyTdy', Math.round(d['GriEgyTdy'].value * 1000));
145
- service.end();
146
- }
147
-
148
- if(d['GriEgyTot'].value !== null) {
149
- var id = 'sma_webbox_' + service.name + '.total';
150
- var chart = webbox.charts[id];
151
-
152
- if(typeof chart === 'undefined') {
153
- chart = {
154
- id: id, // the unique id of the chart
155
- name: '', // the unique name of the chart
156
- title: service.name + ' Total Grid Power', // the title of the chart
157
- units: d['GriEgyTot'].unit, // the units of the chart dimensions
158
- family: 'total', // the family of the chart
159
- context: 'sma_webbox.grid.power.total', // the context of the chart
160
- type: netdata.chartTypes.area, // the type of the chart
161
- priority: webbox.base_priority + 3, // the priority relative to others in the same family
162
- update_every: service.update_every, // the expected update frequency of the chart
163
- dimensions: {
164
- 'GriEgyTot': {
165
- id: 'GriEgyTot', // the unique id of the dimension
166
- name: 'power', // the name of the dimension
167
- algorithm: netdata.chartAlgorithms.absolute,// the id of the netdata algorithm
168
- multiplier: 1, // the multiplier
169
- divisor: 1000, // the divisor
170
- hidden: false // is hidden (boolean)
171
- }
172
- }
173
- };
174
-
175
- chart = service.chart(id, chart);
176
- webbox.charts[id] = chart;
177
- }
178
-
179
- service.begin(chart);
180
- service.set('GriEgyTot', Math.round(d['GriEgyTot'].value * 1000));
181
- service.end();
182
- }
183
- }
184
- },
185
-
186
- // module.serviceExecute()
187
- // this function is called only from this module
188
- // its purpose is to prepare the request and call
189
- // netdata.serviceExecute()
190
- serviceExecute: function(name, hostname, update_every) {
191
- if(netdata.options.DEBUG === true) netdata.debug(this.name + ': ' + name + ': hostname: ' + hostname + ', update_every: ' + update_every);
192
-
193
- var service = netdata.service({
194
- name: name,
195
- request: netdata.requestFromURL('http://' + hostname + '/rpc'),
196
- update_every: update_every,
197
- module: this
198
- });
199
- service.postData = 'RPC={"proc":"GetPlantOverview","format":"JSON","version":"1.0","id":"1"}';
200
- service.request.method = 'POST';
201
- service.request.headers['Content-Length'] = service.postData.length;
202
-
203
- service.execute(this.processResponse);
204
- },
205
-
206
- configure: function(config) {
207
- var added = 0;
208
-
209
- if(typeof(config.servers) !== 'undefined') {
210
- var len = config.servers.length;
211
- while(len--) {
212
- if(typeof config.servers[len].update_every === 'undefined')
213
- config.servers[len].update_every = this.update_every;
214
-
215
- if(config.servers[len].update_every < 5)
216
- config.servers[len].update_every = 5;
217
-
218
- this.serviceExecute(config.servers[len].name, config.servers[len].hostname, config.servers[len].update_every);
219
- added++;
220
- }
221
- }
222
-
223
- return added;
224
- },
225
-
226
- // module.update()
227
- // this is called repeatidly to collect data, by calling
228
- // netdata.serviceExecute()
229
- update: function(service, callback) {
230
- service.execute(function(serv, data) {
231
- service.module.processResponse(serv, data);
232
- callback();
233
- });
234
- },
33
+ name: __filename,
34
+ enable_autodetect: true,
35
+ update_every: 1,
36
+ base_priority: 60000,
37
+ charts: {},
38
+
39
+ processResponse: function(service, data) {
40
+ if(data !== null) {
41
+ var r = JSON.parse(data);
42
+
43
+ var d = {
44
+ 'GriPwr': {
45
+ unit: null,
46
+ value: null
47
+ },
48
+ 'GriEgyTdy': {
49
+ unit: null,
50
+ value: null
51
+ },
52
+ 'GriEgyTot': {
53
+ unit: null,
54
+ value: null
55
+ }
56
+ };
57
+
58
+ // parse the webbox response
59
+ // and put it in our d object
60
+ var found = 0;
61
+ var len = r.result.overview.length;
62
+ while(len--) {
63
+ var e = r.result.overview[len];
64
+ if(typeof(d[e.meta]) !== 'undefined') {
65
+ found++;
66
+ d[e.meta].value = e.value;
67
+ d[e.meta].unit = e.unit;
68
+ }
69
+ }
70
+
71
+ // add the service
72
+ if(found > 0 && service.added !== true)
73
+ service.commit();
74
+
75
+ // Grid Current Power Chart
76
+ if(d['GriPwr'].value !== null) {
77
+ var id = 'sma_webbox_' + service.name + '.current';
78
+ var chart = webbox.charts[id];
79
+
80
+ if(typeof chart === 'undefined') {
81
+ chart = {
82
+ id: id, // the unique id of the chart
83
+ name: '', // the unique name of the chart
84
+ title: service.name + ' Current Grid Power', // the title of the chart
85
+ units: d['GriPwr'].unit, // the units of the chart dimensions
86
+ family: 'now', // the family of the chart
87
+ context: 'sma_webbox.grid.power', // the context of the chart
88
+ type: netdata.chartTypes.area, // the type of the chart
89
+ priority: webbox.base_priority + 1, // the priority relative to others in the same family
90
+ update_every: service.update_every, // the expected update frequency of the chart
91
+ dimensions: {
92
+ 'GriPwr': {
93
+ id: 'GriPwr', // the unique id of the dimension
94
+ name: 'power', // the name of the dimension
95
+ algorithm: netdata.chartAlgorithms.absolute,// the id of the netdata algorithm
96
+ multiplier: 1, // the multiplier
97
+ divisor: 1, // the divisor
98
+ hidden: false // is hidden (boolean)
99
+ }
100
+ }
101
+ };
102
+
103
+ chart = service.chart(id, chart);
104
+ webbox.charts[id] = chart;
105
+ }
106
+
107
+ service.begin(chart);
108
+ service.set('GriPwr', Math.round(d['GriPwr'].value));
109
+ service.end();
110
+ }
111
+
112
+ if(d['GriEgyTdy'].value !== null) {
113
+ var id = 'sma_webbox_' + service.name + '.today';
114
+ var chart = webbox.charts[id];
115
+
116
+ if(typeof chart === 'undefined') {
117
+ chart = {
118
+ id: id, // the unique id of the chart
119
+ name: '', // the unique name of the chart
120
+ title: service.name + ' Today Grid Power', // the title of the chart
121
+ units: d['GriEgyTdy'].unit, // the units of the chart dimensions
122
+ family: 'today', // the family of the chart
123
+ context: 'sma_webbox.grid.power.today', // the context of the chart
124
+ type: netdata.chartTypes.area, // the type of the chart
125
+ priority: webbox.base_priority + 2, // the priority relative to others in the same family
126
+ update_every: service.update_every, // the expected update frequency of the chart
127
+ dimensions: {
128
+ 'GriEgyTdy': {
129
+ id: 'GriEgyTdy', // the unique id of the dimension
130
+ name: 'power', // the name of the dimension
131
+ algorithm: netdata.chartAlgorithms.absolute,// the id of the netdata algorithm
132
+ multiplier: 1, // the multiplier
133
+ divisor: 1000, // the divisor
134
+ hidden: false // is hidden (boolean)
135
+ }
136
+ }
137
+ };
138
+
139
+ chart = service.chart(id, chart);
140
+ webbox.charts[id] = chart;
141
+ }
142
+
143
+ service.begin(chart);
144
+ service.set('GriEgyTdy', Math.round(d['GriEgyTdy'].value * 1000));
145
+ service.end();
146
+ }
147
+
148
+ if(d['GriEgyTot'].value !== null) {
149
+ var id = 'sma_webbox_' + service.name + '.total';
150
+ var chart = webbox.charts[id];
151
+
152
+ if(typeof chart === 'undefined') {
153
+ chart = {
154
+ id: id, // the unique id of the chart
155
+ name: '', // the unique name of the chart
156
+ title: service.name + ' Total Grid Power', // the title of the chart
157
+ units: d['GriEgyTot'].unit, // the units of the chart dimensions
158
+ family: 'total', // the family of the chart
159
+ context: 'sma_webbox.grid.power.total', // the context of the chart
160
+ type: netdata.chartTypes.area, // the type of the chart
161
+ priority: webbox.base_priority + 3, // the priority relative to others in the same family
162
+ update_every: service.update_every, // the expected update frequency of the chart
163
+ dimensions: {
164
+ 'GriEgyTot': {
165
+ id: 'GriEgyTot', // the unique id of the dimension
166
+ name: 'power', // the name of the dimension
167
+ algorithm: netdata.chartAlgorithms.absolute,// the id of the netdata algorithm
168
+ multiplier: 1, // the multiplier
169
+ divisor: 1000, // the divisor
170
+ hidden: false // is hidden (boolean)
171
+ }
172
+ }
173
+ };
174
+
175
+ chart = service.chart(id, chart);
176
+ webbox.charts[id] = chart;
177
+ }
178
+
179
+ service.begin(chart);
180
+ service.set('GriEgyTot', Math.round(d['GriEgyTot'].value * 1000));
181
+ service.end();
182
+ }
183
+ }
184
+ },
185
+
186
+ // module.serviceExecute()
187
+ // this function is called only from this module
188
+ // its purpose is to prepare the request and call
189
+ // netdata.serviceExecute()
190
+ serviceExecute: function(name, hostname, update_every) {
191
+ if(netdata.options.DEBUG === true) netdata.debug(this.name + ': ' + name + ': hostname: ' + hostname + ', update_every: ' + update_every);
192
+
193
+ var service = netdata.service({
194
+ name: name,
195
+ request: netdata.requestFromURL('http://' + hostname + '/rpc'),
196
+ update_every: update_every,
197
+ module: this
198
+ });
199
+ service.postData = 'RPC={"proc":"GetPlantOverview","format":"JSON","version":"1.0","id":"1"}';
200
+ service.request.method = 'POST';
201
+ service.request.headers['Content-Length'] = service.postData.length;
202
+
203
+ service.execute(this.processResponse);
204
+ },
205
+
206
+ configure: function(config) {
207
+ var added = 0;
208
+
209
+ if(typeof(config.servers) !== 'undefined') {
210
+ var len = config.servers.length;
211
+ while(len--) {
212
+ if(typeof config.servers[len].update_every === 'undefined')
213
+ config.servers[len].update_every = this.update_every;
214
+
215
+ if(config.servers[len].update_every < 5)
216
+ config.servers[len].update_every = 5;
217
+
218
+ this.serviceExecute(config.servers[len].name, config.servers[len].hostname, config.servers[len].update_every);
219
+ added++;
220
+ }
221
+ }
222
+
223
+ return added;
224
+ },
225
+
226
+ // module.update()
227
+ // this is called repeatidly to collect data, by calling
228
+ // netdata.serviceExecute()
229
+ update: function(service, callback) {
230
+ service.execute(function(serv, data) {
231
+ service.module.processResponse(serv, data);
232
+ callback();
233
+ });
234
+ },
235
};
236
237
module.exports = webbox;
node.d/snmp.node.js
+405
-405
@@ -5,60 +5,60 @@
5
// example configuration in /etc/netdata/snmp.conf
6
/*
7
{
8
- "enable_autodetect": false,
9
- "update_every": 5,
10
- "max_request_size": 50,
11
- "servers": [
12
- {
13
- "hostname": "10.11.12.8",
14
- "community": "public",
15
- "update_every": 10,
16
- "max_request_size": 50,
17
- "options": { "timeout": 10000 },
18
- "charts": {
19
- "snmp_switch.bandwidth_port1": {
20
- "title": "Switch Bandwidth for port 1",
21
- "units": "kilobits/s",
22
- "type": "area",
23
- "priority": 1,
24
- "dimensions": {
25
- "in": {
26
- "oid": ".1.3.6.1.2.1.2.2.1.10.1",
27
- "algorithm": "incremental",
28
- "multiplier": 8,
29
- "divisor": 1024
30
- },
31
- "out": {
32
- "oid": ".1.3.6.1.2.1.2.2.1.16.1",
33
- "algorithm": "incremental",
34
- "multiplier": -8,
35
- "divisor": 1024
36
- }
37
- }
38
- },
39
- "snmp_switch.bandwidth_port2": {
40
- "title": "Switch Bandwidth for port 2",
41
- "units": "kilobits/s",
42
- "type": "area",
43
- "priority": 1,
44
- "dimensions": {
45
- "in": {
46
- "oid": ".1.3.6.1.2.1.2.2.1.10.2",
47
- "algorithm": "incremental",
48
- "multiplier": 8,
49
- "divisor": 1024
50
- },
51
- "out": {
52
- "oid": ".1.3.6.1.2.1.2.2.1.16.2",
53
- "algorithm": "incremental",
54
- "multiplier": -8,
55
- "divisor": 1024
56
- }
57
- }
58
- }
59
- }
60
- }
61
- ]
8
+ "enable_autodetect": false,
9
+ "update_every": 5,
10
+ "max_request_size": 50,
11
+ "servers": [
12
+ {
13
+ "hostname": "10.11.12.8",
14
+ "community": "public",
15
+ "update_every": 10,
16
+ "max_request_size": 50,
17
+ "options": { "timeout": 10000 },
18
+ "charts": {
19
+ "snmp_switch.bandwidth_port1": {
20
+ "title": "Switch Bandwidth for port 1",
21
+ "units": "kilobits/s",
22
+ "type": "area",
23
+ "priority": 1,
24
+ "dimensions": {
25
+ "in": {
26
+ "oid": ".1.3.6.1.2.1.2.2.1.10.1",
27
+ "algorithm": "incremental",
28
+ "multiplier": 8,
29
+ "divisor": 1024
30
+ },
31
+ "out": {
32
+ "oid": ".1.3.6.1.2.1.2.2.1.16.1",
33
+ "algorithm": "incremental",
34
+ "multiplier": -8,
35
+ "divisor": 1024
36
+ }
37
+ }
38
+ },
39
+ "snmp_switch.bandwidth_port2": {
40
+ "title": "Switch Bandwidth for port 2",
41
+ "units": "kilobits/s",
42
+ "type": "area",
43
+ "priority": 1,
44
+ "dimensions": {
45
+ "in": {
46
+ "oid": ".1.3.6.1.2.1.2.2.1.10.2",
47
+ "algorithm": "incremental",
48
+ "multiplier": 8,
49
+ "divisor": 1024
50
+ },
51
+ "out": {
52
+ "oid": ".1.3.6.1.2.1.2.2.1.16.2",
53
+ "algorithm": "incremental",
54
+ "multiplier": -8,
55
+ "divisor": 1024
56
+ }
57
+ }
58
+ }
59
+ }
60
+ }
61
+ ]
62
}
63
*/
64
@@ -67,41 +67,41 @@
67
// so that 24 charts will be created.
68
/*
69
{
70
- "enable_autodetect": false,
71
- "update_every": 10,
72
- "max_request_size": 50,
73
- "servers": [
74
- {
75
- "hostname": "10.11.12.8",
76
- "community": "public",
77
- "update_every": 10,
78
- "max_request_size": 50,
79
- "options": { "timeout": 20000 },
80
- "charts": {
81
- "snmp_switch.bandwidth_port": {
82
- "title": "Switch Bandwidth for port ",
83
- "units": "kilobits/s",
84
- "type": "area",
85
- "priority": 1,
86
- "multiply_range": [ 1, 24 ],
87
- "dimensions": {
88
- "in": {
89
- "oid": ".1.3.6.1.2.1.2.2.1.10.",
90
- "algorithm": "incremental",
91
- "multiplier": 8,
92
- "divisor": 1024
93
- },
94
- "out": {
95
- "oid": ".1.3.6.1.2.1.2.2.1.16.",
96
- "algorithm": "incremental",
97
- "multiplier": -8,
98
- "divisor": 1024
99
- }
100
- }
101
- }
102
- }
103
- }
104
- ]
70
+ "enable_autodetect": false,
71
+ "update_every": 10,
72
+ "max_request_size": 50,
73
+ "servers": [
74
+ {
75
+ "hostname": "10.11.12.8",
76
+ "community": "public",
77
+ "update_every": 10,
78
+ "max_request_size": 50,
79
+ "options": { "timeout": 20000 },
80
+ "charts": {
81
+ "snmp_switch.bandwidth_port": {
82
+ "title": "Switch Bandwidth for port ",
83
+ "units": "kilobits/s",
84
+ "type": "area",
85
+ "priority": 1,
86
+ "multiply_range": [ 1, 24 ],
87
+ "dimensions": {
88
+ "in": {
89
+ "oid": ".1.3.6.1.2.1.2.2.1.10.",
90
+ "algorithm": "incremental",
91
+ "multiplier": 8,
92
+ "divisor": 1024
93
+ },
94
+ "out": {
95
+ "oid": ".1.3.6.1.2.1.2.2.1.16.",
96
+ "algorithm": "incremental",
97
+ "multiplier": -8,
98
+ "divisor": 1024
99
+ }
100
+ }
101
+ }
102
+ }
103
+ }
104
+ ]
105
}
106
*/
107
@@ -112,325 +112,325 @@ var netdata = require('netdata');
112
if(netdata.options.DEBUG === true) netdata.debug('loaded ' + __filename + ' plugin');
113
114
netdata.processors.snmp = {
115
- name: 'snmp',
116
-
117
- fixoid: function(oid) {
118
- if(typeof oid !== 'string')
119
- return oid;
120
-
121
- if(oid.charAt(0) === '.')
122
- return oid.substring(1, oid.length);
123
-
124
- return oid;
125
- },
126
-
127
- prepare: function(service) {
128
- if(typeof service.snmp_oids === 'undefined' || service.snmp_oids === null || service.snmp_oids.length === 0) {
129
- // this is the first time we see this service
130
-
131
- if(netdata.options.DEBUG === true)
132
- netdata.debug(service.module.name + ': ' + service.name + ': preparing ' + this.name + ' OIDs');
133
-
134
- // build an index of all OIDs
135
- service.snmp_oids_index = {};
136
- for(var c in service.request.charts) {
137
- // for each chart
138
-
139
- if(netdata.options.DEBUG === true)
140
- netdata.debug(service.module.name + ': ' + service.name + ': indexing ' + this.name + ' chart: ' + c);
141
-
142
- if(typeof service.request.charts[c].titleoid !== 'undefined') {
143
- service.snmp_oids_index[this.fixoid(service.request.charts[c].titleoid)] = {
144
- type: 'title',
145
- link: service.request.charts[c]
146
- };
147
- }
148
-
149
- for(var d in service.request.charts[c].dimensions) {
150
- // for each dimension in the chart
151
-
152
- var oid = this.fixoid(service.request.charts[c].dimensions[d].oid);
153
- var oidname = this.fixoid(service.request.charts[c].dimensions[d].oidname);
154
-
155
- if(netdata.options.DEBUG === true)
156
- netdata.debug(service.module.name + ': ' + service.name + ': indexing ' + this.name + ' chart: ' + c + ', dimension: ' + d + ', OID: ' + oid + ", OID name: " + oidname);
157
-
158
- // link it to the point we need to set the value to
159
- service.snmp_oids_index[oid] = {
160
- type: 'value',
161
- link: service.request.charts[c].dimensions[d]
162
- };
163
-
164
- if(typeof oidname !== 'undefined')
165
- service.snmp_oids_index[oidname] = {
166
- type: 'name',
167
- link: service.request.charts[c].dimensions[d]
168
- };
169
-
170
- // and set the value to null
171
- service.request.charts[c].dimensions[d].value = null;
172
- }
173
- }
174
-
175
- if(netdata.options.DEBUG === true)
176
- netdata.debug(service.module.name + ': ' + service.name + ': indexed ' + this.name + ' OIDs: ' + netdata.stringify(service.snmp_oids_index));
177
-
178
- // now create the array of OIDs needed by net-snmp
179
- service.snmp_oids = new Array();
180
- for(var o in service.snmp_oids_index)
181
- service.snmp_oids.push(o);
182
-
183
- if(netdata.options.DEBUG === true)
184
- netdata.debug(service.module.name + ': ' + service.name + ': final list of ' + this.name + ' OIDs: ' + netdata.stringify(service.snmp_oids));
185
-
186
- service.snmp_oids_cleaned = 0;
187
- }
188
- else if(service.snmp_oids_cleaned === 0) {
189
- service.snmp_oids_cleaned = 1;
190
-
191
- // the second time, keep only values
192
- service.snmp_oids = new Array();
193
- for(var o in service.snmp_oids_index)
194
- if(service.snmp_oids_index[o].type === 'value')
195
- service.snmp_oids.push(o);
196
- }
197
- },
198
-
199
- getdata: function(service, index, ok, failed, callback) {
200
- var that = this;
201
-
202
- if(index >= service.snmp_oids.length) {
203
- callback((ok > 0)?{ ok: ok, failed: failed }:null);
204
- return;
205
- }
206
-
207
- var slice;
208
- if(service.snmp_oids.length <= service.request.max_request_size) {
209
- slice = service.snmp_oids;
210
- index = service.snmp_oids.length;
211
- }
212
- else if(service.snmp_oids.length - index <= service.request.max_request_size) {
213
- slice = service.snmp_oids.slice(index, service.snmp_oids.length);
214
- index = service.snmp_oids.length;
215
- }
216
- else {
217
- slice = service.snmp_oids.slice(index, index + service.request.max_request_size);
218
- index += service.request.max_request_size;
219
- }
220
-
221
- if(netdata.options.DEBUG === true)
222
- netdata.debug(service.module.name + ': ' + service.name + ': making ' + slice.length + ' entries request, max is: ' + service.request.max_request_size);
223
-
224
- service.snmp_session.get(slice, function(error, varbinds) {
225
- if(error) {
226
- service.error('Received error = ' + netdata.stringify(error) + ' varbinds = ' + netdata.stringify(varbinds));
227
-
228
- // make all values null
229
- var len = slice.length;
230
- while(len--)
231
- service.snmp_oids_index[slice[len]].value = null;
232
- }
233
- else {
234
- if(netdata.options.DEBUG === true)
235
- netdata.debug(service.module.name + ': ' + service.name + ': got valid ' + service.module.name + ' response: ' + netdata.stringify(varbinds));
236
-
237
- for(var i = 0; i < varbinds.length; i++) {
238
- var value = null;
239
-
240
- if(net_snmp.isVarbindError(varbinds[i])) {
241
- if(netdata.options.DEBUG === true)
242
- netdata.debug(service.module.name + ': ' + service.name + ': failed ' + service.module.name + ' get for OIDs ' + varbinds[i].oid);
243
-
244
- service.error('OID ' + varbinds[i].oid + ' gave error: ' + snmp.varbindError(varbinds[i]));
245
- value = null;
246
- failed++;
247
- }
248
- else {
249
- if(netdata.options.DEBUG === true)
250
- netdata.debug(service.module.name + ': ' + service.name + ': found ' + service.module.name + ' value of OIDs ' + varbinds[i].oid + " = " + varbinds[i].value);
251
-
252
- value = varbinds[i].value;
253
- ok++;
254
- }
255
-
256
- if(value !== null) {
257
- switch(service.snmp_oids_index[varbinds[i].oid].type) {
258
- case 'title': service.snmp_oids_index[varbinds[i].oid].link.title += ' ' + value; break;
259
- case 'name' : service.snmp_oids_index[varbinds[i].oid].link.name = value; break;
260
- case 'value': service.snmp_oids_index[varbinds[i].oid].link.value = value; break;
261
- }
262
- }
263
- }
264
-
265
- if(netdata.options.DEBUG === true)
266
- netdata.debug(service.module.name + ': ' + service.name + ': finished ' + service.module.name + ' with ' + ok + ' successful and ' + failed + ' failed values');
267
- }
268
- that.getdata(service, index, ok, failed, callback);
269
- });
270
- },
271
-
272
- process: function(service, callback) {
273
- this.prepare(service);
274
-
275
- if(service.snmp_oids.length === 0) {
276
- // no OIDs found for this service
277
-
278
- if(netdata.options.DEBUG === true)
279
- service.error('no OIDs to process.');
280
-
281
- callback(null);
282
- return;
283
- }
284
-
285
- if(typeof service.snmp_session === 'undefined' || service.snmp_session === null) {
286
- // no SNMP session has been created for this service
287
- // the SNMP session is just the initialization of NET-SNMP
288
-
289
- if(netdata.options.DEBUG === true)
290
- netdata.debug(service.module.name + ': ' + service.name + ': opening ' + this.name + ' session on ' + service.request.hostname + ' community ' + service.request.community + ' options ' + netdata.stringify(service.request.options));
291
-
292
- // create the SNMP session
293
- service.snmp_session = net_snmp.createSession (service.request.hostname, service.request.community, service.request.options);
294
-
295
- if(netdata.options.DEBUG === true)
296
- netdata.debug(service.module.name + ': ' + service.name + ': got ' + this.name + ' session: ' + netdata.stringify(service.snmp_session));
297
-
298
- // if we later need traps, this is how to do it:
299
- //service.snmp_session.trap(net_snmp.TrapType.LinkDown, function(error) {
300
- // if(error) console.error('trap error: ' + netdata.stringify(error));
301
- //});
302
- }
303
-
304
- // do it, get the SNMP values for the sessions we need
305
- this.getdata(service, 0, 0, 0, callback);
306
- }
115
+ name: 'snmp',
116
+
117
+ fixoid: function(oid) {
118
+ if(typeof oid !== 'string')
119
+ return oid;
120
+
121
+ if(oid.charAt(0) === '.')
122
+ return oid.substring(1, oid.length);
123
+
124
+ return oid;
125
+ },
126
+
127
+ prepare: function(service) {
128
+ if(typeof service.snmp_oids === 'undefined' || service.snmp_oids === null || service.snmp_oids.length === 0) {
129
+ // this is the first time we see this service
130
+
131
+ if(netdata.options.DEBUG === true)
132
+ netdata.debug(service.module.name + ': ' + service.name + ': preparing ' + this.name + ' OIDs');
133
+
134
+ // build an index of all OIDs
135
+ service.snmp_oids_index = {};
136
+ for(var c in service.request.charts) {
137
+ // for each chart
138
+
139
+ if(netdata.options.DEBUG === true)
140
+ netdata.debug(service.module.name + ': ' + service.name + ': indexing ' + this.name + ' chart: ' + c);
141
+
142
+ if(typeof service.request.charts[c].titleoid !== 'undefined') {
143
+ service.snmp_oids_index[this.fixoid(service.request.charts[c].titleoid)] = {
144
+ type: 'title',
145
+ link: service.request.charts[c]
146
+ };
147
+ }
148
+
149
+ for(var d in service.request.charts[c].dimensions) {
150
+ // for each dimension in the chart
151
+
152
+ var oid = this.fixoid(service.request.charts[c].dimensions[d].oid);
153
+ var oidname = this.fixoid(service.request.charts[c].dimensions[d].oidname);
154
+
155
+ if(netdata.options.DEBUG === true)
156
+ netdata.debug(service.module.name + ': ' + service.name + ': indexing ' + this.name + ' chart: ' + c + ', dimension: ' + d + ', OID: ' + oid + ", OID name: " + oidname);
157
+
158
+ // link it to the point we need to set the value to
159
+ service.snmp_oids_index[oid] = {
160
+ type: 'value',
161
+ link: service.request.charts[c].dimensions[d]
162
+ };
163
+
164
+ if(typeof oidname !== 'undefined')
165
+ service.snmp_oids_index[oidname] = {
166
+ type: 'name',
167
+ link: service.request.charts[c].dimensions[d]
168
+ };
169
+
170
+ // and set the value to null
171
+ service.request.charts[c].dimensions[d].value = null;
172
+ }
173
+ }
174
+
175
+ if(netdata.options.DEBUG === true)
176
+ netdata.debug(service.module.name + ': ' + service.name + ': indexed ' + this.name + ' OIDs: ' + netdata.stringify(service.snmp_oids_index));
177
+
178
+ // now create the array of OIDs needed by net-snmp
179
+ service.snmp_oids = new Array();
180
+ for(var o in service.snmp_oids_index)
181
+ service.snmp_oids.push(o);
182
+
183
+ if(netdata.options.DEBUG === true)
184
+ netdata.debug(service.module.name + ': ' + service.name + ': final list of ' + this.name + ' OIDs: ' + netdata.stringify(service.snmp_oids));
185
+
186
+ service.snmp_oids_cleaned = 0;
187
+ }
188
+ else if(service.snmp_oids_cleaned === 0) {
189
+ service.snmp_oids_cleaned = 1;
190
+
191
+ // the second time, keep only values
192
+ service.snmp_oids = new Array();
193
+ for(var o in service.snmp_oids_index)
194
+ if(service.snmp_oids_index[o].type === 'value')
195
+ service.snmp_oids.push(o);
196
+ }
197
+ },
198
+
199
+ getdata: function(service, index, ok, failed, callback) {
200
+ var that = this;
201
+
202
+ if(index >= service.snmp_oids.length) {
203
+ callback((ok > 0)?{ ok: ok, failed: failed }:null);
204
+ return;
205
+ }
206
+
207
+ var slice;
208
+ if(service.snmp_oids.length <= service.request.max_request_size) {
209
+ slice = service.snmp_oids;
210
+ index = service.snmp_oids.length;
211
+ }
212
+ else if(service.snmp_oids.length - index <= service.request.max_request_size) {
213
+ slice = service.snmp_oids.slice(index, service.snmp_oids.length);
214
+ index = service.snmp_oids.length;
215
+ }
216
+ else {
217
+ slice = service.snmp_oids.slice(index, index + service.request.max_request_size);
218
+ index += service.request.max_request_size;
219
+ }
220
+
221
+ if(netdata.options.DEBUG === true)
222
+ netdata.debug(service.module.name + ': ' + service.name + ': making ' + slice.length + ' entries request, max is: ' + service.request.max_request_size);
223
+
224
+ service.snmp_session.get(slice, function(error, varbinds) {
225
+ if(error) {
226
+ service.error('Received error = ' + netdata.stringify(error) + ' varbinds = ' + netdata.stringify(varbinds));
227
+
228
+ // make all values null
229
+ var len = slice.length;
230
+ while(len--)
231
+ service.snmp_oids_index[slice[len]].value = null;
232
+ }
233
+ else {
234
+ if(netdata.options.DEBUG === true)
235
+ netdata.debug(service.module.name + ': ' + service.name + ': got valid ' + service.module.name + ' response: ' + netdata.stringify(varbinds));
236
+
237
+ for(var i = 0; i < varbinds.length; i++) {
238
+ var value = null;
239
+
240
+ if(net_snmp.isVarbindError(varbinds[i])) {
241
+ if(netdata.options.DEBUG === true)
242
+ netdata.debug(service.module.name + ': ' + service.name + ': failed ' + service.module.name + ' get for OIDs ' + varbinds[i].oid);
243
+
244
+ service.error('OID ' + varbinds[i].oid + ' gave error: ' + snmp.varbindError(varbinds[i]));
245
+ value = null;
246
+ failed++;
247
+ }
248
+ else {
249
+ if(netdata.options.DEBUG === true)
250
+ netdata.debug(service.module.name + ': ' + service.name + ': found ' + service.module.name + ' value of OIDs ' + varbinds[i].oid + " = " + varbinds[i].value);
251
+
252
+ value = varbinds[i].value;
253
+ ok++;
254
+ }
255
+
256
+ if(value !== null) {
257
+ switch(service.snmp_oids_index[varbinds[i].oid].type) {
258
+ case 'title': service.snmp_oids_index[varbinds[i].oid].link.title += ' ' + value; break;
259
+ case 'name' : service.snmp_oids_index[varbinds[i].oid].link.name = value; break;
260
+ case 'value': service.snmp_oids_index[varbinds[i].oid].link.value = value; break;
261
+ }
262
+ }
263
+ }
264
+
265
+ if(netdata.options.DEBUG === true)
266
+ netdata.debug(service.module.name + ': ' + service.name + ': finished ' + service.module.name + ' with ' + ok + ' successful and ' + failed + ' failed values');
267
+ }
268
+ that.getdata(service, index, ok, failed, callback);
269
+ });
270
+ },
271
+
272
+ process: function(service, callback) {
273
+ this.prepare(service);
274
+
275
+ if(service.snmp_oids.length === 0) {
276
+ // no OIDs found for this service
277
+
278
+ if(netdata.options.DEBUG === true)
279
+ service.error('no OIDs to process.');
280
+
281
+ callback(null);
282
+ return;
283
+ }
284
+
285
+ if(typeof service.snmp_session === 'undefined' || service.snmp_session === null) {
286
+ // no SNMP session has been created for this service
287
+ // the SNMP session is just the initialization of NET-SNMP
288
+
289
+ if(netdata.options.DEBUG === true)
290
+ netdata.debug(service.module.name + ': ' + service.name + ': opening ' + this.name + ' session on ' + service.request.hostname + ' community ' + service.request.community + ' options ' + netdata.stringify(service.request.options));
291
+
292
+ // create the SNMP session
293
+ service.snmp_session = net_snmp.createSession (service.request.hostname, service.request.community, service.request.options);
294
+
295
+ if(netdata.options.DEBUG === true)
296
+ netdata.debug(service.module.name + ': ' + service.name + ': got ' + this.name + ' session: ' + netdata.stringify(service.snmp_session));
297
+
298
+ // if we later need traps, this is how to do it:
299
+ //service.snmp_session.trap(net_snmp.TrapType.LinkDown, function(error) {
300
+ // if(error) console.error('trap error: ' + netdata.stringify(error));
301
+ //});
302
+ }
303
+
304
+ // do it, get the SNMP values for the sessions we need
305
+ this.getdata(service, 0, 0, 0, callback);
306
+ }
307
};
308
309
var snmp = {
310
- name: __filename,
311
- enable_autodetect: true,
312
- update_every: 1,
313
- base_priority: 50000,
314
-
315
- charts: {},
316
-
317
- processResponse: function(service, data) {
318
- if(data !== null) {
319
- if(service.added !== true)
320
- service.commit();
321
-
322
- for(var c in service.request.charts) {
323
- var chart = snmp.charts[c];
324
-
325
- if(typeof chart === 'undefined') {
326
- chart = service.chart(c, service.request.charts[c]);
327
- snmp.charts[c] = chart;
328
- }
329
-
330
- service.begin(chart);
331
-
332
- for( var d in service.request.charts[c].dimensions )
333
- if(service.request.charts[c].dimensions[d].value !== null)
334
- service.set(d, service.request.charts[c].dimensions[d].value);
335
-
336
- service.end();
337
- }
338
- }
339
- },
340
-
341
- // module.serviceExecute()
342
- // this function is called only from this module
343
- // its purpose is to prepare the request and call
344
- // netdata.serviceExecute()
345
- serviceExecute: function(conf) {
346
- if(netdata.options.DEBUG === true)
347
- netdata.debug(this.name + ': snmp hostname: ' + conf.hostname + ', update_every: ' + conf.update_every);
348
-
349
- var service = netdata.service({
350
- name: conf.hostname,
351
- request: conf,
352
- update_every: conf.update_every,
353
- module: this,
354
- processor: netdata.processors.snmp
355
- });
356
-
357
- // multiply the charts, if required
358
- for(var c in service.request.charts) {
359
- if(netdata.options.DEBUG === true)
360
- netdata.debug(this.name + ': snmp hostname: ' + conf.hostname + ', examining chart: ' + c);
361
-
362
- if(typeof service.request.charts[c].update_every === 'undefined')
363
- service.request.charts[c].update_every = service.update_every;
364
-
365
- if(typeof service.request.charts[c].multiply_range !== 'undefined') {
366
- var from = service.request.charts[c].multiply_range[0];
367
- var to = service.request.charts[c].multiply_range[1];
368
- var prio = service.request.charts[c].priority || 1;
369
-
370
- if(prio < snmp.base_priority) prio += snmp.base_priority;
371
-
372
- while(from <= to) {
373
- var id = c + from.toString();
374
- var chart = extend(true, {}, service.request.charts[c]);
375
- chart.title += from.toString();
376
-
377
- if(typeof chart.titleoid !== 'undefined')
378
- chart.titleoid += from.toString();
379
-
380
- chart.priority = prio++;
381
- for(var d in chart.dimensions) {
382
- chart.dimensions[d].oid += from.toString();
383
-
384
- if(typeof chart.dimensions[d].oidname !== 'undefined')
385
- chart.dimensions[d].oidname += from.toString();
386
- }
387
- service.request.charts[id] = chart;
388
- from++;
389
- }
390
-
391
- delete service.request.charts[c];
392
- }
393
- else {
394
- if(service.request.charts[c].priority < snmp.base_priority)
395
- service.request.charts[c].priority += snmp.base_priority;
396
- }
397
- }
398
-
399
- service.execute(this.processResponse);
400
- },
401
-
402
- configure: function(config) {
403
- var added = 0;
404
-
405
- if(typeof config.max_request_size === 'undefined')
406
- config.max_request_size = 50;
407
-
408
- if(typeof(config.servers) !== 'undefined') {
409
- var len = config.servers.length;
410
- while(len--) {
411
- if(typeof config.servers[len].update_every === 'undefined')
412
- config.servers[len].update_every = this.update_every;
413
-
414
- if(typeof config.servers[len].max_request_size === 'undefined')
415
- config.servers[len].max_request_size = config.max_request_size;
416
-
417
- this.serviceExecute(config.servers[len]);
418
- added++;
419
- }
420
- }
421
-
422
- return added;
423
- },
424
-
425
- // module.update()
426
- // this is called repeatidly to collect data, by calling
427
- // service.execute()
428
- update: function(service, callback) {
429
- service.execute(function(serv, data) {
430
- service.module.processResponse(serv, data);
431
- callback();
432
- });
433
- },
310
+ name: __filename,
311
+ enable_autodetect: true,
312
+ update_every: 1,
313
+ base_priority: 50000,
314
+
315
+ charts: {},
316
+
317
+ processResponse: function(service, data) {
318
+ if(data !== null) {
319
+ if(service.added !== true)
320
+ service.commit();
321
+
322
+ for(var c in service.request.charts) {
323
+ var chart = snmp.charts[c];
324
+
325
+ if(typeof chart === 'undefined') {
326
+ chart = service.chart(c, service.request.charts[c]);
327
+ snmp.charts[c] = chart;
328
+ }
329
+
330
+ service.begin(chart);
331
+
332
+ for( var d in service.request.charts[c].dimensions )
333
+ if(service.request.charts[c].dimensions[d].value !== null)
334
+ service.set(d, service.request.charts[c].dimensions[d].value);
335
+
336
+ service.end();
337
+ }
338
+ }
339
+ },
340
+
341
+ // module.serviceExecute()
342
+ // this function is called only from this module
343
+ // its purpose is to prepare the request and call
344
+ // netdata.serviceExecute()
345
+ serviceExecute: function(conf) {
346
+ if(netdata.options.DEBUG === true)
347
+ netdata.debug(this.name + ': snmp hostname: ' + conf.hostname + ', update_every: ' + conf.update_every);
348
+
349
+ var service = netdata.service({
350
+ name: conf.hostname,
351
+ request: conf,
352
+ update_every: conf.update_every,
353
+ module: this,
354
+ processor: netdata.processors.snmp
355
+ });
356
+
357
+ // multiply the charts, if required
358
+ for(var c in service.request.charts) {
359
+ if(netdata.options.DEBUG === true)
360
+ netdata.debug(this.name + ': snmp hostname: ' + conf.hostname + ', examining chart: ' + c);
361
+
362
+ if(typeof service.request.charts[c].update_every === 'undefined')
363
+ service.request.charts[c].update_every = service.update_every;
364
+
365
+ if(typeof service.request.charts[c].multiply_range !== 'undefined') {
366
+ var from = service.request.charts[c].multiply_range[0];
367
+ var to = service.request.charts[c].multiply_range[1];
368
+ var prio = service.request.charts[c].priority || 1;
369
+
370
+ if(prio < snmp.base_priority) prio += snmp.base_priority;
371
+
372
+ while(from <= to) {
373
+ var id = c + from.toString();
374
+ var chart = extend(true, {}, service.request.charts[c]);
375
+ chart.title += from.toString();
376
+
377
+ if(typeof chart.titleoid !== 'undefined')
378
+ chart.titleoid += from.toString();
379
+
380
+ chart.priority = prio++;
381
+ for(var d in chart.dimensions) {
382
+ chart.dimensions[d].oid += from.toString();
383
+
384
+ if(typeof chart.dimensions[d].oidname !== 'undefined')
385
+ chart.dimensions[d].oidname += from.toString();
386
+ }
387
+ service.request.charts[id] = chart;
388
+ from++;
389
+ }
390
+
391
+ delete service.request.charts[c];
392
+ }
393
+ else {
394
+ if(service.request.charts[c].priority < snmp.base_priority)
395
+ service.request.charts[c].priority += snmp.base_priority;
396
+ }
397
+ }
398
+
399
+ service.execute(this.processResponse);
400
+ },
401
+
402
+ configure: function(config) {
403
+ var added = 0;
404
+
405
+ if(typeof config.max_request_size === 'undefined')
406
+ config.max_request_size = 50;
407
+
408
+ if(typeof(config.servers) !== 'undefined') {
409
+ var len = config.servers.length;
410
+ while(len--) {
411
+ if(typeof config.servers[len].update_every === 'undefined')
412
+ config.servers[len].update_every = this.update_every;
413
+
414
+ if(typeof config.servers[len].max_request_size === 'undefined')
415
+ config.servers[len].max_request_size = config.max_request_size;
416
+
417
+ this.serviceExecute(config.servers[len]);
418
+ added++;
419
+ }
420
+ }
421
+
422
+ return added;
423
+ },
424
+
425
+ // module.update()
426
+ // this is called repeatidly to collect data, by calling
427
+ // service.execute()
428
+ update: function(service, callback) {
429
+ service.execute(function(serv, data) {
430
+ service.module.processResponse(serv, data);
431
+ callback();
432
+ });
433
+ },
434
};
435
436
module.exports = snmp;
plugins.d/cgroup-name.sh
+45
-45
@@ -9,66 +9,66 @@ CGROUP="${1}"
9
NAME=
10
11
if [ -z "${CGROUP}" ]
12
- then
13
- echo >&2 "${0}: called without a cgroup name. Nothing to do."
14
- exit 1
12
+ then
13
+ echo >&2 "${0}: called without a cgroup name. Nothing to do."
14
+ exit 1
15
fi
16
17
if [ -f "${CONFIG}" ]
18
- then
19
- NAME="$(cat "${CONFIG}" | grep "^${CGROUP} " | sed "s/[[:space:]]\+/ /g" | cut -d ' ' -f 2)"
20
- if [ -z "${NAME}" ]
21
- then
22
- echo >&2 "${0}: cannot find cgroup '${CGROUP}' in '${CONFIG}'."
23
- fi
18
+ then
19
+ NAME="$(cat "${CONFIG}" | grep "^${CGROUP} " | sed "s/[[:space:]]\+/ /g" | cut -d ' ' -f 2)"
20
+ if [ -z "${NAME}" ]
21
+ then
22
+ echo >&2 "${0}: cannot find cgroup '${CGROUP}' in '${CONFIG}'."
23
+ fi
24
#else
25
-# echo >&2 "${0}: configuration file '${CONFIG}' is not available."
25
+# echo >&2 "${0}: configuration file '${CONFIG}' is not available."
26
fi
27
28
function get_name_classic {
29
- DOCKERID=$1
30
- echo >&2 "Running command: docker ps --filter=id=\"${DOCKERID}\" --format=\"{{.Names}}\""
31
- NAME="$( docker ps --filter=id="${DOCKERID}" --format="{{.Names}}" )"
29
+ DOCKERID=$1
30
+ echo >&2 "Running command: docker ps --filter=id=\"${DOCKERID}\" --format=\"{{.Names}}\""
31
+ NAME="$( docker ps --filter=id="${DOCKERID}" --format="{{.Names}}" )"
32
}
33
34
function get_name_api {
35
- DOCKERID=$1
36
- if [ ! -S "/var/run/docker.sock" ]
37
- then
38
- echo >&2 "Can't find /var/run/docker.sock"
39
- return
40
- fi
41
- echo >&2 "Running API command: /containers/${DOCKERID}/json"
42
- JSON=$(echo -e "GET /containers/${DOCKERID}/json HTTP/1.0\r\n" | nc -U /var/run/docker.sock | egrep '^{.*')
43
- NAME=$(echo $JSON | jq -r .Name,.Config.Hostname | grep -v null | head -n1 | sed 's|^/||')
35
+ DOCKERID=$1
36
+ if [ ! -S "/var/run/docker.sock" ]
37
+ then
38
+ echo >&2 "Can't find /var/run/docker.sock"
39
+ return
40
+ fi
41
+ echo >&2 "Running API command: /containers/${DOCKERID}/json"
42
+ JSON=$(echo -e "GET /containers/${DOCKERID}/json HTTP/1.0\r\n" | nc -U /var/run/docker.sock | egrep '^{.*')
43
+ NAME=$(echo $JSON | jq -r .Name,.Config.Hostname | grep -v null | head -n1 | sed 's|^/||')
44
}
45
46
if [ -z "${NAME}" ]
47
- then
48
- if [[ "${CGROUP}" =~ ^.*docker[-/\.][a-fA-F0-9]+[-\.]?.*$ ]]
49
- then
50
- DOCKERID="$( echo "${CGROUP}" | sed "s|^.*docker[-/]\([a-fA-F0-9]\+\)[-\.]\?.*$|\1|" )"
47
+ then
48
+ if [[ "${CGROUP}" =~ ^.*docker[-/\.][a-fA-F0-9]+[-\.]?.*$ ]]
49
+ then
50
+ DOCKERID="$( echo "${CGROUP}" | sed "s|^.*docker[-/]\([a-fA-F0-9]\+\)[-\.]\?.*$|\1|" )"
51
52
- if [ ! -z "${DOCKERID}" -a \( ${#DOCKERID} -eq 64 -o ${#DOCKERID} -eq 12 \) ]
53
- then
54
- if hash docker 2>/dev/null
55
- then
56
- get_name_classic $DOCKERID
57
- else
58
- get_name_api $DOCKERID
59
- fi
60
- if [ -z "${NAME}" ]
61
- then
62
- echo >&2 "Cannot find the name of docker container '${DOCKERID}'"
63
- NAME="${DOCKERID:0:12}"
64
- else
65
- echo >&2 "Docker container '${DOCKERID}' is named '${NAME}'"
66
- fi
67
- fi
68
- fi
52
+ if [ ! -z "${DOCKERID}" -a \( ${#DOCKERID} -eq 64 -o ${#DOCKERID} -eq 12 \) ]
53
+ then
54
+ if hash docker 2>/dev/null
55
+ then
56
+ get_name_classic $DOCKERID
57
+ else
58
+ get_name_api $DOCKERID
59
+ fi
60
+ if [ -z "${NAME}" ]
61
+ then
62
+ echo >&2 "Cannot find the name of docker container '${DOCKERID}'"
63
+ NAME="${DOCKERID:0:12}"
64
+ else
65
+ echo >&2 "Docker container '${DOCKERID}' is named '${NAME}'"
66
+ fi
67
+ fi
68
+ fi
69
70
- [ -z "${NAME}" ] && NAME="${CGROUP}"
71
- [ ${#NAME} -gt 50 ] && NAME="${NAME:0:50}"
70
+ [ -z "${NAME}" ] && NAME="${CGROUP}"
71
+ [ ${#NAME} -gt 50 ] && NAME="${NAME:0:50}"
72
fi
73
74
echo >&2 "${0}: cgroup '${CGROUP}' is called '${NAME}'"
plugins.d/charts.d.dryrun-helper.sh
+23
-23
@@ -14,7 +14,7 @@ tmp1="`mktemp`"
14
tmp2="`mktemp`"
15
16
myset() {
17
- set | grep -v "^_=" | grep -v "^PIPESTATUS=" | grep -v "^BASH_LINENO="
17
+ set | grep -v "^_=" | grep -v "^PIPESTATUS=" | grep -v "^BASH_LINENO="
18
}
19
20
# save 2 'set'
@@ -25,9 +25,9 @@ myset >"$tmp2"
25
diff "$tmp1" "$tmp2" >/dev/null 2>&1
26
if [ $? -ne 0 ]
27
then
28
- # they differ, we cannot do the check
29
- echo >&2 "$me: cannot check with diff."
30
- can_diff=0
28
+ # they differ, we cannot do the check
29
+ echo >&2 "$me: cannot check with diff."
30
+ can_diff=0
31
fi
32
33
# do it again, now including the script
@@ -36,21 +36,21 @@ myset >"$tmp1"
36
# include the plugin and its config
37
if [ -f "$conf" ]
38
then
39
- . "$conf"
40
- if [ $? -ne 0 ]
41
- then
42
- echo >&2 "$me: cannot load config file $conf"
43
- rm "$tmp1" "$tmp2"
44
- exit 1
45
- fi
39
+ . "$conf"
40
+ if [ $? -ne 0 ]
41
+ then
42
+ echo >&2 "$me: cannot load config file $conf"
43
+ rm "$tmp1" "$tmp2"
44
+ exit 1
45
+ fi
46
fi
47
48
. "$chart"
49
if [ $? -ne 0 ]
50
then
51
- echo >&2 "$me: cannot load chart file $chart"
52
- rm "$tmp1" "$tmp2"
53
- exit 1
51
+ echo >&2 "$me: cannot load chart file $chart"
52
+ rm "$tmp1" "$tmp2"
53
+ exit 1
54
fi
55
56
# remove all variables starting with the plugin name
@@ -58,15 +58,15 @@ myset | grep -v "^$name" >"$tmp2"
58
59
if [ $can_diff -eq 1 ]
60
then
61
- # check if they are different
62
- # make sure they don't differ
63
- diff "$tmp1" "$tmp2" >&2
64
- if [ $? -ne 0 ]
65
- then
66
- # they differ
67
- rm "$tmp1" "$tmp2"
68
- exit 1
69
- fi
61
+ # check if they are different
62
+ # make sure they don't differ
63
+ diff "$tmp1" "$tmp2" >&2
64
+ if [ $? -ne 0 ]
65
+ then
66
+ # they differ
67
+ rm "$tmp1" "$tmp2"
68
+ exit 1
69
+ fi
70
fi
71
72
rm "$tmp1" "$tmp2"
plugins.d/charts.d.plugin
+414
-414
@@ -14,24 +14,24 @@ echo >&2 "$PROGRAM_NAME: started from '$PROGRAM_FILE' with options: $*"
14
15
if [ $(( ${BASH_VERSINFO[0]} )) -lt 4 ]
16
then
17
- echo >&2
18
- echo >&2 "$PROGRAM_NAME: ERROR"
19
- echo >&2 "BASH version 4 or later is required."
20
- echo >&2 "You are running version: ${BASH_VERSION}"
21
- echo >&2 "Please upgrade."
22
- echo >&2
23
- exit 1
17
+ echo >&2
18
+ echo >&2 "$PROGRAM_NAME: ERROR"
19
+ echo >&2 "BASH version 4 or later is required."
20
+ echo >&2 "You are running version: ${BASH_VERSION}"
21
+ echo >&2 "Please upgrade."
22
+ echo >&2
23
+ exit 1
24
fi
25
26
# check a few commands
27
require_cmd() {
28
- which "$1" >/dev/null
29
- if [ $? -ne 0 ]
30
- then
31
- echo >&2 "$PROGRAM_NAME: ERROR: Command '$1' is not found in the system path."
32
- return 1
33
- fi
34
- return 0
28
+ which "$1" >/dev/null
29
+ if [ $? -ne 0 ]
30
+ then
31
+ echo >&2 "$PROGRAM_NAME: ERROR: Command '$1' is not found in the system path."
32
+ return 1
33
+ fi
34
+ return 0
35
}
36
37
require_cmd date || exit 1
@@ -61,7 +61,7 @@ chartsd="$pluginsd/../charts.d"
61
myconfig="$confd/$PROGRAM_NAME.conf"
62
63
minimum_update_frequency="${NETDATA_UPDATE_EVERY-1}"
64
-update_every=${minimum_update_frequency} # this will be overwritten by the command line
64
+update_every=${minimum_update_frequency} # this will be overwritten by the command line
65
66
# work around for non BASH shells
67
charts_create="_create"
@@ -106,50 +106,50 @@ check=0
106
chart_only=
107
while [ ! -z "$1" ]
108
do
109
- if [ "$1" = "check" ]
110
- then
111
- check=1
112
- shift
113
- continue
114
- fi
115
-
116
- if [ "$1" = "debug" -o "$1" = "all" ]
117
- then
118
- debug=1
119
- shift
120
- continue
121
- fi
122
-
123
- if [ -f "$chartsd/$1.chart.sh" ]
124
- then
125
- debug=1
126
- chart_only="$( echo $1.chart.sh | sed "s/\.chart\.sh$//g" )"
127
- shift
128
- continue
129
- fi
130
-
131
- if [ -f "$chartsd/$1" ]
132
- then
133
- debug=1
134
- chart_only="$( echo $1 | sed "s/\.chart\.sh$//g" )"
135
- shift
136
- continue
137
- fi
138
-
139
- # number check
140
- n="$1"
141
- x=$(( n ))
142
- if [ "$x" = "$n" ]
143
- then
144
- shift
145
- update_every=$x
146
- [ $update_every -lt $minimum_update_frequency ] && update_every=$minimum_update_frequency
147
- continue
148
- fi
149
-
150
- echo >&2 "Cannot understand parameter $1. Aborting."
151
- echo "DISABLE"
152
- exit 1
109
+ if [ "$1" = "check" ]
110
+ then
111
+ check=1
112
+ shift
113
+ continue
114
+ fi
115
+
116
+ if [ "$1" = "debug" -o "$1" = "all" ]
117
+ then
118
+ debug=1
119
+ shift
120
+ continue
121
+ fi
122
+
123
+ if [ -f "$chartsd/$1.chart.sh" ]
124
+ then
125
+ debug=1
126
+ chart_only="$( echo $1.chart.sh | sed "s/\.chart\.sh$//g" )"
127
+ shift
128
+ continue
129
+ fi
130
+
131
+ if [ -f "$chartsd/$1" ]
132
+ then
133
+ debug=1
134
+ chart_only="$( echo $1 | sed "s/\.chart\.sh$//g" )"
135
+ shift
136
+ continue
137
+ fi
138
+
139
+ # number check
140
+ n="$1"
141
+ x=$(( n ))
142
+ if [ "$x" = "$n" ]
143
+ then
144
+ shift
145
+ update_every=$x
146
+ [ $update_every -lt $minimum_update_frequency ] && update_every=$minimum_update_frequency
147
+ continue
148
+ fi
149
+
150
+ echo >&2 "Cannot understand parameter $1. Aborting."
151
+ echo "DISABLE"
152
+ exit 1
153
done
154
155
@@ -157,26 +157,26 @@ done
157
# load my configuration
158
159
if [ -f "$myconfig" ]
160
- then
161
- . "$myconfig"
162
- if [ $? -ne 0 ]
163
- then
164
- echo >&2 "$PROGRAM_NAME: cannot load $myconfig"
165
- echo "DISABLE"
166
- exit 1
167
- fi
168
- time_divisor=$((time_divisor))
169
- [ $time_divisor -lt 10 ] && time_divisor=10
170
- [ $time_divisor -gt 100 ] && time_divisor=100
160
+ then
161
+ . "$myconfig"
162
+ if [ $? -ne 0 ]
163
+ then
164
+ echo >&2 "$PROGRAM_NAME: cannot load $myconfig"
165
+ echo "DISABLE"
166
+ exit 1
167
+ fi
168
+ time_divisor=$((time_divisor))
169
+ [ $time_divisor -lt 10 ] && time_divisor=10
170
+ [ $time_divisor -gt 100 ] && time_divisor=100
171
else
172
- echo >&2 "$PROGRAM_NAME: configuration file '$myconfig' not found. Using defaults."
172
+ echo >&2 "$PROGRAM_NAME: configuration file '$myconfig' not found. Using defaults."
173
fi
174
175
if [ "$pause_method" = "suspend" ]
176
then
177
- # enable bash job control
178
- # this is required for suspend to work
179
- set -m
177
+ # enable bash job control
178
+ # this is required for suspend to work
179
+ set -m
180
fi
181
182
# we check for the timeout command, after we load our
@@ -185,22 +185,22 @@ fi
185
# can emulate the timeout command we need:
186
# > timeout SECONDS command ...
187
if [ $check_for_timeout -eq 1 ]
188
- then
189
- require_cmd timeout || exit 1
188
+ then
189
+ require_cmd timeout || exit 1
190
fi
191
192
# -----------------------------------------------------------------------------
193
# internal checks
194
195
# netdata passes the requested update frequency as the first argument
196
-update_every=$(( update_every + 1 - 1)) # makes sure it is a number
196
+update_every=$(( update_every + 1 - 1)) # makes sure it is a number
197
test $update_every -eq 0 && update_every=1 # if it is zero, make it 1
198
199
# check the charts.d directory
200
if [ ! -d "$chartsd" ]
201
- then
202
- echo >&2 "$PROGRAM_NAME: cannot find charts directory '$chartsd'"
203
- echo "DISABLE"
201
+ then
202
+ echo >&2 "$PROGRAM_NAME: cannot find charts directory '$chartsd'"
203
+ echo "DISABLE"
204
fi
205
206
@@ -210,13 +210,13 @@ fi
210
# default sleep function
211
LOOPSLEEPMS_HIGHRES=0
212
loopsleepms() {
213
- [ "$1" = "tellwork" ] && shift
214
- sleep $1
213
+ [ "$1" = "tellwork" ] && shift
214
+ sleep $1
215
}
216
217
now_ms=
218
current_time_ms() {
219
- now_ms="$(date +'%s')000"
219
+ now_ms="$(date +'%s')000"
220
}
221
222
# if found and included, this file overwrites loopsleepms()
@@ -229,10 +229,10 @@ current_time_ms() {
229
# library functions
230
231
fixid() {
232
- echo "$*" |\
233
- tr -c "[A-Z][a-z][0-9]" "_" |\
234
- sed -e "s|^_\+||g" -e "s|_\+$||g" -e "s|_\+|_|g" |\
235
- tr "[A-Z]" "[a-z]"
232
+ echo "$*" |\
233
+ tr -c "[A-Z][a-z][0-9]" "_" |\
234
+ sed -e "s|^_\+||g" -e "s|_\+$||g" -e "s|_\+|_|g" |\
235
+ tr "[A-Z]" "[a-z]"
236
}
237
238
# convert any floating point number
@@ -241,57 +241,57 @@ fixid() {
241
# so that no fork is necessary
242
# the multiplier must be a power of 10
243
float2int() {
244
- local f m="$2" a b l v=($1)
245
- f=${v[0]}
246
-
247
- # echo >&2 "value='${1}' f='${f}', m='${m}'"
248
-
249
- # the length of the multiplier - 1
250
- l=$(( ${#m} - 1 ))
251
-
252
- # check if the number is in scientific notation
253
- if [[ ${f} =~ ^[[:space:]]*(-)?[0-9.]+(e|E)(\+|-)[0-9]+ ]]
254
- then
255
- # convert it to decimal
256
- # unfortunately, this fork cannot be avoided
257
- # if you know of a way to avoid it, please let me know
258
- f=$(printf "%0.${l}f" ${f})
259
- fi
260
-
261
- # split the floating point number
262
- # in integer (a) and decimal (b)
263
- a=${f/.*/}
264
- b=${f/*./}
265
-
266
- # if the integer part is missing
267
- # set it to zero
268
- [ -z "${a}" ] && a="0"
269
-
270
- # strip leading zeros from the integer part
271
- # base 10 convertion
272
- a=$((10#$a))
273
-
274
- # check the length of the decimal part
275
- # against the length of the multiplier
276
- if [ ${#b} -gt ${l} ]
277
- then
278
- # too many digits - take the most significant
279
- b=${b:0:${l}}
280
-
281
- elif [ ${#b} -lt ${l} ]
282
- then
283
- # too few digits - pad with zero on the right
284
- local z="00000000000000000000000" r=$((l - ${#b}))
285
- b="${b}${z:0:${r}}"
286
- fi
287
-
288
- # strip leading zeros from the decimal part
289
- # base 10 convertion
290
- b=$((10#$b))
291
-
292
- # store the result
293
- FLOAT2INT_RESULT=$(( (a * m) + b ))
294
- #echo >&2 "FLOAT2INT_RESULT='${FLOAT2INT_RESULT}'"
244
+ local f m="$2" a b l v=($1)
245
+ f=${v[0]}
246
+
247
+ # echo >&2 "value='${1}' f='${f}', m='${m}'"
248
+
249
+ # the length of the multiplier - 1
250
+ l=$(( ${#m} - 1 ))
251
+
252
+ # check if the number is in scientific notation
253
+ if [[ ${f} =~ ^[[:space:]]*(-)?[0-9.]+(e|E)(\+|-)[0-9]+ ]]
254
+ then
255
+ # convert it to decimal
256
+ # unfortunately, this fork cannot be avoided
257
+ # if you know of a way to avoid it, please let me know
258
+ f=$(printf "%0.${l}f" ${f})
259
+ fi
260
+
261
+ # split the floating point number
262
+ # in integer (a) and decimal (b)
263
+ a=${f/.*/}
264
+ b=${f/*./}
265
+
266
+ # if the integer part is missing
267
+ # set it to zero
268
+ [ -z "${a}" ] && a="0"
269
+
270
+ # strip leading zeros from the integer part
271
+ # base 10 convertion
272
+ a=$((10#$a))
273
+
274
+ # check the length of the decimal part
275
+ # against the length of the multiplier
276
+ if [ ${#b} -gt ${l} ]
277
+ then
278
+ # too many digits - take the most significant
279
+ b=${b:0:${l}}
280
+
281
+ elif [ ${#b} -lt ${l} ]
282
+ then
283
+ # too few digits - pad with zero on the right
284
+ local z="00000000000000000000000" r=$((l - ${#b}))
285
+ b="${b}${z:0:${r}}"
286
+ fi
287
+
288
+ # strip leading zeros from the decimal part
289
+ # base 10 convertion
290
+ b=$((10#$b))
291
+
292
+ # store the result
293
+ FLOAT2INT_RESULT=$(( (a * m) + b ))
294
+ #echo >&2 "FLOAT2INT_RESULT='${FLOAT2INT_RESULT}'"
295
}
296
297
@@ -299,105 +299,105 @@ float2int() {
299
# charts check functions
300
301
all_charts() {
302
- cd "$chartsd"
303
- [ $? -ne 0 ] && echo >&2 "$PROGRAM_NAME: Cannot cd to $chartsd" && return 1
302
+ cd "$chartsd"
303
+ [ $? -ne 0 ] && echo >&2 "$PROGRAM_NAME: Cannot cd to $chartsd" && return 1
304
305
- ls *.chart.sh | sed "s/\.chart\.sh$//g"
305
+ ls *.chart.sh | sed "s/\.chart\.sh$//g"
306
}
307
308
declare -A charts_enable_keyword=(
309
- ['apache']="force"
310
- ['cpu_apps']="force"
311
- ['cpufreq']="force"
312
- ['example']="force"
313
- ['exim']="force"
314
- ['hddtemp']="force"
315
- ['load_average']="force"
316
- ['mem_apps']="force"
317
- ['mysql']="force"
318
- ['nginx']="force"
319
- ['phpfpm']="force"
320
- ['postfix']="force"
321
- ['sensors']="force"
322
- ['squid']="force"
323
- ['tomcat']="force"
324
- )
309
+ ['apache']="force"
310
+ ['cpu_apps']="force"
311
+ ['cpufreq']="force"
312
+ ['example']="force"
313
+ ['exim']="force"
314
+ ['hddtemp']="force"
315
+ ['load_average']="force"
316
+ ['mem_apps']="force"
317
+ ['mysql']="force"
318
+ ['nginx']="force"
319
+ ['phpfpm']="force"
320
+ ['postfix']="force"
321
+ ['sensors']="force"
322
+ ['squid']="force"
323
+ ['tomcat']="force"
324
+ )
325
326
all_enabled_charts() {
327
- local charts= enabled= required=
328
-
329
- # find all enabled charts
330
-
331
- for chart in $( all_charts )
332
- do
333
- eval "enabled=\$$chart"
334
- if [ -z "${enabled}" ]
335
- then
336
- enabled="${enable_all_charts}"
337
- fi
338
-
339
- required="${charts_enable_keyword[${chart}]}"
340
- [ -z "${required}" ] && required="yes"
341
-
342
- if [ ! "${enabled}" = "${required}" ]
343
- then
344
- echo >&2 "$PROGRAM_NAME: '$chart' is NOT enabled. Add a line with $chart=$required in $myconfig to enable it (or remove the line that disables it)."
345
- else
346
- [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: '$chart' is enabled."
347
- local charts="$charts $chart"
348
- fi
349
- done
350
-
351
- local charts2=
352
- for chart in $charts
353
- do
354
- # check the enabled charts
355
- local check="$( cat "$chartsd/$chart.chart.sh" | sed "s/^ \+//g" | grep "^$chart$charts_check()" )"
356
- if [ -z "$check" ]
357
- then
358
- echo >&2 "$PROGRAM_NAME: chart '$chart' does not seem to have a $chart$charts_check() function. Disabling it."
359
- continue
360
- fi
361
-
362
- local create="$( cat "$chartsd/$chart.chart.sh" | sed "s/^ \+//g" | grep "^$chart$charts_create()" )"
363
- if [ -z "$create" ]
364
- then
365
- echo >&2 "$PROGRAM_NAME: chart '$chart' does not seem to have a $chart$charts_create() function. Disabling it."
366
- continue
367
- fi
368
-
369
- local update="$( cat "$chartsd/$chart.chart.sh" | sed "s/^ \+//g" | grep "^$chart$charts_update()" )"
370
- if [ -z "$update" ]
371
- then
372
- echo >&2 "$PROGRAM_NAME: chart '$chart' does not seem to have a $chart$charts_update() function. Disabling it."
373
- continue
374
- fi
375
-
376
- # check its config
377
- #if [ -f "$confd/$chart.conf" ]
378
- #then
379
- # if [ ! -z "$( cat "$confd/$chart.conf" | sed "s/^ \+//g" | grep -v "^$" | grep -v "^#" | grep -v "^$chart$charts_undescore" )" ]
380
- # then
381
- # echo >&2 "$PROGRAM_NAME: chart's $chart config $confd/$chart.conf should only have lines starting with $chart$charts_undescore . Disabling it."
382
- # continue
383
- # fi
384
- #fi
385
-
386
- #if [ $dryrunner -eq 1 ]
387
- # then
388
- # "$pluginsd/charts.d.dryrun-helper.sh" "$chart" "$chartsd/$chart.chart.sh" "$confd/$chart.conf" >/dev/null
389
- # if [ $? -ne 0 ]
390
- # then
391
- # echo >&2 "$PROGRAM_NAME: chart's $chart did not pass the dry run check. This means it uses global variables not starting with $chart. Disabling it."
392
- # continue
393
- # fi
394
- #fi
395
-
396
- local charts2="$charts2 $chart"
397
- done
398
-
399
- echo $charts2
400
- [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: enabled charts: $charts2"
327
+ local charts= enabled= required=
328
+
329
+ # find all enabled charts
330
+
331
+ for chart in $( all_charts )
332
+ do
333
+ eval "enabled=\$$chart"
334
+ if [ -z "${enabled}" ]
335
+ then
336
+ enabled="${enable_all_charts}"
337
+ fi
338
+
339
+ required="${charts_enable_keyword[${chart}]}"
340
+ [ -z "${required}" ] && required="yes"
341
+
342
+ if [ ! "${enabled}" = "${required}" ]
343
+ then
344
+ echo >&2 "$PROGRAM_NAME: '$chart' is NOT enabled. Add a line with $chart=$required in $myconfig to enable it (or remove the line that disables it)."
345
+ else
346
+ [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: '$chart' is enabled."
347
+ local charts="$charts $chart"
348
+ fi
349
+ done
350
+
351
+ local charts2=
352
+ for chart in $charts
353
+ do
354
+ # check the enabled charts
355
+ local check="$( cat "$chartsd/$chart.chart.sh" | sed "s/^ \+//g" | grep "^$chart$charts_check()" )"
356
+ if [ -z "$check" ]
357
+ then
358
+ echo >&2 "$PROGRAM_NAME: chart '$chart' does not seem to have a $chart$charts_check() function. Disabling it."
359
+ continue
360
+ fi
361
+
362
+ local create="$( cat "$chartsd/$chart.chart.sh" | sed "s/^ \+//g" | grep "^$chart$charts_create()" )"
363
+ if [ -z "$create" ]
364
+ then
365
+ echo >&2 "$PROGRAM_NAME: chart '$chart' does not seem to have a $chart$charts_create() function. Disabling it."
366
+ continue
367
+ fi
368
+
369
+ local update="$( cat "$chartsd/$chart.chart.sh" | sed "s/^ \+//g" | grep "^$chart$charts_update()" )"
370
+ if [ -z "$update" ]
371
+ then
372
+ echo >&2 "$PROGRAM_NAME: chart '$chart' does not seem to have a $chart$charts_update() function. Disabling it."
373
+ continue
374
+ fi
375
+
376
+ # check its config
377
+ #if [ -f "$confd/$chart.conf" ]
378
+ #then
379
+ # if [ ! -z "$( cat "$confd/$chart.conf" | sed "s/^ \+//g" | grep -v "^$" | grep -v "^#" | grep -v "^$chart$charts_undescore" )" ]
380
+ # then
381
+ # echo >&2 "$PROGRAM_NAME: chart's $chart config $confd/$chart.conf should only have lines starting with $chart$charts_undescore . Disabling it."
382
+ # continue
383
+ # fi
384
+ #fi
385
+
386
+ #if [ $dryrunner -eq 1 ]
387
+ # then
388
+ # "$pluginsd/charts.d.dryrun-helper.sh" "$chart" "$chartsd/$chart.chart.sh" "$confd/$chart.conf" >/dev/null
389
+ # if [ $? -ne 0 ]
390
+ # then
391
+ # echo >&2 "$PROGRAM_NAME: chart's $chart did not pass the dry run check. This means it uses global variables not starting with $chart. Disabling it."
392
+ # continue
393
+ # fi
394
+ #fi
395
+
396
+ local charts2="$charts2 $chart"
397
+ done
398
+
399
+ echo $charts2
400
+ [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: enabled charts: $charts2"
401
}
402
403
@@ -408,36 +408,36 @@ suffix_update_every="_update_every"
408
active_charts=
409
for chart in $( all_enabled_charts )
410
do
411
- [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: loading chart: '$chartsd/$chart.chart.sh'"
412
- . "$chartsd/$chart.chart.sh"
413
-
414
- if [ -f "$confd/charts.d/$chart.conf" ]
415
- then
416
- [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: loading chart options: '$confd/charts.d/$chart.conf'"
417
- . "$confd/charts.d/$chart.conf"
418
- elif [ -f "$confd/$chart.conf" ]
419
- then
420
- [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: loading chart options: '$confd/$chart.conf'"
421
- . "$confd/$chart.conf"
422
- else
423
- echo >&2 "$PROGRAM_NAME: $chart: configuration file '$confd/charts.d/$chart.conf' not found. Using defaults."
424
- fi
425
-
426
- eval "dt=\$$chart$suffix_update_every"
427
- dt=$(( dt + 1 - 1 )) # make sure it is a number
428
- if [ $dt -lt $update_every ]
429
- then
430
- eval "$chart$suffix_update_every=$update_every"
431
- fi
432
-
433
- $chart$charts_check
434
- if [ $? -eq 0 ]
435
- then
436
- [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: '$chart' activated"
437
- active_charts="$active_charts $chart"
438
- else
439
- echo >&2 "$PROGRAM_NAME: chart '$chart' check() function reports failure."
440
- fi
411
+ [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: loading chart: '$chartsd/$chart.chart.sh'"
412
+ . "$chartsd/$chart.chart.sh"
413
+
414
+ if [ -f "$confd/charts.d/$chart.conf" ]
415
+ then
416
+ [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: loading chart options: '$confd/charts.d/$chart.conf'"
417
+ . "$confd/charts.d/$chart.conf"
418
+ elif [ -f "$confd/$chart.conf" ]
419
+ then
420
+ [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: loading chart options: '$confd/$chart.conf'"
421
+ . "$confd/$chart.conf"
422
+ else
423
+ echo >&2 "$PROGRAM_NAME: $chart: configuration file '$confd/charts.d/$chart.conf' not found. Using defaults."
424
+ fi
425
+
426
+ eval "dt=\$$chart$suffix_update_every"
427
+ dt=$(( dt + 1 - 1 )) # make sure it is a number
428
+ if [ $dt -lt $update_every ]
429
+ then
430
+ eval "$chart$suffix_update_every=$update_every"
431
+ fi
432
+
433
+ $chart$charts_check
434
+ if [ $? -eq 0 ]
435
+ then
436
+ [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: '$chart' activated"
437
+ active_charts="$active_charts $chart"
438
+ else
439
+ echo >&2 "$PROGRAM_NAME: chart '$chart' check() function reports failure."
440
+ fi
441
done
442
[ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: activated charts: $active_charts"
443
@@ -452,26 +452,26 @@ test $debug -eq 1 && debug_time=tellwork
452
# if we only need a specific chart, remove all the others
453
if [ ! -z "${chart_only}" ]
454
then
455
- [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: requested to run only for: '${chart_only}'"
456
- check_charts=
457
- for chart in $active_charts
458
- do
459
- if [ "$chart" = "$chart_only" ]
460
- then
461
- check_charts="$chart"
462
- break
463
- fi
464
- done
465
- active_charts="$check_charts"
455
+ [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: requested to run only for: '${chart_only}'"
456
+ check_charts=
457
+ for chart in $active_charts
458
+ do
459
+ if [ "$chart" = "$chart_only" ]
460
+ then
461
+ check_charts="$chart"
462
+ break
463
+ fi
464
+ done
465
+ active_charts="$check_charts"
466
fi
467
[ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: activated charts: $active_charts"
468
469
# stop if we just need a pre-check
470
if [ $check -eq 1 ]
471
then
472
- echo >&2 "CHECK RESULT"
473
- echo >&2 "Will run the charts: $active_charts"
474
- exit 0
472
+ echo >&2 "CHECK RESULT"
473
+ echo >&2 "Will run the charts: $active_charts"
474
+ exit 0
475
fi
476
477
# -----------------------------------------------------------------------------
@@ -479,13 +479,13 @@ fi
479
480
TMP_DIR=
481
chartsd_cleanup() {
482
- cd /tmp
483
- if [ ! -z "$TMP_DIR" -a -d "$TMP_DIR" ]
484
- then
485
- [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: cleaning up temporary directory $TMP_DIR ..."
486
- rm -rf "$TMP_DIR"
487
- fi
488
- exit 0
482
+ cd /tmp
483
+ if [ ! -z "$TMP_DIR" -a -d "$TMP_DIR" ]
484
+ then
485
+ [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: cleaning up temporary directory $TMP_DIR ..."
486
+ rm -rf "$TMP_DIR"
487
+ fi
488
+ exit 0
489
}
490
trap chartsd_cleanup EXIT
491
trap chartsd_cleanup SIGHUP
@@ -493,9 +493,9 @@ trap chartsd_cleanup INT
493
494
if [ $UID = "0" ]
495
then
496
- TMP_DIR="$( mktemp -d /var/run/netdata-${PROGRAM_NAME}-XXXXXXXXXX )"
496
+ TMP_DIR="$( mktemp -d /var/run/netdata-${PROGRAM_NAME}-XXXXXXXXXX )"
497
else
498
- TMP_DIR="$( mktemp -d /tmp/.netdata-${PROGRAM_NAME}-XXXXXXXXXX )"
498
+ TMP_DIR="$( mktemp -d /tmp/.netdata-${PROGRAM_NAME}-XXXXXXXXXX )"
499
fi
500
501
cd "$TMP_DIR" || exit 1
@@ -506,15 +506,15 @@ cd "$TMP_DIR" || exit 1
506
run_charts=
507
for chart in $active_charts
508
do
509
- [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: Calling '$chart$charts_create()'..."
510
- $chart$charts_create
511
- if [ $? -eq 0 ]
512
- then
513
- run_charts="$run_charts $chart"
514
- [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: '$chart' has initialized."
515
- else
516
- echo >&2 "$PROGRAM_NAME: chart '$chart' function '$chart$charts_create()' reports failure."
517
- fi
509
+ [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: Calling '$chart$charts_create()'..."
510
+ $chart$charts_create
511
+ if [ $? -eq 0 ]
512
+ then
513
+ run_charts="$run_charts $chart"
514
+ [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: '$chart' has initialized."
515
+ else
516
+ echo >&2 "$PROGRAM_NAME: chart '$chart' function '$chart$charts_create()' reports failure."
517
+ fi
518
done
519
[ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: run_charts='$run_charts'"
520
@@ -523,131 +523,131 @@ done
523
# update dimensions
524
525
if [ -z "$run_charts" ]
526
- then
527
- echo >&2 "$PROGRAM_NAME: No charts to collect data from."
528
- echo "DISABLE"
529
- exit 1
526
+ then
527
+ echo >&2 "$PROGRAM_NAME: No charts to collect data from."
528
+ echo "DISABLE"
529
+ exit 1
530
fi
531
532
declare -A charts_last_update=() charts_update_every=() charts_next_update=() charts_run_counter=() charts_serial_failures=()
533
global_update() {
534
- local exit_at \
535
- c=0 dt ret last_ms exec_start_ms exec_end_ms \
536
- chart now_charts=() next_charts=($run_charts) \
537
- next_ms x seconds millis
538
-
539
- # return the current time in ms in $now_ms
540
- current_time_ms
541
-
542
- exit_at=$(( now_ms + (restart_timeout * 1000) ))
543
-
544
- for chart in $run_charts
545
- do
546
- eval "charts_update_every[$chart]=\$$chart$suffix_update_every"
547
- test -z "${charts_update_every[$chart]}" && charts_update_every[$charts]=$update_every
548
- charts_last_update[$chart]=$((now_ms - (now_ms % (charts_update_every[$chart] * 1000) ) ))
549
- charts_next_update[$chart]=$(( charts_last_update[$chart] + (charts_update_every[$chart] * 1000) ))
550
- charts_run_counter[$chart]=0
551
- charts_serial_failures[$chart]=0
552
-
553
- echo "CHART netdata.plugin_chartsd_$chart '' 'Execution time for $chart plugin' 'milliseconds / run' charts.d netdata.plugin_charts area 145000 ${charts_update_every[$chart]}"
554
- echo "DIMENSION run_time 'run time' absolute 1 1"
555
- done
556
-
557
- # the main loop
558
- while [ "${#next_charts[@]}" -gt 0 ]
559
- do
560
- c=$((c + 1))
561
- now_charts=("${next_charts[@]}")
562
- next_charts=()
563
-
564
- # return the current time in ms in $now_ms
565
- current_time_ms
566
-
567
- for chart in "${now_charts[@]}"
568
- do
569
- # echo >&2 "DEBUG: chart: $chart last: ${charts_last_update[$chart]}, next: ${charts_next_update[$chart]}, now: ${now_ms}"
570
- if [ ${now_ms} -ge ${charts_next_update[$chart]} ]
571
- then
572
- last_ms=${charts_last_update[$chart]}
573
- dt=$(( (now_ms - last_ms) ))
574
- # echo >&2 "DEBUG: chart: $chart last: ${charts_last_update[$chart]}, next: ${charts_next_update[$chart]}, now: ${now_ms}, dt: ${dt}"
575
-
576
- charts_last_update[$chart]=${now_ms}
577
-
578
- while [ ${charts_next_update[$chart]} -lt ${now_ms} ]
579
- do
580
- charts_next_update[$chart]=$(( charts_next_update[$chart] + (charts_update_every[$chart] * 1000) ))
581
- done
582
-
583
- # the first call should not give a duration
584
- # so that netdata calibrates to current time
585
- dt=$(( dt * 1000 ))
586
- charts_run_counter[$chart]=$(( charts_run_counter[$chart] + 1 ))
587
- if [ ${charts_run_counter[$chart]} -eq 1 ]
588
- then
589
- dt=
590
- fi
591
-
592
- exec_start_ms=$now_ms
593
- $chart$charts_update $dt
594
- ret=$?
595
-
596
- # return the current time in ms in $now_ms
597
- current_time_ms; exec_end_ms=$now_ms
598
-
599
- echo "BEGIN netdata.plugin_chartsd_$chart $dt"
600
- echo "SET run_time = $(( exec_end_ms - exec_start_ms ))"
601
- echo "END"
602
-
603
- if [ $ret -eq 0 ]
604
- then
605
- charts_serial_failures[$chart]=0
606
- next_charts+=($chart)
607
- else
608
- charts_serial_failures[$chart]=$(( charts_serial_failures[$chart] + 1 ))
609
-
610
- if [ ${charts_serial_failures[$chart]} -gt 10 ]
611
- then
612
- echo >&2 "$PROGRAM_NAME: chart '$chart' update() function reported failure ${charts_serial_failures[$chart]} times. Disabling it."
613
- else
614
- echo >&2 "$PROGRAM_NAME: chart '$chart' update() function reports failure. Will keep trying for a while."
615
- next_charts+=($chart)
616
- fi
617
- fi
618
- else
619
- next_charts+=($chart)
620
- fi
621
- done
622
-
623
- if [ "$pause_method" = "suspend" ]
624
- then
625
- echo "STOPPING_WAKE_ME_UP_PLEASE"
626
- suspend || ( echo >&2 "$PROGRAM_NAME: suspend returned error $?, falling back to sleep."; loopsleepms $debug_time $update_every $time_divisor)
627
- else
628
- # wait the time you are required to
629
- next_ms=$((now_ms + (update_every * 1000 * 100) ))
630
- for x in "${charts_next_update[@]}"; do [ ${x} -lt ${next_ms} ] && next_ms=${x}; done
631
- next_ms=$((next_ms - now_ms))
632
-
633
- if [ ${LOOPSLEEPMS_HIGHRES} -eq 1 -a ${next_ms} -gt 0 ]
634
- then
635
- seconds=$(( next_ms / 1000 ))
636
- millis=$(( next_ms % 1000 ))
637
- [ ${millis} -lt 10 ] && millis="0${millis}"
638
- [ ${millis} -lt 100 ] && millis="0${millis}"
639
- [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: sleeping for ${seconds}.${millis} seconds."
640
- sleep ${seconds}.${millis}
641
- else
642
- sleep $update_every
643
- fi
644
- fi
645
-
646
- test ${now_ms} -ge ${exit_at} && exit 0
647
- done
648
-
649
- echo >&2 "$PROGRAM_NAME: Nothing left to do. Disabling charts.d.plugin."
650
- echo "DISABLE"
534
+ local exit_at \
535
+ c=0 dt ret last_ms exec_start_ms exec_end_ms \
536
+ chart now_charts=() next_charts=($run_charts) \
537
+ next_ms x seconds millis
538
+
539
+ # return the current time in ms in $now_ms
540
+ current_time_ms
541
+
542
+ exit_at=$(( now_ms + (restart_timeout * 1000) ))
543
+
544
+ for chart in $run_charts
545
+ do
546
+ eval "charts_update_every[$chart]=\$$chart$suffix_update_every"
547
+ test -z "${charts_update_every[$chart]}" && charts_update_every[$charts]=$update_every
548
+ charts_last_update[$chart]=$((now_ms - (now_ms % (charts_update_every[$chart] * 1000) ) ))
549
+ charts_next_update[$chart]=$(( charts_last_update[$chart] + (charts_update_every[$chart] * 1000) ))
550
+ charts_run_counter[$chart]=0
551
+ charts_serial_failures[$chart]=0
552
+
553
+ echo "CHART netdata.plugin_chartsd_$chart '' 'Execution time for $chart plugin' 'milliseconds / run' charts.d netdata.plugin_charts area 145000 ${charts_update_every[$chart]}"
554
+ echo "DIMENSION run_time 'run time' absolute 1 1"
555
+ done
556
+
557
+ # the main loop
558
+ while [ "${#next_charts[@]}" -gt 0 ]
559
+ do
560
+ c=$((c + 1))
561
+ now_charts=("${next_charts[@]}")
562
+ next_charts=()
563
+
564
+ # return the current time in ms in $now_ms
565
+ current_time_ms
566
+
567
+ for chart in "${now_charts[@]}"
568
+ do
569
+ # echo >&2 "DEBUG: chart: $chart last: ${charts_last_update[$chart]}, next: ${charts_next_update[$chart]}, now: ${now_ms}"
570
+ if [ ${now_ms} -ge ${charts_next_update[$chart]} ]
571
+ then
572
+ last_ms=${charts_last_update[$chart]}
573
+ dt=$(( (now_ms - last_ms) ))
574
+ # echo >&2 "DEBUG: chart: $chart last: ${charts_last_update[$chart]}, next: ${charts_next_update[$chart]}, now: ${now_ms}, dt: ${dt}"
575
+
576
+ charts_last_update[$chart]=${now_ms}
577
+
578
+ while [ ${charts_next_update[$chart]} -lt ${now_ms} ]
579
+ do
580
+ charts_next_update[$chart]=$(( charts_next_update[$chart] + (charts_update_every[$chart] * 1000) ))
581
+ done
582
+
583
+ # the first call should not give a duration
584
+ # so that netdata calibrates to current time
585
+ dt=$(( dt * 1000 ))
586
+ charts_run_counter[$chart]=$(( charts_run_counter[$chart] + 1 ))
587
+ if [ ${charts_run_counter[$chart]} -eq 1 ]
588
+ then
589
+ dt=
590
+ fi
591
+
592
+ exec_start_ms=$now_ms
593
+ $chart$charts_update $dt
594
+ ret=$?
595
+
596
+ # return the current time in ms in $now_ms
597
+ current_time_ms; exec_end_ms=$now_ms
598
+
599
+ echo "BEGIN netdata.plugin_chartsd_$chart $dt"
600
+ echo "SET run_time = $(( exec_end_ms - exec_start_ms ))"
601
+ echo "END"
602
+
603
+ if [ $ret -eq 0 ]
604
+ then
605
+ charts_serial_failures[$chart]=0
606
+ next_charts+=($chart)
607
+ else
608
+ charts_serial_failures[$chart]=$(( charts_serial_failures[$chart] + 1 ))
609
+
610
+ if [ ${charts_serial_failures[$chart]} -gt 10 ]
611
+ then
612
+ echo >&2 "$PROGRAM_NAME: chart '$chart' update() function reported failure ${charts_serial_failures[$chart]} times. Disabling it."
613
+ else
614
+ echo >&2 "$PROGRAM_NAME: chart '$chart' update() function reports failure. Will keep trying for a while."
615
+ next_charts+=($chart)
616
+ fi
617
+ fi
618
+ else
619
+ next_charts+=($chart)
620
+ fi
621
+ done
622
+
623
+ if [ "$pause_method" = "suspend" ]
624
+ then
625
+ echo "STOPPING_WAKE_ME_UP_PLEASE"
626
+ suspend || ( echo >&2 "$PROGRAM_NAME: suspend returned error $?, falling back to sleep."; loopsleepms $debug_time $update_every $time_divisor)
627
+ else
628
+ # wait the time you are required to
629
+ next_ms=$((now_ms + (update_every * 1000 * 100) ))
630
+ for x in "${charts_next_update[@]}"; do [ ${x} -lt ${next_ms} ] && next_ms=${x}; done
631
+ next_ms=$((next_ms - now_ms))
632
+
633
+ if [ ${LOOPSLEEPMS_HIGHRES} -eq 1 -a ${next_ms} -gt 0 ]
634
+ then
635
+ seconds=$(( next_ms / 1000 ))
636
+ millis=$(( next_ms % 1000 ))
637
+ [ ${millis} -lt 10 ] && millis="0${millis}"
638
+ [ ${millis} -lt 100 ] && millis="0${millis}"
639
+ [ $debug -eq 1 ] && echo >&2 "$PROGRAM_NAME: sleeping for ${seconds}.${millis} seconds."
640
+ sleep ${seconds}.${millis}
641
+ else
642
+ sleep $update_every
643
+ fi
644
+ fi
645
+
646
+ test ${now_ms} -ge ${exit_at} && exit 0
647
+ done
648
+
649
+ echo >&2 "$PROGRAM_NAME: Nothing left to do. Disabling charts.d.plugin."
650
+ echo "DISABLE"
651
}
652
653
global_update
plugins.d/loopsleepms.sh.inc
+53
-53
@@ -7,9 +7,9 @@
7
8
LOOPSLEEP_DATE="$(which date)"
9
if [ -z "$LOOPSLEEP_DATE" ]
10
- then
11
- echo >&2 "$0: ERROR: Cannot find the command 'date' in the system path."
12
- exit 1
10
+ then
11
+ echo >&2 "$0: ERROR: Cannot find the command 'date' in the system path."
12
+ exit 1
13
fi
14
15
LOOPSLEEPMS_LASTRUN=0
@@ -21,70 +21,70 @@ test "$($LOOPSLEEP_DATE +%N)" = "%N" && LOOPSLEEPMS_HIGHRES=0
21
22
now_ms=
23
current_time_ms() {
24
- # if high resolution is not supported
25
- # just sleep the time requested, in seconds
26
- if [ $LOOPSLEEPMS_HIGHRES -eq 0 ]
27
- then
28
- now_ms="$($LOOPSLEEP_DATE +'%s')000"
29
- else
30
- now_ms="$(( $( $LOOPSLEEP_DATE +'%s * 1000 + %-N / 1000000' ) ))"
31
- fi
24
+ # if high resolution is not supported
25
+ # just sleep the time requested, in seconds
26
+ if [ $LOOPSLEEPMS_HIGHRES -eq 0 ]
27
+ then
28
+ now_ms="$($LOOPSLEEP_DATE +'%s')000"
29
+ else
30
+ now_ms="$(( $( $LOOPSLEEP_DATE +'%s * 1000 + %-N / 1000000' ) ))"
31
+ fi
32
}
33
34
loopsleepms() {
35
- local tellwork=0 t="$1" div s m now mstosleep
35
+ local tellwork=0 t="$1" div s m now mstosleep
36
37
- if [ "$t" = "tellwork" ]
38
- then
39
- tellwork=1
40
- shift
41
- t="$1"
42
- fi
43
- div="${2-100}"
37
+ if [ "$t" = "tellwork" ]
38
+ then
39
+ tellwork=1
40
+ shift
41
+ t="$1"
42
+ fi
43
+ div="${2-100}"
44
45
- # $t = the time in seconds to wait
45
+ # $t = the time in seconds to wait
46
47
- # if high resolution is not supported
48
- # just sleep the time requested, in seconds
49
- if [ $LOOPSLEEPMS_HIGHRES -eq 0 ]
50
- then
51
- sleep $t
52
- return
53
- fi
47
+ # if high resolution is not supported
48
+ # just sleep the time requested, in seconds
49
+ if [ $LOOPSLEEPMS_HIGHRES -eq 0 ]
50
+ then
51
+ sleep $t
52
+ return
53
+ fi
54
55
- # get the current time, in ms
56
- # milliseconds since epoch (1-1-1970)
57
- now="$(( $( $LOOPSLEEP_DATE +'%s * 1000 + %-N / 1000000' ) ))"
55
+ # get the current time, in ms
56
+ # milliseconds since epoch (1-1-1970)
57
+ now="$(( $( $LOOPSLEEP_DATE +'%s * 1000 + %-N / 1000000' ) ))"
58
59
- # calculate required sleep in ms
60
- t=$((t * 1000 * div / 100))
59
+ # calculate required sleep in ms
60
+ t=$((t * 1000 * div / 100))
61
62
- # this is our first run
63
- # just wait the requested time
64
- test $LOOPSLEEPMS_LASTRUN -eq 0 && LOOPSLEEPMS_LASTRUN=$now
62
+ # this is our first run
63
+ # just wait the requested time
64
+ test $LOOPSLEEPMS_LASTRUN -eq 0 && LOOPSLEEPMS_LASTRUN=$now
65
66
- # calculate ms since last run
67
- LOOPSLEEPMS_LASTWORK=$((now - LOOPSLEEPMS_LASTRUN - LOOPSLEEPMS_LASTSLEEP))
68
- # echo "# last loop's work took $LOOPSLEEPMS_LASTWORK ms"
66
+ # calculate ms since last run
67
+ LOOPSLEEPMS_LASTWORK=$((now - LOOPSLEEPMS_LASTRUN - LOOPSLEEPMS_LASTSLEEP))
68
+ # echo "# last loop's work took $LOOPSLEEPMS_LASTWORK ms"
69
70
- # calculate ms to sleep
71
- mstosleep=$(( t - LOOPSLEEPMS_LASTWORK ))
72
- # echo "# mstosleep is $mstosleep ms"
70
+ # calculate ms to sleep
71
+ mstosleep=$(( t - LOOPSLEEPMS_LASTWORK ))
72
+ # echo "# mstosleep is $mstosleep ms"
73
74
- # if we are too slow, sleep some time
75
- test $mstosleep -lt 200 && mstosleep=200
74
+ # if we are too slow, sleep some time
75
+ test $mstosleep -lt 200 && mstosleep=200
76
77
- s=$((mstosleep / 1000))
78
- m=$((mstosleep - (s * 1000)))
77
+ s=$((mstosleep / 1000))
78
+ m=$((mstosleep - (s * 1000)))
79
80
- test $tellwork -eq 1 && echo >&2 " >>> PERFORMANCE >>> WORK TOOK $LOOPSLEEPMS_LASTWORK ms ( $((LOOPSLEEPMS_LASTWORK * 100 / 1000)).$((LOOPSLEEPMS_LASTWORK % 10))% cpu ) >>> SLEEPING $mstosleep ms"
80
+ test $tellwork -eq 1 && echo >&2 " >>> PERFORMANCE >>> WORK TOOK $LOOPSLEEPMS_LASTWORK ms ( $((LOOPSLEEPMS_LASTWORK * 100 / 1000)).$((LOOPSLEEPMS_LASTWORK % 10))% cpu ) >>> SLEEPING $mstosleep ms"
81
82
- # echo "# sleeping $s.$m"
83
- # echo
84
- sleep $s.$m
82
+ # echo "# sleeping $s.$m"
83
+ # echo
84
+ sleep $s.$m
85
86
- # keep the values we need
87
- # for our next run
88
- LOOPSLEEPMS_LASTRUN=$now
89
- LOOPSLEEPMS_LASTSLEEP=$mstosleep
86
+ # keep the values we need
87
+ # for our next run
88
+ LOOPSLEEPMS_LASTRUN=$now
89
+ LOOPSLEEPMS_LASTSLEEP=$mstosleep
90
}
plugins.d/node.d.plugin
+181
-181
@@ -40,60 +40,60 @@ var netdata = require('netdata');
40
// configuration
41
42
function pluginConfig(filename) {
43
- var f = path.basename(filename);
43
+ var f = path.basename(filename);
44
45
- // node.d.plugin configuration
46
- var m = f.match('.plugin' + '$');
47
- if(m !== null)
48
- return netdata.options.paths.config + '/' + f.substring(0, m.index) + '.conf';
45
+ // node.d.plugin configuration
46
+ var m = f.match('.plugin' + '$');
47
+ if(m !== null)
48
+ return netdata.options.paths.config + '/' + f.substring(0, m.index) + '.conf';
49
50
- // node.d modules configuration
51
- m = f.match('.node.js' + '$');
52
- if(m !== null)
53
- return netdata.options.paths.config + '/node.d/' + f.substring(0, m.index) + '.conf';
50
+ // node.d modules configuration
51
+ m = f.match('.node.js' + '$');
52
+ if(m !== null)
53
+ return netdata.options.paths.config + '/node.d/' + f.substring(0, m.index) + '.conf';
54
55
- return netdata.options.paths.config + '/node.d/' + f + '.conf';
55
+ return netdata.options.paths.config + '/node.d/' + f + '.conf';
56
}
57
58
// internal defaults
59
extend(true, netdata.options, {
60
- filename: path.basename(__filename),
60
+ filename: path.basename(__filename),
61
62
- update_every: NETDATA_UPDATE_EVERY,
62
+ update_every: NETDATA_UPDATE_EVERY,
63
64
- exit_after_ms: 3600 * 4 * 1000,
64
+ exit_after_ms: 3600 * 4 * 1000,
65
66
- paths: {
67
- plugins: NETDATA_PLUGINS_DIR,
68
- config: NETDATA_CONFIG_DIR,
69
- modules: [],
70
- },
66
+ paths: {
67
+ plugins: NETDATA_PLUGINS_DIR,
68
+ config: NETDATA_CONFIG_DIR,
69
+ modules: [],
70
+ },
71
72
- modules_enable_autodetect: true,
73
- modules_enable_all: true,
74
- modules: {},
72
+ modules_enable_autodetect: true,
73
+ modules_enable_all: true,
74
+ modules: {},
75
});
76
netdata.options.config_filename = pluginConfig(__filename);
77
78
// load configuration file
79
try {
80
- netdata.options_loaded = JSON.parse(fs.readFileSync(netdata.options.config_filename, 'utf8'));
81
- extend(true, netdata.options, netdata.options_loaded);
82
- console.error('merged netdata object:');
83
- console.error(netdata);
80
+ netdata.options_loaded = JSON.parse(fs.readFileSync(netdata.options.config_filename, 'utf8'));
81
+ extend(true, netdata.options, netdata.options_loaded);
82
+ console.error('merged netdata object:');
83
+ console.error(netdata);
84
}
85
catch(e) {
86
- netdata.error('Cannot read configuration file ' + netdata.options.config_filename + ': ' + e.message + ', using internal defaults.');
87
- netdata.options_loaded = undefined;
88
- dumpError(e);
86
+ netdata.error('Cannot read configuration file ' + netdata.options.config_filename + ': ' + e.message + ', using internal defaults.');
87
+ netdata.options_loaded = undefined;
88
+ dumpError(e);
89
}
90
91
92
// apply module paths to node.js process
93
function applyModulePaths() {
94
- var len = netdata.options.paths.modules.length;
95
- while(len--)
96
- process.mainModule.paths.unshift(netdata.options.paths.modules[len]);
94
+ var len = netdata.options.paths.modules.length;
95
+ while(len--)
96
+ process.mainModule.paths.unshift(netdata.options.paths.modules[len]);
97
}
98
applyModulePaths();
99
@@ -102,165 +102,165 @@ applyModulePaths();
102
// tracing
103
104
function dumpError(err) {
105
- if (typeof err === 'object') {
106
- if (err.stack) {
107
- netdata.debug(err.stack);
108
- }
109
- }
105
+ if (typeof err === 'object') {
106
+ if (err.stack) {
107
+ netdata.debug(err.stack);
108
+ }
109
+ }
110
}
111
112
// --------------------------------------------------------------------------------------------------------------------
113
// get command line arguments
114
{
115
- var found_myself = false;
116
- var found_number = false;
117
- var found_modules = false;
118
- process.argv.forEach(function (val, index, array) {
119
- netdata.debug('PARAM: ' + val);
120
-
121
- if(!found_myself) {
122
- if(val === __filename)
123
- found_myself = true;
124
- }
125
- else {
126
- switch(val) {
127
- case 'debug':
128
- netdata.options.DEBUG = true;
129
- netdata.debug('DEBUG enabled');
130
- break;
131
-
132
- default:
133
- if(found_number === true) {
134
- if(found_modules === false) {
135
- for(var i in netdata.options.modules)
136
- netdata.options.modules[i].enabled = false;
137
- }
138
-
139
- if(typeof netdata.options.modules[val] === 'undefined')
140
- netdata.options.modules[val] = {};
141
-
142
- netdata.options.modules[val].enabled = true;
143
- netdata.options.modules_enable_all = false;
144
- netdata.debug('enabled module ' + val);
145
- }
146
- else {
147
- try {
148
- var x = parseInt(val);
149
- if(x > 0) {
150
- netdata.options.update_every = x;
151
- if(netdata.options.update_every < NETDATA_UPDATE_EVERY) {
152
- netdata.options.update_every = NETDATA_UPDATE_EVERY;
153
- netdata.debug('Update frequency ' + x + 's is too low');
154
- }
155
-
156
- found_number = true;
157
- netdata.debug('Update frequency set to ' + netdata.options.update_every + ' seconds');
158
- }
159
- else netdata.error('Ignoring parameter: ' + val);
160
- }
161
- catch(e) {
162
- netdata.error('Cannot get value of parameter: ' + val);
163
- dumpError(e);
164
- }
165
- }
166
- break;
167
- }
168
- }
169
- });
115
+ var found_myself = false;
116
+ var found_number = false;
117
+ var found_modules = false;
118
+ process.argv.forEach(function (val, index, array) {
119
+ netdata.debug('PARAM: ' + val);
120
+
121
+ if(!found_myself) {
122
+ if(val === __filename)
123
+ found_myself = true;
124
+ }
125
+ else {
126
+ switch(val) {
127
+ case 'debug':
128
+ netdata.options.DEBUG = true;
129
+ netdata.debug('DEBUG enabled');
130
+ break;
131
+
132
+ default:
133
+ if(found_number === true) {
134
+ if(found_modules === false) {
135
+ for(var i in netdata.options.modules)
136
+ netdata.options.modules[i].enabled = false;
137
+ }
138
+
139
+ if(typeof netdata.options.modules[val] === 'undefined')
140
+ netdata.options.modules[val] = {};
141
+
142
+ netdata.options.modules[val].enabled = true;
143
+ netdata.options.modules_enable_all = false;
144
+ netdata.debug('enabled module ' + val);
145
+ }
146
+ else {
147
+ try {
148
+ var x = parseInt(val);
149
+ if(x > 0) {
150
+ netdata.options.update_every = x;
151
+ if(netdata.options.update_every < NETDATA_UPDATE_EVERY) {
152
+ netdata.options.update_every = NETDATA_UPDATE_EVERY;
153
+ netdata.debug('Update frequency ' + x + 's is too low');
154
+ }
155
+
156
+ found_number = true;
157
+ netdata.debug('Update frequency set to ' + netdata.options.update_every + ' seconds');
158
+ }
159
+ else netdata.error('Ignoring parameter: ' + val);
160
+ }
161
+ catch(e) {
162
+ netdata.error('Cannot get value of parameter: ' + val);
163
+ dumpError(e);
164
+ }
165
+ }
166
+ break;
167
+ }
168
+ }
169
+ });
170
}
171
172
if(netdata.options.update_every < 1) {
173
- netdata.debug('Adjusting update frequency to 1 second');
174
- netdata.options.update_every = 1;
173
+ netdata.debug('Adjusting update frequency to 1 second');
174
+ netdata.options.update_every = 1;
175
}
176
177
// --------------------------------------------------------------------------------------------------------------------
178
// find modules
179
180
function findModules() {
181
- var found = 0;
182
-
183
- var files = fs.readdirSync(NODE_D_DIR);
184
- var len = files.length;
185
- while(len--) {
186
- var m = files[len].match('.node.js' + '$');
187
- if(m !== null) {
188
- var n = files[len].substring(0, m.index);
189
-
190
- if(typeof(netdata.options.modules[n]) === 'undefined')
191
- netdata.options.modules[n] = { name: n, enabled: netdata.options.modules_enable_all };
192
-
193
- if(netdata.options.modules[n].enabled === true) {
194
- netdata.options.modules[n].name = n;
195
- netdata.options.modules[n].filename = NODE_D_DIR + '/' + files[len];
196
- netdata.options.modules[n].loaded = false;
197
-
198
- if(typeof(netdata.options.modules[n].config_filename) !== 'string')
199
- netdata.options.modules[n].config_filename = pluginConfig(files[len]);
200
-
201
- // load the module
202
- try {
203
- netdata.debug('loading module ' + netdata.options.modules[n].filename);
204
- netdata.options.modules[n].module = require(netdata.options.modules[n].filename);
205
- netdata.options.modules[n].module.name = n;
206
- netdata.debug('loaded module ' + netdata.options.modules[n].name + ' from ' + netdata.options.modules[n].filename);
207
- }
208
- catch(e) {
209
- netdata.options.modules[n].enabled = false;
210
- netdata.error('Cannot load module: ' + netdata.options.modules[n].filename + ' exception: ' + e);
211
- dumpError(e);
212
- continue;
213
- }
214
-
215
- // load its configuration
216
- var c = {
217
- enable_autodetect: netdata.options.modules_enable_autodetect,
218
- update_every: netdata.options.update_every
219
- };
220
- try {
221
- netdata.debug('loading module\'s ' + netdata.options.modules[n].name + ' config ' + netdata.options.modules[n].config_filename);
222
- var c2 = JSON.parse(fs.readFileSync(netdata.options.modules[n].config_filename, 'utf8'));
223
- extend(true, c, c2);
224
- netdata.debug('loaded module\'s ' + netdata.options.modules[n].name + ' config ' + netdata.options.modules[n].config_filename);
225
- }
226
- catch(e) {
227
- netdata.error('Cannot load module\'s ' + netdata.options.modules[n].name + ' config from ' + netdata.options.modules[n].config_filename + ' exception: ' + e + ', using internal defaults.');
228
- dumpError(e);
229
- }
230
-
231
- // call module auto-detection / configuration
232
- try {
233
- netdata.modules_configuring++;
234
- netdata.debug('Configuring module ' + netdata.options.modules[n].name);
235
- var serv = netdata.configure(netdata.options.modules[n].module, c, function() {
236
- netdata.debug('Configured module ' + netdata.options.modules[n].name);
237
- netdata.modules_configuring--;
238
- });
239
-
240
- netdata.debug('Configuring module ' + netdata.options.modules[n].name + ' reports ' + serv + ' eligible services.');
241
- }
242
- catch(e) {
243
- netdata.modules_configuring--;
244
- netdata.options.modules[n].enabled = false;
245
- netdata.error('Failed module auto-detection: ' + netdata.options.modules[n].name + ' exception: ' + e + ', disabling module.');
246
- dumpError(e);
247
- continue;
248
- }
249
-
250
- netdata.options.modules[n].loaded = true;
251
- found++;
252
- }
253
- }
254
- }
255
-
256
- // netdata.debug(netdata.options.modules);
257
- return found;
181
+ var found = 0;
182
+
183
+ var files = fs.readdirSync(NODE_D_DIR);
184
+ var len = files.length;
185
+ while(len--) {
186
+ var m = files[len].match('.node.js' + '$');
187
+ if(m !== null) {
188
+ var n = files[len].substring(0, m.index);
189
+
190
+ if(typeof(netdata.options.modules[n]) === 'undefined')
191
+ netdata.options.modules[n] = { name: n, enabled: netdata.options.modules_enable_all };
192
+
193
+ if(netdata.options.modules[n].enabled === true) {
194
+ netdata.options.modules[n].name = n;
195
+ netdata.options.modules[n].filename = NODE_D_DIR + '/' + files[len];
196
+ netdata.options.modules[n].loaded = false;
197
+
198
+ if(typeof(netdata.options.modules[n].config_filename) !== 'string')
199
+ netdata.options.modules[n].config_filename = pluginConfig(files[len]);
200
+
201
+ // load the module
202
+ try {
203
+ netdata.debug('loading module ' + netdata.options.modules[n].filename);
204
+ netdata.options.modules[n].module = require(netdata.options.modules[n].filename);
205
+ netdata.options.modules[n].module.name = n;
206
+ netdata.debug('loaded module ' + netdata.options.modules[n].name + ' from ' + netdata.options.modules[n].filename);
207
+ }
208
+ catch(e) {
209
+ netdata.options.modules[n].enabled = false;
210
+ netdata.error('Cannot load module: ' + netdata.options.modules[n].filename + ' exception: ' + e);
211
+ dumpError(e);
212
+ continue;
213
+ }
214
+
215
+ // load its configuration
216
+ var c = {
217
+ enable_autodetect: netdata.options.modules_enable_autodetect,
218
+ update_every: netdata.options.update_every
219
+ };
220
+ try {
221
+ netdata.debug('loading module\'s ' + netdata.options.modules[n].name + ' config ' + netdata.options.modules[n].config_filename);
222
+ var c2 = JSON.parse(fs.readFileSync(netdata.options.modules[n].config_filename, 'utf8'));
223
+ extend(true, c, c2);
224
+ netdata.debug('loaded module\'s ' + netdata.options.modules[n].name + ' config ' + netdata.options.modules[n].config_filename);
225
+ }
226
+ catch(e) {
227
+ netdata.error('Cannot load module\'s ' + netdata.options.modules[n].name + ' config from ' + netdata.options.modules[n].config_filename + ' exception: ' + e + ', using internal defaults.');
228
+ dumpError(e);
229
+ }
230
+
231
+ // call module auto-detection / configuration
232
+ try {
233
+ netdata.modules_configuring++;
234
+ netdata.debug('Configuring module ' + netdata.options.modules[n].name);
235
+ var serv = netdata.configure(netdata.options.modules[n].module, c, function() {
236
+ netdata.debug('Configured module ' + netdata.options.modules[n].name);
237
+ netdata.modules_configuring--;
238
+ });
239
+
240
+ netdata.debug('Configuring module ' + netdata.options.modules[n].name + ' reports ' + serv + ' eligible services.');
241
+ }
242
+ catch(e) {
243
+ netdata.modules_configuring--;
244
+ netdata.options.modules[n].enabled = false;
245
+ netdata.error('Failed module auto-detection: ' + netdata.options.modules[n].name + ' exception: ' + e + ', disabling module.');
246
+ dumpError(e);
247
+ continue;
248
+ }
249
+
250
+ netdata.options.modules[n].loaded = true;
251
+ found++;
252
+ }
253
+ }
254
+ }
255
+
256
+ // netdata.debug(netdata.options.modules);
257
+ return found;
258
}
259
260
if(findModules() === 0) {
261
- netdata.error('Cannot load any .node.js module from: ' + NODE_D_DIR);
262
- netdata.disableNodePlugin();
263
- process.exit(1);
261
+ netdata.error('Cannot load any .node.js module from: ' + NODE_D_DIR);
262
+ netdata.disableNodePlugin();
263
+ process.exit(1);
264
}
265
266
@@ -268,14 +268,14 @@ if(findModules() === 0) {
268
// start
269
270
function start_when_configuring_ends() {
271
- if(netdata.modules_configuring > 0) {
272
- netdata.debug('Waiting modules configuration, still running ' + netdata.modules_configuring);
273
- setTimeout(start_when_configuring_ends, 500);
274
- return;
275
- }
276
-
277
- netdata.modules_configuring = 0;
278
- netdata.start();
271
+ if(netdata.modules_configuring > 0) {
272
+ netdata.debug('Waiting modules configuration, still running ' + netdata.modules_configuring);
273
+ setTimeout(start_when_configuring_ends, 500);
274
+ return;
275
+ }
276
+
277
+ netdata.modules_configuring = 0;
278
+ netdata.start();
279
}
280
start_when_configuring_ends();
281
plugins.d/tc-qos-helper.sh
+52
-52
@@ -23,21 +23,21 @@ update_every=$((t))
23
24
# allow the user to override our defaults
25
if [ -f "${config_dir}/tc-qos-helper.conf" ]
26
- then
27
- source "${config_dir}/tc-qos-helper.conf"
26
+ then
27
+ source "${config_dir}/tc-qos-helper.conf"
28
fi
29
30
# default time function
31
now_ms=
32
current_time_ms() {
33
- now_ms="$(date +'%s')000"
33
+ now_ms="$(date +'%s')000"
34
}
35
36
# default sleep function
37
LOOPSLEEPMS_LASTWORK=0
38
loopsleepms() {
39
- [ "$1" = "tellwork" ] && shift
40
- sleep $1
39
+ [ "$1" = "tellwork" ] && shift
40
+ sleep $1
41
}
42
43
# if found and included, this file overwrites loopsleepms()
@@ -45,49 +45,49 @@ loopsleepms() {
45
. "${plugins_dir}/loopsleepms.sh.inc"
46
47
if [ -z "${tc}" -o ! -x "${tc}" ]
48
- then
49
- echo >&2 "${PROGRAM_NAME}: Cannot find command 'tc' in this system."
50
- exit 1
48
+ then
49
+ echo >&2 "${PROGRAM_NAME}: Cannot find command 'tc' in this system."
50
+ exit 1
51
fi
52
53
devices=
54
fix_names=
55
56
setclassname() {
57
- echo "SETCLASSNAME $3 $2"
57
+ echo "SETCLASSNAME $3 $2"
58
}
59
60
show_tc() {
61
- local x="${1}" interface_dev interface_classes interface_classes_monitor
62
-
63
- echo "BEGIN ${x}"
64
- ${tc} -s class show dev ${x}
65
-
66
- # check FireQOS names for classes
67
- if [ ! -z "${fix_names}" -a -f "${fireqos_run_dir}/ifaces/${x}" ]
68
- then
69
- name="$(<"${fireqos_run_dir}/ifaces/${x}")"
70
- echo "SETDEVICENAME ${name}"
71
-
72
- interface_dev=
73
- interface_classes=
74
- interface_classes_monitor=
75
- source "${fireqos_run_dir}/${name}.conf"
76
- for n in ${interface_classes_monitor}
77
- do
78
- setclassname ${n//|/ }
79
- done
80
- [ ! -z "${interface_dev}" ] && echo "SETDEVICEGROUP ${interface_dev}"
81
- fi
82
- echo "END ${x}"
61
+ local x="${1}" interface_dev interface_classes interface_classes_monitor
62
+
63
+ echo "BEGIN ${x}"
64
+ ${tc} -s class show dev ${x}
65
+
66
+ # check FireQOS names for classes
67
+ if [ ! -z "${fix_names}" -a -f "${fireqos_run_dir}/ifaces/${x}" ]
68
+ then
69
+ name="$(<"${fireqos_run_dir}/ifaces/${x}")"
70
+ echo "SETDEVICENAME ${name}"
71
+
72
+ interface_dev=
73
+ interface_classes=
74
+ interface_classes_monitor=
75
+ source "${fireqos_run_dir}/${name}.conf"
76
+ for n in ${interface_classes_monitor}
77
+ do
78
+ setclassname ${n//|/ }
79
+ done
80
+ [ ! -z "${interface_dev}" ] && echo "SETDEVICEGROUP ${interface_dev}"
81
+ fi
82
+ echo "END ${x}"
83
}
84
85
all_devices() {
86
- cat /proc/net/dev | grep ":" | cut -d ':' -f 1 | while read dev
87
- do
88
- l=$(${tc} class show dev ${dev} | wc -l)
89
- [ $l -ne 0 ] && echo ${dev}
90
- done
86
+ cat /proc/net/dev | grep ":" | cut -d ':' -f 1 | while read dev
87
+ do
88
+ l=$(${tc} class show dev ${dev} | wc -l)
89
+ [ $l -ne 0 ] && echo ${dev}
90
+ done
91
}
92
93
# update devices and class names
@@ -102,25 +102,25 @@ c=0
102
gc=0
103
while [ 1 ]
104
do
105
- fix_names=
106
- c=$((c + 1))
107
- gc=$((gc + 1))
105
+ fix_names=
106
+ c=$((c + 1))
107
+ gc=$((gc + 1))
108
109
- if [ ${c} -le 1 -o ${c} -ge ${names_every} ]
110
- then
111
- c=1
112
- fix_names="YES"
113
- devices="$( all_devices )"
114
- fi
109
+ if [ ${c} -le 1 -o ${c} -ge ${names_every} ]
110
+ then
111
+ c=1
112
+ fix_names="YES"
113
+ devices="$( all_devices )"
114
+ fi
115
116
- for d in ${devices}
117
- do
118
- show_tc ${d}
119
- done
116
+ for d in ${devices}
117
+ do
118
+ show_tc ${d}
119
+ done
120
121
- echo "WORKTIME ${LOOPSLEEPMS_LASTWORK}"
121
+ echo "WORKTIME ${LOOPSLEEPMS_LASTWORK}"
122
123
- loopsleepms ${update_every}
123
+ loopsleepms ${update_every}
124
125
- [ ${gc} -gt ${exit_after} ] && exit 0
125
+ [ ${gc} -gt ${exit_after} ] && exit 0
126
done
src/appconfig.c
+324
-324
@@ -13,33 +13,33 @@ pthread_mutex_t config_mutex = PTHREAD_MUTEX_INITIALIZER;
13
#define CONFIG_VALUE_CHECKED 0x08 // has been checked if the value is different from the default
14
15
struct config_value {
16
- avl avl; // the index - this has to be first!
16
+ avl avl; // the index - this has to be first!
17
18
- uint8_t flags;
19
- uint32_t hash; // a simple hash to speed up searching
20
- // we first compare hashes, and only if the hashes are equal we do string comparisons
18
+ uint8_t flags;
19
+ uint32_t hash; // a simple hash to speed up searching
20
+ // we first compare hashes, and only if the hashes are equal we do string comparisons
21
22
- char *name;
23
- char *value;
22
+ char *name;
23
+ char *value;
24
25
- struct config_value *next; // config->mutex protects just this
25
+ struct config_value *next; // config->mutex protects just this
26
};
27
28
struct config {
29
- avl avl;
29
+ avl avl;
30
31
- uint32_t hash; // a simple hash to speed up searching
32
- // we first compare hashes, and only if the hashes are equal we do string comparisons
31
+ uint32_t hash; // a simple hash to speed up searching
32
+ // we first compare hashes, and only if the hashes are equal we do string comparisons
33
34
- char *name;
34
+ char *name;
35
36
- struct config *next; // gloabl config_mutex protects just this
36
+ struct config *next; // gloabl config_mutex protects just this
37
38
- struct config_value *values;
39
- avl_tree_lock values_index;
38
+ struct config_value *values;
39
+ avl_tree_lock values_index;
40
41
- pthread_mutex_t mutex; // this locks only the writers, to ensure atomic updates
42
- // readers are protected using the rwlock in avl_tree_lock
41
+ pthread_mutex_t mutex; // this locks only the writers, to ensure atomic updates
42
+ // readers are protected using the rwlock in avl_tree_lock
43
} *config_root = NULL;
44
45
@@ -47,19 +47,19 @@ struct config {
47
// locking
48
49
static inline void config_global_write_lock(void) {
50
- pthread_mutex_lock(&config_mutex);
50
+ pthread_mutex_lock(&config_mutex);
51
}
52
53
static inline void config_global_unlock(void) {
54
- pthread_mutex_unlock(&config_mutex);
54
+ pthread_mutex_unlock(&config_mutex);
55
}
56
57
static inline void config_section_write_lock(struct config *co) {
58
- pthread_mutex_lock(&co->mutex);
58
+ pthread_mutex_lock(&co->mutex);
59
}
60
61
static inline void config_section_unlock(struct config *co) {
62
- pthread_mutex_unlock(&co->mutex);
62
+ pthread_mutex_unlock(&co->mutex);
63
}
64
65
@@ -67,20 +67,20 @@ static inline void config_section_unlock(struct config *co) {
67
// config name-value index
68
69
static int config_value_compare(void* a, void* b) {
70
- if(((struct config_value *)a)->hash < ((struct config_value *)b)->hash) return -1;
71
- else if(((struct config_value *)a)->hash > ((struct config_value *)b)->hash) return 1;
72
- else return strcmp(((struct config_value *)a)->name, ((struct config_value *)b)->name);
70
+ if(((struct config_value *)a)->hash < ((struct config_value *)b)->hash) return -1;
71
+ else if(((struct config_value *)a)->hash > ((struct config_value *)b)->hash) return 1;
72
+ else return strcmp(((struct config_value *)a)->name, ((struct config_value *)b)->name);
73
}
74
75
#define config_value_index_add(co, cv) avl_insert_lock(&((co)->values_index), (avl *)(cv))
76
#define config_value_index_del(co, cv) avl_remove_lock(&((co)->values_index), (avl *)(cv))
77
78
static struct config_value *config_value_index_find(struct config *co, const char *name, uint32_t hash) {
79
- struct config_value tmp;
80
- tmp.hash = (hash)?hash:simple_hash(name);
81
- tmp.name = (char *)name;
79
+ struct config_value tmp;
80
+ tmp.hash = (hash)?hash:simple_hash(name);
81
+ tmp.name = (char *)name;
82
83
- return (struct config_value *)avl_search_lock(&(co->values_index), (avl *) &tmp);
83
+ return (struct config_value *)avl_search_lock(&(co->values_index), (avl *) &tmp);
84
}
85
86
@@ -88,25 +88,25 @@ static struct config_value *config_value_index_find(struct config *co, const cha
88
// config sections index
89
90
static int config_compare(void* a, void* b) {
91
- if(((struct config *)a)->hash < ((struct config *)b)->hash) return -1;
92
- else if(((struct config *)a)->hash > ((struct config *)b)->hash) return 1;
93
- else return strcmp(((struct config *)a)->name, ((struct config *)b)->name);
91
+ if(((struct config *)a)->hash < ((struct config *)b)->hash) return -1;
92
+ else if(((struct config *)a)->hash > ((struct config *)b)->hash) return 1;
93
+ else return strcmp(((struct config *)a)->name, ((struct config *)b)->name);
94
}
95
96
avl_tree_lock config_root_index = {
97
- { NULL, config_compare },
98
- AVL_LOCK_INITIALIZER
97
+ { NULL, config_compare },
98
+ AVL_LOCK_INITIALIZER
99
};
100
101
#define config_index_add(cfg) avl_insert_lock(&config_root_index, (avl *)(cfg))
102
#define config_index_del(cfg) avl_remove_lock(&config_root_index, (avl *)(cfg))
103
104
static struct config *config_index_find(const char *name, uint32_t hash) {
105
- struct config tmp;
106
- tmp.hash = (hash)?hash:simple_hash(name);
107
- tmp.name = (char *)name;
105
+ struct config tmp;
106
+ tmp.hash = (hash)?hash:simple_hash(name);
107
+ tmp.name = (char *)name;
108
109
- return (struct config *)avl_search_lock(&config_root_index, (avl *) &tmp);
109
+ return (struct config *)avl_search_lock(&config_root_index, (avl *) &tmp);
110
}
111
112
@@ -114,31 +114,31 @@ static struct config *config_index_find(const char *name, uint32_t hash) {
114
// config section methods
115
116
static inline struct config *config_section_find(const char *section) {
117
- return config_index_find(section, 0);
117
+ return config_index_find(section, 0);
118
}
119
120
static inline struct config *config_section_create(const char *section)
121
{
122
- debug(D_CONFIG, "Creating section '%s'.", section);
122
+ debug(D_CONFIG, "Creating section '%s'.", section);
123
124
- struct config *co = callocz(1, sizeof(struct config));
125
- co->name = strdupz(section);
126
- co->hash = simple_hash(co->name);
124
+ struct config *co = callocz(1, sizeof(struct config));
125
+ co->name = strdupz(section);
126
+ co->hash = simple_hash(co->name);
127
128
- avl_init_lock(&co->values_index, config_value_compare);
128
+ avl_init_lock(&co->values_index, config_value_compare);
129
130
- config_index_add(co);
130
+ config_index_add(co);
131
132
- config_global_write_lock();
133
- struct config *co2 = config_root;
134
- if(co2) {
135
- while (co2->next) co2 = co2->next;
136
- co2->next = co;
137
- }
138
- else config_root = co;
139
- config_global_unlock();
132
+ config_global_write_lock();
133
+ struct config *co2 = config_root;
134
+ if(co2) {
135
+ while (co2->next) co2 = co2->next;
136
+ co2->next = co;
137
+ }
138
+ else config_root = co;
139
+ config_global_unlock();
140
141
- return co;
141
+ return co;
142
}
143
144
@@ -147,221 +147,221 @@ static inline struct config *config_section_create(const char *section)
147
148
static inline struct config_value *config_value_create(struct config *co, const char *name, const char *value)
149
{
150
- debug(D_CONFIG, "Creating config entry for name '%s', value '%s', in section '%s'.", name, value, co->name);
150
+ debug(D_CONFIG, "Creating config entry for name '%s', value '%s', in section '%s'.", name, value, co->name);
151
152
- struct config_value *cv = callocz(1, sizeof(struct config_value));
153
- cv->name = strdupz(name);
154
- cv->hash = simple_hash(cv->name);
155
- cv->value = strdupz(value);
152
+ struct config_value *cv = callocz(1, sizeof(struct config_value));
153
+ cv->name = strdupz(name);
154
+ cv->hash = simple_hash(cv->name);
155
+ cv->value = strdupz(value);
156
157
- config_value_index_add(co, cv);
157
+ config_value_index_add(co, cv);
158
159
- config_section_write_lock(co);
160
- struct config_value *cv2 = co->values;
161
- if(cv2) {
162
- while (cv2->next) cv2 = cv2->next;
163
- cv2->next = cv;
164
- }
165
- else co->values = cv;
166
- config_section_unlock(co);
159
+ config_section_write_lock(co);
160
+ struct config_value *cv2 = co->values;
161
+ if(cv2) {
162
+ while (cv2->next) cv2 = cv2->next;
163
+ cv2->next = cv;
164
+ }
165
+ else co->values = cv;
166
+ config_section_unlock(co);
167
168
- return cv;
168
+ return cv;
169
}
170
171
int config_exists(const char *section, const char *name) {
172
- struct config_value *cv;
172
+ struct config_value *cv;
173
174
- debug(D_CONFIG, "request to get config in section '%s', name '%s'", section, name);
174
+ debug(D_CONFIG, "request to get config in section '%s', name '%s'", section, name);
175
176
- struct config *co = config_section_find(section);
177
- if(!co) return 0;
176
+ struct config *co = config_section_find(section);
177
+ if(!co) return 0;
178
179
- cv = config_value_index_find(co, name, 0);
180
- if(!cv) return 0;
179
+ cv = config_value_index_find(co, name, 0);
180
+ if(!cv) return 0;
181
182
- return 1;
182
+ return 1;
183
}
184
185
int config_rename(const char *section, const char *old, const char *new) {
186
- struct config_value *cv, *cv2;
186
+ struct config_value *cv, *cv2;
187
188
- debug(D_CONFIG, "request to rename config in section '%s', old name '%s', new name '%s'", section, old, new);
188
+ debug(D_CONFIG, "request to rename config in section '%s', old name '%s', new name '%s'", section, old, new);
189
190
- struct config *co = config_section_find(section);
191
- if(!co) return -1;
190
+ struct config *co = config_section_find(section);
191
+ if(!co) return -1;
192
193
- config_section_write_lock(co);
193
+ config_section_write_lock(co);
194
195
- cv = config_value_index_find(co, old, 0);
196
- if(!cv) goto cleanup;
195
+ cv = config_value_index_find(co, old, 0);
196
+ if(!cv) goto cleanup;
197
198
- cv2 = config_value_index_find(co, new, 0);
199
- if(cv2) goto cleanup;
198
+ cv2 = config_value_index_find(co, new, 0);
199
+ if(cv2) goto cleanup;
200
201
- config_value_index_del(co, cv);
201
+ config_value_index_del(co, cv);
202
203
- freez(cv->name);
204
- cv->name = strdupz(new);
203
+ freez(cv->name);
204
+ cv->name = strdupz(new);
205
206
- cv->hash = simple_hash(cv->name);
206
+ cv->hash = simple_hash(cv->name);
207
208
- config_value_index_add(co, cv);
209
- config_section_unlock(co);
208
+ config_value_index_add(co, cv);
209
+ config_section_unlock(co);
210
211
- return 0;
211
+ return 0;
212
213
cleanup:
214
- config_section_unlock(co);
215
- return -1;
214
+ config_section_unlock(co);
215
+ return -1;
216
}
217
218
char *config_get(const char *section, const char *name, const char *default_value)
219
{
220
- struct config_value *cv;
221
-
222
- debug(D_CONFIG, "request to get config in section '%s', name '%s', default_value '%s'", section, name, default_value);
223
-
224
- struct config *co = config_section_find(section);
225
- if(!co) co = config_section_create(section);
226
-
227
- cv = config_value_index_find(co, name, 0);
228
- if(!cv) {
229
- cv = config_value_create(co, name, default_value);
230
- if(!cv) return NULL;
231
- }
232
- cv->flags |= CONFIG_VALUE_USED;
233
-
234
- if((cv->flags & CONFIG_VALUE_LOADED) || (cv->flags & CONFIG_VALUE_CHANGED)) {
235
- // this is a loaded value from the config file
236
- // if it is different that the default, mark it
237
- if(!(cv->flags & CONFIG_VALUE_CHECKED)) {
238
- if(strcmp(cv->value, default_value) != 0) cv->flags |= CONFIG_VALUE_CHANGED;
239
- cv->flags |= CONFIG_VALUE_CHECKED;
240
- }
241
- }
242
-
243
- return(cv->value);
220
+ struct config_value *cv;
221
+
222
+ debug(D_CONFIG, "request to get config in section '%s', name '%s', default_value '%s'", section, name, default_value);
223
+
224
+ struct config *co = config_section_find(section);
225
+ if(!co) co = config_section_create(section);
226
+
227
+ cv = config_value_index_find(co, name, 0);
228
+ if(!cv) {
229
+ cv = config_value_create(co, name, default_value);
230
+ if(!cv) return NULL;
231
+ }
232
+ cv->flags |= CONFIG_VALUE_USED;
233
+
234
+ if((cv->flags & CONFIG_VALUE_LOADED) || (cv->flags & CONFIG_VALUE_CHANGED)) {
235
+ // this is a loaded value from the config file
236
+ // if it is different that the default, mark it
237
+ if(!(cv->flags & CONFIG_VALUE_CHECKED)) {
238
+ if(strcmp(cv->value, default_value) != 0) cv->flags |= CONFIG_VALUE_CHANGED;
239
+ cv->flags |= CONFIG_VALUE_CHECKED;
240
+ }
241
+ }
242
+
243
+ return(cv->value);
244
}
245
246
long long config_get_number(const char *section, const char *name, long long value)
247
{
248
- char buffer[100], *s;
249
- sprintf(buffer, "%lld", value);
248
+ char buffer[100], *s;
249
+ sprintf(buffer, "%lld", value);
250
251
- s = config_get(section, name, buffer);
252
- if(!s) return value;
251
+ s = config_get(section, name, buffer);
252
+ if(!s) return value;
253
254
- return strtoll(s, NULL, 0);
254
+ return strtoll(s, NULL, 0);
255
}
256
257
int config_get_boolean(const char *section, const char *name, int value)
258
{
259
- char *s;
260
- if(value) s = "yes";
261
- else s = "no";
259
+ char *s;
260
+ if(value) s = "yes";
261
+ else s = "no";
262
263
- s = config_get(section, name, s);
264
- if(!s) return value;
263
+ s = config_get(section, name, s);
264
+ if(!s) return value;
265
266
- if(!strcmp(s, "yes") || !strcmp(s, "auto") || !strcmp(s, "on demand")) return 1;
267
- return 0;
266
+ if(!strcmp(s, "yes") || !strcmp(s, "auto") || !strcmp(s, "on demand")) return 1;
267
+ return 0;
268
}
269
270
int config_get_boolean_ondemand(const char *section, const char *name, int value)
271
{
272
- char *s;
272
+ char *s;
273
274
- if(value == CONFIG_ONDEMAND_ONDEMAND)
275
- s = "auto";
274
+ if(value == CONFIG_ONDEMAND_ONDEMAND)
275
+ s = "auto";
276
277
- else if(value == CONFIG_ONDEMAND_NO)
278
- s = "no";
277
+ else if(value == CONFIG_ONDEMAND_NO)
278
+ s = "no";
279
280
- else
281
- s = "yes";
280
+ else
281
+ s = "yes";
282
283
- s = config_get(section, name, s);
284
- if(!s) return value;
283
+ s = config_get(section, name, s);
284
+ if(!s) return value;
285
286
- if(!strcmp(s, "yes"))
287
- return CONFIG_ONDEMAND_YES;
288
- else if(!strcmp(s, "no"))
289
- return CONFIG_ONDEMAND_NO;
290
- else if(!strcmp(s, "auto") || !strcmp(s, "on demand"))
291
- return CONFIG_ONDEMAND_ONDEMAND;
286
+ if(!strcmp(s, "yes"))
287
+ return CONFIG_ONDEMAND_YES;
288
+ else if(!strcmp(s, "no"))
289
+ return CONFIG_ONDEMAND_NO;
290
+ else if(!strcmp(s, "auto") || !strcmp(s, "on demand"))
291
+ return CONFIG_ONDEMAND_ONDEMAND;
292
293
- return value;
293
+ return value;
294
}
295
296
const char *config_set_default(const char *section, const char *name, const char *value)
297
{
298
- struct config_value *cv;
298
+ struct config_value *cv;
299
300
- debug(D_CONFIG, "request to set config in section '%s', name '%s', value '%s'", section, name, value);
300
+ debug(D_CONFIG, "request to set config in section '%s', name '%s', value '%s'", section, name, value);
301
302
- struct config *co = config_section_find(section);
303
- if(!co) return config_set(section, name, value);
302
+ struct config *co = config_section_find(section);
303
+ if(!co) return config_set(section, name, value);
304
305
- cv = config_value_index_find(co, name, 0);
306
- if(!cv) return config_set(section, name, value);
305
+ cv = config_value_index_find(co, name, 0);
306
+ if(!cv) return config_set(section, name, value);
307
308
- cv->flags |= CONFIG_VALUE_USED;
308
+ cv->flags |= CONFIG_VALUE_USED;
309
310
- if(cv->flags & CONFIG_VALUE_LOADED)
311
- return cv->value;
310
+ if(cv->flags & CONFIG_VALUE_LOADED)
311
+ return cv->value;
312
313
- if(strcmp(cv->value, value) != 0) {
314
- cv->flags |= CONFIG_VALUE_CHANGED;
313
+ if(strcmp(cv->value, value) != 0) {
314
+ cv->flags |= CONFIG_VALUE_CHANGED;
315
316
- freez(cv->value);
317
- cv->value = strdupz(value);
318
- }
316
+ freez(cv->value);
317
+ cv->value = strdupz(value);
318
+ }
319
320
- return cv->value;
320
+ return cv->value;
321
}
322
323
const char *config_set(const char *section, const char *name, const char *value)
324
{
325
- struct config_value *cv;
325
+ struct config_value *cv;
326
327
- debug(D_CONFIG, "request to set config in section '%s', name '%s', value '%s'", section, name, value);
327
+ debug(D_CONFIG, "request to set config in section '%s', name '%s', value '%s'", section, name, value);
328
329
- struct config *co = config_section_find(section);
330
- if(!co) co = config_section_create(section);
329
+ struct config *co = config_section_find(section);
330
+ if(!co) co = config_section_create(section);
331
332
- cv = config_value_index_find(co, name, 0);
333
- if(!cv) cv = config_value_create(co, name, value);
334
- cv->flags |= CONFIG_VALUE_USED;
332
+ cv = config_value_index_find(co, name, 0);
333
+ if(!cv) cv = config_value_create(co, name, value);
334
+ cv->flags |= CONFIG_VALUE_USED;
335
336
- if(strcmp(cv->value, value) != 0) {
337
- cv->flags |= CONFIG_VALUE_CHANGED;
336
+ if(strcmp(cv->value, value) != 0) {
337
+ cv->flags |= CONFIG_VALUE_CHANGED;
338
339
- freez(cv->value);
340
- cv->value = strdupz(value);
341
- }
339
+ freez(cv->value);
340
+ cv->value = strdupz(value);
341
+ }
342
343
- return value;
343
+ return value;
344
}
345
346
long long config_set_number(const char *section, const char *name, long long value)
347
{
348
- char buffer[100];
349
- sprintf(buffer, "%lld", value);
348
+ char buffer[100];
349
+ sprintf(buffer, "%lld", value);
350
351
- config_set(section, name, buffer);
351
+ config_set(section, name, buffer);
352
353
- return value;
353
+ return value;
354
}
355
356
int config_set_boolean(const char *section, const char *name, int value)
357
{
358
- char *s;
359
- if(value) s = "yes";
360
- else s = "no";
358
+ char *s;
359
+ if(value) s = "yes";
360
+ else s = "no";
361
362
- config_set(section, name, s);
362
+ config_set(section, name, s);
363
364
- return value;
364
+ return value;
365
}
366
367
@@ -370,151 +370,151 @@ int config_set_boolean(const char *section, const char *name, int value)
370
371
int load_config(char *filename, int overwrite_used)
372
{
373
- int line = 0;
374
- struct config *co = NULL;
375
-
376
- char buffer[CONFIG_FILE_LINE_MAX + 1], *s;
377
-
378
- if(!filename) filename = CONFIG_DIR "/" CONFIG_FILENAME;
379
- FILE *fp = fopen(filename, "r");
380
- if(!fp) {
381
- error("Cannot open file '%s'", filename);
382
- return 0;
383
- }
384
-
385
- while(fgets(buffer, CONFIG_FILE_LINE_MAX, fp) != NULL) {
386
- buffer[CONFIG_FILE_LINE_MAX] = '\0';
387
- line++;
388
-
389
- s = trim(buffer);
390
- if(!s) {
391
- debug(D_CONFIG, "Ignoring line %d, it is empty.", line);
392
- continue;
393
- }
394
-
395
- int len = (int) strlen(s);
396
- if(*s == '[' && s[len - 1] == ']') {
397
- // new section
398
- s[len - 1] = '\0';
399
- s++;
400
-
401
- co = config_section_find(s);
402
- if(!co) co = config_section_create(s);
403
-
404
- continue;
405
- }
406
-
407
- if(!co) {
408
- // line outside a section
409
- error("Ignoring line %d ('%s'), it is outside all sections.", line, s);
410
- continue;
411
- }
412
-
413
- char *name = s;
414
- char *value = strchr(s, '=');
415
- if(!value) {
416
- error("Ignoring line %d ('%s'), there is no = in it.", line, s);
417
- continue;
418
- }
419
- *value = '\0';
420
- value++;
421
-
422
- name = trim(name);
423
- value = trim(value);
424
-
425
- if(!name) {
426
- error("Ignoring line %d, name is empty.", line);
427
- continue;
428
- }
429
- if(!value) {
430
- debug(D_CONFIG, "Ignoring line %d, value is empty.", line);
431
- continue;
432
- }
433
-
434
- struct config_value *cv = config_value_index_find(co, name, 0);
435
-
436
- if(!cv) cv = config_value_create(co, name, value);
437
- else {
438
- if(((cv->flags & CONFIG_VALUE_USED) && overwrite_used) || !(cv->flags & CONFIG_VALUE_USED)) {
439
- debug(D_CONFIG, "Line %d, overwriting '%s/%s'.", line, co->name, cv->name);
440
- freez(cv->value);
441
- cv->value = strdupz(value);
442
- }
443
- else
444
- debug(D_CONFIG, "Ignoring line %d, '%s/%s' is already present and used.", line, co->name, cv->name);
445
- }
446
- cv->flags |= CONFIG_VALUE_LOADED;
447
- }
448
-
449
- fclose(fp);
450
-
451
- return 1;
373
+ int line = 0;
374
+ struct config *co = NULL;
375
+
376
+ char buffer[CONFIG_FILE_LINE_MAX + 1], *s;
377
+
378
+ if(!filename) filename = CONFIG_DIR "/" CONFIG_FILENAME;
379
+ FILE *fp = fopen(filename, "r");
380
+ if(!fp) {
381
+ error("Cannot open file '%s'", filename);
382
+ return 0;
383
+ }
384
+
385
+ while(fgets(buffer, CONFIG_FILE_LINE_MAX, fp) != NULL) {
386
+ buffer[CONFIG_FILE_LINE_MAX] = '\0';
387
+ line++;
388
+
389
+ s = trim(buffer);
390
+ if(!s) {
391
+ debug(D_CONFIG, "Ignoring line %d, it is empty.", line);
392
+ continue;
393
+ }
394
+
395
+ int len = (int) strlen(s);
396
+ if(*s == '[' && s[len - 1] == ']') {
397
+ // new section
398
+ s[len - 1] = '\0';
399
+ s++;
400
+
401
+ co = config_section_find(s);
402
+ if(!co) co = config_section_create(s);
403
+
404
+ continue;
405
+ }
406
+
407
+ if(!co) {
408
+ // line outside a section
409
+ error("Ignoring line %d ('%s'), it is outside all sections.", line, s);
410
+ continue;
411
+ }
412
+
413
+ char *name = s;
414
+ char *value = strchr(s, '=');
415
+ if(!value) {
416
+ error("Ignoring line %d ('%s'), there is no = in it.", line, s);
417
+ continue;
418
+ }
419
+ *value = '\0';
420
+ value++;
421
+
422
+ name = trim(name);
423
+ value = trim(value);
424
+
425
+ if(!name) {
426
+ error("Ignoring line %d, name is empty.", line);
427
+ continue;
428
+ }
429
+ if(!value) {
430
+ debug(D_CONFIG, "Ignoring line %d, value is empty.", line);
431
+ continue;
432
+ }
433
+
434
+ struct config_value *cv = config_value_index_find(co, name, 0);
435
+
436
+ if(!cv) cv = config_value_create(co, name, value);
437
+ else {
438
+ if(((cv->flags & CONFIG_VALUE_USED) && overwrite_used) || !(cv->flags & CONFIG_VALUE_USED)) {
439
+ debug(D_CONFIG, "Line %d, overwriting '%s/%s'.", line, co->name, cv->name);
440
+ freez(cv->value);
441
+ cv->value = strdupz(value);
442
+ }
443
+ else
444
+ debug(D_CONFIG, "Ignoring line %d, '%s/%s' is already present and used.", line, co->name, cv->name);
445
+ }
446
+ cv->flags |= CONFIG_VALUE_LOADED;
447
+ }
448
+
449
+ fclose(fp);
450
+
451
+ return 1;
452
}
453
454
void generate_config(BUFFER *wb, int only_changed)
455
{
456
- int i, pri;
457
- struct config *co;
458
- struct config_value *cv;
459
-
460
- for(i = 0; i < 3 ;i++) {
461
- switch(i) {
462
- case 0:
463
- buffer_strcat(wb,
464
- "# NetData Configuration\n"
465
- "# You can uncomment and change any of the options below.\n"
466
- "# The value shown in the commented settings, is the default value.\n"
467
- "\n# global netdata configuration\n");
468
- break;
469
-
470
- case 1:
471
- buffer_strcat(wb, "\n\n# per plugin configuration\n");
472
- break;
473
-
474
- case 2:
475
- buffer_strcat(wb, "\n\n# per chart configuration\n");
476
- break;
477
- }
478
-
479
- config_global_write_lock();
480
- for(co = config_root; co ; co = co->next) {
481
- if(strcmp(co->name, "global") == 0 || strcmp(co->name, "plugins") == 0 || strcmp(co->name, "registry") == 0) pri = 0;
482
- else if(strncmp(co->name, "plugin:", 7) == 0) pri = 1;
483
- else pri = 2;
484
-
485
- if(i == pri) {
486
- int used = 0;
487
- int changed = 0;
488
- int count = 0;
489
-
490
- config_section_write_lock(co);
491
- for(cv = co->values; cv ; cv = cv->next) {
492
- used += (cv->flags & CONFIG_VALUE_USED)?1:0;
493
- changed += (cv->flags & CONFIG_VALUE_CHANGED)?1:0;
494
- count++;
495
- }
496
- config_section_unlock(co);
497
-
498
- if(!count) continue;
499
- if(only_changed && !changed) continue;
500
-
501
- if(!used) {
502
- buffer_sprintf(wb, "\n# node '%s' is not used.", co->name);
503
- }
504
-
505
- buffer_sprintf(wb, "\n[%s]\n", co->name);
506
-
507
- config_section_write_lock(co);
508
- for(cv = co->values; cv ; cv = cv->next) {
509
-
510
- if(used && !(cv->flags & CONFIG_VALUE_USED)) {
511
- buffer_sprintf(wb, "\n\t# option '%s' is not used.\n", cv->name);
512
- }
513
- buffer_sprintf(wb, "\t%s%s = %s\n", ((!(cv->flags & CONFIG_VALUE_CHANGED)) && (cv->flags & CONFIG_VALUE_USED))?"# ":"", cv->name, cv->value);
514
- }
515
- config_section_unlock(co);
516
- }
517
- }
518
- config_global_unlock();
519
- }
456
+ int i, pri;
457
+ struct config *co;
458
+ struct config_value *cv;
459
+
460
+ for(i = 0; i < 3 ;i++) {
461
+ switch(i) {
462
+ case 0:
463
+ buffer_strcat(wb,
464
+ "# NetData Configuration\n"
465
+ "# You can uncomment and change any of the options below.\n"
466
+ "# The value shown in the commented settings, is the default value.\n"
467
+ "\n# global netdata configuration\n");
468
+ break;
469
+
470
+ case 1:
471
+ buffer_strcat(wb, "\n\n# per plugin configuration\n");
472
+ break;
473
+
474
+ case 2:
475
+ buffer_strcat(wb, "\n\n# per chart configuration\n");
476
+ break;
477
+ }
478
+
479
+ config_global_write_lock();
480
+ for(co = config_root; co ; co = co->next) {
481
+ if(strcmp(co->name, "global") == 0 || strcmp(co->name, "plugins") == 0 || strcmp(co->name, "registry") == 0) pri = 0;
482
+ else if(strncmp(co->name, "plugin:", 7) == 0) pri = 1;
483
+ else pri = 2;
484
+
485
+ if(i == pri) {
486
+ int used = 0;
487
+ int changed = 0;
488
+ int count = 0;
489
+
490
+ config_section_write_lock(co);
491
+ for(cv = co->values; cv ; cv = cv->next) {
492
+ used += (cv->flags & CONFIG_VALUE_USED)?1:0;
493
+ changed += (cv->flags & CONFIG_VALUE_CHANGED)?1:0;
494
+ count++;
495
+ }
496
+ config_section_unlock(co);
497
+
498
+ if(!count) continue;
499
+ if(only_changed && !changed) continue;
500
+
501
+ if(!used) {
502
+ buffer_sprintf(wb, "\n# node '%s' is not used.", co->name);
503
+ }
504
+
505
+ buffer_sprintf(wb, "\n[%s]\n", co->name);
506
+
507
+ config_section_write_lock(co);
508
+ for(cv = co->values; cv ; cv = cv->next) {
509
+
510
+ if(used && !(cv->flags & CONFIG_VALUE_USED)) {
511
+ buffer_sprintf(wb, "\n\t# option '%s' is not used.\n", cv->name);
512
+ }
513
+ buffer_sprintf(wb, "\t%s%s = %s\n", ((!(cv->flags & CONFIG_VALUE_CHANGED)) && (cv->flags & CONFIG_VALUE_USED))?"# ":"", cv->name, cv->value);
514
+ }
515
+ config_section_unlock(co);
516
+ }
517
+ }
518
+ config_global_unlock();
519
+ }
520
}
src/apps_plugin.c
+2331
-2331
@@ -36,7 +36,7 @@ int enable_guest_charts = 0;
36
// ----------------------------------------------------------------------------
37
38
void netdata_cleanup_and_exit(int ret) {
39
- exit(ret);
39
+ exit(ret);
40
}
41
42
@@ -45,55 +45,55 @@ void netdata_cleanup_and_exit(int ret) {
45
// to retrieve settings of the system
46
47
long get_system_cpus(void) {
48
- procfile *ff = NULL;
48
+ procfile *ff = NULL;
49
50
- int processors = 0;
50
+ int processors = 0;
51
52
- char filename[FILENAME_MAX + 1];
53
- snprintfz(filename, FILENAME_MAX, "%s/proc/stat", host_prefix);
52
+ char filename[FILENAME_MAX + 1];
53
+ snprintfz(filename, FILENAME_MAX, "%s/proc/stat", host_prefix);
54
55
- ff = procfile_open(filename, NULL, PROCFILE_FLAG_DEFAULT);
56
- if(!ff) return 1;
55
+ ff = procfile_open(filename, NULL, PROCFILE_FLAG_DEFAULT);
56
+ if(!ff) return 1;
57
58
- ff = procfile_readall(ff);
59
- if(!ff) {
60
- procfile_close(ff);
61
- return 1;
62
- }
58
+ ff = procfile_readall(ff);
59
+ if(!ff) {
60
+ procfile_close(ff);
61
+ return 1;
62
+ }
63
64
- unsigned int i;
65
- for(i = 0; i < procfile_lines(ff); i++) {
66
- if(!procfile_linewords(ff, i)) continue;
64
+ unsigned int i;
65
+ for(i = 0; i < procfile_lines(ff); i++) {
66
+ if(!procfile_linewords(ff, i)) continue;
67
68
- if(strncmp(procfile_lineword(ff, i, 0), "cpu", 3) == 0) processors++;
69
- }
70
- processors--;
71
- if(processors < 1) processors = 1;
68
+ if(strncmp(procfile_lineword(ff, i, 0), "cpu", 3) == 0) processors++;
69
+ }
70
+ processors--;
71
+ if(processors < 1) processors = 1;
72
73
- procfile_close(ff);
74
- return processors;
73
+ procfile_close(ff);
74
+ return processors;
75
}
76
77
pid_t get_system_pid_max(void) {
78
- procfile *ff = NULL;
79
- pid_t mpid = 32768;
80
-
81
- char filename[FILENAME_MAX + 1];
82
- snprintfz(filename, FILENAME_MAX, "%s/proc/sys/kernel/pid_max", host_prefix);
83
- ff = procfile_open(filename, NULL, PROCFILE_FLAG_DEFAULT);
84
- if(!ff) return mpid;
85
-
86
- ff = procfile_readall(ff);
87
- if(!ff) {
88
- procfile_close(ff);
89
- return mpid;
90
- }
78
+ procfile *ff = NULL;
79
+ pid_t mpid = 32768;
80
+
81
+ char filename[FILENAME_MAX + 1];
82
+ snprintfz(filename, FILENAME_MAX, "%s/proc/sys/kernel/pid_max", host_prefix);
83
+ ff = procfile_open(filename, NULL, PROCFILE_FLAG_DEFAULT);
84
+ if(!ff) return mpid;
85
+
86
+ ff = procfile_readall(ff);
87
+ if(!ff) {
88
+ procfile_close(ff);
89
+ return mpid;
90
+ }
91
92
- mpid = (pid_t)atoi(procfile_lineword(ff, 0, 0));
93
- if(!mpid) mpid = 32768;
92
+ mpid = (pid_t)atoi(procfile_lineword(ff, 0, 0));
93
+ if(!mpid) mpid = 32768;
94
95
- procfile_close(ff);
96
- return mpid;
95
+ procfile_close(ff);
96
+ return mpid;
97
}
98
99
// ----------------------------------------------------------------------------
@@ -101,68 +101,68 @@ pid_t get_system_pid_max(void) {
101
// target is the structure that process data are aggregated
102
103
struct target {
104
- char compare[MAX_COMPARE_NAME + 1];
105
- uint32_t comparehash;
106
- size_t comparelen;
107
-
108
- char id[MAX_NAME + 1];
109
- uint32_t idhash;
110
-
111
- char name[MAX_NAME + 1];
112
-
113
- uid_t uid;
114
- gid_t gid;
115
-
116
- unsigned long long minflt;
117
- unsigned long long cminflt;
118
- unsigned long long majflt;
119
- unsigned long long cmajflt;
120
- unsigned long long utime;
121
- unsigned long long stime;
122
- unsigned long long gtime;
123
- unsigned long long cutime;
124
- unsigned long long cstime;
125
- unsigned long long cgtime;
126
- unsigned long long num_threads;
127
- unsigned long long rss;
128
-
129
- unsigned long long statm_size;
130
- unsigned long long statm_resident;
131
- unsigned long long statm_share;
132
- unsigned long long statm_text;
133
- unsigned long long statm_lib;
134
- unsigned long long statm_data;
135
- unsigned long long statm_dirty;
136
-
137
- unsigned long long io_logical_bytes_read;
138
- unsigned long long io_logical_bytes_written;
139
- unsigned long long io_read_calls;
140
- unsigned long long io_write_calls;
141
- unsigned long long io_storage_bytes_read;
142
- unsigned long long io_storage_bytes_written;
143
- unsigned long long io_cancelled_write_bytes;
144
-
145
- int *fds;
146
- unsigned long long openfiles;
147
- unsigned long long openpipes;
148
- unsigned long long opensockets;
149
- unsigned long long openinotifies;
150
- unsigned long long openeventfds;
151
- unsigned long long opentimerfds;
152
- unsigned long long opensignalfds;
153
- unsigned long long openeventpolls;
154
- unsigned long long openother;
155
-
156
- unsigned long processes; // how many processes have been merged to this
157
- int exposed; // if set, we have sent this to netdata
158
- int hidden; // if set, we set the hidden flag on the dimension
159
- int debug;
160
- int ends_with;
161
- int starts_with; // if set, the compare string matches only the
162
- // beginning of the command
163
-
164
- struct target *target; // the one that will be reported to netdata
165
- struct target *next;
104
+ char compare[MAX_COMPARE_NAME + 1];
105
+ uint32_t comparehash;
106
+ size_t comparelen;
107
+
108
+ char id[MAX_NAME + 1];
109
+ uint32_t idhash;
110
+
111
+ char name[MAX_NAME + 1];
112
+
113
+ uid_t uid;
114
+ gid_t gid;
115
+
116
+ unsigned long long minflt;
117
+ unsigned long long cminflt;
118
+ unsigned long long majflt;
119
+ unsigned long long cmajflt;
120
+ unsigned long long utime;
121
+ unsigned long long stime;
122
+ unsigned long long gtime;
123
+ unsigned long long cutime;
124
+ unsigned long long cstime;
125
+ unsigned long long cgtime;
126
+ unsigned long long num_threads;
127
+ unsigned long long rss;
128
+
129
+ unsigned long long statm_size;
130
+ unsigned long long statm_resident;
131
+ unsigned long long statm_share;
132
+ unsigned long long statm_text;
133
+ unsigned long long statm_lib;
134
+ unsigned long long statm_data;
135
+ unsigned long long statm_dirty;
136
+
137
+ unsigned long long io_logical_bytes_read;
138
+ unsigned long long io_logical_bytes_written;
139
+ unsigned long long io_read_calls;
140
+ unsigned long long io_write_calls;
141
+ unsigned long long io_storage_bytes_read;
142
+ unsigned long long io_storage_bytes_written;
143
+ unsigned long long io_cancelled_write_bytes;
144
+
145
+ int *fds;
146
+ unsigned long long openfiles;
147
+ unsigned long long openpipes;
148
+ unsigned long long opensockets;
149
+ unsigned long long openinotifies;
150
+ unsigned long long openeventfds;
151
+ unsigned long long opentimerfds;
152
+ unsigned long long opensignalfds;
153
+ unsigned long long openeventpolls;
154
+ unsigned long long openother;
155
+
156
+ unsigned long processes; // how many processes have been merged to this
157
+ int exposed; // if set, we have sent this to netdata
158
+ int hidden; // if set, we set the hidden flag on the dimension
159
+ int debug;
160
+ int ends_with;
161
+ int starts_with; // if set, the compare string matches only the
162
+ // beginning of the command
163
+
164
+ struct target *target; // the one that will be reported to netdata
165
+ struct target *next;
166
};
167
168
@@ -179,214 +179,214 @@ struct target *groups_root_target = NULL;
179
180
struct target *get_users_target(uid_t uid)
181
{
182
- struct target *w;
183
- for(w = users_root_target ; w ; w = w->next)
184
- if(w->uid == uid) return w;
182
+ struct target *w;
183
+ for(w = users_root_target ; w ; w = w->next)
184
+ if(w->uid == uid) return w;
185
186
- w = callocz(sizeof(struct target), 1);
187
- snprintfz(w->compare, MAX_COMPARE_NAME, "%u", uid);
188
- w->comparehash = simple_hash(w->compare);
189
- w->comparelen = strlen(w->compare);
186
+ w = callocz(sizeof(struct target), 1);
187
+ snprintfz(w->compare, MAX_COMPARE_NAME, "%u", uid);
188
+ w->comparehash = simple_hash(w->compare);
189
+ w->comparelen = strlen(w->compare);
190
191
- snprintfz(w->id, MAX_NAME, "%u", uid);
192
- w->idhash = simple_hash(w->id);
191
+ snprintfz(w->id, MAX_NAME, "%u", uid);
192
+ w->idhash = simple_hash(w->id);
193
194
- struct passwd *pw = getpwuid(uid);
195
- if(!pw)
196
- snprintfz(w->name, MAX_NAME, "%u", uid);
197
- else
198
- snprintfz(w->name, MAX_NAME, "%s", pw->pw_name);
194
+ struct passwd *pw = getpwuid(uid);
195
+ if(!pw)
196
+ snprintfz(w->name, MAX_NAME, "%u", uid);
197
+ else
198
+ snprintfz(w->name, MAX_NAME, "%s", pw->pw_name);
199
200
- netdata_fix_chart_name(w->name);
200
+ netdata_fix_chart_name(w->name);
201
202
- w->uid = uid;
202
+ w->uid = uid;
203
204
- w->next = users_root_target;
205
- users_root_target = w;
204
+ w->next = users_root_target;
205
+ users_root_target = w;
206
207
- if(unlikely(debug))
208
- fprintf(stderr, "apps.plugin: added uid %u ('%s') target\n", w->uid, w->name);
207
+ if(unlikely(debug))
208
+ fprintf(stderr, "apps.plugin: added uid %u ('%s') target\n", w->uid, w->name);
209
210
- return w;
210
+ return w;
211
}
212
213
struct target *get_groups_target(gid_t gid)
214
{
215
- struct target *w;
216
- for(w = groups_root_target ; w ; w = w->next)
217
- if(w->gid == gid) return w;
215
+ struct target *w;
216
+ for(w = groups_root_target ; w ; w = w->next)
217
+ if(w->gid == gid) return w;
218
219
- w = callocz(sizeof(struct target), 1);
220
- snprintfz(w->compare, MAX_COMPARE_NAME, "%u", gid);
221
- w->comparehash = simple_hash(w->compare);
222
- w->comparelen = strlen(w->compare);
219
+ w = callocz(sizeof(struct target), 1);
220
+ snprintfz(w->compare, MAX_COMPARE_NAME, "%u", gid);
221
+ w->comparehash = simple_hash(w->compare);
222
+ w->comparelen = strlen(w->compare);
223
224
- snprintfz(w->id, MAX_NAME, "%u", gid);
225
- w->idhash = simple_hash(w->id);
224
+ snprintfz(w->id, MAX_NAME, "%u", gid);
225
+ w->idhash = simple_hash(w->id);
226
227
- struct group *gr = getgrgid(gid);
228
- if(!gr)
229
- snprintfz(w->name, MAX_NAME, "%u", gid);
230
- else
231
- snprintfz(w->name, MAX_NAME, "%s", gr->gr_name);
227
+ struct group *gr = getgrgid(gid);
228
+ if(!gr)
229
+ snprintfz(w->name, MAX_NAME, "%u", gid);
230
+ else
231
+ snprintfz(w->name, MAX_NAME, "%s", gr->gr_name);
232
233
- netdata_fix_chart_name(w->name);
233
+ netdata_fix_chart_name(w->name);
234
235
- w->gid = gid;
235
+ w->gid = gid;
236
237
- w->next = groups_root_target;
238
- groups_root_target = w;
237
+ w->next = groups_root_target;
238
+ groups_root_target = w;
239
240
- if(unlikely(debug))
241
- fprintf(stderr, "apps.plugin: added gid %u ('%s') target\n", w->gid, w->name);
240
+ if(unlikely(debug))
241
+ fprintf(stderr, "apps.plugin: added gid %u ('%s') target\n", w->gid, w->name);
242
243
- return w;
243
+ return w;
244
}
245
246
// find or create a new target
247
// there are targets that are just aggregated to other target (the second argument)
248
struct target *get_apps_groups_target(const char *id, struct target *target) {
249
- int tdebug = 0, thidden = 0, ends_with = 0;
250
- const char *nid = id;
251
-
252
- while(nid[0] == '-' || nid[0] == '+' || nid[0] == '*') {
253
- if(nid[0] == '-') thidden = 1;
254
- if(nid[0] == '+') tdebug = 1;
255
- if(nid[0] == '*') ends_with = 1;
256
- nid++;
257
- }
258
- uint32_t hash = simple_hash(id);
259
-
260
- struct target *w, *last = apps_groups_root_target;
261
- for(w = apps_groups_root_target ; w ; w = w->next) {
262
- if(w->idhash == hash && strncmp(nid, w->id, MAX_NAME) == 0)
263
- return w;
264
-
265
- last = w;
266
- }
267
-
268
- w = callocz(sizeof(struct target), 1);
269
- strncpyz(w->id, nid, MAX_NAME);
270
- w->idhash = simple_hash(w->id);
271
-
272
- strncpyz(w->name, nid, MAX_NAME);
273
-
274
- strncpyz(w->compare, nid, MAX_COMPARE_NAME);
275
- size_t len = strlen(w->compare);
276
- if(w->compare[len - 1] == '*') {
277
- w->compare[len - 1] = '\0';
278
- w->starts_with = 1;
279
- }
280
- w->ends_with = ends_with;
281
-
282
- if(w->starts_with && w->ends_with)
283
- proc_pid_cmdline_is_needed = 1;
284
-
285
- w->comparehash = simple_hash(w->compare);
286
- w->comparelen = strlen(w->compare);
287
-
288
- w->hidden = thidden;
289
- w->debug = tdebug;
290
- w->target = target;
291
-
292
- // append it, to maintain the order in apps_groups.conf
293
- if(last) last->next = w;
294
- else apps_groups_root_target = w;
295
-
296
- if(unlikely(debug))
297
- fprintf(stderr, "apps.plugin: ADDING TARGET ID '%s', process name '%s' (%s), aggregated on target '%s', options: %s %s\n"
298
- , w->id
299
- , w->compare, (w->starts_with && w->ends_with)?"substring":((w->starts_with)?"prefix":((w->ends_with)?"suffix":"exact"))
300
- , w->target?w->target->id:w->id
301
- , (w->hidden)?"hidden":"-"
302
- , (w->debug)?"debug":"-"
303
- );
304
-
305
- return w;
249
+ int tdebug = 0, thidden = 0, ends_with = 0;
250
+ const char *nid = id;
251
+
252
+ while(nid[0] == '-' || nid[0] == '+' || nid[0] == '*') {
253
+ if(nid[0] == '-') thidden = 1;
254
+ if(nid[0] == '+') tdebug = 1;
255
+ if(nid[0] == '*') ends_with = 1;
256
+ nid++;
257
+ }
258
+ uint32_t hash = simple_hash(id);
259
+
260
+ struct target *w, *last = apps_groups_root_target;
261
+ for(w = apps_groups_root_target ; w ; w = w->next) {
262
+ if(w->idhash == hash && strncmp(nid, w->id, MAX_NAME) == 0)
263
+ return w;
264
+
265
+ last = w;
266
+ }
267
+
268
+ w = callocz(sizeof(struct target), 1);
269
+ strncpyz(w->id, nid, MAX_NAME);
270
+ w->idhash = simple_hash(w->id);
271
+
272
+ strncpyz(w->name, nid, MAX_NAME);
273
+
274
+ strncpyz(w->compare, nid, MAX_COMPARE_NAME);
275
+ size_t len = strlen(w->compare);
276
+ if(w->compare[len - 1] == '*') {
277
+ w->compare[len - 1] = '\0';
278
+ w->starts_with = 1;
279
+ }
280
+ w->ends_with = ends_with;
281
+
282
+ if(w->starts_with && w->ends_with)
283
+ proc_pid_cmdline_is_needed = 1;
284
+
285
+ w->comparehash = simple_hash(w->compare);
286
+ w->comparelen = strlen(w->compare);
287
+
288
+ w->hidden = thidden;
289
+ w->debug = tdebug;
290
+ w->target = target;
291
+
292
+ // append it, to maintain the order in apps_groups.conf
293
+ if(last) last->next = w;
294
+ else apps_groups_root_target = w;
295
+
296
+ if(unlikely(debug))
297
+ fprintf(stderr, "apps.plugin: ADDING TARGET ID '%s', process name '%s' (%s), aggregated on target '%s', options: %s %s\n"
298
+ , w->id
299
+ , w->compare, (w->starts_with && w->ends_with)?"substring":((w->starts_with)?"prefix":((w->ends_with)?"suffix":"exact"))
300
+ , w->target?w->target->id:w->id
301
+ , (w->hidden)?"hidden":"-"
302
+ , (w->debug)?"debug":"-"
303
+ );
304
+
305
+ return w;
306
}
307
308
// read the apps_groups.conf file
309
int read_apps_groups_conf(const char *name)
310
{
311
- char filename[FILENAME_MAX + 1];
312
-
313
- snprintfz(filename, FILENAME_MAX, "%s/apps_%s.conf", config_dir, name);
311
+ char filename[FILENAME_MAX + 1];
312
315
- if(unlikely(debug))
316
- fprintf(stderr, "apps.plugin: process groups file: '%s'\n", filename);
313
+ snprintfz(filename, FILENAME_MAX, "%s/apps_%s.conf", config_dir, name);
314
318
- // ----------------------------------------
315
+ if(unlikely(debug))
316
+ fprintf(stderr, "apps.plugin: process groups file: '%s'\n", filename);
317
320
- procfile *ff = procfile_open(filename, " :\t", PROCFILE_FLAG_DEFAULT);
321
- if(!ff) return 1;
318
+ // ----------------------------------------
319
323
- procfile_set_quotes(ff, "'\"");
320
+ procfile *ff = procfile_open(filename, " :\t", PROCFILE_FLAG_DEFAULT);
321
+ if(!ff) return 1;
322
325
- ff = procfile_readall(ff);
326
- if(!ff) {
327
- procfile_close(ff);
328
- return 1;
329
- }
323
+ procfile_set_quotes(ff, "'\"");
324
331
- unsigned long line, lines = procfile_lines(ff);
332
-
333
- for(line = 0; line < lines ;line++) {
334
- unsigned long word, words = procfile_linewords(ff, line);
335
- struct target *w = NULL;
336
-
337
- char *t = procfile_lineword(ff, line, 0);
338
- if(!t || !*t) continue;
325
+ ff = procfile_readall(ff);
326
+ if(!ff) {
327
+ procfile_close(ff);
328
+ return 1;
329
+ }
330
340
- for(word = 0; word < words ;word++) {
341
- char *s = procfile_lineword(ff, line, word);
342
- if(!s || !*s) continue;
343
- if(*s == '#') break;
331
+ unsigned long line, lines = procfile_lines(ff);
332
345
- if(t == s) continue;
333
+ for(line = 0; line < lines ;line++) {
334
+ unsigned long word, words = procfile_linewords(ff, line);
335
+ struct target *w = NULL;
336
347
- struct target *n = get_apps_groups_target(s, w);
348
- if(!n) {
349
- error("Cannot create target '%s' (line %lu, word %lu)", s, line, word);
350
- continue;
351
- }
337
+ char *t = procfile_lineword(ff, line, 0);
338
+ if(!t || !*t) continue;
339
353
- if(!w) w = n;
354
- }
340
+ for(word = 0; word < words ;word++) {
341
+ char *s = procfile_lineword(ff, line, word);
342
+ if(!s || !*s) continue;
343
+ if(*s == '#') break;
344
356
- if(w) {
357
- int tdebug = 0, thidden = 0;
345
+ if(t == s) continue;
346
359
- while(t[0] == '-' || t[0] == '+') {
360
- if(t[0] == '-') thidden = 1;
361
- if(t[0] == '+') tdebug = 1;
362
- t++;
363
- }
347
+ struct target *n = get_apps_groups_target(s, w);
348
+ if(!n) {
349
+ error("Cannot create target '%s' (line %lu, word %lu)", s, line, word);
350
+ continue;
351
+ }
352
365
- strncpyz(w->name, t, MAX_NAME);
366
- w->hidden = thidden;
367
- w->debug = tdebug;
353
+ if(!w) w = n;
354
+ }
355
369
- if(unlikely(debug))
370
- fprintf(stderr, "apps.plugin: AGGREGATION TARGET NAME '%s' on ID '%s', process name '%s' (%s), aggregated on target '%s', options: %s %s\n"
371
- , w->name
372
- , w->id
373
- , w->compare, (w->starts_with && w->ends_with)?"substring":((w->starts_with)?"prefix":((w->ends_with)?"suffix":"exact"))
374
- , w->target?w->target->id:w->id
375
- , (w->hidden)?"hidden":"-"
376
- , (w->debug)?"debug":"-"
377
- );
378
- }
379
- }
356
+ if(w) {
357
+ int tdebug = 0, thidden = 0;
358
+
359
+ while(t[0] == '-' || t[0] == '+') {
360
+ if(t[0] == '-') thidden = 1;
361
+ if(t[0] == '+') tdebug = 1;
362
+ t++;
363
+ }
364
+
365
+ strncpyz(w->name, t, MAX_NAME);
366
+ w->hidden = thidden;
367
+ w->debug = tdebug;
368
+
369
+ if(unlikely(debug))
370
+ fprintf(stderr, "apps.plugin: AGGREGATION TARGET NAME '%s' on ID '%s', process name '%s' (%s), aggregated on target '%s', options: %s %s\n"
371
+ , w->name
372
+ , w->id
373
+ , w->compare, (w->starts_with && w->ends_with)?"substring":((w->starts_with)?"prefix":((w->ends_with)?"suffix":"exact"))
374
+ , w->target?w->target->id:w->id
375
+ , (w->hidden)?"hidden":"-"
376
+ , (w->debug)?"debug":"-"
377
+ );
378
+ }
379
+ }
380
381
- procfile_close(ff);
381
+ procfile_close(ff);
382
383
- apps_groups_default_target = get_apps_groups_target("p+!o@w#e$i^r&7*5(-i)l-o_", NULL); // match nothing
384
- if(!apps_groups_default_target)
385
- error("Cannot create default target");
386
- else
387
- strncpyz(apps_groups_default_target->name, "other", MAX_NAME);
383
+ apps_groups_default_target = get_apps_groups_target("p+!o@w#e$i^r&7*5(-i)l-o_", NULL); // match nothing
384
+ if(!apps_groups_default_target)
385
+ error("Cannot create default target");
386
+ else
387
+ strncpyz(apps_groups_default_target->name, "other", MAX_NAME);
388
389
- return 0;
389
+ return 0;
390
}
391
392
@@ -395,174 +395,174 @@ int read_apps_groups_conf(const char *name)
395
// see: man proc
396
397
struct pid_stat {
398
- int32_t pid;
399
- char comm[MAX_COMPARE_NAME + 1];
400
- char cmdline[MAX_CMDLINE + 1];
401
-
402
- // char state;
403
- int32_t ppid;
404
- // int32_t pgrp;
405
- // int32_t session;
406
- // int32_t tty_nr;
407
- // int32_t tpgid;
408
- // uint64_t flags;
409
-
410
- // these are raw values collected
411
- unsigned long long minflt_raw;
412
- unsigned long long cminflt_raw;
413
- unsigned long long majflt_raw;
414
- unsigned long long cmajflt_raw;
415
- unsigned long long utime_raw;
416
- unsigned long long stime_raw;
417
- unsigned long long gtime_raw; // guest_time
418
- unsigned long long cutime_raw;
419
- unsigned long long cstime_raw;
420
- unsigned long long cgtime_raw; // cguest_time
421
-
422
- // these are rates
423
- unsigned long long minflt;
424
- unsigned long long cminflt;
425
- unsigned long long majflt;
426
- unsigned long long cmajflt;
427
- unsigned long long utime;
428
- unsigned long long stime;
429
- unsigned long long gtime;
430
- unsigned long long cutime;
431
- unsigned long long cstime;
432
- unsigned long long cgtime;
433
-
434
- // int64_t priority;
435
- // int64_t nice;
436
- int32_t num_threads;
437
- // int64_t itrealvalue;
438
- // unsigned long long starttime;
439
- // unsigned long long vsize;
440
- unsigned long long rss;
441
- // unsigned long long rsslim;
442
- // unsigned long long starcode;
443
- // unsigned long long endcode;
444
- // unsigned long long startstack;
445
- // unsigned long long kstkesp;
446
- // unsigned long long kstkeip;
447
- // uint64_t signal;
448
- // uint64_t blocked;
449
- // uint64_t sigignore;
450
- // uint64_t sigcatch;
451
- // uint64_t wchan;
452
- // uint64_t nswap;
453
- // uint64_t cnswap;
454
- // int32_t exit_signal;
455
- // int32_t processor;
456
- // uint32_t rt_priority;
457
- // uint32_t policy;
458
- // unsigned long long delayacct_blkio_ticks;
459
-
460
- uid_t uid;
461
- gid_t gid;
462
-
463
- unsigned long long statm_size;
464
- unsigned long long statm_resident;
465
- unsigned long long statm_share;
466
- unsigned long long statm_text;
467
- unsigned long long statm_lib;
468
- unsigned long long statm_data;
469
- unsigned long long statm_dirty;
470
-
471
- unsigned long long io_logical_bytes_read_raw;
472
- unsigned long long io_logical_bytes_written_raw;
473
- unsigned long long io_read_calls_raw;
474
- unsigned long long io_write_calls_raw;
475
- unsigned long long io_storage_bytes_read_raw;
476
- unsigned long long io_storage_bytes_written_raw;
477
- unsigned long long io_cancelled_write_bytes_raw;
478
-
479
- unsigned long long io_logical_bytes_read;
480
- unsigned long long io_logical_bytes_written;
481
- unsigned long long io_read_calls;
482
- unsigned long long io_write_calls;
483
- unsigned long long io_storage_bytes_read;
484
- unsigned long long io_storage_bytes_written;
485
- unsigned long long io_cancelled_write_bytes;
486
-
487
- int *fds; // array of fds it uses
488
- int fds_size; // the size of the fds array
489
-
490
- int children_count; // number of processes directly referencing this
491
- int keep; // 1 when we need to keep this process in memory even after it exited
492
- int keeploops; // increases by 1 every time keep is 1 and updated 0
493
- int updated; // 1 when the process is currently running
494
- int merged; // 1 when it has been merged to its parent
495
- int new_entry; // 1 when this is a new process, just saw for the first time
496
- int read; // 1 when we have already read this process for this iteration
497
- int sortlist; // higher numbers = top on the process tree
498
- // each process gets a unique number
499
-
500
- struct target *target; // app_groups.conf targets
501
- struct target *user_target; // uid based targets
502
- struct target *group_target; // gid based targets
503
-
504
- unsigned long long stat_collected_usec;
505
- unsigned long long last_stat_collected_usec;
506
-
507
- unsigned long long io_collected_usec;
508
- unsigned long long last_io_collected_usec;
509
-
510
- char *stat_filename;
511
- char *statm_filename;
512
- char *io_filename;
513
- char *cmdline_filename;
514
-
515
- struct pid_stat *parent;
516
- struct pid_stat *prev;
517
- struct pid_stat *next;
398
+ int32_t pid;
399
+ char comm[MAX_COMPARE_NAME + 1];
400
+ char cmdline[MAX_CMDLINE + 1];
401
+
402
+ // char state;
403
+ int32_t ppid;
404
+ // int32_t pgrp;
405
+ // int32_t session;
406
+ // int32_t tty_nr;
407
+ // int32_t tpgid;
408
+ // uint64_t flags;
409
+
410
+ // these are raw values collected
411
+ unsigned long long minflt_raw;
412
+ unsigned long long cminflt_raw;
413
+ unsigned long long majflt_raw;
414
+ unsigned long long cmajflt_raw;
415
+ unsigned long long utime_raw;
416
+ unsigned long long stime_raw;
417
+ unsigned long long gtime_raw; // guest_time
418
+ unsigned long long cutime_raw;
419
+ unsigned long long cstime_raw;
420
+ unsigned long long cgtime_raw; // cguest_time
421
+
422
+ // these are rates
423
+ unsigned long long minflt;
424
+ unsigned long long cminflt;
425
+ unsigned long long majflt;
426
+ unsigned long long cmajflt;
427
+ unsigned long long utime;
428
+ unsigned long long stime;
429
+ unsigned long long gtime;
430
+ unsigned long long cutime;
431
+ unsigned long long cstime;
432
+ unsigned long long cgtime;
433
+
434
+ // int64_t priority;
435
+ // int64_t nice;
436
+ int32_t num_threads;
437
+ // int64_t itrealvalue;
438
+ // unsigned long long starttime;
439
+ // unsigned long long vsize;
440
+ unsigned long long rss;
441
+ // unsigned long long rsslim;
442
+ // unsigned long long starcode;
443
+ // unsigned long long endcode;
444
+ // unsigned long long startstack;
445
+ // unsigned long long kstkesp;
446
+ // unsigned long long kstkeip;
447
+ // uint64_t signal;
448
+ // uint64_t blocked;
449
+ // uint64_t sigignore;
450
+ // uint64_t sigcatch;
451
+ // uint64_t wchan;
452
+ // uint64_t nswap;
453
+ // uint64_t cnswap;
454
+ // int32_t exit_signal;
455
+ // int32_t processor;
456
+ // uint32_t rt_priority;
457
+ // uint32_t policy;
458
+ // unsigned long long delayacct_blkio_ticks;
459
+
460
+ uid_t uid;
461
+ gid_t gid;
462
+
463
+ unsigned long long statm_size;
464
+ unsigned long long statm_resident;
465
+ unsigned long long statm_share;
466
+ unsigned long long statm_text;
467
+ unsigned long long statm_lib;
468
+ unsigned long long statm_data;
469
+ unsigned long long statm_dirty;
470
+
471
+ unsigned long long io_logical_bytes_read_raw;
472
+ unsigned long long io_logical_bytes_written_raw;
473
+ unsigned long long io_read_calls_raw;
474
+ unsigned long long io_write_calls_raw;
475
+ unsigned long long io_storage_bytes_read_raw;
476
+ unsigned long long io_storage_bytes_written_raw;
477
+ unsigned long long io_cancelled_write_bytes_raw;
478
+
479
+ unsigned long long io_logical_bytes_read;
480
+ unsigned long long io_logical_bytes_written;
481
+ unsigned long long io_read_calls;
482
+ unsigned long long io_write_calls;
483
+ unsigned long long io_storage_bytes_read;
484
+ unsigned long long io_storage_bytes_written;
485
+ unsigned long long io_cancelled_write_bytes;
486
+
487
+ int *fds; // array of fds it uses
488
+ int fds_size; // the size of the fds array
489
+
490
+ int children_count; // number of processes directly referencing this
491
+ int keep; // 1 when we need to keep this process in memory even after it exited
492
+ int keeploops; // increases by 1 every time keep is 1 and updated 0
493
+ int updated; // 1 when the process is currently running
494
+ int merged; // 1 when it has been merged to its parent
495
+ int new_entry; // 1 when this is a new process, just saw for the first time
496
+ int read; // 1 when we have already read this process for this iteration
497
+ int sortlist; // higher numbers = top on the process tree
498
+ // each process gets a unique number
499
+
500
+ struct target *target; // app_groups.conf targets
501
+ struct target *user_target; // uid based targets
502
+ struct target *group_target; // gid based targets
503
+
504
+ unsigned long long stat_collected_usec;
505
+ unsigned long long last_stat_collected_usec;
506
+
507
+ unsigned long long io_collected_usec;
508
+ unsigned long long last_io_collected_usec;
509
+
510
+ char *stat_filename;
511
+ char *statm_filename;
512
+ char *io_filename;
513
+ char *cmdline_filename;
514
+
515
+ struct pid_stat *parent;
516
+ struct pid_stat *prev;
517
+ struct pid_stat *next;
518
} *root_of_pids = NULL, **all_pids;
519
520
long all_pids_count = 0;
521
522
struct pid_stat *get_pid_entry(pid_t pid) {
523
- if(all_pids[pid]) {
524
- all_pids[pid]->new_entry = 0;
525
- return all_pids[pid];
526
- }
523
+ if(all_pids[pid]) {
524
+ all_pids[pid]->new_entry = 0;
525
+ return all_pids[pid];
526
+ }
527
528
- all_pids[pid] = callocz(sizeof(struct pid_stat), 1);
529
- all_pids[pid]->fds = callocz(sizeof(int), 100);
530
- all_pids[pid]->fds_size = 100;
528
+ all_pids[pid] = callocz(sizeof(struct pid_stat), 1);
529
+ all_pids[pid]->fds = callocz(sizeof(int), 100);
530
+ all_pids[pid]->fds_size = 100;
531
532
- if(root_of_pids) root_of_pids->prev = all_pids[pid];
533
- all_pids[pid]->next = root_of_pids;
534
- root_of_pids = all_pids[pid];
532
+ if(root_of_pids) root_of_pids->prev = all_pids[pid];
533
+ all_pids[pid]->next = root_of_pids;
534
+ root_of_pids = all_pids[pid];
535
536
- all_pids[pid]->pid = pid;
537
- all_pids[pid]->new_entry = 1;
536
+ all_pids[pid]->pid = pid;
537
+ all_pids[pid]->new_entry = 1;
538
539
- all_pids_count++;
539
+ all_pids_count++;
540
541
- return all_pids[pid];
541
+ return all_pids[pid];
542
}
543
544
void del_pid_entry(pid_t pid) {
545
- if(!all_pids[pid]) {
546
- error("attempted to free pid %d that is not allocated.", pid);
547
- return;
548
- }
549
-
550
- if(unlikely(debug))
551
- fprintf(stderr, "apps.plugin: process %d %s exited, deleting it.\n", pid, all_pids[pid]->comm);
552
-
553
- if(root_of_pids == all_pids[pid]) root_of_pids = all_pids[pid]->next;
554
- if(all_pids[pid]->next) all_pids[pid]->next->prev = all_pids[pid]->prev;
555
- if(all_pids[pid]->prev) all_pids[pid]->prev->next = all_pids[pid]->next;
556
-
557
- if(all_pids[pid]->fds) freez(all_pids[pid]->fds);
558
- if(all_pids[pid]->stat_filename) freez(all_pids[pid]->stat_filename);
559
- if(all_pids[pid]->statm_filename) freez(all_pids[pid]->statm_filename);
560
- if(all_pids[pid]->io_filename) freez(all_pids[pid]->io_filename);
561
- if(all_pids[pid]->cmdline_filename) freez(all_pids[pid]->cmdline_filename);
562
- freez(all_pids[pid]);
563
-
564
- all_pids[pid] = NULL;
565
- all_pids_count--;
545
+ if(!all_pids[pid]) {
546
+ error("attempted to free pid %d that is not allocated.", pid);
547
+ return;
548
+ }
549
+
550
+ if(unlikely(debug))
551
+ fprintf(stderr, "apps.plugin: process %d %s exited, deleting it.\n", pid, all_pids[pid]->comm);
552
+
553
+ if(root_of_pids == all_pids[pid]) root_of_pids = all_pids[pid]->next;
554
+ if(all_pids[pid]->next) all_pids[pid]->next->prev = all_pids[pid]->prev;
555
+ if(all_pids[pid]->prev) all_pids[pid]->prev->next = all_pids[pid]->next;
556
+
557
+ if(all_pids[pid]->fds) freez(all_pids[pid]->fds);
558
+ if(all_pids[pid]->stat_filename) freez(all_pids[pid]->stat_filename);
559
+ if(all_pids[pid]->statm_filename) freez(all_pids[pid]->statm_filename);
560
+ if(all_pids[pid]->io_filename) freez(all_pids[pid]->io_filename);
561
+ if(all_pids[pid]->cmdline_filename) freez(all_pids[pid]->cmdline_filename);
562
+ freez(all_pids[pid]);
563
+
564
+ all_pids[pid] = NULL;
565
+ all_pids_count--;
566
}
567
568
@@ -570,160 +570,160 @@ void del_pid_entry(pid_t pid) {
570
// update pids from proc
571
572
int read_proc_pid_cmdline(struct pid_stat *p) {
573
-
574
- if(unlikely(!p->cmdline_filename)) {
575
- char filename[FILENAME_MAX + 1];
576
- snprintfz(filename, FILENAME_MAX, "%s/proc/%d/cmdline", host_prefix, p->pid);
577
- p->cmdline_filename = strdupz(filename);
578
- }
573
+
574
+ if(unlikely(!p->cmdline_filename)) {
575
+ char filename[FILENAME_MAX + 1];
576
+ snprintfz(filename, FILENAME_MAX, "%s/proc/%d/cmdline", host_prefix, p->pid);
577
+ p->cmdline_filename = strdupz(filename);
578
+ }
579
580
- int fd = open(p->cmdline_filename, O_RDONLY, 0666);
581
- if(unlikely(fd == -1)) goto cleanup;
580
+ int fd = open(p->cmdline_filename, O_RDONLY, 0666);
581
+ if(unlikely(fd == -1)) goto cleanup;
582
583
- ssize_t i, bytes = read(fd, p->cmdline, MAX_CMDLINE);
584
- close(fd);
583
+ ssize_t i, bytes = read(fd, p->cmdline, MAX_CMDLINE);
584
+ close(fd);
585
586
- if(unlikely(bytes <= 0)) goto cleanup;
586
+ if(unlikely(bytes <= 0)) goto cleanup;
587
588
- p->cmdline[bytes] = '\0';
589
- for(i = 0; i < bytes ; i++)
590
- if(unlikely(!p->cmdline[i])) p->cmdline[i] = ' ';
588
+ p->cmdline[bytes] = '\0';
589
+ for(i = 0; i < bytes ; i++)
590
+ if(unlikely(!p->cmdline[i])) p->cmdline[i] = ' ';
591
592
- if(unlikely(debug))
593
- fprintf(stderr, "Read file '%s' contents: %s\n", p->cmdline_filename, p->cmdline);
592
+ if(unlikely(debug))
593
+ fprintf(stderr, "Read file '%s' contents: %s\n", p->cmdline_filename, p->cmdline);
594
595
- return 0;
595
+ return 0;
596
597
cleanup:
598
- // copy the command to the command line
599
- strncpyz(p->cmdline, p->comm, MAX_CMDLINE);
600
- return 0;
598
+ // copy the command to the command line
599
+ strncpyz(p->cmdline, p->comm, MAX_CMDLINE);
600
+ return 0;
601
}
602
603
int read_proc_pid_ownership(struct pid_stat *p) {
604
- if(unlikely(!p->stat_filename)) {
605
- error("pid %d does not have a stat_filename", p->pid);
606
- return 1;
607
- }
604
+ if(unlikely(!p->stat_filename)) {
605
+ error("pid %d does not have a stat_filename", p->pid);
606
+ return 1;
607
+ }
608
609
- // ----------------------------------------
610
- // read uid and gid
609
+ // ----------------------------------------
610
+ // read uid and gid
611
612
- struct stat st;
613
- if(stat(p->stat_filename, &st) != 0) {
614
- error("Cannot stat file '%s'", p->stat_filename);
615
- return 1;
616
- }
612
+ struct stat st;
613
+ if(stat(p->stat_filename, &st) != 0) {
614
+ error("Cannot stat file '%s'", p->stat_filename);
615
+ return 1;
616
+ }
617
618
- p->uid = st.st_uid;
619
- p->gid = st.st_gid;
618
+ p->uid = st.st_uid;
619
+ p->gid = st.st_gid;
620
621
- return 0;
621
+ return 0;
622
}
623
624
int read_proc_pid_stat(struct pid_stat *p) {
625
- static procfile *ff = NULL;
626
-
627
- if(unlikely(!p->stat_filename)) {
628
- char filename[FILENAME_MAX + 1];
629
- snprintfz(filename, FILENAME_MAX, "%s/proc/%d/stat", host_prefix, p->pid);
630
- p->stat_filename = strdupz(filename);
631
- }
632
-
633
- int set_quotes = (!ff)?1:0;
634
-
635
- ff = procfile_reopen(ff, p->stat_filename, NULL, PROCFILE_FLAG_NO_ERROR_ON_FILE_IO);
636
- if(unlikely(!ff)) goto cleanup;
637
-
638
- // if(set_quotes) procfile_set_quotes(ff, "()");
639
- if(set_quotes) procfile_set_open_close(ff, "(", ")");
640
-
641
- ff = procfile_readall(ff);
642
- if(unlikely(!ff)) goto cleanup;
643
-
644
- p->last_stat_collected_usec = p->stat_collected_usec;
645
- p->stat_collected_usec = time_usec();
646
- file_counter++;
647
-
648
- // p->pid = atol(procfile_lineword(ff, 0, 0+i));
649
-
650
- strncpyz(p->comm, procfile_lineword(ff, 0, 1), MAX_COMPARE_NAME);
651
-
652
- // p->state = *(procfile_lineword(ff, 0, 2));
653
- p->ppid = (int32_t) atol(procfile_lineword(ff, 0, 3));
654
- // p->pgrp = atol(procfile_lineword(ff, 0, 4));
655
- // p->session = atol(procfile_lineword(ff, 0, 5));
656
- // p->tty_nr = atol(procfile_lineword(ff, 0, 6));
657
- // p->tpgid = atol(procfile_lineword(ff, 0, 7));
658
- // p->flags = strtoull(procfile_lineword(ff, 0, 8), NULL, 10);
659
-
660
- unsigned long long last;
661
-
662
- last = p->minflt_raw;
663
- p->minflt_raw = strtoull(procfile_lineword(ff, 0, 9), NULL, 10);
664
- p->minflt = (p->minflt_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
665
-
666
- last = p->cminflt_raw;
667
- p->cminflt_raw = strtoull(procfile_lineword(ff, 0, 10), NULL, 10);
668
- p->cminflt = (p->cminflt_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
669
-
670
- last = p->majflt_raw;
671
- p->majflt_raw = strtoull(procfile_lineword(ff, 0, 11), NULL, 10);
672
- p->majflt = (p->majflt_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
673
-
674
- last = p->cmajflt_raw;
675
- p->cmajflt_raw = strtoull(procfile_lineword(ff, 0, 12), NULL, 10);
676
- p->cmajflt = (p->cmajflt_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
677
-
678
- last = p->utime_raw;
679
- p->utime_raw = strtoull(procfile_lineword(ff, 0, 13), NULL, 10);
680
- p->utime = (p->utime_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
681
-
682
- last = p->stime_raw;
683
- p->stime_raw = strtoull(procfile_lineword(ff, 0, 14), NULL, 10);
684
- p->stime = (p->stime_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
685
-
686
- last = p->cutime_raw;
687
- p->cutime_raw = strtoull(procfile_lineword(ff, 0, 15), NULL, 10);
688
- p->cutime = (p->cutime_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
689
-
690
- last = p->cstime_raw;
691
- p->cstime_raw = strtoull(procfile_lineword(ff, 0, 16), NULL, 10);
692
- p->cstime = (p->cstime_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
693
-
694
- // p->priority = strtoull(procfile_lineword(ff, 0, 17), NULL, 10);
695
- // p->nice = strtoull(procfile_lineword(ff, 0, 18), NULL, 10);
696
- p->num_threads = (int32_t) atol(procfile_lineword(ff, 0, 19));
697
- // p->itrealvalue = strtoull(procfile_lineword(ff, 0, 20), NULL, 10);
698
- // p->starttime = strtoull(procfile_lineword(ff, 0, 21), NULL, 10);
699
- // p->vsize = strtoull(procfile_lineword(ff, 0, 22), NULL, 10);
700
- p->rss = strtoull(procfile_lineword(ff, 0, 23), NULL, 10);
701
- // p->rsslim = strtoull(procfile_lineword(ff, 0, 24), NULL, 10);
702
- // p->starcode = strtoull(procfile_lineword(ff, 0, 25), NULL, 10);
703
- // p->endcode = strtoull(procfile_lineword(ff, 0, 26), NULL, 10);
704
- // p->startstack = strtoull(procfile_lineword(ff, 0, 27), NULL, 10);
705
- // p->kstkesp = strtoull(procfile_lineword(ff, 0, 28), NULL, 10);
706
- // p->kstkeip = strtoull(procfile_lineword(ff, 0, 29), NULL, 10);
707
- // p->signal = strtoull(procfile_lineword(ff, 0, 30), NULL, 10);
708
- // p->blocked = strtoull(procfile_lineword(ff, 0, 31), NULL, 10);
709
- // p->sigignore = strtoull(procfile_lineword(ff, 0, 32), NULL, 10);
710
- // p->sigcatch = strtoull(procfile_lineword(ff, 0, 33), NULL, 10);
711
- // p->wchan = strtoull(procfile_lineword(ff, 0, 34), NULL, 10);
712
- // p->nswap = strtoull(procfile_lineword(ff, 0, 35), NULL, 10);
713
- // p->cnswap = strtoull(procfile_lineword(ff, 0, 36), NULL, 10);
714
- // p->exit_signal = atol(procfile_lineword(ff, 0, 37));
715
- // p->processor = atol(procfile_lineword(ff, 0, 38));
716
- // p->rt_priority = strtoul(procfile_lineword(ff, 0, 39), NULL, 10);
717
- // p->policy = strtoul(procfile_lineword(ff, 0, 40), NULL, 10);
718
- // p->delayacct_blkio_ticks = strtoull(procfile_lineword(ff, 0, 41), NULL, 10);
625
+ static procfile *ff = NULL;
626
+
627
+ if(unlikely(!p->stat_filename)) {
628
+ char filename[FILENAME_MAX + 1];
629
+ snprintfz(filename, FILENAME_MAX, "%s/proc/%d/stat", host_prefix, p->pid);
630
+ p->stat_filename = strdupz(filename);
631
+ }
632
+
633
+ int set_quotes = (!ff)?1:0;
634
+
635
+ ff = procfile_reopen(ff, p->stat_filename, NULL, PROCFILE_FLAG_NO_ERROR_ON_FILE_IO);
636
+ if(unlikely(!ff)) goto cleanup;
637
+
638
+ // if(set_quotes) procfile_set_quotes(ff, "()");
639
+ if(set_quotes) procfile_set_open_close(ff, "(", ")");
640
+
641
+ ff = procfile_readall(ff);
642
+ if(unlikely(!ff)) goto cleanup;
643
+
644
+ p->last_stat_collected_usec = p->stat_collected_usec;
645
+ p->stat_collected_usec = time_usec();
646
+ file_counter++;
647
+
648
+ // p->pid = atol(procfile_lineword(ff, 0, 0+i));
649
+
650
+ strncpyz(p->comm, procfile_lineword(ff, 0, 1), MAX_COMPARE_NAME);
651
+
652
+ // p->state = *(procfile_lineword(ff, 0, 2));
653
+ p->ppid = (int32_t) atol(procfile_lineword(ff, 0, 3));
654
+ // p->pgrp = atol(procfile_lineword(ff, 0, 4));
655
+ // p->session = atol(procfile_lineword(ff, 0, 5));
656
+ // p->tty_nr = atol(procfile_lineword(ff, 0, 6));
657
+ // p->tpgid = atol(procfile_lineword(ff, 0, 7));
658
+ // p->flags = strtoull(procfile_lineword(ff, 0, 8), NULL, 10);
659
+
660
+ unsigned long long last;
661
+
662
+ last = p->minflt_raw;
663
+ p->minflt_raw = strtoull(procfile_lineword(ff, 0, 9), NULL, 10);
664
+ p->minflt = (p->minflt_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
665
+
666
+ last = p->cminflt_raw;
667
+ p->cminflt_raw = strtoull(procfile_lineword(ff, 0, 10), NULL, 10);
668
+ p->cminflt = (p->cminflt_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
669
+
670
+ last = p->majflt_raw;
671
+ p->majflt_raw = strtoull(procfile_lineword(ff, 0, 11), NULL, 10);
672
+ p->majflt = (p->majflt_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
673
+
674
+ last = p->cmajflt_raw;
675
+ p->cmajflt_raw = strtoull(procfile_lineword(ff, 0, 12), NULL, 10);
676
+ p->cmajflt = (p->cmajflt_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
677
+
678
+ last = p->utime_raw;
679
+ p->utime_raw = strtoull(procfile_lineword(ff, 0, 13), NULL, 10);
680
+ p->utime = (p->utime_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
681
+
682
+ last = p->stime_raw;
683
+ p->stime_raw = strtoull(procfile_lineword(ff, 0, 14), NULL, 10);
684
+ p->stime = (p->stime_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
685
+
686
+ last = p->cutime_raw;
687
+ p->cutime_raw = strtoull(procfile_lineword(ff, 0, 15), NULL, 10);
688
+ p->cutime = (p->cutime_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
689
+
690
+ last = p->cstime_raw;
691
+ p->cstime_raw = strtoull(procfile_lineword(ff, 0, 16), NULL, 10);
692
+ p->cstime = (p->cstime_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
693
+
694
+ // p->priority = strtoull(procfile_lineword(ff, 0, 17), NULL, 10);
695
+ // p->nice = strtoull(procfile_lineword(ff, 0, 18), NULL, 10);
696
+ p->num_threads = (int32_t) atol(procfile_lineword(ff, 0, 19));
697
+ // p->itrealvalue = strtoull(procfile_lineword(ff, 0, 20), NULL, 10);
698
+ // p->starttime = strtoull(procfile_lineword(ff, 0, 21), NULL, 10);
699
+ // p->vsize = strtoull(procfile_lineword(ff, 0, 22), NULL, 10);
700
+ p->rss = strtoull(procfile_lineword(ff, 0, 23), NULL, 10);
701
+ // p->rsslim = strtoull(procfile_lineword(ff, 0, 24), NULL, 10);
702
+ // p->starcode = strtoull(procfile_lineword(ff, 0, 25), NULL, 10);
703
+ // p->endcode = strtoull(procfile_lineword(ff, 0, 26), NULL, 10);
704
+ // p->startstack = strtoull(procfile_lineword(ff, 0, 27), NULL, 10);
705
+ // p->kstkesp = strtoull(procfile_lineword(ff, 0, 28), NULL, 10);
706
+ // p->kstkeip = strtoull(procfile_lineword(ff, 0, 29), NULL, 10);
707
+ // p->signal = strtoull(procfile_lineword(ff, 0, 30), NULL, 10);
708
+ // p->blocked = strtoull(procfile_lineword(ff, 0, 31), NULL, 10);
709
+ // p->sigignore = strtoull(procfile_lineword(ff, 0, 32), NULL, 10);
710
+ // p->sigcatch = strtoull(procfile_lineword(ff, 0, 33), NULL, 10);
711
+ // p->wchan = strtoull(procfile_lineword(ff, 0, 34), NULL, 10);
712
+ // p->nswap = strtoull(procfile_lineword(ff, 0, 35), NULL, 10);
713
+ // p->cnswap = strtoull(procfile_lineword(ff, 0, 36), NULL, 10);
714
+ // p->exit_signal = atol(procfile_lineword(ff, 0, 37));
715
+ // p->processor = atol(procfile_lineword(ff, 0, 38));
716
+ // p->rt_priority = strtoul(procfile_lineword(ff, 0, 39), NULL, 10);
717
+ // p->policy = strtoul(procfile_lineword(ff, 0, 40), NULL, 10);
718
+ // p->delayacct_blkio_ticks = strtoull(procfile_lineword(ff, 0, 41), NULL, 10);
719
720
if(enable_guest_charts) {
721
last = p->gtime_raw;
722
- p->gtime_raw = strtoull(procfile_lineword(ff, 0, 42), NULL, 10);
722
+ p->gtime_raw = strtoull(procfile_lineword(ff, 0, 42), NULL, 10);
723
p->gtime = (p->gtime_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
724
725
last = p->cgtime_raw;
726
- p->cgtime_raw = strtoull(procfile_lineword(ff, 0, 43), NULL, 10);
726
+ p->cgtime_raw = strtoull(procfile_lineword(ff, 0, 43), NULL, 10);
727
p->cgtime = (p->cgtime_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
728
729
if (show_guest_time || p->gtime || p->cgtime) {
@@ -733,150 +733,150 @@ int read_proc_pid_stat(struct pid_stat *p) {
733
}
734
}
735
736
- if(unlikely(debug || (p->target && p->target->debug)))
737
- fprintf(stderr, "apps.plugin: READ PROC/PID/STAT: %s/proc/%d/stat, process: '%s' on target '%s' (dt=%llu) VALUES: utime=%llu, stime=%llu, cutime=%llu, cstime=%llu, minflt=%llu, majflt=%llu, cminflt=%llu, cmajflt=%llu, threads=%d\n", host_prefix, p->pid, p->comm, (p->target)?p->target->name:"UNSET", p->stat_collected_usec - p->last_stat_collected_usec, p->utime, p->stime, p->cutime, p->cstime, p->minflt, p->majflt, p->cminflt, p->cmajflt, p->num_threads);
738
-
739
- if(unlikely(global_iterations_counter == 1)) {
740
- p->minflt = 0;
741
- p->cminflt = 0;
742
- p->majflt = 0;
743
- p->cmajflt = 0;
744
- p->utime = 0;
745
- p->stime = 0;
746
- p->gtime = 0;
747
- p->cutime = 0;
748
- p->cstime = 0;
749
- p->cgtime = 0;
750
- }
736
+ if(unlikely(debug || (p->target && p->target->debug)))
737
+ fprintf(stderr, "apps.plugin: READ PROC/PID/STAT: %s/proc/%d/stat, process: '%s' on target '%s' (dt=%llu) VALUES: utime=%llu, stime=%llu, cutime=%llu, cstime=%llu, minflt=%llu, majflt=%llu, cminflt=%llu, cmajflt=%llu, threads=%d\n", host_prefix, p->pid, p->comm, (p->target)?p->target->name:"UNSET", p->stat_collected_usec - p->last_stat_collected_usec, p->utime, p->stime, p->cutime, p->cstime, p->minflt, p->majflt, p->cminflt, p->cmajflt, p->num_threads);
738
+
739
+ if(unlikely(global_iterations_counter == 1)) {
740
+ p->minflt = 0;
741
+ p->cminflt = 0;
742
+ p->majflt = 0;
743
+ p->cmajflt = 0;
744
+ p->utime = 0;
745
+ p->stime = 0;
746
+ p->gtime = 0;
747
+ p->cutime = 0;
748
+ p->cstime = 0;
749
+ p->cgtime = 0;
750
+ }
751
752
- return 0;
752
+ return 0;
753
754
cleanup:
755
- p->minflt = 0;
756
- p->cminflt = 0;
757
- p->majflt = 0;
758
- p->cmajflt = 0;
759
- p->utime = 0;
760
- p->stime = 0;
761
- p->gtime = 0;
762
- p->cutime = 0;
763
- p->cstime = 0;
764
- p->cgtime = 0;
765
- p->num_threads = 0;
766
- p->rss = 0;
767
- return 1;
755
+ p->minflt = 0;
756
+ p->cminflt = 0;
757
+ p->majflt = 0;
758
+ p->cmajflt = 0;
759
+ p->utime = 0;
760
+ p->stime = 0;
761
+ p->gtime = 0;
762
+ p->cutime = 0;
763
+ p->cstime = 0;
764
+ p->cgtime = 0;
765
+ p->num_threads = 0;
766
+ p->rss = 0;
767
+ return 1;
768
}
769
770
int read_proc_pid_statm(struct pid_stat *p) {
771
- static procfile *ff = NULL;
771
+ static procfile *ff = NULL;
772
773
- if(unlikely(!p->statm_filename)) {
774
- char filename[FILENAME_MAX + 1];
775
- snprintfz(filename, FILENAME_MAX, "%s/proc/%d/statm", host_prefix, p->pid);
776
- p->statm_filename = strdupz(filename);
777
- }
773
+ if(unlikely(!p->statm_filename)) {
774
+ char filename[FILENAME_MAX + 1];
775
+ snprintfz(filename, FILENAME_MAX, "%s/proc/%d/statm", host_prefix, p->pid);
776
+ p->statm_filename = strdupz(filename);
777
+ }
778
779
- ff = procfile_reopen(ff, p->statm_filename, NULL, PROCFILE_FLAG_NO_ERROR_ON_FILE_IO);
780
- if(unlikely(!ff)) goto cleanup;
779
+ ff = procfile_reopen(ff, p->statm_filename, NULL, PROCFILE_FLAG_NO_ERROR_ON_FILE_IO);
780
+ if(unlikely(!ff)) goto cleanup;
781
782
- ff = procfile_readall(ff);
783
- if(unlikely(!ff)) goto cleanup;
782
+ ff = procfile_readall(ff);
783
+ if(unlikely(!ff)) goto cleanup;
784
785
- file_counter++;
785
+ file_counter++;
786
787
- p->statm_size = strtoull(procfile_lineword(ff, 0, 0), NULL, 10);
788
- p->statm_resident = strtoull(procfile_lineword(ff, 0, 1), NULL, 10);
789
- p->statm_share = strtoull(procfile_lineword(ff, 0, 2), NULL, 10);
790
- p->statm_text = strtoull(procfile_lineword(ff, 0, 3), NULL, 10);
791
- p->statm_lib = strtoull(procfile_lineword(ff, 0, 4), NULL, 10);
792
- p->statm_data = strtoull(procfile_lineword(ff, 0, 5), NULL, 10);
793
- p->statm_dirty = strtoull(procfile_lineword(ff, 0, 6), NULL, 10);
787
+ p->statm_size = strtoull(procfile_lineword(ff, 0, 0), NULL, 10);
788
+ p->statm_resident = strtoull(procfile_lineword(ff, 0, 1), NULL, 10);
789
+ p->statm_share = strtoull(procfile_lineword(ff, 0, 2), NULL, 10);
790
+ p->statm_text = strtoull(procfile_lineword(ff, 0, 3), NULL, 10);
791
+ p->statm_lib = strtoull(procfile_lineword(ff, 0, 4), NULL, 10);
792
+ p->statm_data = strtoull(procfile_lineword(ff, 0, 5), NULL, 10);
793
+ p->statm_dirty = strtoull(procfile_lineword(ff, 0, 6), NULL, 10);
794
795
- return 0;
795
+ return 0;
796
797
cleanup:
798
- p->statm_size = 0;
799
- p->statm_resident = 0;
800
- p->statm_share = 0;
801
- p->statm_text = 0;
802
- p->statm_lib = 0;
803
- p->statm_data = 0;
804
- p->statm_dirty = 0;
805
- return 1;
798
+ p->statm_size = 0;
799
+ p->statm_resident = 0;
800
+ p->statm_share = 0;
801
+ p->statm_text = 0;
802
+ p->statm_lib = 0;
803
+ p->statm_data = 0;
804
+ p->statm_dirty = 0;
805
+ return 1;
806
}
807
808
int read_proc_pid_io(struct pid_stat *p) {
809
- static procfile *ff = NULL;
809
+ static procfile *ff = NULL;
810
811
- if(unlikely(!p->io_filename)) {
812
- char filename[FILENAME_MAX + 1];
813
- snprintfz(filename, FILENAME_MAX, "%s/proc/%d/io", host_prefix, p->pid);
814
- p->io_filename = strdupz(filename);
815
- }
811
+ if(unlikely(!p->io_filename)) {
812
+ char filename[FILENAME_MAX + 1];
813
+ snprintfz(filename, FILENAME_MAX, "%s/proc/%d/io", host_prefix, p->pid);
814
+ p->io_filename = strdupz(filename);
815
+ }
816
817
- // open the file
818
- ff = procfile_reopen(ff, p->io_filename, NULL, PROCFILE_FLAG_NO_ERROR_ON_FILE_IO);
819
- if(unlikely(!ff)) goto cleanup;
817
+ // open the file
818
+ ff = procfile_reopen(ff, p->io_filename, NULL, PROCFILE_FLAG_NO_ERROR_ON_FILE_IO);
819
+ if(unlikely(!ff)) goto cleanup;
820
821
- ff = procfile_readall(ff);
822
- if(unlikely(!ff)) goto cleanup;
821
+ ff = procfile_readall(ff);
822
+ if(unlikely(!ff)) goto cleanup;
823
824
- file_counter++;
824
+ file_counter++;
825
826
- p->last_io_collected_usec = p->io_collected_usec;
827
- p->io_collected_usec = time_usec();
826
+ p->last_io_collected_usec = p->io_collected_usec;
827
+ p->io_collected_usec = time_usec();
828
829
- unsigned long long last;
829
+ unsigned long long last;
830
831
- last = p->io_logical_bytes_read_raw;
832
- p->io_logical_bytes_read_raw = strtoull(procfile_lineword(ff, 0, 1), NULL, 10);
833
- p->io_logical_bytes_read = (p->io_logical_bytes_read_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
831
+ last = p->io_logical_bytes_read_raw;
832
+ p->io_logical_bytes_read_raw = strtoull(procfile_lineword(ff, 0, 1), NULL, 10);
833
+ p->io_logical_bytes_read = (p->io_logical_bytes_read_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
834
835
- last = p->io_logical_bytes_written_raw;
836
- p->io_logical_bytes_written_raw = strtoull(procfile_lineword(ff, 1, 1), NULL, 10);
837
- p->io_logical_bytes_written = (p->io_logical_bytes_written_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
835
+ last = p->io_logical_bytes_written_raw;
836
+ p->io_logical_bytes_written_raw = strtoull(procfile_lineword(ff, 1, 1), NULL, 10);
837
+ p->io_logical_bytes_written = (p->io_logical_bytes_written_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
838
839
- last = p->io_read_calls_raw;
840
- p->io_read_calls_raw = strtoull(procfile_lineword(ff, 2, 1), NULL, 10);
841
- p->io_read_calls = (p->io_read_calls_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
839
+ last = p->io_read_calls_raw;
840
+ p->io_read_calls_raw = strtoull(procfile_lineword(ff, 2, 1), NULL, 10);
841
+ p->io_read_calls = (p->io_read_calls_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
842
843
- last = p->io_write_calls_raw;
844
- p->io_write_calls_raw = strtoull(procfile_lineword(ff, 3, 1), NULL, 10);
845
- p->io_write_calls = (p->io_write_calls_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
843
+ last = p->io_write_calls_raw;
844
+ p->io_write_calls_raw = strtoull(procfile_lineword(ff, 3, 1), NULL, 10);
845
+ p->io_write_calls = (p->io_write_calls_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
846
847
- last = p->io_storage_bytes_read_raw;
848
- p->io_storage_bytes_read_raw = strtoull(procfile_lineword(ff, 4, 1), NULL, 10);
849
- p->io_storage_bytes_read = (p->io_storage_bytes_read_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
847
+ last = p->io_storage_bytes_read_raw;
848
+ p->io_storage_bytes_read_raw = strtoull(procfile_lineword(ff, 4, 1), NULL, 10);
849
+ p->io_storage_bytes_read = (p->io_storage_bytes_read_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
850
851
- last = p->io_storage_bytes_written_raw;
852
- p->io_storage_bytes_written_raw = strtoull(procfile_lineword(ff, 5, 1), NULL, 10);
853
- p->io_storage_bytes_written = (p->io_storage_bytes_written_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
851
+ last = p->io_storage_bytes_written_raw;
852
+ p->io_storage_bytes_written_raw = strtoull(procfile_lineword(ff, 5, 1), NULL, 10);
853
+ p->io_storage_bytes_written = (p->io_storage_bytes_written_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
854
855
- last = p->io_cancelled_write_bytes_raw;
856
- p->io_cancelled_write_bytes_raw = strtoull(procfile_lineword(ff, 6, 1), NULL, 10);
857
- p->io_cancelled_write_bytes = (p->io_cancelled_write_bytes_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
855
+ last = p->io_cancelled_write_bytes_raw;
856
+ p->io_cancelled_write_bytes_raw = strtoull(procfile_lineword(ff, 6, 1), NULL, 10);
857
+ p->io_cancelled_write_bytes = (p->io_cancelled_write_bytes_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
858
859
- if(unlikely(global_iterations_counter == 1)) {
860
- p->io_logical_bytes_read = 0;
861
- p->io_logical_bytes_written = 0;
862
- p->io_read_calls = 0;
863
- p->io_write_calls = 0;
864
- p->io_storage_bytes_read = 0;
865
- p->io_storage_bytes_written = 0;
866
- p->io_cancelled_write_bytes = 0;
867
- }
859
+ if(unlikely(global_iterations_counter == 1)) {
860
+ p->io_logical_bytes_read = 0;
861
+ p->io_logical_bytes_written = 0;
862
+ p->io_read_calls = 0;
863
+ p->io_write_calls = 0;
864
+ p->io_storage_bytes_read = 0;
865
+ p->io_storage_bytes_written = 0;
866
+ p->io_cancelled_write_bytes = 0;
867
+ }
868
869
- return 0;
869
+ return 0;
870
871
cleanup:
872
- p->io_logical_bytes_read = 0;
873
- p->io_logical_bytes_written = 0;
874
- p->io_read_calls = 0;
875
- p->io_write_calls = 0;
876
- p->io_storage_bytes_read = 0;
877
- p->io_storage_bytes_written = 0;
878
- p->io_cancelled_write_bytes = 0;
879
- return 1;
872
+ p->io_logical_bytes_read = 0;
873
+ p->io_logical_bytes_written = 0;
874
+ p->io_read_calls = 0;
875
+ p->io_write_calls = 0;
876
+ p->io_storage_bytes_read = 0;
877
+ p->io_storage_bytes_written = 0;
878
+ p->io_cancelled_write_bytes = 0;
879
+ return 1;
880
}
881
882
unsigned long long global_utime = 0;
@@ -884,38 +884,38 @@ unsigned long long global_stime = 0;
884
unsigned long long global_gtime = 0;
885
886
int read_proc_stat() {
887
- static char filename[FILENAME_MAX + 1] = "";
888
- static procfile *ff = NULL;
889
- static unsigned long long utime_raw = 0, stime_raw = 0, gtime_raw = 0, gntime_raw = 0, ntime_raw = 0, collected_usec = 0, last_collected_usec = 0;
890
-
891
- if(unlikely(!ff)) {
892
- snprintfz(filename, FILENAME_MAX, "%s/proc/stat", host_prefix);
893
- ff = procfile_open(filename, " \t:", PROCFILE_FLAG_DEFAULT);
894
- if(unlikely(!ff)) goto cleanup;
895
- }
887
+ static char filename[FILENAME_MAX + 1] = "";
888
+ static procfile *ff = NULL;
889
+ static unsigned long long utime_raw = 0, stime_raw = 0, gtime_raw = 0, gntime_raw = 0, ntime_raw = 0, collected_usec = 0, last_collected_usec = 0;
890
+
891
+ if(unlikely(!ff)) {
892
+ snprintfz(filename, FILENAME_MAX, "%s/proc/stat", host_prefix);
893
+ ff = procfile_open(filename, " \t:", PROCFILE_FLAG_DEFAULT);
894
+ if(unlikely(!ff)) goto cleanup;
895
+ }
896
897
- ff = procfile_readall(ff);
898
- if(unlikely(!ff)) goto cleanup;
897
+ ff = procfile_readall(ff);
898
+ if(unlikely(!ff)) goto cleanup;
899
900
- last_collected_usec = collected_usec;
901
- collected_usec = time_usec();
900
+ last_collected_usec = collected_usec;
901
+ collected_usec = time_usec();
902
903
- file_counter++;
903
+ file_counter++;
904
905
- unsigned long long last;
905
+ unsigned long long last;
906
907
- last = utime_raw;
908
- utime_raw = strtoull(procfile_lineword(ff, 0, 1), NULL, 10);
909
- global_utime = (utime_raw - last) * (1000000ULL * RATES_DETAIL) / (collected_usec - last_collected_usec);
907
+ last = utime_raw;
908
+ utime_raw = strtoull(procfile_lineword(ff, 0, 1), NULL, 10);
909
+ global_utime = (utime_raw - last) * (1000000ULL * RATES_DETAIL) / (collected_usec - last_collected_usec);
910
911
// nice time, on user time
912
- last = ntime_raw;
913
- ntime_raw = strtoull(procfile_lineword(ff, 0, 2), NULL, 10);
914
- global_utime += (ntime_raw - last) * (1000000ULL * RATES_DETAIL) / (collected_usec - last_collected_usec);
912
+ last = ntime_raw;
913
+ ntime_raw = strtoull(procfile_lineword(ff, 0, 2), NULL, 10);
914
+ global_utime += (ntime_raw - last) * (1000000ULL * RATES_DETAIL) / (collected_usec - last_collected_usec);
915
916
- last = stime_raw;
917
- stime_raw = strtoull(procfile_lineword(ff, 0, 3), NULL, 10);
918
- global_stime = (stime_raw - last) * (1000000ULL * RATES_DETAIL) / (collected_usec - last_collected_usec);
916
+ last = stime_raw;
917
+ stime_raw = strtoull(procfile_lineword(ff, 0, 3), NULL, 10);
918
+ global_stime = (stime_raw - last) * (1000000ULL * RATES_DETAIL) / (collected_usec - last_collected_usec);
919
920
last = gtime_raw;
921
gtime_raw = strtoull(procfile_lineword(ff, 0, 10), NULL, 10);
@@ -931,19 +931,19 @@ int read_proc_stat() {
931
global_utime -= (global_utime > global_gtime) ? global_gtime : global_utime;
932
}
933
934
- if(unlikely(global_iterations_counter == 1)) {
935
- global_utime = 0;
936
- global_stime = 0;
937
- global_gtime = 0;
938
- }
934
+ if(unlikely(global_iterations_counter == 1)) {
935
+ global_utime = 0;
936
+ global_stime = 0;
937
+ global_gtime = 0;
938
+ }
939
940
- return 0;
940
+ return 0;
941
942
cleanup:
943
- global_utime = 0;
944
- global_stime = 0;
945
- global_gtime = 0;
946
- return 1;
943
+ global_utime = 0;
944
+ global_stime = 0;
945
+ global_gtime = 0;
946
+ return 1;
947
}
948
949
@@ -955,15 +955,15 @@ cleanup:
955
#define FILE_DESCRIPTORS_INCREASE_STEP 100
956
957
struct file_descriptor {
958
- avl avl;
958
+ avl avl;
959
#ifdef NETDATA_INTERNAL_CHECKS
960
- uint32_t magic;
960
+ uint32_t magic;
961
#endif /* NETDATA_INTERNAL_CHECKS */
962
- uint32_t hash;
963
- const char *name;
964
- int type;
965
- int count;
966
- int pos;
962
+ uint32_t hash;
963
+ const char *name;
964
+ int type;
965
+ int count;
966
+ int pos;
967
} *all_files = NULL;
968
969
int all_files_len = 0;
@@ -971,38 +971,38 @@ int all_files_size = 0;
971
972
int file_descriptor_compare(void* a, void* b) {
973
#ifdef NETDATA_INTERNAL_CHECKS
974
- if(((struct file_descriptor *)a)->magic != 0x0BADCAFE || ((struct file_descriptor *)b)->magic != 0x0BADCAFE)
975
- error("Corrupted index data detected. Please report this.");
974
+ if(((struct file_descriptor *)a)->magic != 0x0BADCAFE || ((struct file_descriptor *)b)->magic != 0x0BADCAFE)
975
+ error("Corrupted index data detected. Please report this.");
976
#endif /* NETDATA_INTERNAL_CHECKS */
977
978
- if(((struct file_descriptor *)a)->hash < ((struct file_descriptor *)b)->hash)
979
- return -1;
978
+ if(((struct file_descriptor *)a)->hash < ((struct file_descriptor *)b)->hash)
979
+ return -1;
980
981
- else if(((struct file_descriptor *)a)->hash > ((struct file_descriptor *)b)->hash)
982
- return 1;
981
+ else if(((struct file_descriptor *)a)->hash > ((struct file_descriptor *)b)->hash)
982
+ return 1;
983
984
- else
985
- return strcmp(((struct file_descriptor *)a)->name, ((struct file_descriptor *)b)->name);
984
+ else
985
+ return strcmp(((struct file_descriptor *)a)->name, ((struct file_descriptor *)b)->name);
986
}
987
988
int file_descriptor_iterator(avl *a) { if(a) {}; return 0; }
989
990
avl_tree all_files_index = {
991
- NULL,
992
- file_descriptor_compare
991
+ NULL,
992
+ file_descriptor_compare
993
};
994
995
static struct file_descriptor *file_descriptor_find(const char *name, uint32_t hash) {
996
- struct file_descriptor tmp;
997
- tmp.hash = (hash)?hash:simple_hash(name);
998
- tmp.name = name;
999
- tmp.count = 0;
1000
- tmp.pos = 0;
996
+ struct file_descriptor tmp;
997
+ tmp.hash = (hash)?hash:simple_hash(name);
998
+ tmp.name = name;
999
+ tmp.count = 0;
1000
+ tmp.pos = 0;
1001
#ifdef NETDATA_INTERNAL_CHECKS
1002
- tmp.magic = 0x0BADCAFE;
1002
+ tmp.magic = 0x0BADCAFE;
1003
#endif /* NETDATA_INTERNAL_CHECKS */
1004
1005
- return (struct file_descriptor *)avl_search(&all_files_index, (avl *) &tmp);
1005
+ return (struct file_descriptor *)avl_search(&all_files_index, (avl *) &tmp);
1006
}
1007
1008
#define file_descriptor_add(fd) avl_insert(&all_files_index, (avl *)(fd))
@@ -1020,526 +1020,526 @@ static struct file_descriptor *file_descriptor_find(const char *name, uint32_t h
1020
1021
void file_descriptor_not_used(int id)
1022
{
1023
- if(id > 0 && id < all_files_size) {
1023
+ if(id > 0 && id < all_files_size) {
1024
1025
#ifdef NETDATA_INTERNAL_CHECKS
1026
- if(all_files[id].magic != 0x0BADCAFE) {
1027
- error("Ignoring request to remove empty file id %d.", id);
1028
- return;
1029
- }
1026
+ if(all_files[id].magic != 0x0BADCAFE) {
1027
+ error("Ignoring request to remove empty file id %d.", id);
1028
+ return;
1029
+ }
1030
#endif /* NETDATA_INTERNAL_CHECKS */
1031
1032
- if(unlikely(debug))
1033
- fprintf(stderr, "apps.plugin: decreasing slot %d (count = %d).\n", id, all_files[id].count);
1032
+ if(unlikely(debug))
1033
+ fprintf(stderr, "apps.plugin: decreasing slot %d (count = %d).\n", id, all_files[id].count);
1034
1035
- if(all_files[id].count > 0) {
1036
- all_files[id].count--;
1035
+ if(all_files[id].count > 0) {
1036
+ all_files[id].count--;
1037
1038
- if(!all_files[id].count) {
1039
- if(unlikely(debug))
1040
- fprintf(stderr, "apps.plugin: >> slot %d is empty.\n", id);
1038
+ if(!all_files[id].count) {
1039
+ if(unlikely(debug))
1040
+ fprintf(stderr, "apps.plugin: >> slot %d is empty.\n", id);
1041
1042
- file_descriptor_remove(&all_files[id]);
1042
+ file_descriptor_remove(&all_files[id]);
1043
#ifdef NETDATA_INTERNAL_CHECKS
1044
- all_files[id].magic = 0x00000000;
1044
+ all_files[id].magic = 0x00000000;
1045
#endif /* NETDATA_INTERNAL_CHECKS */
1046
- all_files_len--;
1047
- }
1048
- }
1049
- else
1050
- error("Request to decrease counter of fd %d (%s), while the use counter is 0", id, all_files[id].name);
1051
- }
1052
- else error("Request to decrease counter of fd %d, which is outside the array size (1 to %d)", id, all_files_size);
1046
+ all_files_len--;
1047
+ }
1048
+ }
1049
+ else
1050
+ error("Request to decrease counter of fd %d (%s), while the use counter is 0", id, all_files[id].name);
1051
+ }
1052
+ else error("Request to decrease counter of fd %d, which is outside the array size (1 to %d)", id, all_files_size);
1053
}
1054
1055
int file_descriptor_find_or_add(const char *name)
1056
{
1057
- static int last_pos = 0;
1058
- uint32_t hash = simple_hash(name);
1059
-
1060
- if(unlikely(debug))
1061
- fprintf(stderr, "apps.plugin: adding or finding name '%s' with hash %u\n", name, hash);
1062
-
1063
- struct file_descriptor *fd = file_descriptor_find(name, hash);
1064
- if(fd) {
1065
- // found
1066
- if(unlikely(debug))
1067
- fprintf(stderr, "apps.plugin: >> found on slot %d\n", fd->pos);
1068
-
1069
- fd->count++;
1070
- return fd->pos;
1071
- }
1072
- // not found
1073
-
1074
- // check we have enough memory to add it
1075
- if(!all_files || all_files_len == all_files_size) {
1076
- void *old = all_files;
1077
- int i;
1078
-
1079
- // there is no empty slot
1080
- if(unlikely(debug))
1081
- fprintf(stderr, "apps.plugin: extending fd array to %d entries\n", all_files_size + FILE_DESCRIPTORS_INCREASE_STEP);
1082
-
1083
- all_files = reallocz(all_files, (all_files_size + FILE_DESCRIPTORS_INCREASE_STEP) * sizeof(struct file_descriptor));
1084
-
1085
- // if the address changed, we have to rebuild the index
1086
- // since all pointers are now invalid
1087
- if(old && old != (void *)all_files) {
1088
- if(unlikely(debug))
1089
- fprintf(stderr, "apps.plugin: >> re-indexing.\n");
1090
-
1091
- all_files_index.root = NULL;
1092
- for(i = 0; i < all_files_size; i++) {
1093
- if(!all_files[i].count) continue;
1094
- file_descriptor_add(&all_files[i]);
1095
- }
1096
-
1097
- if(unlikely(debug))
1098
- fprintf(stderr, "apps.plugin: >> re-indexing done.\n");
1099
- }
1100
-
1101
- for(i = all_files_size; i < (all_files_size + FILE_DESCRIPTORS_INCREASE_STEP); i++) {
1102
- all_files[i].count = 0;
1103
- all_files[i].name = NULL;
1057
+ static int last_pos = 0;
1058
+ uint32_t hash = simple_hash(name);
1059
+
1060
+ if(unlikely(debug))
1061
+ fprintf(stderr, "apps.plugin: adding or finding name '%s' with hash %u\n", name, hash);
1062
+
1063
+ struct file_descriptor *fd = file_descriptor_find(name, hash);
1064
+ if(fd) {
1065
+ // found
1066
+ if(unlikely(debug))
1067
+ fprintf(stderr, "apps.plugin: >> found on slot %d\n", fd->pos);
1068
+
1069
+ fd->count++;
1070
+ return fd->pos;
1071
+ }
1072
+ // not found
1073
+
1074
+ // check we have enough memory to add it
1075
+ if(!all_files || all_files_len == all_files_size) {
1076
+ void *old = all_files;
1077
+ int i;
1078
+
1079
+ // there is no empty slot
1080
+ if(unlikely(debug))
1081
+ fprintf(stderr, "apps.plugin: extending fd array to %d entries\n", all_files_size + FILE_DESCRIPTORS_INCREASE_STEP);
1082
+
1083
+ all_files = reallocz(all_files, (all_files_size + FILE_DESCRIPTORS_INCREASE_STEP) * sizeof(struct file_descriptor));
1084
+
1085
+ // if the address changed, we have to rebuild the index
1086
+ // since all pointers are now invalid
1087
+ if(old && old != (void *)all_files) {
1088
+ if(unlikely(debug))
1089
+ fprintf(stderr, "apps.plugin: >> re-indexing.\n");
1090
+
1091
+ all_files_index.root = NULL;
1092
+ for(i = 0; i < all_files_size; i++) {
1093
+ if(!all_files[i].count) continue;
1094
+ file_descriptor_add(&all_files[i]);
1095
+ }
1096
+
1097
+ if(unlikely(debug))
1098
+ fprintf(stderr, "apps.plugin: >> re-indexing done.\n");
1099
+ }
1100
+
1101
+ for(i = all_files_size; i < (all_files_size + FILE_DESCRIPTORS_INCREASE_STEP); i++) {
1102
+ all_files[i].count = 0;
1103
+ all_files[i].name = NULL;
1104
#ifdef NETDATA_INTERNAL_CHECKS
1105
- all_files[i].magic = 0x00000000;
1105
+ all_files[i].magic = 0x00000000;
1106
#endif /* NETDATA_INTERNAL_CHECKS */
1107
- all_files[i].pos = i;
1108
- }
1107
+ all_files[i].pos = i;
1108
+ }
1109
1110
- if(!all_files_size) all_files_len = 1;
1111
- all_files_size += FILE_DESCRIPTORS_INCREASE_STEP;
1112
- }
1110
+ if(!all_files_size) all_files_len = 1;
1111
+ all_files_size += FILE_DESCRIPTORS_INCREASE_STEP;
1112
+ }
1113
1114
- if(unlikely(debug))
1115
- fprintf(stderr, "apps.plugin: >> searching for empty slot.\n");
1114
+ if(unlikely(debug))
1115
+ fprintf(stderr, "apps.plugin: >> searching for empty slot.\n");
1116
1117
- // search for an empty slot
1118
- int i, c;
1119
- for(i = 0, c = last_pos ; i < all_files_size ; i++, c++) {
1120
- if(c >= all_files_size) c = 0;
1121
- if(c == 0) continue;
1117
+ // search for an empty slot
1118
+ int i, c;
1119
+ for(i = 0, c = last_pos ; i < all_files_size ; i++, c++) {
1120
+ if(c >= all_files_size) c = 0;
1121
+ if(c == 0) continue;
1122
1123
- if(!all_files[c].count) {
1124
- if(unlikely(debug))
1125
- fprintf(stderr, "apps.plugin: >> Examining slot %d.\n", c);
1123
+ if(!all_files[c].count) {
1124
+ if(unlikely(debug))
1125
+ fprintf(stderr, "apps.plugin: >> Examining slot %d.\n", c);
1126
1127
#ifdef NETDATA_INTERNAL_CHECKS
1128
- if(all_files[c].magic == 0x0BADCAFE && all_files[c].name && file_descriptor_find(all_files[c].name, all_files[c].hash))
1129
- error("fd on position %d is not cleared properly. It still has %s in it.\n", c, all_files[c].name);
1128
+ if(all_files[c].magic == 0x0BADCAFE && all_files[c].name && file_descriptor_find(all_files[c].name, all_files[c].hash))
1129
+ error("fd on position %d is not cleared properly. It still has %s in it.\n", c, all_files[c].name);
1130
#endif /* NETDATA_INTERNAL_CHECKS */
1131
1132
- if(unlikely(debug))
1133
- fprintf(stderr, "apps.plugin: >> %s fd position %d for %s (last name: %s)\n", all_files[c].name?"re-using":"using", c, name, all_files[c].name);
1134
-
1135
- if(all_files[c].name) freez((void *)all_files[c].name);
1136
- all_files[c].name = NULL;
1137
- last_pos = c;
1138
- break;
1139
- }
1140
- }
1141
- if(i == all_files_size) {
1142
- fatal("We should find an empty slot, but there isn't any");
1143
- exit(1);
1144
- }
1145
-
1146
- if(unlikely(debug))
1147
- fprintf(stderr, "apps.plugin: >> updating slot %d.\n", c);
1148
-
1149
- all_files_len++;
1150
-
1151
- // else we have an empty slot in 'c'
1152
-
1153
- int type;
1154
- if(name[0] == '/') type = FILETYPE_FILE;
1155
- else if(strncmp(name, "pipe:", 5) == 0) type = FILETYPE_PIPE;
1156
- else if(strncmp(name, "socket:", 7) == 0) type = FILETYPE_SOCKET;
1157
- else if(strcmp(name, "anon_inode:inotify") == 0 || strcmp(name, "inotify") == 0) type = FILETYPE_INOTIFY;
1158
- else if(strcmp(name, "anon_inode:[eventfd]") == 0) type = FILETYPE_EVENTFD;
1159
- else if(strcmp(name, "anon_inode:[eventpoll]") == 0) type = FILETYPE_EVENTPOLL;
1160
- else if(strcmp(name, "anon_inode:[timerfd]") == 0) type = FILETYPE_TIMERFD;
1161
- else if(strcmp(name, "anon_inode:[signalfd]") == 0) type = FILETYPE_SIGNALFD;
1162
- else if(strncmp(name, "anon_inode:", 11) == 0) {
1163
- if(unlikely(debug))
1164
- fprintf(stderr, "apps.plugin: FIXME: unknown anonymous inode: %s\n", name);
1165
-
1166
- type = FILETYPE_OTHER;
1167
- }
1168
- else {
1169
- if(unlikely(debug))
1170
- fprintf(stderr, "apps.plugin: FIXME: cannot understand linkname: %s\n", name);
1171
-
1172
- type = FILETYPE_OTHER;
1173
- }
1174
-
1175
- all_files[c].name = strdupz(name);
1176
- all_files[c].hash = hash;
1177
- all_files[c].type = type;
1178
- all_files[c].pos = c;
1179
- all_files[c].count = 1;
1132
+ if(unlikely(debug))
1133
+ fprintf(stderr, "apps.plugin: >> %s fd position %d for %s (last name: %s)\n", all_files[c].name?"re-using":"using", c, name, all_files[c].name);
1134
+
1135
+ if(all_files[c].name) freez((void *)all_files[c].name);
1136
+ all_files[c].name = NULL;
1137
+ last_pos = c;
1138
+ break;
1139
+ }
1140
+ }
1141
+ if(i == all_files_size) {
1142
+ fatal("We should find an empty slot, but there isn't any");
1143
+ exit(1);
1144
+ }
1145
+
1146
+ if(unlikely(debug))
1147
+ fprintf(stderr, "apps.plugin: >> updating slot %d.\n", c);
1148
+
1149
+ all_files_len++;
1150
+
1151
+ // else we have an empty slot in 'c'
1152
+
1153
+ int type;
1154
+ if(name[0] == '/') type = FILETYPE_FILE;
1155
+ else if(strncmp(name, "pipe:", 5) == 0) type = FILETYPE_PIPE;
1156
+ else if(strncmp(name, "socket:", 7) == 0) type = FILETYPE_SOCKET;
1157
+ else if(strcmp(name, "anon_inode:inotify") == 0 || strcmp(name, "inotify") == 0) type = FILETYPE_INOTIFY;
1158
+ else if(strcmp(name, "anon_inode:[eventfd]") == 0) type = FILETYPE_EVENTFD;
1159
+ else if(strcmp(name, "anon_inode:[eventpoll]") == 0) type = FILETYPE_EVENTPOLL;
1160
+ else if(strcmp(name, "anon_inode:[timerfd]") == 0) type = FILETYPE_TIMERFD;
1161
+ else if(strcmp(name, "anon_inode:[signalfd]") == 0) type = FILETYPE_SIGNALFD;
1162
+ else if(strncmp(name, "anon_inode:", 11) == 0) {
1163
+ if(unlikely(debug))
1164
+ fprintf(stderr, "apps.plugin: FIXME: unknown anonymous inode: %s\n", name);
1165
+
1166
+ type = FILETYPE_OTHER;
1167
+ }
1168
+ else {
1169
+ if(unlikely(debug))
1170
+ fprintf(stderr, "apps.plugin: FIXME: cannot understand linkname: %s\n", name);
1171
+
1172
+ type = FILETYPE_OTHER;
1173
+ }
1174
+
1175
+ all_files[c].name = strdupz(name);
1176
+ all_files[c].hash = hash;
1177
+ all_files[c].type = type;
1178
+ all_files[c].pos = c;
1179
+ all_files[c].count = 1;
1180
#ifdef NETDATA_INTERNAL_CHECKS
1181
- all_files[c].magic = 0x0BADCAFE;
1181
+ all_files[c].magic = 0x0BADCAFE;
1182
#endif /* NETDATA_INTERNAL_CHECKS */
1183
- file_descriptor_add(&all_files[c]);
1183
+ file_descriptor_add(&all_files[c]);
1184
1185
- if(unlikely(debug))
1186
- fprintf(stderr, "apps.plugin: using fd position %d (name: %s)\n", c, all_files[c].name);
1185
+ if(unlikely(debug))
1186
+ fprintf(stderr, "apps.plugin: using fd position %d (name: %s)\n", c, all_files[c].name);
1187
1188
- return c;
1188
+ return c;
1189
}
1190
1191
int read_pid_file_descriptors(struct pid_stat *p) {
1192
- char dirname[FILENAME_MAX+1];
1193
-
1194
- snprintfz(dirname, FILENAME_MAX, "%s/proc/%d/fd", host_prefix, p->pid);
1195
- DIR *fds = opendir(dirname);
1196
- if(fds) {
1197
- int c;
1198
- struct dirent *de;
1199
- char fdname[FILENAME_MAX + 1];
1200
- char linkname[FILENAME_MAX + 1];
1201
-
1202
- // make the array negative
1203
- for(c = 0 ; c < p->fds_size ; c++)
1204
- p->fds[c] = -p->fds[c];
1205
-
1206
- while((de = readdir(fds))) {
1207
- if(strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
1208
- continue;
1209
-
1210
- // check if the fds array is small
1211
- int fdid = atoi(de->d_name);
1212
- if(fdid < 0) continue;
1213
- if(fdid >= p->fds_size) {
1214
- // it is small, extend it
1215
- if(unlikely(debug))
1216
- fprintf(stderr, "apps.plugin: extending fd memory slots for %s from %d to %d\n", p->comm, p->fds_size, fdid + 100);
1217
-
1218
- p->fds = reallocz(p->fds, (fdid + 100) * sizeof(int));
1219
- if(!p->fds) {
1220
- fatal("Cannot re-allocate fds for %s", p->comm);
1221
- break;
1222
- }
1223
-
1224
- // and initialize it
1225
- for(c = p->fds_size ; c < (fdid + 100) ; c++) p->fds[c] = 0;
1226
- p->fds_size = fdid + 100;
1227
- }
1228
-
1229
- if(p->fds[fdid] == 0) {
1230
- // we don't know this fd, get it
1231
-
1232
- sprintf(fdname, "%s/proc/%d/fd/%s", host_prefix, p->pid, de->d_name);
1233
- ssize_t l = readlink(fdname, linkname, FILENAME_MAX);
1234
- if(l == -1) {
1235
- if(debug || (p->target && p->target->debug)) {
1236
- if(debug || (p->target && p->target->debug))
1237
- error("Cannot read link %s", fdname);
1238
- }
1239
- continue;
1240
- }
1241
- linkname[l] = '\0';
1242
- file_counter++;
1243
-
1244
- // if another process already has this, we will get
1245
- // the same id
1246
- p->fds[fdid] = file_descriptor_find_or_add(linkname);
1247
- }
1248
-
1249
- // else make it positive again, we need it
1250
- // of course, the actual file may have changed, but we don't care so much
1251
- // FIXME: we could compare the inode as returned by readdir direct structure
1252
- else p->fds[fdid] = -p->fds[fdid];
1253
- }
1254
- closedir(fds);
1255
-
1256
- // remove all the negative file descriptors
1257
- for(c = 0 ; c < p->fds_size ; c++) if(p->fds[c] < 0) {
1258
- file_descriptor_not_used(-p->fds[c]);
1259
- p->fds[c] = 0;
1260
- }
1261
- }
1262
- else return 1;
1263
-
1264
- return 0;
1192
+ char dirname[FILENAME_MAX+1];
1193
+
1194
+ snprintfz(dirname, FILENAME_MAX, "%s/proc/%d/fd", host_prefix, p->pid);
1195
+ DIR *fds = opendir(dirname);
1196
+ if(fds) {
1197
+ int c;
1198
+ struct dirent *de;
1199
+ char fdname[FILENAME_MAX + 1];
1200
+ char linkname[FILENAME_MAX + 1];
1201
+
1202
+ // make the array negative
1203
+ for(c = 0 ; c < p->fds_size ; c++)
1204
+ p->fds[c] = -p->fds[c];
1205
+
1206
+ while((de = readdir(fds))) {
1207
+ if(strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
1208
+ continue;
1209
+
1210
+ // check if the fds array is small
1211
+ int fdid = atoi(de->d_name);
1212
+ if(fdid < 0) continue;
1213
+ if(fdid >= p->fds_size) {
1214
+ // it is small, extend it
1215
+ if(unlikely(debug))
1216
+ fprintf(stderr, "apps.plugin: extending fd memory slots for %s from %d to %d\n", p->comm, p->fds_size, fdid + 100);
1217
+
1218
+ p->fds = reallocz(p->fds, (fdid + 100) * sizeof(int));
1219
+ if(!p->fds) {
1220
+ fatal("Cannot re-allocate fds for %s", p->comm);
1221
+ break;
1222
+ }
1223
+
1224
+ // and initialize it
1225
+ for(c = p->fds_size ; c < (fdid + 100) ; c++) p->fds[c] = 0;
1226
+ p->fds_size = fdid + 100;
1227
+ }
1228
+
1229
+ if(p->fds[fdid] == 0) {
1230
+ // we don't know this fd, get it
1231
+
1232
+ sprintf(fdname, "%s/proc/%d/fd/%s", host_prefix, p->pid, de->d_name);
1233
+ ssize_t l = readlink(fdname, linkname, FILENAME_MAX);
1234
+ if(l == -1) {
1235
+ if(debug || (p->target && p->target->debug)) {
1236
+ if(debug || (p->target && p->target->debug))
1237
+ error("Cannot read link %s", fdname);
1238
+ }
1239
+ continue;
1240
+ }
1241
+ linkname[l] = '\0';
1242
+ file_counter++;
1243
+
1244
+ // if another process already has this, we will get
1245
+ // the same id
1246
+ p->fds[fdid] = file_descriptor_find_or_add(linkname);
1247
+ }
1248
+
1249
+ // else make it positive again, we need it
1250
+ // of course, the actual file may have changed, but we don't care so much
1251
+ // FIXME: we could compare the inode as returned by readdir direct structure
1252
+ else p->fds[fdid] = -p->fds[fdid];
1253
+ }
1254
+ closedir(fds);
1255
+
1256
+ // remove all the negative file descriptors
1257
+ for(c = 0 ; c < p->fds_size ; c++) if(p->fds[c] < 0) {
1258
+ file_descriptor_not_used(-p->fds[c]);
1259
+ p->fds[c] = 0;
1260
+ }
1261
+ }
1262
+ else return 1;
1263
+
1264
+ return 0;
1265
}
1266
1267
// ----------------------------------------------------------------------------
1268
1269
int print_process_and_parents(struct pid_stat *p, unsigned long long time) {
1270
- char *prefix = "\\_ ";
1271
- int indent = 0;
1272
-
1273
- if(p->parent)
1274
- indent = print_process_and_parents(p->parent, p->stat_collected_usec);
1275
- else
1276
- prefix = " > ";
1277
-
1278
- char buffer[indent + 1];
1279
- int i;
1280
-
1281
- for(i = 0; i < indent ;i++) buffer[i] = ' ';
1282
- buffer[i] = '\0';
1283
-
1284
- fprintf(stderr, " %s %s%s (%d %s %lld"
1285
- , buffer
1286
- , prefix
1287
- , p->comm
1288
- , p->pid
1289
- , p->updated?"running":"exited"
1290
- , (long long)p->stat_collected_usec - (long long)time
1291
- );
1292
-
1293
- if(p->utime) fprintf(stderr, " utime=%llu", p->utime);
1294
- if(p->stime) fprintf(stderr, " stime=%llu", p->stime);
1295
- if(p->gtime) fprintf(stderr, " gtime=%llu", p->gtime);
1296
- if(p->cutime) fprintf(stderr, " cutime=%llu", p->cutime);
1297
- if(p->cstime) fprintf(stderr, " cstime=%llu", p->cstime);
1298
- if(p->cgtime) fprintf(stderr, " cgtime=%llu", p->cgtime);
1299
- if(p->minflt) fprintf(stderr, " minflt=%llu", p->minflt);
1300
- if(p->cminflt) fprintf(stderr, " cminflt=%llu", p->cminflt);
1301
- if(p->majflt) fprintf(stderr, " majflt=%llu", p->majflt);
1302
- if(p->cmajflt) fprintf(stderr, " cmajflt=%llu", p->cmajflt);
1303
- fprintf(stderr, ")\n");
1304
-
1305
- return indent + 1;
1270
+ char *prefix = "\\_ ";
1271
+ int indent = 0;
1272
+
1273
+ if(p->parent)
1274
+ indent = print_process_and_parents(p->parent, p->stat_collected_usec);
1275
+ else
1276
+ prefix = " > ";
1277
+
1278
+ char buffer[indent + 1];
1279
+ int i;
1280
+
1281
+ for(i = 0; i < indent ;i++) buffer[i] = ' ';
1282
+ buffer[i] = '\0';
1283
+
1284
+ fprintf(stderr, " %s %s%s (%d %s %lld"
1285
+ , buffer
1286
+ , prefix
1287
+ , p->comm
1288
+ , p->pid
1289
+ , p->updated?"running":"exited"
1290
+ , (long long)p->stat_collected_usec - (long long)time
1291
+ );
1292
+
1293
+ if(p->utime) fprintf(stderr, " utime=%llu", p->utime);
1294
+ if(p->stime) fprintf(stderr, " stime=%llu", p->stime);
1295
+ if(p->gtime) fprintf(stderr, " gtime=%llu", p->gtime);
1296
+ if(p->cutime) fprintf(stderr, " cutime=%llu", p->cutime);
1297
+ if(p->cstime) fprintf(stderr, " cstime=%llu", p->cstime);
1298
+ if(p->cgtime) fprintf(stderr, " cgtime=%llu", p->cgtime);
1299
+ if(p->minflt) fprintf(stderr, " minflt=%llu", p->minflt);
1300
+ if(p->cminflt) fprintf(stderr, " cminflt=%llu", p->cminflt);
1301
+ if(p->majflt) fprintf(stderr, " majflt=%llu", p->majflt);
1302
+ if(p->cmajflt) fprintf(stderr, " cmajflt=%llu", p->cmajflt);
1303
+ fprintf(stderr, ")\n");
1304
+
1305
+ return indent + 1;
1306
}
1307
1308
void print_process_tree(struct pid_stat *p, char *msg) {
1309
- log_date(stderr);
1310
- fprintf(stderr, "%s: process %s (%d, %s) with parents:\n", msg, p->comm, p->pid, p->updated?"running":"exited");
1311
- print_process_and_parents(p, p->stat_collected_usec);
1309
+ log_date(stderr);
1310
+ fprintf(stderr, "%s: process %s (%d, %s) with parents:\n", msg, p->comm, p->pid, p->updated?"running":"exited");
1311
+ print_process_and_parents(p, p->stat_collected_usec);
1312
}
1313
1314
void find_lost_child_debug(struct pid_stat *pe, unsigned long long lost, int type) {
1315
- int found = 0;
1316
- struct pid_stat *p = NULL;
1317
-
1318
- for(p = root_of_pids; p ; p = p->next) {
1319
- if(p == pe) continue;
1320
-
1321
- switch(type) {
1322
- case 1:
1323
- if(p->cminflt > lost) {
1324
- fprintf(stderr, " > process %d (%s) could use the lost exited child minflt %llu of process %d (%s)\n", p->pid, p->comm, lost, pe->pid, pe->comm);
1325
- found++;
1326
- }
1327
- break;
1328
-
1329
- case 2:
1330
- if(p->cmajflt > lost) {
1331
- fprintf(stderr, " > process %d (%s) could use the lost exited child majflt %llu of process %d (%s)\n", p->pid, p->comm, lost, pe->pid, pe->comm);
1332
- found++;
1333
- }
1334
- break;
1335
-
1336
- case 3:
1337
- if(p->cutime > lost) {
1338
- fprintf(stderr, " > process %d (%s) could use the lost exited child utime %llu of process %d (%s)\n", p->pid, p->comm, lost, pe->pid, pe->comm);
1339
- found++;
1340
- }
1341
- break;
1342
-
1343
- case 4:
1344
- if(p->cstime > lost) {
1345
- fprintf(stderr, " > process %d (%s) could use the lost exited child stime %llu of process %d (%s)\n", p->pid, p->comm, lost, pe->pid, pe->comm);
1346
- found++;
1347
- }
1348
- break;
1349
-
1350
- case 5:
1351
- if(p->cgtime > lost) {
1352
- fprintf(stderr, " > process %d (%s) could use the lost exited child gtime %llu of process %d (%s)\n", p->pid, p->comm, lost, pe->pid, pe->comm);
1353
- found++;
1354
- }
1355
- break;
1356
- }
1357
- }
1358
-
1359
- if(!found) {
1360
- switch(type) {
1361
- case 1:
1362
- fprintf(stderr, " > cannot find any process to use the lost exited child minflt %llu of process %d (%s)\n", lost, pe->pid, pe->comm);
1363
- break;
1364
-
1365
- case 2:
1366
- fprintf(stderr, " > cannot find any process to use the lost exited child majflt %llu of process %d (%s)\n", lost, pe->pid, pe->comm);
1367
- break;
1368
-
1369
- case 3:
1370
- fprintf(stderr, " > cannot find any process to use the lost exited child utime %llu of process %d (%s)\n", lost, pe->pid, pe->comm);
1371
- break;
1372
-
1373
- case 4:
1374
- fprintf(stderr, " > cannot find any process to use the lost exited child stime %llu of process %d (%s)\n", lost, pe->pid, pe->comm);
1375
- break;
1376
-
1377
- case 5:
1378
- fprintf(stderr, " > cannot find any process to use the lost exited child gtime %llu of process %d (%s)\n", lost, pe->pid, pe->comm);
1379
- break;
1380
- }
1381
- }
1315
+ int found = 0;
1316
+ struct pid_stat *p = NULL;
1317
+
1318
+ for(p = root_of_pids; p ; p = p->next) {
1319
+ if(p == pe) continue;
1320
+
1321
+ switch(type) {
1322
+ case 1:
1323
+ if(p->cminflt > lost) {
1324
+ fprintf(stderr, " > process %d (%s) could use the lost exited child minflt %llu of process %d (%s)\n", p->pid, p->comm, lost, pe->pid, pe->comm);
1325
+ found++;
1326
+ }
1327
+ break;
1328
+
1329
+ case 2:
1330
+ if(p->cmajflt > lost) {
1331
+ fprintf(stderr, " > process %d (%s) could use the lost exited child majflt %llu of process %d (%s)\n", p->pid, p->comm, lost, pe->pid, pe->comm);
1332
+ found++;
1333
+ }
1334
+ break;
1335
+
1336
+ case 3:
1337
+ if(p->cutime > lost) {
1338
+ fprintf(stderr, " > process %d (%s) could use the lost exited child utime %llu of process %d (%s)\n", p->pid, p->comm, lost, pe->pid, pe->comm);
1339
+ found++;
1340
+ }
1341
+ break;
1342
+
1343
+ case 4:
1344
+ if(p->cstime > lost) {
1345
+ fprintf(stderr, " > process %d (%s) could use the lost exited child stime %llu of process %d (%s)\n", p->pid, p->comm, lost, pe->pid, pe->comm);
1346
+ found++;
1347
+ }
1348
+ break;
1349
+
1350
+ case 5:
1351
+ if(p->cgtime > lost) {
1352
+ fprintf(stderr, " > process %d (%s) could use the lost exited child gtime %llu of process %d (%s)\n", p->pid, p->comm, lost, pe->pid, pe->comm);
1353
+ found++;
1354
+ }
1355
+ break;
1356
+ }
1357
+ }
1358
+
1359
+ if(!found) {
1360
+ switch(type) {
1361
+ case 1:
1362
+ fprintf(stderr, " > cannot find any process to use the lost exited child minflt %llu of process %d (%s)\n", lost, pe->pid, pe->comm);
1363
+ break;
1364
+
1365
+ case 2:
1366
+ fprintf(stderr, " > cannot find any process to use the lost exited child majflt %llu of process %d (%s)\n", lost, pe->pid, pe->comm);
1367
+ break;
1368
+
1369
+ case 3:
1370
+ fprintf(stderr, " > cannot find any process to use the lost exited child utime %llu of process %d (%s)\n", lost, pe->pid, pe->comm);
1371
+ break;
1372
+
1373
+ case 4:
1374
+ fprintf(stderr, " > cannot find any process to use the lost exited child stime %llu of process %d (%s)\n", lost, pe->pid, pe->comm);
1375
+ break;
1376
+
1377
+ case 5:
1378
+ fprintf(stderr, " > cannot find any process to use the lost exited child gtime %llu of process %d (%s)\n", lost, pe->pid, pe->comm);
1379
+ break;
1380
+ }
1381
+ }
1382
}
1383
1384
unsigned long long remove_exited_child_from_parent(unsigned long long *field, unsigned long long *pfield) {
1385
- unsigned long long absorbed = 0;
1386
-
1387
- if(*field > *pfield) {
1388
- absorbed += *pfield;
1389
- *field -= *pfield;
1390
- *pfield = 0;
1391
- }
1392
- else {
1393
- absorbed += *field;
1394
- *pfield -= *field;
1395
- *field = 0;
1396
- }
1397
-
1398
- return absorbed;
1385
+ unsigned long long absorbed = 0;
1386
+
1387
+ if(*field > *pfield) {
1388
+ absorbed += *pfield;
1389
+ *field -= *pfield;
1390
+ *pfield = 0;
1391
+ }
1392
+ else {
1393
+ absorbed += *field;
1394
+ *pfield -= *field;
1395
+ *field = 0;
1396
+ }
1397
+
1398
+ return absorbed;
1399
}
1400
1401
void process_exited_processes() {
1402
- struct pid_stat *p;
1403
-
1404
- for(p = root_of_pids; p ; p = p->next) {
1405
- if(p->updated || !p->stat_collected_usec)
1406
- continue;
1407
-
1408
- struct pid_stat *pp = p->parent;
1409
-
1410
- unsigned long long utime = (p->utime_raw + p->cutime_raw) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
1411
- unsigned long long stime = (p->stime_raw + p->cstime_raw) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
1412
- unsigned long long gtime = (p->gtime_raw + p->cgtime_raw) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
1413
- unsigned long long minflt = (p->minflt_raw + p->cminflt_raw) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
1414
- unsigned long long majflt = (p->majflt_raw + p->cmajflt_raw) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
1415
-
1416
- if(utime + stime + gtime + minflt + majflt == 0)
1417
- continue;
1418
-
1419
- if(unlikely(debug)) {
1420
- log_date(stderr);
1421
- fprintf(stderr, "Absorb %s (%d %s total resources: utime=%llu stime=%llu gtime=%llu minflt=%llu majflt=%llu)\n"
1422
- , p->comm
1423
- , p->pid
1424
- , p->updated?"running":"exited"
1425
- , utime
1426
- , stime
1427
- , gtime
1428
- , minflt
1429
- , majflt
1430
- );
1431
- print_process_tree(p, "Searching parents");
1432
- }
1433
-
1434
- for(pp = p->parent; pp ; pp = pp->parent) {
1435
- if(!pp->updated) continue;
1436
-
1437
- unsigned long long absorbed;
1438
- absorbed = remove_exited_child_from_parent(&utime, &pp->cutime);
1439
- if(unlikely(debug && absorbed))
1440
- fprintf(stderr, " > process %s (%d %s) absorbed %llu utime (remaining: %llu)\n", pp->comm, pp->pid, pp->updated?"running":"exited", absorbed, utime);
1441
-
1442
- absorbed = remove_exited_child_from_parent(&stime, &pp->cstime);
1443
- if(unlikely(debug && absorbed))
1444
- fprintf(stderr, " > process %s (%d %s) absorbed %llu stime (remaining: %llu)\n", pp->comm, pp->pid, pp->updated?"running":"exited", absorbed, stime);
1445
-
1446
- absorbed = remove_exited_child_from_parent(>ime, &pp->cgtime);
1447
- if(unlikely(debug && absorbed))
1448
- fprintf(stderr, " > process %s (%d %s) absorbed %llu gtime (remaining: %llu)\n", pp->comm, pp->pid, pp->updated?"running":"exited", absorbed, gtime);
1449
-
1450
- absorbed = remove_exited_child_from_parent(&minflt, &pp->cminflt);
1451
- if(unlikely(debug && absorbed))
1452
- fprintf(stderr, " > process %s (%d %s) absorbed %llu minflt (remaining: %llu)\n", pp->comm, pp->pid, pp->updated?"running":"exited", absorbed, minflt);
1453
-
1454
- absorbed = remove_exited_child_from_parent(&majflt, &pp->cmajflt);
1455
- if(unlikely(debug && absorbed))
1456
- fprintf(stderr, " > process %s (%d %s) absorbed %llu majflt (remaining: %llu)\n", pp->comm, pp->pid, pp->updated?"running":"exited", absorbed, majflt);
1457
- }
1458
-
1459
- if(unlikely(utime + stime + gtime + minflt + majflt > 0)) {
1460
- if(unlikely(debug)) {
1461
- if(utime) find_lost_child_debug(p, utime, 3);
1462
- if(stime) find_lost_child_debug(p, stime, 4);
1463
- if(gtime) find_lost_child_debug(p, gtime, 5);
1464
- if(minflt) find_lost_child_debug(p, minflt, 1);
1465
- if(majflt) find_lost_child_debug(p, majflt, 2);
1466
- }
1467
-
1468
- p->keep = 1;
1469
-
1470
- if(unlikely(debug))
1471
- fprintf(stderr, " > remaining resources - KEEP - for another loop: %s (%d %s total resources: utime=%llu stime=%llu gtime=%llu minflt=%llu majflt=%llu)\n"
1472
- , p->comm
1473
- , p->pid
1474
- , p->updated?"running":"exited"
1475
- , utime
1476
- , stime
1477
- , gtime
1478
- , minflt
1479
- , majflt
1480
- );
1481
-
1482
- for(pp = p->parent; pp ; pp = pp->parent) {
1483
- if(pp->updated) break;
1484
- pp->keep = 1;
1485
-
1486
- if(unlikely(debug))
1487
- fprintf(stderr, " > - KEEP - parent for another loop: %s (%d %s)\n"
1488
- , pp->comm
1489
- , pp->pid
1490
- , pp->updated?"running":"exited"
1491
- );
1492
- }
1493
-
1494
- p->utime_raw = utime * (p->stat_collected_usec - p->last_stat_collected_usec) / (1000000ULL * RATES_DETAIL);
1495
- p->stime_raw = stime * (p->stat_collected_usec - p->last_stat_collected_usec) / (1000000ULL * RATES_DETAIL);
1496
- p->gtime_raw = gtime * (p->stat_collected_usec - p->last_stat_collected_usec) / (1000000ULL * RATES_DETAIL);
1497
- p->minflt_raw = minflt * (p->stat_collected_usec - p->last_stat_collected_usec) / (1000000ULL * RATES_DETAIL);
1498
- p->majflt_raw = majflt * (p->stat_collected_usec - p->last_stat_collected_usec) / (1000000ULL * RATES_DETAIL);
1499
- p->cutime_raw = p->cstime_raw = p->cgtime_raw = p->cminflt_raw = p->cmajflt_raw = 0;
1500
-
1501
- if(unlikely(debug))
1502
- fprintf(stderr, "\n");
1503
- }
1504
- else if(unlikely(debug)) {
1505
- fprintf(stderr, " > totally absorbed - DONE - %s (%d %s)\n"
1506
- , p->comm
1507
- , p->pid
1508
- , p->updated?"running":"exited"
1509
- );
1510
- }
1511
- }
1402
+ struct pid_stat *p;
1403
+
1404
+ for(p = root_of_pids; p ; p = p->next) {
1405
+ if(p->updated || !p->stat_collected_usec)
1406
+ continue;
1407
+
1408
+ struct pid_stat *pp = p->parent;
1409
+
1410
+ unsigned long long utime = (p->utime_raw + p->cutime_raw) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
1411
+ unsigned long long stime = (p->stime_raw + p->cstime_raw) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
1412
+ unsigned long long gtime = (p->gtime_raw + p->cgtime_raw) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
1413
+ unsigned long long minflt = (p->minflt_raw + p->cminflt_raw) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
1414
+ unsigned long long majflt = (p->majflt_raw + p->cmajflt_raw) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
1415
+
1416
+ if(utime + stime + gtime + minflt + majflt == 0)
1417
+ continue;
1418
+
1419
+ if(unlikely(debug)) {
1420
+ log_date(stderr);
1421
+ fprintf(stderr, "Absorb %s (%d %s total resources: utime=%llu stime=%llu gtime=%llu minflt=%llu majflt=%llu)\n"
1422
+ , p->comm
1423
+ , p->pid
1424
+ , p->updated?"running":"exited"
1425
+ , utime
1426
+ , stime
1427
+ , gtime
1428
+ , minflt
1429
+ , majflt
1430
+ );
1431
+ print_process_tree(p, "Searching parents");
1432
+ }
1433
+
1434
+ for(pp = p->parent; pp ; pp = pp->parent) {
1435
+ if(!pp->updated) continue;
1436
+
1437
+ unsigned long long absorbed;
1438
+ absorbed = remove_exited_child_from_parent(&utime, &pp->cutime);
1439
+ if(unlikely(debug && absorbed))
1440
+ fprintf(stderr, " > process %s (%d %s) absorbed %llu utime (remaining: %llu)\n", pp->comm, pp->pid, pp->updated?"running":"exited", absorbed, utime);
1441
+
1442
+ absorbed = remove_exited_child_from_parent(&stime, &pp->cstime);
1443
+ if(unlikely(debug && absorbed))
1444
+ fprintf(stderr, " > process %s (%d %s) absorbed %llu stime (remaining: %llu)\n", pp->comm, pp->pid, pp->updated?"running":"exited", absorbed, stime);
1445
+
1446
+ absorbed = remove_exited_child_from_parent(>ime, &pp->cgtime);
1447
+ if(unlikely(debug && absorbed))
1448
+ fprintf(stderr, " > process %s (%d %s) absorbed %llu gtime (remaining: %llu)\n", pp->comm, pp->pid, pp->updated?"running":"exited", absorbed, gtime);
1449
+
1450
+ absorbed = remove_exited_child_from_parent(&minflt, &pp->cminflt);
1451
+ if(unlikely(debug && absorbed))
1452
+ fprintf(stderr, " > process %s (%d %s) absorbed %llu minflt (remaining: %llu)\n", pp->comm, pp->pid, pp->updated?"running":"exited", absorbed, minflt);
1453
+
1454
+ absorbed = remove_exited_child_from_parent(&majflt, &pp->cmajflt);
1455
+ if(unlikely(debug && absorbed))
1456
+ fprintf(stderr, " > process %s (%d %s) absorbed %llu majflt (remaining: %llu)\n", pp->comm, pp->pid, pp->updated?"running":"exited", absorbed, majflt);
1457
+ }
1458
+
1459
+ if(unlikely(utime + stime + gtime + minflt + majflt > 0)) {
1460
+ if(unlikely(debug)) {
1461
+ if(utime) find_lost_child_debug(p, utime, 3);
1462
+ if(stime) find_lost_child_debug(p, stime, 4);
1463
+ if(gtime) find_lost_child_debug(p, gtime, 5);
1464
+ if(minflt) find_lost_child_debug(p, minflt, 1);
1465
+ if(majflt) find_lost_child_debug(p, majflt, 2);
1466
+ }
1467
+
1468
+ p->keep = 1;
1469
+
1470
+ if(unlikely(debug))
1471
+ fprintf(stderr, " > remaining resources - KEEP - for another loop: %s (%d %s total resources: utime=%llu stime=%llu gtime=%llu minflt=%llu majflt=%llu)\n"
1472
+ , p->comm
1473
+ , p->pid
1474
+ , p->updated?"running":"exited"
1475
+ , utime
1476
+ , stime
1477
+ , gtime
1478
+ , minflt
1479
+ , majflt
1480
+ );
1481
+
1482
+ for(pp = p->parent; pp ; pp = pp->parent) {
1483
+ if(pp->updated) break;
1484
+ pp->keep = 1;
1485
+
1486
+ if(unlikely(debug))
1487
+ fprintf(stderr, " > - KEEP - parent for another loop: %s (%d %s)\n"
1488
+ , pp->comm
1489
+ , pp->pid
1490
+ , pp->updated?"running":"exited"
1491
+ );
1492
+ }
1493
+
1494
+ p->utime_raw = utime * (p->stat_collected_usec - p->last_stat_collected_usec) / (1000000ULL * RATES_DETAIL);
1495
+ p->stime_raw = stime * (p->stat_collected_usec - p->last_stat_collected_usec) / (1000000ULL * RATES_DETAIL);
1496
+ p->gtime_raw = gtime * (p->stat_collected_usec - p->last_stat_collected_usec) / (1000000ULL * RATES_DETAIL);
1497
+ p->minflt_raw = minflt * (p->stat_collected_usec - p->last_stat_collected_usec) / (1000000ULL * RATES_DETAIL);
1498
+ p->majflt_raw = majflt * (p->stat_collected_usec - p->last_stat_collected_usec) / (1000000ULL * RATES_DETAIL);
1499
+ p->cutime_raw = p->cstime_raw = p->cgtime_raw = p->cminflt_raw = p->cmajflt_raw = 0;
1500
+
1501
+ if(unlikely(debug))
1502
+ fprintf(stderr, "\n");
1503
+ }
1504
+ else if(unlikely(debug)) {
1505
+ fprintf(stderr, " > totally absorbed - DONE - %s (%d %s)\n"
1506
+ , p->comm
1507
+ , p->pid
1508
+ , p->updated?"running":"exited"
1509
+ );
1510
+ }
1511
+ }
1512
}
1513
1514
void link_all_processes_to_their_parents(void) {
1515
- struct pid_stat *p, *pp;
1516
-
1517
- // link all children to their parents
1518
- // and update children count on parents
1519
- for(p = root_of_pids; p ; p = p->next) {
1520
- // for each process found
1521
-
1522
- p->sortlist = 0;
1523
- p->parent = NULL;
1524
-
1525
- if(unlikely(!p->ppid)) {
1526
- p->parent = NULL;
1527
- continue;
1528
- }
1529
-
1530
- pp = all_pids[p->ppid];
1531
- if(likely(pp)) {
1532
- p->parent = pp;
1533
- pp->children_count++;
1534
-
1535
- if(unlikely(debug || (p->target && p->target->debug)))
1536
- fprintf(stderr, "apps.plugin: \tchild %d (%s, %s) on target '%s' has parent %d (%s, %s). Parent: utime=%llu, stime=%llu, gtime=%llu, minflt=%llu, majflt=%llu, cutime=%llu, cstime=%llu, cgtime=%llu, cminflt=%llu, cmajflt=%llu\n", p->pid, p->comm, p->updated?"running":"exited", (p->target)?p->target->name:"UNSET", pp->pid, pp->comm, pp->updated?"running":"exited", pp->utime, pp->stime, pp->gtime, pp->minflt, pp->majflt, pp->cutime, pp->cstime, pp->cgtime, pp->cminflt, pp->cmajflt);
1537
- }
1538
- else {
1539
- p->parent = NULL;
1540
- error("pid %d %s states parent %d, but the later does not exist.", p->pid, p->comm, p->ppid);
1541
- }
1542
- }
1515
+ struct pid_stat *p, *pp;
1516
+
1517
+ // link all children to their parents
1518
+ // and update children count on parents
1519
+ for(p = root_of_pids; p ; p = p->next) {
1520
+ // for each process found
1521
+
1522
+ p->sortlist = 0;
1523
+ p->parent = NULL;
1524
+
1525
+ if(unlikely(!p->ppid)) {
1526
+ p->parent = NULL;
1527
+ continue;
1528
+ }
1529
+
1530
+ pp = all_pids[p->ppid];
1531
+ if(likely(pp)) {
1532
+ p->parent = pp;
1533
+ pp->children_count++;
1534
+
1535
+ if(unlikely(debug || (p->target && p->target->debug)))
1536
+ fprintf(stderr, "apps.plugin: \tchild %d (%s, %s) on target '%s' has parent %d (%s, %s). Parent: utime=%llu, stime=%llu, gtime=%llu, minflt=%llu, majflt=%llu, cutime=%llu, cstime=%llu, cgtime=%llu, cminflt=%llu, cmajflt=%llu\n", p->pid, p->comm, p->updated?"running":"exited", (p->target)?p->target->name:"UNSET", pp->pid, pp->comm, pp->updated?"running":"exited", pp->utime, pp->stime, pp->gtime, pp->minflt, pp->majflt, pp->cutime, pp->cstime, pp->cgtime, pp->cminflt, pp->cmajflt);
1537
+ }
1538
+ else {
1539
+ p->parent = NULL;
1540
+ error("pid %d %s states parent %d, but the later does not exist.", p->pid, p->comm, p->ppid);
1541
+ }
1542
+ }
1543
}
1544
1545
// ----------------------------------------------------------------------------
@@ -1562,203 +1562,203 @@ void link_all_processes_to_their_parents(void) {
1562
1563
static int compar_pid(const void *pid1, const void *pid2) {
1564
1565
- struct pid_stat *p1 = all_pids[*((pid_t *)pid1)];
1566
- struct pid_stat *p2 = all_pids[*((pid_t *)pid2)];
1565
+ struct pid_stat *p1 = all_pids[*((pid_t *)pid1)];
1566
+ struct pid_stat *p2 = all_pids[*((pid_t *)pid2)];
1567
1568
- if(p1->sortlist > p2->sortlist)
1569
- return -1;
1570
- else
1571
- return 1;
1568
+ if(p1->sortlist > p2->sortlist)
1569
+ return -1;
1570
+ else
1571
+ return 1;
1572
}
1573
1574
void collect_data_for_pid(pid_t pid) {
1575
- if(unlikely(pid <= 0 || pid > pid_max)) {
1576
- error("Invalid pid %d read (expected 1 to %d). Ignoring process.", pid, pid_max);
1577
- return;
1578
- }
1579
-
1580
- struct pid_stat *p = get_pid_entry(pid);
1581
- if(unlikely(!p || p->read)) return;
1582
- p->read = 1;
1583
-
1584
- // fprintf(stderr, "Reading process %d (%s), sortlist %d\n", p->pid, p->comm, p->sortlist);
1585
-
1586
- // --------------------------------------------------------------------
1587
- // /proc/<pid>/stat
1588
-
1589
- if(unlikely(read_proc_pid_stat(p))) {
1590
- if(errno != ENOENT || debug)
1591
- error("Cannot process %s/proc/%d/stat (command '%s')", host_prefix, pid, p->comm);
1592
- else
1593
- errno = 0;
1594
- // there is no reason to proceed if we cannot get its status
1595
- return;
1596
- }
1597
-
1598
- read_proc_pid_ownership(p);
1599
-
1600
- // check its parent pid
1601
- if(unlikely(p->ppid < 0 || p->ppid > pid_max)) {
1602
- error("Pid %d (command '%s') states invalid parent pid %d. Using 0.", pid, p->comm, p->ppid);
1603
- p->ppid = 0;
1604
- }
1605
-
1606
- // --------------------------------------------------------------------
1607
- // /proc/<pid>/io
1608
-
1609
- if(unlikely(read_proc_pid_io(p))) {
1610
- if(errno != ENOENT || debug)
1611
- error("Cannot process %s/proc/%d/io (command '%s')", host_prefix, pid, p->comm);
1612
- else
1613
- errno = 0;
1614
- }
1615
-
1616
- // --------------------------------------------------------------------
1617
- // /proc/<pid>/statm
1618
-
1619
- if(unlikely(read_proc_pid_statm(p))) {
1620
- if(errno != ENOENT || debug)
1621
- error("Cannot process %s/proc/%d/statm (command '%s')", host_prefix, pid, p->comm);
1622
- else
1623
- errno = 0;
1624
- // there is no reason to proceed if we cannot get its memory status
1625
- return;
1626
- }
1627
-
1628
- // --------------------------------------------------------------------
1629
- // link it
1630
-
1631
- // check if it is target
1632
- // we do this only once, the first time this pid is loaded
1633
- if(unlikely(p->new_entry)) {
1634
- // /proc/<pid>/cmdline
1635
- if(likely(proc_pid_cmdline_is_needed)) {
1636
- if(unlikely(read_proc_pid_cmdline(p))) {
1637
- if(errno != ENOENT || debug)
1638
- error("Cannot process %s/proc/%d/cmdline (command '%s')", host_prefix, pid, p->comm);
1639
- else
1640
- errno = 0;
1641
- }
1642
- }
1643
-
1644
- if(unlikely(debug))
1645
- fprintf(stderr, "apps.plugin: \tJust added %d (%s)\n", pid, p->comm);
1646
-
1647
- uint32_t hash = simple_hash(p->comm);
1648
- size_t pclen = strlen(p->comm);
1649
-
1650
- struct target *w;
1651
- for(w = apps_groups_root_target; w ; w = w->next) {
1652
- // if(debug || (p->target && p->target->debug)) fprintf(stderr, "apps.plugin: \t\tcomparing '%s' with '%s'\n", w->compare, p->comm);
1653
-
1654
- // find it - 4 cases:
1655
- // 1. the target is not a pattern
1656
- // 2. the target has the prefix
1657
- // 3. the target has the suffix
1658
- // 4. the target is something inside cmdline
1659
- if( (!w->starts_with && !w->ends_with && w->comparehash == hash && !strcmp(w->compare, p->comm))
1660
- || (w->starts_with && !w->ends_with && !strncmp(w->compare, p->comm, w->comparelen))
1661
- || (!w->starts_with && w->ends_with && pclen >= w->comparelen && !strcmp(w->compare, &p->comm[pclen - w->comparelen]))
1662
- || (proc_pid_cmdline_is_needed && w->starts_with && w->ends_with && strstr(p->cmdline, w->compare))
1663
- ) {
1664
- if(w->target) p->target = w->target;
1665
- else p->target = w;
1666
-
1667
- if(debug || (p->target && p->target->debug))
1668
- fprintf(stderr, "apps.plugin: \t\t%s linked to target %s\n", p->comm, p->target->name);
1669
-
1670
- break;
1671
- }
1672
- }
1673
- }
1674
-
1675
- // --------------------------------------------------------------------
1676
- // /proc/<pid>/fd
1677
-
1678
- if(unlikely(read_pid_file_descriptors(p))) {
1679
- if(errno != ENOENT || debug)
1680
- error("Cannot process entries in %s/proc/%d/fd (command '%s')", host_prefix, pid, p->comm);
1681
- else
1682
- errno = 0;
1683
- }
1684
-
1685
- // --------------------------------------------------------------------
1686
- // done!
1687
-
1688
- if(unlikely(debug && include_exited_childs && all_pids_count && p->ppid && all_pids[p->ppid] && !all_pids[p->ppid]->read))
1689
- fprintf(stderr, "Read process %d (%s) sortlisted %d, but its parent %d (%s) sortlisted %d, is not read\n", p->pid, p->comm, p->sortlist, all_pids[p->ppid]->pid, all_pids[p->ppid]->comm, all_pids[p->ppid]->sortlist);
1690
-
1691
- // mark it as updated
1692
- p->updated = 1;
1693
- p->keep = 0;
1694
- p->keeploops = 0;
1575
+ if(unlikely(pid <= 0 || pid > pid_max)) {
1576
+ error("Invalid pid %d read (expected 1 to %d). Ignoring process.", pid, pid_max);
1577
+ return;
1578
+ }
1579
+
1580
+ struct pid_stat *p = get_pid_entry(pid);
1581
+ if(unlikely(!p || p->read)) return;
1582
+ p->read = 1;
1583
+
1584
+ // fprintf(stderr, "Reading process %d (%s), sortlist %d\n", p->pid, p->comm, p->sortlist);
1585
+
1586
+ // --------------------------------------------------------------------
1587
+ // /proc/<pid>/stat
1588
+
1589
+ if(unlikely(read_proc_pid_stat(p))) {
1590
+ if(errno != ENOENT || debug)
1591
+ error("Cannot process %s/proc/%d/stat (command '%s')", host_prefix, pid, p->comm);
1592
+ else
1593
+ errno = 0;
1594
+ // there is no reason to proceed if we cannot get its status
1595
+ return;
1596
+ }
1597
+
1598
+ read_proc_pid_ownership(p);
1599
+
1600
+ // check its parent pid
1601
+ if(unlikely(p->ppid < 0 || p->ppid > pid_max)) {
1602
+ error("Pid %d (command '%s') states invalid parent pid %d. Using 0.", pid, p->comm, p->ppid);
1603
+ p->ppid = 0;
1604
+ }
1605
+
1606
+ // --------------------------------------------------------------------
1607
+ // /proc/<pid>/io
1608
+
1609
+ if(unlikely(read_proc_pid_io(p))) {
1610
+ if(errno != ENOENT || debug)
1611
+ error("Cannot process %s/proc/%d/io (command '%s')", host_prefix, pid, p->comm);
1612
+ else
1613
+ errno = 0;
1614
+ }
1615
+
1616
+ // --------------------------------------------------------------------
1617
+ // /proc/<pid>/statm
1618
+
1619
+ if(unlikely(read_proc_pid_statm(p))) {
1620
+ if(errno != ENOENT || debug)
1621
+ error("Cannot process %s/proc/%d/statm (command '%s')", host_prefix, pid, p->comm);
1622
+ else
1623
+ errno = 0;
1624
+ // there is no reason to proceed if we cannot get its memory status
1625
+ return;
1626
+ }
1627
+
1628
+ // --------------------------------------------------------------------
1629
+ // link it
1630
+
1631
+ // check if it is target
1632
+ // we do this only once, the first time this pid is loaded
1633
+ if(unlikely(p->new_entry)) {
1634
+ // /proc/<pid>/cmdline
1635
+ if(likely(proc_pid_cmdline_is_needed)) {
1636
+ if(unlikely(read_proc_pid_cmdline(p))) {
1637
+ if(errno != ENOENT || debug)
1638
+ error("Cannot process %s/proc/%d/cmdline (command '%s')", host_prefix, pid, p->comm);
1639
+ else
1640
+ errno = 0;
1641
+ }
1642
+ }
1643
+
1644
+ if(unlikely(debug))
1645
+ fprintf(stderr, "apps.plugin: \tJust added %d (%s)\n", pid, p->comm);
1646
+
1647
+ uint32_t hash = simple_hash(p->comm);
1648
+ size_t pclen = strlen(p->comm);
1649
+
1650
+ struct target *w;
1651
+ for(w = apps_groups_root_target; w ; w = w->next) {
1652
+ // if(debug || (p->target && p->target->debug)) fprintf(stderr, "apps.plugin: \t\tcomparing '%s' with '%s'\n", w->compare, p->comm);
1653
+
1654
+ // find it - 4 cases:
1655
+ // 1. the target is not a pattern
1656
+ // 2. the target has the prefix
1657
+ // 3. the target has the suffix
1658
+ // 4. the target is something inside cmdline
1659
+ if( (!w->starts_with && !w->ends_with && w->comparehash == hash && !strcmp(w->compare, p->comm))
1660
+ || (w->starts_with && !w->ends_with && !strncmp(w->compare, p->comm, w->comparelen))
1661
+ || (!w->starts_with && w->ends_with && pclen >= w->comparelen && !strcmp(w->compare, &p->comm[pclen - w->comparelen]))
1662
+ || (proc_pid_cmdline_is_needed && w->starts_with && w->ends_with && strstr(p->cmdline, w->compare))
1663
+ ) {
1664
+ if(w->target) p->target = w->target;
1665
+ else p->target = w;
1666
+
1667
+ if(debug || (p->target && p->target->debug))
1668
+ fprintf(stderr, "apps.plugin: \t\t%s linked to target %s\n", p->comm, p->target->name);
1669
+
1670
+ break;
1671
+ }
1672
+ }
1673
+ }
1674
+
1675
+ // --------------------------------------------------------------------
1676
+ // /proc/<pid>/fd
1677
+
1678
+ if(unlikely(read_pid_file_descriptors(p))) {
1679
+ if(errno != ENOENT || debug)
1680
+ error("Cannot process entries in %s/proc/%d/fd (command '%s')", host_prefix, pid, p->comm);
1681
+ else
1682
+ errno = 0;
1683
+ }
1684
+
1685
+ // --------------------------------------------------------------------
1686
+ // done!
1687
+
1688
+ if(unlikely(debug && include_exited_childs && all_pids_count && p->ppid && all_pids[p->ppid] && !all_pids[p->ppid]->read))
1689
+ fprintf(stderr, "Read process %d (%s) sortlisted %d, but its parent %d (%s) sortlisted %d, is not read\n", p->pid, p->comm, p->sortlist, all_pids[p->ppid]->pid, all_pids[p->ppid]->comm, all_pids[p->ppid]->sortlist);
1690
+
1691
+ // mark it as updated
1692
+ p->updated = 1;
1693
+ p->keep = 0;
1694
+ p->keeploops = 0;
1695
}
1696
1697
int collect_data_for_all_processes_from_proc(void) {
1698
- struct pid_stat *p = NULL;
1699
-
1700
- if(all_pids_count) {
1701
- // read parents before childs
1702
- // this is needed to prevent a situation where
1703
- // a child is found running, but until we read
1704
- // its parent, it has exited and its parent
1705
- // has accumulated its resources
1706
-
1707
- long slc = 0;
1708
- for(p = root_of_pids; p ; p = p->next) {
1709
- p->read = 0;
1710
- p->updated = 0;
1711
- p->new_entry = 0;
1712
- p->merged = 0;
1713
- p->children_count = 0;
1714
- p->parent = NULL;
1715
-
1716
- all_pids_sortlist[slc++] = p->pid;
1717
- }
1718
-
1719
- if(unlikely(slc != all_pids_count)) {
1720
- error("Internal error: I was thinking I had %ld processes in my arrays, but it seems there are more.", all_pids_count);
1721
- all_pids_count = slc;
1722
- }
1723
-
1724
- if(include_exited_childs) {
1725
- qsort((void *)all_pids_sortlist, all_pids_count, sizeof(pid_t), compar_pid);
1726
- for(slc = 0; slc < all_pids_count; slc++)
1727
- collect_data_for_pid(all_pids_sortlist[slc]);
1728
- }
1729
- }
1730
-
1731
- char dirname[FILENAME_MAX + 1];
1732
-
1733
- snprintfz(dirname, FILENAME_MAX, "%s/proc", host_prefix);
1734
- DIR *dir = opendir(dirname);
1735
- if(!dir) return 0;
1736
-
1737
- struct dirent *file = NULL;
1738
-
1739
- while((file = readdir(dir))) {
1740
- char *endptr = file->d_name;
1741
- pid_t pid = (pid_t) strtoul(file->d_name, &endptr, 10);
1742
-
1743
- // make sure we read a valid number
1744
- if(unlikely(endptr == file->d_name || *endptr != '\0'))
1745
- continue;
1746
-
1747
- collect_data_for_pid(pid);
1748
- }
1749
- closedir(dir);
1750
-
1751
- // normally this is done
1752
- // however we may have processes exited while we collected values
1753
- // so let's find the exited ones
1754
- // we do this by collecting the ownership of process
1755
- // if we manage to get the ownership, the process still runs
1756
-
1757
- read_proc_stat();
1758
- link_all_processes_to_their_parents();
1759
- process_exited_processes();
1760
-
1761
- return 1;
1698
+ struct pid_stat *p = NULL;
1699
+
1700
+ if(all_pids_count) {
1701
+ // read parents before childs
1702
+ // this is needed to prevent a situation where
1703
+ // a child is found running, but until we read
1704
+ // its parent, it has exited and its parent
1705
+ // has accumulated its resources
1706
+
1707
+ long slc = 0;
1708
+ for(p = root_of_pids; p ; p = p->next) {
1709
+ p->read = 0;
1710
+ p->updated = 0;
1711
+ p->new_entry = 0;
1712
+ p->merged = 0;
1713
+ p->children_count = 0;
1714
+ p->parent = NULL;
1715
+
1716
+ all_pids_sortlist[slc++] = p->pid;
1717
+ }
1718
+
1719
+ if(unlikely(slc != all_pids_count)) {
1720
+ error("Internal error: I was thinking I had %ld processes in my arrays, but it seems there are more.", all_pids_count);
1721
+ all_pids_count = slc;
1722
+ }
1723
+
1724
+ if(include_exited_childs) {
1725
+ qsort((void *)all_pids_sortlist, all_pids_count, sizeof(pid_t), compar_pid);
1726
+ for(slc = 0; slc < all_pids_count; slc++)
1727
+ collect_data_for_pid(all_pids_sortlist[slc]);
1728
+ }
1729
+ }
1730
+
1731
+ char dirname[FILENAME_MAX + 1];
1732
+
1733
+ snprintfz(dirname, FILENAME_MAX, "%s/proc", host_prefix);
1734
+ DIR *dir = opendir(dirname);
1735
+ if(!dir) return 0;
1736
+
1737
+ struct dirent *file = NULL;
1738
+
1739
+ while((file = readdir(dir))) {
1740
+ char *endptr = file->d_name;
1741
+ pid_t pid = (pid_t) strtoul(file->d_name, &endptr, 10);
1742
+
1743
+ // make sure we read a valid number
1744
+ if(unlikely(endptr == file->d_name || *endptr != '\0'))
1745
+ continue;
1746
+
1747
+ collect_data_for_pid(pid);
1748
+ }
1749
+ closedir(dir);
1750
+
1751
+ // normally this is done
1752
+ // however we may have processes exited while we collected values
1753
+ // so let's find the exited ones
1754
+ // we do this by collecting the ownership of process
1755
+ // if we manage to get the ownership, the process still runs
1756
+
1757
+ read_proc_stat();
1758
+ link_all_processes_to_their_parents();
1759
+ process_exited_processes();
1760
+
1761
+ return 1;
1762
}
1763
1764
// ----------------------------------------------------------------------------
@@ -1778,371 +1778,371 @@ int collect_data_for_all_processes_from_proc(void) {
1778
// check: update_apps_groups_statistics()
1779
1780
void cleanup_exited_pids(void) {
1781
- int c;
1782
- struct pid_stat *p = NULL;
1783
-
1784
- for(p = root_of_pids; p ;) {
1785
- if(!p->updated && (!p->keep || p->keeploops > 0)) {
1786
-// fprintf(stderr, "\tEXITED %d %s [parent %d %s, target %s] utime=%llu, stime=%llu, gtime=%llu, cutime=%llu, cstime=%llu, cgtime=%llu, minflt=%llu, majflt=%llu, cminflt=%llu, cmajflt=%llu\n", p->pid, p->comm, p->parent->pid, p->parent->comm, p->target->name, p->utime, p->stime, p->gtime, p->cutime, p->cstime, p->cgtime, p->minflt, p->majflt, p->cminflt, p->cmajflt);
1787
-
1788
- if(unlikely(debug && (p->keep || p->keeploops)))
1789
- fprintf(stderr, " > CLEANUP cannot keep exited process %d (%s) anymore - removing it.\n", p->pid, p->comm);
1790
-
1791
- for(c = 0 ; c < p->fds_size ; c++) if(p->fds[c] > 0) {
1792
- file_descriptor_not_used(p->fds[c]);
1793
- p->fds[c] = 0;
1794
- }
1795
-
1796
- pid_t r = p->pid;
1797
- p = p->next;
1798
- del_pid_entry(r);
1799
- }
1800
- else {
1801
- if(unlikely(p->keep)) p->keeploops++;
1802
- p->keep = 0;
1803
- p = p->next;
1804
- }
1805
- }
1781
+ int c;
1782
+ struct pid_stat *p = NULL;
1783
+
1784
+ for(p = root_of_pids; p ;) {
1785
+ if(!p->updated && (!p->keep || p->keeploops > 0)) {
1786
+// fprintf(stderr, "\tEXITED %d %s [parent %d %s, target %s] utime=%llu, stime=%llu, gtime=%llu, cutime=%llu, cstime=%llu, cgtime=%llu, minflt=%llu, majflt=%llu, cminflt=%llu, cmajflt=%llu\n", p->pid, p->comm, p->parent->pid, p->parent->comm, p->target->name, p->utime, p->stime, p->gtime, p->cutime, p->cstime, p->cgtime, p->minflt, p->majflt, p->cminflt, p->cmajflt);
1787
+
1788
+ if(unlikely(debug && (p->keep || p->keeploops)))
1789
+ fprintf(stderr, " > CLEANUP cannot keep exited process %d (%s) anymore - removing it.\n", p->pid, p->comm);
1790
+
1791
+ for(c = 0 ; c < p->fds_size ; c++) if(p->fds[c] > 0) {
1792
+ file_descriptor_not_used(p->fds[c]);
1793
+ p->fds[c] = 0;
1794
+ }
1795
+
1796
+ pid_t r = p->pid;
1797
+ p = p->next;
1798
+ del_pid_entry(r);
1799
+ }
1800
+ else {
1801
+ if(unlikely(p->keep)) p->keeploops++;
1802
+ p->keep = 0;
1803
+ p = p->next;
1804
+ }
1805
+ }
1806
}
1807
1808
void apply_apps_groups_targets_inheritance(void) {
1809
- struct pid_stat *p = NULL;
1810
-
1811
- // children that do not have a target
1812
- // inherit their target from their parent
1813
- int found = 1, loops = 0;
1814
- while(found) {
1815
- if(unlikely(debug)) loops++;
1816
- found = 0;
1817
- for(p = root_of_pids; p ; p = p->next) {
1818
- // if this process does not have a target
1819
- // and it has a parent
1820
- // and its parent has a target
1821
- // then, set the parent's target to this process
1822
- if(unlikely(!p->target && p->parent && p->parent->target)) {
1823
- p->target = p->parent->target;
1824
- found++;
1825
-
1826
- if(debug || (p->target && p->target->debug))
1827
- fprintf(stderr, "apps.plugin: \t\tTARGET INHERITANCE: %s is inherited by %d (%s) from its parent %d (%s).\n", p->target->name, p->pid, p->comm, p->parent->pid, p->parent->comm);
1828
- }
1829
- }
1830
- }
1831
-
1832
- // find all the procs with 0 childs and merge them to their parents
1833
- // repeat, until nothing more can be done.
1834
- int sortlist = 1;
1835
- found = 1;
1836
- while(found) {
1837
- if(unlikely(debug)) loops++;
1838
- found = 0;
1839
-
1840
- for(p = root_of_pids; p ; p = p->next) {
1841
- if(unlikely(!p->sortlist && !p->children_count))
1842
- p->sortlist = sortlist++;
1843
-
1844
- // if this process does not have any children
1845
- // and is not already merged
1846
- // and has a parent
1847
- // and its parent has children
1848
- // and the target of this process and its parent is the same, or the parent does not have a target
1849
- // and its parent is not init
1850
- // then, mark them as merged.
1851
- if(unlikely(
1852
- !p->children_count
1853
- && !p->merged
1854
- && p->parent
1855
- && p->parent->children_count
1856
- && (p->target == p->parent->target || !p->parent->target)
1857
- && p->ppid != 1
1858
- )) {
1859
- p->parent->children_count--;
1860
- p->merged = 1;
1861
-
1862
- // the parent inherits the child's target, if it does not have a target itself
1863
- if(unlikely(p->target && !p->parent->target)) {
1864
- p->parent->target = p->target;
1865
-
1866
- if(debug || (p->target && p->target->debug))
1867
- fprintf(stderr, "apps.plugin: \t\tTARGET INHERITANCE: %s is inherited by %d (%s) from its child %d (%s).\n", p->target->name, p->parent->pid, p->parent->comm, p->pid, p->comm);
1868
- }
1869
-
1870
- found++;
1871
- }
1872
- }
1873
-
1874
- if(unlikely(debug))
1875
- fprintf(stderr, "apps.plugin: TARGET INHERITANCE: merged %d processes\n", found);
1876
- }
1877
-
1878
- // init goes always to default target
1879
- if(all_pids[1])
1880
- all_pids[1]->target = apps_groups_default_target;
1881
-
1882
- // give a default target on all top level processes
1883
- if(unlikely(debug)) loops++;
1884
- for(p = root_of_pids; p ; p = p->next) {
1885
- // if the process is not merged itself
1886
- // then is is a top level process
1887
- if(unlikely(!p->merged && !p->target))
1888
- p->target = apps_groups_default_target;
1889
-
1890
- // make sure all processes have a sortlist
1891
- if(unlikely(!p->sortlist))
1892
- p->sortlist = sortlist++;
1893
- }
1894
-
1895
- if(all_pids[1])
1896
- all_pids[1]->sortlist = sortlist++;
1897
-
1898
- // give a target to all merged child processes
1899
- found = 1;
1900
- while(found) {
1901
- if(unlikely(debug)) loops++;
1902
- found = 0;
1903
- for(p = root_of_pids; p ; p = p->next) {
1904
- if(unlikely(!p->target && p->merged && p->parent && p->parent->target)) {
1905
- p->target = p->parent->target;
1906
- found++;
1907
-
1908
- if(debug || (p->target && p->target->debug))
1909
- fprintf(stderr, "apps.plugin: \t\tTARGET INHERITANCE: %s is inherited by %d (%s) from its parent %d (%s) at phase 2.\n", p->target->name, p->pid, p->comm, p->parent->pid, p->parent->comm);
1910
- }
1911
- }
1912
- }
1913
-
1914
- if(unlikely(debug))
1915
- fprintf(stderr, "apps.plugin: apply_apps_groups_targets_inheritance() made %d loops on the process tree\n", loops);
1809
+ struct pid_stat *p = NULL;
1810
+
1811
+ // children that do not have a target
1812
+ // inherit their target from their parent
1813
+ int found = 1, loops = 0;
1814
+ while(found) {
1815
+ if(unlikely(debug)) loops++;
1816
+ found = 0;
1817
+ for(p = root_of_pids; p ; p = p->next) {
1818
+ // if this process does not have a target
1819
+ // and it has a parent
1820
+ // and its parent has a target
1821
+ // then, set the parent's target to this process
1822
+ if(unlikely(!p->target && p->parent && p->parent->target)) {
1823
+ p->target = p->parent->target;
1824
+ found++;
1825
+
1826
+ if(debug || (p->target && p->target->debug))
1827
+ fprintf(stderr, "apps.plugin: \t\tTARGET INHERITANCE: %s is inherited by %d (%s) from its parent %d (%s).\n", p->target->name, p->pid, p->comm, p->parent->pid, p->parent->comm);
1828
+ }
1829
+ }
1830
+ }
1831
+
1832
+ // find all the procs with 0 childs and merge them to their parents
1833
+ // repeat, until nothing more can be done.
1834
+ int sortlist = 1;
1835
+ found = 1;
1836
+ while(found) {
1837
+ if(unlikely(debug)) loops++;
1838
+ found = 0;
1839
+
1840
+ for(p = root_of_pids; p ; p = p->next) {
1841
+ if(unlikely(!p->sortlist && !p->children_count))
1842
+ p->sortlist = sortlist++;
1843
+
1844
+ // if this process does not have any children
1845
+ // and is not already merged
1846
+ // and has a parent
1847
+ // and its parent has children
1848
+ // and the target of this process and its parent is the same, or the parent does not have a target
1849
+ // and its parent is not init
1850
+ // then, mark them as merged.
1851
+ if(unlikely(
1852
+ !p->children_count
1853
+ && !p->merged
1854
+ && p->parent
1855
+ && p->parent->children_count
1856
+ && (p->target == p->parent->target || !p->parent->target)
1857
+ && p->ppid != 1
1858
+ )) {
1859
+ p->parent->children_count--;
1860
+ p->merged = 1;
1861
+
1862
+ // the parent inherits the child's target, if it does not have a target itself
1863
+ if(unlikely(p->target && !p->parent->target)) {
1864
+ p->parent->target = p->target;
1865
+
1866
+ if(debug || (p->target && p->target->debug))
1867
+ fprintf(stderr, "apps.plugin: \t\tTARGET INHERITANCE: %s is inherited by %d (%s) from its child %d (%s).\n", p->target->name, p->parent->pid, p->parent->comm, p->pid, p->comm);
1868
+ }
1869
+
1870
+ found++;
1871
+ }
1872
+ }
1873
+
1874
+ if(unlikely(debug))
1875
+ fprintf(stderr, "apps.plugin: TARGET INHERITANCE: merged %d processes\n", found);
1876
+ }
1877
+
1878
+ // init goes always to default target
1879
+ if(all_pids[1])
1880
+ all_pids[1]->target = apps_groups_default_target;
1881
+
1882
+ // give a default target on all top level processes
1883
+ if(unlikely(debug)) loops++;
1884
+ for(p = root_of_pids; p ; p = p->next) {
1885
+ // if the process is not merged itself
1886
+ // then is is a top level process
1887
+ if(unlikely(!p->merged && !p->target))
1888
+ p->target = apps_groups_default_target;
1889
+
1890
+ // make sure all processes have a sortlist
1891
+ if(unlikely(!p->sortlist))
1892
+ p->sortlist = sortlist++;
1893
+ }
1894
+
1895
+ if(all_pids[1])
1896
+ all_pids[1]->sortlist = sortlist++;
1897
+
1898
+ // give a target to all merged child processes
1899
+ found = 1;
1900
+ while(found) {
1901
+ if(unlikely(debug)) loops++;
1902
+ found = 0;
1903
+ for(p = root_of_pids; p ; p = p->next) {
1904
+ if(unlikely(!p->target && p->merged && p->parent && p->parent->target)) {
1905
+ p->target = p->parent->target;
1906
+ found++;
1907
+
1908
+ if(debug || (p->target && p->target->debug))
1909
+ fprintf(stderr, "apps.plugin: \t\tTARGET INHERITANCE: %s is inherited by %d (%s) from its parent %d (%s) at phase 2.\n", p->target->name, p->pid, p->comm, p->parent->pid, p->parent->comm);
1910
+ }
1911
+ }
1912
+ }
1913
+
1914
+ if(unlikely(debug))
1915
+ fprintf(stderr, "apps.plugin: apply_apps_groups_targets_inheritance() made %d loops on the process tree\n", loops);
1916
}
1917
1918
long zero_all_targets(struct target *root) {
1919
- struct target *w;
1920
- long count = 0;
1921
-
1922
- for (w = root; w ; w = w->next) {
1923
- count++;
1924
-
1925
- if(w->fds) freez(w->fds);
1926
- w->fds = NULL;
1927
-
1928
- w->minflt = 0;
1929
- w->majflt = 0;
1930
- w->utime = 0;
1931
- w->stime = 0;
1932
- w->gtime = 0;
1933
- w->cminflt = 0;
1934
- w->cmajflt = 0;
1935
- w->cutime = 0;
1936
- w->cstime = 0;
1937
- w->cgtime = 0;
1938
- w->num_threads = 0;
1939
- w->rss = 0;
1940
- w->processes = 0;
1941
-
1942
- w->statm_size = 0;
1943
- w->statm_resident = 0;
1944
- w->statm_share = 0;
1945
- w->statm_text = 0;
1946
- w->statm_lib = 0;
1947
- w->statm_data = 0;
1948
- w->statm_dirty = 0;
1949
-
1950
- w->io_logical_bytes_read = 0;
1951
- w->io_logical_bytes_written = 0;
1952
- w->io_read_calls = 0;
1953
- w->io_write_calls = 0;
1954
- w->io_storage_bytes_read = 0;
1955
- w->io_storage_bytes_written = 0;
1956
- w->io_cancelled_write_bytes = 0;
1957
- }
1958
-
1959
- return count;
1919
+ struct target *w;
1920
+ long count = 0;
1921
+
1922
+ for (w = root; w ; w = w->next) {
1923
+ count++;
1924
+
1925
+ if(w->fds) freez(w->fds);
1926
+ w->fds = NULL;
1927
+
1928
+ w->minflt = 0;
1929
+ w->majflt = 0;
1930
+ w->utime = 0;
1931
+ w->stime = 0;
1932
+ w->gtime = 0;
1933
+ w->cminflt = 0;
1934
+ w->cmajflt = 0;
1935
+ w->cutime = 0;
1936
+ w->cstime = 0;
1937
+ w->cgtime = 0;
1938
+ w->num_threads = 0;
1939
+ w->rss = 0;
1940
+ w->processes = 0;
1941
+
1942
+ w->statm_size = 0;
1943
+ w->statm_resident = 0;
1944
+ w->statm_share = 0;
1945
+ w->statm_text = 0;
1946
+ w->statm_lib = 0;
1947
+ w->statm_data = 0;
1948
+ w->statm_dirty = 0;
1949
+
1950
+ w->io_logical_bytes_read = 0;
1951
+ w->io_logical_bytes_written = 0;
1952
+ w->io_read_calls = 0;
1953
+ w->io_write_calls = 0;
1954
+ w->io_storage_bytes_read = 0;
1955
+ w->io_storage_bytes_written = 0;
1956
+ w->io_cancelled_write_bytes = 0;
1957
+ }
1958
+
1959
+ return count;
1960
}
1961
1962
void aggregate_pid_on_target(struct target *w, struct pid_stat *p, struct target *o) {
1963
- (void)o;
1964
-
1965
- if(unlikely(!w->fds))
1966
- w->fds = callocz(sizeof(int), (size_t) all_files_size);
1967
-
1968
- if(likely(p->updated)) {
1969
- w->cutime += p->cutime;
1970
- w->cstime += p->cstime;
1971
- w->cgtime += p->cgtime;
1972
- w->cminflt += p->cminflt;
1973
- w->cmajflt += p->cmajflt;
1974
-
1975
- w->utime += p->utime;
1976
- w->stime += p->stime;
1977
- w->gtime += p->gtime;
1978
- w->minflt += p->minflt;
1979
- w->majflt += p->majflt;
1980
-
1981
- w->rss += p->rss;
1982
-
1983
- w->statm_size += p->statm_size;
1984
- w->statm_resident += p->statm_resident;
1985
- w->statm_share += p->statm_share;
1986
- w->statm_text += p->statm_text;
1987
- w->statm_lib += p->statm_lib;
1988
- w->statm_data += p->statm_data;
1989
- w->statm_dirty += p->statm_dirty;
1990
-
1991
- w->io_logical_bytes_read += p->io_logical_bytes_read;
1992
- w->io_logical_bytes_written += p->io_logical_bytes_written;
1993
- w->io_read_calls += p->io_read_calls;
1994
- w->io_write_calls += p->io_write_calls;
1995
- w->io_storage_bytes_read += p->io_storage_bytes_read;
1996
- w->io_storage_bytes_written += p->io_storage_bytes_written;
1997
- w->io_cancelled_write_bytes += p->io_cancelled_write_bytes;
1998
-
1999
- w->processes++;
2000
- w->num_threads += p->num_threads;
2001
-
2002
- if(likely(w->fds)) {
2003
- int c;
2004
- for(c = 0; c < p->fds_size ;c++) {
2005
- if(p->fds[c] == 0) continue;
2006
-
2007
- if(likely(p->fds[c] < all_files_size)) {
2008
- if(w->fds) w->fds[p->fds[c]]++;
2009
- }
2010
- else
2011
- error("Invalid fd number %d", p->fds[c]);
2012
- }
2013
- }
2014
-
2015
- if(unlikely(debug || w->debug))
2016
- fprintf(stderr, "apps.plugin: \taggregating '%s' pid %d on target '%s' utime=%llu, stime=%llu, gtime=%llu, cutime=%llu, cstime=%llu, cgtime=%llu, minflt=%llu, majflt=%llu, cminflt=%llu, cmajflt=%llu\n", p->comm, p->pid, w->name, p->utime, p->stime, p->gtime, p->cutime, p->cstime, p->cgtime, p->minflt, p->majflt, p->cminflt, p->cmajflt);
2017
- }
1963
+ (void)o;
1964
+
1965
+ if(unlikely(!w->fds))
1966
+ w->fds = callocz(sizeof(int), (size_t) all_files_size);
1967
+
1968
+ if(likely(p->updated)) {
1969
+ w->cutime += p->cutime;
1970
+ w->cstime += p->cstime;
1971
+ w->cgtime += p->cgtime;
1972
+ w->cminflt += p->cminflt;
1973
+ w->cmajflt += p->cmajflt;
1974
+
1975
+ w->utime += p->utime;
1976
+ w->stime += p->stime;
1977
+ w->gtime += p->gtime;
1978
+ w->minflt += p->minflt;
1979
+ w->majflt += p->majflt;
1980
+
1981
+ w->rss += p->rss;
1982
+
1983
+ w->statm_size += p->statm_size;
1984
+ w->statm_resident += p->statm_resident;
1985
+ w->statm_share += p->statm_share;
1986
+ w->statm_text += p->statm_text;
1987
+ w->statm_lib += p->statm_lib;
1988
+ w->statm_data += p->statm_data;
1989
+ w->statm_dirty += p->statm_dirty;
1990
+
1991
+ w->io_logical_bytes_read += p->io_logical_bytes_read;
1992
+ w->io_logical_bytes_written += p->io_logical_bytes_written;
1993
+ w->io_read_calls += p->io_read_calls;
1994
+ w->io_write_calls += p->io_write_calls;
1995
+ w->io_storage_bytes_read += p->io_storage_bytes_read;
1996
+ w->io_storage_bytes_written += p->io_storage_bytes_written;
1997
+ w->io_cancelled_write_bytes += p->io_cancelled_write_bytes;
1998
+
1999
+ w->processes++;
2000
+ w->num_threads += p->num_threads;
2001
+
2002
+ if(likely(w->fds)) {
2003
+ int c;
2004
+ for(c = 0; c < p->fds_size ;c++) {
2005
+ if(p->fds[c] == 0) continue;
2006
+
2007
+ if(likely(p->fds[c] < all_files_size)) {
2008
+ if(w->fds) w->fds[p->fds[c]]++;
2009
+ }
2010
+ else
2011
+ error("Invalid fd number %d", p->fds[c]);
2012
+ }
2013
+ }
2014
+
2015
+ if(unlikely(debug || w->debug))
2016
+ fprintf(stderr, "apps.plugin: \taggregating '%s' pid %d on target '%s' utime=%llu, stime=%llu, gtime=%llu, cutime=%llu, cstime=%llu, cgtime=%llu, minflt=%llu, majflt=%llu, cminflt=%llu, cmajflt=%llu\n", p->comm, p->pid, w->name, p->utime, p->stime, p->gtime, p->cutime, p->cstime, p->cgtime, p->minflt, p->majflt, p->cminflt, p->cmajflt);
2017
+ }
2018
}
2019
2020
void count_targets_fds(struct target *root) {
2021
- int c;
2022
- struct target *w;
2023
-
2024
- for (w = root; w ; w = w->next) {
2025
- if(!w->fds) continue;
2026
-
2027
- w->openfiles = 0;
2028
- w->openpipes = 0;
2029
- w->opensockets = 0;
2030
- w->openinotifies = 0;
2031
- w->openeventfds = 0;
2032
- w->opentimerfds = 0;
2033
- w->opensignalfds = 0;
2034
- w->openeventpolls = 0;
2035
- w->openother = 0;
2036
-
2037
- for(c = 1; c < all_files_size ;c++) {
2038
- if(w->fds[c] > 0)
2039
- switch(all_files[c].type) {
2040
- case FILETYPE_FILE:
2041
- w->openfiles++;
2042
- break;
2043
-
2044
- case FILETYPE_PIPE:
2045
- w->openpipes++;
2046
- break;
2047
-
2048
- case FILETYPE_SOCKET:
2049
- w->opensockets++;
2050
- break;
2051
-
2052
- case FILETYPE_INOTIFY:
2053
- w->openinotifies++;
2054
- break;
2055
-
2056
- case FILETYPE_EVENTFD:
2057
- w->openeventfds++;
2058
- break;
2059
-
2060
- case FILETYPE_TIMERFD:
2061
- w->opentimerfds++;
2062
- break;
2063
-
2064
- case FILETYPE_SIGNALFD:
2065
- w->opensignalfds++;
2066
- break;
2067
-
2068
- case FILETYPE_EVENTPOLL:
2069
- w->openeventpolls++;
2070
- break;
2071
-
2072
- default:
2073
- w->openother++;
2074
- }
2075
- }
2076
-
2077
- freez(w->fds);
2078
- w->fds = NULL;
2079
- }
2021
+ int c;
2022
+ struct target *w;
2023
+
2024
+ for (w = root; w ; w = w->next) {
2025
+ if(!w->fds) continue;
2026
+
2027
+ w->openfiles = 0;
2028
+ w->openpipes = 0;
2029
+ w->opensockets = 0;
2030
+ w->openinotifies = 0;
2031
+ w->openeventfds = 0;
2032
+ w->opentimerfds = 0;
2033
+ w->opensignalfds = 0;
2034
+ w->openeventpolls = 0;
2035
+ w->openother = 0;
2036
+
2037
+ for(c = 1; c < all_files_size ;c++) {
2038
+ if(w->fds[c] > 0)
2039
+ switch(all_files[c].type) {
2040
+ case FILETYPE_FILE:
2041
+ w->openfiles++;
2042
+ break;
2043
+
2044
+ case FILETYPE_PIPE:
2045
+ w->openpipes++;
2046
+ break;
2047
+
2048
+ case FILETYPE_SOCKET:
2049
+ w->opensockets++;
2050
+ break;
2051
+
2052
+ case FILETYPE_INOTIFY:
2053
+ w->openinotifies++;
2054
+ break;
2055
+
2056
+ case FILETYPE_EVENTFD:
2057
+ w->openeventfds++;
2058
+ break;
2059
+
2060
+ case FILETYPE_TIMERFD:
2061
+ w->opentimerfds++;
2062
+ break;
2063
+
2064
+ case FILETYPE_SIGNALFD:
2065
+ w->opensignalfds++;
2066
+ break;
2067
+
2068
+ case FILETYPE_EVENTPOLL:
2069
+ w->openeventpolls++;
2070
+ break;
2071
+
2072
+ default:
2073
+ w->openother++;
2074
+ }
2075
+ }
2076
+
2077
+ freez(w->fds);
2078
+ w->fds = NULL;
2079
+ }
2080
}
2081
2082
void calculate_netdata_statistics(void) {
2083
- apply_apps_groups_targets_inheritance();
2083
+ apply_apps_groups_targets_inheritance();
2084
2085
- zero_all_targets(users_root_target);
2086
- zero_all_targets(groups_root_target);
2087
- apps_groups_targets = zero_all_targets(apps_groups_root_target);
2085
+ zero_all_targets(users_root_target);
2086
+ zero_all_targets(groups_root_target);
2087
+ apps_groups_targets = zero_all_targets(apps_groups_root_target);
2088
2089
- // this has to be done, before the cleanup
2090
- struct pid_stat *p = NULL;
2091
- struct target *w = NULL, *o = NULL;
2089
+ // this has to be done, before the cleanup
2090
+ struct pid_stat *p = NULL;
2091
+ struct target *w = NULL, *o = NULL;
2092
2093
- // concentrate everything on the apps_groups_targets
2094
- for(p = root_of_pids; p ; p = p->next) {
2093
+ // concentrate everything on the apps_groups_targets
2094
+ for(p = root_of_pids; p ; p = p->next) {
2095
2096
- // --------------------------------------------------------------------
2097
- // apps_groups targets
2098
- if(likely(p->target))
2099
- aggregate_pid_on_target(p->target, p, NULL);
2100
- else
2101
- error("pid %d %s was left without a target!", p->pid, p->comm);
2096
+ // --------------------------------------------------------------------
2097
+ // apps_groups targets
2098
+ if(likely(p->target))
2099
+ aggregate_pid_on_target(p->target, p, NULL);
2100
+ else
2101
+ error("pid %d %s was left without a target!", p->pid, p->comm);
2102
2103
2104
- // --------------------------------------------------------------------
2105
- // user targets
2106
- o = p->user_target;
2107
- if(likely(p->user_target && p->user_target->uid == p->uid))
2108
- w = p->user_target;
2109
- else {
2110
- if(unlikely(debug && p->user_target))
2111
- fprintf(stderr, "apps.plugin: \t\tpid %d (%s) switched user from %u (%s) to %u.\n", p->pid, p->comm, p->user_target->uid, p->user_target->name, p->uid);
2104
+ // --------------------------------------------------------------------
2105
+ // user targets
2106
+ o = p->user_target;
2107
+ if(likely(p->user_target && p->user_target->uid == p->uid))
2108
+ w = p->user_target;
2109
+ else {
2110
+ if(unlikely(debug && p->user_target))
2111
+ fprintf(stderr, "apps.plugin: \t\tpid %d (%s) switched user from %u (%s) to %u.\n", p->pid, p->comm, p->user_target->uid, p->user_target->name, p->uid);
2112
2113
- w = p->user_target = get_users_target(p->uid);
2114
- }
2113
+ w = p->user_target = get_users_target(p->uid);
2114
+ }
2115
2116
- if(likely(w))
2117
- aggregate_pid_on_target(w, p, o);
2118
- else
2119
- error("pid %d %s was left without a user target!", p->pid, p->comm);
2116
+ if(likely(w))
2117
+ aggregate_pid_on_target(w, p, o);
2118
+ else
2119
+ error("pid %d %s was left without a user target!", p->pid, p->comm);
2120
2121
2122
- // --------------------------------------------------------------------
2123
- // group targets
2124
- o = p->group_target;
2125
- if(likely(p->group_target && p->group_target->gid == p->gid))
2126
- w = p->group_target;
2127
- else {
2128
- if(unlikely(debug && p->group_target))
2129
- fprintf(stderr, "apps.plugin: \t\tpid %d (%s) switched group from %u (%s) to %u.\n", p->pid, p->comm, p->group_target->gid, p->group_target->name, p->gid);
2122
+ // --------------------------------------------------------------------
2123
+ // group targets
2124
+ o = p->group_target;
2125
+ if(likely(p->group_target && p->group_target->gid == p->gid))
2126
+ w = p->group_target;
2127
+ else {
2128
+ if(unlikely(debug && p->group_target))
2129
+ fprintf(stderr, "apps.plugin: \t\tpid %d (%s) switched group from %u (%s) to %u.\n", p->pid, p->comm, p->group_target->gid, p->group_target->name, p->gid);
2130
2131
- w = p->group_target = get_groups_target(p->gid);
2132
- }
2131
+ w = p->group_target = get_groups_target(p->gid);
2132
+ }
2133
2134
- if(likely(w))
2135
- aggregate_pid_on_target(w, p, o);
2136
- else
2137
- error("pid %d %s was left without a group target!", p->pid, p->comm);
2134
+ if(likely(w))
2135
+ aggregate_pid_on_target(w, p, o);
2136
+ else
2137
+ error("pid %d %s was left without a group target!", p->pid, p->comm);
2138
2139
- }
2139
+ }
2140
2141
- count_targets_fds(apps_groups_root_target);
2142
- count_targets_fds(users_root_target);
2143
- count_targets_fds(groups_root_target);
2141
+ count_targets_fds(apps_groups_root_target);
2142
+ count_targets_fds(users_root_target);
2143
+ count_targets_fds(groups_root_target);
2144
2145
- cleanup_exited_pids();
2145
+ cleanup_exited_pids();
2146
}
2147
2148
// ----------------------------------------------------------------------------
@@ -2152,383 +2152,383 @@ BUFFER *output = NULL;
2152
int print_calculated_number(char *str, calculated_number value) { (void)str; (void)value; return 0; }
2153
2154
static inline void send_BEGIN(const char *type, const char *id, unsigned long long usec) {
2155
- // fprintf(stdout, "BEGIN %s.%s %llu\n", type, id, usec);
2156
- buffer_strcat(output, "BEGIN ");
2157
- buffer_strcat(output, type);
2158
- buffer_strcat(output, ".");
2159
- buffer_strcat(output, id);
2160
- buffer_strcat(output, " ");
2161
- buffer_print_llu(output, usec);
2162
- buffer_strcat(output, "\n");
2155
+ // fprintf(stdout, "BEGIN %s.%s %llu\n", type, id, usec);
2156
+ buffer_strcat(output, "BEGIN ");
2157
+ buffer_strcat(output, type);
2158
+ buffer_strcat(output, ".");
2159
+ buffer_strcat(output, id);
2160
+ buffer_strcat(output, " ");
2161
+ buffer_print_llu(output, usec);
2162
+ buffer_strcat(output, "\n");
2163
}
2164
2165
static inline void send_SET(const char *name, unsigned long long value) {
2166
- // fprintf(stdout, "SET %s = %llu\n", name, value);
2167
- buffer_strcat(output, "SET ");
2168
- buffer_strcat(output, name);
2169
- buffer_strcat(output, " = ");
2170
- buffer_print_llu(output, value);
2171
- buffer_strcat(output, "\n");
2166
+ // fprintf(stdout, "SET %s = %llu\n", name, value);
2167
+ buffer_strcat(output, "SET ");
2168
+ buffer_strcat(output, name);
2169
+ buffer_strcat(output, " = ");
2170
+ buffer_print_llu(output, value);
2171
+ buffer_strcat(output, "\n");
2172
}
2173
2174
static inline void send_END(void) {
2175
- // fprintf(stdout, "END\n");
2176
- buffer_strcat(output, "END\n");
2175
+ // fprintf(stdout, "END\n");
2176
+ buffer_strcat(output, "END\n");
2177
}
2178
2179
double utime_fix_ratio = 1.0, stime_fix_ratio = 1.0, gtime_fix_ratio = 1.0, cutime_fix_ratio = 1.0, cstime_fix_ratio = 1.0, cgtime_fix_ratio = 1.0;
2180
double minflt_fix_ratio = 1.0, majflt_fix_ratio = 1.0, cminflt_fix_ratio = 1.0, cmajflt_fix_ratio = 1.0;
2181
2182
unsigned long long send_resource_usage_to_netdata() {
2183
- static struct timeval last = { 0, 0 };
2184
- static struct rusage me_last;
2185
-
2186
- struct timeval now;
2187
- struct rusage me;
2188
-
2189
- unsigned long long usec;
2190
- unsigned long long cpuuser;
2191
- unsigned long long cpusyst;
2192
-
2193
- if(!last.tv_sec) {
2194
- gettimeofday(&last, NULL);
2195
- getrusage(RUSAGE_SELF, &me_last);
2196
-
2197
- // the first time, give a zero to allow
2198
- // netdata calibrate to the current time
2199
- // usec = update_every * 1000000ULL;
2200
- usec = 0ULL;
2201
- cpuuser = 0;
2202
- cpusyst = 0;
2203
- }
2204
- else {
2205
- gettimeofday(&now, NULL);
2206
- getrusage(RUSAGE_SELF, &me);
2207
-
2208
- usec = usec_dt(&now, &last);
2209
- cpuuser = me.ru_utime.tv_sec * 1000000ULL + me.ru_utime.tv_usec;
2210
- cpusyst = me.ru_stime.tv_sec * 1000000ULL + me.ru_stime.tv_usec;
2211
-
2212
- bcopy(&now, &last, sizeof(struct timeval));
2213
- bcopy(&me, &me_last, sizeof(struct rusage));
2214
- }
2215
-
2216
- buffer_sprintf(output,
2217
- "BEGIN netdata.apps_cpu %llu\n"
2218
- "SET user = %llu\n"
2219
- "SET system = %llu\n"
2220
- "END\n"
2221
- "BEGIN netdata.apps_files %llu\n"
2222
- "SET files = %llu\n"
2223
- "SET pids = %ld\n"
2224
- "SET fds = %d\n"
2225
- "SET targets = %ld\n"
2226
- "END\n"
2227
- "BEGIN netdata.apps_fix %llu\n"
2228
- "SET utime = %llu\n"
2229
- "SET stime = %llu\n"
2230
- "SET gtime = %llu\n"
2231
- "SET minflt = %llu\n"
2232
- "SET majflt = %llu\n"
2233
- "END\n"
2234
- , usec
2235
- , cpuuser
2236
- , cpusyst
2237
- , usec
2238
- , file_counter
2239
- , all_pids_count
2240
- , all_files_len
2241
- , apps_groups_targets
2242
- , usec
2243
- , (unsigned long long)(utime_fix_ratio * 100 * RATES_DETAIL)
2244
- , (unsigned long long)(stime_fix_ratio * 100 * RATES_DETAIL)
2245
- , (unsigned long long)(gtime_fix_ratio * 100 * RATES_DETAIL)
2246
- , (unsigned long long)(minflt_fix_ratio * 100 * RATES_DETAIL)
2247
- , (unsigned long long)(majflt_fix_ratio * 100 * RATES_DETAIL)
2248
- );
2249
-
2250
- if(include_exited_childs)
2251
- buffer_sprintf(output,
2252
- "BEGIN netdata.apps_children_fix %llu\n"
2253
- "SET cutime = %llu\n"
2254
- "SET cstime = %llu\n"
2255
- "SET cgtime = %llu\n"
2256
- "SET cminflt = %llu\n"
2257
- "SET cmajflt = %llu\n"
2258
- "END\n"
2259
- , usec
2260
- , (unsigned long long)(cutime_fix_ratio * 100 * RATES_DETAIL)
2261
- , (unsigned long long)(cstime_fix_ratio * 100 * RATES_DETAIL)
2262
- , (unsigned long long)(cgtime_fix_ratio * 100 * RATES_DETAIL)
2263
- , (unsigned long long)(cminflt_fix_ratio * 100 * RATES_DETAIL)
2264
- , (unsigned long long)(cmajflt_fix_ratio * 100 * RATES_DETAIL)
2265
- );
2266
-
2267
- return usec;
2183
+ static struct timeval last = { 0, 0 };
2184
+ static struct rusage me_last;
2185
+
2186
+ struct timeval now;
2187
+ struct rusage me;
2188
+
2189
+ unsigned long long usec;
2190
+ unsigned long long cpuuser;
2191
+ unsigned long long cpusyst;
2192
+
2193
+ if(!last.tv_sec) {
2194
+ gettimeofday(&last, NULL);
2195
+ getrusage(RUSAGE_SELF, &me_last);
2196
+
2197
+ // the first time, give a zero to allow
2198
+ // netdata calibrate to the current time
2199
+ // usec = update_every * 1000000ULL;
2200
+ usec = 0ULL;
2201
+ cpuuser = 0;
2202
+ cpusyst = 0;
2203
+ }
2204
+ else {
2205
+ gettimeofday(&now, NULL);
2206
+ getrusage(RUSAGE_SELF, &me);
2207
+
2208
+ usec = usec_dt(&now, &last);
2209
+ cpuuser = me.ru_utime.tv_sec * 1000000ULL + me.ru_utime.tv_usec;
2210
+ cpusyst = me.ru_stime.tv_sec * 1000000ULL + me.ru_stime.tv_usec;
2211
+
2212
+ bcopy(&now, &last, sizeof(struct timeval));
2213
+ bcopy(&me, &me_last, sizeof(struct rusage));
2214
+ }
2215
+
2216
+ buffer_sprintf(output,
2217
+ "BEGIN netdata.apps_cpu %llu\n"
2218
+ "SET user = %llu\n"
2219
+ "SET system = %llu\n"
2220
+ "END\n"
2221
+ "BEGIN netdata.apps_files %llu\n"
2222
+ "SET files = %llu\n"
2223
+ "SET pids = %ld\n"
2224
+ "SET fds = %d\n"
2225
+ "SET targets = %ld\n"
2226
+ "END\n"
2227
+ "BEGIN netdata.apps_fix %llu\n"
2228
+ "SET utime = %llu\n"
2229
+ "SET stime = %llu\n"
2230
+ "SET gtime = %llu\n"
2231
+ "SET minflt = %llu\n"
2232
+ "SET majflt = %llu\n"
2233
+ "END\n"
2234
+ , usec
2235
+ , cpuuser
2236
+ , cpusyst
2237
+ , usec
2238
+ , file_counter
2239
+ , all_pids_count
2240
+ , all_files_len
2241
+ , apps_groups_targets
2242
+ , usec
2243
+ , (unsigned long long)(utime_fix_ratio * 100 * RATES_DETAIL)
2244
+ , (unsigned long long)(stime_fix_ratio * 100 * RATES_DETAIL)
2245
+ , (unsigned long long)(gtime_fix_ratio * 100 * RATES_DETAIL)
2246
+ , (unsigned long long)(minflt_fix_ratio * 100 * RATES_DETAIL)
2247
+ , (unsigned long long)(majflt_fix_ratio * 100 * RATES_DETAIL)
2248
+ );
2249
+
2250
+ if(include_exited_childs)
2251
+ buffer_sprintf(output,
2252
+ "BEGIN netdata.apps_children_fix %llu\n"
2253
+ "SET cutime = %llu\n"
2254
+ "SET cstime = %llu\n"
2255
+ "SET cgtime = %llu\n"
2256
+ "SET cminflt = %llu\n"
2257
+ "SET cmajflt = %llu\n"
2258
+ "END\n"
2259
+ , usec
2260
+ , (unsigned long long)(cutime_fix_ratio * 100 * RATES_DETAIL)
2261
+ , (unsigned long long)(cstime_fix_ratio * 100 * RATES_DETAIL)
2262
+ , (unsigned long long)(cgtime_fix_ratio * 100 * RATES_DETAIL)
2263
+ , (unsigned long long)(cminflt_fix_ratio * 100 * RATES_DETAIL)
2264
+ , (unsigned long long)(cmajflt_fix_ratio * 100 * RATES_DETAIL)
2265
+ );
2266
+
2267
+ return usec;
2268
}
2269
2270
void normalize_data(struct target *root) {
2271
- struct target *w;
2272
-
2273
- // childs processing introduces spikes
2274
- // here we try to eliminate them by disabling childs processing either for specific dimensions
2275
- // or entirely. Of course, either way, we disable it just a single iteration.
2276
-
2277
- unsigned long long max = processors * hz * RATES_DETAIL;
2278
- unsigned long long utime = 0, cutime = 0, stime = 0, cstime = 0, gtime = 0, cgtime = 0, minflt = 0, cminflt = 0, majflt = 0, cmajflt = 0;
2279
-
2280
- if(global_utime > max) global_utime = max;
2281
- if(global_stime > max) global_stime = max;
2282
- if(global_gtime > max) global_gtime = max;
2283
-
2284
- for(w = root; w ; w = w->next) {
2285
- if(w->target || (!w->processes && !w->exposed)) continue;
2286
-
2287
- utime += w->utime;
2288
- stime += w->stime;
2289
- gtime += w->gtime;
2290
- cutime += w->cutime;
2291
- cstime += w->cstime;
2292
- cgtime += w->cgtime;
2293
-
2294
- minflt += w->minflt;
2295
- majflt += w->majflt;
2296
- cminflt += w->cminflt;
2297
- cmajflt += w->cmajflt;
2298
- }
2299
-
2300
- if((global_utime || global_stime || global_gtime) && (utime || stime || gtime)) {
2301
- if(global_utime + global_stime + global_gtime > utime + cutime + stime + cstime + gtime + cgtime) {
2302
- // everything we collected fits
2303
- utime_fix_ratio =
2304
- stime_fix_ratio =
2305
- gtime_fix_ratio =
2306
- cutime_fix_ratio =
2307
- cstime_fix_ratio =
2308
- cgtime_fix_ratio = 1.0; //(double)(global_utime + global_stime) / (double)(utime + cutime + stime + cstime);
2309
- }
2310
- else if(global_utime + global_stime > utime + stime) {
2311
- // childrens resources are too high
2312
- // lower only the children resources
2313
- utime_fix_ratio =
2314
- stime_fix_ratio =
2315
- gtime_fix_ratio = 1.0;
2316
- cutime_fix_ratio =
2317
- cstime_fix_ratio =
2318
- cgtime_fix_ratio = (double)((global_utime + global_stime) - (utime + stime)) / (double)(cutime + cstime);
2319
- }
2320
- else {
2321
- // even running processes are unrealistic
2322
- // zero the children resources
2323
- // lower the running processes resources
2324
- utime_fix_ratio =
2325
- stime_fix_ratio =
2326
- gtime_fix_ratio = (double)(global_utime + global_stime) / (double)(utime + stime);
2327
- cutime_fix_ratio =
2328
- cstime_fix_ratio =
2329
- cgtime_fix_ratio = 0.0;
2330
- }
2331
- }
2332
- else {
2333
- utime_fix_ratio =
2334
- stime_fix_ratio =
2335
- gtime_fix_ratio =
2336
- cutime_fix_ratio =
2337
- cstime_fix_ratio =
2338
- cgtime_fix_ratio = 0.0;
2339
- }
2340
-
2341
- if(utime_fix_ratio > 1.0) utime_fix_ratio = 1.0;
2342
- if(cutime_fix_ratio > 1.0) cutime_fix_ratio = 1.0;
2343
- if(stime_fix_ratio > 1.0) stime_fix_ratio = 1.0;
2344
- if(cstime_fix_ratio > 1.0) cstime_fix_ratio = 1.0;
2345
- if(gtime_fix_ratio > 1.0) gtime_fix_ratio = 1.0;
2346
- if(cgtime_fix_ratio > 1.0) cgtime_fix_ratio = 1.0;
2347
-
2348
- // if(utime_fix_ratio < 0.0) utime_fix_ratio = 0.0;
2349
- // if(cutime_fix_ratio < 0.0) cutime_fix_ratio = 0.0;
2350
- // if(stime_fix_ratio < 0.0) stime_fix_ratio = 0.0;
2351
- // if(cstime_fix_ratio < 0.0) cstime_fix_ratio = 0.0;
2352
- // if(gtime_fix_ratio < 0.0) gtime_fix_ratio = 0.0;
2353
- // if(cgtime_fix_ratio < 0.0) cgtime_fix_ratio = 0.0;
2354
-
2355
- // FIXME
2356
- // we use cpu time to normalize page faults
2357
- // the problem is that to find the proper max values
2358
- // for page faults we have to parse /proc/vmstat
2359
- // which is quite big to do it again (netdata does it already)
2360
- //
2361
- // a better solution could be to somehow have netdata
2362
- // do this normalization for us
2363
-
2364
- if(utime || stime || gtime)
2365
- majflt_fix_ratio =
2366
- minflt_fix_ratio = (double)(utime * utime_fix_ratio + stime * stime_fix_ratio + gtime * gtime_fix_ratio) / (double)(utime + stime + gtime);
2367
- else
2368
- minflt_fix_ratio =
2369
- majflt_fix_ratio = 1.0;
2370
-
2371
- if(cutime || cstime || cgtime)
2372
- cmajflt_fix_ratio =
2373
- cminflt_fix_ratio = (double)(cutime * cutime_fix_ratio + cstime * cstime_fix_ratio + cgtime * cgtime_fix_ratio) / (double)(cutime + cstime + cgtime);
2374
- else
2375
- cminflt_fix_ratio =
2376
- cmajflt_fix_ratio = 1.0;
2377
-
2378
- // the report
2379
-
2380
- if(unlikely(debug)) {
2381
- fprintf(stderr,
2382
- "SYSTEM: u=%llu s=%llu g=%llu "
2383
- "COLLECTED: u=%llu s=%llu g=%llu cu=%llu cs=%llu cg=%llu "
2384
- "DELTA: u=%lld s=%lld g=%lld "
2385
- "FIX: u=%0.2f s=%0.2f g=%0.2f cu=%0.2f cs=%0.2f cg=%0.2f "
2386
- "FINALLY: u=%llu s=%llu g=%llu cu=%llu cs=%llu cg=%llu "
2387
- "\n"
2388
- , global_utime
2389
- , global_stime
2390
- , global_gtime
2391
- , utime
2392
- , stime
2393
- , gtime
2394
- , cutime
2395
- , cstime
2396
- , cgtime
2397
- , (long long)utime + (long long)cutime - (long long)global_utime
2398
- , (long long)stime + (long long)cstime - (long long)global_stime
2399
- , (long long)gtime + (long long)cgtime - (long long)global_gtime
2400
- , utime_fix_ratio
2401
- , stime_fix_ratio
2402
- , gtime_fix_ratio
2403
- , cutime_fix_ratio
2404
- , cstime_fix_ratio
2405
- , cgtime_fix_ratio
2406
- , (unsigned long long)(utime * utime_fix_ratio)
2407
- , (unsigned long long)(stime * stime_fix_ratio)
2408
- , (unsigned long long)(gtime * gtime_fix_ratio)
2409
- , (unsigned long long)(cutime * cutime_fix_ratio)
2410
- , (unsigned long long)(cstime * cstime_fix_ratio)
2411
- , (unsigned long long)(cgtime * cgtime_fix_ratio)
2412
- );
2413
- }
2271
+ struct target *w;
2272
+
2273
+ // childs processing introduces spikes
2274
+ // here we try to eliminate them by disabling childs processing either for specific dimensions
2275
+ // or entirely. Of course, either way, we disable it just a single iteration.
2276
+
2277
+ unsigned long long max = processors * hz * RATES_DETAIL;
2278
+ unsigned long long utime = 0, cutime = 0, stime = 0, cstime = 0, gtime = 0, cgtime = 0, minflt = 0, cminflt = 0, majflt = 0, cmajflt = 0;
2279
+
2280
+ if(global_utime > max) global_utime = max;
2281
+ if(global_stime > max) global_stime = max;
2282
+ if(global_gtime > max) global_gtime = max;
2283
+
2284
+ for(w = root; w ; w = w->next) {
2285
+ if(w->target || (!w->processes && !w->exposed)) continue;
2286
+
2287
+ utime += w->utime;
2288
+ stime += w->stime;
2289
+ gtime += w->gtime;
2290
+ cutime += w->cutime;
2291
+ cstime += w->cstime;
2292
+ cgtime += w->cgtime;
2293
+
2294
+ minflt += w->minflt;
2295
+ majflt += w->majflt;
2296
+ cminflt += w->cminflt;
2297
+ cmajflt += w->cmajflt;
2298
+ }
2299
+
2300
+ if((global_utime || global_stime || global_gtime) && (utime || stime || gtime)) {
2301
+ if(global_utime + global_stime + global_gtime > utime + cutime + stime + cstime + gtime + cgtime) {
2302
+ // everything we collected fits
2303
+ utime_fix_ratio =
2304
+ stime_fix_ratio =
2305
+ gtime_fix_ratio =
2306
+ cutime_fix_ratio =
2307
+ cstime_fix_ratio =
2308
+ cgtime_fix_ratio = 1.0; //(double)(global_utime + global_stime) / (double)(utime + cutime + stime + cstime);
2309
+ }
2310
+ else if(global_utime + global_stime > utime + stime) {
2311
+ // childrens resources are too high
2312
+ // lower only the children resources
2313
+ utime_fix_ratio =
2314
+ stime_fix_ratio =
2315
+ gtime_fix_ratio = 1.0;
2316
+ cutime_fix_ratio =
2317
+ cstime_fix_ratio =
2318
+ cgtime_fix_ratio = (double)((global_utime + global_stime) - (utime + stime)) / (double)(cutime + cstime);
2319
+ }
2320
+ else {
2321
+ // even running processes are unrealistic
2322
+ // zero the children resources
2323
+ // lower the running processes resources
2324
+ utime_fix_ratio =
2325
+ stime_fix_ratio =
2326
+ gtime_fix_ratio = (double)(global_utime + global_stime) / (double)(utime + stime);
2327
+ cutime_fix_ratio =
2328
+ cstime_fix_ratio =
2329
+ cgtime_fix_ratio = 0.0;
2330
+ }
2331
+ }
2332
+ else {
2333
+ utime_fix_ratio =
2334
+ stime_fix_ratio =
2335
+ gtime_fix_ratio =
2336
+ cutime_fix_ratio =
2337
+ cstime_fix_ratio =
2338
+ cgtime_fix_ratio = 0.0;
2339
+ }
2340
+
2341
+ if(utime_fix_ratio > 1.0) utime_fix_ratio = 1.0;
2342
+ if(cutime_fix_ratio > 1.0) cutime_fix_ratio = 1.0;
2343
+ if(stime_fix_ratio > 1.0) stime_fix_ratio = 1.0;
2344
+ if(cstime_fix_ratio > 1.0) cstime_fix_ratio = 1.0;
2345
+ if(gtime_fix_ratio > 1.0) gtime_fix_ratio = 1.0;
2346
+ if(cgtime_fix_ratio > 1.0) cgtime_fix_ratio = 1.0;
2347
+
2348
+ // if(utime_fix_ratio < 0.0) utime_fix_ratio = 0.0;
2349
+ // if(cutime_fix_ratio < 0.0) cutime_fix_ratio = 0.0;
2350
+ // if(stime_fix_ratio < 0.0) stime_fix_ratio = 0.0;
2351
+ // if(cstime_fix_ratio < 0.0) cstime_fix_ratio = 0.0;
2352
+ // if(gtime_fix_ratio < 0.0) gtime_fix_ratio = 0.0;
2353
+ // if(cgtime_fix_ratio < 0.0) cgtime_fix_ratio = 0.0;
2354
+
2355
+ // FIXME
2356
+ // we use cpu time to normalize page faults
2357
+ // the problem is that to find the proper max values
2358
+ // for page faults we have to parse /proc/vmstat
2359
+ // which is quite big to do it again (netdata does it already)
2360
+ //
2361
+ // a better solution could be to somehow have netdata
2362
+ // do this normalization for us
2363
+
2364
+ if(utime || stime || gtime)
2365
+ majflt_fix_ratio =
2366
+ minflt_fix_ratio = (double)(utime * utime_fix_ratio + stime * stime_fix_ratio + gtime * gtime_fix_ratio) / (double)(utime + stime + gtime);
2367
+ else
2368
+ minflt_fix_ratio =
2369
+ majflt_fix_ratio = 1.0;
2370
+
2371
+ if(cutime || cstime || cgtime)
2372
+ cmajflt_fix_ratio =
2373
+ cminflt_fix_ratio = (double)(cutime * cutime_fix_ratio + cstime * cstime_fix_ratio + cgtime * cgtime_fix_ratio) / (double)(cutime + cstime + cgtime);
2374
+ else
2375
+ cminflt_fix_ratio =
2376
+ cmajflt_fix_ratio = 1.0;
2377
+
2378
+ // the report
2379
+
2380
+ if(unlikely(debug)) {
2381
+ fprintf(stderr,
2382
+ "SYSTEM: u=%llu s=%llu g=%llu "
2383
+ "COLLECTED: u=%llu s=%llu g=%llu cu=%llu cs=%llu cg=%llu "
2384
+ "DELTA: u=%lld s=%lld g=%lld "
2385
+ "FIX: u=%0.2f s=%0.2f g=%0.2f cu=%0.2f cs=%0.2f cg=%0.2f "
2386
+ "FINALLY: u=%llu s=%llu g=%llu cu=%llu cs=%llu cg=%llu "
2387
+ "\n"
2388
+ , global_utime
2389
+ , global_stime
2390
+ , global_gtime
2391
+ , utime
2392
+ , stime
2393
+ , gtime
2394
+ , cutime
2395
+ , cstime
2396
+ , cgtime
2397
+ , (long long)utime + (long long)cutime - (long long)global_utime
2398
+ , (long long)stime + (long long)cstime - (long long)global_stime
2399
+ , (long long)gtime + (long long)cgtime - (long long)global_gtime
2400
+ , utime_fix_ratio
2401
+ , stime_fix_ratio
2402
+ , gtime_fix_ratio
2403
+ , cutime_fix_ratio
2404
+ , cstime_fix_ratio
2405
+ , cgtime_fix_ratio
2406
+ , (unsigned long long)(utime * utime_fix_ratio)
2407
+ , (unsigned long long)(stime * stime_fix_ratio)
2408
+ , (unsigned long long)(gtime * gtime_fix_ratio)
2409
+ , (unsigned long long)(cutime * cutime_fix_ratio)
2410
+ , (unsigned long long)(cstime * cstime_fix_ratio)
2411
+ , (unsigned long long)(cgtime * cgtime_fix_ratio)
2412
+ );
2413
+ }
2414
}
2415
2416
void send_collected_data_to_netdata(struct target *root, const char *type, unsigned long long usec) {
2417
- struct target *w;
2418
-
2419
- send_BEGIN(type, "cpu", usec);
2420
- for (w = root; w ; w = w->next) {
2421
- if(unlikely(w->exposed))
2422
- send_SET(w->name, (unsigned long long)(w->utime * utime_fix_ratio) + (unsigned long long)(w->stime * stime_fix_ratio) + (unsigned long long)(w->gtime * gtime_fix_ratio) + (include_exited_childs?((unsigned long long)(w->cutime * cutime_fix_ratio) + (unsigned long long)(w->cstime * cstime_fix_ratio) + (unsigned long long)(w->cgtime * cgtime_fix_ratio)):0ULL));
2423
- }
2424
- send_END();
2425
-
2426
- send_BEGIN(type, "cpu_user", usec);
2427
- for (w = root; w ; w = w->next) {
2428
- if(unlikely(w->exposed))
2429
- send_SET(w->name, (unsigned long long)(w->utime * utime_fix_ratio) + (include_exited_childs?((unsigned long long)(w->cutime * cutime_fix_ratio)):0ULL));
2430
- }
2431
- send_END();
2432
-
2433
- send_BEGIN(type, "cpu_system", usec);
2434
- for (w = root; w ; w = w->next) {
2435
- if(unlikely(w->exposed))
2436
- send_SET(w->name, (unsigned long long)(w->stime * stime_fix_ratio) + (include_exited_childs?((unsigned long long)(w->cstime * cstime_fix_ratio)):0ULL));
2437
- }
2438
- send_END();
2439
-
2440
- if(show_guest_time) {
2441
- send_BEGIN(type, "cpu_guest", usec);
2442
- for (w = root; w ; w = w->next) {
2443
- if(unlikely(w->exposed))
2444
- send_SET(w->name, (unsigned long long)(w->gtime * gtime_fix_ratio) + (include_exited_childs?((unsigned long long)(w->cgtime * cgtime_fix_ratio)):0ULL));
2445
- }
2446
- send_END();
2447
- }
2448
-
2449
- send_BEGIN(type, "threads", usec);
2450
- for (w = root; w ; w = w->next) {
2451
- if(unlikely(w->exposed))
2452
- send_SET(w->name, w->num_threads);
2453
- }
2454
- send_END();
2455
-
2456
- send_BEGIN(type, "processes", usec);
2457
- for (w = root; w ; w = w->next) {
2458
- if(unlikely(w->exposed))
2459
- send_SET(w->name, w->processes);
2460
- }
2461
- send_END();
2462
-
2463
- send_BEGIN(type, "mem", usec);
2464
- for (w = root; w ; w = w->next) {
2465
- if(unlikely(w->exposed))
2466
- send_SET(w->name, (w->statm_resident > w->statm_share)?(w->statm_resident - w->statm_share):0ULL);
2467
- }
2468
- send_END();
2469
-
2470
- send_BEGIN(type, "minor_faults", usec);
2471
- for (w = root; w ; w = w->next) {
2472
- if(unlikely(w->exposed))
2473
- send_SET(w->name, (unsigned long long)(w->minflt * minflt_fix_ratio) + (include_exited_childs?((unsigned long long)(w->cminflt * cminflt_fix_ratio)):0ULL));
2474
- }
2475
- send_END();
2476
-
2477
- send_BEGIN(type, "major_faults", usec);
2478
- for (w = root; w ; w = w->next) {
2479
- if(unlikely(w->exposed))
2480
- send_SET(w->name, (unsigned long long)(w->majflt * majflt_fix_ratio) + (include_exited_childs?((unsigned long long)(w->cmajflt * cmajflt_fix_ratio)):0ULL));
2481
- }
2482
- send_END();
2483
-
2484
- send_BEGIN(type, "lreads", usec);
2485
- for (w = root; w ; w = w->next) {
2486
- if(unlikely(w->exposed))
2487
- send_SET(w->name, w->io_logical_bytes_read);
2488
- }
2489
- send_END();
2490
-
2491
- send_BEGIN(type, "lwrites", usec);
2492
- for (w = root; w ; w = w->next) {
2493
- if(unlikely(w->exposed))
2494
- send_SET(w->name, w->io_logical_bytes_written);
2495
- }
2496
- send_END();
2497
-
2498
- send_BEGIN(type, "preads", usec);
2499
- for (w = root; w ; w = w->next) {
2500
- if(unlikely(w->exposed))
2501
- send_SET(w->name, w->io_storage_bytes_read);
2502
- }
2503
- send_END();
2504
-
2505
- send_BEGIN(type, "pwrites", usec);
2506
- for (w = root; w ; w = w->next) {
2507
- if(unlikely(w->exposed))
2508
- send_SET(w->name, w->io_storage_bytes_written);
2509
- }
2510
- send_END();
2511
-
2512
- send_BEGIN(type, "files", usec);
2513
- for (w = root; w ; w = w->next) {
2514
- if(unlikely(w->exposed))
2515
- send_SET(w->name, w->openfiles);
2516
- }
2517
- send_END();
2518
-
2519
- send_BEGIN(type, "sockets", usec);
2520
- for (w = root; w ; w = w->next) {
2521
- if(unlikely(w->exposed))
2522
- send_SET(w->name, w->opensockets);
2523
- }
2524
- send_END();
2525
-
2526
- send_BEGIN(type, "pipes", usec);
2527
- for (w = root; w ; w = w->next) {
2528
- if(unlikely(w->exposed))
2529
- send_SET(w->name, w->openpipes);
2530
- }
2531
- send_END();
2417
+ struct target *w;
2418
+
2419
+ send_BEGIN(type, "cpu", usec);
2420
+ for (w = root; w ; w = w->next) {
2421
+ if(unlikely(w->exposed))
2422
+ send_SET(w->name, (unsigned long long)(w->utime * utime_fix_ratio) + (unsigned long long)(w->stime * stime_fix_ratio) + (unsigned long long)(w->gtime * gtime_fix_ratio) + (include_exited_childs?((unsigned long long)(w->cutime * cutime_fix_ratio) + (unsigned long long)(w->cstime * cstime_fix_ratio) + (unsigned long long)(w->cgtime * cgtime_fix_ratio)):0ULL));
2423
+ }
2424
+ send_END();
2425
+
2426
+ send_BEGIN(type, "cpu_user", usec);
2427
+ for (w = root; w ; w = w->next) {
2428
+ if(unlikely(w->exposed))
2429
+ send_SET(w->name, (unsigned long long)(w->utime * utime_fix_ratio) + (include_exited_childs?((unsigned long long)(w->cutime * cutime_fix_ratio)):0ULL));
2430
+ }
2431
+ send_END();
2432
+
2433
+ send_BEGIN(type, "cpu_system", usec);
2434
+ for (w = root; w ; w = w->next) {
2435
+ if(unlikely(w->exposed))
2436
+ send_SET(w->name, (unsigned long long)(w->stime * stime_fix_ratio) + (include_exited_childs?((unsigned long long)(w->cstime * cstime_fix_ratio)):0ULL));
2437
+ }
2438
+ send_END();
2439
+
2440
+ if(show_guest_time) {
2441
+ send_BEGIN(type, "cpu_guest", usec);
2442
+ for (w = root; w ; w = w->next) {
2443
+ if(unlikely(w->exposed))
2444
+ send_SET(w->name, (unsigned long long)(w->gtime * gtime_fix_ratio) + (include_exited_childs?((unsigned long long)(w->cgtime * cgtime_fix_ratio)):0ULL));
2445
+ }
2446
+ send_END();
2447
+ }
2448
+
2449
+ send_BEGIN(type, "threads", usec);
2450
+ for (w = root; w ; w = w->next) {
2451
+ if(unlikely(w->exposed))
2452
+ send_SET(w->name, w->num_threads);
2453
+ }
2454
+ send_END();
2455
+
2456
+ send_BEGIN(type, "processes", usec);
2457
+ for (w = root; w ; w = w->next) {
2458
+ if(unlikely(w->exposed))
2459
+ send_SET(w->name, w->processes);
2460
+ }
2461
+ send_END();
2462
+
2463
+ send_BEGIN(type, "mem", usec);
2464
+ for (w = root; w ; w = w->next) {
2465
+ if(unlikely(w->exposed))
2466
+ send_SET(w->name, (w->statm_resident > w->statm_share)?(w->statm_resident - w->statm_share):0ULL);
2467
+ }
2468
+ send_END();
2469
+
2470
+ send_BEGIN(type, "minor_faults", usec);
2471
+ for (w = root; w ; w = w->next) {
2472
+ if(unlikely(w->exposed))
2473
+ send_SET(w->name, (unsigned long long)(w->minflt * minflt_fix_ratio) + (include_exited_childs?((unsigned long long)(w->cminflt * cminflt_fix_ratio)):0ULL));
2474
+ }
2475
+ send_END();
2476
+
2477
+ send_BEGIN(type, "major_faults", usec);
2478
+ for (w = root; w ; w = w->next) {
2479
+ if(unlikely(w->exposed))
2480
+ send_SET(w->name, (unsigned long long)(w->majflt * majflt_fix_ratio) + (include_exited_childs?((unsigned long long)(w->cmajflt * cmajflt_fix_ratio)):0ULL));
2481
+ }
2482
+ send_END();
2483
+
2484
+ send_BEGIN(type, "lreads", usec);
2485
+ for (w = root; w ; w = w->next) {
2486
+ if(unlikely(w->exposed))
2487
+ send_SET(w->name, w->io_logical_bytes_read);
2488
+ }
2489
+ send_END();
2490
+
2491
+ send_BEGIN(type, "lwrites", usec);
2492
+ for (w = root; w ; w = w->next) {
2493
+ if(unlikely(w->exposed))
2494
+ send_SET(w->name, w->io_logical_bytes_written);
2495
+ }
2496
+ send_END();
2497
+
2498
+ send_BEGIN(type, "preads", usec);
2499
+ for (w = root; w ; w = w->next) {
2500
+ if(unlikely(w->exposed))
2501
+ send_SET(w->name, w->io_storage_bytes_read);
2502
+ }
2503
+ send_END();
2504
+
2505
+ send_BEGIN(type, "pwrites", usec);
2506
+ for (w = root; w ; w = w->next) {
2507
+ if(unlikely(w->exposed))
2508
+ send_SET(w->name, w->io_storage_bytes_written);
2509
+ }
2510
+ send_END();
2511
+
2512
+ send_BEGIN(type, "files", usec);
2513
+ for (w = root; w ; w = w->next) {
2514
+ if(unlikely(w->exposed))
2515
+ send_SET(w->name, w->openfiles);
2516
+ }
2517
+ send_END();
2518
+
2519
+ send_BEGIN(type, "sockets", usec);
2520
+ for (w = root; w ; w = w->next) {
2521
+ if(unlikely(w->exposed))
2522
+ send_SET(w->name, w->opensockets);
2523
+ }
2524
+ send_END();
2525
+
2526
+ send_BEGIN(type, "pipes", usec);
2527
+ for (w = root; w ; w = w->next) {
2528
+ if(unlikely(w->exposed))
2529
+ send_SET(w->name, w->openpipes);
2530
+ }
2531
+ send_END();
2532
}
2533
2534
@@ -2537,121 +2537,121 @@ void send_collected_data_to_netdata(struct target *root, const char *type, unsig
2537
2538
void send_charts_updates_to_netdata(struct target *root, const char *type, const char *title)
2539
{
2540
- struct target *w;
2541
- int newly_added = 0;
2542
-
2543
- for(w = root ; w ; w = w->next) {
2544
- if (w->target) continue;
2545
-
2546
- if (!w->exposed && w->processes) {
2547
- newly_added++;
2548
- w->exposed = 1;
2549
- if (debug || w->debug) fprintf(stderr, "apps.plugin: %s just added - regenerating charts.\n", w->name);
2550
- }
2551
- }
2552
-
2553
- // nothing more to show
2554
- if(!newly_added && show_guest_time == show_guest_time_old) return;
2555
-
2556
- // we have something new to show
2557
- // update the charts
2558
- buffer_sprintf(output, "CHART %s.cpu '' '%s CPU Time (%d%% = %d core%s)' 'cpu time %%' cpu %s.cpu stacked 20001 %d\n", type, title, (processors * 100), processors, (processors>1)?"s":"", type, update_every);
2559
- for (w = root; w ; w = w->next) {
2560
- if(unlikely(w->exposed))
2561
- buffer_sprintf(output, "DIMENSION %s '' absolute 1 %llu %s\n", w->name, hz * RATES_DETAIL / 100, w->hidden ? "hidden" : "");
2562
- }
2563
-
2564
- buffer_sprintf(output, "CHART %s.mem '' '%s Dedicated Memory (w/o shared)' 'MB' mem %s.mem stacked 20003 %d\n", type, title, type, update_every);
2565
- for (w = root; w ; w = w->next) {
2566
- if(unlikely(w->exposed))
2567
- buffer_sprintf(output, "DIMENSION %s '' absolute %ld %ld\n", w->name, sysconf(_SC_PAGESIZE), 1024L*1024L);
2568
- }
2569
-
2570
- buffer_sprintf(output, "CHART %s.threads '' '%s Threads' 'threads' processes %s.threads stacked 20005 %d\n", type, title, type, update_every);
2571
- for (w = root; w ; w = w->next) {
2572
- if(unlikely(w->exposed))
2573
- buffer_sprintf(output, "DIMENSION %s '' absolute 1 1\n", w->name);
2574
- }
2575
-
2576
- buffer_sprintf(output, "CHART %s.processes '' '%s Processes' 'processes' processes %s.processes stacked 20004 %d\n", type, title, type, update_every);
2577
- for (w = root; w ; w = w->next) {
2578
- if(unlikely(w->exposed))
2579
- buffer_sprintf(output, "DIMENSION %s '' absolute 1 1\n", w->name);
2580
- }
2581
-
2582
- buffer_sprintf(output, "CHART %s.cpu_user '' '%s CPU User Time (%d%% = %d core%s)' 'cpu time %%' cpu %s.cpu_user stacked 20020 %d\n", type, title, (processors * 100), processors, (processors>1)?"s":"", type, update_every);
2583
- for (w = root; w ; w = w->next) {
2584
- if(unlikely(w->exposed))
2585
- buffer_sprintf(output, "DIMENSION %s '' absolute 1 %llu\n", w->name, hz * RATES_DETAIL / 100LLU);
2586
- }
2587
-
2588
- buffer_sprintf(output, "CHART %s.cpu_system '' '%s CPU System Time (%d%% = %d core%s)' 'cpu time %%' cpu %s.cpu_system stacked 20021 %d\n", type, title, (processors * 100), processors, (processors>1)?"s":"", type, update_every);
2589
- for (w = root; w ; w = w->next) {
2590
- if(unlikely(w->exposed))
2591
- buffer_sprintf(output, "DIMENSION %s '' absolute 1 %llu\n", w->name, hz * RATES_DETAIL / 100LLU);
2592
- }
2593
-
2594
- if(show_guest_time) {
2595
- buffer_sprintf(output, "CHART %s.cpu_guest '' '%s CPU Guest Time (%d%% = %d core%s)' 'cpu time %%' cpu %s.cpu_system stacked 20022 %d\n", type, title, (processors * 100), processors, (processors > 1) ? "s" : "", type, update_every);
2596
- for (w = root; w; w = w->next) {
2597
- if(unlikely(w->exposed))
2598
- buffer_sprintf(output, "DIMENSION %s '' absolute 1 %llu\n", w->name, hz * RATES_DETAIL / 100LLU);
2599
- }
2600
- }
2601
-
2602
- buffer_sprintf(output, "CHART %s.major_faults '' '%s Major Page Faults (swap read)' 'page faults/s' swap %s.major_faults stacked 20010 %d\n", type, title, type, update_every);
2603
- for (w = root; w ; w = w->next) {
2604
- if(unlikely(w->exposed))
2605
- buffer_sprintf(output, "DIMENSION %s '' absolute 1 %llu\n", w->name, RATES_DETAIL);
2606
- }
2607
-
2608
- buffer_sprintf(output, "CHART %s.minor_faults '' '%s Minor Page Faults' 'page faults/s' mem %s.minor_faults stacked 20011 %d\n", type, title, type, update_every);
2609
- for (w = root; w ; w = w->next) {
2610
- if(unlikely(w->exposed))
2611
- buffer_sprintf(output, "DIMENSION %s '' absolute 1 %llu\n", w->name, RATES_DETAIL);
2612
- }
2613
-
2614
- buffer_sprintf(output, "CHART %s.lreads '' '%s Disk Logical Reads' 'kilobytes/s' disk %s.lreads stacked 20042 %d\n", type, title, type, update_every);
2615
- for (w = root; w ; w = w->next) {
2616
- if(unlikely(w->exposed))
2617
- buffer_sprintf(output, "DIMENSION %s '' absolute 1 %llu\n", w->name, 1024LLU * RATES_DETAIL);
2618
- }
2619
-
2620
- buffer_sprintf(output, "CHART %s.lwrites '' '%s I/O Logical Writes' 'kilobytes/s' disk %s.lwrites stacked 20042 %d\n", type, title, type, update_every);
2621
- for (w = root; w ; w = w->next) {
2622
- if(unlikely(w->exposed))
2623
- buffer_sprintf(output, "DIMENSION %s '' absolute 1 %llu\n", w->name, 1024LLU * RATES_DETAIL);
2624
- }
2625
-
2626
- buffer_sprintf(output, "CHART %s.preads '' '%s Disk Reads' 'kilobytes/s' disk %s.preads stacked 20002 %d\n", type, title, type, update_every);
2627
- for (w = root; w ; w = w->next) {
2628
- if(unlikely(w->exposed))
2629
- buffer_sprintf(output, "DIMENSION %s '' absolute 1 %llu\n", w->name, 1024LLU * RATES_DETAIL);
2630
- }
2631
-
2632
- buffer_sprintf(output, "CHART %s.pwrites '' '%s Disk Writes' 'kilobytes/s' disk %s.pwrites stacked 20002 %d\n", type, title, type, update_every);
2633
- for (w = root; w ; w = w->next) {
2634
- if(unlikely(w->exposed))
2635
- buffer_sprintf(output, "DIMENSION %s '' absolute 1 %llu\n", w->name, 1024LLU * RATES_DETAIL);
2636
- }
2637
-
2638
- buffer_sprintf(output, "CHART %s.files '' '%s Open Files' 'open files' disk %s.files stacked 20050 %d\n", type, title, type, update_every);
2639
- for (w = root; w ; w = w->next) {
2640
- if(unlikely(w->exposed))
2641
- buffer_sprintf(output, "DIMENSION %s '' absolute 1 1\n", w->name);
2642
- }
2643
-
2644
- buffer_sprintf(output, "CHART %s.sockets '' '%s Open Sockets' 'open sockets' net %s.sockets stacked 20051 %d\n", type, title, type, update_every);
2645
- for (w = root; w ; w = w->next) {
2646
- if(unlikely(w->exposed))
2647
- buffer_sprintf(output, "DIMENSION %s '' absolute 1 1\n", w->name);
2648
- }
2649
-
2650
- buffer_sprintf(output, "CHART %s.pipes '' '%s Pipes' 'open pipes' processes %s.pipes stacked 20053 %d\n", type, title, type, update_every);
2651
- for (w = root; w ; w = w->next) {
2652
- if(unlikely(w->exposed))
2653
- buffer_sprintf(output, "DIMENSION %s '' absolute 1 1\n", w->name);
2654
- }
2540
+ struct target *w;
2541
+ int newly_added = 0;
2542
+
2543
+ for(w = root ; w ; w = w->next) {
2544
+ if (w->target) continue;
2545
+
2546
+ if (!w->exposed && w->processes) {
2547
+ newly_added++;
2548
+ w->exposed = 1;
2549
+ if (debug || w->debug) fprintf(stderr, "apps.plugin: %s just added - regenerating charts.\n", w->name);
2550
+ }
2551
+ }
2552
+
2553
+ // nothing more to show
2554
+ if(!newly_added && show_guest_time == show_guest_time_old) return;
2555
+
2556
+ // we have something new to show
2557
+ // update the charts
2558
+ buffer_sprintf(output, "CHART %s.cpu '' '%s CPU Time (%d%% = %d core%s)' 'cpu time %%' cpu %s.cpu stacked 20001 %d\n", type, title, (processors * 100), processors, (processors>1)?"s":"", type, update_every);
2559
+ for (w = root; w ; w = w->next) {
2560
+ if(unlikely(w->exposed))
2561
+ buffer_sprintf(output, "DIMENSION %s '' absolute 1 %llu %s\n", w->name, hz * RATES_DETAIL / 100, w->hidden ? "hidden" : "");
2562
+ }
2563
+
2564
+ buffer_sprintf(output, "CHART %s.mem '' '%s Dedicated Memory (w/o shared)' 'MB' mem %s.mem stacked 20003 %d\n", type, title, type, update_every);
2565
+ for (w = root; w ; w = w->next) {
2566
+ if(unlikely(w->exposed))
2567
+ buffer_sprintf(output, "DIMENSION %s '' absolute %ld %ld\n", w->name, sysconf(_SC_PAGESIZE), 1024L*1024L);
2568
+ }
2569
+
2570
+ buffer_sprintf(output, "CHART %s.threads '' '%s Threads' 'threads' processes %s.threads stacked 20005 %d\n", type, title, type, update_every);
2571
+ for (w = root; w ; w = w->next) {
2572
+ if(unlikely(w->exposed))
2573
+ buffer_sprintf(output, "DIMENSION %s '' absolute 1 1\n", w->name);
2574
+ }
2575
+
2576
+ buffer_sprintf(output, "CHART %s.processes '' '%s Processes' 'processes' processes %s.processes stacked 20004 %d\n", type, title, type, update_every);
2577
+ for (w = root; w ; w = w->next) {
2578
+ if(unlikely(w->exposed))
2579
+ buffer_sprintf(output, "DIMENSION %s '' absolute 1 1\n", w->name);
2580
+ }
2581
+
2582
+ buffer_sprintf(output, "CHART %s.cpu_user '' '%s CPU User Time (%d%% = %d core%s)' 'cpu time %%' cpu %s.cpu_user stacked 20020 %d\n", type, title, (processors * 100), processors, (processors>1)?"s":"", type, update_every);
2583
+ for (w = root; w ; w = w->next) {
2584
+ if(unlikely(w->exposed))
2585
+ buffer_sprintf(output, "DIMENSION %s '' absolute 1 %llu\n", w->name, hz * RATES_DETAIL / 100LLU);
2586
+ }
2587
+
2588
+ buffer_sprintf(output, "CHART %s.cpu_system '' '%s CPU System Time (%d%% = %d core%s)' 'cpu time %%' cpu %s.cpu_system stacked 20021 %d\n", type, title, (processors * 100), processors, (processors>1)?"s":"", type, update_every);
2589
+ for (w = root; w ; w = w->next) {
2590
+ if(unlikely(w->exposed))
2591
+ buffer_sprintf(output, "DIMENSION %s '' absolute 1 %llu\n", w->name, hz * RATES_DETAIL / 100LLU);
2592
+ }
2593
+
2594
+ if(show_guest_time) {
2595
+ buffer_sprintf(output, "CHART %s.cpu_guest '' '%s CPU Guest Time (%d%% = %d core%s)' 'cpu time %%' cpu %s.cpu_system stacked 20022 %d\n", type, title, (processors * 100), processors, (processors > 1) ? "s" : "", type, update_every);
2596
+ for (w = root; w; w = w->next) {
2597
+ if(unlikely(w->exposed))
2598
+ buffer_sprintf(output, "DIMENSION %s '' absolute 1 %llu\n", w->name, hz * RATES_DETAIL / 100LLU);
2599
+ }
2600
+ }
2601
+
2602
+ buffer_sprintf(output, "CHART %s.major_faults '' '%s Major Page Faults (swap read)' 'page faults/s' swap %s.major_faults stacked 20010 %d\n", type, title, type, update_every);
2603
+ for (w = root; w ; w = w->next) {
2604
+ if(unlikely(w->exposed))
2605
+ buffer_sprintf(output, "DIMENSION %s '' absolute 1 %llu\n", w->name, RATES_DETAIL);
2606
+ }
2607
+
2608
+ buffer_sprintf(output, "CHART %s.minor_faults '' '%s Minor Page Faults' 'page faults/s' mem %s.minor_faults stacked 20011 %d\n", type, title, type, update_every);
2609
+ for (w = root; w ; w = w->next) {
2610
+ if(unlikely(w->exposed))
2611
+ buffer_sprintf(output, "DIMENSION %s '' absolute 1 %llu\n", w->name, RATES_DETAIL);
2612
+ }
2613
+
2614
+ buffer_sprintf(output, "CHART %s.lreads '' '%s Disk Logical Reads' 'kilobytes/s' disk %s.lreads stacked 20042 %d\n", type, title, type, update_every);
2615
+ for (w = root; w ; w = w->next) {
2616
+ if(unlikely(w->exposed))
2617
+ buffer_sprintf(output, "DIMENSION %s '' absolute 1 %llu\n", w->name, 1024LLU * RATES_DETAIL);
2618
+ }
2619
+
2620
+ buffer_sprintf(output, "CHART %s.lwrites '' '%s I/O Logical Writes' 'kilobytes/s' disk %s.lwrites stacked 20042 %d\n", type, title, type, update_every);
2621
+ for (w = root; w ; w = w->next) {
2622
+ if(unlikely(w->exposed))
2623
+ buffer_sprintf(output, "DIMENSION %s '' absolute 1 %llu\n", w->name, 1024LLU * RATES_DETAIL);
2624
+ }
2625
+
2626
+ buffer_sprintf(output, "CHART %s.preads '' '%s Disk Reads' 'kilobytes/s' disk %s.preads stacked 20002 %d\n", type, title, type, update_every);
2627
+ for (w = root; w ; w = w->next) {
2628
+ if(unlikely(w->exposed))
2629
+ buffer_sprintf(output, "DIMENSION %s '' absolute 1 %llu\n", w->name, 1024LLU * RATES_DETAIL);
2630
+ }
2631
+
2632
+ buffer_sprintf(output, "CHART %s.pwrites '' '%s Disk Writes' 'kilobytes/s' disk %s.pwrites stacked 20002 %d\n", type, title, type, update_every);
2633
+ for (w = root; w ; w = w->next) {
2634
+ if(unlikely(w->exposed))
2635
+ buffer_sprintf(output, "DIMENSION %s '' absolute 1 %llu\n", w->name, 1024LLU * RATES_DETAIL);
2636
+ }
2637
+
2638
+ buffer_sprintf(output, "CHART %s.files '' '%s Open Files' 'open files' disk %s.files stacked 20050 %d\n", type, title, type, update_every);
2639
+ for (w = root; w ; w = w->next) {
2640
+ if(unlikely(w->exposed))
2641
+ buffer_sprintf(output, "DIMENSION %s '' absolute 1 1\n", w->name);
2642
+ }
2643
+
2644
+ buffer_sprintf(output, "CHART %s.sockets '' '%s Open Sockets' 'open sockets' net %s.sockets stacked 20051 %d\n", type, title, type, update_every);
2645
+ for (w = root; w ; w = w->next) {
2646
+ if(unlikely(w->exposed))
2647
+ buffer_sprintf(output, "DIMENSION %s '' absolute 1 1\n", w->name);
2648
+ }
2649
+
2650
+ buffer_sprintf(output, "CHART %s.pipes '' '%s Pipes' 'open pipes' processes %s.pipes stacked 20053 %d\n", type, title, type, update_every);
2651
+ for (w = root; w ; w = w->next) {
2652
+ if(unlikely(w->exposed))
2653
+ buffer_sprintf(output, "DIMENSION %s '' absolute 1 1\n", w->name);
2654
+ }
2655
}
2656
2657
@@ -2660,33 +2660,33 @@ void send_charts_updates_to_netdata(struct target *root, const char *type, const
2660
2661
void parse_args(int argc, char **argv)
2662
{
2663
- int i, freq = 0;
2664
- char *name = NULL;
2665
-
2666
- for(i = 1; i < argc; i++) {
2667
- if(!freq) {
2668
- int n = atoi(argv[i]);
2669
- if(n > 0) {
2670
- freq = n;
2671
- continue;
2672
- }
2673
- }
2674
-
2675
- if(strcmp("debug", argv[i]) == 0) {
2676
- debug = 1;
2677
- // debug_flags = 0xffffffff;
2678
- continue;
2679
- }
2680
-
2681
- if(strcmp("no-childs", argv[i]) == 0 || strcmp("without-childs", argv[i]) == 0) {
2682
- include_exited_childs = 0;
2683
- continue;
2684
- }
2685
-
2686
- if(strcmp("with-childs", argv[i]) == 0) {
2687
- include_exited_childs = 1;
2688
- continue;
2689
- }
2663
+ int i, freq = 0;
2664
+ char *name = NULL;
2665
+
2666
+ for(i = 1; i < argc; i++) {
2667
+ if(!freq) {
2668
+ int n = atoi(argv[i]);
2669
+ if(n > 0) {
2670
+ freq = n;
2671
+ continue;
2672
+ }
2673
+ }
2674
+
2675
+ if(strcmp("debug", argv[i]) == 0) {
2676
+ debug = 1;
2677
+ // debug_flags = 0xffffffff;
2678
+ continue;
2679
+ }
2680
+
2681
+ if(strcmp("no-childs", argv[i]) == 0 || strcmp("without-childs", argv[i]) == 0) {
2682
+ include_exited_childs = 0;
2683
+ continue;
2684
+ }
2685
+
2686
+ if(strcmp("with-childs", argv[i]) == 0) {
2687
+ include_exited_childs = 1;
2688
+ continue;
2689
+ }
2690
2691
if(strcmp("with-guest", argv[i]) == 0) {
2692
enable_guest_charts = 1;
@@ -2698,7 +2698,7 @@ void parse_args(int argc, char **argv)
2698
continue;
2699
}
2700
2701
- if(strcmp("-h", argv[i]) == 0 || strcmp("--help", argv[i]) == 0) {
2701
+ if(strcmp("-h", argv[i]) == 0 || strcmp("--help", argv[i]) == 0) {
2702
fprintf(stderr,
2703
"apps.plugin\n"
2704
"(C) 2016 Costa Tsaousis"
@@ -2728,161 +2728,161 @@ void parse_args(int argc, char **argv)
2728
}
2729
2730
if(!name) {
2731
- name = argv[i];
2732
- continue;
2733
- }
2731
+ name = argv[i];
2732
+ continue;
2733
+ }
2734
2735
- error("Cannot understand option %s", argv[i]);
2736
- exit(1);
2737
- }
2735
+ error("Cannot understand option %s", argv[i]);
2736
+ exit(1);
2737
+ }
2738
2739
- if(freq > 0) update_every = freq;
2740
- if(!name) name = "groups";
2739
+ if(freq > 0) update_every = freq;
2740
+ if(!name) name = "groups";
2741
2742
- if(read_apps_groups_conf(name)) {
2743
- error("Cannot read process groups %s", name);
2744
- exit(1);
2745
- }
2742
+ if(read_apps_groups_conf(name)) {
2743
+ error("Cannot read process groups %s", name);
2744
+ exit(1);
2745
+ }
2746
}
2747
2748
int main(int argc, char **argv)
2749
{
2750
- // debug_flags = D_PROCFILE;
2750
+ // debug_flags = D_PROCFILE;
2751
2752
- // set the name for logging
2753
- program_name = "apps.plugin";
2752
+ // set the name for logging
2753
+ program_name = "apps.plugin";
2754
2755
- // disable syslog for apps.plugin
2756
- error_log_syslog = 0;
2755
+ // disable syslog for apps.plugin
2756
+ error_log_syslog = 0;
2757
2758
- // set errors flood protection to 100 logs per hour
2759
- error_log_errors_per_period = 100;
2760
- error_log_throttle_period = 3600;
2758
+ // set errors flood protection to 100 logs per hour
2759
+ error_log_errors_per_period = 100;
2760
+ error_log_throttle_period = 3600;
2761
2762
- host_prefix = getenv("NETDATA_HOST_PREFIX");
2763
- if(host_prefix == NULL) {
2764
- info("NETDATA_HOST_PREFIX is not passed from netdata");
2765
- host_prefix = "";
2766
- }
2767
- else info("Found NETDATA_HOST_PREFIX='%s'", host_prefix);
2762
+ host_prefix = getenv("NETDATA_HOST_PREFIX");
2763
+ if(host_prefix == NULL) {
2764
+ info("NETDATA_HOST_PREFIX is not passed from netdata");
2765
+ host_prefix = "";
2766
+ }
2767
+ else info("Found NETDATA_HOST_PREFIX='%s'", host_prefix);
2768
2769
- config_dir = getenv("NETDATA_CONFIG_DIR");
2770
- if(config_dir == NULL) {
2771
- info("NETDATA_CONFIG_DIR is not passed from netdata");
2772
- config_dir = CONFIG_DIR;
2773
- }
2774
- else info("Found NETDATA_CONFIG_DIR='%s'", config_dir);
2769
+ config_dir = getenv("NETDATA_CONFIG_DIR");
2770
+ if(config_dir == NULL) {
2771
+ info("NETDATA_CONFIG_DIR is not passed from netdata");
2772
+ config_dir = CONFIG_DIR;
2773
+ }
2774
+ else info("Found NETDATA_CONFIG_DIR='%s'", config_dir);
2775
2776
#ifdef NETDATA_INTERNAL_CHECKS
2777
- if(debug_flags != 0) {
2778
- struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY };
2779
- if(setrlimit(RLIMIT_CORE, &rl) != 0)
2780
- info("Cannot request unlimited core dumps for debugging... Proceeding anyway...");
2781
- prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
2782
- }
2777
+ if(debug_flags != 0) {
2778
+ struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY };
2779
+ if(setrlimit(RLIMIT_CORE, &rl) != 0)
2780
+ info("Cannot request unlimited core dumps for debugging... Proceeding anyway...");
2781
+ prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
2782
+ }
2783
#endif /* NETDATA_INTERNAL_CHECKS */
2784
2785
- procfile_adaptive_initial_allocation = 1;
2786
-
2787
- time_t started_t = time(NULL);
2788
- time_t current_t;
2789
- get_HZ();
2790
- pid_max = get_system_pid_max();
2791
- processors = get_system_cpus();
2792
-
2793
- parse_args(argc, argv);
2794
-
2795
- all_pids_sortlist = callocz(sizeof(pid_t), (size_t)pid_max);
2796
- all_pids = callocz(sizeof(struct pid_stat *), (size_t) pid_max);
2797
-
2798
- output = buffer_create(1024);
2799
- buffer_sprintf(output,
2800
- "CHART netdata.apps_cpu '' 'Apps Plugin CPU' 'milliseconds/s' apps.plugin netdata.apps_cpu stacked 140000 %1$d\n"
2801
- "DIMENSION user '' incremental 1 1000\n"
2802
- "DIMENSION system '' incremental 1 1000\n"
2803
- "CHART netdata.apps_files '' 'Apps Plugin Files' 'files/s' apps.plugin netdata.apps_files line 140001 %1$d\n"
2804
- "DIMENSION files '' incremental 1 1\n"
2805
- "DIMENSION pids '' absolute 1 1\n"
2806
- "DIMENSION fds '' absolute 1 1\n"
2807
- "DIMENSION targets '' absolute 1 1\n"
2808
- "CHART netdata.apps_fix '' 'Apps Plugin Normalization Ratios' 'percentage' apps.plugin netdata.apps_fix line 140002 %1$d\n"
2809
- "DIMENSION utime '' absolute 1 %2$llu\n"
2810
- "DIMENSION stime '' absolute 1 %2$llu\n"
2811
- "DIMENSION gtime '' absolute 1 %2$llu\n"
2812
- "DIMENSION minflt '' absolute 1 %2$llu\n"
2813
- "DIMENSION majflt '' absolute 1 %2$llu\n"
2814
- , update_every
2815
- , RATES_DETAIL
2816
- );
2817
-
2818
- if(include_exited_childs)
2819
- buffer_sprintf(output,
2820
- "CHART netdata.apps_children_fix '' 'Apps Plugin Exited Children Normalization Ratios' 'percentage' apps.plugin netdata.apps_children_fix line 140003 %1$d\n"
2821
- "DIMENSION cutime '' absolute 1 %2$llu\n"
2822
- "DIMENSION cstime '' absolute 1 %2$llu\n"
2823
- "DIMENSION cgtime '' absolute 1 %2$llu\n"
2824
- "DIMENSION cminflt '' absolute 1 %2$llu\n"
2825
- "DIMENSION cmajflt '' absolute 1 %2$llu\n"
2826
- , update_every
2827
- , RATES_DETAIL
2828
- );
2785
+ procfile_adaptive_initial_allocation = 1;
2786
+
2787
+ time_t started_t = time(NULL);
2788
+ time_t current_t;
2789
+ get_HZ();
2790
+ pid_max = get_system_pid_max();
2791
+ processors = get_system_cpus();
2792
+
2793
+ parse_args(argc, argv);
2794
+
2795
+ all_pids_sortlist = callocz(sizeof(pid_t), (size_t)pid_max);
2796
+ all_pids = callocz(sizeof(struct pid_stat *), (size_t) pid_max);
2797
+
2798
+ output = buffer_create(1024);
2799
+ buffer_sprintf(output,
2800
+ "CHART netdata.apps_cpu '' 'Apps Plugin CPU' 'milliseconds/s' apps.plugin netdata.apps_cpu stacked 140000 %1$d\n"
2801
+ "DIMENSION user '' incremental 1 1000\n"
2802
+ "DIMENSION system '' incremental 1 1000\n"
2803
+ "CHART netdata.apps_files '' 'Apps Plugin Files' 'files/s' apps.plugin netdata.apps_files line 140001 %1$d\n"
2804
+ "DIMENSION files '' incremental 1 1\n"
2805
+ "DIMENSION pids '' absolute 1 1\n"
2806
+ "DIMENSION fds '' absolute 1 1\n"
2807
+ "DIMENSION targets '' absolute 1 1\n"
2808
+ "CHART netdata.apps_fix '' 'Apps Plugin Normalization Ratios' 'percentage' apps.plugin netdata.apps_fix line 140002 %1$d\n"
2809
+ "DIMENSION utime '' absolute 1 %2$llu\n"
2810
+ "DIMENSION stime '' absolute 1 %2$llu\n"
2811
+ "DIMENSION gtime '' absolute 1 %2$llu\n"
2812
+ "DIMENSION minflt '' absolute 1 %2$llu\n"
2813
+ "DIMENSION majflt '' absolute 1 %2$llu\n"
2814
+ , update_every
2815
+ , RATES_DETAIL
2816
+ );
2817
+
2818
+ if(include_exited_childs)
2819
+ buffer_sprintf(output,
2820
+ "CHART netdata.apps_children_fix '' 'Apps Plugin Exited Children Normalization Ratios' 'percentage' apps.plugin netdata.apps_children_fix line 140003 %1$d\n"
2821
+ "DIMENSION cutime '' absolute 1 %2$llu\n"
2822
+ "DIMENSION cstime '' absolute 1 %2$llu\n"
2823
+ "DIMENSION cgtime '' absolute 1 %2$llu\n"
2824
+ "DIMENSION cminflt '' absolute 1 %2$llu\n"
2825
+ "DIMENSION cmajflt '' absolute 1 %2$llu\n"
2826
+ , update_every
2827
+ , RATES_DETAIL
2828
+ );
2829
2830
#ifndef PROFILING_MODE
2831
- unsigned long long sunext = (time(NULL) - (time(NULL) % update_every) + update_every) * 1000000ULL;
2832
- unsigned long long sunow;
2831
+ unsigned long long sunext = (time(NULL) - (time(NULL) % update_every) + update_every) * 1000000ULL;
This file is too large to show in full.
src/avl.c
+27
-27
@@ -15,7 +15,7 @@
15
16
17
/* Search |tree| for an item matching |item|, and return it if found.
18
- Otherwise return |NULL|. */
18
+ Otherwise return |NULL|. */
19
avl *avl_search(avl_tree *tree, avl *item) {
20
avl *p;
21
@@ -36,8 +36,8 @@ avl *avl_search(avl_tree *tree, avl *item) {
36
}
37
38
/* Inserts |item| into |tree| and returns a pointer to |item|'s address.
39
- If a duplicate item is found in the tree,
40
- returns a pointer to the duplicate without inserting |item|.
39
+ If a duplicate item is found in the tree,
40
+ returns a pointer to the duplicate without inserting |item|.
41
*/
42
avl *avl_insert(avl_tree *tree, avl *item) {
43
avl *y, *z; /* Top node to update balance factor, and parent. */
@@ -134,7 +134,7 @@ avl *avl_insert(avl_tree *tree, avl *item) {
134
}
135
136
/* Deletes from |tree| and returns an item matching |item|.
137
- Returns a null pointer if no matching item found. */
137
+ Returns a null pointer if no matching item found. */
138
avl *avl_remove(avl_tree *tree, avl *item) {
139
/* Stack of nodes. */
140
avl *pa[AVL_MAX_HEIGHT]; /* Nodes. */
@@ -283,9 +283,9 @@ avl *avl_remove(avl_tree *tree, avl *item) {
283
void avl_read_lock(avl_tree_lock *t) {
284
#ifndef AVL_WITHOUT_PTHREADS
285
#ifdef AVL_LOCK_WITH_MUTEX
286
- pthread_mutex_lock(&t->mutex);
286
+ pthread_mutex_lock(&t->mutex);
287
#else
288
- pthread_rwlock_rdlock(&t->rwlock);
288
+ pthread_rwlock_rdlock(&t->rwlock);
289
#endif
290
#endif /* AVL_WITHOUT_PTHREADS */
291
}
@@ -293,9 +293,9 @@ void avl_read_lock(avl_tree_lock *t) {
293
void avl_write_lock(avl_tree_lock *t) {
294
#ifndef AVL_WITHOUT_PTHREADS
295
#ifdef AVL_LOCK_WITH_MUTEX
296
- pthread_mutex_lock(&t->mutex);
296
+ pthread_mutex_lock(&t->mutex);
297
#else
298
- pthread_rwlock_wrlock(&t->rwlock);
298
+ pthread_rwlock_wrlock(&t->rwlock);
299
#endif
300
#endif /* AVL_WITHOUT_PTHREADS */
301
}
@@ -303,9 +303,9 @@ void avl_write_lock(avl_tree_lock *t) {
303
void avl_unlock(avl_tree_lock *t) {
304
#ifndef AVL_WITHOUT_PTHREADS
305
#ifdef AVL_LOCK_WITH_MUTEX
306
- pthread_mutex_unlock(&t->mutex);
306
+ pthread_mutex_unlock(&t->mutex);
307
#else
308
- pthread_rwlock_unlock(&t->rwlock);
308
+ pthread_rwlock_unlock(&t->rwlock);
309
#endif
310
#endif /* AVL_WITHOUT_PTHREADS */
311
}
@@ -313,42 +313,42 @@ void avl_unlock(avl_tree_lock *t) {
313
/* ------------------------------------------------------------------------- */
314
315
void avl_init_lock(avl_tree_lock *t, int (*compar)(void *a, void *b)) {
316
- avl_init(&t->avl_tree, compar);
316
+ avl_init(&t->avl_tree, compar);
317
318
#ifndef AVL_WITHOUT_PTHREADS
319
- int lock;
319
+ int lock;
320
321
#ifdef AVL_LOCK_WITH_MUTEX
322
- lock = pthread_mutex_init(&t->mutex, NULL);
322
+ lock = pthread_mutex_init(&t->mutex, NULL);
323
#else
324
- lock = pthread_rwlock_init(&t->rwlock, NULL);
324
+ lock = pthread_rwlock_init(&t->rwlock, NULL);
325
#endif
326
327
- if(lock != 0)
328
- fatal("Failed to initialize AVL mutex/rwlock, error: %d", lock);
327
+ if(lock != 0)
328
+ fatal("Failed to initialize AVL mutex/rwlock, error: %d", lock);
329
330
#endif /* AVL_WITHOUT_PTHREADS */
331
}
332
333
avl *avl_search_lock(avl_tree_lock *t, avl *a) {
334
- avl_read_lock(t);
335
- avl *ret = avl_search(&t->avl_tree, a);
336
- avl_unlock(t);
337
- return ret;
334
+ avl_read_lock(t);
335
+ avl *ret = avl_search(&t->avl_tree, a);
336
+ avl_unlock(t);
337
+ return ret;
338
}
339
340
avl * avl_remove_lock(avl_tree_lock *t, avl *a) {
341
- avl_write_lock(t);
342
- avl *ret = avl_remove(&t->avl_tree, a);
343
- avl_unlock(t);
344
- return ret;
341
+ avl_write_lock(t);
342
+ avl *ret = avl_remove(&t->avl_tree, a);
343
+ avl_unlock(t);
344
+ return ret;
345
}
346
347
avl *avl_insert_lock(avl_tree_lock *t, avl *a) {
348
- avl_write_lock(t);
348
+ avl_write_lock(t);
349
avl * ret = avl_insert(&t->avl_tree, a);
350
- avl_unlock(t);
351
- return ret;
350
+ avl_unlock(t);
351
+ return ret;
352
}
353
354
void avl_init(avl_tree *t, int (*compar)(void *a, void *b)) {
src/avl.h
+5
-5
@@ -32,18 +32,18 @@ typedef struct avl {
32
33
/* An AVL tree */
34
typedef struct avl_tree {
35
- avl *root;
36
- int (*compar)(void *a, void *b);
35
+ avl *root;
36
+ int (*compar)(void *a, void *b);
37
} avl_tree;
38
39
typedef struct avl_tree_lock {
40
- avl_tree avl_tree;
40
+ avl_tree avl_tree;
41
42
#ifndef AVL_WITHOUT_PTHREADS
43
#ifdef AVL_LOCK_WITH_MUTEX
44
- pthread_mutex_t mutex;
44
+ pthread_mutex_t mutex;
45
#else /* AVL_LOCK_WITH_MUTEX */
46
- pthread_rwlock_t rwlock;
46
+ pthread_rwlock_t rwlock;
47
#endif /* AVL_LOCK_WITH_MUTEX */
48
#endif /* AVL_WITHOUT_PTHREADS */
49
} avl_tree_lock;
src/common.c
+28
-28
@@ -642,15 +642,15 @@ void netdata_fix_chart_id(char *s) {
642
// http://stackoverflow.com/questions/7666509/hash-function-for-string
643
uint32_t simple_hash(const char *name)
644
{
645
- const char *s = name;
646
- uint32_t hash = 5381;
647
- int i;
645
+ const char *s = name;
646
+ uint32_t hash = 5381;
647
+ int i;
648
649
- while((i = *s++)) hash = ((hash << 5) + hash) + i;
649
+ while((i = *s++)) hash = ((hash << 5) + hash) + i;
650
651
- // fprintf(stderr, "HASH: %lu %s\n", hash, name);
651
+ // fprintf(stderr, "HASH: %lu %s\n", hash, name);
652
653
- return hash;
653
+ return hash;
654
}
655
*/
656
@@ -694,22 +694,22 @@ uint32_t simple_uhash(const char *name) {
694
// http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
695
// one at a time hash
696
uint32_t simple_hash(const char *name) {
697
- unsigned char *s = (unsigned char *)name;
698
- uint32_t h = 0;
697
+ unsigned char *s = (unsigned char *)name;
698
+ uint32_t h = 0;
699
700
- while(*s) {
701
- h += *s++;
702
- h += (h << 10);
703
- h ^= (h >> 6);
704
- }
700
+ while(*s) {
701
+ h += *s++;
702
+ h += (h << 10);
703
+ h ^= (h >> 6);
704
+ }
705
706
- h += (h << 3);
707
- h ^= (h >> 11);
708
- h += (h << 15);
706
+ h += (h << 3);
707
+ h ^= (h >> 11);
708
+ h += (h << 15);
709
710
- // fprintf(stderr, "HASH: %u = %s\n", h, name);
710
+ // fprintf(stderr, "HASH: %u = %s\n", h, name);
711
712
- return h;
712
+ return h;
713
}
714
*/
715
@@ -782,16 +782,16 @@ void *mymmap(const char *filename, size_t size, int flags, int ksm) {
782
#ifdef MADV_MERGEABLE
783
} else {
784
/*
785
- // test - load the file into memory
786
- mem = calloc(1, size);
787
- if(mem) {
788
- if(lseek(fd, 0, SEEK_SET) == 0) {
789
- if(read(fd, mem, size) != (ssize_t)size)
790
- error("Cannot read from file '%s'", filename);
791
- }
792
- else
793
- error("Cannot seek to beginning of file '%s'.", filename);
794
- }
785
+ // test - load the file into memory
786
+ mem = calloc(1, size);
787
+ if(mem) {
788
+ if(lseek(fd, 0, SEEK_SET) == 0) {
789
+ if(read(fd, mem, size) != (ssize_t)size)
790
+ error("Cannot read from file '%s'", filename);
791
+ }
792
+ else
793
+ error("Cannot seek to beginning of file '%s'.", filename);
794
+ }
795
*/
796
mem = mmap(NULL, size, PROT_READ | PROT_WRITE, flags | MAP_ANONYMOUS, -1, 0);
797
if (mem != MAP_FAILED) {
src/daemon.c
+168
-168
@@ -23,195 +23,195 @@ void sig_handler_logrotate(int signo)
23
24
void sig_handler_save(int signo)
25
{
26
- if(signo) {
26
+ if(signo) {
27
error_log_limit_reset();
28
- info("Received signal %d to save the database...", signo);
29
- rrdset_save_all();
30
- }
28
+ info("Received signal %d to save the database...", signo);
29
+ rrdset_save_all();
30
+ }
31
}
32
33
static void chown_open_file(int fd, uid_t uid, gid_t gid) {
34
- if(fd == -1) return;
34
+ if(fd == -1) return;
35
36
- struct stat buf;
36
+ struct stat buf;
37
38
- if(fstat(fd, &buf) == -1) {
39
- error("Cannot fstat() fd %d", fd);
40
- return;
41
- }
38
+ if(fstat(fd, &buf) == -1) {
39
+ error("Cannot fstat() fd %d", fd);
40
+ return;
41
+ }
42
43
- if((buf.st_uid != uid || buf.st_gid != gid) && S_ISREG(buf.st_mode)) {
44
- if(fchown(fd, uid, gid) == -1)
45
- error("Cannot fchown() fd %d.", fd);
46
- }
43
+ if((buf.st_uid != uid || buf.st_gid != gid) && S_ISREG(buf.st_mode)) {
44
+ if(fchown(fd, uid, gid) == -1)
45
+ error("Cannot fchown() fd %d.", fd);
46
+ }
47
}
48
49
int become_user(const char *username, int pid_fd)
50
{
51
- struct passwd *pw = getpwnam(username);
52
- if(!pw) {
53
- error("User %s is not present.", username);
54
- return -1;
55
- }
56
-
57
- uid_t uid = pw->pw_uid;
58
- gid_t gid = pw->pw_gid;
59
-
60
- int ngroups = (int)sysconf(_SC_NGROUPS_MAX);
61
- gid_t *supplementary_groups = NULL;
62
- if(ngroups) {
63
- supplementary_groups = mallocz(sizeof(gid_t) * ngroups);
64
- if(getgrouplist(username, gid, supplementary_groups, &ngroups) == -1) {
65
- error("Cannot get supplementary groups of user '%s'.", username);
66
- freez(supplementary_groups);
67
- supplementary_groups = NULL;
68
- ngroups = 0;
69
- }
70
- }
71
-
72
- chown_open_file(STDOUT_FILENO, uid, gid);
73
- chown_open_file(STDERR_FILENO, uid, gid);
74
- chown_open_file(stdaccess_fd, uid, gid);
75
- chown_open_file(pid_fd, uid, gid);
76
-
77
- if(supplementary_groups && ngroups) {
78
- if(setgroups(ngroups, supplementary_groups) == -1)
79
- error("Cannot set supplementary groups for user '%s'", username);
80
-
81
- freez(supplementary_groups);
82
- supplementary_groups = NULL;
83
- ngroups = 0;
84
- }
85
-
86
- if(setresgid(gid, gid, gid) != 0) {
87
- error("Cannot switch to user's %s group (gid: %u).", username, gid);
88
- return -1;
89
- }
90
-
91
- if(setresuid(uid, uid, uid) != 0) {
92
- error("Cannot switch to user %s (uid: %u).", username, uid);
93
- return -1;
94
- }
95
-
96
- if(setgid(gid) != 0) {
97
- error("Cannot switch to user's %s group (gid: %u).", username, gid);
98
- return -1;
99
- }
100
- if(setegid(gid) != 0) {
101
- error("Cannot effectively switch to user's %s group (gid: %u).", username, gid);
102
- return -1;
103
- }
104
- if(setuid(uid) != 0) {
105
- error("Cannot switch to user %s (uid: %u).", username, uid);
106
- return -1;
107
- }
108
- if(seteuid(uid) != 0) {
109
- error("Cannot effectively switch to user %s (uid: %u).", username, uid);
110
- return -1;
111
- }
112
-
113
- return(0);
51
+ struct passwd *pw = getpwnam(username);
52
+ if(!pw) {
53
+ error("User %s is not present.", username);
54
+ return -1;
55
+ }
56
+
57
+ uid_t uid = pw->pw_uid;
58
+ gid_t gid = pw->pw_gid;
59
+
60
+ int ngroups = (int)sysconf(_SC_NGROUPS_MAX);
61
+ gid_t *supplementary_groups = NULL;
62
+ if(ngroups) {
63
+ supplementary_groups = mallocz(sizeof(gid_t) * ngroups);
64
+ if(getgrouplist(username, gid, supplementary_groups, &ngroups) == -1) {
65
+ error("Cannot get supplementary groups of user '%s'.", username);
66
+ freez(supplementary_groups);
67
+ supplementary_groups = NULL;
68
+ ngroups = 0;
69
+ }
70
+ }
71
+
72
+ chown_open_file(STDOUT_FILENO, uid, gid);
73
+ chown_open_file(STDERR_FILENO, uid, gid);
74
+ chown_open_file(stdaccess_fd, uid, gid);
75
+ chown_open_file(pid_fd, uid, gid);
76
+
77
+ if(supplementary_groups && ngroups) {
78
+ if(setgroups(ngroups, supplementary_groups) == -1)
79
+ error("Cannot set supplementary groups for user '%s'", username);
80
+
81
+ freez(supplementary_groups);
82
+ supplementary_groups = NULL;
83
+ ngroups = 0;
84
+ }
85
+
86
+ if(setresgid(gid, gid, gid) != 0) {
87
+ error("Cannot switch to user's %s group (gid: %u).", username, gid);
88
+ return -1;
89
+ }
90
+
91
+ if(setresuid(uid, uid, uid) != 0) {
92
+ error("Cannot switch to user %s (uid: %u).", username, uid);
93
+ return -1;
94
+ }
95
+
96
+ if(setgid(gid) != 0) {
97
+ error("Cannot switch to user's %s group (gid: %u).", username, gid);
98
+ return -1;
99
+ }
100
+ if(setegid(gid) != 0) {
101
+ error("Cannot effectively switch to user's %s group (gid: %u).", username, gid);
102
+ return -1;
103
+ }
104
+ if(setuid(uid) != 0) {
105
+ error("Cannot switch to user %s (uid: %u).", username, uid);
106
+ return -1;
107
+ }
108
+ if(seteuid(uid) != 0) {
109
+ error("Cannot effectively switch to user %s (uid: %u).", username, uid);
110
+ return -1;
111
+ }
112
+
113
+ return(0);
114
}
115
116
void oom_score_adj(int score) {
117
- int done = 0;
118
- int fd = open("/proc/self/oom_score_adj", O_WRONLY);
119
- if(fd != -1) {
120
- char buf[10 + 1];
121
- ssize_t len = snprintfz(buf, 10, "%d", score);
122
- if(write(fd, buf, len) == len) done = 1;
123
- close(fd);
124
- }
125
-
126
- if(!done)
127
- error("Cannot adjust my Out-Of-Memory score to %d.", score);
128
- else
129
- info("Adjusted my Out-Of-Memory score to %d.", score);
117
+ int done = 0;
118
+ int fd = open("/proc/self/oom_score_adj", O_WRONLY);
119
+ if(fd != -1) {
120
+ char buf[10 + 1];
121
+ ssize_t len = snprintfz(buf, 10, "%d", score);
122
+ if(write(fd, buf, len) == len) done = 1;
123
+ close(fd);
124
+ }
125
+
126
+ if(!done)
127
+ error("Cannot adjust my Out-Of-Memory score to %d.", score);
128
+ else
129
+ info("Adjusted my Out-Of-Memory score to %d.", score);
130
}
131
132
int sched_setscheduler_idle(void) {
133
- const struct sched_param param = {
134
- .sched_priority = 0
135
- };
133
+ const struct sched_param param = {
134
+ .sched_priority = 0
135
+ };
136
137
- int i = sched_setscheduler(0, SCHED_IDLE, ¶m);
138
- if(i != 0)
139
- error("Cannot adjust my scheduling priority to IDLE.");
140
- else
141
- info("Adjusted my scheduling priority to IDLE.");
137
+ int i = sched_setscheduler(0, SCHED_IDLE, ¶m);
138
+ if(i != 0)
139
+ error("Cannot adjust my scheduling priority to IDLE.");
140
+ else
141
+ info("Adjusted my scheduling priority to IDLE.");
142
143
- return i;
143
+ return i;
144
}
145
146
int become_daemon(int dont_fork, const char *user)
147
{
148
- if(!dont_fork) {
149
- int i = fork();
150
- if(i == -1) {
151
- perror("cannot fork");
152
- exit(1);
153
- }
154
- if(i != 0) {
155
- exit(0); // the parent
156
- }
157
-
158
- // become session leader
159
- if (setsid() < 0) {
160
- perror("Cannot become session leader.");
161
- exit(2);
162
- }
163
-
164
- // fork() again
165
- i = fork();
166
- if(i == -1) {
167
- perror("cannot fork");
168
- exit(1);
169
- }
170
- if(i != 0) {
171
- exit(0); // the parent
172
- }
173
- }
174
-
175
- // generate our pid file
176
- int pidfd = -1;
177
- if(pidfile[0]) {
178
- pidfd = open(pidfile, O_WRONLY | O_CREAT, 0644);
179
- if(pidfd >= 0) {
180
- if(ftruncate(pidfd, 0) != 0)
181
- error("Cannot truncate pidfile '%s'.", pidfile);
182
-
183
- char b[100];
184
- sprintf(b, "%d\n", getpid());
185
- ssize_t i = write(pidfd, b, strlen(b));
186
- if(i <= 0)
187
- error("Cannot write pidfile '%s'.", pidfile);
188
- }
189
- else error("Failed to open pidfile '%s'.", pidfile);
190
- }
191
-
192
- // Set new file permissions
193
- umask(0002);
194
-
195
- // adjust my Out-Of-Memory score
196
- oom_score_adj(1000);
197
-
198
- // never become a problem
199
- if(sched_setscheduler_idle() != 0) {
200
- if(nice(19) == -1) error("Cannot lower my CPU priority.");
201
- else info("Set my nice value to 19.");
202
- }
203
-
204
- if(user && *user) {
205
- if(become_user(user, pidfd) != 0) {
206
- error("Cannot become user '%s'. Continuing as we are.", user);
207
- }
208
- else info("Successfully became user '%s'.", user);
209
- }
210
-
211
- if(pidfd != -1) {
212
- close(pidfd);
213
- pidfd = -1;
214
- }
215
-
216
- return(0);
148
+ if(!dont_fork) {
149
+ int i = fork();
150
+ if(i == -1) {
151
+ perror("cannot fork");
152
+ exit(1);
153
+ }
154
+ if(i != 0) {
155
+ exit(0); // the parent
156
+ }
157
+
158
+ // become session leader
159
+ if (setsid() < 0) {
160
+ perror("Cannot become session leader.");
161
+ exit(2);
162
+ }
163
+
164
+ // fork() again
165
+ i = fork();
166
+ if(i == -1) {
167
+ perror("cannot fork");
168
+ exit(1);
169
+ }
170
+ if(i != 0) {
171
+ exit(0); // the parent
172
+ }
173
+ }
174
+
175
+ // generate our pid file
176
+ int pidfd = -1;
177
+ if(pidfile[0]) {
178
+ pidfd = open(pidfile, O_WRONLY | O_CREAT, 0644);
179
+ if(pidfd >= 0) {
180
+ if(ftruncate(pidfd, 0) != 0)
181
+ error("Cannot truncate pidfile '%s'.", pidfile);
182
+
183
+ char b[100];
184
+ sprintf(b, "%d\n", getpid());
185
+ ssize_t i = write(pidfd, b, strlen(b));
186
+ if(i <= 0)
187
+ error("Cannot write pidfile '%s'.", pidfile);
188
+ }
189
+ else error("Failed to open pidfile '%s'.", pidfile);
190
+ }
191
+
192
+ // Set new file permissions
193
+ umask(0002);
194
+
195
+ // adjust my Out-Of-Memory score
196
+ oom_score_adj(1000);
197
+
198
+ // never become a problem
199
+ if(sched_setscheduler_idle() != 0) {
200
+ if(nice(19) == -1) error("Cannot lower my CPU priority.");
201
+ else info("Set my nice value to 19.");
202
+ }
203
+
204
+ if(user && *user) {
205
+ if(become_user(user, pidfd) != 0) {
206
+ error("Cannot become user '%s'. Continuing as we are.", user);
207
+ }
208
+ else info("Successfully became user '%s'.", user);
209
+ }
210
+
211
+ if(pidfd != -1) {
212
+ close(pidfd);
213
+ pidfd = -1;
214
+ }
215
+
216
+ return(0);
217
}
src/dictionary.c
+157
-157
@@ -4,24 +4,24 @@
4
// dictionary statistics
5
6
static inline void NETDATA_DICTIONARY_STATS_INSERTS_PLUS1(DICTIONARY *dict) {
7
- if(likely(dict->stats))
8
- dict->stats->inserts++;
7
+ if(likely(dict->stats))
8
+ dict->stats->inserts++;
9
}
10
static inline void NETDATA_DICTIONARY_STATS_DELETES_PLUS1(DICTIONARY *dict) {
11
- if(likely(dict->stats))
12
- dict->stats->deletes++;
11
+ if(likely(dict->stats))
12
+ dict->stats->deletes++;
13
}
14
static inline void NETDATA_DICTIONARY_STATS_SEARCHES_PLUS1(DICTIONARY *dict) {
15
- if(likely(dict->stats))
16
- dict->stats->searches++;
15
+ if(likely(dict->stats))
16
+ dict->stats->searches++;
17
}
18
static inline void NETDATA_DICTIONARY_STATS_ENTRIES_PLUS1(DICTIONARY *dict) {
19
- if(likely(dict->stats))
20
- dict->stats->entries++;
19
+ if(likely(dict->stats))
20
+ dict->stats->entries++;
21
}
22
static inline void NETDATA_DICTIONARY_STATS_ENTRIES_MINUS1(DICTIONARY *dict) {
23
- if(likely(dict->stats))
24
- dict->stats->entries--;
23
+ if(likely(dict->stats))
24
+ dict->stats->entries--;
25
}
26
27
@@ -29,24 +29,24 @@ static inline void NETDATA_DICTIONARY_STATS_ENTRIES_MINUS1(DICTIONARY *dict) {
29
// dictionary locks
30
31
static inline void dictionary_read_lock(DICTIONARY *dict) {
32
- if(likely(dict->rwlock)) {
33
- // debug(D_DICTIONARY, "Dictionary READ lock");
34
- pthread_rwlock_rdlock(dict->rwlock);
35
- }
32
+ if(likely(dict->rwlock)) {
33
+ // debug(D_DICTIONARY, "Dictionary READ lock");
34
+ pthread_rwlock_rdlock(dict->rwlock);
35
+ }
36
}
37
38
static inline void dictionary_write_lock(DICTIONARY *dict) {
39
- if(likely(dict->rwlock)) {
40
- // debug(D_DICTIONARY, "Dictionary WRITE lock");
41
- pthread_rwlock_wrlock(dict->rwlock);
42
- }
39
+ if(likely(dict->rwlock)) {
40
+ // debug(D_DICTIONARY, "Dictionary WRITE lock");
41
+ pthread_rwlock_wrlock(dict->rwlock);
42
+ }
43
}
44
45
static inline void dictionary_unlock(DICTIONARY *dict) {
46
- if(likely(dict->rwlock)) {
47
- // debug(D_DICTIONARY, "Dictionary UNLOCK lock");
48
- pthread_rwlock_unlock(dict->rwlock);
49
- }
46
+ if(likely(dict->rwlock)) {
47
+ // debug(D_DICTIONARY, "Dictionary UNLOCK lock");
48
+ pthread_rwlock_unlock(dict->rwlock);
49
+ }
50
}
51
52
@@ -54,196 +54,196 @@ static inline void dictionary_unlock(DICTIONARY *dict) {
54
// avl index
55
56
static int name_value_compare(void* a, void* b) {
57
- if(((NAME_VALUE *)a)->hash < ((NAME_VALUE *)b)->hash) return -1;
58
- else if(((NAME_VALUE *)a)->hash > ((NAME_VALUE *)b)->hash) return 1;
59
- else return strcmp(((NAME_VALUE *)a)->name, ((NAME_VALUE *)b)->name);
57
+ if(((NAME_VALUE *)a)->hash < ((NAME_VALUE *)b)->hash) return -1;
58
+ else if(((NAME_VALUE *)a)->hash > ((NAME_VALUE *)b)->hash) return 1;
59
+ else return strcmp(((NAME_VALUE *)a)->name, ((NAME_VALUE *)b)->name);
60
}
61
62
#define dictionary_name_value_index_add_nolock(dict, nv) do { NETDATA_DICTIONARY_STATS_INSERTS_PLUS1(dict); avl_insert(&((dict)->values_index), (avl *)(nv)); } while(0)
63
#define dictionary_name_value_index_del_nolock(dict, nv) do { NETDATA_DICTIONARY_STATS_DELETES_PLUS1(dict); avl_remove(&(dict->values_index), (avl *)(nv)); } while(0)
64
65
static inline NAME_VALUE *dictionary_name_value_index_find_nolock(DICTIONARY *dict, const char *name, uint32_t hash) {
66
- NAME_VALUE tmp;
67
- tmp.hash = (hash)?hash:simple_hash(name);
68
- tmp.name = (char *)name;
66
+ NAME_VALUE tmp;
67
+ tmp.hash = (hash)?hash:simple_hash(name);
68
+ tmp.name = (char *)name;
69
70
- NETDATA_DICTIONARY_STATS_SEARCHES_PLUS1(dict);
71
- return (NAME_VALUE *)avl_search(&(dict->values_index), (avl *) &tmp);
70
+ NETDATA_DICTIONARY_STATS_SEARCHES_PLUS1(dict);
71
+ return (NAME_VALUE *)avl_search(&(dict->values_index), (avl *) &tmp);
72
}
73
74
// ----------------------------------------------------------------------------
75
// internal methods
76
77
static NAME_VALUE *dictionary_name_value_create_nolock(DICTIONARY *dict, const char *name, void *value, size_t value_len, uint32_t hash) {
78
- debug(D_DICTIONARY, "Creating name value entry for name '%s'.", name);
78
+ debug(D_DICTIONARY, "Creating name value entry for name '%s'.", name);
79
80
- NAME_VALUE *nv = callocz(1, sizeof(NAME_VALUE));
80
+ NAME_VALUE *nv = callocz(1, sizeof(NAME_VALUE));
81
82
- if(dict->flags & DICTIONARY_FLAG_NAME_LINK_DONT_CLONE)
83
- nv->name = (char *)name;
84
- else {
85
- nv->name = strdupz(name);
86
- }
82
+ if(dict->flags & DICTIONARY_FLAG_NAME_LINK_DONT_CLONE)
83
+ nv->name = (char *)name;
84
+ else {
85
+ nv->name = strdupz(name);
86
+ }
87
88
- nv->hash = (hash)?hash:simple_hash(nv->name);
88
+ nv->hash = (hash)?hash:simple_hash(nv->name);
89
90
- if(dict->flags & DICTIONARY_FLAG_VALUE_LINK_DONT_CLONE)
91
- nv->value = value;
92
- else {
93
- nv->value = mallocz(value_len);
94
- memcpy(nv->value, value, value_len);
95
- }
90
+ if(dict->flags & DICTIONARY_FLAG_VALUE_LINK_DONT_CLONE)
91
+ nv->value = value;
92
+ else {
93
+ nv->value = mallocz(value_len);
94
+ memcpy(nv->value, value, value_len);
95
+ }
96
97
- // index it
98
- dictionary_name_value_index_add_nolock(dict, nv);
99
- NETDATA_DICTIONARY_STATS_ENTRIES_PLUS1(dict);
97
+ // index it
98
+ dictionary_name_value_index_add_nolock(dict, nv);
99
+ NETDATA_DICTIONARY_STATS_ENTRIES_PLUS1(dict);
100
101
- return nv;
101
+ return nv;
102
}
103
104
static void dictionary_name_value_destroy_nolock(DICTIONARY *dict, NAME_VALUE *nv) {
105
- debug(D_DICTIONARY, "Destroying name value entry for name '%s'.", nv->name);
105
+ debug(D_DICTIONARY, "Destroying name value entry for name '%s'.", nv->name);
106
107
- dictionary_name_value_index_del_nolock(dict, nv);
107
+ dictionary_name_value_index_del_nolock(dict, nv);
108
109
- NETDATA_DICTIONARY_STATS_ENTRIES_MINUS1(dict);
109
+ NETDATA_DICTIONARY_STATS_ENTRIES_MINUS1(dict);
110
111
- if(!(dict->flags & DICTIONARY_FLAG_VALUE_LINK_DONT_CLONE)) {
112
- debug(D_REGISTRY, "Dictionary freeing value of '%s'", nv->name);
113
- freez(nv->value);
114
- }
111
+ if(!(dict->flags & DICTIONARY_FLAG_VALUE_LINK_DONT_CLONE)) {
112
+ debug(D_REGISTRY, "Dictionary freeing value of '%s'", nv->name);
113
+ freez(nv->value);
114
+ }
115
116
- if(!(dict->flags & DICTIONARY_FLAG_NAME_LINK_DONT_CLONE)) {
117
- debug(D_REGISTRY, "Dictionary freeing name '%s'", nv->name);
118
- freez(nv->name);
119
- }
116
+ if(!(dict->flags & DICTIONARY_FLAG_NAME_LINK_DONT_CLONE)) {
117
+ debug(D_REGISTRY, "Dictionary freeing name '%s'", nv->name);
118
+ freez(nv->name);
119
+ }
120
121
- freez(nv);
121
+ freez(nv);
122
}
123
124
// ----------------------------------------------------------------------------
125
// API - basic methods
126
127
DICTIONARY *dictionary_create(uint8_t flags) {
128
- debug(D_DICTIONARY, "Creating dictionary.");
128
+ debug(D_DICTIONARY, "Creating dictionary.");
129
130
- DICTIONARY *dict = callocz(1, sizeof(DICTIONARY));
130
+ DICTIONARY *dict = callocz(1, sizeof(DICTIONARY));
131
132
- if(flags & DICTIONARY_FLAG_WITH_STATISTICS)
133
- dict->stats = callocz(1, sizeof(struct dictionary_stats));
132
+ if(flags & DICTIONARY_FLAG_WITH_STATISTICS)
133
+ dict->stats = callocz(1, sizeof(struct dictionary_stats));
134
135
- if(!(flags & DICTIONARY_FLAG_SINGLE_THREADED)) {
136
- dict->rwlock = callocz(1, sizeof(pthread_rwlock_t));
137
- pthread_rwlock_init(dict->rwlock, NULL);
138
- }
135
+ if(!(flags & DICTIONARY_FLAG_SINGLE_THREADED)) {
136
+ dict->rwlock = callocz(1, sizeof(pthread_rwlock_t));
137
+ pthread_rwlock_init(dict->rwlock, NULL);
138
+ }
139
140
- avl_init(&dict->values_index, name_value_compare);
141
- dict->flags = flags;
140
+ avl_init(&dict->values_index, name_value_compare);
141
+ dict->flags = flags;
142
143
- return dict;
143
+ return dict;
144
}
145
146
void dictionary_destroy(DICTIONARY *dict) {
147
- debug(D_DICTIONARY, "Destroying dictionary.");
147
+ debug(D_DICTIONARY, "Destroying dictionary.");
148
149
- dictionary_write_lock(dict);
149
+ dictionary_write_lock(dict);
150
151
- while(dict->values_index.root)
152
- dictionary_name_value_destroy_nolock(dict, (NAME_VALUE *)dict->values_index.root);
151
+ while(dict->values_index.root)
152
+ dictionary_name_value_destroy_nolock(dict, (NAME_VALUE *)dict->values_index.root);
153
154
- dictionary_unlock(dict);
154
+ dictionary_unlock(dict);
155
156
- if(dict->stats)
157
- freez(dict->stats);
156
+ if(dict->stats)
157
+ freez(dict->stats);
158
159
- if(dict->rwlock)
160
- freez(dict->rwlock);
159
+ if(dict->rwlock)
160
+ freez(dict->rwlock);
161
162
- freez(dict);
162
+ freez(dict);
163
}
164
165
// ----------------------------------------------------------------------------
166
167
void *dictionary_set(DICTIONARY *dict, const char *name, void *value, size_t value_len) {
168
- debug(D_DICTIONARY, "SET dictionary entry with name '%s'.", name);
168
+ debug(D_DICTIONARY, "SET dictionary entry with name '%s'.", name);
169
170
- uint32_t hash = simple_hash(name);
170
+ uint32_t hash = simple_hash(name);
171
172
- dictionary_write_lock(dict);
172
+ dictionary_write_lock(dict);
173
174
- NAME_VALUE *nv = dictionary_name_value_index_find_nolock(dict, name, hash);
175
- if(unlikely(!nv)) {
176
- debug(D_DICTIONARY, "Dictionary entry with name '%s' not found. Creating a new one.", name);
174
+ NAME_VALUE *nv = dictionary_name_value_index_find_nolock(dict, name, hash);
175
+ if(unlikely(!nv)) {
176
+ debug(D_DICTIONARY, "Dictionary entry with name '%s' not found. Creating a new one.", name);
177
178
- nv = dictionary_name_value_create_nolock(dict, name, value, value_len, hash);
179
- if(unlikely(!nv))
180
- fatal("Cannot create name_value.");
181
- }
182
- else {
183
- debug(D_DICTIONARY, "Dictionary entry with name '%s' found. Changing its value.", name);
178
+ nv = dictionary_name_value_create_nolock(dict, name, value, value_len, hash);
179
+ if(unlikely(!nv))
180
+ fatal("Cannot create name_value.");
181
+ }
182
+ else {
183
+ debug(D_DICTIONARY, "Dictionary entry with name '%s' found. Changing its value.", name);
184
185
- if(dict->flags & DICTIONARY_FLAG_VALUE_LINK_DONT_CLONE) {
186
- debug(D_REGISTRY, "Dictionary: linking value to '%s'", name);
187
- nv->value = value;
188
- }
189
- else {
190
- debug(D_REGISTRY, "Dictionary: cloning value to '%s'", name);
185
+ if(dict->flags & DICTIONARY_FLAG_VALUE_LINK_DONT_CLONE) {
186
+ debug(D_REGISTRY, "Dictionary: linking value to '%s'", name);
187
+ nv->value = value;
188
+ }
189
+ else {
190
+ debug(D_REGISTRY, "Dictionary: cloning value to '%s'", name);
191
192
- // copy the new value without breaking
193
- // any other thread accessing the same entry
194
- void *new = mallocz(value_len),
195
- *old = nv->value;
192
+ // copy the new value without breaking
193
+ // any other thread accessing the same entry
194
+ void *new = mallocz(value_len),
195
+ *old = nv->value;
196
197
- memcpy(new, value, value_len);
198
- nv->value = new;
197
+ memcpy(new, value, value_len);
198
+ nv->value = new;
199
200
- debug(D_REGISTRY, "Dictionary: freeing old value of '%s'", name);
201
- freez(old);
202
- }
203
- }
200
+ debug(D_REGISTRY, "Dictionary: freeing old value of '%s'", name);
201
+ freez(old);
202
+ }
203
+ }
204
205
- dictionary_unlock(dict);
205
+ dictionary_unlock(dict);
206
207
- return nv->value;
207
+ return nv->value;
208
}
209
210
void *dictionary_get(DICTIONARY *dict, const char *name) {
211
- debug(D_DICTIONARY, "GET dictionary entry with name '%s'.", name);
211
+ debug(D_DICTIONARY, "GET dictionary entry with name '%s'.", name);
212
213
- dictionary_read_lock(dict);
214
- NAME_VALUE *nv = dictionary_name_value_index_find_nolock(dict, name, 0);
215
- dictionary_unlock(dict);
213
+ dictionary_read_lock(dict);
214
+ NAME_VALUE *nv = dictionary_name_value_index_find_nolock(dict, name, 0);
215
+ dictionary_unlock(dict);
216
217
- if(unlikely(!nv)) {
218
- debug(D_DICTIONARY, "Not found dictionary entry with name '%s'.", name);
219
- return NULL;
220
- }
217
+ if(unlikely(!nv)) {
218
+ debug(D_DICTIONARY, "Not found dictionary entry with name '%s'.", name);
219
+ return NULL;
220
+ }
221
222
- debug(D_DICTIONARY, "Found dictionary entry with name '%s'.", name);
223
- return nv->value;
222
+ debug(D_DICTIONARY, "Found dictionary entry with name '%s'.", name);
223
+ return nv->value;
224
}
225
226
int dictionary_del(DICTIONARY *dict, const char *name) {
227
- int ret;
227
+ int ret;
228
229
- debug(D_DICTIONARY, "DEL dictionary entry with name '%s'.", name);
229
+ debug(D_DICTIONARY, "DEL dictionary entry with name '%s'.", name);
230
231
- dictionary_write_lock(dict);
231
+ dictionary_write_lock(dict);
232
233
- NAME_VALUE *nv = dictionary_name_value_index_find_nolock(dict, name, 0);
234
- if(unlikely(!nv)) {
235
- debug(D_DICTIONARY, "Not found dictionary entry with name '%s'.", name);
236
- ret = -1;
237
- }
238
- else {
239
- debug(D_DICTIONARY, "Found dictionary entry with name '%s'.", name);
240
- dictionary_name_value_destroy_nolock(dict, nv);
241
- ret = 0;
242
- }
233
+ NAME_VALUE *nv = dictionary_name_value_index_find_nolock(dict, name, 0);
234
+ if(unlikely(!nv)) {
235
+ debug(D_DICTIONARY, "Not found dictionary entry with name '%s'.", name);
236
+ ret = -1;
237
+ }
238
+ else {
239
+ debug(D_DICTIONARY, "Found dictionary entry with name '%s'.", name);
240
+ dictionary_name_value_destroy_nolock(dict, nv);
241
+ ret = 0;
242
+ }
243
244
- dictionary_unlock(dict);
244
+ dictionary_unlock(dict);
245
246
- return ret;
246
+ return ret;
247
}
248
249
@@ -253,36 +253,36 @@ int dictionary_del(DICTIONARY *dict, const char *name) {
253
// do not user other dictionary calls while walking the dictionary - deadlock!
254
255
static int dictionary_walker(avl *a, int (*callback)(void *entry, void *data), void *data) {
256
- int total = 0, ret = 0;
256
+ int total = 0, ret = 0;
257
258
- if(a->avl_link[0]) {
259
- ret = dictionary_walker(a->avl_link[0], callback, data);
260
- if(ret < 0) return ret;
261
- total += ret;
262
- }
258
+ if(a->avl_link[0]) {
259
+ ret = dictionary_walker(a->avl_link[0], callback, data);
260
+ if(ret < 0) return ret;
261
+ total += ret;
262
+ }
263
264
- ret = callback(((NAME_VALUE *)a)->value, data);
265
- if(ret < 0) return ret;
266
- total += ret;
264
+ ret = callback(((NAME_VALUE *)a)->value, data);
265
+ if(ret < 0) return ret;
266
+ total += ret;
267
268
- if(a->avl_link[1]) {
269
- ret = dictionary_walker(a->avl_link[1], callback, data);
270
- if (ret < 0) return ret;
271
- total += ret;
272
- }
268
+ if(a->avl_link[1]) {
269
+ ret = dictionary_walker(a->avl_link[1], callback, data);
270
+ if (ret < 0) return ret;
271
+ total += ret;
272
+ }
273
274
- return total;
274
+ return total;
275
}
276
277
int dictionary_get_all(DICTIONARY *dict, int (*callback)(void *entry, void *data), void *data) {
278
- int ret = 0;
278
+ int ret = 0;
279
280
- dictionary_read_lock(dict);
280
+ dictionary_read_lock(dict);
281
282
- if(likely(dict->values_index.root))
283
- ret = dictionary_walker(dict->values_index.root, callback, data);
282
+ if(likely(dict->values_index.root))
283
+ ret = dictionary_walker(dict->values_index.root, callback, data);
284
285
- dictionary_unlock(dict);
285
+ dictionary_unlock(dict);
286
287
- return ret;
287
+ return ret;
288
}
src/dictionary.h
+18
-18
@@ -2,36 +2,36 @@
2
#define NETDATA_DICTIONARY_H 1
3
4
struct dictionary_stats {
5
- unsigned long long inserts;
6
- unsigned long long deletes;
7
- unsigned long long searches;
8
- unsigned long long entries;
5
+ unsigned long long inserts;
6
+ unsigned long long deletes;
7
+ unsigned long long searches;
8
+ unsigned long long entries;
9
};
10
11
typedef struct name_value {
12
- avl avl; // the index - this has to be first!
12
+ avl avl; // the index - this has to be first!
13
14
- uint32_t hash; // a simple hash to speed up searching
15
- // we first compare hashes, and only if the hashes are equal we do string comparisons
14
+ uint32_t hash; // a simple hash to speed up searching
15
+ // we first compare hashes, and only if the hashes are equal we do string comparisons
16
17
- char *name;
18
- void *value;
17
+ char *name;
18
+ void *value;
19
} NAME_VALUE;
20
21
typedef struct dictionary {
22
- avl_tree values_index;
22
+ avl_tree values_index;
23
24
- uint8_t flags;
24
+ uint8_t flags;
25
26
- struct dictionary_stats *stats;
27
- pthread_rwlock_t *rwlock;
26
+ struct dictionary_stats *stats;
27
+ pthread_rwlock_t *rwlock;
28
} DICTIONARY;
29
30
-#define DICTIONARY_FLAG_DEFAULT 0x00000000
31
-#define DICTIONARY_FLAG_SINGLE_THREADED 0x00000001
32
-#define DICTIONARY_FLAG_VALUE_LINK_DONT_CLONE 0x00000002
33
-#define DICTIONARY_FLAG_NAME_LINK_DONT_CLONE 0x00000004
34
-#define DICTIONARY_FLAG_WITH_STATISTICS 0x00000008
30
+#define DICTIONARY_FLAG_DEFAULT 0x00000000
31
+#define DICTIONARY_FLAG_SINGLE_THREADED 0x00000001
32
+#define DICTIONARY_FLAG_VALUE_LINK_DONT_CLONE 0x00000002
33
+#define DICTIONARY_FLAG_NAME_LINK_DONT_CLONE 0x00000004
34
+#define DICTIONARY_FLAG_WITH_STATISTICS 0x00000008
35
36
extern DICTIONARY *dictionary_create(uint8_t flags);
37
extern void dictionary_destroy(DICTIONARY *dict);
src/global_statistics.h
+5
-5
@@ -7,13 +7,13 @@
7
struct global_statistics {
8
volatile uint16_t connected_clients;
9
10
- volatile uint64_t web_requests;
10
+ volatile uint64_t web_requests;
11
volatile uint64_t web_usec;
12
volatile uint64_t web_usec_max;
13
- volatile uint64_t bytes_received;
14
- volatile uint64_t bytes_sent;
15
- volatile uint64_t content_size;
16
- volatile uint64_t compressed_content_size;
13
+ volatile uint64_t bytes_received;
14
+ volatile uint64_t bytes_sent;
15
+ volatile uint64_t content_size;
16
+ volatile uint64_t compressed_content_size;
17
};
18
19
extern volatile struct global_statistics global_statistics;
src/log.c
+170
-170
@@ -5,7 +5,7 @@ unsigned long long debug_flags = DEBUG;
5
6
int access_log_syslog = 1;
7
int error_log_syslog = 1;
8
-int output_log_syslog = 1; // debug log
8
+int output_log_syslog = 1; // debug log
9
10
int stdaccess_fd = -1;
11
FILE *stdaccess = NULL;
@@ -124,79 +124,79 @@ time_t error_log_throttle_period = 1200;
124
unsigned long error_log_errors_per_period = 200;
125
126
int error_log_limit(int reset) {
127
- static time_t start = 0;
128
- static unsigned long counter = 0, prevented = 0;
129
-
130
- // do not throttle if the period is 0
131
- if(error_log_throttle_period == 0)
132
- return 0;
133
-
134
- // prevent all logs if the errors per period is 0
135
- if(error_log_errors_per_period == 0)
136
- return 1;
137
-
138
- time_t now = time(NULL);
139
- if(!start) start = now;
140
-
141
- if(reset) {
142
- if(prevented) {
143
- log_date(stderr);
144
- fprintf(stderr, "%s: Resetting logging for process '%s' (prevented %lu logs in the last %ld seconds).\n"
145
- , program_name
146
- , program_name
147
- , prevented
148
- , now - start
149
- );
150
- }
151
-
152
- start = now;
153
- counter = 0;
154
- prevented = 0;
155
- }
156
-
157
- // detect if we log too much
158
- counter++;
159
-
160
- if(now - start > error_log_throttle_period) {
161
- if(prevented) {
162
- log_date(stderr);
163
- fprintf(stderr, "%s: Resuming logging from process '%s' (prevented %lu logs in the last %ld seconds).\n"
164
- , program_name
165
- , program_name
166
- , prevented
167
- , error_log_throttle_period
168
- );
169
- }
170
-
171
- // restart the period accounting
172
- start = now;
173
- counter = 1;
174
- prevented = 0;
175
-
176
- // log this error
177
- return 0;
178
- }
179
-
180
- if(counter > error_log_errors_per_period) {
181
- if(!prevented) {
182
- log_date(stderr);
183
- fprintf(stderr, "%s: Too many logs (%lu logs in %ld seconds, threshold is set to %lu logs in %ld seconds). Preventing more logs from process '%s' for %ld seconds.\n"
184
- , program_name
185
- , counter
186
- , now - start
187
- , error_log_errors_per_period
188
- , error_log_throttle_period
189
- , program_name
190
- , start + error_log_throttle_period - now);
191
- }
192
-
193
- prevented++;
194
-
195
- // prevent logging this error
196
- return 1;
197
- }
198
-
199
- return 0;
127
+ static time_t start = 0;
128
+ static unsigned long counter = 0, prevented = 0;
129
+
130
+ // do not throttle if the period is 0
131
+ if(error_log_throttle_period == 0)
132
+ return 0;
133
+
134
+ // prevent all logs if the errors per period is 0
135
+ if(error_log_errors_per_period == 0)
136
+ return 1;
137
+
138
+ time_t now = time(NULL);
139
+ if(!start) start = now;
140
+
141
+ if(reset) {
142
+ if(prevented) {
143
+ log_date(stderr);
144
+ fprintf(stderr, "%s: Resetting logging for process '%s' (prevented %lu logs in the last %ld seconds).\n"
145
+ , program_name
146
+ , program_name
147
+ , prevented
148
+ , now - start
149
+ );
150
+ }
151
+
152
+ start = now;
153
+ counter = 0;
154
+ prevented = 0;
155
+ }
156
+
157
+ // detect if we log too much
158
+ counter++;
159
+
160
+ if(now - start > error_log_throttle_period) {
161
+ if(prevented) {
162
+ log_date(stderr);
163
+ fprintf(stderr, "%s: Resuming logging from process '%s' (prevented %lu logs in the last %ld seconds).\n"
164
+ , program_name
165
+ , program_name
166
+ , prevented
167
+ , error_log_throttle_period
168
+ );
169
+ }
170
+
171
+ // restart the period accounting
172
+ start = now;
173
+ counter = 1;
174
+ prevented = 0;
175
+
176
+ // log this error
177
+ return 0;
178
+ }
179
+
180
+ if(counter > error_log_errors_per_period) {
181
+ if(!prevented) {
182
+ log_date(stderr);
183
+ fprintf(stderr, "%s: Too many logs (%lu logs in %ld seconds, threshold is set to %lu logs in %ld seconds). Preventing more logs from process '%s' for %ld seconds.\n"
184
+ , program_name
185
+ , counter
186
+ , now - start
187
+ , error_log_errors_per_period
188
+ , error_log_throttle_period
189
+ , program_name
190
+ , start + error_log_throttle_period - now);
191
+ }
192
+
193
+ prevented++;
194
+
195
+ // prevent logging this error
196
+ return 1;
197
+ }
198
+
199
+ return 0;
200
}
201
202
// ----------------------------------------------------------------------------
@@ -208,17 +208,17 @@ int error_log_limit(int reset) {
208
209
void log_date(FILE *out)
210
{
211
- char outstr[24];
212
- time_t t;
213
- struct tm *tmp, tmbuf;
211
+ char outstr[24];
212
+ time_t t;
213
+ struct tm *tmp, tmbuf;
214
215
- t = time(NULL);
216
- tmp = localtime_r(&t, &tmbuf);
215
+ t = time(NULL);
216
+ tmp = localtime_r(&t, &tmbuf);
217
218
- if (tmp == NULL) return;
219
- if (unlikely(strftime(outstr, sizeof(outstr), "%y-%m-%d %H:%M:%S", tmp) == 0)) return;
218
+ if (tmp == NULL) return;
219
+ if (unlikely(strftime(outstr, sizeof(outstr), "%y-%m-%d %H:%M:%S", tmp) == 0)) return;
220
221
- fprintf(out, "%s: ", outstr);
221
+ fprintf(out, "%s: ", outstr);
222
}
223
224
// ----------------------------------------------------------------------------
@@ -226,22 +226,22 @@ void log_date(FILE *out)
226
227
void debug_int( const char *file, const char *function, const unsigned long line, const char *fmt, ... )
228
{
229
- va_list args;
230
-
231
- log_date(stdout);
232
- va_start( args, fmt );
233
- printf("DEBUG (%04lu@%-10.10s:%-15.15s): %s: ", line, file, function, program_name);
234
- vprintf(fmt, args);
235
- va_end( args );
236
- putchar('\n');
237
-
238
- if(output_log_syslog) {
239
- va_start( args, fmt );
240
- vsyslog(LOG_ERR, fmt, args );
241
- va_end( args );
242
- }
243
-
244
- fflush(stdout);
229
+ va_list args;
230
+
231
+ log_date(stdout);
232
+ va_start( args, fmt );
233
+ printf("DEBUG (%04lu@%-10.10s:%-15.15s): %s: ", line, file, function, program_name);
234
+ vprintf(fmt, args);
235
+ va_end( args );
236
+ putchar('\n');
237
+
238
+ if(output_log_syslog) {
239
+ va_start( args, fmt );
240
+ vsyslog(LOG_ERR, fmt, args );
241
+ va_end( args );
242
+ }
243
+
244
+ fflush(stdout);
245
}
246
247
// ----------------------------------------------------------------------------
@@ -249,26 +249,26 @@ void debug_int( const char *file, const char *function, const unsigned long line
249
250
void info_int( const char *file, const char *function, const unsigned long line, const char *fmt, ... )
251
{
252
- va_list args;
252
+ va_list args;
253
254
- // prevent logging too much
255
- if(error_log_limit(0)) return;
254
+ // prevent logging too much
255
+ if(error_log_limit(0)) return;
256
257
- log_date(stderr);
257
+ log_date(stderr);
258
259
- va_start( args, fmt );
260
- if(debug_flags) fprintf(stderr, "INFO (%04lu@%-10.10s:%-15.15s): %s: ", line, file, function, program_name);
261
- else fprintf(stderr, "INFO: %s: ", program_name);
262
- vfprintf( stderr, fmt, args );
263
- va_end( args );
259
+ va_start( args, fmt );
260
+ if(debug_flags) fprintf(stderr, "INFO (%04lu@%-10.10s:%-15.15s): %s: ", line, file, function, program_name);
261
+ else fprintf(stderr, "INFO: %s: ", program_name);
262
+ vfprintf( stderr, fmt, args );
263
+ va_end( args );
264
265
- fputc('\n', stderr);
265
+ fputc('\n', stderr);
266
267
- if(error_log_syslog) {
268
- va_start( args, fmt );
269
- vsyslog(LOG_INFO, fmt, args );
270
- va_end( args );
271
- }
267
+ if(error_log_syslog) {
268
+ va_start( args, fmt );
269
+ vsyslog(LOG_INFO, fmt, args );
270
+ va_end( args );
271
+ }
272
}
273
274
// ----------------------------------------------------------------------------
@@ -276,56 +276,56 @@ void info_int( const char *file, const char *function, const unsigned long line,
276
277
void error_int( const char *prefix, const char *file, const char *function, const unsigned long line, const char *fmt, ... )
278
{
279
- va_list args;
280
-
281
- // prevent logging too much
282
- if(error_log_limit(0)) return;
283
-
284
- log_date(stderr);
285
-
286
- va_start( args, fmt );
287
- if(debug_flags) fprintf(stderr, "%s (%04lu@%-10.10s:%-15.15s): %s: ", prefix, line, file, function, program_name);
288
- else fprintf(stderr, "%s: %s: ", prefix, program_name);
289
- vfprintf( stderr, fmt, args );
290
- va_end( args );
291
-
292
- if(errno) {
293
- char buf[1024];
294
- fprintf(stderr, " (errno %d, %s)\n", errno, strerror_r(errno, buf, 1023));
295
- errno = 0;
296
- }
297
- else
298
- fputc('\n', stderr);
299
-
300
- if(error_log_syslog) {
301
- va_start( args, fmt );
302
- vsyslog(LOG_ERR, fmt, args );
303
- va_end( args );
304
- }
279
+ va_list args;
280
+
281
+ // prevent logging too much
282
+ if(error_log_limit(0)) return;
283
+
284
+ log_date(stderr);
285
+
286
+ va_start( args, fmt );
287
+ if(debug_flags) fprintf(stderr, "%s (%04lu@%-10.10s:%-15.15s): %s: ", prefix, line, file, function, program_name);
288
+ else fprintf(stderr, "%s: %s: ", prefix, program_name);
289
+ vfprintf( stderr, fmt, args );
290
+ va_end( args );
291
+
292
+ if(errno) {
293
+ char buf[1024];
294
+ fprintf(stderr, " (errno %d, %s)\n", errno, strerror_r(errno, buf, 1023));
295
+ errno = 0;
296
+ }
297
+ else
298
+ fputc('\n', stderr);
299
+
300
+ if(error_log_syslog) {
301
+ va_start( args, fmt );
302
+ vsyslog(LOG_ERR, fmt, args );
303
+ va_end( args );
304
+ }
305
}
306
307
void fatal_int( const char *file, const char *function, const unsigned long line, const char *fmt, ... )
308
{
309
- va_list args;
309
+ va_list args;
310
311
- log_date(stderr);
311
+ log_date(stderr);
312
313
- va_start( args, fmt );
314
- if(debug_flags) fprintf(stderr, "FATAL (%04lu@%-10.10s:%-15.15s): %s: ", line, file, function, program_name);
315
- else fprintf(stderr, "FATAL: %s: ", program_name);
316
- vfprintf( stderr, fmt, args );
317
- va_end( args );
313
+ va_start( args, fmt );
314
+ if(debug_flags) fprintf(stderr, "FATAL (%04lu@%-10.10s:%-15.15s): %s: ", line, file, function, program_name);
315
+ else fprintf(stderr, "FATAL: %s: ", program_name);
316
+ vfprintf( stderr, fmt, args );
317
+ va_end( args );
318
319
- perror(" # ");
320
- fputc('\n', stderr);
319
+ perror(" # ");
320
+ fputc('\n', stderr);
321
322
- if(error_log_syslog) {
323
- va_start( args, fmt );
324
- vsyslog(LOG_CRIT, fmt, args );
325
- va_end( args );
326
- }
322
+ if(error_log_syslog) {
323
+ va_start( args, fmt );
324
+ vsyslog(LOG_CRIT, fmt, args );
325
+ va_end( args );
326
+ }
327
328
- netdata_cleanup_and_exit(1);
328
+ netdata_cleanup_and_exit(1);
329
}
330
331
// ----------------------------------------------------------------------------
@@ -333,21 +333,21 @@ void fatal_int( const char *file, const char *function, const unsigned long line
333
334
void log_access( const char *fmt, ... )
335
{
336
- va_list args;
337
-
338
- if(stdaccess) {
339
- log_date(stdaccess);
340
-
341
- va_start( args, fmt );
342
- vfprintf( stdaccess, fmt, args );
343
- va_end( args );
344
- fputc('\n', stdaccess);
345
- }
346
-
347
- if(access_log_syslog) {
348
- va_start( args, fmt );
349
- vsyslog(LOG_INFO, fmt, args );
350
- va_end( args );
351
- }
336
+ va_list args;
337
+
338
+ if(stdaccess) {
339
+ log_date(stdaccess);
340
+
341
+ va_start( args, fmt );
342
+ vfprintf( stdaccess, fmt, args );
343
+ va_end( args );
344
+ fputc('\n', stdaccess);
345
+ }
346
+
347
+ if(access_log_syslog) {
348
+ va_start( args, fmt );
349
+ vsyslog(LOG_INFO, fmt, args );
350
+ va_end( args );
351
+ }
352
}
353
src/log.h
+13
-13
@@ -1,14 +1,14 @@
1
#ifndef NETDATA_LOG_H
2
#define NETDATA_LOG_H 1
3
4
-#define D_WEB_BUFFER 0x00000001
5
-#define D_WEB_CLIENT 0x00000002
6
-#define D_LISTENER 0x00000004
7
-#define D_WEB_DATA 0x00000008
8
-#define D_OPTIONS 0x00000010
4
+#define D_WEB_BUFFER 0x00000001
5
+#define D_WEB_CLIENT 0x00000002
6
+#define D_LISTENER 0x00000004
7
+#define D_WEB_DATA 0x00000008
8
+#define D_OPTIONS 0x00000010
9
#define D_PROCNETDEV_LOOP 0x00000020
10
-#define D_RRD_STATS 0x00000040
11
-#define D_WEB_CLIENT_ACCESS 0x00000080
10
+#define D_RRD_STATS 0x00000040
11
+#define D_WEB_CLIENT_ACCESS 0x00000080
12
#define D_TC_LOOP 0x00000100
13
#define D_DEFLATE 0x00000200
14
#define D_CONFIG 0x00000400
@@ -16,13 +16,13 @@
16
#define D_CHILDS 0x00001000
17
#define D_EXIT 0x00002000
18
#define D_CHECKS 0x00004000
19
-#define D_NFACCT_LOOP 0x00008000
20
-#define D_PROCFILE 0x00010000
21
-#define D_RRD_CALLS 0x00020000
22
-#define D_DICTIONARY 0x00040000
23
-#define D_MEMORY 0x00080000
19
+#define D_NFACCT_LOOP 0x00008000
20
+#define D_PROCFILE 0x00010000
21
+#define D_RRD_CALLS 0x00020000
22
+#define D_DICTIONARY 0x00040000
23
+#define D_MEMORY 0x00080000
24
#define D_CGROUP 0x00100000
25
-#define D_REGISTRY 0x00200000
25
+#define D_REGISTRY 0x00200000
26
#define D_VARIABLES 0x00400000
27
28
//#define DEBUG (D_WEB_CLIENT_ACCESS|D_LISTENER|D_RRD_STATS)
src/main.h
+9
-9
@@ -7,15 +7,15 @@ extern volatile sig_atomic_t netdata_exit;
7
* This struct contains information about command line options.
8
*/
9
struct option_def {
10
- /** The option character */
11
- const char val;
12
- /** The name of the long option. */
13
- const char *description;
14
- /** Short descripton what the option does */
15
- /** Name of the argument displayed in SYNOPSIS */
16
- const char *arg_name;
17
- /** Default value if not set */
18
- const char *default_value;
10
+ /** The option character */
11
+ const char val;
12
+ /** The name of the long option. */
13
+ const char *description;
14
+ /** Short descripton what the option does */
15
+ /** Name of the argument displayed in SYNOPSIS */
16
+ const char *arg_name;
17
+ /** Default value if not set */
18
+ const char *default_value;
19
};
20
21
/**
src/plugin_checks.c
+58
-58
@@ -2,83 +2,83 @@
2
3
void *checks_main(void *ptr)
4
{
5
- if(ptr) { ; }
5
+ if(ptr) { ; }
6
7
- info("CHECKS thread created with task id %d", gettid());
7
+ info("CHECKS thread created with task id %d", gettid());
8
9
- if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
10
- error("Cannot set pthread cancel type to DEFERRED.");
9
+ if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
10
+ error("Cannot set pthread cancel type to DEFERRED.");
11
12
- if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
13
- error("Cannot set pthread cancel state to ENABLE.");
12
+ if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
13
+ error("Cannot set pthread cancel state to ENABLE.");
14
15
- unsigned long long usec = 0, susec = rrd_update_every * 1000000ULL, loop_usec = 0, total_susec = 0;
16
- struct timeval now, last, loop;
15
+ unsigned long long usec = 0, susec = rrd_update_every * 1000000ULL, loop_usec = 0, total_susec = 0;
16
+ struct timeval now, last, loop;
17
18
- RRDSET *check1, *check2, *check3, *apps_cpu = NULL;
18
+ RRDSET *check1, *check2, *check3, *apps_cpu = NULL;
19
20
- check1 = rrdset_create("netdata", "check1", NULL, "netdata", NULL, "Caller gives microseconds", "a million !", 99999, rrd_update_every, RRDSET_TYPE_LINE);
21
- rrddim_add(check1, "absolute", NULL, -1, 1, RRDDIM_ABSOLUTE);
22
- rrddim_add(check1, "incremental", NULL, 1, 1, RRDDIM_INCREMENTAL);
20
+ check1 = rrdset_create("netdata", "check1", NULL, "netdata", NULL, "Caller gives microseconds", "a million !", 99999, rrd_update_every, RRDSET_TYPE_LINE);
21
+ rrddim_add(check1, "absolute", NULL, -1, 1, RRDDIM_ABSOLUTE);
22
+ rrddim_add(check1, "incremental", NULL, 1, 1, RRDDIM_INCREMENTAL);
23
24
- check2 = rrdset_create("netdata", "check2", NULL, "netdata", NULL, "Netdata calcs microseconds", "a million !", 99999, rrd_update_every, RRDSET_TYPE_LINE);
25
- rrddim_add(check2, "absolute", NULL, -1, 1, RRDDIM_ABSOLUTE);
26
- rrddim_add(check2, "incremental", NULL, 1, 1, RRDDIM_INCREMENTAL);
24
+ check2 = rrdset_create("netdata", "check2", NULL, "netdata", NULL, "Netdata calcs microseconds", "a million !", 99999, rrd_update_every, RRDSET_TYPE_LINE);
25
+ rrddim_add(check2, "absolute", NULL, -1, 1, RRDDIM_ABSOLUTE);
26
+ rrddim_add(check2, "incremental", NULL, 1, 1, RRDDIM_INCREMENTAL);
27
28
- check3 = rrdset_create("netdata", "checkdt", NULL, "netdata", NULL, "Clock difference", "microseconds diff", 99999, rrd_update_every, RRDSET_TYPE_LINE);
29
- rrddim_add(check3, "caller", NULL, 1, 1, RRDDIM_ABSOLUTE);
30
- rrddim_add(check3, "netdata", NULL, 1, 1, RRDDIM_ABSOLUTE);
31
- rrddim_add(check3, "apps.plugin", NULL, 1, 1, RRDDIM_ABSOLUTE);
28
+ check3 = rrdset_create("netdata", "checkdt", NULL, "netdata", NULL, "Clock difference", "microseconds diff", 99999, rrd_update_every, RRDSET_TYPE_LINE);
29
+ rrddim_add(check3, "caller", NULL, 1, 1, RRDDIM_ABSOLUTE);
30
+ rrddim_add(check3, "netdata", NULL, 1, 1, RRDDIM_ABSOLUTE);
31
+ rrddim_add(check3, "apps.plugin", NULL, 1, 1, RRDDIM_ABSOLUTE);
32
33
- gettimeofday(&last, NULL);
34
- while(1) {
35
- usleep(susec);
33
+ gettimeofday(&last, NULL);
34
+ while(1) {
35
+ usleep(susec);
36
37
- // find the time to sleep in order to wait exactly update_every seconds
38
- gettimeofday(&now, NULL);
39
- loop_usec = usec_dt(&now, &last);
40
- usec = loop_usec - susec;
41
- debug(D_PROCNETDEV_LOOP, "CHECK: last loop took %llu usec (worked for %llu, sleeped for %llu).", loop_usec, usec, susec);
37
+ // find the time to sleep in order to wait exactly update_every seconds
38
+ gettimeofday(&now, NULL);
39
+ loop_usec = usec_dt(&now, &last);
40
+ usec = loop_usec - susec;
41
+ debug(D_PROCNETDEV_LOOP, "CHECK: last loop took %llu usec (worked for %llu, sleeped for %llu).", loop_usec, usec, susec);
42
43
- if(usec < (rrd_update_every * 1000000ULL / 2ULL)) susec = (rrd_update_every * 1000000ULL) - usec;
44
- else susec = rrd_update_every * 1000000ULL / 2ULL;
43
+ if(usec < (rrd_update_every * 1000000ULL / 2ULL)) susec = (rrd_update_every * 1000000ULL) - usec;
44
+ else susec = rrd_update_every * 1000000ULL / 2ULL;
45
46
- // --------------------------------------------------------------------
47
- // Calculate loop time
46
+ // --------------------------------------------------------------------
47
+ // Calculate loop time
48
49
- last.tv_sec = now.tv_sec;
50
- last.tv_usec = now.tv_usec;
51
- total_susec += loop_usec;
49
+ last.tv_sec = now.tv_sec;
50
+ last.tv_usec = now.tv_usec;
51
+ total_susec += loop_usec;
52
53
- // --------------------------------------------------------------------
54
- // check chart 1
53
+ // --------------------------------------------------------------------
54
+ // check chart 1
55
56
- if(check1->counter_done) rrdset_next_usec(check1, loop_usec);
57
- rrddim_set(check1, "absolute", 1000000);
58
- rrddim_set(check1, "incremental", total_susec);
59
- rrdset_done(check1);
56
+ if(check1->counter_done) rrdset_next_usec(check1, loop_usec);
57
+ rrddim_set(check1, "absolute", 1000000);
58
+ rrddim_set(check1, "incremental", total_susec);
59
+ rrdset_done(check1);
60
61
- // --------------------------------------------------------------------
62
- // check chart 2
61
+ // --------------------------------------------------------------------
62
+ // check chart 2
63
64
- if(check2->counter_done) rrdset_next(check2);
65
- rrddim_set(check2, "absolute", 1000000);
66
- rrddim_set(check2, "incremental", total_susec);
67
- rrdset_done(check2);
64
+ if(check2->counter_done) rrdset_next(check2);
65
+ rrddim_set(check2, "absolute", 1000000);
66
+ rrddim_set(check2, "incremental", total_susec);
67
+ rrdset_done(check2);
68
69
- // --------------------------------------------------------------------
70
- // check chart 3
69
+ // --------------------------------------------------------------------
70
+ // check chart 3
71
72
- if(!apps_cpu) apps_cpu = rrdset_find("apps.cpu");
73
- if(check3->counter_done) rrdset_next_usec(check3, loop_usec);
74
- gettimeofday(&loop, NULL);
75
- rrddim_set(check3, "caller", (long long) usec_dt(&loop, &check1->last_collected_time));
76
- rrddim_set(check3, "netdata", (long long) usec_dt(&loop, &check2->last_collected_time));
77
- if(apps_cpu) rrddim_set(check3, "apps.plugin", (long long) usec_dt(&loop, &apps_cpu->last_collected_time));
78
- rrdset_done(check3);
79
- }
72
+ if(!apps_cpu) apps_cpu = rrdset_find("apps.cpu");
73
+ if(check3->counter_done) rrdset_next_usec(check3, loop_usec);
74
+ gettimeofday(&loop, NULL);
75
+ rrddim_set(check3, "caller", (long long) usec_dt(&loop, &check1->last_collected_time));
76
+ rrddim_set(check3, "netdata", (long long) usec_dt(&loop, &check2->last_collected_time));
77
+ if(apps_cpu) rrddim_set(check3, "apps.plugin", (long long) usec_dt(&loop, &apps_cpu->last_collected_time));
78
+ rrdset_done(check3);
79
+ }
80
81
- pthread_exit(NULL);
82
- return NULL;
81
+ pthread_exit(NULL);
82
+ return NULL;
83
}
84
src/plugin_idlejitter.c
+35
-35
@@ -4,51 +4,51 @@
4
5
void *cpuidlejitter_main(void *ptr)
6
{
7
- if(ptr) { ; }
7
+ if(ptr) { ; }
8
9
- info("CPU Idle Jitter thread created with task id %d", gettid());
9
+ info("CPU Idle Jitter thread created with task id %d", gettid());
10
11
- if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
12
- error("Cannot set pthread cancel type to DEFERRED.");
11
+ if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
12
+ error("Cannot set pthread cancel type to DEFERRED.");
13
14
- if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
15
- error("Cannot set pthread cancel state to ENABLE.");
14
+ if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
15
+ error("Cannot set pthread cancel state to ENABLE.");
16
17
- int sleep_ms = (int) config_get_number("plugin:idlejitter", "loop time in ms", CPU_IDLEJITTER_SLEEP_TIME_MS);
18
- if(sleep_ms <= 0) {
19
- config_set_number("plugin:idlejitter", "loop time in ms", CPU_IDLEJITTER_SLEEP_TIME_MS);
20
- sleep_ms = CPU_IDLEJITTER_SLEEP_TIME_MS;
21
- }
17
+ int sleep_ms = (int) config_get_number("plugin:idlejitter", "loop time in ms", CPU_IDLEJITTER_SLEEP_TIME_MS);
18
+ if(sleep_ms <= 0) {
19
+ config_set_number("plugin:idlejitter", "loop time in ms", CPU_IDLEJITTER_SLEEP_TIME_MS);
20
+ sleep_ms = CPU_IDLEJITTER_SLEEP_TIME_MS;
21
+ }
22
23
- RRDSET *st = rrdset_find("system.idlejitter");
24
- if(!st) {
25
- st = rrdset_create("system", "idlejitter", NULL, "processes", NULL, "CPU Idle Jitter", "microseconds lost/s", 9999, rrd_update_every, RRDSET_TYPE_LINE);
26
- rrddim_add(st, "jitter", NULL, 1, 1, RRDDIM_ABSOLUTE);
27
- }
23
+ RRDSET *st = rrdset_find("system.idlejitter");
24
+ if(!st) {
25
+ st = rrdset_create("system", "idlejitter", NULL, "processes", NULL, "CPU Idle Jitter", "microseconds lost/s", 9999, rrd_update_every, RRDSET_TYPE_LINE);
26
+ rrddim_add(st, "jitter", NULL, 1, 1, RRDDIM_ABSOLUTE);
27
+ }
28
29
- struct timeval before, after;
30
- unsigned long long counter;
31
- for(counter = 0; 1 ;counter++) {
32
- unsigned long long usec = 0, susec = 0;
29
+ struct timeval before, after;
30
+ unsigned long long counter;
31
+ for(counter = 0; 1 ;counter++) {
32
+ unsigned long long usec = 0, susec = 0;
33
34
- while(susec < (rrd_update_every * 1000000ULL)) {
34
+ while(susec < (rrd_update_every * 1000000ULL)) {
35
36
- gettimeofday(&before, NULL);
37
- usleep(sleep_ms * 1000);
38
- gettimeofday(&after, NULL);
36
+ gettimeofday(&before, NULL);
37
+ usleep(sleep_ms * 1000);
38
+ gettimeofday(&after, NULL);
39
40
- // calculate the time it took for a full loop
41
- usec = usec_dt(&after, &before);
42
- susec += usec;
43
- }
44
- usec -= (sleep_ms * 1000);
40
+ // calculate the time it took for a full loop
41
+ usec = usec_dt(&after, &before);
42
+ susec += usec;
43
+ }
44
+ usec -= (sleep_ms * 1000);
45
46
- if(counter) rrdset_next(st);
47
- rrddim_set(st, "jitter", usec);
48
- rrdset_done(st);
49
- }
46
+ if(counter) rrdset_next(st);
47
+ rrddim_set(st, "jitter", usec);
48
+ rrdset_done(st);
49
+ }
50
51
- pthread_exit(NULL);
52
- return NULL;
51
+ pthread_exit(NULL);
52
+ return NULL;
53
}
54
src/plugin_nfacct.c
+145
-145
@@ -5,198 +5,198 @@
5
#include "common.h"
6
7
struct mynfacct {
8
- const char *name;
9
- uint64_t pkts;
10
- uint64_t bytes;
11
- struct nfacct *nfacct;
8
+ const char *name;
9
+ uint64_t pkts;
10
+ uint64_t bytes;
11
+ struct nfacct *nfacct;
12
};
13
14
struct nfacct_list {
15
- int size;
16
- int len;
17
- struct mynfacct data[];
15
+ int size;
16
+ int len;
17
+ struct mynfacct data[];
18
} *nfacct_list = NULL;
19
20
static int nfacct_callback(const struct nlmsghdr *nlh, void *data) {
21
- if(data) {};
22
-
23
- if(!nfacct_list || nfacct_list->len == nfacct_list->size) {
24
- int size = (nfacct_list) ? nfacct_list->size : 0;
25
- int len = (nfacct_list) ? nfacct_list->len : 0;
26
- size++;
27
-
28
- info("nfacct.plugin: increasing nfacct_list to size %d", size);
29
-
30
- nfacct_list = realloc(nfacct_list, sizeof(struct nfacct_list) + (sizeof(struct mynfacct) * size));
31
- if(!nfacct_list) {
32
- error("nfacct.plugin: cannot allocate nfacct_list.");
33
- return MNL_CB_OK;
34
- }
35
-
36
- nfacct_list->data[len].nfacct = nfacct_alloc();
37
- if(!nfacct_list->data[size - 1].nfacct) {
38
- error("nfacct.plugin: nfacct_alloc() failed.");
39
- free(nfacct_list);
40
- nfacct_list = NULL;
41
- return MNL_CB_OK;
42
- }
43
-
44
- nfacct_list->size = size;
45
- nfacct_list->len = len;
46
- }
47
-
48
- if(nfacct_nlmsg_parse_payload(nlh, nfacct_list->data[nfacct_list->len].nfacct) < 0) {
49
- error("nfacct.plugin: nfacct_nlmsg_parse_payload() failed.");
50
- return MNL_CB_OK;
51
- }
52
-
53
- nfacct_list->data[nfacct_list->len].name = nfacct_attr_get_str(nfacct_list->data[nfacct_list->len].nfacct, NFACCT_ATTR_NAME);
54
- nfacct_list->data[nfacct_list->len].pkts = nfacct_attr_get_u64(nfacct_list->data[nfacct_list->len].nfacct, NFACCT_ATTR_PKTS);
55
- nfacct_list->data[nfacct_list->len].bytes = nfacct_attr_get_u64(nfacct_list->data[nfacct_list->len].nfacct, NFACCT_ATTR_BYTES);
56
-
57
- nfacct_list->len++;
58
- return MNL_CB_OK;
21
+ if(data) {};
22
+
23
+ if(!nfacct_list || nfacct_list->len == nfacct_list->size) {
24
+ int size = (nfacct_list) ? nfacct_list->size : 0;
25
+ int len = (nfacct_list) ? nfacct_list->len : 0;
26
+ size++;
27
+
28
+ info("nfacct.plugin: increasing nfacct_list to size %d", size);
29
+
30
+ nfacct_list = realloc(nfacct_list, sizeof(struct nfacct_list) + (sizeof(struct mynfacct) * size));
31
+ if(!nfacct_list) {
32
+ error("nfacct.plugin: cannot allocate nfacct_list.");
33
+ return MNL_CB_OK;
34
+ }
35
+
36
+ nfacct_list->data[len].nfacct = nfacct_alloc();
37
+ if(!nfacct_list->data[size - 1].nfacct) {
38
+ error("nfacct.plugin: nfacct_alloc() failed.");
39
+ free(nfacct_list);
40
+ nfacct_list = NULL;
41
+ return MNL_CB_OK;
42
+ }
43
+
44
+ nfacct_list->size = size;
45
+ nfacct_list->len = len;
46
+ }
47
+
48
+ if(nfacct_nlmsg_parse_payload(nlh, nfacct_list->data[nfacct_list->len].nfacct) < 0) {
49
+ error("nfacct.plugin: nfacct_nlmsg_parse_payload() failed.");
50
+ return MNL_CB_OK;
51
+ }
52
+
53
+ nfacct_list->data[nfacct_list->len].name = nfacct_attr_get_str(nfacct_list->data[nfacct_list->len].nfacct, NFACCT_ATTR_NAME);
54
+ nfacct_list->data[nfacct_list->len].pkts = nfacct_attr_get_u64(nfacct_list->data[nfacct_list->len].nfacct, NFACCT_ATTR_PKTS);
55
+ nfacct_list->data[nfacct_list->len].bytes = nfacct_attr_get_u64(nfacct_list->data[nfacct_list->len].nfacct, NFACCT_ATTR_BYTES);
56
+
57
+ nfacct_list->len++;
58
+ return MNL_CB_OK;
59
}
60
61
void *nfacct_main(void *ptr) {
62
- if(ptr) { ; }
62
+ if(ptr) { ; }
63
64
- info("NFACCT thread created with task id %d", gettid());
64
+ info("NFACCT thread created with task id %d", gettid());
65
66
- if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
67
- error("nfacct.plugin: Cannot set pthread cancel type to DEFERRED.");
66
+ if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
67
+ error("nfacct.plugin: Cannot set pthread cancel type to DEFERRED.");
68
69
- if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
70
- error("nfacct.plugin: Cannot set pthread cancel state to ENABLE.");
69
+ if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
70
+ error("nfacct.plugin: Cannot set pthread cancel state to ENABLE.");
71
72
- char buf[MNL_SOCKET_BUFFER_SIZE];
73
- struct mnl_socket *nl = NULL;
74
- struct nlmsghdr *nlh = NULL;
75
- unsigned int seq = 0, portid = 0;
72
+ char buf[MNL_SOCKET_BUFFER_SIZE];
73
+ struct mnl_socket *nl = NULL;
74
+ struct nlmsghdr *nlh = NULL;
75
+ unsigned int seq = 0, portid = 0;
76
77
- seq = time(NULL) - 1;
77
+ seq = time(NULL) - 1;
78
79
- nl = mnl_socket_open(NETLINK_NETFILTER);
80
- if(!nl) {
81
- error("nfacct.plugin: mnl_socket_open() failed");
82
- pthread_exit(NULL);
83
- return NULL;
84
- }
79
+ nl = mnl_socket_open(NETLINK_NETFILTER);
80
+ if(!nl) {
81
+ error("nfacct.plugin: mnl_socket_open() failed");
82
+ pthread_exit(NULL);
83
+ return NULL;
84
+ }
85
86
- if(mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
87
- mnl_socket_close(nl);
88
- error("nfacct.plugin: mnl_socket_bind() failed");
89
- pthread_exit(NULL);
90
- return NULL;
91
- }
92
- portid = mnl_socket_get_portid(nl);
86
+ if(mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
87
+ mnl_socket_close(nl);
88
+ error("nfacct.plugin: mnl_socket_bind() failed");
89
+ pthread_exit(NULL);
90
+ return NULL;
91
+ }
92
+ portid = mnl_socket_get_portid(nl);
93
94
- // ------------------------------------------------------------------------
94
+ // ------------------------------------------------------------------------
95
96
- struct timeval last, now;
97
- unsigned long long usec = 0, susec = 0;
98
- RRDSET *st = NULL;
96
+ struct timeval last, now;
97
+ unsigned long long usec = 0, susec = 0;
98
+ RRDSET *st = NULL;
99
100
- gettimeofday(&last, NULL);
100
+ gettimeofday(&last, NULL);
101
102
- // ------------------------------------------------------------------------
102
+ // ------------------------------------------------------------------------
103
104
- while(1) {
105
- if(unlikely(netdata_exit)) break;
104
+ while(1) {
105
+ if(unlikely(netdata_exit)) break;
106
107
- seq++;
107
+ seq++;
108
109
- nlh = nfacct_nlmsg_build_hdr(buf, NFNL_MSG_ACCT_GET, NLM_F_DUMP, seq);
110
- if(!nlh) {
111
- mnl_socket_close(nl);
112
- error("nfacct.plugin: nfacct_nlmsg_build_hdr() failed");
113
- pthread_exit(NULL);
114
- return NULL;
115
- }
109
+ nlh = nfacct_nlmsg_build_hdr(buf, NFNL_MSG_ACCT_GET, NLM_F_DUMP, seq);
110
+ if(!nlh) {
111
+ mnl_socket_close(nl);
112
+ error("nfacct.plugin: nfacct_nlmsg_build_hdr() failed");
113
+ pthread_exit(NULL);
114
+ return NULL;
115
+ }
116
117
- if(mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
118
- error("nfacct.plugin: mnl_socket_send");
119
- pthread_exit(NULL);
120
- return NULL;
121
- }
117
+ if(mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
118
+ error("nfacct.plugin: mnl_socket_send");
119
+ pthread_exit(NULL);
120
+ return NULL;
121
+ }
122
123
- if(nfacct_list) nfacct_list->len = 0;
123
+ if(nfacct_list) nfacct_list->len = 0;
124
125
- int ret;
126
- while((ret = mnl_socket_recvfrom(nl, buf, sizeof(buf))) > 0) {
127
- if((ret = mnl_cb_run(buf, ret, seq, portid, nfacct_callback, NULL)) <= 0) break;
128
- }
125
+ int ret;
126
+ while((ret = mnl_socket_recvfrom(nl, buf, sizeof(buf))) > 0) {
127
+ if((ret = mnl_cb_run(buf, ret, seq, portid, nfacct_callback, NULL)) <= 0) break;
128
+ }
129
130
- if (ret == -1) {
131
- error("nfacct.plugin: error communicating with kernel.");
132
- pthread_exit(NULL);
133
- return NULL;
134
- }
130
+ if (ret == -1) {
131
+ error("nfacct.plugin: error communicating with kernel.");
132
+ pthread_exit(NULL);
133
+ return NULL;
134
+ }
135
136
- // --------------------------------------------------------------------
136
+ // --------------------------------------------------------------------
137
138
- gettimeofday(&now, NULL);
139
- usec = usecdiff(&now, &last) - susec;
140
- debug(D_NFACCT_LOOP, "nfacct.plugin: last loop took %llu usec (worked for %llu, sleeped for %llu).", usec + susec, usec, susec);
138
+ gettimeofday(&now, NULL);
139
+ usec = usecdiff(&now, &last) - susec;
140
+ debug(D_NFACCT_LOOP, "nfacct.plugin: last loop took %llu usec (worked for %llu, sleeped for %llu).", usec + susec, usec, susec);
141
142
- if(usec < (rrd_update_every * 1000000ULL / 2ULL)) susec = (rrd_update_every * 1000000ULL) - usec;
143
- else susec = rrd_update_every * 1000000ULL / 2ULL;
142
+ if(usec < (rrd_update_every * 1000000ULL / 2ULL)) susec = (rrd_update_every * 1000000ULL) - usec;
143
+ else susec = rrd_update_every * 1000000ULL / 2ULL;
144
145
146
- // --------------------------------------------------------------------
146
+ // --------------------------------------------------------------------
147
148
- if(nfacct_list && nfacct_list->len) {
149
- int i;
148
+ if(nfacct_list && nfacct_list->len) {
149
+ int i;
150
151
- st = rrdset_find_bytype("netfilter", "nfacct_packets");
152
- if(!st) {
153
- st = rrdset_create("netfilter", "nfacct_packets", NULL, "nfacct", NULL, "Netfilter Accounting Packets", "packets/s", 1006, rrd_update_every, RRDSET_TYPE_STACKED);
151
+ st = rrdset_find_bytype("netfilter", "nfacct_packets");
152
+ if(!st) {
153
+ st = rrdset_create("netfilter", "nfacct_packets", NULL, "nfacct", NULL, "Netfilter Accounting Packets", "packets/s", 1006, rrd_update_every, RRDSET_TYPE_STACKED);
154
155
- for(i = 0; i < nfacct_list->len ; i++)
156
- rrddim_add(st, nfacct_list->data[i].name, NULL, 1, rrd_update_every, RRDDIM_INCREMENTAL);
157
- }
158
- else rrdset_next(st);
155
+ for(i = 0; i < nfacct_list->len ; i++)
156
+ rrddim_add(st, nfacct_list->data[i].name, NULL, 1, rrd_update_every, RRDDIM_INCREMENTAL);
157
+ }
158
+ else rrdset_next(st);
159
160
- for(i = 0; i < nfacct_list->len ; i++) {
161
- RRDDIM *rd = rrddim_find(st, nfacct_list->data[i].name);
160
+ for(i = 0; i < nfacct_list->len ; i++) {
161
+ RRDDIM *rd = rrddim_find(st, nfacct_list->data[i].name);
162
163
- if(!rd) rd = rrddim_add(st, nfacct_list->data[i].name, NULL, 1, rrd_update_every, RRDDIM_INCREMENTAL);
164
- if(rd) rrddim_set_by_pointer(st, rd, nfacct_list->data[i].pkts);
165
- }
163
+ if(!rd) rd = rrddim_add(st, nfacct_list->data[i].name, NULL, 1, rrd_update_every, RRDDIM_INCREMENTAL);
164
+ if(rd) rrddim_set_by_pointer(st, rd, nfacct_list->data[i].pkts);
165
+ }
166
167
- rrdset_done(st);
167
+ rrdset_done(st);
168
169
- // ----------------------------------------------------------------
169
+ // ----------------------------------------------------------------
170
171
- st = rrdset_find_bytype("netfilter", "nfacct_bytes");
172
- if(!st) {
173
- st = rrdset_create("netfilter", "nfacct_bytes", NULL, "nfacct", NULL, "Netfilter Accounting Bandwidth", "kilobytes/s", 1007, rrd_update_every, RRDSET_TYPE_STACKED);
171
+ st = rrdset_find_bytype("netfilter", "nfacct_bytes");
172
+ if(!st) {
173
+ st = rrdset_create("netfilter", "nfacct_bytes", NULL, "nfacct", NULL, "Netfilter Accounting Bandwidth", "kilobytes/s", 1007, rrd_update_every, RRDSET_TYPE_STACKED);
174
175
- for(i = 0; i < nfacct_list->len ; i++)
176
- rrddim_add(st, nfacct_list->data[i].name, NULL, 1, 1000 * rrd_update_every, RRDDIM_INCREMENTAL);
177
- }
178
- else rrdset_next(st);
175
+ for(i = 0; i < nfacct_list->len ; i++)
176
+ rrddim_add(st, nfacct_list->data[i].name, NULL, 1, 1000 * rrd_update_every, RRDDIM_INCREMENTAL);
177
+ }
178
+ else rrdset_next(st);
179
180
- for(i = 0; i < nfacct_list->len ; i++) {
181
- RRDDIM *rd = rrddim_find(st, nfacct_list->data[i].name);
180
+ for(i = 0; i < nfacct_list->len ; i++) {
181
+ RRDDIM *rd = rrddim_find(st, nfacct_list->data[i].name);
182
183
- if(!rd) rd = rrddim_add(st, nfacct_list->data[i].name, NULL, 1, 1000 * rrd_update_every, RRDDIM_INCREMENTAL);
184
- if(rd) rrddim_set_by_pointer(st, rd, nfacct_list->data[i].bytes);
185
- }
183
+ if(!rd) rd = rrddim_add(st, nfacct_list->data[i].name, NULL, 1, 1000 * rrd_update_every, RRDDIM_INCREMENTAL);
184
+ if(rd) rrddim_set_by_pointer(st, rd, nfacct_list->data[i].bytes);
185
+ }
186
187
- rrdset_done(st);
188
- }
187
+ rrdset_done(st);
188
+ }
189
190
- // --------------------------------------------------------------------
190
+ // --------------------------------------------------------------------
191
192
- usleep(susec);
192
+ usleep(susec);
193
194
- // copy current to last
195
- bcopy(&now, &last, sizeof(struct timeval));
196
- }
194
+ // copy current to last
195
+ bcopy(&now, &last, sizeof(struct timeval));
196
+ }
197
198
- mnl_socket_close(nl);
199
- pthread_exit(NULL);
200
- return NULL;
198
+ mnl_socket_close(nl);
199
+ pthread_exit(NULL);
200
+ return NULL;
201
}
202
#endif
src/plugin_proc.c
+219
-219
@@ -2,225 +2,225 @@
2
3
void *proc_main(void *ptr)
4
{
5
- (void)ptr;
6
-
7
- info("PROC Plugin thread created with task id %d", gettid());
8
-
9
- if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
10
- error("Cannot set pthread cancel type to DEFERRED.");
11
-
12
- if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
13
- error("Cannot set pthread cancel state to ENABLE.");
14
-
15
- // disable (by default) various interface that are not needed
16
- config_get_boolean("plugin:proc:/proc/net/dev:lo", "enabled", 0);
17
- config_get_boolean("plugin:proc:/proc/net/dev:fireqos_monitor", "enabled", 0);
18
-
19
- // when ZERO, attempt to do it
20
- int vdo_proc_net_dev = !config_get_boolean("plugin:proc", "/proc/net/dev", 1);
21
- int vdo_proc_diskstats = !config_get_boolean("plugin:proc", "/proc/diskstats", 1);
22
- int vdo_proc_net_snmp = !config_get_boolean("plugin:proc", "/proc/net/snmp", 1);
23
- int vdo_proc_net_snmp6 = !config_get_boolean("plugin:proc", "/proc/net/snmp6", 1);
24
- int vdo_proc_net_netstat = !config_get_boolean("plugin:proc", "/proc/net/netstat", 1);
25
- int vdo_proc_net_stat_conntrack = !config_get_boolean("plugin:proc", "/proc/net/stat/conntrack", 1);
26
- int vdo_proc_net_ip_vs_stats = !config_get_boolean("plugin:proc", "/proc/net/ip_vs/stats", 1);
27
- int vdo_proc_net_stat_synproxy = !config_get_boolean("plugin:proc", "/proc/net/stat/synproxy", 1);
28
- int vdo_proc_stat = !config_get_boolean("plugin:proc", "/proc/stat", 1);
29
- int vdo_proc_meminfo = !config_get_boolean("plugin:proc", "/proc/meminfo", 1);
30
- int vdo_proc_vmstat = !config_get_boolean("plugin:proc", "/proc/vmstat", 1);
31
- int vdo_proc_net_rpc_nfsd = !config_get_boolean("plugin:proc", "/proc/net/rpc/nfsd", 1);
32
- int vdo_proc_sys_kernel_random_entropy_avail = !config_get_boolean("plugin:proc", "/proc/sys/kernel/random/entropy_avail", 1);
33
- int vdo_proc_interrupts = !config_get_boolean("plugin:proc", "/proc/interrupts", 1);
34
- int vdo_proc_softirqs = !config_get_boolean("plugin:proc", "/proc/softirqs", 1);
35
- int vdo_proc_loadavg = !config_get_boolean("plugin:proc", "/proc/loadavg", 1);
36
- int vdo_sys_kernel_mm_ksm = !config_get_boolean("plugin:proc", "/sys/kernel/mm/ksm", 1);
37
- int vdo_cpu_netdata = !config_get_boolean("plugin:proc", "netdata server resources", 1);
38
-
39
- // keep track of the time each module was called
40
- unsigned long long sutime_proc_net_dev = 0ULL;
41
- unsigned long long sutime_proc_diskstats = 0ULL;
42
- unsigned long long sutime_proc_net_snmp = 0ULL;
43
- unsigned long long sutime_proc_net_snmp6 = 0ULL;
44
- unsigned long long sutime_proc_net_netstat = 0ULL;
45
- unsigned long long sutime_proc_net_stat_conntrack = 0ULL;
46
- unsigned long long sutime_proc_net_ip_vs_stats = 0ULL;
47
- unsigned long long sutime_proc_net_stat_synproxy = 0ULL;
48
- unsigned long long sutime_proc_stat = 0ULL;
49
- unsigned long long sutime_proc_meminfo = 0ULL;
50
- unsigned long long sutime_proc_vmstat = 0ULL;
51
- unsigned long long sutime_proc_net_rpc_nfsd = 0ULL;
52
- unsigned long long sutime_proc_sys_kernel_random_entropy_avail = 0ULL;
53
- unsigned long long sutime_proc_interrupts = 0ULL;
54
- unsigned long long sutime_proc_softirqs = 0ULL;
55
- unsigned long long sutime_proc_loadavg = 0ULL;
56
- unsigned long long sutime_sys_kernel_mm_ksm = 0ULL;
57
-
58
- // the next time we will run - aligned properly
59
- unsigned long long sunext = (time(NULL) - (time(NULL) % rrd_update_every) + rrd_update_every) * 1000000ULL;
60
- unsigned long long sunow;
61
-
62
- for(;1;) {
63
- if(unlikely(netdata_exit)) break;
64
-
65
- // delay until it is our time to run
66
- while((sunow = time_usec()) < sunext)
67
- sleep_usec(sunext - sunow);
68
-
69
- // find the next time we need to run
70
- while(time_usec() > sunext)
71
- sunext += rrd_update_every * 1000000ULL;
72
-
73
- if(unlikely(netdata_exit)) break;
74
-
75
- // BEGIN -- the job to be done
76
-
77
- if(!vdo_sys_kernel_mm_ksm) {
78
- debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_sys_kernel_mm_ksm().");
79
-
80
- sunow = time_usec();
81
- vdo_sys_kernel_mm_ksm = do_sys_kernel_mm_ksm(rrd_update_every, (sutime_sys_kernel_mm_ksm > 0)?sunow - sutime_sys_kernel_mm_ksm:0ULL);
82
- sutime_sys_kernel_mm_ksm = sunow;
83
- }
84
- if(unlikely(netdata_exit)) break;
85
-
86
- if(!vdo_proc_loadavg) {
87
- debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_loadavg().");
88
- sunow = time_usec();
89
- vdo_proc_loadavg = do_proc_loadavg(rrd_update_every, (sutime_proc_loadavg > 0)?sunow - sutime_proc_loadavg:0ULL);
90
- sutime_proc_loadavg = sunow;
91
- }
92
- if(unlikely(netdata_exit)) break;
93
-
94
- if(!vdo_proc_interrupts) {
95
- debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_interrupts().");
96
- sunow = time_usec();
97
- vdo_proc_interrupts = do_proc_interrupts(rrd_update_every, (sutime_proc_interrupts > 0)?sunow - sutime_proc_interrupts:0ULL);
98
- sutime_proc_interrupts = sunow;
99
- }
100
- if(unlikely(netdata_exit)) break;
101
-
102
- if(!vdo_proc_softirqs) {
103
- debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_softirqs().");
104
- sunow = time_usec();
105
- vdo_proc_softirqs = do_proc_softirqs(rrd_update_every, (sutime_proc_softirqs > 0)?sunow - sutime_proc_softirqs:0ULL);
106
- sutime_proc_softirqs = sunow;
107
- }
108
- if(unlikely(netdata_exit)) break;
109
-
110
- if(!vdo_proc_sys_kernel_random_entropy_avail) {
111
- debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_sys_kernel_random_entropy_avail().");
112
- sunow = time_usec();
113
- vdo_proc_sys_kernel_random_entropy_avail = do_proc_sys_kernel_random_entropy_avail(rrd_update_every, (sutime_proc_sys_kernel_random_entropy_avail > 0)?sunow - sutime_proc_sys_kernel_random_entropy_avail:0ULL);
114
- sutime_proc_sys_kernel_random_entropy_avail = sunow;
115
- }
116
- if(unlikely(netdata_exit)) break;
117
-
118
- if(!vdo_proc_net_dev) {
119
- debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_dev().");
120
- sunow = time_usec();
121
- vdo_proc_net_dev = do_proc_net_dev(rrd_update_every, (sutime_proc_net_dev > 0)?sunow - sutime_proc_net_dev:0ULL);
122
- sutime_proc_net_dev = sunow;
123
- }
124
- if(unlikely(netdata_exit)) break;
125
-
126
- if(!vdo_proc_diskstats) {
127
- debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_diskstats().");
128
- sunow = time_usec();
129
- vdo_proc_diskstats = do_proc_diskstats(rrd_update_every, (sutime_proc_diskstats > 0)?sunow - sutime_proc_diskstats:0ULL);
130
- sutime_proc_diskstats = sunow;
131
- }
132
- if(unlikely(netdata_exit)) break;
133
-
134
- if(!vdo_proc_net_snmp) {
135
- debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_snmp().");
136
- sunow = time_usec();
137
- vdo_proc_net_snmp = do_proc_net_snmp(rrd_update_every, (sutime_proc_net_snmp > 0)?sunow - sutime_proc_net_snmp:0ULL);
138
- sutime_proc_net_snmp = sunow;
139
- }
140
- if(unlikely(netdata_exit)) break;
141
-
142
- if(!vdo_proc_net_snmp6) {
143
- debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_snmp6().");
144
- sunow = time_usec();
145
- vdo_proc_net_snmp6 = do_proc_net_snmp6(rrd_update_every, (sutime_proc_net_snmp6 > 0)?sunow - sutime_proc_net_snmp6:0ULL);
146
- sutime_proc_net_snmp6 = sunow;
147
- }
148
- if(unlikely(netdata_exit)) break;
149
-
150
- if(!vdo_proc_net_netstat) {
151
- debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_netstat().");
152
- sunow = time_usec();
153
- vdo_proc_net_netstat = do_proc_net_netstat(rrd_update_every, (sutime_proc_net_netstat > 0)?sunow - sutime_proc_net_netstat:0ULL);
154
- sutime_proc_net_netstat = sunow;
155
- }
156
- if(unlikely(netdata_exit)) break;
157
-
158
- if(!vdo_proc_net_stat_conntrack) {
159
- debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_stat_conntrack().");
160
- sunow = time_usec();
161
- vdo_proc_net_stat_conntrack = do_proc_net_stat_conntrack(rrd_update_every, (sutime_proc_net_stat_conntrack > 0)?sunow - sutime_proc_net_stat_conntrack:0ULL);
162
- sutime_proc_net_stat_conntrack = sunow;
163
- }
164
- if(unlikely(netdata_exit)) break;
165
-
166
- if(!vdo_proc_net_ip_vs_stats) {
167
- debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_net_ip_vs_stats().");
168
- sunow = time_usec();
169
- vdo_proc_net_ip_vs_stats = do_proc_net_ip_vs_stats(rrd_update_every, (sutime_proc_net_ip_vs_stats > 0)?sunow - sutime_proc_net_ip_vs_stats:0ULL);
170
- sutime_proc_net_ip_vs_stats = sunow;
171
- }
172
- if(unlikely(netdata_exit)) break;
173
-
174
- if(!vdo_proc_net_stat_synproxy) {
175
- debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_net_stat_synproxy().");
176
- sunow = time_usec();
177
- vdo_proc_net_stat_synproxy = do_proc_net_stat_synproxy(rrd_update_every, (sutime_proc_net_stat_synproxy > 0)?sunow - sutime_proc_net_stat_synproxy:0ULL);
178
- sutime_proc_net_stat_synproxy = sunow;
179
- }
180
- if(unlikely(netdata_exit)) break;
181
-
182
- if(!vdo_proc_stat) {
183
- debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_stat().");
184
- sunow = time_usec();
185
- vdo_proc_stat = do_proc_stat(rrd_update_every, (sutime_proc_stat > 0)?sunow - sutime_proc_stat:0ULL);
186
- sutime_proc_stat = sunow;
187
- }
188
- if(unlikely(netdata_exit)) break;
189
-
190
- if(!vdo_proc_meminfo) {
191
- debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_meminfo().");
192
- sunow = time_usec();
193
- vdo_proc_meminfo = do_proc_meminfo(rrd_update_every, (sutime_proc_meminfo > 0)?sunow - sutime_proc_meminfo:0ULL);
194
- sutime_proc_meminfo = sunow;
195
- }
196
- if(unlikely(netdata_exit)) break;
197
-
198
- if(!vdo_proc_vmstat) {
199
- debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_vmstat().");
200
- sunow = time_usec();
201
- vdo_proc_vmstat = do_proc_vmstat(rrd_update_every, (sutime_proc_vmstat > 0)?sunow - sutime_proc_vmstat:0ULL);
202
- sutime_proc_vmstat = sunow;
203
- }
204
- if(unlikely(netdata_exit)) break;
205
-
206
- if(!vdo_proc_net_rpc_nfsd) {
207
- debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_rpc_nfsd().");
208
- sunow = time_usec();
209
- vdo_proc_net_rpc_nfsd = do_proc_net_rpc_nfsd(rrd_update_every, (sutime_proc_net_rpc_nfsd > 0)?sunow - sutime_proc_net_rpc_nfsd:0ULL);
210
- sutime_proc_net_rpc_nfsd = sunow;
211
- }
212
- if(unlikely(netdata_exit)) break;
213
-
214
- // END -- the job is done
215
-
216
- // --------------------------------------------------------------------
217
-
218
- if(!vdo_cpu_netdata) {
5
+ (void)ptr;
6
+
7
+ info("PROC Plugin thread created with task id %d", gettid());
8
+
9
+ if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
10
+ error("Cannot set pthread cancel type to DEFERRED.");
11
+
12
+ if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
13
+ error("Cannot set pthread cancel state to ENABLE.");
14
+
15
+ // disable (by default) various interface that are not needed
16
+ config_get_boolean("plugin:proc:/proc/net/dev:lo", "enabled", 0);
17
+ config_get_boolean("plugin:proc:/proc/net/dev:fireqos_monitor", "enabled", 0);
18
+
19
+ // when ZERO, attempt to do it
20
+ int vdo_proc_net_dev = !config_get_boolean("plugin:proc", "/proc/net/dev", 1);
21
+ int vdo_proc_diskstats = !config_get_boolean("plugin:proc", "/proc/diskstats", 1);
22
+ int vdo_proc_net_snmp = !config_get_boolean("plugin:proc", "/proc/net/snmp", 1);
23
+ int vdo_proc_net_snmp6 = !config_get_boolean("plugin:proc", "/proc/net/snmp6", 1);
24
+ int vdo_proc_net_netstat = !config_get_boolean("plugin:proc", "/proc/net/netstat", 1);
25
+ int vdo_proc_net_stat_conntrack = !config_get_boolean("plugin:proc", "/proc/net/stat/conntrack", 1);
26
+ int vdo_proc_net_ip_vs_stats = !config_get_boolean("plugin:proc", "/proc/net/ip_vs/stats", 1);
27
+ int vdo_proc_net_stat_synproxy = !config_get_boolean("plugin:proc", "/proc/net/stat/synproxy", 1);
28
+ int vdo_proc_stat = !config_get_boolean("plugin:proc", "/proc/stat", 1);
29
+ int vdo_proc_meminfo = !config_get_boolean("plugin:proc", "/proc/meminfo", 1);
30
+ int vdo_proc_vmstat = !config_get_boolean("plugin:proc", "/proc/vmstat", 1);
31
+ int vdo_proc_net_rpc_nfsd = !config_get_boolean("plugin:proc", "/proc/net/rpc/nfsd", 1);
32
+ int vdo_proc_sys_kernel_random_entropy_avail = !config_get_boolean("plugin:proc", "/proc/sys/kernel/random/entropy_avail", 1);
33
+ int vdo_proc_interrupts = !config_get_boolean("plugin:proc", "/proc/interrupts", 1);
34
+ int vdo_proc_softirqs = !config_get_boolean("plugin:proc", "/proc/softirqs", 1);
35
+ int vdo_proc_loadavg = !config_get_boolean("plugin:proc", "/proc/loadavg", 1);
36
+ int vdo_sys_kernel_mm_ksm = !config_get_boolean("plugin:proc", "/sys/kernel/mm/ksm", 1);
37
+ int vdo_cpu_netdata = !config_get_boolean("plugin:proc", "netdata server resources", 1);
38
+
39
+ // keep track of the time each module was called
40
+ unsigned long long sutime_proc_net_dev = 0ULL;
41
+ unsigned long long sutime_proc_diskstats = 0ULL;
42
+ unsigned long long sutime_proc_net_snmp = 0ULL;
43
+ unsigned long long sutime_proc_net_snmp6 = 0ULL;
44
+ unsigned long long sutime_proc_net_netstat = 0ULL;
45
+ unsigned long long sutime_proc_net_stat_conntrack = 0ULL;
46
+ unsigned long long sutime_proc_net_ip_vs_stats = 0ULL;
47
+ unsigned long long sutime_proc_net_stat_synproxy = 0ULL;
48
+ unsigned long long sutime_proc_stat = 0ULL;
49
+ unsigned long long sutime_proc_meminfo = 0ULL;
50
+ unsigned long long sutime_proc_vmstat = 0ULL;
51
+ unsigned long long sutime_proc_net_rpc_nfsd = 0ULL;
52
+ unsigned long long sutime_proc_sys_kernel_random_entropy_avail = 0ULL;
53
+ unsigned long long sutime_proc_interrupts = 0ULL;
54
+ unsigned long long sutime_proc_softirqs = 0ULL;
55
+ unsigned long long sutime_proc_loadavg = 0ULL;
56
+ unsigned long long sutime_sys_kernel_mm_ksm = 0ULL;
57
+
58
+ // the next time we will run - aligned properly
59
+ unsigned long long sunext = (time(NULL) - (time(NULL) % rrd_update_every) + rrd_update_every) * 1000000ULL;
60
+ unsigned long long sunow;
61
+
62
+ for(;1;) {
63
+ if(unlikely(netdata_exit)) break;
64
+
65
+ // delay until it is our time to run
66
+ while((sunow = time_usec()) < sunext)
67
+ sleep_usec(sunext - sunow);
68
+
69
+ // find the next time we need to run
70
+ while(time_usec() > sunext)
71
+ sunext += rrd_update_every * 1000000ULL;
72
+
73
+ if(unlikely(netdata_exit)) break;
74
+
75
+ // BEGIN -- the job to be done
76
+
77
+ if(!vdo_sys_kernel_mm_ksm) {
78
+ debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_sys_kernel_mm_ksm().");
79
+
80
+ sunow = time_usec();
81
+ vdo_sys_kernel_mm_ksm = do_sys_kernel_mm_ksm(rrd_update_every, (sutime_sys_kernel_mm_ksm > 0)?sunow - sutime_sys_kernel_mm_ksm:0ULL);
82
+ sutime_sys_kernel_mm_ksm = sunow;
83
+ }
84
+ if(unlikely(netdata_exit)) break;
85
+
86
+ if(!vdo_proc_loadavg) {
87
+ debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_loadavg().");
88
+ sunow = time_usec();
89
+ vdo_proc_loadavg = do_proc_loadavg(rrd_update_every, (sutime_proc_loadavg > 0)?sunow - sutime_proc_loadavg:0ULL);
90
+ sutime_proc_loadavg = sunow;
91
+ }
92
+ if(unlikely(netdata_exit)) break;
93
+
94
+ if(!vdo_proc_interrupts) {
95
+ debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_interrupts().");
96
+ sunow = time_usec();
97
+ vdo_proc_interrupts = do_proc_interrupts(rrd_update_every, (sutime_proc_interrupts > 0)?sunow - sutime_proc_interrupts:0ULL);
98
+ sutime_proc_interrupts = sunow;
99
+ }
100
+ if(unlikely(netdata_exit)) break;
101
+
102
+ if(!vdo_proc_softirqs) {
103
+ debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_softirqs().");
104
+ sunow = time_usec();
105
+ vdo_proc_softirqs = do_proc_softirqs(rrd_update_every, (sutime_proc_softirqs > 0)?sunow - sutime_proc_softirqs:0ULL);
106
+ sutime_proc_softirqs = sunow;
107
+ }
108
+ if(unlikely(netdata_exit)) break;
109
+
110
+ if(!vdo_proc_sys_kernel_random_entropy_avail) {
111
+ debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_sys_kernel_random_entropy_avail().");
112
+ sunow = time_usec();
113
+ vdo_proc_sys_kernel_random_entropy_avail = do_proc_sys_kernel_random_entropy_avail(rrd_update_every, (sutime_proc_sys_kernel_random_entropy_avail > 0)?sunow - sutime_proc_sys_kernel_random_entropy_avail:0ULL);
114
+ sutime_proc_sys_kernel_random_entropy_avail = sunow;
115
+ }
116
+ if(unlikely(netdata_exit)) break;
117
+
118
+ if(!vdo_proc_net_dev) {
119
+ debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_dev().");
120
+ sunow = time_usec();
121
+ vdo_proc_net_dev = do_proc_net_dev(rrd_update_every, (sutime_proc_net_dev > 0)?sunow - sutime_proc_net_dev:0ULL);
122
+ sutime_proc_net_dev = sunow;
123
+ }
124
+ if(unlikely(netdata_exit)) break;
125
+
126
+ if(!vdo_proc_diskstats) {
127
+ debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_diskstats().");
128
+ sunow = time_usec();
129
+ vdo_proc_diskstats = do_proc_diskstats(rrd_update_every, (sutime_proc_diskstats > 0)?sunow - sutime_proc_diskstats:0ULL);
130
+ sutime_proc_diskstats = sunow;
131
+ }
132
+ if(unlikely(netdata_exit)) break;
133
+
134
+ if(!vdo_proc_net_snmp) {
135
+ debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_snmp().");
136
+ sunow = time_usec();
137
+ vdo_proc_net_snmp = do_proc_net_snmp(rrd_update_every, (sutime_proc_net_snmp > 0)?sunow - sutime_proc_net_snmp:0ULL);
138
+ sutime_proc_net_snmp = sunow;
139
+ }
140
+ if(unlikely(netdata_exit)) break;
141
+
142
+ if(!vdo_proc_net_snmp6) {
143
+ debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_snmp6().");
144
+ sunow = time_usec();
145
+ vdo_proc_net_snmp6 = do_proc_net_snmp6(rrd_update_every, (sutime_proc_net_snmp6 > 0)?sunow - sutime_proc_net_snmp6:0ULL);
146
+ sutime_proc_net_snmp6 = sunow;
147
+ }
148
+ if(unlikely(netdata_exit)) break;
149
+
150
+ if(!vdo_proc_net_netstat) {
151
+ debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_netstat().");
152
+ sunow = time_usec();
153
+ vdo_proc_net_netstat = do_proc_net_netstat(rrd_update_every, (sutime_proc_net_netstat > 0)?sunow - sutime_proc_net_netstat:0ULL);
154
+ sutime_proc_net_netstat = sunow;
155
+ }
156
+ if(unlikely(netdata_exit)) break;
157
+
158
+ if(!vdo_proc_net_stat_conntrack) {
159
+ debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_stat_conntrack().");
160
+ sunow = time_usec();
161
+ vdo_proc_net_stat_conntrack = do_proc_net_stat_conntrack(rrd_update_every, (sutime_proc_net_stat_conntrack > 0)?sunow - sutime_proc_net_stat_conntrack:0ULL);
162
+ sutime_proc_net_stat_conntrack = sunow;
163
+ }
164
+ if(unlikely(netdata_exit)) break;
165
+
166
+ if(!vdo_proc_net_ip_vs_stats) {
167
+ debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_net_ip_vs_stats().");
168
+ sunow = time_usec();
169
+ vdo_proc_net_ip_vs_stats = do_proc_net_ip_vs_stats(rrd_update_every, (sutime_proc_net_ip_vs_stats > 0)?sunow - sutime_proc_net_ip_vs_stats:0ULL);
170
+ sutime_proc_net_ip_vs_stats = sunow;
171
+ }
172
+ if(unlikely(netdata_exit)) break;
173
+
174
+ if(!vdo_proc_net_stat_synproxy) {
175
+ debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_net_stat_synproxy().");
176
+ sunow = time_usec();
177
+ vdo_proc_net_stat_synproxy = do_proc_net_stat_synproxy(rrd_update_every, (sutime_proc_net_stat_synproxy > 0)?sunow - sutime_proc_net_stat_synproxy:0ULL);
178
+ sutime_proc_net_stat_synproxy = sunow;
179
+ }
180
+ if(unlikely(netdata_exit)) break;
181
+
182
+ if(!vdo_proc_stat) {
183
+ debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_stat().");
184
+ sunow = time_usec();
185
+ vdo_proc_stat = do_proc_stat(rrd_update_every, (sutime_proc_stat > 0)?sunow - sutime_proc_stat:0ULL);
186
+ sutime_proc_stat = sunow;
187
+ }
188
+ if(unlikely(netdata_exit)) break;
189
+
190
+ if(!vdo_proc_meminfo) {
191
+ debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_meminfo().");
192
+ sunow = time_usec();
193
+ vdo_proc_meminfo = do_proc_meminfo(rrd_update_every, (sutime_proc_meminfo > 0)?sunow - sutime_proc_meminfo:0ULL);
194
+ sutime_proc_meminfo = sunow;
195
+ }
196
+ if(unlikely(netdata_exit)) break;
197
+
198
+ if(!vdo_proc_vmstat) {
199
+ debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_vmstat().");
200
+ sunow = time_usec();
201
+ vdo_proc_vmstat = do_proc_vmstat(rrd_update_every, (sutime_proc_vmstat > 0)?sunow - sutime_proc_vmstat:0ULL);
202
+ sutime_proc_vmstat = sunow;
203
+ }
204
+ if(unlikely(netdata_exit)) break;
205
+
206
+ if(!vdo_proc_net_rpc_nfsd) {
207
+ debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_rpc_nfsd().");
208
+ sunow = time_usec();
209
+ vdo_proc_net_rpc_nfsd = do_proc_net_rpc_nfsd(rrd_update_every, (sutime_proc_net_rpc_nfsd > 0)?sunow - sutime_proc_net_rpc_nfsd:0ULL);
210
+ sutime_proc_net_rpc_nfsd = sunow;
211
+ }
212
+ if(unlikely(netdata_exit)) break;
213
+
214
+ // END -- the job is done
215
+
216
+ // --------------------------------------------------------------------
217
+
218
+ if(!vdo_cpu_netdata) {
219
global_statistics_charts();
220
- registry_statistics();
221
- }
222
- }
220
+ registry_statistics();
221
+ }
222
+ }
223
224
- pthread_exit(NULL);
225
- return NULL;
224
+ pthread_exit(NULL);
225
+ return NULL;
226
}
src/plugin_tc.c
+731
-731
@@ -1,7 +1,7 @@
1
#include "common.h"
2
3
-#define RRD_TYPE_TC "tc"
4
-#define RRD_TYPE_TC_LEN strlen(RRD_TYPE_TC)
3
+#define RRD_TYPE_TC "tc"
4
+#define RRD_TYPE_TC_LEN strlen(RRD_TYPE_TC)
5
6
// ----------------------------------------------------------------------------
7
// /sbin/tc processor
@@ -10,71 +10,71 @@
10
#define TC_LINE_MAX 1024
11
12
struct tc_class {
13
- avl avl;
14
-
15
- char *id;
16
- uint32_t hash;
17
-
18
- char *name;
19
-
20
- char *leafid;
21
- uint32_t leaf_hash;
22
-
23
- char *parentid;
24
- uint32_t parent_hash;
25
-
26
- char hasparent;
27
- char isleaf;
28
- unsigned long long bytes;
29
- unsigned long long packets;
30
- unsigned long long dropped;
31
- unsigned long long overlimits;
32
- unsigned long long requeues;
33
- unsigned long long lended;
34
- unsigned long long borrowed;
35
- unsigned long long giants;
36
- unsigned long long tokens;
37
- unsigned long long ctokens;
38
-
39
- RRDDIM *rd_bytes;
40
- RRDDIM *rd_packets;
41
- RRDDIM *rd_dropped;
42
-
43
- char name_updated;
44
- char updated; // updated bytes
45
- int seen; // seen in the tc list (even without bytes)
46
-
47
- struct tc_class *next;
48
- struct tc_class *prev;
13
+ avl avl;
14
+
15
+ char *id;
16
+ uint32_t hash;
17
+
18
+ char *name;
19
+
20
+ char *leafid;
21
+ uint32_t leaf_hash;
22
+
23
+ char *parentid;
24
+ uint32_t parent_hash;
25
+
26
+ char hasparent;
27
+ char isleaf;
28
+ unsigned long long bytes;
29
+ unsigned long long packets;
30
+ unsigned long long dropped;
31
+ unsigned long long overlimits;
32
+ unsigned long long requeues;
33
+ unsigned long long lended;
34
+ unsigned long long borrowed;
35
+ unsigned long long giants;
36
+ unsigned long long tokens;
37
+ unsigned long long ctokens;
38
+
39
+ RRDDIM *rd_bytes;
40
+ RRDDIM *rd_packets;
41
+ RRDDIM *rd_dropped;
42
+
43
+ char name_updated;
44
+ char updated; // updated bytes
45
+ int seen; // seen in the tc list (even without bytes)
46
+
47
+ struct tc_class *next;
48
+ struct tc_class *prev;
49
};
50
51
struct tc_device {
52
- avl avl;
52
+ avl avl;
53
54
- char *id;
55
- uint32_t hash;
54
+ char *id;
55
+ uint32_t hash;
56
57
- char *name;
58
- char *family;
57
+ char *name;
58
+ char *family;
59
60
- char name_updated;
61
- char family_updated;
60
+ char name_updated;
61
+ char family_updated;
62
63
- char enabled;
64
- char enabled_bytes;
65
- char enabled_packets;
66
- char enabled_dropped;
63
+ char enabled;
64
+ char enabled_bytes;
65
+ char enabled_packets;
66
+ char enabled_dropped;
67
68
- RRDSET *st_bytes;
69
- RRDSET *st_packets;
70
- RRDSET *st_dropped;
68
+ RRDSET *st_bytes;
69
+ RRDSET *st_packets;
70
+ RRDSET *st_dropped;
71
72
- avl_tree classes_index;
72
+ avl_tree classes_index;
73
74
- struct tc_class *classes;
74
+ struct tc_class *classes;
75
76
- struct tc_device *next;
77
- struct tc_device *prev;
76
+ struct tc_device *next;
77
+ struct tc_device *prev;
78
};
79
80
@@ -84,25 +84,25 @@ struct tc_device *tc_device_root = NULL;
84
// tc_device index
85
86
static int tc_device_compare(void* a, void* b) {
87
- if(((struct tc_device *)a)->hash < ((struct tc_device *)b)->hash) return -1;
88
- else if(((struct tc_device *)a)->hash > ((struct tc_device *)b)->hash) return 1;
89
- else return strcmp(((struct tc_device *)a)->id, ((struct tc_device *)b)->id);
87
+ if(((struct tc_device *)a)->hash < ((struct tc_device *)b)->hash) return -1;
88
+ else if(((struct tc_device *)a)->hash > ((struct tc_device *)b)->hash) return 1;
89
+ else return strcmp(((struct tc_device *)a)->id, ((struct tc_device *)b)->id);
90
}
91
92
avl_tree tc_device_root_index = {
93
- NULL,
94
- tc_device_compare
93
+ NULL,
94
+ tc_device_compare
95
};
96
97
#define tc_device_index_add(st) avl_insert(&tc_device_root_index, (avl *)(st))
98
#define tc_device_index_del(st) avl_remove(&tc_device_root_index, (avl *)(st))
99
100
static inline struct tc_device *tc_device_index_find(const char *id, uint32_t hash) {
101
- struct tc_device tmp;
102
- tmp.id = (char *)id;
103
- tmp.hash = (hash)?hash:simple_hash(tmp.id);
101
+ struct tc_device tmp;
102
+ tmp.id = (char *)id;
103
+ tmp.hash = (hash)?hash:simple_hash(tmp.id);
104
105
- return (struct tc_device *)avl_search(&(tc_device_root_index), (avl *)&tmp);
105
+ return (struct tc_device *)avl_search(&(tc_device_root_index), (avl *)&tmp);
106
}
107
108
@@ -110,764 +110,764 @@ static inline struct tc_device *tc_device_index_find(const char *id, uint32_t ha
110
// tc_class index
111
112
static int tc_class_compare(void* a, void* b) {
113
- if(((struct tc_class *)a)->hash < ((struct tc_class *)b)->hash) return -1;
114
- else if(((struct tc_class *)a)->hash > ((struct tc_class *)b)->hash) return 1;
115
- else return strcmp(((struct tc_class *)a)->id, ((struct tc_class *)b)->id);
113
+ if(((struct tc_class *)a)->hash < ((struct tc_class *)b)->hash) return -1;
114
+ else if(((struct tc_class *)a)->hash > ((struct tc_class *)b)->hash) return 1;
115
+ else return strcmp(((struct tc_class *)a)->id, ((struct tc_class *)b)->id);
116
}
117
118
#define tc_class_index_add(st, rd) avl_insert(&((st)->classes_index), (avl *)(rd))
119
#define tc_class_index_del(st, rd) avl_remove(&((st)->classes_index), (avl *)(rd))
120
121
static inline struct tc_class *tc_class_index_find(struct tc_device *st, const char *id, uint32_t hash) {
122
- struct tc_class tmp;
123
- tmp.id = (char *)id;
124
- tmp.hash = (hash)?hash:simple_hash(tmp.id);
122
+ struct tc_class tmp;
123
+ tmp.id = (char *)id;
124
+ tmp.hash = (hash)?hash:simple_hash(tmp.id);
125
126
- return (struct tc_class *)avl_search(&(st->classes_index), (avl *) &tmp);
126
+ return (struct tc_class *)avl_search(&(st->classes_index), (avl *) &tmp);
127
}
128
129
// ----------------------------------------------------------------------------
130
131
static inline void tc_class_free(struct tc_device *n, struct tc_class *c) {
132
- debug(D_TC_LOOP, "Removing from device '%s' class '%s', parentid '%s', leafid '%s', seen=%d", n->id, c->id, c->parentid?c->parentid:"", c->leafid?c->leafid:"", c->seen);
133
-
134
- if(c->next) c->next->prev = c->prev;
135
- if(c->prev) c->prev->next = c->next;
136
- if(n->classes == c) {
137
- if(c->next) n->classes = c->next;
138
- else n->classes = c->prev;
139
- }
140
-
141
- tc_class_index_del(n, c);
142
-
143
- freez(c->id);
144
- freez(c->name);
145
- freez(c->leafid);
146
- freez(c->parentid);
147
- freez(c);
132
+ debug(D_TC_LOOP, "Removing from device '%s' class '%s', parentid '%s', leafid '%s', seen=%d", n->id, c->id, c->parentid?c->parentid:"", c->leafid?c->leafid:"", c->seen);
133
+
134
+ if(c->next) c->next->prev = c->prev;
135
+ if(c->prev) c->prev->next = c->next;
136
+ if(n->classes == c) {
137
+ if(c->next) n->classes = c->next;
138
+ else n->classes = c->prev;
139
+ }
140
+
141
+ tc_class_index_del(n, c);
142
+
143
+ freez(c->id);
144
+ freez(c->name);
145
+ freez(c->leafid);
146
+ freez(c->parentid);
147
+ freez(c);
148
}
149
150
static inline void tc_device_classes_cleanup(struct tc_device *d) {
151
- static int cleanup_every = 999;
152
-
153
- if(unlikely(cleanup_every > 0)) {
154
- cleanup_every = (int) config_get_number("plugin:tc", "cleanup unused classes every", 60);
155
- if(cleanup_every < 0) cleanup_every = -cleanup_every;
156
- }
157
-
158
- d->name_updated = 0;
159
- d->family_updated = 0;
160
-
161
- struct tc_class *c = d->classes;
162
- while(c) {
163
- if(unlikely(cleanup_every > 0 && c->seen >= cleanup_every)) {
164
- struct tc_class *nc = c->next;
165
- tc_class_free(d, c);
166
- c = nc;
167
- }
168
- else {
169
- c->updated = 0;
170
- c->name_updated = 0;
171
-
172
- c = c->next;
173
- }
174
- }
151
+ static int cleanup_every = 999;
152
+
153
+ if(unlikely(cleanup_every > 0)) {
154
+ cleanup_every = (int) config_get_number("plugin:tc", "cleanup unused classes every", 60);
155
+ if(cleanup_every < 0) cleanup_every = -cleanup_every;
156
+ }
157
+
158
+ d->name_updated = 0;
159
+ d->family_updated = 0;
160
+
161
+ struct tc_class *c = d->classes;
162
+ while(c) {
163
+ if(unlikely(cleanup_every > 0 && c->seen >= cleanup_every)) {
164
+ struct tc_class *nc = c->next;
165
+ tc_class_free(d, c);
166
+ c = nc;
167
+ }
168
+ else {
169
+ c->updated = 0;
170
+ c->name_updated = 0;
171
+
172
+ c = c->next;
173
+ }
174
+ }
175
}
176
177
static inline void tc_device_commit(struct tc_device *d) {
178
- static int enable_new_interfaces = -1, enable_bytes = -1, enable_packets = -1, enable_dropped = -1;
179
-
180
- if(unlikely(enable_new_interfaces == -1)) {
181
- enable_new_interfaces = config_get_boolean_ondemand("plugin:tc", "enable new interfaces detected at runtime", CONFIG_ONDEMAND_YES);
182
- enable_bytes = config_get_boolean_ondemand("plugin:tc", "enable traffic charts for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
183
- enable_packets = config_get_boolean_ondemand("plugin:tc", "enable packets charts for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
184
- enable_dropped = config_get_boolean_ondemand("plugin:tc", "enable dropped charts for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
185
- }
186
-
187
- // we only need to add leaf classes
188
- struct tc_class *c, *x;
189
- unsigned long long bytes_sum = 0, packets_sum = 0, dropped_sum = 0;
190
- int active_classes = 0;
191
-
192
- // set all classes
193
- for(c = d->classes ; c ; c = c->next) {
194
- c->isleaf = 1;
195
- c->hasparent = 0;
196
- }
197
-
198
- // mark the classes as leafs and parents
199
- for(c = d->classes ; c ; c = c->next) {
200
- if(unlikely(!c->updated)) continue;
201
-
202
- for(x = d->classes ; x ; x = x->next) {
203
- if(unlikely(!x->updated)) continue;
204
-
205
- if(unlikely(c == x)) continue;
206
-
207
- if(x->parentid && (
208
- ( c->hash == x->parent_hash && strcmp(c->id, x->parentid) == 0) ||
209
- (c->leafid && c->leaf_hash == x->parent_hash && strcmp(c->leafid, x->parentid) == 0))) {
210
- // debug(D_TC_LOOP, "TC: In device '%s', class '%s' (leafid: '%s') has as leaf class '%s' (parentid: '%s').", d->name?d->name:d->id, c->name?c->name:c->id, c->leafid?c->leafid:c->id, x->name?x->name:x->id, x->parentid?x->parentid:x->id);
211
- c->isleaf = 0;
212
- x->hasparent = 1;
213
- }
214
- }
215
- }
216
-
217
- // debugging:
218
- /*
219
- for ( c = d->classes ; c ; c = c->next) {
220
- if(c->isleaf && c->hasparent) debug(D_TC_LOOP, "TC: Device %s, class %s, OK", d->name, c->id);
221
- else debug(D_TC_LOOP, "TC: Device %s, class %s, IGNORE (isleaf: %d, hasparent: %d, parent: %s)", d->name, c->id, c->isleaf, c->hasparent, c->parentid);
222
- }
223
- */
224
-
225
- // we need at least a class
226
- for(c = d->classes ; c ; c = c->next) {
227
- // debug(D_TC_LOOP, "TC: Device '%s', class '%s', isLeaf=%d, HasParent=%d, Seen=%d", d->name?d->name:d->id, c->name?c->name:c->id, c->isleaf, c->hasparent, c->seen);
228
- if(!c->updated) continue;
229
- if(c->isleaf && c->hasparent) {
230
- active_classes++;
231
- bytes_sum += c->bytes;
232
- packets_sum += c->packets;
233
- dropped_sum += c->dropped;
234
- }
235
- }
236
-
237
- if(unlikely(!active_classes)) {
238
- debug(D_TC_LOOP, "TC: Ignoring TC device '%s'. No leaf classes.", d->name?d->name:d->id);
239
- tc_device_classes_cleanup(d);
240
- return;
241
- }
242
-
243
- if(unlikely(d->enabled == -1)) {
244
- char var_name[CONFIG_MAX_NAME + 1];
245
- snprintfz(var_name, CONFIG_MAX_NAME, "qos for %s", d->id);
246
- d->enabled = config_get_boolean_ondemand("plugin:tc", var_name, enable_new_interfaces);
247
-
248
- snprintfz(var_name, CONFIG_MAX_NAME, "traffic chart for %s", d->id);
249
- d->enabled_bytes = config_get_boolean_ondemand("plugin:tc", var_name, enable_bytes);
250
-
251
- snprintfz(var_name, CONFIG_MAX_NAME, "packets chart for %s", d->id);
252
- d->enabled_packets = config_get_boolean_ondemand("plugin:tc", var_name, enable_packets);
253
-
254
- snprintfz(var_name, CONFIG_MAX_NAME, "dropped packets chart for %s", d->id);
255
- d->enabled_dropped = config_get_boolean_ondemand("plugin:tc", var_name, enable_dropped);
256
- }
257
-
258
- if(likely(d->enabled)) {
259
- // --------------------------------------------------------------------
260
- // bytes
261
-
262
- if(d->enabled_bytes == CONFIG_ONDEMAND_YES || (d->enabled_bytes == CONFIG_ONDEMAND_ONDEMAND && bytes_sum)) {
263
- d->enabled_bytes = CONFIG_ONDEMAND_YES;
264
-
265
- if(unlikely(!d->st_bytes)) {
266
- d->st_bytes = rrdset_find_bytype(RRD_TYPE_TC, d->id);
267
- if(unlikely(!d->st_bytes)) {
268
- debug(D_TC_LOOP, "TC: Creating new chart for device '%s'", d->name?d->name:d->id);
269
- d->st_bytes = rrdset_create(RRD_TYPE_TC, d->id, d->name?d->name:d->id, d->family?d->family:d->id, RRD_TYPE_TC ".qos", "Class Usage", "kilobits/s", 7000, rrd_update_every, RRDSET_TYPE_STACKED);
270
- }
271
- }
272
- else {
273
- debug(D_TC_LOOP, "TC: Updating chart for device '%s'", d->name?d->name:d->id);
274
- rrdset_next_plugins(d->st_bytes);
275
-
276
- if(unlikely(d->name_updated && d->name && strcmp(d->id, d->name) != 0)) {
277
- rrdset_set_name(d->st_bytes, d->name);
278
- d->name_updated = 0;
279
- }
280
-
281
- // FIXME
282
- // update the family
283
- }
284
-
285
- for(c = d->classes ; c ; c = c->next) {
286
- if(unlikely(!c->updated)) continue;
287
-
288
- if(c->isleaf && c->hasparent) {
289
- c->seen++;
290
-
291
- if(unlikely(!c->rd_bytes)) {
292
- c->rd_bytes = rrddim_find(d->st_bytes, c->id);
293
- if(unlikely(!c->rd_bytes)) {
294
- debug(D_TC_LOOP, "TC: Adding to chart '%s', dimension '%s' (name: '%s')", d->st_bytes->id, c->id, c->name);
295
-
296
- // new class, we have to add it
297
- c->rd_bytes = rrddim_add(d->st_bytes, c->id, c->name?c->name:c->id, 8, 1024, RRDDIM_INCREMENTAL);
298
- }
299
- else debug(D_TC_LOOP, "TC: Updating chart '%s', dimension '%s'", d->st_bytes->id, c->id);
300
- }
301
-
302
- rrddim_set_by_pointer(d->st_bytes, c->rd_bytes, c->bytes);
303
-
304
- // if it has a name, different to the id
305
- if(unlikely(c->name_updated && c->name && strcmp(c->id, c->name) != 0)) {
306
- // update the rrd dimension with the new name
307
- debug(D_TC_LOOP, "TC: Setting chart '%s', dimension '%s' name to '%s'", d->st_bytes->id, c->rd_bytes->id, c->name);
308
- rrddim_set_name(d->st_bytes, c->rd_bytes, c->name);
309
- }
310
- }
311
- }
312
- rrdset_done(d->st_bytes);
313
- }
314
-
315
- // --------------------------------------------------------------------
316
- // packets
317
-
318
- if(d->enabled_packets == CONFIG_ONDEMAND_YES || (d->enabled_packets == CONFIG_ONDEMAND_ONDEMAND && packets_sum)) {
319
- d->enabled_packets = CONFIG_ONDEMAND_YES;
320
-
321
- if(unlikely(!d->st_packets)) {
322
- char id[RRD_ID_LENGTH_MAX + 1];
323
- char name[RRD_ID_LENGTH_MAX + 1];
324
- snprintfz(id, RRD_ID_LENGTH_MAX, "%s_packets", d->id);
325
- snprintfz(name, RRD_ID_LENGTH_MAX, "%s_packets", d->name?d->name:d->id);
326
-
327
- d->st_packets = rrdset_find_bytype(RRD_TYPE_TC, id);
328
- if(unlikely(!d->st_packets)) {
329
- debug(D_TC_LOOP, "TC: Creating new _packets chart for device '%s'", d->name?d->name:d->id);
330
- d->st_packets = rrdset_create(RRD_TYPE_TC, id, name, d->family?d->family:d->id, RRD_TYPE_TC ".qos_packets", "Class Packets", "packets/s", 7010, rrd_update_every, RRDSET_TYPE_STACKED);
331
- }
332
- }
333
- else {
334
- debug(D_TC_LOOP, "TC: Updating _packets chart for device '%s'", d->name?d->name:d->id);
335
- rrdset_next_plugins(d->st_packets);
336
-
337
- // FIXME
338
- // update the family
339
- }
340
-
341
- for(c = d->classes ; c ; c = c->next) {
342
- if(unlikely(!c->updated)) continue;
343
-
344
- if(c->isleaf && c->hasparent) {
345
- if(unlikely(!c->rd_packets)) {
346
- c->rd_packets = rrddim_find(d->st_packets, c->id);
347
- if(unlikely(!c->rd_packets)) {
348
- debug(D_TC_LOOP, "TC: Adding to chart '%s', dimension '%s' (name: '%s')", d->st_packets->id, c->id, c->name);
349
-
350
- // new class, we have to add it
351
- c->rd_packets = rrddim_add(d->st_packets, c->id, c->name?c->name:c->id, 1, 1, RRDDIM_INCREMENTAL);
352
- }
353
- else debug(D_TC_LOOP, "TC: Updating chart '%s', dimension '%s'", d->st_packets->id, c->id);
354
- }
355
-
356
- rrddim_set_by_pointer(d->st_packets, c->rd_packets, c->packets);
357
-
358
- // if it has a name, different to the id
359
- if(unlikely(c->name_updated && c->name && strcmp(c->id, c->name) != 0)) {
360
- // update the rrd dimension with the new name
361
- debug(D_TC_LOOP, "TC: Setting chart '%s', dimension '%s' name to '%s'", d->st_packets->id, c->rd_packets->id, c->name);
362
- rrddim_set_name(d->st_packets, c->rd_packets, c->name);
363
- }
364
- }
365
- }
366
- rrdset_done(d->st_packets);
367
- }
368
-
369
- // --------------------------------------------------------------------
370
- // dropped
371
-
372
- if(d->enabled_dropped == CONFIG_ONDEMAND_YES || (d->enabled_dropped == CONFIG_ONDEMAND_ONDEMAND && dropped_sum)) {
373
- d->enabled_dropped = CONFIG_ONDEMAND_YES;
374
-
375
- if(unlikely(!d->st_dropped)) {
376
- char id[RRD_ID_LENGTH_MAX + 1];
377
- char name[RRD_ID_LENGTH_MAX + 1];
378
- snprintfz(id, RRD_ID_LENGTH_MAX, "%s_dropped", d->id);
379
- snprintfz(name, RRD_ID_LENGTH_MAX, "%s_dropped", d->name?d->name:d->id);
380
-
381
- d->st_dropped = rrdset_find_bytype(RRD_TYPE_TC, id);
382
- if(unlikely(!d->st_dropped)) {
383
- debug(D_TC_LOOP, "TC: Creating new _dropped chart for device '%s'", d->name?d->name:d->id);
384
- d->st_dropped = rrdset_create(RRD_TYPE_TC, id, name, d->family?d->family:d->id, RRD_TYPE_TC ".qos_dropped", "Class Dropped Packets", "packets/s", 7020, rrd_update_every, RRDSET_TYPE_STACKED);
385
- }
386
- }
387
- else {
388
- debug(D_TC_LOOP, "TC: Updating _dropped chart for device '%s'", d->name?d->name:d->id);
389
- rrdset_next_plugins(d->st_dropped);
390
-
391
- // FIXME
392
- // update the family
393
- }
394
-
395
- for(c = d->classes ; c ; c = c->next) {
396
- if(unlikely(!c->updated)) continue;
397
-
398
- if(c->isleaf && c->hasparent) {
399
- if(unlikely(!c->rd_dropped)) {
400
- c->rd_dropped = rrddim_find(d->st_dropped, c->id);
401
- if(unlikely(!c->rd_dropped)) {
402
- debug(D_TC_LOOP, "TC: Adding to chart '%s', dimension '%s' (name: '%s')", d->st_dropped->id, c->id, c->name);
403
-
404
- // new class, we have to add it
405
- c->rd_dropped = rrddim_add(d->st_dropped, c->id, c->name?c->name:c->id, 1, 1, RRDDIM_INCREMENTAL);
406
- }
407
- else debug(D_TC_LOOP, "TC: Updating chart '%s', dimension '%s'", d->st_dropped->id, c->id);
408
- }
409
-
410
- rrddim_set_by_pointer(d->st_dropped, c->rd_dropped, c->dropped);
411
-
412
- // if it has a name, different to the id
413
- if(unlikely(c->name_updated && c->name && strcmp(c->id, c->name) != 0)) {
414
- // update the rrd dimension with the new name
415
- debug(D_TC_LOOP, "TC: Setting chart '%s', dimension '%s' name to '%s'", d->st_dropped->id, c->rd_dropped->id, c->name);
416
- rrddim_set_name(d->st_dropped, c->rd_dropped, c->name);
417
- }
418
- }
419
- }
420
- rrdset_done(d->st_dropped);
421
- }
422
- }
423
-
424
- tc_device_classes_cleanup(d);
178
+ static int enable_new_interfaces = -1, enable_bytes = -1, enable_packets = -1, enable_dropped = -1;
179
+
180
+ if(unlikely(enable_new_interfaces == -1)) {
181
+ enable_new_interfaces = config_get_boolean_ondemand("plugin:tc", "enable new interfaces detected at runtime", CONFIG_ONDEMAND_YES);
182
+ enable_bytes = config_get_boolean_ondemand("plugin:tc", "enable traffic charts for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
183
+ enable_packets = config_get_boolean_ondemand("plugin:tc", "enable packets charts for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
184
+ enable_dropped = config_get_boolean_ondemand("plugin:tc", "enable dropped charts for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
185
+ }
186
+
187
+ // we only need to add leaf classes
188
+ struct tc_class *c, *x;
189
+ unsigned long long bytes_sum = 0, packets_sum = 0, dropped_sum = 0;
190
+ int active_classes = 0;
191
+
192
+ // set all classes
193
+ for(c = d->classes ; c ; c = c->next) {
194
+ c->isleaf = 1;
195
+ c->hasparent = 0;
196
+ }
197
+
198
+ // mark the classes as leafs and parents
199
+ for(c = d->classes ; c ; c = c->next) {
200
+ if(unlikely(!c->updated)) continue;
201
+
202
+ for(x = d->classes ; x ; x = x->next) {
203
+ if(unlikely(!x->updated)) continue;
204
+
205
+ if(unlikely(c == x)) continue;
206
+
207
+ if(x->parentid && (
208
+ ( c->hash == x->parent_hash && strcmp(c->id, x->parentid) == 0) ||
209
+ (c->leafid && c->leaf_hash == x->parent_hash && strcmp(c->leafid, x->parentid) == 0))) {
210
+ // debug(D_TC_LOOP, "TC: In device '%s', class '%s' (leafid: '%s') has as leaf class '%s' (parentid: '%s').", d->name?d->name:d->id, c->name?c->name:c->id, c->leafid?c->leafid:c->id, x->name?x->name:x->id, x->parentid?x->parentid:x->id);
211
+ c->isleaf = 0;
212
+ x->hasparent = 1;
213
+ }
214
+ }
215
+ }
216
+
217
+ // debugging:
218
+ /*
219
+ for ( c = d->classes ; c ; c = c->next) {
220
+ if(c->isleaf && c->hasparent) debug(D_TC_LOOP, "TC: Device %s, class %s, OK", d->name, c->id);
221
+ else debug(D_TC_LOOP, "TC: Device %s, class %s, IGNORE (isleaf: %d, hasparent: %d, parent: %s)", d->name, c->id, c->isleaf, c->hasparent, c->parentid);
222
+ }
223
+ */
224
+
225
+ // we need at least a class
226
+ for(c = d->classes ; c ; c = c->next) {
227
+ // debug(D_TC_LOOP, "TC: Device '%s', class '%s', isLeaf=%d, HasParent=%d, Seen=%d", d->name?d->name:d->id, c->name?c->name:c->id, c->isleaf, c->hasparent, c->seen);
228
+ if(!c->updated) continue;
229
+ if(c->isleaf && c->hasparent) {
230
+ active_classes++;
231
+ bytes_sum += c->bytes;
232
+ packets_sum += c->packets;
233
+ dropped_sum += c->dropped;
234
+ }
235
+ }
236
+
237
+ if(unlikely(!active_classes)) {
238
+ debug(D_TC_LOOP, "TC: Ignoring TC device '%s'. No leaf classes.", d->name?d->name:d->id);
239
+ tc_device_classes_cleanup(d);
240
+ return;
241
+ }
242
+
243
+ if(unlikely(d->enabled == -1)) {
244
+ char var_name[CONFIG_MAX_NAME + 1];
245
+ snprintfz(var_name, CONFIG_MAX_NAME, "qos for %s", d->id);
246
+ d->enabled = config_get_boolean_ondemand("plugin:tc", var_name, enable_new_interfaces);
247
+
248
+ snprintfz(var_name, CONFIG_MAX_NAME, "traffic chart for %s", d->id);
249
+ d->enabled_bytes = config_get_boolean_ondemand("plugin:tc", var_name, enable_bytes);
250
+
251
+ snprintfz(var_name, CONFIG_MAX_NAME, "packets chart for %s", d->id);
252
+ d->enabled_packets = config_get_boolean_ondemand("plugin:tc", var_name, enable_packets);
253
+
254
+ snprintfz(var_name, CONFIG_MAX_NAME, "dropped packets chart for %s", d->id);
255
+ d->enabled_dropped = config_get_boolean_ondemand("plugin:tc", var_name, enable_dropped);
256
+ }
257
+
258
+ if(likely(d->enabled)) {
259
+ // --------------------------------------------------------------------
260
+ // bytes
261
+
262
+ if(d->enabled_bytes == CONFIG_ONDEMAND_YES || (d->enabled_bytes == CONFIG_ONDEMAND_ONDEMAND && bytes_sum)) {
263
+ d->enabled_bytes = CONFIG_ONDEMAND_YES;
264
+
265
+ if(unlikely(!d->st_bytes)) {
266
+ d->st_bytes = rrdset_find_bytype(RRD_TYPE_TC, d->id);
267
+ if(unlikely(!d->st_bytes)) {
268
+ debug(D_TC_LOOP, "TC: Creating new chart for device '%s'", d->name?d->name:d->id);
269
+ d->st_bytes = rrdset_create(RRD_TYPE_TC, d->id, d->name?d->name:d->id, d->family?d->family:d->id, RRD_TYPE_TC ".qos", "Class Usage", "kilobits/s", 7000, rrd_update_every, RRDSET_TYPE_STACKED);
270
+ }
271
+ }
272
+ else {
273
+ debug(D_TC_LOOP, "TC: Updating chart for device '%s'", d->name?d->name:d->id);
274
+ rrdset_next_plugins(d->st_bytes);
275
+
276
+ if(unlikely(d->name_updated && d->name && strcmp(d->id, d->name) != 0)) {
277
+ rrdset_set_name(d->st_bytes, d->name);
278
+ d->name_updated = 0;
279
+ }
280
+
281
+ // FIXME
282
+ // update the family
283
+ }
284
+
285
+ for(c = d->classes ; c ; c = c->next) {
286
+ if(unlikely(!c->updated)) continue;
287
+
288
+ if(c->isleaf && c->hasparent) {
289
+ c->seen++;
290
+
291
+ if(unlikely(!c->rd_bytes)) {
292
+ c->rd_bytes = rrddim_find(d->st_bytes, c->id);
293
+ if(unlikely(!c->rd_bytes)) {
294
+ debug(D_TC_LOOP, "TC: Adding to chart '%s', dimension '%s' (name: '%s')", d->st_bytes->id, c->id, c->name);
295
+
296
+ // new class, we have to add it
297
+ c->rd_bytes = rrddim_add(d->st_bytes, c->id, c->name?c->name:c->id, 8, 1024, RRDDIM_INCREMENTAL);
298
+ }
299
+ else debug(D_TC_LOOP, "TC: Updating chart '%s', dimension '%s'", d->st_bytes->id, c->id);
300
+ }
301
+
302
+ rrddim_set_by_pointer(d->st_bytes, c->rd_bytes, c->bytes);
303
+
304
+ // if it has a name, different to the id
305
+ if(unlikely(c->name_updated && c->name && strcmp(c->id, c->name) != 0)) {
306
+ // update the rrd dimension with the new name
307
+ debug(D_TC_LOOP, "TC: Setting chart '%s', dimension '%s' name to '%s'", d->st_bytes->id, c->rd_bytes->id, c->name);
308
+ rrddim_set_name(d->st_bytes, c->rd_bytes, c->name);
309
+ }
310
+ }
311
+ }
312
+ rrdset_done(d->st_bytes);
313
+ }
314
+
315
+ // --------------------------------------------------------------------
316
+ // packets
317
+
318
+ if(d->enabled_packets == CONFIG_ONDEMAND_YES || (d->enabled_packets == CONFIG_ONDEMAND_ONDEMAND && packets_sum)) {
319
+ d->enabled_packets = CONFIG_ONDEMAND_YES;
320
+
321
+ if(unlikely(!d->st_packets)) {
322
+ char id[RRD_ID_LENGTH_MAX + 1];
323
+ char name[RRD_ID_LENGTH_MAX + 1];
324
+ snprintfz(id, RRD_ID_LENGTH_MAX, "%s_packets", d->id);
325
+ snprintfz(name, RRD_ID_LENGTH_MAX, "%s_packets", d->name?d->name:d->id);
326
+
327
+ d->st_packets = rrdset_find_bytype(RRD_TYPE_TC, id);
328
+ if(unlikely(!d->st_packets)) {
329
+ debug(D_TC_LOOP, "TC: Creating new _packets chart for device '%s'", d->name?d->name:d->id);
330
+ d->st_packets = rrdset_create(RRD_TYPE_TC, id, name, d->family?d->family:d->id, RRD_TYPE_TC ".qos_packets", "Class Packets", "packets/s", 7010, rrd_update_every, RRDSET_TYPE_STACKED);
331
+ }
332
+ }
333
+ else {
334
+ debug(D_TC_LOOP, "TC: Updating _packets chart for device '%s'", d->name?d->name:d->id);
335
+ rrdset_next_plugins(d->st_packets);
336
+
337
+ // FIXME
338
+ // update the family
339
+ }
340
+
341
+ for(c = d->classes ; c ; c = c->next) {
342
+ if(unlikely(!c->updated)) continue;
343
+
344
+ if(c->isleaf && c->hasparent) {
345
+ if(unlikely(!c->rd_packets)) {
346
+ c->rd_packets = rrddim_find(d->st_packets, c->id);
347
+ if(unlikely(!c->rd_packets)) {
348
+ debug(D_TC_LOOP, "TC: Adding to chart '%s', dimension '%s' (name: '%s')", d->st_packets->id, c->id, c->name);
349
+
350
+ // new class, we have to add it
351
+ c->rd_packets = rrddim_add(d->st_packets, c->id, c->name?c->name:c->id, 1, 1, RRDDIM_INCREMENTAL);
352
+ }
353
+ else debug(D_TC_LOOP, "TC: Updating chart '%s', dimension '%s'", d->st_packets->id, c->id);
354
+ }
355
+
356
+ rrddim_set_by_pointer(d->st_packets, c->rd_packets, c->packets);
357
+
358
+ // if it has a name, different to the id
359
+ if(unlikely(c->name_updated && c->name && strcmp(c->id, c->name) != 0)) {
360
+ // update the rrd dimension with the new name
361
+ debug(D_TC_LOOP, "TC: Setting chart '%s', dimension '%s' name to '%s'", d->st_packets->id, c->rd_packets->id, c->name);
362
+ rrddim_set_name(d->st_packets, c->rd_packets, c->name);
363
+ }
364
+ }
365
+ }
366
+ rrdset_done(d->st_packets);
367
+ }
368
+
369
+ // --------------------------------------------------------------------
370
+ // dropped
371
+
372
+ if(d->enabled_dropped == CONFIG_ONDEMAND_YES || (d->enabled_dropped == CONFIG_ONDEMAND_ONDEMAND && dropped_sum)) {
373
+ d->enabled_dropped = CONFIG_ONDEMAND_YES;
374
+
375
+ if(unlikely(!d->st_dropped)) {
376
+ char id[RRD_ID_LENGTH_MAX + 1];
377
+ char name[RRD_ID_LENGTH_MAX + 1];
378
+ snprintfz(id, RRD_ID_LENGTH_MAX, "%s_dropped", d->id);
379
+ snprintfz(name, RRD_ID_LENGTH_MAX, "%s_dropped", d->name?d->name:d->id);
380
+
381
+ d->st_dropped = rrdset_find_bytype(RRD_TYPE_TC, id);
382
+ if(unlikely(!d->st_dropped)) {
383
+ debug(D_TC_LOOP, "TC: Creating new _dropped chart for device '%s'", d->name?d->name:d->id);
384
+ d->st_dropped = rrdset_create(RRD_TYPE_TC, id, name, d->family?d->family:d->id, RRD_TYPE_TC ".qos_dropped", "Class Dropped Packets", "packets/s", 7020, rrd_update_every, RRDSET_TYPE_STACKED);
385
+ }
386
+ }
387
+ else {
388
+ debug(D_TC_LOOP, "TC: Updating _dropped chart for device '%s'", d->name?d->name:d->id);
389
+ rrdset_next_plugins(d->st_dropped);
390
+
391
+ // FIXME
392
+ // update the family
393
+ }
394
+
395
+ for(c = d->classes ; c ; c = c->next) {
396
+ if(unlikely(!c->updated)) continue;
397
+
398
+ if(c->isleaf && c->hasparent) {
399
+ if(unlikely(!c->rd_dropped)) {
400
+ c->rd_dropped = rrddim_find(d->st_dropped, c->id);
401
+ if(unlikely(!c->rd_dropped)) {
402
+ debug(D_TC_LOOP, "TC: Adding to chart '%s', dimension '%s' (name: '%s')", d->st_dropped->id, c->id, c->name);
403
+
404
+ // new class, we have to add it
405
+ c->rd_dropped = rrddim_add(d->st_dropped, c->id, c->name?c->name:c->id, 1, 1, RRDDIM_INCREMENTAL);
406
+ }
407
+ else debug(D_TC_LOOP, "TC: Updating chart '%s', dimension '%s'", d->st_dropped->id, c->id);
408
+ }
409
+
410
+ rrddim_set_by_pointer(d->st_dropped, c->rd_dropped, c->dropped);
411
+
412
+ // if it has a name, different to the id
413
+ if(unlikely(c->name_updated && c->name && strcmp(c->id, c->name) != 0)) {
414
+ // update the rrd dimension with the new name
415
+ debug(D_TC_LOOP, "TC: Setting chart '%s', dimension '%s' name to '%s'", d->st_dropped->id, c->rd_dropped->id, c->name);
416
+ rrddim_set_name(d->st_dropped, c->rd_dropped, c->name);
417
+ }
418
+ }
419
+ }
420
+ rrdset_done(d->st_dropped);
421
+ }
422
+ }
423
+
424
+ tc_device_classes_cleanup(d);
425
}
426
427
static inline void tc_device_set_class_name(struct tc_device *d, char *id, char *name)
428
{
429
- struct tc_class *c = tc_class_index_find(d, id, 0);
430
- if(likely(c)) {
431
- freez(c->name);
432
- c->name = NULL;
433
-
434
- if(likely(name && *name && strcmp(c->id, name) != 0)) {
435
- debug(D_TC_LOOP, "TC: Setting device '%s', class '%s' name to '%s'", d->id, id, name);
436
- c->name = strdupz(name);
437
- c->name_updated = 1;
438
- }
439
- }
429
+ struct tc_class *c = tc_class_index_find(d, id, 0);
430
+ if(likely(c)) {
431
+ freez(c->name);
432
+ c->name = NULL;
433
+
434
+ if(likely(name && *name && strcmp(c->id, name) != 0)) {
435
+ debug(D_TC_LOOP, "TC: Setting device '%s', class '%s' name to '%s'", d->id, id, name);
436
+ c->name = strdupz(name);
437
+ c->name_updated = 1;
438
+ }
439
+ }
440
}
441
442
static inline void tc_device_set_device_name(struct tc_device *d, char *name) {
443
- freez(d->name);
444
- d->name = NULL;
445
-
446
- if(likely(name && *name && strcmp(d->id, name) != 0)) {
447
- debug(D_TC_LOOP, "TC: Setting device '%s' name to '%s'", d->id, name);
448
- d->name = strdupz(name);
449
- d->name_updated = 1;
450
- }
443
+ freez(d->name);
444
+ d->name = NULL;
445
+
446
+ if(likely(name && *name && strcmp(d->id, name) != 0)) {
447
+ debug(D_TC_LOOP, "TC: Setting device '%s' name to '%s'", d->id, name);
448
+ d->name = strdupz(name);
449
+ d->name_updated = 1;
450
+ }
451
}
452
453
static inline void tc_device_set_device_family(struct tc_device *d, char *family) {
454
- freez(d->family);
455
- d->family = NULL;
456
-
457
- if(likely(family && *family && strcmp(d->id, family) != 0)) {
458
- debug(D_TC_LOOP, "TC: Setting device '%s' family to '%s'", d->id, family);
459
- d->family = strdupz(family);
460
- d->family_updated = 1;
461
- }
462
- // no need for null termination - it is already null
454
+ freez(d->family);
455
+ d->family = NULL;
456
+
457
+ if(likely(family && *family && strcmp(d->id, family) != 0)) {
458
+ debug(D_TC_LOOP, "TC: Setting device '%s' family to '%s'", d->id, family);
459
+ d->family = strdupz(family);
460
+ d->family_updated = 1;
461
+ }
462
+ // no need for null termination - it is already null
463
}
464
465
static inline struct tc_device *tc_device_create(char *id)
466
{
467
- struct tc_device *d = tc_device_index_find(id, 0);
467
+ struct tc_device *d = tc_device_index_find(id, 0);
468
469
- if(!d) {
470
- debug(D_TC_LOOP, "TC: Creating device '%s'", id);
469
+ if(!d) {
470
+ debug(D_TC_LOOP, "TC: Creating device '%s'", id);
471
472
- d = callocz(1, sizeof(struct tc_device));
472
+ d = callocz(1, sizeof(struct tc_device));
473
474
- d->id = strdupz(id);
475
- d->hash = simple_hash(d->id);
476
- d->enabled = -1;
474
+ d->id = strdupz(id);
475
+ d->hash = simple_hash(d->id);
476
+ d->enabled = -1;
477
478
- avl_init(&d->classes_index, tc_class_compare);
479
- tc_device_index_add(d);
478
+ avl_init(&d->classes_index, tc_class_compare);
479
+ tc_device_index_add(d);
480
481
- if(!tc_device_root) {
482
- tc_device_root = d;
483
- }
484
- else {
485
- d->next = tc_device_root;
486
- tc_device_root->prev = d;
487
- tc_device_root = d;
488
- }
489
- }
481
+ if(!tc_device_root) {
482
+ tc_device_root = d;
483
+ }
484
+ else {
485
+ d->next = tc_device_root;
486
+ tc_device_root->prev = d;
487
+ tc_device_root = d;
488
+ }
489
+ }
490
491
- return(d);
491
+ return(d);
492
}
493
494
static inline struct tc_class *tc_class_add(struct tc_device *n, char *id, char *parentid, char *leafid)
495
{
496
- struct tc_class *c = tc_class_index_find(n, id, 0);
496
+ struct tc_class *c = tc_class_index_find(n, id, 0);
497
498
- if(!c) {
499
- debug(D_TC_LOOP, "TC: Creating in device '%s', class id '%s', parentid '%s', leafid '%s'", n->id, id, parentid?parentid:"", leafid?leafid:"");
498
+ if(!c) {
499
+ debug(D_TC_LOOP, "TC: Creating in device '%s', class id '%s', parentid '%s', leafid '%s'", n->id, id, parentid?parentid:"", leafid?leafid:"");
500
501
- c = callocz(1, sizeof(struct tc_class));
501
+ c = callocz(1, sizeof(struct tc_class));
502
503
- if(n->classes) n->classes->prev = c;
504
- c->next = n->classes;
505
- n->classes = c;
503
+ if(n->classes) n->classes->prev = c;
504
+ c->next = n->classes;
505
+ n->classes = c;
506
507
- c->id = strdupz(id);
508
- c->hash = simple_hash(c->id);
507
+ c->id = strdupz(id);
508
+ c->hash = simple_hash(c->id);
509
510
- if(parentid && *parentid) {
511
- c->parentid = strdupz(parentid);
512
- c->parent_hash = simple_hash(c->parentid);
513
- }
510
+ if(parentid && *parentid) {
511
+ c->parentid = strdupz(parentid);
512
+ c->parent_hash = simple_hash(c->parentid);
513
+ }
514
515
- if(leafid && *leafid) {
516
- c->leafid = strdupz(leafid);
517
- c->leaf_hash = simple_hash(c->leafid);
518
- }
515
+ if(leafid && *leafid) {
516
+ c->leafid = strdupz(leafid);
517
+ c->leaf_hash = simple_hash(c->leafid);
518
+ }
519
520
- tc_class_index_add(n, c);
521
- }
520
+ tc_class_index_add(n, c);
521
+ }
522
523
- c->seen = 1;
523
+ c->seen = 1;
524
525
- return(c);
525
+ return(c);
526
}
527
528
static inline void tc_device_free(struct tc_device *n)
529
{
530
- if(n->next) n->next->prev = n->prev;
531
- if(n->prev) n->prev->next = n->next;
532
- if(tc_device_root == n) {
533
- if(n->next) tc_device_root = n->next;
534
- else tc_device_root = n->prev;
535
- }
530
+ if(n->next) n->next->prev = n->prev;
531
+ if(n->prev) n->prev->next = n->next;
532
+ if(tc_device_root == n) {
533
+ if(n->next) tc_device_root = n->next;
534
+ else tc_device_root = n->prev;
535
+ }
536
537
- tc_device_index_del(n);
537
+ tc_device_index_del(n);
538
539
- while(n->classes) tc_class_free(n, n->classes);
539
+ while(n->classes) tc_class_free(n, n->classes);
540
541
- freez(n->id);
542
- freez(n->name);
543
- freez(n->family);
544
- freez(n);
541
+ freez(n->id);
542
+ freez(n->name);
543
+ freez(n->family);
544
+ freez(n);
545
}
546
547
static inline void tc_device_free_all()
548
{
549
- while(tc_device_root)
550
- tc_device_free(tc_device_root);
549
+ while(tc_device_root)
550
+ tc_device_free(tc_device_root);
551
}
552
553
#define MAX_WORDS 20
554
555
static inline int tc_space(char c) {
556
- switch(c) {
557
- case ' ':
558
- case '\t':
559
- case '\r':
560
- case '\n':
561
- return 1;
562
-
563
- default:
564
- return 0;
565
- }
556
+ switch(c) {
557
+ case ' ':
558
+ case '\t':
559
+ case '\r':
560
+ case '\n':
561
+ return 1;
562
+
563
+ default:
564
+ return 0;
565
+ }
566
}
567
568
static inline void tc_split_words(char *str, char **words, int max_words) {
569
- char *s = str;
570
- int i = 0;
569
+ char *s = str;
570
+ int i = 0;
571
572
- // skip all white space
573
- while(tc_space(*s)) s++;
572
+ // skip all white space
573
+ while(tc_space(*s)) s++;
574
575
- // store the first word
576
- words[i++] = s;
575
+ // store the first word
576
+ words[i++] = s;
577
578
- // while we have something
579
- while(*s) {
580
- // if it is a space
581
- if(unlikely(tc_space(*s))) {
578
+ // while we have something
579
+ while(*s) {
580
+ // if it is a space
581
+ if(unlikely(tc_space(*s))) {
582
583
- // terminate the word
584
- *s++ = '\0';
583
+ // terminate the word
584
+ *s++ = '\0';
585
586
- // skip all white space
587
- while(tc_space(*s)) s++;
586
+ // skip all white space
587
+ while(tc_space(*s)) s++;
588
589
- // if we reached the end, stop
590
- if(!*s) break;
589
+ // if we reached the end, stop
590
+ if(!*s) break;
591
592
- // store the next word
593
- if(i < max_words) words[i++] = s;
594
- else break;
595
- }
596
- else s++;
597
- }
592
+ // store the next word
593
+ if(i < max_words) words[i++] = s;
594
+ else break;
595
+ }
596
+ else s++;
597
+ }
598
599
- // terminate the words
600
- while(i < max_words) words[i++] = NULL;
599
+ // terminate the words
600
+ while(i < max_words) words[i++] = NULL;
601
}
602
603
pid_t tc_child_pid = 0;
604
void *tc_main(void *ptr) {
605
- (void)ptr;
605
+ (void)ptr;
606
607
- info("TC thread created with task id %d", gettid());
607
+ info("TC thread created with task id %d", gettid());
608
609
- if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
610
- error("Cannot set pthread cancel type to DEFERRED.");
609
+ if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
610
+ error("Cannot set pthread cancel type to DEFERRED.");
611
612
- if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
613
- error("Cannot set pthread cancel state to ENABLE.");
612
+ if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
613
+ error("Cannot set pthread cancel state to ENABLE.");
614
615
- struct rusage thread;
616
- RRDSET *stcpu = NULL, *sttime = NULL;
615
+ struct rusage thread;
616
+ RRDSET *stcpu = NULL, *sttime = NULL;
617
618
- char buffer[TC_LINE_MAX+1] = "";
619
- char *words[MAX_WORDS] = { NULL };
618
+ char buffer[TC_LINE_MAX+1] = "";
619
+ char *words[MAX_WORDS] = { NULL };
620
621
- uint32_t BEGIN_HASH = simple_hash("BEGIN");
622
- uint32_t END_HASH = simple_hash("END");
623
- uint32_t CLASS_HASH = simple_hash("class");
624
- uint32_t SENT_HASH = simple_hash("Sent");
625
- uint32_t LENDED_HASH = simple_hash("lended:");
626
- uint32_t TOKENS_HASH = simple_hash("tokens:");
627
- uint32_t SETDEVICENAME_HASH = simple_hash("SETDEVICENAME");
628
- uint32_t SETDEVICEGROUP_HASH = simple_hash("SETDEVICEGROUP");
629
- uint32_t SETCLASSNAME_HASH = simple_hash("SETCLASSNAME");
630
- uint32_t WORKTIME_HASH = simple_hash("WORKTIME");
621
+ uint32_t BEGIN_HASH = simple_hash("BEGIN");
622
+ uint32_t END_HASH = simple_hash("END");
623
+ uint32_t CLASS_HASH = simple_hash("class");
624
+ uint32_t SENT_HASH = simple_hash("Sent");
625
+ uint32_t LENDED_HASH = simple_hash("lended:");
626
+ uint32_t TOKENS_HASH = simple_hash("tokens:");
627
+ uint32_t SETDEVICENAME_HASH = simple_hash("SETDEVICENAME");
628
+ uint32_t SETDEVICEGROUP_HASH = simple_hash("SETDEVICEGROUP");
629
+ uint32_t SETCLASSNAME_HASH = simple_hash("SETCLASSNAME");
630
+ uint32_t WORKTIME_HASH = simple_hash("WORKTIME");
631
#ifdef DETACH_PLUGINS_FROM_NETDATA
632
- uint32_t MYPID_HASH = simple_hash("MYPID");
632
+ uint32_t MYPID_HASH = simple_hash("MYPID");
633
#endif
634
- uint32_t first_hash;
635
-
636
- snprintfz(buffer, TC_LINE_MAX, "%s/tc-qos-helper.sh", config_get("plugins", "plugins directory", PLUGINS_DIR));
637
- char *tc_script = config_get("plugin:tc", "script to run to get tc values", buffer);
638
-
639
- for(;1;) {
640
- if(unlikely(netdata_exit)) break;
641
-
642
- FILE *fp;
643
- struct tc_device *device = NULL;
644
- struct tc_class *class = NULL;
645
-
646
- snprintfz(buffer, TC_LINE_MAX, "exec %s %d", tc_script, rrd_update_every);
647
- debug(D_TC_LOOP, "executing '%s'", buffer);
648
-
649
- fp = mypopen(buffer, &tc_child_pid);
650
- if(unlikely(!fp)) {
651
- error("TC: Cannot popen(\"%s\", \"r\").", buffer);
652
- pthread_exit(NULL);
653
- return NULL;
654
- }
655
-
656
- while(fgets(buffer, TC_LINE_MAX, fp) != NULL) {
657
- if(unlikely(netdata_exit)) break;
658
-
659
- buffer[TC_LINE_MAX] = '\0';
660
- // debug(D_TC_LOOP, "TC: read '%s'", buffer);
661
-
662
- tc_split_words(buffer, words, MAX_WORDS);
663
-
664
- if(unlikely(!words[0] || !*words[0])) {
665
- // debug(D_TC_LOOP, "empty line");
666
- continue;
667
- }
668
- // else debug(D_TC_LOOP, "First word is '%s'", words[0]);
669
-
670
- first_hash = simple_hash(words[0]);
671
-
672
- if(unlikely(device && first_hash == CLASS_HASH && strcmp(words[0], "class") == 0)) {
673
- // debug(D_TC_LOOP, "CLASS line on class id='%s', parent='%s', parentid='%s', leaf='%s', leafid='%s'", words[2], words[3], words[4], words[5], words[6]);
674
-
675
- // words[1] : class type
676
- // words[2] : N:XX
677
- // words[3] : parent or root
678
- if(likely(words[1] && words[2] && words[3] && (strcmp(words[3], "parent") == 0 || strcmp(words[3], "root") == 0))) {
679
- //char *type = words[1]; // the class: htb, fq_codel, etc
680
-
681
- // we are only interested for HTB classes
682
- //if(strcmp(type, "htb") != 0) continue;
683
-
684
- char *id = words[2]; // the class major:minor
685
- char *parent = words[3]; // 'parent' or 'root'
686
- char *parentid = words[4]; // the parent's id
687
- char *leaf = words[5]; // 'leaf'
688
- char *leafid = words[6]; // leafid
689
-
690
- if(strcmp(parent, "root") == 0) {
691
- parentid = NULL;
692
- leafid = NULL;
693
- }
694
- else if(!leaf || strcmp(leaf, "leaf") != 0)
695
- leafid = NULL;
696
-
697
- char leafbuf[20 + 1] = "";
698
- if(leafid && leafid[strlen(leafid) - 1] == ':') {
699
- strncpyz(leafbuf, leafid, 20 - 1);
700
- strcat(leafbuf, "1");
701
- leafid = leafbuf;
702
- }
703
-
704
- class = tc_class_add(device, id, parentid, leafid);
705
- }
706
- else {
707
- // clear the last class
708
- class = NULL;
709
- }
710
- }
711
- else if(unlikely(first_hash == END_HASH && strcmp(words[0], "END") == 0)) {
712
- // debug(D_TC_LOOP, "END line");
713
-
714
- if(likely(device)) {
715
- if(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL) != 0)
716
- error("Cannot set pthread cancel state to DISABLE.");
717
-
718
- tc_device_commit(device);
719
- // tc_device_free(device);
720
-
721
- if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
722
- error("Cannot set pthread cancel state to ENABLE.");
723
- }
724
-
725
- device = NULL;
726
- class = NULL;
727
- }
728
- else if(unlikely(first_hash == BEGIN_HASH && strcmp(words[0], "BEGIN") == 0)) {
729
- // debug(D_TC_LOOP, "BEGIN line on device '%s'", words[1]);
730
-
731
- if(likely(words[1] && *words[1])) {
732
- device = tc_device_create(words[1]);
733
- }
734
- else {
735
- // tc_device_free(device);
736
- device = NULL;
737
- }
738
-
739
- class = NULL;
740
- }
741
- else if(unlikely(device && class && first_hash == SENT_HASH && strcmp(words[0], "Sent") == 0)) {
742
- // debug(D_TC_LOOP, "SENT line '%s'", words[1]);
743
- if(likely(words[1] && *words[1])) {
744
- class->bytes = strtoull(words[1], NULL, 10);
745
- class->updated = 1;
746
- }
747
- else {
748
- class->updated = 0;
749
- }
750
-
751
- if(likely(words[3] && *words[3]))
752
- class->packets = strtoull(words[3], NULL, 10);
753
-
754
- if(likely(words[6] && *words[6]))
755
- class->dropped = strtoull(words[6], NULL, 10);
756
-
757
- if(likely(words[8] && *words[8]))
758
- class->overlimits = strtoull(words[8], NULL, 10);
759
-
760
- if(likely(words[10] && *words[10]))
761
- class->requeues = strtoull(words[8], NULL, 10);
762
- }
763
- else if(unlikely(device && class && class->updated && first_hash == LENDED_HASH && strcmp(words[0], "lended:") == 0)) {
764
- // debug(D_TC_LOOP, "LENDED line '%s'", words[1]);
765
- if(likely(words[1] && *words[1]))
766
- class->lended = strtoull(words[1], NULL, 10);
767
-
768
- if(likely(words[3] && *words[3]))
769
- class->borrowed = strtoull(words[3], NULL, 10);
770
-
771
- if(likely(words[5] && *words[5]))
772
- class->giants = strtoull(words[5], NULL, 10);
773
- }
774
- else if(unlikely(device && class && class->updated && first_hash == TOKENS_HASH && strcmp(words[0], "tokens:") == 0)) {
775
- // debug(D_TC_LOOP, "TOKENS line '%s'", words[1]);
776
- if(likely(words[1] && *words[1]))
777
- class->tokens = strtoull(words[1], NULL, 10);
778
-
779
- if(likely(words[3] && *words[3]))
780
- class->ctokens = strtoull(words[3], NULL, 10);
781
- }
782
- else if(unlikely(device && first_hash == SETDEVICENAME_HASH && strcmp(words[0], "SETDEVICENAME") == 0)) {
783
- // debug(D_TC_LOOP, "SETDEVICENAME line '%s'", words[1]);
784
- if(likely(words[1] && *words[1]))
785
- tc_device_set_device_name(device, words[1]);
786
- }
787
- else if(unlikely(device && first_hash == SETDEVICEGROUP_HASH && strcmp(words[0], "SETDEVICEGROUP") == 0)) {
788
- // debug(D_TC_LOOP, "SETDEVICEGROUP line '%s'", words[1]);
789
- if(likely(words[1] && *words[1]))
790
- tc_device_set_device_family(device, words[1]);
791
- }
792
- else if(unlikely(device && first_hash == SETCLASSNAME_HASH && strcmp(words[0], "SETCLASSNAME") == 0)) {
793
- // debug(D_TC_LOOP, "SETCLASSNAME line '%s' '%s'", words[1], words[2]);
794
- char *id = words[1];
795
- char *path = words[2];
796
- if(likely(id && *id && path && *path))
797
- tc_device_set_class_name(device, id, path);
798
- }
799
- else if(unlikely(first_hash == WORKTIME_HASH && strcmp(words[0], "WORKTIME") == 0)) {
800
- // debug(D_TC_LOOP, "WORKTIME line '%s' '%s'", words[1], words[2]);
801
- getrusage(RUSAGE_THREAD, &thread);
802
-
803
- if(unlikely(!stcpu)) stcpu = rrdset_find("netdata.plugin_tc_cpu");
804
- if(unlikely(!stcpu)) {
805
- stcpu = rrdset_create("netdata", "plugin_tc_cpu", NULL, "tc.helper", NULL, "NetData TC CPU usage", "milliseconds/s", 135000, rrd_update_every, RRDSET_TYPE_STACKED);
806
- rrddim_add(stcpu, "user", NULL, 1, 1000, RRDDIM_INCREMENTAL);
807
- rrddim_add(stcpu, "system", NULL, 1, 1000, RRDDIM_INCREMENTAL);
808
- }
809
- else rrdset_next(stcpu);
810
-
811
- rrddim_set(stcpu, "user" , thread.ru_utime.tv_sec * 1000000ULL + thread.ru_utime.tv_usec);
812
- rrddim_set(stcpu, "system", thread.ru_stime.tv_sec * 1000000ULL + thread.ru_stime.tv_usec);
813
- rrdset_done(stcpu);
814
-
815
- if(unlikely(!sttime)) stcpu = rrdset_find("netdata.plugin_tc_time");
816
- if(unlikely(!sttime)) {
817
- sttime = rrdset_create("netdata", "plugin_tc_time", NULL, "tc.helper", NULL, "NetData TC script execution", "milliseconds/run", 135001, rrd_update_every, RRDSET_TYPE_AREA);
818
- rrddim_add(sttime, "run_time", "run time", 1, 1, RRDDIM_ABSOLUTE);
819
- }
820
- else rrdset_next(sttime);
821
-
822
- rrddim_set(sttime, "run_time", atoll(words[1]));
823
- rrdset_done(sttime);
824
-
825
- }
634
+ uint32_t first_hash;
635
+
636
+ snprintfz(buffer, TC_LINE_MAX, "%s/tc-qos-helper.sh", config_get("plugins", "plugins directory", PLUGINS_DIR));
637
+ char *tc_script = config_get("plugin:tc", "script to run to get tc values", buffer);
638
+
639
+ for(;1;) {
640
+ if(unlikely(netdata_exit)) break;
641
+
642
+ FILE *fp;
643
+ struct tc_device *device = NULL;
644
+ struct tc_class *class = NULL;
645
+
646
+ snprintfz(buffer, TC_LINE_MAX, "exec %s %d", tc_script, rrd_update_every);
647
+ debug(D_TC_LOOP, "executing '%s'", buffer);
648
+
649
+ fp = mypopen(buffer, &tc_child_pid);
650
+ if(unlikely(!fp)) {
651
+ error("TC: Cannot popen(\"%s\", \"r\").", buffer);
652
+ pthread_exit(NULL);
653
+ return NULL;
654
+ }
655
+
656
+ while(fgets(buffer, TC_LINE_MAX, fp) != NULL) {
657
+ if(unlikely(netdata_exit)) break;
658
+
659
+ buffer[TC_LINE_MAX] = '\0';
660
+ // debug(D_TC_LOOP, "TC: read '%s'", buffer);
661
+
662
+ tc_split_words(buffer, words, MAX_WORDS);
663
+
664
+ if(unlikely(!words[0] || !*words[0])) {
665
+ // debug(D_TC_LOOP, "empty line");
666
+ continue;
667
+ }
668
+ // else debug(D_TC_LOOP, "First word is '%s'", words[0]);
669
+
670
+ first_hash = simple_hash(words[0]);
671
+
672
+ if(unlikely(device && first_hash == CLASS_HASH && strcmp(words[0], "class") == 0)) {
673
+ // debug(D_TC_LOOP, "CLASS line on class id='%s', parent='%s', parentid='%s', leaf='%s', leafid='%s'", words[2], words[3], words[4], words[5], words[6]);
674
+
675
+ // words[1] : class type
676
+ // words[2] : N:XX
677
+ // words[3] : parent or root
678
+ if(likely(words[1] && words[2] && words[3] && (strcmp(words[3], "parent") == 0 || strcmp(words[3], "root") == 0))) {
679
+ //char *type = words[1]; // the class: htb, fq_codel, etc
680
+
681
+ // we are only interested for HTB classes
682
+ //if(strcmp(type, "htb") != 0) continue;
683
+
684
+ char *id = words[2]; // the class major:minor
685
+ char *parent = words[3]; // 'parent' or 'root'
686
+ char *parentid = words[4]; // the parent's id
687
+ char *leaf = words[5]; // 'leaf'
688
+ char *leafid = words[6]; // leafid
689
+
690
+ if(strcmp(parent, "root") == 0) {
691
+ parentid = NULL;
692
+ leafid = NULL;
693
+ }
694
+ else if(!leaf || strcmp(leaf, "leaf") != 0)
695
+ leafid = NULL;
696
+
697
+ char leafbuf[20 + 1] = "";
698
+ if(leafid && leafid[strlen(leafid) - 1] == ':') {
699
+ strncpyz(leafbuf, leafid, 20 - 1);
700
+ strcat(leafbuf, "1");
701
+ leafid = leafbuf;
702
+ }
703
+
704
+ class = tc_class_add(device, id, parentid, leafid);
705
+ }
706
+ else {
707
+ // clear the last class
708
+ class = NULL;
709
+ }
710
+ }
711
+ else if(unlikely(first_hash == END_HASH && strcmp(words[0], "END") == 0)) {
712
+ // debug(D_TC_LOOP, "END line");
713
+
714
+ if(likely(device)) {
715
+ if(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL) != 0)
716
+ error("Cannot set pthread cancel state to DISABLE.");
717
+
718
+ tc_device_commit(device);
719
+ // tc_device_free(device);
720
+
721
+ if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
722
+ error("Cannot set pthread cancel state to ENABLE.");
723
+ }
724
+
725
+ device = NULL;
726
+ class = NULL;
727
+ }
728
+ else if(unlikely(first_hash == BEGIN_HASH && strcmp(words[0], "BEGIN") == 0)) {
729
+ // debug(D_TC_LOOP, "BEGIN line on device '%s'", words[1]);
730
+
731
+ if(likely(words[1] && *words[1])) {
732
+ device = tc_device_create(words[1]);
733
+ }
734
+ else {
735
+ // tc_device_free(device);
736
+ device = NULL;
737
+ }
738
+
739
+ class = NULL;
740
+ }
741
+ else if(unlikely(device && class && first_hash == SENT_HASH && strcmp(words[0], "Sent") == 0)) {
742
+ // debug(D_TC_LOOP, "SENT line '%s'", words[1]);
743
+ if(likely(words[1] && *words[1])) {
744
+ class->bytes = strtoull(words[1], NULL, 10);
745
+ class->updated = 1;
746
+ }
747
+ else {
748
+ class->updated = 0;
749
+ }
750
+
751
+ if(likely(words[3] && *words[3]))
752
+ class->packets = strtoull(words[3], NULL, 10);
753
+
754
+ if(likely(words[6] && *words[6]))
755
+ class->dropped = strtoull(words[6], NULL, 10);
756
+
757
+ if(likely(words[8] && *words[8]))
758
+ class->overlimits = strtoull(words[8], NULL, 10);
759
+
760
+ if(likely(words[10] && *words[10]))
761
+ class->requeues = strtoull(words[8], NULL, 10);
762
+ }
763
+ else if(unlikely(device && class && class->updated && first_hash == LENDED_HASH && strcmp(words[0], "lended:") == 0)) {
764
+ // debug(D_TC_LOOP, "LENDED line '%s'", words[1]);
765
+ if(likely(words[1] && *words[1]))
766
+ class->lended = strtoull(words[1], NULL, 10);
767
+
768
+ if(likely(words[3] && *words[3]))
769
+ class->borrowed = strtoull(words[3], NULL, 10);
770
+
771
+ if(likely(words[5] && *words[5]))
772
+ class->giants = strtoull(words[5], NULL, 10);
773
+ }
774
+ else if(unlikely(device && class && class->updated && first_hash == TOKENS_HASH && strcmp(words[0], "tokens:") == 0)) {
775
+ // debug(D_TC_LOOP, "TOKENS line '%s'", words[1]);
776
+ if(likely(words[1] && *words[1]))
777
+ class->tokens = strtoull(words[1], NULL, 10);
778
+
779
+ if(likely(words[3] && *words[3]))
780
+ class->ctokens = strtoull(words[3], NULL, 10);
781
+ }
782
+ else if(unlikely(device && first_hash == SETDEVICENAME_HASH && strcmp(words[0], "SETDEVICENAME") == 0)) {
783
+ // debug(D_TC_LOOP, "SETDEVICENAME line '%s'", words[1]);
784
+ if(likely(words[1] && *words[1]))
785
+ tc_device_set_device_name(device, words[1]);
786
+ }
787
+ else if(unlikely(device && first_hash == SETDEVICEGROUP_HASH && strcmp(words[0], "SETDEVICEGROUP") == 0)) {
788
+ // debug(D_TC_LOOP, "SETDEVICEGROUP line '%s'", words[1]);
789
+ if(likely(words[1] && *words[1]))
790
+ tc_device_set_device_family(device, words[1]);
791
+ }
792
+ else if(unlikely(device && first_hash == SETCLASSNAME_HASH && strcmp(words[0], "SETCLASSNAME") == 0)) {
793
+ // debug(D_TC_LOOP, "SETCLASSNAME line '%s' '%s'", words[1], words[2]);
794
+ char *id = words[1];
795
+ char *path = words[2];
796
+ if(likely(id && *id && path && *path))
797
+ tc_device_set_class_name(device, id, path);
798
+ }
799
+ else if(unlikely(first_hash == WORKTIME_HASH && strcmp(words[0], "WORKTIME") == 0)) {
800
+ // debug(D_TC_LOOP, "WORKTIME line '%s' '%s'", words[1], words[2]);
801
+ getrusage(RUSAGE_THREAD, &thread);
802
+
803
+ if(unlikely(!stcpu)) stcpu = rrdset_find("netdata.plugin_tc_cpu");
804
+ if(unlikely(!stcpu)) {
805
+ stcpu = rrdset_create("netdata", "plugin_tc_cpu", NULL, "tc.helper", NULL, "NetData TC CPU usage", "milliseconds/s", 135000, rrd_update_every, RRDSET_TYPE_STACKED);
806
+ rrddim_add(stcpu, "user", NULL, 1, 1000, RRDDIM_INCREMENTAL);
807
+ rrddim_add(stcpu, "system", NULL, 1, 1000, RRDDIM_INCREMENTAL);
808
+ }
809
+ else rrdset_next(stcpu);
810
+
811
+ rrddim_set(stcpu, "user" , thread.ru_utime.tv_sec * 1000000ULL + thread.ru_utime.tv_usec);
812
+ rrddim_set(stcpu, "system", thread.ru_stime.tv_sec * 1000000ULL + thread.ru_stime.tv_usec);
813
+ rrdset_done(stcpu);
814
+
815
+ if(unlikely(!sttime)) stcpu = rrdset_find("netdata.plugin_tc_time");
816
+ if(unlikely(!sttime)) {
817
+ sttime = rrdset_create("netdata", "plugin_tc_time", NULL, "tc.helper", NULL, "NetData TC script execution", "milliseconds/run", 135001, rrd_update_every, RRDSET_TYPE_AREA);
818
+ rrddim_add(sttime, "run_time", "run time", 1, 1, RRDDIM_ABSOLUTE);
819
+ }
820
+ else rrdset_next(sttime);
821
+
822
+ rrddim_set(sttime, "run_time", atoll(words[1]));
823
+ rrdset_done(sttime);
824
+
825
+ }
826
#ifdef DETACH_PLUGINS_FROM_NETDATA
827
- else if(unlikely(first_hash == MYPID_HASH && (strcmp(words[0], "MYPID") == 0))) {
828
- // debug(D_TC_LOOP, "MYPID line '%s'", words[1]);
829
- char *id = words[1];
830
- pid_t pid = atol(id);
827
+ else if(unlikely(first_hash == MYPID_HASH && (strcmp(words[0], "MYPID") == 0))) {
828
+ // debug(D_TC_LOOP, "MYPID line '%s'", words[1]);
829
+ char *id = words[1];
830
+ pid_t pid = atol(id);
831
832
- if(likely(pid)) tc_child_pid = pid;
832
+ if(likely(pid)) tc_child_pid = pid;
833
834
- debug(D_TC_LOOP, "TC: Child PID is %d.", tc_child_pid);
835
- }
834
+ debug(D_TC_LOOP, "TC: Child PID is %d.", tc_child_pid);
835
+ }
836
#endif
837
- //else {
838
- // debug(D_TC_LOOP, "IGNORED line");
839
- //}
840
- }
841
-
842
- // fgets() failed or loop broke
843
- int code = mypclose(fp, tc_child_pid);
844
- tc_child_pid = 0;
845
-
846
- if(unlikely(device)) {
847
- // tc_device_free(device);
848
- device = NULL;
849
- class = NULL;
850
- }
851
-
852
- if(unlikely(netdata_exit)) {
853
- tc_device_free_all();
854
- pthread_exit(NULL);
855
- return NULL;
856
- }
857
-
858
- if(code == 1 || code == 127) {
859
- // 1 = DISABLE
860
- // 127 = cannot even run it
861
- error("TC: tc-qos-helper.sh exited with code %d. Disabling it.", code);
862
-
863
- tc_device_free_all();
864
- pthread_exit(NULL);
865
- return NULL;
866
- }
867
-
868
- sleep((unsigned int) rrd_update_every);
869
- }
870
-
871
- pthread_exit(NULL);
872
- return NULL;
837
+ //else {
838
+ // debug(D_TC_LOOP, "IGNORED line");
839
+ //}
840
+ }
841
+
842
+ // fgets() failed or loop broke
843
+ int code = mypclose(fp, tc_child_pid);
844
+ tc_child_pid = 0;
845
+
846
+ if(unlikely(device)) {
847
+ // tc_device_free(device);
848
+ device = NULL;
849
+ class = NULL;
850
+ }
851
+
852
+ if(unlikely(netdata_exit)) {
853
+ tc_device_free_all();
854
+ pthread_exit(NULL);
855
+ return NULL;
856
+ }
857
+
858
+ if(code == 1 || code == 127) {
859
+ // 1 = DISABLE
860
+ // 127 = cannot even run it
861
+ error("TC: tc-qos-helper.sh exited with code %d. Disabling it.", code);
862
+
863
+ tc_device_free_all();
864
+ pthread_exit(NULL);
865
+ return NULL;
866
+ }
867
+
868
+ sleep((unsigned int) rrd_update_every);
869
+ }
870
+
871
+ pthread_exit(NULL);
872
+ return NULL;
873
}
src/plugins_d.c
+517
-517
@@ -5,544 +5,544 @@ struct plugind *pluginsd_root = NULL;
5
#define MAX_WORDS 20
6
7
static inline int pluginsd_space(char c) {
8
- switch(c) {
9
- case ' ':
10
- case '\t':
11
- case '\r':
12
- case '\n':
13
- case '=':
14
- return 1;
15
-
16
- default:
17
- return 0;
18
- }
8
+ switch(c) {
9
+ case ' ':
10
+ case '\t':
11
+ case '\r':
12
+ case '\n':
13
+ case '=':
14
+ return 1;
15
+
16
+ default:
17
+ return 0;
18
+ }
19
}
20
21
static int pluginsd_split_words(char *str, char **words, int max_words) {
22
- char *s = str, quote = 0;
23
- int i = 0, j;
24
-
25
- // skip all white space
26
- while(unlikely(pluginsd_space(*s))) s++;
27
-
28
- // check for quote
29
- if(unlikely(*s == '\'' || *s == '"')) {
30
- quote = *s; // remember the quote
31
- s++; // skip the quote
32
- }
33
-
34
- // store the first word
35
- words[i++] = s;
36
-
37
- // while we have something
38
- while(likely(*s)) {
39
- // if it is escape
40
- if(unlikely(*s == '\\' && s[1])) {
41
- s += 2;
42
- continue;
43
- }
44
-
45
- // if it is quote
46
- else if(unlikely(*s == quote)) {
47
- quote = 0;
48
- *s = ' ';
49
- continue;
50
- }
51
-
52
- // if it is a space
53
- else if(unlikely(quote == 0 && pluginsd_space(*s))) {
54
-
55
- // terminate the word
56
- *s++ = '\0';
57
-
58
- // skip all white space
59
- while(likely(pluginsd_space(*s))) s++;
60
-
61
- // check for quote
62
- if(unlikely(*s == '\'' || *s == '"')) {
63
- quote = *s; // remember the quote
64
- s++; // skip the quote
65
- }
66
-
67
- // if we reached the end, stop
68
- if(unlikely(!*s)) break;
69
-
70
- // store the next word
71
- if(likely(i < max_words)) words[i++] = s;
72
- else break;
73
- }
74
-
75
- // anything else
76
- else s++;
77
- }
78
-
79
- // terminate the words
80
- j = i;
81
- while(likely(j < max_words)) words[j++] = NULL;
82
-
83
- return i;
22
+ char *s = str, quote = 0;
23
+ int i = 0, j;
24
+
25
+ // skip all white space
26
+ while(unlikely(pluginsd_space(*s))) s++;
27
+
28
+ // check for quote
29
+ if(unlikely(*s == '\'' || *s == '"')) {
30
+ quote = *s; // remember the quote
31
+ s++; // skip the quote
32
+ }
33
+
34
+ // store the first word
35
+ words[i++] = s;
36
+
37
+ // while we have something
38
+ while(likely(*s)) {
39
+ // if it is escape
40
+ if(unlikely(*s == '\\' && s[1])) {
41
+ s += 2;
42
+ continue;
43
+ }
44
+
45
+ // if it is quote
46
+ else if(unlikely(*s == quote)) {
47
+ quote = 0;
48
+ *s = ' ';
49
+ continue;
50
+ }
51
+
52
+ // if it is a space
53
+ else if(unlikely(quote == 0 && pluginsd_space(*s))) {
54
+
55
+ // terminate the word
56
+ *s++ = '\0';
57
+
58
+ // skip all white space
59
+ while(likely(pluginsd_space(*s))) s++;
60
+
61
+ // check for quote
62
+ if(unlikely(*s == '\'' || *s == '"')) {
63
+ quote = *s; // remember the quote
64
+ s++; // skip the quote
65
+ }
66
+
67
+ // if we reached the end, stop
68
+ if(unlikely(!*s)) break;
69
+
70
+ // store the next word
71
+ if(likely(i < max_words)) words[i++] = s;
72
+ else break;
73
+ }
74
+
75
+ // anything else
76
+ else s++;
77
+ }
78
+
79
+ // terminate the words
80
+ j = i;
81
+ while(likely(j < max_words)) words[j++] = NULL;
82
+
83
+ return i;
84
}
85
86
87
void *pluginsd_worker_thread(void *arg)
88
{
89
- struct plugind *cd = (struct plugind *)arg;
90
- char line[PLUGINSD_LINE_MAX + 1];
89
+ struct plugind *cd = (struct plugind *)arg;
90
+ char line[PLUGINSD_LINE_MAX + 1];
91
92
#ifdef DETACH_PLUGINS_FROM_NETDATA
93
- unsigned long long usec = 0, susec = 0;
94
- struct timeval last = {0, 0} , now = {0, 0};
93
+ unsigned long long usec = 0, susec = 0;
94
+ struct timeval last = {0, 0} , now = {0, 0};
95
#endif
96
97
- char *words[MAX_WORDS] = { NULL };
98
- uint32_t SET_HASH = simple_hash("SET");
99
- uint32_t BEGIN_HASH = simple_hash("BEGIN");
100
- uint32_t END_HASH = simple_hash("END");
101
- uint32_t FLUSH_HASH = simple_hash("FLUSH");
102
- uint32_t CHART_HASH = simple_hash("CHART");
103
- uint32_t DIMENSION_HASH = simple_hash("DIMENSION");
104
- uint32_t DISABLE_HASH = simple_hash("DISABLE");
97
+ char *words[MAX_WORDS] = { NULL };
98
+ uint32_t SET_HASH = simple_hash("SET");
99
+ uint32_t BEGIN_HASH = simple_hash("BEGIN");
100
+ uint32_t END_HASH = simple_hash("END");
101
+ uint32_t FLUSH_HASH = simple_hash("FLUSH");
102
+ uint32_t CHART_HASH = simple_hash("CHART");
103
+ uint32_t DIMENSION_HASH = simple_hash("DIMENSION");
104
+ uint32_t DISABLE_HASH = simple_hash("DISABLE");
105
#ifdef DETACH_PLUGINS_FROM_NETDATA
106
- uint32_t MYPID_HASH = simple_hash("MYPID");
107
- uint32_t STOPPING_WAKE_ME_UP_PLEASE_HASH = simple_hash("STOPPING_WAKE_ME_UP_PLEASE");
106
+ uint32_t MYPID_HASH = simple_hash("MYPID");
107
+ uint32_t STOPPING_WAKE_ME_UP_PLEASE_HASH = simple_hash("STOPPING_WAKE_ME_UP_PLEASE");
108
#endif
109
110
- size_t count = 0;
111
-
112
- while(likely(1)) {
113
- if(unlikely(netdata_exit)) break;
114
-
115
- FILE *fp = mypopen(cd->cmd, &cd->pid);
116
- if(unlikely(!fp)) {
117
- error("Cannot popen(\"%s\", \"r\").", cd->cmd);
118
- break;
119
- }
120
-
121
- info("PLUGINSD: '%s' running on pid %d", cd->fullfilename, cd->pid);
122
-
123
- RRDSET *st = NULL;
124
- char *s;
125
- uint32_t hash;
126
-
127
- while(likely(fgets(line, PLUGINSD_LINE_MAX, fp) != NULL)) {
128
- if(unlikely(netdata_exit)) break;
129
-
130
- line[PLUGINSD_LINE_MAX] = '\0';
131
-
132
- // debug(D_PLUGINSD, "PLUGINSD: %s: %s", cd->filename, line);
133
-
134
- int w = pluginsd_split_words(line, words, MAX_WORDS);
135
- s = words[0];
136
- if(unlikely(!s || !*s || !w)) {
137
- // debug(D_PLUGINSD, "PLUGINSD: empty line");
138
- continue;
139
- }
140
-
141
- // debug(D_PLUGINSD, "PLUGINSD: words 0='%s' 1='%s' 2='%s' 3='%s' 4='%s' 5='%s' 6='%s' 7='%s' 8='%s' 9='%s'", words[0], words[1], words[2], words[3], words[4], words[5], words[6], words[7], words[8], words[9]);
142
-
143
- hash = simple_hash(s);
144
-
145
- if(likely(hash == SET_HASH && !strcmp(s, "SET"))) {
146
- char *dimension = words[1];
147
- char *value = words[2];
148
-
149
- if(unlikely(!dimension || !*dimension)) {
150
- error("PLUGINSD: '%s' is requesting a SET on chart '%s', without a dimension. Disabling it.", cd->fullfilename, st->id);
151
- cd->enabled = 0;
152
- killpid(cd->pid, SIGTERM);
153
- break;
154
- }
155
-
156
- if(unlikely(!value || !*value)) value = NULL;
157
-
158
- if(unlikely(!st)) {
159
- error("PLUGINSD: '%s' is requesting a SET on dimension %s with value %s, without a BEGIN. Disabling it.", cd->fullfilename, dimension, value?value:"<nothing>");
160
- cd->enabled = 0;
161
- killpid(cd->pid, SIGTERM);
162
- break;
163
- }
164
-
165
- if(unlikely(st->debug)) debug(D_PLUGINSD, "PLUGINSD: '%s' is setting dimension %s/%s to %s", cd->fullfilename, st->id, dimension, value?value:"<nothing>");
166
-
167
- if(value) rrddim_set(st, dimension, strtoll(value, NULL, 0));
168
- }
169
- else if(likely(hash == BEGIN_HASH && !strcmp(s, "BEGIN"))) {
170
- char *id = words[1];
171
- char *microseconds_txt = words[2];
172
-
173
- if(unlikely(!id)) {
174
- error("PLUGINSD: '%s' is requesting a BEGIN without a chart id. Disabling it.", cd->fullfilename);
175
- cd->enabled = 0;
176
- killpid(cd->pid, SIGTERM);
177
- break;
178
- }
179
-
180
- st = rrdset_find(id);
181
- if(unlikely(!st)) {
182
- error("PLUGINSD: '%s' is requesting a BEGIN on chart '%s', which does not exist. Disabling it.", cd->fullfilename, id);
183
- cd->enabled = 0;
184
- killpid(cd->pid, SIGTERM);
185
- break;
186
- }
187
-
188
- if(likely(st->counter_done)) {
189
- unsigned long long microseconds = 0;
190
- if(microseconds_txt && *microseconds_txt) microseconds = strtoull(microseconds_txt, NULL, 10);
191
- if(microseconds) rrdset_next_usec(st, microseconds);
192
- else rrdset_next_plugins(st);
193
- }
194
- }
195
- else if(likely(hash == END_HASH && !strcmp(s, "END"))) {
196
- if(unlikely(!st)) {
197
- error("PLUGINSD: '%s' is requesting an END, without a BEGIN. Disabling it.", cd->fullfilename);
198
- cd->enabled = 0;
199
- killpid(cd->pid, SIGTERM);
200
- break;
201
- }
202
-
203
- if(unlikely(st->debug)) debug(D_PLUGINSD, "PLUGINSD: '%s' is requesting an END on chart %s", cd->fullfilename, st->id);
204
-
205
- rrdset_done(st);
206
- st = NULL;
207
-
208
- count++;
209
- }
210
- else if(likely(hash == FLUSH_HASH && !strcmp(s, "FLUSH"))) {
211
- debug(D_PLUGINSD, "PLUGINSD: '%s' is requesting a FLUSH", cd->fullfilename);
212
- st = NULL;
213
- }
214
- else if(likely(hash == CHART_HASH && !strcmp(s, "CHART"))) {
215
- int noname = 0;
216
- st = NULL;
217
-
218
- if((words[1]) != NULL && (words[2]) != NULL && strcmp(words[1], words[2]) == 0)
219
- noname = 1;
220
-
221
- char *type = words[1];
222
- char *id = NULL;
223
- if(likely(type)) {
224
- id = strchr(type, '.');
225
- if(likely(id)) { *id = '\0'; id++; }
226
- }
227
- char *name = words[2];
228
- char *title = words[3];
229
- char *units = words[4];
230
- char *family = words[5];
231
- char *context = words[6];
232
- char *chart = words[7];
233
- char *priority_s = words[8];
234
- char *update_every_s = words[9];
235
-
236
- if(unlikely(!type || !*type || !id || !*id)) {
237
- error("PLUGINSD: '%s' is requesting a CHART, without a type.id. Disabling it.", cd->fullfilename);
238
- cd->enabled = 0;
239
- killpid(cd->pid, SIGTERM);
240
- break;
241
- }
242
-
243
- int priority = 1000;
244
- if(likely(priority_s)) priority = atoi(priority_s);
245
-
246
- int update_every = cd->update_every;
247
- if(likely(update_every_s)) update_every = atoi(update_every_s);
248
- if(unlikely(!update_every)) update_every = cd->update_every;
249
-
250
- int chart_type = RRDSET_TYPE_LINE;
251
- if(unlikely(chart)) chart_type = rrdset_type_id(chart);
252
-
253
- if(unlikely(noname || !name || !*name || strcasecmp(name, "NULL") == 0 || strcasecmp(name, "(NULL)") == 0)) name = NULL;
254
- if(unlikely(!family || !*family)) family = NULL;
255
- if(unlikely(!context || !*context)) context = NULL;
256
-
257
- st = rrdset_find_bytype(type, id);
258
- if(unlikely(!st)) {
259
- debug(D_PLUGINSD, "PLUGINSD: Creating chart type='%s', id='%s', name='%s', family='%s', context='%s', chart='%s', priority=%d, update_every=%d"
260
- , type, id
261
- , name?name:""
262
- , family?family:""
263
- , context?context:""
264
- , rrdset_type_name(chart_type)
265
- , priority
266
- , update_every
267
- );
268
-
269
- st = rrdset_create(type, id, name, family, context, title, units, priority, update_every, chart_type);
270
- cd->update_every = update_every;
271
- }
272
- else debug(D_PLUGINSD, "PLUGINSD: Chart '%s' already exists. Not adding it again.", st->id);
273
- }
274
- else if(likely(hash == DIMENSION_HASH && !strcmp(s, "DIMENSION"))) {
275
- char *id = words[1];
276
- char *name = words[2];
277
- char *algorithm = words[3];
278
- char *multiplier_s = words[4];
279
- char *divisor_s = words[5];
280
- char *options = words[6];
281
-
282
- if(unlikely(!id || !*id)) {
283
- error("PLUGINSD: '%s' is requesting a DIMENSION, without an id. Disabling it.", cd->fullfilename);
284
- cd->enabled = 0;
285
- killpid(cd->pid, SIGTERM);
286
- break;
287
- }
288
-
289
- if(unlikely(!st)) {
290
- error("PLUGINSD: '%s' is requesting a DIMENSION, without a CHART. Disabling it.", cd->fullfilename);
291
- cd->enabled = 0;
292
- killpid(cd->pid, SIGTERM);
293
- break;
294
- }
295
-
296
- long multiplier = 1;
297
- if(multiplier_s && *multiplier_s) multiplier = strtol(multiplier_s, NULL, 0);
298
- if(unlikely(!multiplier)) multiplier = 1;
299
-
300
- long divisor = 1;
301
- if(likely(divisor_s && *divisor_s)) divisor = strtol(divisor_s, NULL, 0);
302
- if(unlikely(!divisor)) divisor = 1;
303
-
304
- if(unlikely(!algorithm || !*algorithm)) algorithm = "absolute";
305
-
306
- if(unlikely(st->debug)) debug(D_PLUGINSD, "PLUGINSD: Creating dimension in chart %s, id='%s', name='%s', algorithm='%s', multiplier=%ld, divisor=%ld, hidden='%s'"
307
- , st->id
308
- , id
309
- , name?name:""
310
- , rrddim_algorithm_name(rrddim_algorithm_id(algorithm))
311
- , multiplier
312
- , divisor
313
- , options?options:""
314
- );
315
-
316
- RRDDIM *rd = rrddim_find(st, id);
317
- if(unlikely(!rd)) {
318
- rd = rrddim_add(st, id, name, multiplier, divisor, rrddim_algorithm_id(algorithm));
319
- rd->flags = 0x00000000;
320
- if(options && *options) {
321
- if(strstr(options, "hidden") != NULL) rd->flags |= RRDDIM_FLAG_HIDDEN;
322
- if(strstr(options, "noreset") != NULL) rd->flags |= RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS;
323
- if(strstr(options, "nooverflow") != NULL) rd->flags |= RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS;
324
- }
325
- }
326
- else if(unlikely(st->debug)) debug(D_PLUGINSD, "PLUGINSD: dimension %s/%s already exists. Not adding it again.", st->id, id);
327
- }
328
- else if(unlikely(hash == DISABLE_HASH && !strcmp(s, "DISABLE"))) {
329
- error("PLUGINSD: '%s' called DISABLE. Disabling it.", cd->fullfilename);
330
- cd->enabled = 0;
331
- killpid(cd->pid, SIGTERM);
332
- break;
333
- }
110
+ size_t count = 0;
111
+
112
+ while(likely(1)) {
113
+ if(unlikely(netdata_exit)) break;
114
+
115
+ FILE *fp = mypopen(cd->cmd, &cd->pid);
116
+ if(unlikely(!fp)) {
117
+ error("Cannot popen(\"%s\", \"r\").", cd->cmd);
118
+ break;
119
+ }
120
+
121
+ info("PLUGINSD: '%s' running on pid %d", cd->fullfilename, cd->pid);
122
+
123
+ RRDSET *st = NULL;
124
+ char *s;
125
+ uint32_t hash;
126
+
127
+ while(likely(fgets(line, PLUGINSD_LINE_MAX, fp) != NULL)) {
128
+ if(unlikely(netdata_exit)) break;
129
+
130
+ line[PLUGINSD_LINE_MAX] = '\0';
131
+
132
+ // debug(D_PLUGINSD, "PLUGINSD: %s: %s", cd->filename, line);
133
+
134
+ int w = pluginsd_split_words(line, words, MAX_WORDS);
135
+ s = words[0];
136
+ if(unlikely(!s || !*s || !w)) {
137
+ // debug(D_PLUGINSD, "PLUGINSD: empty line");
138
+ continue;
139
+ }
140
+
141
+ // debug(D_PLUGINSD, "PLUGINSD: words 0='%s' 1='%s' 2='%s' 3='%s' 4='%s' 5='%s' 6='%s' 7='%s' 8='%s' 9='%s'", words[0], words[1], words[2], words[3], words[4], words[5], words[6], words[7], words[8], words[9]);
142
+
143
+ hash = simple_hash(s);
144
+
145
+ if(likely(hash == SET_HASH && !strcmp(s, "SET"))) {
146
+ char *dimension = words[1];
147
+ char *value = words[2];
148
+
149
+ if(unlikely(!dimension || !*dimension)) {
150
+ error("PLUGINSD: '%s' is requesting a SET on chart '%s', without a dimension. Disabling it.", cd->fullfilename, st->id);
151
+ cd->enabled = 0;
152
+ killpid(cd->pid, SIGTERM);
153
+ break;
154
+ }
155
+
156
+ if(unlikely(!value || !*value)) value = NULL;
157
+
158
+ if(unlikely(!st)) {
159
+ error("PLUGINSD: '%s' is requesting a SET on dimension %s with value %s, without a BEGIN. Disabling it.", cd->fullfilename, dimension, value?value:"<nothing>");
160
+ cd->enabled = 0;
161
+ killpid(cd->pid, SIGTERM);
162
+ break;
163
+ }
164
+
165
+ if(unlikely(st->debug)) debug(D_PLUGINSD, "PLUGINSD: '%s' is setting dimension %s/%s to %s", cd->fullfilename, st->id, dimension, value?value:"<nothing>");
166
+
167
+ if(value) rrddim_set(st, dimension, strtoll(value, NULL, 0));
168
+ }
169
+ else if(likely(hash == BEGIN_HASH && !strcmp(s, "BEGIN"))) {
170
+ char *id = words[1];
171
+ char *microseconds_txt = words[2];
172
+
173
+ if(unlikely(!id)) {
174
+ error("PLUGINSD: '%s' is requesting a BEGIN without a chart id. Disabling it.", cd->fullfilename);
175
+ cd->enabled = 0;
176
+ killpid(cd->pid, SIGTERM);
177
+ break;
178
+ }
179
+
180
+ st = rrdset_find(id);
181
+ if(unlikely(!st)) {
182
+ error("PLUGINSD: '%s' is requesting a BEGIN on chart '%s', which does not exist. Disabling it.", cd->fullfilename, id);
183
+ cd->enabled = 0;
184
+ killpid(cd->pid, SIGTERM);
185
+ break;
186
+ }
187
+
188
+ if(likely(st->counter_done)) {
189
+ unsigned long long microseconds = 0;
190
+ if(microseconds_txt && *microseconds_txt) microseconds = strtoull(microseconds_txt, NULL, 10);
191
+ if(microseconds) rrdset_next_usec(st, microseconds);
192
+ else rrdset_next_plugins(st);
193
+ }
194
+ }
195
+ else if(likely(hash == END_HASH && !strcmp(s, "END"))) {
196
+ if(unlikely(!st)) {
197
+ error("PLUGINSD: '%s' is requesting an END, without a BEGIN. Disabling it.", cd->fullfilename);
198
+ cd->enabled = 0;
199
+ killpid(cd->pid, SIGTERM);
200
+ break;
201
+ }
202
+
203
+ if(unlikely(st->debug)) debug(D_PLUGINSD, "PLUGINSD: '%s' is requesting an END on chart %s", cd->fullfilename, st->id);
204
+
205
+ rrdset_done(st);
206
+ st = NULL;
207
+
208
+ count++;
209
+ }
210
+ else if(likely(hash == FLUSH_HASH && !strcmp(s, "FLUSH"))) {
211
+ debug(D_PLUGINSD, "PLUGINSD: '%s' is requesting a FLUSH", cd->fullfilename);
212
+ st = NULL;
213
+ }
214
+ else if(likely(hash == CHART_HASH && !strcmp(s, "CHART"))) {
215
+ int noname = 0;
216
+ st = NULL;
217
+
218
+ if((words[1]) != NULL && (words[2]) != NULL && strcmp(words[1], words[2]) == 0)
219
+ noname = 1;
220
+
221
+ char *type = words[1];
222
+ char *id = NULL;
223
+ if(likely(type)) {
224
+ id = strchr(type, '.');
225
+ if(likely(id)) { *id = '\0'; id++; }
226
+ }
227
+ char *name = words[2];
228
+ char *title = words[3];
229
+ char *units = words[4];
230
+ char *family = words[5];
231
+ char *context = words[6];
232
+ char *chart = words[7];
233
+ char *priority_s = words[8];
234
+ char *update_every_s = words[9];
235
+
236
+ if(unlikely(!type || !*type || !id || !*id)) {
237
+ error("PLUGINSD: '%s' is requesting a CHART, without a type.id. Disabling it.", cd->fullfilename);
238
+ cd->enabled = 0;
239
+ killpid(cd->pid, SIGTERM);
240
+ break;
241
+ }
242
+
243
+ int priority = 1000;
244
+ if(likely(priority_s)) priority = atoi(priority_s);
245
+
246
+ int update_every = cd->update_every;
247
+ if(likely(update_every_s)) update_every = atoi(update_every_s);
248
+ if(unlikely(!update_every)) update_every = cd->update_every;
249
+
250
+ int chart_type = RRDSET_TYPE_LINE;
251
+ if(unlikely(chart)) chart_type = rrdset_type_id(chart);
252
+
253
+ if(unlikely(noname || !name || !*name || strcasecmp(name, "NULL") == 0 || strcasecmp(name, "(NULL)") == 0)) name = NULL;
254
+ if(unlikely(!family || !*family)) family = NULL;
255
+ if(unlikely(!context || !*context)) context = NULL;
256
+
257
+ st = rrdset_find_bytype(type, id);
258
+ if(unlikely(!st)) {
259
+ debug(D_PLUGINSD, "PLUGINSD: Creating chart type='%s', id='%s', name='%s', family='%s', context='%s', chart='%s', priority=%d, update_every=%d"
260
+ , type, id
261
+ , name?name:""
262
+ , family?family:""
263
+ , context?context:""
264
+ , rrdset_type_name(chart_type)
265
+ , priority
266
+ , update_every
267
+ );
268
+
269
+ st = rrdset_create(type, id, name, family, context, title, units, priority, update_every, chart_type);
270
+ cd->update_every = update_every;
271
+ }
272
+ else debug(D_PLUGINSD, "PLUGINSD: Chart '%s' already exists. Not adding it again.", st->id);
273
+ }
274
+ else if(likely(hash == DIMENSION_HASH && !strcmp(s, "DIMENSION"))) {
275
+ char *id = words[1];
276
+ char *name = words[2];
277
+ char *algorithm = words[3];
278
+ char *multiplier_s = words[4];
279
+ char *divisor_s = words[5];
280
+ char *options = words[6];
281
+
282
+ if(unlikely(!id || !*id)) {
283
+ error("PLUGINSD: '%s' is requesting a DIMENSION, without an id. Disabling it.", cd->fullfilename);
284
+ cd->enabled = 0;
285
+ killpid(cd->pid, SIGTERM);
286
+ break;
287
+ }
288
+
289
+ if(unlikely(!st)) {
290
+ error("PLUGINSD: '%s' is requesting a DIMENSION, without a CHART. Disabling it.", cd->fullfilename);
291
+ cd->enabled = 0;
292
+ killpid(cd->pid, SIGTERM);
293
+ break;
294
+ }
295
+
296
+ long multiplier = 1;
297
+ if(multiplier_s && *multiplier_s) multiplier = strtol(multiplier_s, NULL, 0);
298
+ if(unlikely(!multiplier)) multiplier = 1;
299
+
300
+ long divisor = 1;
301
+ if(likely(divisor_s && *divisor_s)) divisor = strtol(divisor_s, NULL, 0);
302
+ if(unlikely(!divisor)) divisor = 1;
303
+
304
+ if(unlikely(!algorithm || !*algorithm)) algorithm = "absolute";
305
+
306
+ if(unlikely(st->debug)) debug(D_PLUGINSD, "PLUGINSD: Creating dimension in chart %s, id='%s', name='%s', algorithm='%s', multiplier=%ld, divisor=%ld, hidden='%s'"
307
+ , st->id
308
+ , id
309
+ , name?name:""
310
+ , rrddim_algorithm_name(rrddim_algorithm_id(algorithm))
311
+ , multiplier
312
+ , divisor
313
+ , options?options:""
314
+ );
315
+
316
+ RRDDIM *rd = rrddim_find(st, id);
317
+ if(unlikely(!rd)) {
318
+ rd = rrddim_add(st, id, name, multiplier, divisor, rrddim_algorithm_id(algorithm));
319
+ rd->flags = 0x00000000;
320
+ if(options && *options) {
321
+ if(strstr(options, "hidden") != NULL) rd->flags |= RRDDIM_FLAG_HIDDEN;
322
+ if(strstr(options, "noreset") != NULL) rd->flags |= RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS;
323
+ if(strstr(options, "nooverflow") != NULL) rd->flags |= RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS;
324
+ }
325
+ }
326
+ else if(unlikely(st->debug)) debug(D_PLUGINSD, "PLUGINSD: dimension %s/%s already exists. Not adding it again.", st->id, id);
327
+ }
328
+ else if(unlikely(hash == DISABLE_HASH && !strcmp(s, "DISABLE"))) {
329
+ error("PLUGINSD: '%s' called DISABLE. Disabling it.", cd->fullfilename);
330
+ cd->enabled = 0;
331
+ killpid(cd->pid, SIGTERM);
332
+ break;
333
+ }
334
#ifdef DETACH_PLUGINS_FROM_NETDATA
335
- else if(likely(hash == MYPID_HASH && !strcmp(s, "MYPID"))) {
336
- char *pid_s = words[1];
337
- pid_t pid = strtod(pid_s, NULL, 0);
338
-
339
- if(likely(pid)) cd->pid = pid;
340
- debug(D_PLUGINSD, "PLUGINSD: %s is on pid %d", cd->id, cd->pid);
341
- }
342
- else if(likely(hash == STOPPING_WAKE_ME_UP_PLEASE_HASH && !strcmp(s, "STOPPING_WAKE_ME_UP_PLEASE"))) {
343
- error("PLUGINSD: '%s' (pid %d) called STOPPING_WAKE_ME_UP_PLEASE.", cd->fullfilename, cd->pid);
344
-
345
- gettimeofday(&now, NULL);
346
- if(unlikely(!usec && !susec)) {
347
- // our first run
348
- susec = cd->rrd_update_every * 1000000ULL;
349
- }
350
- else {
351
- // second+ run
352
- usec = usecdiff(&now, &last) - susec;
353
- error("PLUGINSD: %s last loop took %llu usec (worked for %llu, sleeped for %llu).\n", cd->fullfilename, usec + susec, usec, susec);
354
- if(unlikely(usec < (rrd_update_every * 1000000ULL / 2ULL))) susec = (rrd_update_every * 1000000ULL) - usec;
355
- else susec = rrd_update_every * 1000000ULL / 2ULL;
356
- }
357
-
358
- error("PLUGINSD: %s sleeping for %llu. Will kill with SIGCONT pid %d to wake it up.\n", cd->fullfilename, susec, cd->pid);
359
- usleep(susec);
360
- killpid(cd->pid, SIGCONT);
361
- bcopy(&now, &last, sizeof(struct timeval));
362
- break;
363
- }
335
+ else if(likely(hash == MYPID_HASH && !strcmp(s, "MYPID"))) {
336
+ char *pid_s = words[1];
337
+ pid_t pid = strtod(pid_s, NULL, 0);
338
+
339
+ if(likely(pid)) cd->pid = pid;
340
+ debug(D_PLUGINSD, "PLUGINSD: %s is on pid %d", cd->id, cd->pid);
341
+ }
342
+ else if(likely(hash == STOPPING_WAKE_ME_UP_PLEASE_HASH && !strcmp(s, "STOPPING_WAKE_ME_UP_PLEASE"))) {
343
+ error("PLUGINSD: '%s' (pid %d) called STOPPING_WAKE_ME_UP_PLEASE.", cd->fullfilename, cd->pid);
344
+
345
+ gettimeofday(&now, NULL);
346
+ if(unlikely(!usec && !susec)) {
347
+ // our first run
348
+ susec = cd->rrd_update_every * 1000000ULL;
349
+ }
350
+ else {
351
+ // second+ run
352
+ usec = usecdiff(&now, &last) - susec;
353
+ error("PLUGINSD: %s last loop took %llu usec (worked for %llu, sleeped for %llu).\n", cd->fullfilename, usec + susec, usec, susec);
354
+ if(unlikely(usec < (rrd_update_every * 1000000ULL / 2ULL))) susec = (rrd_update_every * 1000000ULL) - usec;
355
+ else susec = rrd_update_every * 1000000ULL / 2ULL;
356
+ }
357
+
358
+ error("PLUGINSD: %s sleeping for %llu. Will kill with SIGCONT pid %d to wake it up.\n", cd->fullfilename, susec, cd->pid);
359
+ usleep(susec);
360
+ killpid(cd->pid, SIGCONT);
361
+ bcopy(&now, &last, sizeof(struct timeval));
362
+ break;
363
+ }
364
#endif
365
- else {
366
- error("PLUGINSD: '%s' is sending command '%s' which is not known by netdata. Disabling it.", cd->fullfilename, s);
367
- cd->enabled = 0;
368
- killpid(cd->pid, SIGTERM);
369
- break;
370
- }
371
- }
372
- if(likely(count)) {
373
- cd->successful_collections += count;
374
- cd->serial_failures = 0;
375
- }
376
- else
377
- cd->serial_failures++;
378
-
379
- info("PLUGINSD: '%s' on pid %d stopped after %zu successful data collections (ENDs).", cd->fullfilename, cd->pid, count);
380
-
381
- // get the return code
382
- int code = mypclose(fp, cd->pid);
383
-
384
- if(netdata_exit) {
385
- cd->pid = 0;
386
- cd->enabled = 0;
387
- cd->obsolete = 1;
388
- pthread_exit(NULL);
389
- return NULL;
390
- }
391
-
392
- if(code != 0) {
393
- // the plugin reports failure
394
-
395
- if(likely(!cd->successful_collections)) {
396
- // nothing collected - disable it
397
- error("PLUGINSD: '%s' exited with error code %d. Disabling it.", cd->fullfilename, code);
398
- cd->enabled = 0;
399
- }
400
- else {
401
- // we have collected something
402
-
403
- if(likely(cd->serial_failures <= 10)) {
404
- error("PLUGINSD: '%s' exited with error code %d, but has given useful output in the past (%zu times). Waiting a bit before starting it again.", cd->fullfilename, code, cd->successful_collections);
405
- sleep((unsigned int) (cd->update_every * 10));
406
- }
407
- else {
408
- error("PLUGINSD: '%s' exited with error code %d, but has given useful output in the past (%zu times). We tried %zu times to restart it, but it failed to generate data. Disabling it.", cd->fullfilename, code, cd->successful_collections, cd->serial_failures);
409
- cd->enabled = 0;
410
- }
411
- }
412
- }
413
- else {
414
- // the plugin reports success
415
-
416
- if(unlikely(!cd->successful_collections)) {
417
- // we have collected nothing so far
418
-
419
- if(likely(cd->serial_failures <= 10)) {
420
- error("PLUGINSD: '%s' (pid %d) does not generate useful output but it reports success (exits with 0). Waiting a bit before starting it again.", cd->fullfilename, cd->pid);
421
- sleep((unsigned int) (cd->update_every * 10));
422
- }
423
- else {
424
- error("PLUGINSD: '%s' (pid %d) does not generate useful output, although it reports success (exits with 0), but we have tried %zu times to collect something. Disabling it.", cd->fullfilename, cd->pid, cd->serial_failures);
425
- cd->enabled = 0;
426
- }
427
- }
428
- else
429
- sleep((unsigned int) cd->update_every);
430
- }
431
- cd->pid = 0;
432
-
433
- if(unlikely(!cd->enabled))
434
- break;
435
- }
436
-
437
- cd->obsolete = 1;
438
- pthread_exit(NULL);
439
- return NULL;
365
+ else {
366
+ error("PLUGINSD: '%s' is sending command '%s' which is not known by netdata. Disabling it.", cd->fullfilename, s);
367
+ cd->enabled = 0;
368
+ killpid(cd->pid, SIGTERM);
369
+ break;
370
+ }
371
+ }
372
+ if(likely(count)) {
373
+ cd->successful_collections += count;
374
+ cd->serial_failures = 0;
375
+ }
376
+ else
377
+ cd->serial_failures++;
378
+
379
+ info("PLUGINSD: '%s' on pid %d stopped after %zu successful data collections (ENDs).", cd->fullfilename, cd->pid, count);
380
+
381
+ // get the return code
382
+ int code = mypclose(fp, cd->pid);
383
+
384
+ if(netdata_exit) {
385
+ cd->pid = 0;
386
+ cd->enabled = 0;
387
+ cd->obsolete = 1;
388
+ pthread_exit(NULL);
389
+ return NULL;
390
+ }
391
+
392
+ if(code != 0) {
393
+ // the plugin reports failure
394
+
395
+ if(likely(!cd->successful_collections)) {
396
+ // nothing collected - disable it
397
+ error("PLUGINSD: '%s' exited with error code %d. Disabling it.", cd->fullfilename, code);
398
+ cd->enabled = 0;
399
+ }
400
+ else {
401
+ // we have collected something
402
+
403
+ if(likely(cd->serial_failures <= 10)) {
404
+ error("PLUGINSD: '%s' exited with error code %d, but has given useful output in the past (%zu times). Waiting a bit before starting it again.", cd->fullfilename, code, cd->successful_collections);
405
+ sleep((unsigned int) (cd->update_every * 10));
406
+ }
407
+ else {
408
+ error("PLUGINSD: '%s' exited with error code %d, but has given useful output in the past (%zu times). We tried %zu times to restart it, but it failed to generate data. Disabling it.", cd->fullfilename, code, cd->successful_collections, cd->serial_failures);
409
+ cd->enabled = 0;
410
+ }
411
+ }
412
+ }
413
+ else {
414
+ // the plugin reports success
415
+
416
+ if(unlikely(!cd->successful_collections)) {
417
+ // we have collected nothing so far
418
+
419
+ if(likely(cd->serial_failures <= 10)) {
420
+ error("PLUGINSD: '%s' (pid %d) does not generate useful output but it reports success (exits with 0). Waiting a bit before starting it again.", cd->fullfilename, cd->pid);
421
+ sleep((unsigned int) (cd->update_every * 10));
422
+ }
423
+ else {
424
+ error("PLUGINSD: '%s' (pid %d) does not generate useful output, although it reports success (exits with 0), but we have tried %zu times to collect something. Disabling it.", cd->fullfilename, cd->pid, cd->serial_failures);
425
+ cd->enabled = 0;
426
+ }
427
+ }
428
+ else
429
+ sleep((unsigned int) cd->update_every);
430
+ }
431
+ cd->pid = 0;
432
+
433
+ if(unlikely(!cd->enabled))
434
+ break;
435
+ }
436
+
437
+ cd->obsolete = 1;
438
+ pthread_exit(NULL);
439
+ return NULL;
440
}
441
442
void *pluginsd_main(void *ptr)
443
{
444
- if(ptr) { ; }
444
+ if(ptr) { ; }
445
446
- info("PLUGINS.D thread created with task id %d", gettid());
447
-
448
- if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
449
- error("Cannot set pthread cancel type to DEFERRED.");
450
-
451
- if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
452
- error("Cannot set pthread cancel state to ENABLE.");
453
-
454
- char *dir_name = config_get("plugins", "plugins directory", PLUGINS_DIR);
455
- int automatic_run = config_get_boolean("plugins", "enable running new plugins", 1);
456
- int scan_frequency = (int) config_get_number("plugins", "check for new plugins every", 60);
457
- DIR *dir = NULL;
458
- struct dirent *file = NULL;
459
- struct plugind *cd;
460
-
461
- // enable the apps plugin by default
462
- // config_get_boolean("plugins", "apps", 1);
463
-
464
- if(scan_frequency < 1) scan_frequency = 1;
465
-
466
- while(likely(1)) {
467
- if(unlikely(netdata_exit)) break;
468
-
469
- dir = opendir(dir_name);
470
- if(unlikely(!dir)) {
471
- error("Cannot open directory '%s'.", dir_name);
472
- pthread_exit(NULL);
473
- return NULL;
474
- }
475
-
476
- while(likely((file = readdir(dir)))) {
477
- if(unlikely(netdata_exit)) break;
478
-
479
- debug(D_PLUGINSD, "PLUGINSD: Examining file '%s'", file->d_name);
480
-
481
- if(unlikely(strcmp(file->d_name, ".") == 0 || strcmp(file->d_name, "..") == 0)) continue;
482
-
483
- int len = (int) strlen(file->d_name);
484
- if(unlikely(len <= (int)PLUGINSD_FILE_SUFFIX_LEN)) continue;
485
- if(unlikely(strcmp(PLUGINSD_FILE_SUFFIX, &file->d_name[len - (int)PLUGINSD_FILE_SUFFIX_LEN]) != 0)) {
486
- debug(D_PLUGINSD, "PLUGINSD: File '%s' does not end in '%s'.", file->d_name, PLUGINSD_FILE_SUFFIX);
487
- continue;
488
- }
489
-
490
- char pluginname[CONFIG_MAX_NAME + 1];
491
- snprintfz(pluginname, CONFIG_MAX_NAME, "%.*s", (int)(len - PLUGINSD_FILE_SUFFIX_LEN), file->d_name);
492
- int enabled = config_get_boolean("plugins", pluginname, automatic_run);
493
-
494
- if(unlikely(!enabled)) {
495
- debug(D_PLUGINSD, "PLUGINSD: plugin '%s' is not enabled", file->d_name);
496
- continue;
497
- }
498
-
499
- // check if it runs already
500
- for(cd = pluginsd_root ; likely(cd) ; cd = cd->next) {
501
- if(unlikely(strcmp(cd->filename, file->d_name) == 0)) break;
502
- }
503
- if(likely(cd && !cd->obsolete)) {
504
- debug(D_PLUGINSD, "PLUGINSD: plugin '%s' is already running", cd->filename);
505
- continue;
506
- }
507
-
508
- // it is not running
509
- // allocate a new one, or use the obsolete one
510
- if(unlikely(!cd)) {
511
- cd = callocz(sizeof(struct plugind), 1);
512
-
513
- snprintfz(cd->id, CONFIG_MAX_NAME, "plugin:%s", pluginname);
514
-
515
- strncpyz(cd->filename, file->d_name, FILENAME_MAX);
516
- snprintfz(cd->fullfilename, FILENAME_MAX, "%s/%s", dir_name, cd->filename);
517
-
518
- cd->enabled = enabled;
519
- cd->update_every = (int) config_get_number(cd->id, "update every", rrd_update_every);
520
- cd->started_t = time(NULL);
521
-
522
- char *def = "";
523
- snprintfz(cd->cmd, PLUGINSD_CMD_MAX, "exec %s %d %s", cd->fullfilename, cd->update_every, config_get(cd->id, "command options", def));
524
-
525
- // link it
526
- if(likely(pluginsd_root)) cd->next = pluginsd_root;
527
- pluginsd_root = cd;
528
- }
529
- cd->obsolete = 0;
530
-
531
- if(unlikely(!cd->enabled)) continue;
532
-
533
- // spawn a new thread for it
534
- if(unlikely(pthread_create(&cd->thread, NULL, pluginsd_worker_thread, cd) != 0)) {
535
- error("PLUGINSD: failed to create new thread for plugin '%s'.", cd->filename);
536
- cd->obsolete = 1;
537
- }
538
- else if(unlikely(pthread_detach(cd->thread) != 0))
539
- error("PLUGINSD: Cannot request detach of newly created thread for plugin '%s'.", cd->filename);
540
- }
541
-
542
- closedir(dir);
543
- sleep((unsigned int) scan_frequency);
544
- }
446
+ info("PLUGINS.D thread created with task id %d", gettid());
447
+
448
+ if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
449
+ error("Cannot set pthread cancel type to DEFERRED.");
450
+
451
+ if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
452
+ error("Cannot set pthread cancel state to ENABLE.");
453
+
454
+ char *dir_name = config_get("plugins", "plugins directory", PLUGINS_DIR);
455
+ int automatic_run = config_get_boolean("plugins", "enable running new plugins", 1);
456
+ int scan_frequency = (int) config_get_number("plugins", "check for new plugins every", 60);
457
+ DIR *dir = NULL;
458
+ struct dirent *file = NULL;
459
+ struct plugind *cd;
460
+
461
+ // enable the apps plugin by default
462
+ // config_get_boolean("plugins", "apps", 1);
463
+
464
+ if(scan_frequency < 1) scan_frequency = 1;
465
+
466
+ while(likely(1)) {
467
+ if(unlikely(netdata_exit)) break;
468
+
469
+ dir = opendir(dir_name);
470
+ if(unlikely(!dir)) {
471
+ error("Cannot open directory '%s'.", dir_name);
472
+ pthread_exit(NULL);
473
+ return NULL;
474
+ }
475
+
476
+ while(likely((file = readdir(dir)))) {
477
+ if(unlikely(netdata_exit)) break;
478
+
479
+ debug(D_PLUGINSD, "PLUGINSD: Examining file '%s'", file->d_name);
480
+
481
+ if(unlikely(strcmp(file->d_name, ".") == 0 || strcmp(file->d_name, "..") == 0)) continue;
482
+
483
+ int len = (int) strlen(file->d_name);
484
+ if(unlikely(len <= (int)PLUGINSD_FILE_SUFFIX_LEN)) continue;
485
+ if(unlikely(strcmp(PLUGINSD_FILE_SUFFIX, &file->d_name[len - (int)PLUGINSD_FILE_SUFFIX_LEN]) != 0)) {
486
+ debug(D_PLUGINSD, "PLUGINSD: File '%s' does not end in '%s'.", file->d_name, PLUGINSD_FILE_SUFFIX);
487
+ continue;
488
+ }
489
+
490
+ char pluginname[CONFIG_MAX_NAME + 1];
491
+ snprintfz(pluginname, CONFIG_MAX_NAME, "%.*s", (int)(len - PLUGINSD_FILE_SUFFIX_LEN), file->d_name);
492
+ int enabled = config_get_boolean("plugins", pluginname, automatic_run);
493
+
494
+ if(unlikely(!enabled)) {
495
+ debug(D_PLUGINSD, "PLUGINSD: plugin '%s' is not enabled", file->d_name);
496
+ continue;
497
+ }
498
+
499
+ // check if it runs already
500
+ for(cd = pluginsd_root ; likely(cd) ; cd = cd->next) {
501
+ if(unlikely(strcmp(cd->filename, file->d_name) == 0)) break;
502
+ }
503
+ if(likely(cd && !cd->obsolete)) {
504
+ debug(D_PLUGINSD, "PLUGINSD: plugin '%s' is already running", cd->filename);
505
+ continue;
506
+ }
507
+
508
+ // it is not running
509
+ // allocate a new one, or use the obsolete one
510
+ if(unlikely(!cd)) {
511
+ cd = callocz(sizeof(struct plugind), 1);
512
+
513
+ snprintfz(cd->id, CONFIG_MAX_NAME, "plugin:%s", pluginname);
514
+
515
+ strncpyz(cd->filename, file->d_name, FILENAME_MAX);
516
+ snprintfz(cd->fullfilename, FILENAME_MAX, "%s/%s", dir_name, cd->filename);
517
+
518
+ cd->enabled = enabled;
519
+ cd->update_every = (int) config_get_number(cd->id, "update every", rrd_update_every);
520
+ cd->started_t = time(NULL);
521
+
522
+ char *def = "";
523
+ snprintfz(cd->cmd, PLUGINSD_CMD_MAX, "exec %s %d %s", cd->fullfilename, cd->update_every, config_get(cd->id, "command options", def));
524
+
525
+ // link it
526
+ if(likely(pluginsd_root)) cd->next = pluginsd_root;
527
+ pluginsd_root = cd;
528
+ }
529
+ cd->obsolete = 0;
530
+
531
+ if(unlikely(!cd->enabled)) continue;
532
+
533
+ // spawn a new thread for it
534
+ if(unlikely(pthread_create(&cd->thread, NULL, pluginsd_worker_thread, cd) != 0)) {
535
+ error("PLUGINSD: failed to create new thread for plugin '%s'.", cd->filename);
536
+ cd->obsolete = 1;
537
+ }
538
+ else if(unlikely(pthread_detach(cd->thread) != 0))
539
+ error("PLUGINSD: Cannot request detach of newly created thread for plugin '%s'.", cd->filename);
540
+ }
541
+
542
+ closedir(dir);
543
+ sleep((unsigned int) scan_frequency);
544
+ }
545
546
- pthread_exit(NULL);
547
- return NULL;
546
+ pthread_exit(NULL);
547
+ return NULL;
548
}
src/plugins_d.h
+15
-15
@@ -7,28 +7,28 @@
7
#define PLUGINSD_LINE_MAX 1024
8
9
struct plugind {
10
- char id[CONFIG_MAX_NAME+1]; // config node id
10
+ char id[CONFIG_MAX_NAME+1]; // config node id
11
12
- char filename[FILENAME_MAX+1]; // just the filename
13
- char fullfilename[FILENAME_MAX+1]; // with path
14
- char cmd[PLUGINSD_CMD_MAX+1]; // the command that is executes
12
+ char filename[FILENAME_MAX+1]; // just the filename
13
+ char fullfilename[FILENAME_MAX+1]; // with path
14
+ char cmd[PLUGINSD_CMD_MAX+1]; // the command that is executes
15
16
- pid_t pid;
17
- pthread_t thread;
16
+ pid_t pid;
17
+ pthread_t thread;
18
19
- size_t successful_collections; // the number of times we have seen
20
- // values collected from this plugin
19
+ size_t successful_collections; // the number of times we have seen
20
+ // values collected from this plugin
21
22
- size_t serial_failures; // the number of times the plugin started
23
- // without collecting values
22
+ size_t serial_failures; // the number of times the plugin started
23
+ // without collecting values
24
25
- int update_every; // the plugin default data collection frequency
26
- int obsolete; // do not touch this structure after setting this to 1
27
- int enabled; // if this is enabled or not
25
+ int update_every; // the plugin default data collection frequency
26
+ int obsolete; // do not touch this structure after setting this to 1
27
+ int enabled; // if this is enabled or not
28
29
- time_t started_t;
29
+ time_t started_t;
30
31
- struct plugind *next;
31
+ struct plugind *next;
32
};
33
34
extern struct plugind *pluginsd_root;
src/popen.c
+152
-152
@@ -2,42 +2,42 @@
2
3
/*
4
struct mypopen {
5
- pid_t pid;
6
- FILE *fp;
7
- struct mypopen *next;
8
- struct mypopen *prev;
5
+ pid_t pid;
6
+ FILE *fp;
7
+ struct mypopen *next;
8
+ struct mypopen *prev;
9
};
10
11
static struct mypopen *mypopen_root = NULL;
12
13
static void mypopen_add(FILE *fp, pid_t *pid) {
14
- struct mypopen *mp = malloc(sizeof(struct mypopen));
15
- if(!mp) {
16
- fatal("Cannot allocate %zu bytes", sizeof(struct mypopen))
17
- return;
18
- }
19
-
20
- mp->fp = fp;
21
- mp->pid = pid;
22
- mp->next = popen_root;
23
- mp->prev = NULL;
24
- if(mypopen_root) mypopen_root->prev = mp;
25
- mypopen_root = mp;
14
+ struct mypopen *mp = malloc(sizeof(struct mypopen));
15
+ if(!mp) {
16
+ fatal("Cannot allocate %zu bytes", sizeof(struct mypopen))
17
+ return;
18
+ }
19
+
20
+ mp->fp = fp;
21
+ mp->pid = pid;
22
+ mp->next = popen_root;
23
+ mp->prev = NULL;
24
+ if(mypopen_root) mypopen_root->prev = mp;
25
+ mypopen_root = mp;
26
}
27
28
static void mypopen_del(FILE *fp) {
29
- struct mypopen *mp;
30
-
31
- for(mp = mypopen_root; mp; mp = mp->next)
32
- if(mp->fd == fp) break;
33
-
34
- if(!mp) error("Cannot find mypopen() file pointer in open childs.");
35
- else {
36
- if(mp->next) mp->next->prev = mp->prev;
37
- if(mp->prev) mp->prev->next = mp->next;
38
- if(mypopen_root == mp) mypopen_root = mp->next;
39
- free(mp);
40
- }
29
+ struct mypopen *mp;
30
+
31
+ for(mp = mypopen_root; mp; mp = mp->next)
32
+ if(mp->fd == fp) break;
33
+
34
+ if(!mp) error("Cannot find mypopen() file pointer in open childs.");
35
+ else {
36
+ if(mp->next) mp->next->prev = mp->prev;
37
+ if(mp->prev) mp->prev->next = mp->next;
38
+ if(mypopen_root == mp) mypopen_root = mp->next;
39
+ free(mp);
40
+ }
41
}
42
*/
43
#define PIPE_READ 0
@@ -45,141 +45,141 @@ static void mypopen_del(FILE *fp) {
45
46
FILE *mypopen(const char *command, pid_t *pidptr)
47
{
48
- int pipefd[2];
49
-
50
- if(pipe(pipefd) == -1) return NULL;
51
-
52
- int pid = fork();
53
- if(pid == -1) {
54
- close(pipefd[PIPE_READ]);
55
- close(pipefd[PIPE_WRITE]);
56
- return NULL;
57
- }
58
- if(pid != 0) {
59
- // the parent
60
- *pidptr = pid;
61
- close(pipefd[PIPE_WRITE]);
62
- FILE *fp = fdopen(pipefd[PIPE_READ], "r");
63
- /*mypopen_add(fp, pid);*/
64
- return(fp);
65
- }
66
- // the child
67
-
68
- // close all files
69
- int i;
70
- for(i = (int) (sysconf(_SC_OPEN_MAX) - 1); i > 0; i--)
71
- if(i != STDIN_FILENO && i != STDERR_FILENO && i != pipefd[PIPE_WRITE]) close(i);
72
-
73
- // move the pipe to stdout
74
- if(pipefd[PIPE_WRITE] != STDOUT_FILENO) {
75
- dup2(pipefd[PIPE_WRITE], STDOUT_FILENO);
76
- close(pipefd[PIPE_WRITE]);
77
- }
48
+ int pipefd[2];
49
+
50
+ if(pipe(pipefd) == -1) return NULL;
51
+
52
+ int pid = fork();
53
+ if(pid == -1) {
54
+ close(pipefd[PIPE_READ]);
55
+ close(pipefd[PIPE_WRITE]);
56
+ return NULL;
57
+ }
58
+ if(pid != 0) {
59
+ // the parent
60
+ *pidptr = pid;
61
+ close(pipefd[PIPE_WRITE]);
62
+ FILE *fp = fdopen(pipefd[PIPE_READ], "r");
63
+ /*mypopen_add(fp, pid);*/
64
+ return(fp);
65
+ }
66
+ // the child
67
+
68
+ // close all files
69
+ int i;
70
+ for(i = (int) (sysconf(_SC_OPEN_MAX) - 1); i > 0; i--)
71
+ if(i != STDIN_FILENO && i != STDERR_FILENO && i != pipefd[PIPE_WRITE]) close(i);
72
+
73
+ // move the pipe to stdout
74
+ if(pipefd[PIPE_WRITE] != STDOUT_FILENO) {
75
+ dup2(pipefd[PIPE_WRITE], STDOUT_FILENO);
76
+ close(pipefd[PIPE_WRITE]);
77
+ }
78
79
#ifdef DETACH_PLUGINS_FROM_NETDATA
80
- // this was an attempt to detach the child and use the suspend mode charts.d
81
- // unfortunatelly it does not work as expected.
80
+ // this was an attempt to detach the child and use the suspend mode charts.d
81
+ // unfortunatelly it does not work as expected.
82
83
- // fork again to become session leader
84
- pid = fork();
85
- if(pid == -1)
86
- error("pre-execution of command '%s' on pid %d: Cannot fork 2nd time.", command, getpid());
83
+ // fork again to become session leader
84
+ pid = fork();
85
+ if(pid == -1)
86
+ error("pre-execution of command '%s' on pid %d: Cannot fork 2nd time.", command, getpid());
87
88
- if(pid != 0) {
89
- // the parent
90
- exit(0);
91
- }
88
+ if(pid != 0) {
89
+ // the parent
90
+ exit(0);
91
+ }
92
93
- // set a new process group id for just this child
94
- if( setpgid(0, 0) != 0 )
95
- error("pre-execution of command '%s' on pid %d: Cannot set a new process group.", command, getpid());
93
+ // set a new process group id for just this child
94
+ if( setpgid(0, 0) != 0 )
95
+ error("pre-execution of command '%s' on pid %d: Cannot set a new process group.", command, getpid());
96
97
- if( getpgid(0) != getpid() )
98
- error("pre-execution of command '%s' on pid %d: Cannot set a new process group. Process group set is incorrect. Expected %d, found %d", command, getpid(), getpid(), getpgid(0));
97
+ if( getpgid(0) != getpid() )
98
+ error("pre-execution of command '%s' on pid %d: Cannot set a new process group. Process group set is incorrect. Expected %d, found %d", command, getpid(), getpid(), getpgid(0));
99
100
- if( setsid() != 0 )
101
- error("pre-execution of command '%s' on pid %d: Cannot set session id.", command, getpid());
100
+ if( setsid() != 0 )
101
+ error("pre-execution of command '%s' on pid %d: Cannot set session id.", command, getpid());
102
103
- fprintf(stdout, "MYPID %d\n", getpid());
104
- fflush(NULL);
103
+ fprintf(stdout, "MYPID %d\n", getpid());
104
+ fflush(NULL);
105
#endif
106
107
- // reset all signals
108
- {
109
- sigset_t sigset;
110
- sigfillset(&sigset);
111
-
112
- if(pthread_sigmask(SIG_UNBLOCK, &sigset, NULL) == -1)
113
- error("pre-execution of command '%s' on pid %d: could not unblock signals for threads.", command, getpid());
114
-
115
- // We only need to reset ignored signals.
116
- // Signals with signal handlers are reset by default.
117
- struct sigaction sa;
118
- sigemptyset(&sa.sa_mask);
119
- sa.sa_handler = SIG_DFL;
120
- sa.sa_flags = 0;
121
-
122
- if(sigaction(SIGUSR1, &sa, NULL) == -1)
123
- error("pre-execution of command '%s' on pid %d: failed to set default signal handler for SIGUSR1.", command, getpid());
124
-
125
- if(sigaction(SIGPIPE, &sa, NULL) == -1)
126
- error("pre-execution of command '%s' on pid %d: failed to set default signal handler for SIGPIPE.", command, getpid());
127
- }
128
-
129
-
130
- info("executing command: '%s' on pid %d.", command, getpid());
131
- execl("/bin/sh", "sh", "-c", command, NULL);
132
- exit(1);
107
+ // reset all signals
108
+ {
109
+ sigset_t sigset;
110
+ sigfillset(&sigset);
111
+
112
+ if(pthread_sigmask(SIG_UNBLOCK, &sigset, NULL) == -1)
113
+ error("pre-execution of command '%s' on pid %d: could not unblock signals for threads.", command, getpid());
114
+
115
+ // We only need to reset ignored signals.
116
+ // Signals with signal handlers are reset by default.
117
+ struct sigaction sa;
118
+ sigemptyset(&sa.sa_mask);
119
+ sa.sa_handler = SIG_DFL;
120
+ sa.sa_flags = 0;
121
+
122
+ if(sigaction(SIGUSR1, &sa, NULL) == -1)
123
+ error("pre-execution of command '%s' on pid %d: failed to set default signal handler for SIGUSR1.", command, getpid());
124
+
125
+ if(sigaction(SIGPIPE, &sa, NULL) == -1)
126
+ error("pre-execution of command '%s' on pid %d: failed to set default signal handler for SIGPIPE.", command, getpid());
127
+ }
128
+
129
+
130
+ info("executing command: '%s' on pid %d.", command, getpid());
131
+ execl("/bin/sh", "sh", "-c", command, NULL);
132
+ exit(1);
133
}
134
135
int mypclose(FILE *fp, pid_t pid) {
136
- debug(D_EXIT, "Request to mypclose() on pid %d", pid);
137
-
138
- /*mypopen_del(fp);*/
139
- fclose(fp);
140
-
141
- siginfo_t info;
142
- if(waitid(P_PID, (id_t) pid, &info, WEXITED) != -1) {
143
- switch(info.si_code) {
144
- case CLD_EXITED:
145
- if(info.si_status)
146
- error("child pid %d exited with code %d.", info.si_pid, info.si_status);
147
- return(info.si_status);
148
- break;
149
-
150
- case CLD_KILLED:
151
- error("child pid %d killed by signal %d.", info.si_pid, info.si_status);
152
- return(-1);
153
- break;
154
-
155
- case CLD_DUMPED:
156
- error("child pid %d core dumped by signal %d.", info.si_pid, info.si_status);
157
- return(-2);
158
- break;
159
-
160
- case CLD_STOPPED:
161
- error("child pid %d stopped by signal %d.", info.si_pid, info.si_status);
162
- return(0);
163
- break;
164
-
165
- case CLD_TRAPPED:
166
- error("child pid %d trapped by signal %d.", info.si_pid, info.si_status);
167
- return(-4);
168
- break;
169
-
170
- case CLD_CONTINUED:
171
- error("child pid %d continued by signal %d.", info.si_pid, info.si_status);
172
- return(0);
173
- break;
174
-
175
- default:
176
- error("child pid %d gave us a SIGCHLD with code %d and status %d.", info.si_pid, info.si_code, info.si_status);
177
- return(-5);
178
- break;
179
- }
180
- }
181
- else
182
- error("Cannot waitid() for pid %d", pid);
183
-
184
- return 0;
136
+ debug(D_EXIT, "Request to mypclose() on pid %d", pid);
137
+
138
+ /*mypopen_del(fp);*/
139
+ fclose(fp);
140
+
141
+ siginfo_t info;
142
+ if(waitid(P_PID, (id_t) pid, &info, WEXITED) != -1) {
143
+ switch(info.si_code) {
144
+ case CLD_EXITED:
145
+ if(info.si_status)
146
+ error("child pid %d exited with code %d.", info.si_pid, info.si_status);
147
+ return(info.si_status);
148
+ break;
149
+
150
+ case CLD_KILLED:
151
+ error("child pid %d killed by signal %d.", info.si_pid, info.si_status);
152
+ return(-1);
153
+ break;
154
+
155
+ case CLD_DUMPED:
156
+ error("child pid %d core dumped by signal %d.", info.si_pid, info.si_status);
157
+ return(-2);
158
+ break;
159
+
160
+ case CLD_STOPPED:
161
+ error("child pid %d stopped by signal %d.", info.si_pid, info.si_status);
162
+ return(0);
163
+ break;
164
+
165
+ case CLD_TRAPPED:
166
+ error("child pid %d trapped by signal %d.", info.si_pid, info.si_status);
167
+ return(-4);
168
+ break;
169
+
170
+ case CLD_CONTINUED:
171
+ error("child pid %d continued by signal %d.", info.si_pid, info.si_status);
172
+ return(0);
173
+ break;
174
+
175
+ default:
176
+ error("child pid %d gave us a SIGCHLD with code %d and status %d.", info.si_pid, info.si_code, info.si_status);
177
+ return(-5);
178
+ break;
179
+ }
180
+ }
181
+ else
182
+ error("Cannot waitid() for pid %d", pid);
183
+
184
+ return 0;
185
}
src/proc_diskstats.c
+678
-678
@@ -7,694 +7,694 @@
7
#define DISK_TYPE_CONTAINER 3
8
9
static struct disk {
10
- char *disk; // the name of the disk (sda, sdb, etc)
11
- unsigned long major;
12
- unsigned long minor;
13
- int sector_size;
14
- int type;
15
- char *mount_point;
16
-
17
- // disk options caching
18
- int configured;
19
- int do_io;
20
- int do_ops;
21
- int do_mops;
22
- int do_iotime;
23
- int do_qops;
24
- int do_util;
25
- int do_backlog;
26
- int do_space;
27
- int do_inodes;
28
-
29
- struct disk *next;
10
+ char *disk; // the name of the disk (sda, sdb, etc)
11
+ unsigned long major;
12
+ unsigned long minor;
13
+ int sector_size;
14
+ int type;
15
+ char *mount_point;
16
+
17
+ // disk options caching
18
+ int configured;
19
+ int do_io;
20
+ int do_ops;
21
+ int do_mops;
22
+ int do_iotime;
23
+ int do_qops;
24
+ int do_util;
25
+ int do_backlog;
26
+ int do_space;
27
+ int do_inodes;
28
+
29
+ struct disk *next;
30
} *disk_root = NULL;
31
32
static struct mountinfo *disk_mountinfo_root = NULL;
33
34
static struct disk *get_disk(unsigned long major, unsigned long minor, char *disk) {
35
- static char path_to_get_hw_sector_size[FILENAME_MAX + 1] = "";
36
- static char path_to_get_hw_sector_size_partitions[FILENAME_MAX + 1] = "";
37
- static char path_find_block_device[FILENAME_MAX + 1] = "";
38
- struct disk *d;
39
-
40
- // search for it in our RAM list.
41
- // this is sequential, but since we just walk through
42
- // and the number of disks / partitions in a system
43
- // should not be that many, it should be acceptable
44
- for(d = disk_root; d ; d = d->next)
45
- if(unlikely(d->major == major && d->minor == minor))
46
- break;
47
-
48
- // if we found it, return it
49
- if(likely(d))
50
- return d;
51
-
52
- // not found
53
- // create a new disk structure
54
- d = (struct disk *)mallocz(sizeof(struct disk));
55
-
56
- d->disk = strdupz(disk);
57
- d->major = major;
58
- d->minor = minor;
59
- d->type = DISK_TYPE_PHYSICAL; // Default type. Changed later if not correct.
60
- d->configured = 0;
61
- d->sector_size = 512; // the default, will be changed below
62
- d->next = NULL;
63
-
64
- // append it to the list
65
- if(!disk_root)
66
- disk_root = d;
67
- else {
68
- struct disk *last;
69
- for(last = disk_root; last->next ;last = last->next);
70
- last->next = d;
71
- }
72
-
73
- // ------------------------------------------------------------------------
74
- // find the type of the device
75
-
76
- char buffer[FILENAME_MAX + 1];
77
-
78
- // get the default path for finding info about the block device
79
- if(unlikely(!path_find_block_device[0])) {
80
- snprintfz(buffer, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/dev/block/%lu:%lu/%s");
81
- snprintfz(path_find_block_device, FILENAME_MAX, "%s", config_get("plugin:proc:/proc/diskstats", "path to get block device infos", buffer));
82
- }
83
-
84
- // find if it is a partition
85
- // by checking if /sys/dev/block/MAJOR:MINOR/partition is readable.
86
- snprintfz(buffer, FILENAME_MAX, path_find_block_device, major, minor, "partition");
87
- if(access(buffer, R_OK) == 0) {
88
- d->type = DISK_TYPE_PARTITION;
89
- } else {
90
- // find if it is a container
91
- // by checking if /sys/dev/block/MAJOR:MINOR/slaves has entries
92
- snprintfz(buffer, FILENAME_MAX, path_find_block_device, major, minor, "slaves/");
93
- DIR *dirp = opendir(buffer);
94
- if (dirp != NULL) {
95
- struct dirent *dp;
96
- while( (dp = readdir(dirp)) ) {
97
- // . and .. are also files in empty folders.
98
- if(strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) {
99
- continue;
100
- }
101
-
102
- d->type = DISK_TYPE_CONTAINER;
103
-
104
- // Stop the loop after we found one file.
105
- break;
106
- }
107
- if(closedir(dirp) == -1)
108
- error("Unable to close dir %s", buffer);
109
- }
110
- }
111
-
112
- // ------------------------------------------------------------------------
113
- // check if we can find its mount point
114
-
115
- // mountinfo_find() can be called with NULL disk_mountinfo_root
116
- struct mountinfo *mi = mountinfo_find(disk_mountinfo_root, d->major, d->minor);
117
- if(unlikely(!mi)) {
118
- // mountinfo_free() can be called with NULL disk_mountinfo_root
119
- mountinfo_free(disk_mountinfo_root);
120
-
121
- // re-read mountinfo in case something changed
122
- disk_mountinfo_root = mountinfo_read();
123
-
124
- // search again for this disk
125
- mi = mountinfo_find(disk_mountinfo_root, d->major, d->minor);
126
- }
127
-
128
- if(mi)
129
- d->mount_point = strdupz(mi->mount_point);
130
- // no need to check for NULL
131
- else
132
- d->mount_point = NULL;
133
-
134
- // ------------------------------------------------------------------------
135
- // find the disk sector size
136
-
137
- if(!path_to_get_hw_sector_size[0]) {
138
- snprintfz(buffer, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/block/%s/queue/hw_sector_size");
139
- snprintfz(path_to_get_hw_sector_size, FILENAME_MAX, "%s", config_get("plugin:proc:/proc/diskstats", "path to get h/w sector size", buffer));
140
- }
141
- if(!path_to_get_hw_sector_size_partitions[0]) {
142
- snprintfz(buffer, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/dev/block/%lu:%lu/subsystem/%s/../queue/hw_sector_size");
143
- snprintfz(path_to_get_hw_sector_size_partitions, FILENAME_MAX, "%s", config_get("plugin:proc:/proc/diskstats", "path to get h/w sector size for partitions", buffer));
144
- }
145
-
146
- {
147
- char tf[FILENAME_MAX + 1], *t;
148
- strncpyz(tf, d->disk, FILENAME_MAX);
149
-
150
- // replace all / with !
151
- for(t = tf; *t ;t++)
152
- if(*t == '/') *t = '!';
153
-
154
- if(d->type == DISK_TYPE_PARTITION)
155
- snprintfz(buffer, FILENAME_MAX, path_to_get_hw_sector_size_partitions, d->major, d->minor, tf);
156
- else
157
- snprintfz(buffer, FILENAME_MAX, path_to_get_hw_sector_size, tf);
158
-
159
- FILE *fpss = fopen(buffer, "r");
160
- if(fpss) {
161
- char buffer2[1024 + 1];
162
- char *tmp = fgets(buffer2, 1024, fpss);
163
-
164
- if(tmp) {
165
- d->sector_size = atoi(tmp);
166
- if(d->sector_size <= 0) {
167
- error("Invalid sector size %d for device %s in %s. Assuming 512.", d->sector_size, d->disk, buffer);
168
- d->sector_size = 512;
169
- }
170
- }
171
- else error("Cannot read data for sector size for device %s from %s. Assuming 512.", d->disk, buffer);
172
-
173
- fclose(fpss);
174
- }
175
- else error("Cannot read sector size for device %s from %s. Assuming 512.", d->disk, buffer);
176
- }
177
-
178
- return d;
35
+ static char path_to_get_hw_sector_size[FILENAME_MAX + 1] = "";
36
+ static char path_to_get_hw_sector_size_partitions[FILENAME_MAX + 1] = "";
37
+ static char path_find_block_device[FILENAME_MAX + 1] = "";
38
+ struct disk *d;
39
+
40
+ // search for it in our RAM list.
41
+ // this is sequential, but since we just walk through
42
+ // and the number of disks / partitions in a system
43
+ // should not be that many, it should be acceptable
44
+ for(d = disk_root; d ; d = d->next)
45
+ if(unlikely(d->major == major && d->minor == minor))
46
+ break;
47
+
48
+ // if we found it, return it
49
+ if(likely(d))
50
+ return d;
51
+
52
+ // not found
53
+ // create a new disk structure
54
+ d = (struct disk *)mallocz(sizeof(struct disk));
55
+
56
+ d->disk = strdupz(disk);
57
+ d->major = major;
58
+ d->minor = minor;
59
+ d->type = DISK_TYPE_PHYSICAL; // Default type. Changed later if not correct.
60
+ d->configured = 0;
61
+ d->sector_size = 512; // the default, will be changed below
62
+ d->next = NULL;
63
+
64
+ // append it to the list
65
+ if(!disk_root)
66
+ disk_root = d;
67
+ else {
68
+ struct disk *last;
69
+ for(last = disk_root; last->next ;last = last->next);
70
+ last->next = d;
71
+ }
72
+
73
+ // ------------------------------------------------------------------------
74
+ // find the type of the device
75
+
76
+ char buffer[FILENAME_MAX + 1];
77
+
78
+ // get the default path for finding info about the block device
79
+ if(unlikely(!path_find_block_device[0])) {
80
+ snprintfz(buffer, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/dev/block/%lu:%lu/%s");
81
+ snprintfz(path_find_block_device, FILENAME_MAX, "%s", config_get("plugin:proc:/proc/diskstats", "path to get block device infos", buffer));
82
+ }
83
+
84
+ // find if it is a partition
85
+ // by checking if /sys/dev/block/MAJOR:MINOR/partition is readable.
86
+ snprintfz(buffer, FILENAME_MAX, path_find_block_device, major, minor, "partition");
87
+ if(access(buffer, R_OK) == 0) {
88
+ d->type = DISK_TYPE_PARTITION;
89
+ } else {
90
+ // find if it is a container
91
+ // by checking if /sys/dev/block/MAJOR:MINOR/slaves has entries
92
+ snprintfz(buffer, FILENAME_MAX, path_find_block_device, major, minor, "slaves/");
93
+ DIR *dirp = opendir(buffer);
94
+ if (dirp != NULL) {
95
+ struct dirent *dp;
96
+ while( (dp = readdir(dirp)) ) {
97
+ // . and .. are also files in empty folders.
98
+ if(strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) {
99
+ continue;
100
+ }
101
+
102
+ d->type = DISK_TYPE_CONTAINER;
103
+
104
+ // Stop the loop after we found one file.
105
+ break;
106
+ }
107
+ if(closedir(dirp) == -1)
108
+ error("Unable to close dir %s", buffer);
109
+ }
110
+ }
111
+
112
+ // ------------------------------------------------------------------------
113
+ // check if we can find its mount point
114
+
115
+ // mountinfo_find() can be called with NULL disk_mountinfo_root
116
+ struct mountinfo *mi = mountinfo_find(disk_mountinfo_root, d->major, d->minor);
117
+ if(unlikely(!mi)) {
118
+ // mountinfo_free() can be called with NULL disk_mountinfo_root
119
+ mountinfo_free(disk_mountinfo_root);
120
+
121
+ // re-read mountinfo in case something changed
122
+ disk_mountinfo_root = mountinfo_read();
123
+
124
+ // search again for this disk
125
+ mi = mountinfo_find(disk_mountinfo_root, d->major, d->minor);
126
+ }
127
+
128
+ if(mi)
129
+ d->mount_point = strdupz(mi->mount_point);
130
+ // no need to check for NULL
131
+ else
132
+ d->mount_point = NULL;
133
+
134
+ // ------------------------------------------------------------------------
135
+ // find the disk sector size
136
+
137
+ if(!path_to_get_hw_sector_size[0]) {
138
+ snprintfz(buffer, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/block/%s/queue/hw_sector_size");
139
+ snprintfz(path_to_get_hw_sector_size, FILENAME_MAX, "%s", config_get("plugin:proc:/proc/diskstats", "path to get h/w sector size", buffer));
140
+ }
141
+ if(!path_to_get_hw_sector_size_partitions[0]) {
142
+ snprintfz(buffer, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/dev/block/%lu:%lu/subsystem/%s/../queue/hw_sector_size");
143
+ snprintfz(path_to_get_hw_sector_size_partitions, FILENAME_MAX, "%s", config_get("plugin:proc:/proc/diskstats", "path to get h/w sector size for partitions", buffer));
144
+ }
145
+
146
+ {
147
+ char tf[FILENAME_MAX + 1], *t;
148
+ strncpyz(tf, d->disk, FILENAME_MAX);
149
+
150
+ // replace all / with !
151
+ for(t = tf; *t ;t++)
152
+ if(*t == '/') *t = '!';
153
+
154
+ if(d->type == DISK_TYPE_PARTITION)
155
+ snprintfz(buffer, FILENAME_MAX, path_to_get_hw_sector_size_partitions, d->major, d->minor, tf);
156
+ else
157
+ snprintfz(buffer, FILENAME_MAX, path_to_get_hw_sector_size, tf);
158
+
159
+ FILE *fpss = fopen(buffer, "r");
160
+ if(fpss) {
161
+ char buffer2[1024 + 1];
162
+ char *tmp = fgets(buffer2, 1024, fpss);
163
+
164
+ if(tmp) {
165
+ d->sector_size = atoi(tmp);
166
+ if(d->sector_size <= 0) {
167
+ error("Invalid sector size %d for device %s in %s. Assuming 512.", d->sector_size, d->disk, buffer);
168
+ d->sector_size = 512;
169
+ }
170
+ }
171
+ else error("Cannot read data for sector size for device %s from %s. Assuming 512.", d->disk, buffer);
172
+
173
+ fclose(fpss);
174
+ }
175
+ else error("Cannot read sector size for device %s from %s. Assuming 512.", d->disk, buffer);
176
+ }
177
+
178
+ return d;
179
}
180
181
static inline int select_positive_option(int option1, int option2) {
182
- if(option1 == CONFIG_ONDEMAND_YES || option2 == CONFIG_ONDEMAND_YES)
183
- return CONFIG_ONDEMAND_YES;
184
- else if(option1 == CONFIG_ONDEMAND_ONDEMAND || option2 == CONFIG_ONDEMAND_ONDEMAND)
185
- return CONFIG_ONDEMAND_ONDEMAND;
182
+ if(option1 == CONFIG_ONDEMAND_YES || option2 == CONFIG_ONDEMAND_YES)
183
+ return CONFIG_ONDEMAND_YES;
184
+ else if(option1 == CONFIG_ONDEMAND_ONDEMAND || option2 == CONFIG_ONDEMAND_ONDEMAND)
185
+ return CONFIG_ONDEMAND_ONDEMAND;
186
187
- return CONFIG_ONDEMAND_NO;
187
+ return CONFIG_ONDEMAND_NO;
188
}
189
190
int do_proc_diskstats(int update_every, unsigned long long dt) {
191
- static procfile *ff = NULL;
192
- static struct statvfs buff_statvfs;
193
- static struct stat buff_stat;
194
- static int global_enable_new_disks_detected_at_runtime = CONFIG_ONDEMAND_YES,
195
- global_enable_performance_for_physical_disks = CONFIG_ONDEMAND_ONDEMAND,
196
- global_enable_performance_for_virtual_disks = CONFIG_ONDEMAND_NO,
197
- global_enable_performance_for_partitions = CONFIG_ONDEMAND_NO,
198
- global_enable_performance_for_mountpoints = CONFIG_ONDEMAND_NO,
199
- global_enable_performance_for_virtual_mountpoints = CONFIG_ONDEMAND_ONDEMAND,
200
- global_enable_space_for_mountpoints = CONFIG_ONDEMAND_ONDEMAND,
201
- global_do_io = CONFIG_ONDEMAND_ONDEMAND,
202
- global_do_ops = CONFIG_ONDEMAND_ONDEMAND,
203
- global_do_mops = CONFIG_ONDEMAND_ONDEMAND,
204
- global_do_iotime = CONFIG_ONDEMAND_ONDEMAND,
205
- global_do_qops = CONFIG_ONDEMAND_ONDEMAND,
206
- global_do_util = CONFIG_ONDEMAND_ONDEMAND,
207
- global_do_backlog = CONFIG_ONDEMAND_ONDEMAND,
208
- global_do_space = CONFIG_ONDEMAND_ONDEMAND,
209
- global_do_inodes = CONFIG_ONDEMAND_ONDEMAND,
210
- globals_initialized = 0;
211
-
212
- if(unlikely(!globals_initialized)) {
213
- global_enable_new_disks_detected_at_runtime = config_get_boolean("plugin:proc:/proc/diskstats", "enable new disks detected at runtime", global_enable_new_disks_detected_at_runtime);
214
-
215
- global_enable_performance_for_physical_disks = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "performance metrics for physical disks", global_enable_performance_for_physical_disks);
216
- global_enable_performance_for_virtual_disks = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "performance metrics for virtual disks", global_enable_performance_for_virtual_disks);
217
- global_enable_performance_for_partitions = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "performance metrics for partitions", global_enable_performance_for_partitions);
218
- global_enable_performance_for_mountpoints = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "performance metrics for mounted filesystems", global_enable_performance_for_mountpoints);
219
- global_enable_performance_for_virtual_mountpoints = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "performance metrics for mounted virtual disks", global_enable_performance_for_virtual_mountpoints);
220
- global_enable_space_for_mountpoints = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "space metrics for mounted filesystems", global_enable_space_for_mountpoints);
221
-
222
- global_do_io = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "bandwidth for all disks", global_do_io);
223
- global_do_ops = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "operations for all disks", global_do_ops);
224
- global_do_mops = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "merged operations for all disks", global_do_mops);
225
- global_do_iotime = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "i/o time for all disks", global_do_iotime);
226
- global_do_qops = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "queued operations for all disks", global_do_qops);
227
- global_do_util = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "utilization percentage for all disks", global_do_util);
228
- global_do_backlog = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "backlog for all disks", global_do_backlog);
229
- global_do_space = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "space usage for all disks", global_do_space);
230
- global_do_inodes = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "inodes usage for all disks", global_do_inodes);
231
-
232
- globals_initialized = 1;
233
- }
234
-
235
- if(!ff) {
236
- char filename[FILENAME_MAX + 1];
237
- snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/diskstats");
238
- ff = procfile_open(config_get("plugin:proc:/proc/diskstats", "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT);
239
- }
240
- if(!ff) return 1;
241
-
242
- ff = procfile_readall(ff);
243
- if(!ff) return 0; // we return 0, so that we will retry to open it next time
244
-
245
- uint32_t lines = procfile_lines(ff), l;
246
- uint32_t words;
247
-
248
- for(l = 0; l < lines ;l++) {
249
- // --------------------------------------------------------------------------
250
- // Read parameters
251
-
252
- char *disk;
253
- unsigned long long major = 0, minor = 0,
254
- reads = 0, mreads = 0, readsectors = 0, readms = 0,
255
- writes = 0, mwrites = 0, writesectors = 0, writems = 0,
256
- queued_ios = 0, busy_ms = 0, backlog_ms = 0,
257
- space_avail = 0, space_avail_root = 0, space_used = 0,
258
- inodes_avail = 0, inodes_avail_root = 0, inodes_used = 0;
259
-
260
- unsigned long long last_reads = 0, last_readsectors = 0, last_readms = 0,
261
- last_writes = 0, last_writesectors = 0, last_writems = 0,
262
- last_busy_ms = 0;
263
-
264
- words = procfile_linewords(ff, l);
265
- if(words < 14) continue;
266
-
267
- major = strtoull(procfile_lineword(ff, l, 0), NULL, 10);
268
- minor = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
269
- disk = procfile_lineword(ff, l, 2);
270
-
271
- // # of reads completed # of writes completed
272
- // This is the total number of reads or writes completed successfully.
273
- reads = strtoull(procfile_lineword(ff, l, 3), NULL, 10); // rd_ios
274
- writes = strtoull(procfile_lineword(ff, l, 7), NULL, 10); // wr_ios
275
-
276
- // # of reads merged # of writes merged
277
- // Reads and writes which are adjacent to each other may be merged for
278
- // efficiency. Thus two 4K reads may become one 8K read before it is
279
- // ultimately handed to the disk, and so it will be counted (and queued)
280
- mreads = strtoull(procfile_lineword(ff, l, 4), NULL, 10); // rd_merges_or_rd_sec
281
- mwrites = strtoull(procfile_lineword(ff, l, 8), NULL, 10); // wr_merges
282
-
283
- // # of sectors read # of sectors written
284
- // This is the total number of sectors read or written successfully.
285
- readsectors = strtoull(procfile_lineword(ff, l, 5), NULL, 10); // rd_sec_or_wr_ios
286
- writesectors = strtoull(procfile_lineword(ff, l, 9), NULL, 10); // wr_sec
287
-
288
- // # of milliseconds spent reading # of milliseconds spent writing
289
- // This is the total number of milliseconds spent by all reads or writes (as
290
- // measured from __make_request() to end_that_request_last()).
291
- readms = strtoull(procfile_lineword(ff, l, 6), NULL, 10); // rd_ticks_or_wr_sec
292
- writems = strtoull(procfile_lineword(ff, l, 10), NULL, 10); // wr_ticks
293
-
294
- // # of I/Os currently in progress
295
- // The only field that should go to zero. Incremented as requests are
296
- // given to appropriate struct request_queue and decremented as they finish.
297
- queued_ios = strtoull(procfile_lineword(ff, l, 11), NULL, 10); // ios_pgr
298
-
299
- // # of milliseconds spent doing I/Os
300
- // This field increases so long as field queued_ios is nonzero.
301
- busy_ms = strtoull(procfile_lineword(ff, l, 12), NULL, 10); // tot_ticks
302
-
303
- // weighted # of milliseconds spent doing I/Os
304
- // This field is incremented at each I/O start, I/O completion, I/O
305
- // merge, or read of these stats by the number of I/Os in progress
306
- // (field queued_ios) times the number of milliseconds spent doing I/O since the
307
- // last update of this field. This can provide an easy measure of both
308
- // I/O completion time and the backlog that may be accumulating.
309
- backlog_ms = strtoull(procfile_lineword(ff, l, 13), NULL, 10); // rq_ticks
310
-
311
-
312
- // --------------------------------------------------------------------------
313
- // remove slashes from disk names
314
- char *s;
315
- for(s = disk; *s ;s++)
316
- if(*s == '/') *s = '_';
317
-
318
- // --------------------------------------------------------------------------
319
- // get a disk structure for the disk
320
-
321
- struct disk *d = get_disk(major, minor, disk);
322
-
323
-
324
- // --------------------------------------------------------------------------
325
- // Set its family based on mount point
326
-
327
- char *family = d->mount_point;
328
- if(!family) family = disk;
329
-
330
-
331
- // --------------------------------------------------------------------------
332
- // Check the configuration for the device
333
-
334
- if(unlikely(!d->configured)) {
335
- char var_name[4096 + 1];
336
- snprintfz(var_name, 4096, "plugin:proc:/proc/diskstats:%s", disk);
337
-
338
- int def_enable = config_get_boolean_ondemand(var_name, "enable", global_enable_new_disks_detected_at_runtime);
339
- if(def_enable == CONFIG_ONDEMAND_NO) {
340
- // the user does not want any metrics for this disk
341
- d->do_io = CONFIG_ONDEMAND_NO;
342
- d->do_ops = CONFIG_ONDEMAND_NO;
343
- d->do_mops = CONFIG_ONDEMAND_NO;
344
- d->do_iotime = CONFIG_ONDEMAND_NO;
345
- d->do_qops = CONFIG_ONDEMAND_NO;
346
- d->do_util = CONFIG_ONDEMAND_NO;
347
- d->do_backlog = CONFIG_ONDEMAND_NO;
348
- d->do_space = CONFIG_ONDEMAND_NO;
349
- d->do_inodes = CONFIG_ONDEMAND_NO;
350
- }
351
- else {
352
- // this disk is enabled
353
- // check its direct settings
354
-
355
- int def_performance = CONFIG_ONDEMAND_ONDEMAND;
356
- int def_space = (d->mount_point)?CONFIG_ONDEMAND_ONDEMAND:CONFIG_ONDEMAND_NO;
357
-
358
- // since this is 'on demand' we can figure the performance settings
359
- // based on the type of disk
360
-
361
- switch(d->type) {
362
- case DISK_TYPE_PHYSICAL:
363
- def_performance = global_enable_performance_for_physical_disks;
364
- break;
365
-
366
- case DISK_TYPE_PARTITION:
367
- def_performance = global_enable_performance_for_partitions;
368
- break;
369
-
370
- case DISK_TYPE_CONTAINER:
371
- def_performance = global_enable_performance_for_virtual_disks;
372
-
373
- if(d->mount_point)
374
- def_performance = select_positive_option(def_performance, global_enable_performance_for_virtual_mountpoints);
375
-
376
- break;
377
- }
378
-
379
- if(d->mount_point)
380
- def_performance = select_positive_option(def_performance, global_enable_performance_for_mountpoints);
381
-
382
- // ------------------------------------------------------------
383
- // now we have def_performance and def_space
384
- // to work further
385
-
386
- // def_performance
387
- // check the user configuration (this will also show our 'on demand' decision)
388
- def_performance = config_get_boolean_ondemand(var_name, "enable performance metrics", def_performance);
389
-
390
- int ddo_io = CONFIG_ONDEMAND_NO,
391
- ddo_ops = CONFIG_ONDEMAND_NO,
392
- ddo_mops = CONFIG_ONDEMAND_NO,
393
- ddo_iotime = CONFIG_ONDEMAND_NO,
394
- ddo_qops = CONFIG_ONDEMAND_NO,
395
- ddo_util = CONFIG_ONDEMAND_NO,
396
- ddo_backlog = CONFIG_ONDEMAND_NO;
397
-
398
- // we enable individual performance charts only when def_performance is not disabled
399
- if(def_performance != CONFIG_ONDEMAND_NO) {
400
- ddo_io = global_do_io,
401
- ddo_ops = global_do_ops,
402
- ddo_mops = global_do_mops,
403
- ddo_iotime = global_do_iotime,
404
- ddo_qops = global_do_qops,
405
- ddo_util = global_do_util,
406
- ddo_backlog = global_do_backlog;
407
- }
408
-
409
- d->do_io = config_get_boolean_ondemand(var_name, "bandwidth", ddo_io);
410
- d->do_ops = config_get_boolean_ondemand(var_name, "operations", ddo_ops);
411
- d->do_mops = config_get_boolean_ondemand(var_name, "merged operations", ddo_mops);
412
- d->do_iotime = config_get_boolean_ondemand(var_name, "i/o time", ddo_iotime);
413
- d->do_qops = config_get_boolean_ondemand(var_name, "queued operations", ddo_qops);
414
- d->do_util = config_get_boolean_ondemand(var_name, "utilization percentage", ddo_util);
415
- d->do_backlog = config_get_boolean_ondemand(var_name, "backlog", ddo_backlog);
416
-
417
- // def_space
418
- if(d->mount_point) {
419
- // check the user configuration (this will also show our 'on demand' decision)
420
- def_space = config_get_boolean_ondemand(var_name, "enable space metrics", def_space);
421
-
422
- int ddo_space = def_space,
423
- ddo_inodes = def_space;
424
-
425
- d->do_space = config_get_boolean_ondemand(var_name, "space usage", ddo_space);
426
- d->do_inodes = config_get_boolean_ondemand(var_name, "inodes usage", ddo_inodes);
427
- }
428
- else {
429
- // don't show settings for this disk
430
- d->do_space = CONFIG_ONDEMAND_NO;
431
- d->do_inodes = CONFIG_ONDEMAND_NO;
432
- }
433
- }
434
-
435
- d->configured = 1;
436
- }
437
-
438
- RRDSET *st;
439
-
440
- // --------------------------------------------------------------------------
441
- // Do performance metrics
442
-
443
- if(d->do_io == CONFIG_ONDEMAND_YES || (d->do_io == CONFIG_ONDEMAND_ONDEMAND && (readsectors || writesectors))) {
444
- d->do_io = CONFIG_ONDEMAND_YES;
445
-
446
- st = rrdset_find_bytype(RRD_TYPE_DISK, disk);
447
- if(!st) {
448
- st = rrdset_create(RRD_TYPE_DISK, disk, NULL, family, "disk.io", "Disk I/O Bandwidth", "kilobytes/s", 2000, update_every, RRDSET_TYPE_AREA);
449
-
450
- rrddim_add(st, "reads", NULL, d->sector_size, 1024, RRDDIM_INCREMENTAL);
451
- rrddim_add(st, "writes", NULL, d->sector_size * -1, 1024, RRDDIM_INCREMENTAL);
452
- }
453
- else rrdset_next_usec(st, dt);
454
-
455
- last_readsectors = rrddim_set(st, "reads", readsectors);
456
- last_writesectors = rrddim_set(st, "writes", writesectors);
457
- rrdset_done(st);
458
- }
459
-
460
- // --------------------------------------------------------------------
461
-
462
- if(d->do_ops == CONFIG_ONDEMAND_YES || (d->do_ops == CONFIG_ONDEMAND_ONDEMAND && (reads || writes))) {
463
- d->do_ops = CONFIG_ONDEMAND_YES;
464
-
465
- st = rrdset_find_bytype("disk_ops", disk);
466
- if(!st) {
467
- st = rrdset_create("disk_ops", disk, NULL, family, "disk.ops", "Disk Completed I/O Operations", "operations/s", 2001, update_every, RRDSET_TYPE_LINE);
468
- st->isdetail = 1;
469
-
470
- rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_INCREMENTAL);
471
- rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_INCREMENTAL);
472
- }
473
- else rrdset_next_usec(st, dt);
474
-
475
- last_reads = rrddim_set(st, "reads", reads);
476
- last_writes = rrddim_set(st, "writes", writes);
477
- rrdset_done(st);
478
- }
479
-
480
- // --------------------------------------------------------------------
481
-
482
- if(d->do_qops == CONFIG_ONDEMAND_YES || (d->do_qops == CONFIG_ONDEMAND_ONDEMAND && queued_ios)) {
483
- d->do_qops = CONFIG_ONDEMAND_YES;
484
-
485
- st = rrdset_find_bytype("disk_qops", disk);
486
- if(!st) {
487
- st = rrdset_create("disk_qops", disk, NULL, family, "disk.qops", "Disk Current I/O Operations", "operations", 2002, update_every, RRDSET_TYPE_LINE);
488
- st->isdetail = 1;
489
-
490
- rrddim_add(st, "operations", NULL, 1, 1, RRDDIM_ABSOLUTE);
491
- }
492
- else rrdset_next_usec(st, dt);
493
-
494
- rrddim_set(st, "operations", queued_ios);
495
- rrdset_done(st);
496
- }
497
-
498
- // --------------------------------------------------------------------
499
-
500
- if(d->do_backlog == CONFIG_ONDEMAND_YES || (d->do_backlog == CONFIG_ONDEMAND_ONDEMAND && backlog_ms)) {
501
- d->do_backlog = CONFIG_ONDEMAND_YES;
502
-
503
- st = rrdset_find_bytype("disk_backlog", disk);
504
- if(!st) {
505
- st = rrdset_create("disk_backlog", disk, NULL, family, "disk.backlog", "Disk Backlog", "backlog (ms)", 2003, update_every, RRDSET_TYPE_AREA);
506
- st->isdetail = 1;
507
-
508
- rrddim_add(st, "backlog", NULL, 1, 10, RRDDIM_INCREMENTAL);
509
- }
510
- else rrdset_next_usec(st, dt);
511
-
512
- rrddim_set(st, "backlog", backlog_ms);
513
- rrdset_done(st);
514
- }
515
-
516
- // --------------------------------------------------------------------
517
-
518
- if(d->do_util == CONFIG_ONDEMAND_YES || (d->do_util == CONFIG_ONDEMAND_ONDEMAND && busy_ms)) {
519
- d->do_util = CONFIG_ONDEMAND_YES;
520
-
521
- st = rrdset_find_bytype("disk_util", disk);
522
- if(!st) {
523
- st = rrdset_create("disk_util", disk, NULL, family, "disk.util", "Disk Utilization Time", "% of time working", 2004, update_every, RRDSET_TYPE_AREA);
524
- st->isdetail = 1;
525
-
526
- rrddim_add(st, "utilization", NULL, 1, 10, RRDDIM_INCREMENTAL);
527
- }
528
- else rrdset_next_usec(st, dt);
529
-
530
- last_busy_ms = rrddim_set(st, "utilization", busy_ms);
531
- rrdset_done(st);
532
- }
533
-
534
- // --------------------------------------------------------------------
535
-
536
- if(d->do_mops == CONFIG_ONDEMAND_YES || (d->do_mops == CONFIG_ONDEMAND_ONDEMAND && (mreads || mwrites))) {
537
- d->do_mops = CONFIG_ONDEMAND_YES;
538
-
539
- st = rrdset_find_bytype("disk_mops", disk);
540
- if(!st) {
541
- st = rrdset_create("disk_mops", disk, NULL, family, "disk.mops", "Disk Merged Operations", "merged operations/s", 2021, update_every, RRDSET_TYPE_LINE);
542
- st->isdetail = 1;
543
-
544
- rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_INCREMENTAL);
545
- rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_INCREMENTAL);
546
- }
547
- else rrdset_next_usec(st, dt);
548
-
549
- rrddim_set(st, "reads", mreads);
550
- rrddim_set(st, "writes", mwrites);
551
- rrdset_done(st);
552
- }
553
-
554
- // --------------------------------------------------------------------
555
-
556
- if(d->do_iotime == CONFIG_ONDEMAND_YES || (d->do_iotime == CONFIG_ONDEMAND_ONDEMAND && (readms || writems))) {
557
- d->do_iotime = CONFIG_ONDEMAND_YES;
558
-
559
- st = rrdset_find_bytype("disk_iotime", disk);
560
- if(!st) {
561
- st = rrdset_create("disk_iotime", disk, NULL, family, "disk.iotime", "Disk Total I/O Time", "milliseconds/s", 2022, update_every, RRDSET_TYPE_LINE);
562
- st->isdetail = 1;
563
-
564
- rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_INCREMENTAL);
565
- rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_INCREMENTAL);
566
- }
567
- else rrdset_next_usec(st, dt);
568
-
569
- last_readms = rrddim_set(st, "reads", readms);
570
- last_writems = rrddim_set(st, "writes", writems);
571
- rrdset_done(st);
572
- }
573
-
574
- // --------------------------------------------------------------------
575
- // calculate differential charts
576
- // only if this is not the first time we run
577
-
578
- if(dt) {
579
- if( (d->do_iotime == CONFIG_ONDEMAND_YES || (d->do_iotime == CONFIG_ONDEMAND_ONDEMAND && (readms || writems))) &&
580
- (d->do_ops == CONFIG_ONDEMAND_YES || (d->do_ops == CONFIG_ONDEMAND_ONDEMAND && (reads || writes)))) {
581
- st = rrdset_find_bytype("disk_await", disk);
582
- if(!st) {
583
- st = rrdset_create("disk_await", disk, NULL, family, "disk.await", "Average Completed I/O Operation Time", "ms per operation", 2005, update_every, RRDSET_TYPE_LINE);
584
- st->isdetail = 1;
585
-
586
- rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_ABSOLUTE);
587
- rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_ABSOLUTE);
588
- }
589
- else rrdset_next_usec(st, dt);
590
-
591
- rrddim_set(st, "reads", (reads - last_reads) ? (readms - last_readms) / (reads - last_reads) : 0);
592
- rrddim_set(st, "writes", (writes - last_writes) ? (writems - last_writems) / (writes - last_writes) : 0);
593
- rrdset_done(st);
594
- }
595
-
596
- if( (d->do_io == CONFIG_ONDEMAND_YES || (d->do_io == CONFIG_ONDEMAND_ONDEMAND && (readsectors || writesectors))) &&
597
- (d->do_ops == CONFIG_ONDEMAND_YES || (d->do_ops == CONFIG_ONDEMAND_ONDEMAND && (reads || writes)))) {
598
- st = rrdset_find_bytype("disk_avgsz", disk);
599
- if(!st) {
600
- st = rrdset_create("disk_avgsz", disk, NULL, family, "disk.avgsz", "Average Completed I/O Operation Bandwidth", "kilobytes per operation", 2006, update_every, RRDSET_TYPE_AREA);
601
- st->isdetail = 1;
602
-
603
- rrddim_add(st, "reads", NULL, d->sector_size, 1024, RRDDIM_ABSOLUTE);
604
- rrddim_add(st, "writes", NULL, d->sector_size * -1, 1024, RRDDIM_ABSOLUTE);
605
- }
606
- else rrdset_next_usec(st, dt);
607
-
608
- rrddim_set(st, "reads", (reads - last_reads) ? (readsectors - last_readsectors) / (reads - last_reads) : 0);
609
- rrddim_set(st, "writes", (writes - last_writes) ? (writesectors - last_writesectors) / (writes - last_writes) : 0);
610
- rrdset_done(st);
611
- }
612
-
613
- if( (d->do_util == CONFIG_ONDEMAND_YES || (d->do_util == CONFIG_ONDEMAND_ONDEMAND && busy_ms)) &&
614
- (d->do_ops == CONFIG_ONDEMAND_YES || (d->do_ops == CONFIG_ONDEMAND_ONDEMAND && (reads || writes)))) {
615
- st = rrdset_find_bytype("disk_svctm", disk);
616
- if(!st) {
617
- st = rrdset_create("disk_svctm", disk, NULL, family, "disk.svctm", "Average Service Time", "ms per operation", 2007, update_every, RRDSET_TYPE_LINE);
618
- st->isdetail = 1;
619
-
620
- rrddim_add(st, "svctm", NULL, 1, 1, RRDDIM_ABSOLUTE);
621
- }
622
- else rrdset_next_usec(st, dt);
623
-
624
- rrddim_set(st, "svctm", ((reads - last_reads) + (writes - last_writes)) ? (busy_ms - last_busy_ms) / ((reads - last_reads) + (writes - last_writes)) : 0);
625
- rrdset_done(st);
626
- }
627
- }
628
-
629
- // --------------------------------------------------------------------------
630
- // space metrics
631
-
632
- if(d->mount_point && (d->do_space || d->do_inodes) ) {
633
- // collect space metrics using statvfs
634
-
635
- if (statvfs(d->mount_point, &buff_statvfs) < 0)
636
- error("Failed statvfs() for '%s' (disk '%s')", d->mount_point, d->disk);
637
- else {
638
- space_avail = buff_statvfs.f_bavail * buff_statvfs.f_bsize;
639
- space_avail_root = (buff_statvfs.f_bfree - buff_statvfs.f_bavail) * buff_statvfs.f_bsize;
640
- space_used = (buff_statvfs.f_blocks - buff_statvfs.f_bfree) * buff_statvfs.f_bsize;
641
-
642
- inodes_avail = buff_statvfs.f_favail;
643
- inodes_avail_root = buff_statvfs.f_ffree - buff_statvfs.f_favail;
644
- inodes_used = buff_statvfs.f_files - buff_statvfs.f_ffree;
645
-
646
- // verify we collected the metrics for the right disk.
647
- // if not the mountpoint has changed.
648
-
649
- if(stat(d->mount_point, &buff_stat) == -1)
650
- error("Failed to stat() for '%s' (disk '%s')", d->mount_point, d->disk);
651
- else {
652
- if(major(buff_stat.st_dev) == major && minor(buff_stat.st_dev) == minor) {
653
-
654
- // --------------------------------------------------------------------------
655
-
656
- if(d->do_space == CONFIG_ONDEMAND_YES || (d->do_space == CONFIG_ONDEMAND_ONDEMAND && (space_avail || space_avail_root || space_used))) {
657
- st = rrdset_find_bytype("disk_space", disk);
658
- if(!st) {
659
- st = rrdset_create("disk_space", disk, NULL, family, "disk.space", "Disk Space Usage", "GB", 2023, update_every, RRDSET_TYPE_STACKED);
660
- st->isdetail = 1;
661
-
662
- rrddim_add(st, "avail", NULL, 1, 1024*1024*1024, RRDDIM_ABSOLUTE);
663
- rrddim_add(st, "used" , NULL, 1, 1024*1024*1024, RRDDIM_ABSOLUTE);
664
- rrddim_add(st, "reserved_for_root", "reserved for root", 1, 1024*1024*1024, RRDDIM_ABSOLUTE);
665
- }
666
- else rrdset_next_usec(st, dt);
667
-
668
- rrddim_set(st, "avail", space_avail);
669
- rrddim_set(st, "used", space_used);
670
- rrddim_set(st, "reserved_for_root", space_avail_root);
671
- rrdset_done(st);
672
- }
673
-
674
- // --------------------------------------------------------------------------
675
-
676
- if(d->do_inodes == CONFIG_ONDEMAND_YES || (d->do_inodes == CONFIG_ONDEMAND_ONDEMAND && (inodes_avail || inodes_avail_root || inodes_used))) {
677
- st = rrdset_find_bytype("disk_inodes", disk);
678
- if(!st) {
679
- st = rrdset_create("disk_inodes", disk, NULL, family, "disk.inodes", "Disk Inodes Usage", "Inodes", 2024, update_every, RRDSET_TYPE_STACKED);
680
- st->isdetail = 1;
681
-
682
- rrddim_add(st, "avail", NULL, 1, 1, RRDDIM_ABSOLUTE);
683
- rrddim_add(st, "used" , NULL, 1, 1, RRDDIM_ABSOLUTE);
684
- rrddim_add(st, "reserved_for_root", "reserved for root", 1, 1, RRDDIM_ABSOLUTE);
685
- }
686
- else rrdset_next_usec(st, dt);
687
-
688
- rrddim_set(st, "avail", inodes_avail);
689
- rrddim_set(st, "used", inodes_used);
690
- rrddim_set(st, "reserved_for_root", inodes_avail_root);
691
- rrdset_done(st);
692
- }
693
- }
694
- }
695
- }
696
- }
697
- }
698
-
699
- return 0;
191
+ static procfile *ff = NULL;
192
+ static struct statvfs buff_statvfs;
193
+ static struct stat buff_stat;
194
+ static int global_enable_new_disks_detected_at_runtime = CONFIG_ONDEMAND_YES,
195
+ global_enable_performance_for_physical_disks = CONFIG_ONDEMAND_ONDEMAND,
196
+ global_enable_performance_for_virtual_disks = CONFIG_ONDEMAND_NO,
197
+ global_enable_performance_for_partitions = CONFIG_ONDEMAND_NO,
198
+ global_enable_performance_for_mountpoints = CONFIG_ONDEMAND_NO,
199
+ global_enable_performance_for_virtual_mountpoints = CONFIG_ONDEMAND_ONDEMAND,
200
+ global_enable_space_for_mountpoints = CONFIG_ONDEMAND_ONDEMAND,
201
+ global_do_io = CONFIG_ONDEMAND_ONDEMAND,
202
+ global_do_ops = CONFIG_ONDEMAND_ONDEMAND,
203
+ global_do_mops = CONFIG_ONDEMAND_ONDEMAND,
204
+ global_do_iotime = CONFIG_ONDEMAND_ONDEMAND,
205
+ global_do_qops = CONFIG_ONDEMAND_ONDEMAND,
206
+ global_do_util = CONFIG_ONDEMAND_ONDEMAND,
207
+ global_do_backlog = CONFIG_ONDEMAND_ONDEMAND,
208
+ global_do_space = CONFIG_ONDEMAND_ONDEMAND,
209
+ global_do_inodes = CONFIG_ONDEMAND_ONDEMAND,
210
+ globals_initialized = 0;
211
+
212
+ if(unlikely(!globals_initialized)) {
213
+ global_enable_new_disks_detected_at_runtime = config_get_boolean("plugin:proc:/proc/diskstats", "enable new disks detected at runtime", global_enable_new_disks_detected_at_runtime);
214
+
215
+ global_enable_performance_for_physical_disks = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "performance metrics for physical disks", global_enable_performance_for_physical_disks);
216
+ global_enable_performance_for_virtual_disks = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "performance metrics for virtual disks", global_enable_performance_for_virtual_disks);
217
+ global_enable_performance_for_partitions = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "performance metrics for partitions", global_enable_performance_for_partitions);
218
+ global_enable_performance_for_mountpoints = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "performance metrics for mounted filesystems", global_enable_performance_for_mountpoints);
219
+ global_enable_performance_for_virtual_mountpoints = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "performance metrics for mounted virtual disks", global_enable_performance_for_virtual_mountpoints);
220
+ global_enable_space_for_mountpoints = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "space metrics for mounted filesystems", global_enable_space_for_mountpoints);
221
+
222
+ global_do_io = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "bandwidth for all disks", global_do_io);
223
+ global_do_ops = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "operations for all disks", global_do_ops);
224
+ global_do_mops = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "merged operations for all disks", global_do_mops);
225
+ global_do_iotime = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "i/o time for all disks", global_do_iotime);
226
+ global_do_qops = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "queued operations for all disks", global_do_qops);
227
+ global_do_util = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "utilization percentage for all disks", global_do_util);
228
+ global_do_backlog = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "backlog for all disks", global_do_backlog);
229
+ global_do_space = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "space usage for all disks", global_do_space);
230
+ global_do_inodes = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "inodes usage for all disks", global_do_inodes);
231
+
232
+ globals_initialized = 1;
233
+ }
234
+
235
+ if(!ff) {
236
+ char filename[FILENAME_MAX + 1];
237
+ snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/diskstats");
238
+ ff = procfile_open(config_get("plugin:proc:/proc/diskstats", "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT);
239
+ }
240
+ if(!ff) return 1;
241
+
242
+ ff = procfile_readall(ff);
243
+ if(!ff) return 0; // we return 0, so that we will retry to open it next time
244
+
245
+ uint32_t lines = procfile_lines(ff), l;
246
+ uint32_t words;
247
+
248
+ for(l = 0; l < lines ;l++) {
249
+ // --------------------------------------------------------------------------
250
+ // Read parameters
251
+
252
+ char *disk;
253
+ unsigned long long major = 0, minor = 0,
254
+ reads = 0, mreads = 0, readsectors = 0, readms = 0,
255
+ writes = 0, mwrites = 0, writesectors = 0, writems = 0,
256
+ queued_ios = 0, busy_ms = 0, backlog_ms = 0,
257
+ space_avail = 0, space_avail_root = 0, space_used = 0,
258
+ inodes_avail = 0, inodes_avail_root = 0, inodes_used = 0;
259
+
260
+ unsigned long long last_reads = 0, last_readsectors = 0, last_readms = 0,
261
+ last_writes = 0, last_writesectors = 0, last_writems = 0,
262
+ last_busy_ms = 0;
263
+
264
+ words = procfile_linewords(ff, l);
265
+ if(words < 14) continue;
266
+
267
+ major = strtoull(procfile_lineword(ff, l, 0), NULL, 10);
268
+ minor = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
269
+ disk = procfile_lineword(ff, l, 2);
270
+
271
+ // # of reads completed # of writes completed
272
+ // This is the total number of reads or writes completed successfully.
273
+ reads = strtoull(procfile_lineword(ff, l, 3), NULL, 10); // rd_ios
274
+ writes = strtoull(procfile_lineword(ff, l, 7), NULL, 10); // wr_ios
275
+
276
+ // # of reads merged # of writes merged
277
+ // Reads and writes which are adjacent to each other may be merged for
278
+ // efficiency. Thus two 4K reads may become one 8K read before it is
279
+ // ultimately handed to the disk, and so it will be counted (and queued)
280
+ mreads = strtoull(procfile_lineword(ff, l, 4), NULL, 10); // rd_merges_or_rd_sec
281
+ mwrites = strtoull(procfile_lineword(ff, l, 8), NULL, 10); // wr_merges
282
+
283
+ // # of sectors read # of sectors written
284
+ // This is the total number of sectors read or written successfully.
285
+ readsectors = strtoull(procfile_lineword(ff, l, 5), NULL, 10); // rd_sec_or_wr_ios
286
+ writesectors = strtoull(procfile_lineword(ff, l, 9), NULL, 10); // wr_sec
287
+
288
+ // # of milliseconds spent reading # of milliseconds spent writing
289
+ // This is the total number of milliseconds spent by all reads or writes (as
290
+ // measured from __make_request() to end_that_request_last()).
291
+ readms = strtoull(procfile_lineword(ff, l, 6), NULL, 10); // rd_ticks_or_wr_sec
292
+ writems = strtoull(procfile_lineword(ff, l, 10), NULL, 10); // wr_ticks
293
+
294
+ // # of I/Os currently in progress
295
+ // The only field that should go to zero. Incremented as requests are
296
+ // given to appropriate struct request_queue and decremented as they finish.
297
+ queued_ios = strtoull(procfile_lineword(ff, l, 11), NULL, 10); // ios_pgr
298
+
299
+ // # of milliseconds spent doing I/Os
300
+ // This field increases so long as field queued_ios is nonzero.
301
+ busy_ms = strtoull(procfile_lineword(ff, l, 12), NULL, 10); // tot_ticks
302
+
303
+ // weighted # of milliseconds spent doing I/Os
304
+ // This field is incremented at each I/O start, I/O completion, I/O
305
+ // merge, or read of these stats by the number of I/Os in progress
306
+ // (field queued_ios) times the number of milliseconds spent doing I/O since the
307
+ // last update of this field. This can provide an easy measure of both
308
+ // I/O completion time and the backlog that may be accumulating.
309
+ backlog_ms = strtoull(procfile_lineword(ff, l, 13), NULL, 10); // rq_ticks
310
+
311
+
312
+ // --------------------------------------------------------------------------
313
+ // remove slashes from disk names
314
+ char *s;
315
+ for(s = disk; *s ;s++)
316
+ if(*s == '/') *s = '_';
317
+
318
+ // --------------------------------------------------------------------------
319
+ // get a disk structure for the disk
320
+
321
+ struct disk *d = get_disk(major, minor, disk);
322
+
323
+
324
+ // --------------------------------------------------------------------------
325
+ // Set its family based on mount point
326
+
327
+ char *family = d->mount_point;
328
+ if(!family) family = disk;
329
+
330
+
331
+ // --------------------------------------------------------------------------
332
+ // Check the configuration for the device
333
+
334
+ if(unlikely(!d->configured)) {
335
+ char var_name[4096 + 1];
336
+ snprintfz(var_name, 4096, "plugin:proc:/proc/diskstats:%s", disk);
337
+
338
+ int def_enable = config_get_boolean_ondemand(var_name, "enable", global_enable_new_disks_detected_at_runtime);
339
+ if(def_enable == CONFIG_ONDEMAND_NO) {
340
+ // the user does not want any metrics for this disk
341
+ d->do_io = CONFIG_ONDEMAND_NO;
342
+ d->do_ops = CONFIG_ONDEMAND_NO;
343
+ d->do_mops = CONFIG_ONDEMAND_NO;
344
+ d->do_iotime = CONFIG_ONDEMAND_NO;
345
+ d->do_qops = CONFIG_ONDEMAND_NO;
346
+ d->do_util = CONFIG_ONDEMAND_NO;
347
+ d->do_backlog = CONFIG_ONDEMAND_NO;
348
+ d->do_space = CONFIG_ONDEMAND_NO;
349
+ d->do_inodes = CONFIG_ONDEMAND_NO;
350
+ }
351
+ else {
352
+ // this disk is enabled
353
+ // check its direct settings
354
+
355
+ int def_performance = CONFIG_ONDEMAND_ONDEMAND;
356
+ int def_space = (d->mount_point)?CONFIG_ONDEMAND_ONDEMAND:CONFIG_ONDEMAND_NO;
357
+
358
+ // since this is 'on demand' we can figure the performance settings
359
+ // based on the type of disk
360
+
361
+ switch(d->type) {
362
+ case DISK_TYPE_PHYSICAL:
363
+ def_performance = global_enable_performance_for_physical_disks;
364
+ break;
365
+
366
+ case DISK_TYPE_PARTITION:
367
+ def_performance = global_enable_performance_for_partitions;
368
+ break;
369
+
370
+ case DISK_TYPE_CONTAINER:
371
+ def_performance = global_enable_performance_for_virtual_disks;
372
+
373
+ if(d->mount_point)
374
+ def_performance = select_positive_option(def_performance, global_enable_performance_for_virtual_mountpoints);
375
+
376
+ break;
377
+ }
378
+
379
+ if(d->mount_point)
380
+ def_performance = select_positive_option(def_performance, global_enable_performance_for_mountpoints);
381
+
382
+ // ------------------------------------------------------------
383
+ // now we have def_performance and def_space
384
+ // to work further
385
+
386
+ // def_performance
387
+ // check the user configuration (this will also show our 'on demand' decision)
388
+ def_performance = config_get_boolean_ondemand(var_name, "enable performance metrics", def_performance);
389
+
390
+ int ddo_io = CONFIG_ONDEMAND_NO,
391
+ ddo_ops = CONFIG_ONDEMAND_NO,
392
+ ddo_mops = CONFIG_ONDEMAND_NO,
393
+ ddo_iotime = CONFIG_ONDEMAND_NO,
394
+ ddo_qops = CONFIG_ONDEMAND_NO,
395
+ ddo_util = CONFIG_ONDEMAND_NO,
396
+ ddo_backlog = CONFIG_ONDEMAND_NO;
397
+
398
+ // we enable individual performance charts only when def_performance is not disabled
399
+ if(def_performance != CONFIG_ONDEMAND_NO) {
400
+ ddo_io = global_do_io,
401
+ ddo_ops = global_do_ops,
402
+ ddo_mops = global_do_mops,
403
+ ddo_iotime = global_do_iotime,
404
+ ddo_qops = global_do_qops,
405
+ ddo_util = global_do_util,
406
+ ddo_backlog = global_do_backlog;
407
+ }
408
+
409
+ d->do_io = config_get_boolean_ondemand(var_name, "bandwidth", ddo_io);
410
+ d->do_ops = config_get_boolean_ondemand(var_name, "operations", ddo_ops);
411
+ d->do_mops = config_get_boolean_ondemand(var_name, "merged operations", ddo_mops);
412
+ d->do_iotime = config_get_boolean_ondemand(var_name, "i/o time", ddo_iotime);
413
+ d->do_qops = config_get_boolean_ondemand(var_name, "queued operations", ddo_qops);
414
+ d->do_util = config_get_boolean_ondemand(var_name, "utilization percentage", ddo_util);
415
+ d->do_backlog = config_get_boolean_ondemand(var_name, "backlog", ddo_backlog);
416
+
417
+ // def_space
418
+ if(d->mount_point) {
419
+ // check the user configuration (this will also show our 'on demand' decision)
420
+ def_space = config_get_boolean_ondemand(var_name, "enable space metrics", def_space);
421
+
422
+ int ddo_space = def_space,
423
+ ddo_inodes = def_space;
424
+
425
+ d->do_space = config_get_boolean_ondemand(var_name, "space usage", ddo_space);
426
+ d->do_inodes = config_get_boolean_ondemand(var_name, "inodes usage", ddo_inodes);
427
+ }
428
+ else {
429
+ // don't show settings for this disk
430
+ d->do_space = CONFIG_ONDEMAND_NO;
431
+ d->do_inodes = CONFIG_ONDEMAND_NO;
432
+ }
433
+ }
434
+
435
+ d->configured = 1;
436
+ }
437
+
438
+ RRDSET *st;
439
+
440
+ // --------------------------------------------------------------------------
441
+ // Do performance metrics
442
+
443
+ if(d->do_io == CONFIG_ONDEMAND_YES || (d->do_io == CONFIG_ONDEMAND_ONDEMAND && (readsectors || writesectors))) {
444
+ d->do_io = CONFIG_ONDEMAND_YES;
445
+
446
+ st = rrdset_find_bytype(RRD_TYPE_DISK, disk);
447
+ if(!st) {
448
+ st = rrdset_create(RRD_TYPE_DISK, disk, NULL, family, "disk.io", "Disk I/O Bandwidth", "kilobytes/s", 2000, update_every, RRDSET_TYPE_AREA);
449
+
450
+ rrddim_add(st, "reads", NULL, d->sector_size, 1024, RRDDIM_INCREMENTAL);
451
+ rrddim_add(st, "writes", NULL, d->sector_size * -1, 1024, RRDDIM_INCREMENTAL);
452
+ }
453
+ else rrdset_next_usec(st, dt);
454
+
455
+ last_readsectors = rrddim_set(st, "reads", readsectors);
456
+ last_writesectors = rrddim_set(st, "writes", writesectors);
457
+ rrdset_done(st);
458
+ }
459
+
460
+ // --------------------------------------------------------------------
461
+
462
+ if(d->do_ops == CONFIG_ONDEMAND_YES || (d->do_ops == CONFIG_ONDEMAND_ONDEMAND && (reads || writes))) {
463
+ d->do_ops = CONFIG_ONDEMAND_YES;
464
+
465
+ st = rrdset_find_bytype("disk_ops", disk);
466
+ if(!st) {
467
+ st = rrdset_create("disk_ops", disk, NULL, family, "disk.ops", "Disk Completed I/O Operations", "operations/s", 2001, update_every, RRDSET_TYPE_LINE);
468
+ st->isdetail = 1;
469
+
470
+ rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_INCREMENTAL);
471
+ rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_INCREMENTAL);
472
+ }
473
+ else rrdset_next_usec(st, dt);
474
+
475
+ last_reads = rrddim_set(st, "reads", reads);
476
+ last_writes = rrddim_set(st, "writes", writes);
477
+ rrdset_done(st);
478
+ }
479
+
480
+ // --------------------------------------------------------------------
481
+
482
+ if(d->do_qops == CONFIG_ONDEMAND_YES || (d->do_qops == CONFIG_ONDEMAND_ONDEMAND && queued_ios)) {
483
+ d->do_qops = CONFIG_ONDEMAND_YES;
484
+
485
+ st = rrdset_find_bytype("disk_qops", disk);
486
+ if(!st) {
487
+ st = rrdset_create("disk_qops", disk, NULL, family, "disk.qops", "Disk Current I/O Operations", "operations", 2002, update_every, RRDSET_TYPE_LINE);
488
+ st->isdetail = 1;
489
+
490
+ rrddim_add(st, "operations", NULL, 1, 1, RRDDIM_ABSOLUTE);
491
+ }
492
+ else rrdset_next_usec(st, dt);
493
+
494
+ rrddim_set(st, "operations", queued_ios);
495
+ rrdset_done(st);
496
+ }
497
+
498
+ // --------------------------------------------------------------------
499
+
500
+ if(d->do_backlog == CONFIG_ONDEMAND_YES || (d->do_backlog == CONFIG_ONDEMAND_ONDEMAND && backlog_ms)) {
501
+ d->do_backlog = CONFIG_ONDEMAND_YES;
502
+
503
+ st = rrdset_find_bytype("disk_backlog", disk);
504
+ if(!st) {
505
+ st = rrdset_create("disk_backlog", disk, NULL, family, "disk.backlog", "Disk Backlog", "backlog (ms)", 2003, update_every, RRDSET_TYPE_AREA);
506
+ st->isdetail = 1;
507
+
508
+ rrddim_add(st, "backlog", NULL, 1, 10, RRDDIM_INCREMENTAL);
509
+ }
510
+ else rrdset_next_usec(st, dt);
511
+
512
+ rrddim_set(st, "backlog", backlog_ms);
513
+ rrdset_done(st);
514
+ }
515
+
516
+ // --------------------------------------------------------------------
517
+
518
+ if(d->do_util == CONFIG_ONDEMAND_YES || (d->do_util == CONFIG_ONDEMAND_ONDEMAND && busy_ms)) {
519
+ d->do_util = CONFIG_ONDEMAND_YES;
520
+
521
+ st = rrdset_find_bytype("disk_util", disk);
522
+ if(!st) {
523
+ st = rrdset_create("disk_util", disk, NULL, family, "disk.util", "Disk Utilization Time", "% of time working", 2004, update_every, RRDSET_TYPE_AREA);
524
+ st->isdetail = 1;
525
+
526
+ rrddim_add(st, "utilization", NULL, 1, 10, RRDDIM_INCREMENTAL);
527
+ }
528
+ else rrdset_next_usec(st, dt);
529
+
530
+ last_busy_ms = rrddim_set(st, "utilization", busy_ms);
531
+ rrdset_done(st);
532
+ }
533
+
534
+ // --------------------------------------------------------------------
535
+
536
+ if(d->do_mops == CONFIG_ONDEMAND_YES || (d->do_mops == CONFIG_ONDEMAND_ONDEMAND && (mreads || mwrites))) {
537
+ d->do_mops = CONFIG_ONDEMAND_YES;
538
+
539
+ st = rrdset_find_bytype("disk_mops", disk);
540
+ if(!st) {
541
+ st = rrdset_create("disk_mops", disk, NULL, family, "disk.mops", "Disk Merged Operations", "merged operations/s", 2021, update_every, RRDSET_TYPE_LINE);
542
+ st->isdetail = 1;
543
+
544
+ rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_INCREMENTAL);
545
+ rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_INCREMENTAL);
546
+ }
547
+ else rrdset_next_usec(st, dt);
548
+
549
+ rrddim_set(st, "reads", mreads);
550
+ rrddim_set(st, "writes", mwrites);
551
+ rrdset_done(st);
552
+ }
553
+
554
+ // --------------------------------------------------------------------
555
+
556
+ if(d->do_iotime == CONFIG_ONDEMAND_YES || (d->do_iotime == CONFIG_ONDEMAND_ONDEMAND && (readms || writems))) {
557
+ d->do_iotime = CONFIG_ONDEMAND_YES;
558
+
559
+ st = rrdset_find_bytype("disk_iotime", disk);
560
+ if(!st) {
561
+ st = rrdset_create("disk_iotime", disk, NULL, family, "disk.iotime", "Disk Total I/O Time", "milliseconds/s", 2022, update_every, RRDSET_TYPE_LINE);
562
+ st->isdetail = 1;
563
+
564
+ rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_INCREMENTAL);
565
+ rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_INCREMENTAL);
566
+ }
567
+ else rrdset_next_usec(st, dt);
568
+
569
+ last_readms = rrddim_set(st, "reads", readms);
570
+ last_writems = rrddim_set(st, "writes", writems);
571
+ rrdset_done(st);
572
+ }
573
+
574
+ // --------------------------------------------------------------------
575
+ // calculate differential charts
576
+ // only if this is not the first time we run
577
+
578
+ if(dt) {
579
+ if( (d->do_iotime == CONFIG_ONDEMAND_YES || (d->do_iotime == CONFIG_ONDEMAND_ONDEMAND && (readms || writems))) &&
580
+ (d->do_ops == CONFIG_ONDEMAND_YES || (d->do_ops == CONFIG_ONDEMAND_ONDEMAND && (reads || writes)))) {
581
+ st = rrdset_find_bytype("disk_await", disk);
582
+ if(!st) {
583
+ st = rrdset_create("disk_await", disk, NULL, family, "disk.await", "Average Completed I/O Operation Time", "ms per operation", 2005, update_every, RRDSET_TYPE_LINE);
584
+ st->isdetail = 1;
585
+
586
+ rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_ABSOLUTE);
587
+ rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_ABSOLUTE);
588
+ }
589
+ else rrdset_next_usec(st, dt);
590
+
591
+ rrddim_set(st, "reads", (reads - last_reads) ? (readms - last_readms) / (reads - last_reads) : 0);
592
+ rrddim_set(st, "writes", (writes - last_writes) ? (writems - last_writems) / (writes - last_writes) : 0);
593
+ rrdset_done(st);
594
+ }
595
+
596
+ if( (d->do_io == CONFIG_ONDEMAND_YES || (d->do_io == CONFIG_ONDEMAND_ONDEMAND && (readsectors || writesectors))) &&
597
+ (d->do_ops == CONFIG_ONDEMAND_YES || (d->do_ops == CONFIG_ONDEMAND_ONDEMAND && (reads || writes)))) {
598
+ st = rrdset_find_bytype("disk_avgsz", disk);
599
+ if(!st) {
600
+ st = rrdset_create("disk_avgsz", disk, NULL, family, "disk.avgsz", "Average Completed I/O Operation Bandwidth", "kilobytes per operation", 2006, update_every, RRDSET_TYPE_AREA);
601
+ st->isdetail = 1;
602
+
603
+ rrddim_add(st, "reads", NULL, d->sector_size, 1024, RRDDIM_ABSOLUTE);
604
+ rrddim_add(st, "writes", NULL, d->sector_size * -1, 1024, RRDDIM_ABSOLUTE);
605
+ }
606
+ else rrdset_next_usec(st, dt);
607
+
608
+ rrddim_set(st, "reads", (reads - last_reads) ? (readsectors - last_readsectors) / (reads - last_reads) : 0);
609
+ rrddim_set(st, "writes", (writes - last_writes) ? (writesectors - last_writesectors) / (writes - last_writes) : 0);
610
+ rrdset_done(st);
611
+ }
612
+
613
+ if( (d->do_util == CONFIG_ONDEMAND_YES || (d->do_util == CONFIG_ONDEMAND_ONDEMAND && busy_ms)) &&
614
+ (d->do_ops == CONFIG_ONDEMAND_YES || (d->do_ops == CONFIG_ONDEMAND_ONDEMAND && (reads || writes)))) {
615
+ st = rrdset_find_bytype("disk_svctm", disk);
616
+ if(!st) {
617
+ st = rrdset_create("disk_svctm", disk, NULL, family, "disk.svctm", "Average Service Time", "ms per operation", 2007, update_every, RRDSET_TYPE_LINE);
618
+ st->isdetail = 1;
619
+
620
+ rrddim_add(st, "svctm", NULL, 1, 1, RRDDIM_ABSOLUTE);
621
+ }
622
+ else rrdset_next_usec(st, dt);
623
+
624
+ rrddim_set(st, "svctm", ((reads - last_reads) + (writes - last_writes)) ? (busy_ms - last_busy_ms) / ((reads - last_reads) + (writes - last_writes)) : 0);
625
+ rrdset_done(st);
626
+ }
627
+ }
628
+
629
+ // --------------------------------------------------------------------------
630
+ // space metrics
631
+
632
+ if(d->mount_point && (d->do_space || d->do_inodes) ) {
633
+ // collect space metrics using statvfs
634
+
635
+ if (statvfs(d->mount_point, &buff_statvfs) < 0)
636
+ error("Failed statvfs() for '%s' (disk '%s')", d->mount_point, d->disk);
637
+ else {
638
+ space_avail = buff_statvfs.f_bavail * buff_statvfs.f_bsize;
639
+ space_avail_root = (buff_statvfs.f_bfree - buff_statvfs.f_bavail) * buff_statvfs.f_bsize;
640
+ space_used = (buff_statvfs.f_blocks - buff_statvfs.f_bfree) * buff_statvfs.f_bsize;
641
+
642
+ inodes_avail = buff_statvfs.f_favail;
643
+ inodes_avail_root = buff_statvfs.f_ffree - buff_statvfs.f_favail;
644
+ inodes_used = buff_statvfs.f_files - buff_statvfs.f_ffree;
645
+
646
+ // verify we collected the metrics for the right disk.
647
+ // if not the mountpoint has changed.
648
+
649
+ if(stat(d->mount_point, &buff_stat) == -1)
650
+ error("Failed to stat() for '%s' (disk '%s')", d->mount_point, d->disk);
651
+ else {
652
+ if(major(buff_stat.st_dev) == major && minor(buff_stat.st_dev) == minor) {
653
+
654
+ // --------------------------------------------------------------------------
655
+
656
+ if(d->do_space == CONFIG_ONDEMAND_YES || (d->do_space == CONFIG_ONDEMAND_ONDEMAND && (space_avail || space_avail_root || space_used))) {
657
+ st = rrdset_find_bytype("disk_space", disk);
658
+ if(!st) {
659
+ st = rrdset_create("disk_space", disk, NULL, family, "disk.space", "Disk Space Usage", "GB", 2023, update_every, RRDSET_TYPE_STACKED);
660
+ st->isdetail = 1;
661
+
662
+ rrddim_add(st, "avail", NULL, 1, 1024*1024*1024, RRDDIM_ABSOLUTE);
663
+ rrddim_add(st, "used" , NULL, 1, 1024*1024*1024, RRDDIM_ABSOLUTE);
664
+ rrddim_add(st, "reserved_for_root", "reserved for root", 1, 1024*1024*1024, RRDDIM_ABSOLUTE);
665
+ }
666
+ else rrdset_next_usec(st, dt);
667
+
668
+ rrddim_set(st, "avail", space_avail);
669
+ rrddim_set(st, "used", space_used);
670
+ rrddim_set(st, "reserved_for_root", space_avail_root);
671
+ rrdset_done(st);
672
+ }
673
+
674
+ // --------------------------------------------------------------------------
675
+
676
+ if(d->do_inodes == CONFIG_ONDEMAND_YES || (d->do_inodes == CONFIG_ONDEMAND_ONDEMAND && (inodes_avail || inodes_avail_root || inodes_used))) {
677
+ st = rrdset_find_bytype("disk_inodes", disk);
678
+ if(!st) {
679
+ st = rrdset_create("disk_inodes", disk, NULL, family, "disk.inodes", "Disk Inodes Usage", "Inodes", 2024, update_every, RRDSET_TYPE_STACKED);
680
+ st->isdetail = 1;
681
+
682
+ rrddim_add(st, "avail", NULL, 1, 1, RRDDIM_ABSOLUTE);
683
+ rrddim_add(st, "used" , NULL, 1, 1, RRDDIM_ABSOLUTE);
684
+ rrddim_add(st, "reserved_for_root", "reserved for root", 1, 1, RRDDIM_ABSOLUTE);
685
+ }
686
+ else rrdset_next_usec(st, dt);
687
+
688
+ rrddim_set(st, "avail", inodes_avail);
689
+ rrddim_set(st, "used", inodes_used);
690
+ rrddim_set(st, "reserved_for_root", inodes_avail_root);
691
+ rrdset_done(st);
692
+ }
693
+ }
694
+ }
695
+ }
696
+ }
697
+ }
698
+
699
+ return 0;
700
}
src/proc_interrupts.c
+153
-153
@@ -3,11 +3,11 @@
3
#define MAX_INTERRUPT_NAME 50
4
5
struct interrupt {
6
- int used;
7
- char *id;
8
- char name[MAX_INTERRUPT_NAME + 1];
9
- unsigned long long total;
10
- unsigned long long value[];
6
+ int used;
7
+ char *id;
8
+ char name[MAX_INTERRUPT_NAME + 1];
9
+ unsigned long long total;
10
+ unsigned long long value[];
11
};
12
13
// since each interrupt is variable in size
@@ -18,157 +18,157 @@ struct interrupt {
18
#define irrindex(base, line, cpus) ((struct interrupt *)&((char *)(base))[line * recordsize(cpus)])
19
20
static inline struct interrupt *get_interrupts_array(int lines, int cpus) {
21
- static struct interrupt *irrs = NULL;
22
- static int allocated = 0;
21
+ static struct interrupt *irrs = NULL;
22
+ static int allocated = 0;
23
24
- if(lines < allocated) return irrs;
25
- else {
26
- irrs = (struct interrupt *)reallocz(irrs, lines * recordsize(cpus));
27
- allocated = lines;
28
- }
24
+ if(lines < allocated) return irrs;
25
+ else {
26
+ irrs = (struct interrupt *)reallocz(irrs, lines * recordsize(cpus));
27
+ allocated = lines;
28
+ }
29
30
- return irrs;
30
+ return irrs;
31
}
32
33
int do_proc_interrupts(int update_every, unsigned long long dt) {
34
- static procfile *ff = NULL;
35
- static int cpus = -1, do_per_core = -1;
36
- struct interrupt *irrs = NULL;
37
-
38
- if(dt) {};
39
-
40
- if(do_per_core == -1) do_per_core = config_get_boolean("plugin:proc:/proc/interrupts", "interrupts per core", 1);
41
-
42
- if(!ff) {
43
- char filename[FILENAME_MAX + 1];
44
- snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/interrupts");
45
- ff = procfile_open(config_get("plugin:proc:/proc/interrupts", "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT);
46
- }
47
- if(!ff) return 1;
48
-
49
- ff = procfile_readall(ff);
50
- if(!ff) return 0; // we return 0, so that we will retry to open it next time
51
-
52
- uint32_t lines = procfile_lines(ff), l;
53
- uint32_t words = procfile_linewords(ff, 0), w;
54
-
55
- if(!lines) {
56
- error("Cannot read /proc/interrupts, zero lines reported.");
57
- return 1;
58
- }
59
-
60
- // find how many CPUs are there
61
- if(cpus == -1) {
62
- cpus = 0;
63
- for(w = 0; w < words ; w++) {
64
- if(strncmp(procfile_lineword(ff, 0, w), "CPU", 3) == 0)
65
- cpus++;
66
- }
67
- }
68
-
69
- if(!cpus) {
70
- error("PLUGIN: PROC_INTERRUPTS: Cannot find the number of CPUs in /proc/interrupts");
71
- return 1;
72
- }
73
-
74
- // allocate the size we need;
75
- irrs = get_interrupts_array(lines, cpus);
76
- irrs[0].used = 0;
77
-
78
- // loop through all lines
79
- for(l = 1; l < lines ;l++) {
80
- struct interrupt *irr = irrindex(irrs, l, cpus);
81
- irr->used = 0;
82
- irr->total = 0;
83
-
84
- words = procfile_linewords(ff, l);
85
- if(!words) continue;
86
-
87
- irr->id = procfile_lineword(ff, l, 0);
88
- if(!irr->id || !irr->id[0]) continue;
89
-
90
- int idlen = strlen(irr->id);
91
- if(irr->id[idlen - 1] == ':')
92
- irr->id[idlen - 1] = '\0';
93
-
94
- int c;
95
- for(c = 0; c < cpus ;c++) {
96
- if((c + 1) < (int)words)
97
- irr->value[c] = strtoull(procfile_lineword(ff, l, (uint32_t)(c + 1)), NULL, 10);
98
- else
99
- irr->value[c] = 0;
100
-
101
- irr->total += irr->value[c];
102
- }
103
-
104
- if(isdigit(irr->id[0]) && (uint32_t)(cpus + 2) < words) {
105
- strncpyz(irr->name, procfile_lineword(ff, l, words - 1), MAX_INTERRUPT_NAME);
106
- int nlen = strlen(irr->name);
107
- if(nlen < (MAX_INTERRUPT_NAME-1)) {
108
- irr->name[nlen] = '_';
109
- strncpyz(&irr->name[nlen + 1], irr->id, MAX_INTERRUPT_NAME - nlen);
110
- }
111
- }
112
- else {
113
- strncpyz(irr->name, irr->id, MAX_INTERRUPT_NAME);
114
- }
115
-
116
- irr->used = 1;
117
- }
118
-
119
- RRDSET *st;
120
-
121
- // --------------------------------------------------------------------
122
-
123
- st = rrdset_find_bytype("system", "interrupts");
124
- if(!st) {
125
- st = rrdset_create("system", "interrupts", NULL, "interrupts", NULL, "System interrupts", "interrupts/s", 1000, update_every, RRDSET_TYPE_STACKED);
126
-
127
- for(l = 0; l < lines ;l++) {
128
- struct interrupt *irr = irrindex(irrs, l, cpus);
129
- if(!irr->used) continue;
130
- rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL);
131
- }
132
- }
133
- else rrdset_next(st);
134
-
135
- for(l = 0; l < lines ;l++) {
136
- struct interrupt *irr = irrindex(irrs, l, cpus);
137
- if(!irr->used) continue;
138
- rrddim_set(st, irr->id, irr->total);
139
- }
140
- rrdset_done(st);
141
-
142
- if(do_per_core) {
143
- int c;
144
-
145
- for(c = 0; c < cpus ; c++) {
146
- char id[256+1];
147
- snprintfz(id, 256, "cpu%d_interrupts", c);
148
-
149
- st = rrdset_find_bytype("cpu", id);
150
- if(!st) {
151
- char name[256+1], title[256+1];
152
- snprintfz(name, 256, "cpu%d_interrupts", c);
153
- snprintfz(title, 256, "CPU%d Interrupts", c);
154
- st = rrdset_create("cpu", id, name, "interrupts", "cpu.interrupts", title, "interrupts/s", 2000 + c, update_every, RRDSET_TYPE_STACKED);
155
-
156
- for(l = 0; l < lines ;l++) {
157
- struct interrupt *irr = irrindex(irrs, l, cpus);
158
- if(!irr->used) continue;
159
- rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL);
160
- }
161
- }
162
- else rrdset_next(st);
163
-
164
- for(l = 0; l < lines ;l++) {
165
- struct interrupt *irr = irrindex(irrs, l, cpus);
166
- if(!irr->used) continue;
167
- rrddim_set(st, irr->id, irr->value[c]);
168
- }
169
- rrdset_done(st);
170
- }
171
- }
172
-
173
- return 0;
34
+ static procfile *ff = NULL;
35
+ static int cpus = -1, do_per_core = -1;
36
+ struct interrupt *irrs = NULL;
37
+
38
+ if(dt) {};
39
+
40
+ if(do_per_core == -1) do_per_core = config_get_boolean("plugin:proc:/proc/interrupts", "interrupts per core", 1);
41
+
42
+ if(!ff) {
43
+ char filename[FILENAME_MAX + 1];
44
+ snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/interrupts");
45
+ ff = procfile_open(config_get("plugin:proc:/proc/interrupts", "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT);
46
+ }
47
+ if(!ff) return 1;
48
+
49
+ ff = procfile_readall(ff);
50
+ if(!ff) return 0; // we return 0, so that we will retry to open it next time
51
+
52
+ uint32_t lines = procfile_lines(ff), l;
53
+ uint32_t words = procfile_linewords(ff, 0), w;
54
+
55
+ if(!lines) {
56
+ error("Cannot read /proc/interrupts, zero lines reported.");
57
+ return 1;
58
+ }
59
+
60
+ // find how many CPUs are there
61
+ if(cpus == -1) {
62
+ cpus = 0;
63
+ for(w = 0; w < words ; w++) {
64
+ if(strncmp(procfile_lineword(ff, 0, w), "CPU", 3) == 0)
65
+ cpus++;
66
+ }
67
+ }
68
+
69
+ if(!cpus) {
70
+ error("PLUGIN: PROC_INTERRUPTS: Cannot find the number of CPUs in /proc/interrupts");
71
+ return 1;
72
+ }
73
+
74
+ // allocate the size we need;
75
+ irrs = get_interrupts_array(lines, cpus);
76
+ irrs[0].used = 0;
77
+
78
+ // loop through all lines
79
+ for(l = 1; l < lines ;l++) {
80
+ struct interrupt *irr = irrindex(irrs, l, cpus);
81
+ irr->used = 0;
82
+ irr->total = 0;
83
+
84
+ words = procfile_linewords(ff, l);
85
+ if(!words) continue;
86
+
87
+ irr->id = procfile_lineword(ff, l, 0);
88
+ if(!irr->id || !irr->id[0]) continue;
89
+
90
+ int idlen = strlen(irr->id);
91
+ if(irr->id[idlen - 1] == ':')
92
+ irr->id[idlen - 1] = '\0';
93
+
94
+ int c;
95
+ for(c = 0; c < cpus ;c++) {
96
+ if((c + 1) < (int)words)
97
+ irr->value[c] = strtoull(procfile_lineword(ff, l, (uint32_t)(c + 1)), NULL, 10);
98
+ else
99
+ irr->value[c] = 0;
100
+
101
+ irr->total += irr->value[c];
102
+ }
103
+
104
+ if(isdigit(irr->id[0]) && (uint32_t)(cpus + 2) < words) {
105
+ strncpyz(irr->name, procfile_lineword(ff, l, words - 1), MAX_INTERRUPT_NAME);
106
+ int nlen = strlen(irr->name);
107
+ if(nlen < (MAX_INTERRUPT_NAME-1)) {
108
+ irr->name[nlen] = '_';
109
+ strncpyz(&irr->name[nlen + 1], irr->id, MAX_INTERRUPT_NAME - nlen);
110
+ }
111
+ }
112
+ else {
113
+ strncpyz(irr->name, irr->id, MAX_INTERRUPT_NAME);
114
+ }
115
+
116
+ irr->used = 1;
117
+ }
118
+
119
+ RRDSET *st;
120
+
121
+ // --------------------------------------------------------------------
122
+
123
+ st = rrdset_find_bytype("system", "interrupts");
124
+ if(!st) {
125
+ st = rrdset_create("system", "interrupts", NULL, "interrupts", NULL, "System interrupts", "interrupts/s", 1000, update_every, RRDSET_TYPE_STACKED);
126
+
127
+ for(l = 0; l < lines ;l++) {
128
+ struct interrupt *irr = irrindex(irrs, l, cpus);
129
+ if(!irr->used) continue;
130
+ rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL);
131
+ }
132
+ }
133
+ else rrdset_next(st);
134
+
135
+ for(l = 0; l < lines ;l++) {
136
+ struct interrupt *irr = irrindex(irrs, l, cpus);
137
+ if(!irr->used) continue;
138
+ rrddim_set(st, irr->id, irr->total);
139
+ }
140
+ rrdset_done(st);
141
+
142
+ if(do_per_core) {
143
+ int c;
144
+
145
+ for(c = 0; c < cpus ; c++) {
146
+ char id[256+1];
147
+ snprintfz(id, 256, "cpu%d_interrupts", c);
148
+
149
+ st = rrdset_find_bytype("cpu", id);
150
+ if(!st) {
151
+ char name[256+1], title[256+1];
152
+ snprintfz(name, 256, "cpu%d_interrupts", c);
153
+ snprintfz(title, 256, "CPU%d Interrupts", c);
154
+ st = rrdset_create("cpu", id, name, "interrupts", "cpu.interrupts", title, "interrupts/s", 2000 + c, update_every, RRDSET_TYPE_STACKED);
155
+
156
+ for(l = 0; l < lines ;l++) {
157
+ struct interrupt *irr = irrindex(irrs, l, cpus);
158
+ if(!irr->used) continue;
159
+ rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL);
160
+ }
161
+ }
162
+ else rrdset_next(st);
163
+
164
+ for(l = 0; l < lines ;l++) {
165
+ struct interrupt *irr = irrindex(irrs, l, cpus);
166
+ if(!irr->used) continue;
167
+ rrddim_set(st, irr->id, irr->value[c]);
168
+ }
169
+ rrdset_done(st);
170
+ }
171
+ }
172
+
173
+ return 0;
174
}
src/proc_loadavg.c
+55
-55
@@ -4,77 +4,77 @@
4
#define MIN_LOADAVG_UPDATE_EVERY 5
5
6
int do_proc_loadavg(int update_every, unsigned long long dt) {
7
- static procfile *ff = NULL;
8
- static int do_loadavg = -1, do_all_processes = -1;
7
+ static procfile *ff = NULL;
8
+ static int do_loadavg = -1, do_all_processes = -1;
9
10
- if(dt) {};
10
+ if(dt) {};
11
12
- if(!ff) {
13
- char filename[FILENAME_MAX + 1];
14
- snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/loadavg");
15
- ff = procfile_open(config_get("plugin:proc:/proc/loadavg", "filename to monitor", filename), " \t,:|/", PROCFILE_FLAG_DEFAULT);
16
- }
17
- if(!ff) return 1;
12
+ if(!ff) {
13
+ char filename[FILENAME_MAX + 1];
14
+ snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/loadavg");
15
+ ff = procfile_open(config_get("plugin:proc:/proc/loadavg", "filename to monitor", filename), " \t,:|/", PROCFILE_FLAG_DEFAULT);
16
+ }
17
+ if(!ff) return 1;
18
19
- ff = procfile_readall(ff);
20
- if(!ff) return 0; // we return 0, so that we will retry to open it next time
19
+ ff = procfile_readall(ff);
20
+ if(!ff) return 0; // we return 0, so that we will retry to open it next time
21
22
- if(do_loadavg == -1) do_loadavg = config_get_boolean("plugin:proc:/proc/loadavg", "enable load average", 1);
23
- if(do_all_processes == -1) do_all_processes = config_get_boolean("plugin:proc:/proc/loadavg", "enable total processes", 1);
22
+ if(do_loadavg == -1) do_loadavg = config_get_boolean("plugin:proc:/proc/loadavg", "enable load average", 1);
23
+ if(do_all_processes == -1) do_all_processes = config_get_boolean("plugin:proc:/proc/loadavg", "enable total processes", 1);
24
25
- if(procfile_lines(ff) < 1) {
26
- error("/proc/loadavg has no lines.");
27
- return 1;
28
- }
29
- if(procfile_linewords(ff, 0) < 6) {
30
- error("/proc/loadavg has less than 6 words in it.");
31
- return 1;
32
- }
25
+ if(procfile_lines(ff) < 1) {
26
+ error("/proc/loadavg has no lines.");
27
+ return 1;
28
+ }
29
+ if(procfile_linewords(ff, 0) < 6) {
30
+ error("/proc/loadavg has less than 6 words in it.");
31
+ return 1;
32
+ }
33
34
- double load1 = strtod(procfile_lineword(ff, 0, 0), NULL);
35
- double load5 = strtod(procfile_lineword(ff, 0, 1), NULL);
36
- double load15 = strtod(procfile_lineword(ff, 0, 2), NULL);
34
+ double load1 = strtod(procfile_lineword(ff, 0, 0), NULL);
35
+ double load5 = strtod(procfile_lineword(ff, 0, 1), NULL);
36
+ double load15 = strtod(procfile_lineword(ff, 0, 2), NULL);
37
38
- //unsigned long long running_processes = strtoull(procfile_lineword(ff, 0, 3), NULL, 10);
39
- unsigned long long active_processes = strtoull(procfile_lineword(ff, 0, 4), NULL, 10);
40
- //unsigned long long next_pid = strtoull(procfile_lineword(ff, 0, 5), NULL, 10);
38
+ //unsigned long long running_processes = strtoull(procfile_lineword(ff, 0, 3), NULL, 10);
39
+ unsigned long long active_processes = strtoull(procfile_lineword(ff, 0, 4), NULL, 10);
40
+ //unsigned long long next_pid = strtoull(procfile_lineword(ff, 0, 5), NULL, 10);
41
42
43
- RRDSET *st;
43
+ RRDSET *st;
44
45
- // --------------------------------------------------------------------
45
+ // --------------------------------------------------------------------
46
47
- if(do_loadavg) {
48
- st = rrdset_find_byname("system.load");
49
- if(!st) {
50
- st = rrdset_create("system", "load", NULL, "load", NULL, "System Load Average", "load", 100, (update_every < MIN_LOADAVG_UPDATE_EVERY)?MIN_LOADAVG_UPDATE_EVERY:update_every, RRDSET_TYPE_LINE);
47
+ if(do_loadavg) {
48
+ st = rrdset_find_byname("system.load");
49
+ if(!st) {
50
+ st = rrdset_create("system", "load", NULL, "load", NULL, "System Load Average", "load", 100, (update_every < MIN_LOADAVG_UPDATE_EVERY)?MIN_LOADAVG_UPDATE_EVERY:update_every, RRDSET_TYPE_LINE);
51
52
- rrddim_add(st, "load1", NULL, 1, 1000, RRDDIM_ABSOLUTE);
53
- rrddim_add(st, "load5", NULL, 1, 1000, RRDDIM_ABSOLUTE);
54
- rrddim_add(st, "load15", NULL, 1, 1000, RRDDIM_ABSOLUTE);
55
- }
56
- else rrdset_next(st);
52
+ rrddim_add(st, "load1", NULL, 1, 1000, RRDDIM_ABSOLUTE);
53
+ rrddim_add(st, "load5", NULL, 1, 1000, RRDDIM_ABSOLUTE);
54
+ rrddim_add(st, "load15", NULL, 1, 1000, RRDDIM_ABSOLUTE);
55
+ }
56
+ else rrdset_next(st);
57
58
- rrddim_set(st, "load1", load1 * 1000);
59
- rrddim_set(st, "load5", load5 * 1000);
60
- rrddim_set(st, "load15", load15 * 1000);
61
- rrdset_done(st);
62
- }
58
+ rrddim_set(st, "load1", load1 * 1000);
59
+ rrddim_set(st, "load5", load5 * 1000);
60
+ rrddim_set(st, "load15", load15 * 1000);
61
+ rrdset_done(st);
62
+ }
63
64
- // --------------------------------------------------------------------
64
+ // --------------------------------------------------------------------
65
66
- if(do_all_processes) {
67
- st = rrdset_find_byname("system.active_processes");
68
- if(!st) {
69
- st = rrdset_create("system", "active_processes", NULL, "processes", NULL, "System Active Processes", "processes", 750, update_every, RRDSET_TYPE_LINE);
66
+ if(do_all_processes) {
67
+ st = rrdset_find_byname("system.active_processes");
68
+ if(!st) {
69
+ st = rrdset_create("system", "active_processes", NULL, "processes", NULL, "System Active Processes", "processes", 750, update_every, RRDSET_TYPE_LINE);
70
71
- rrddim_add(st, "active", NULL, 1, 1, RRDDIM_ABSOLUTE);
72
- }
73
- else rrdset_next(st);
71
+ rrddim_add(st, "active", NULL, 1, 1, RRDDIM_ABSOLUTE);
72
+ }
73
+ else rrdset_next(st);
74
75
- rrddim_set(st, "active", active_processes);
76
- rrdset_done(st);
77
- }
75
+ rrddim_set(st, "active", active_processes);
76
+ rrdset_done(st);
77
+ }
78
79
- return 0;
79
+ return 0;
80
}
src/proc_meminfo.c
+234
-234
@@ -4,239 +4,239 @@
4
#define MAX_PROC_MEMINFO_NAME 1024
5
6
int do_proc_meminfo(int update_every, unsigned long long dt) {
7
- static procfile *ff = NULL;
8
-
9
- static int do_ram = -1, do_swap = -1, do_hwcorrupt = -1, do_committed = -1, do_writeback = -1, do_kernel = -1, do_slab = -1;
10
-
11
- if(do_ram == -1) do_ram = config_get_boolean("plugin:proc:/proc/meminfo", "system ram", 1);
12
- if(do_swap == -1) do_swap = config_get_boolean("plugin:proc:/proc/meminfo", "system swap", 1);
13
- if(do_hwcorrupt == -1) do_hwcorrupt = config_get_boolean_ondemand("plugin:proc:/proc/meminfo", "hardware corrupted ECC", CONFIG_ONDEMAND_ONDEMAND);
14
- if(do_committed == -1) do_committed = config_get_boolean("plugin:proc:/proc/meminfo", "committed memory", 1);
15
- if(do_writeback == -1) do_writeback = config_get_boolean("plugin:proc:/proc/meminfo", "writeback memory", 1);
16
- if(do_kernel == -1) do_kernel = config_get_boolean("plugin:proc:/proc/meminfo", "kernel memory", 1);
17
- if(do_slab == -1) do_slab = config_get_boolean("plugin:proc:/proc/meminfo", "slab memory", 1);
18
-
19
- if(dt) {};
20
-
21
- if(!ff) {
22
- char filename[FILENAME_MAX + 1];
23
- snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/meminfo");
24
- ff = procfile_open(config_get("plugin:proc:/proc/meminfo", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
25
- }
26
- if(!ff) return 1;
27
-
28
- ff = procfile_readall(ff);
29
- if(!ff) return 0; // we return 0, so that we will retry to open it next time
30
-
31
- uint32_t lines = procfile_lines(ff), l;
32
- uint32_t words;
33
-
34
- int hwcorrupted = 0;
35
-
36
- unsigned long long MemTotal = 0, MemFree = 0, Buffers = 0, Cached = 0, SwapCached = 0,
37
- Active = 0, Inactive = 0, ActiveAnon = 0, InactiveAnon = 0, ActiveFile = 0, InactiveFile = 0,
38
- Unevictable = 0, Mlocked = 0, SwapTotal = 0, SwapFree = 0, Dirty = 0, Writeback = 0, AnonPages = 0,
39
- Mapped = 0, Shmem = 0, Slab = 0, SReclaimable = 0, SUnreclaim = 0, KernelStack = 0, PageTables = 0,
40
- NFS_Unstable = 0, Bounce = 0, WritebackTmp = 0, CommitLimit = 0, Committed_AS = 0,
41
- VmallocTotal = 0, VmallocUsed = 0, VmallocChunk = 0,
42
- AnonHugePages = 0, HugePages_Total = 0, HugePages_Free = 0, HugePages_Rsvd = 0, HugePages_Surp = 0, Hugepagesize = 0,
43
- DirectMap4k = 0, DirectMap2M = 0, HardwareCorrupted = 0;
44
-
45
- for(l = 0; l < lines ;l++) {
46
- words = procfile_linewords(ff, l);
47
- if(words < 2) continue;
48
-
49
- char *name = procfile_lineword(ff, l, 0);
50
- unsigned long long value = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
51
-
52
- if(!MemTotal && strcmp(name, "MemTotal") == 0) MemTotal = value;
53
- else if(!MemFree && strcmp(name, "MemFree") == 0) MemFree = value;
54
- else if(!Buffers && strcmp(name, "Buffers") == 0) Buffers = value;
55
- else if(!Cached && strcmp(name, "Cached") == 0) Cached = value;
56
- else if(!SwapCached && strcmp(name, "SwapCached") == 0) SwapCached = value;
57
- else if(!Active && strcmp(name, "Active") == 0) Active = value;
58
- else if(!Inactive && strcmp(name, "Inactive") == 0) Inactive = value;
59
- else if(!ActiveAnon && strcmp(name, "ActiveAnon") == 0) ActiveAnon = value;
60
- else if(!InactiveAnon && strcmp(name, "InactiveAnon") == 0) InactiveAnon = value;
61
- else if(!ActiveFile && strcmp(name, "ActiveFile") == 0) ActiveFile = value;
62
- else if(!InactiveFile && strcmp(name, "InactiveFile") == 0) InactiveFile = value;
63
- else if(!Unevictable && strcmp(name, "Unevictable") == 0) Unevictable = value;
64
- else if(!Mlocked && strcmp(name, "Mlocked") == 0) Mlocked = value;
65
- else if(!SwapTotal && strcmp(name, "SwapTotal") == 0) SwapTotal = value;
66
- else if(!SwapFree && strcmp(name, "SwapFree") == 0) SwapFree = value;
67
- else if(!Dirty && strcmp(name, "Dirty") == 0) Dirty = value;
68
- else if(!Writeback && strcmp(name, "Writeback") == 0) Writeback = value;
69
- else if(!AnonPages && strcmp(name, "AnonPages") == 0) AnonPages = value;
70
- else if(!Mapped && strcmp(name, "Mapped") == 0) Mapped = value;
71
- else if(!Shmem && strcmp(name, "Shmem") == 0) Shmem = value;
72
- else if(!Slab && strcmp(name, "Slab") == 0) Slab = value;
73
- else if(!SReclaimable && strcmp(name, "SReclaimable") == 0) SReclaimable = value;
74
- else if(!SUnreclaim && strcmp(name, "SUnreclaim") == 0) SUnreclaim = value;
75
- else if(!KernelStack && strcmp(name, "KernelStack") == 0) KernelStack = value;
76
- else if(!PageTables && strcmp(name, "PageTables") == 0) PageTables = value;
77
- else if(!NFS_Unstable && strcmp(name, "NFS_Unstable") == 0) NFS_Unstable = value;
78
- else if(!Bounce && strcmp(name, "Bounce") == 0) Bounce = value;
79
- else if(!WritebackTmp && strcmp(name, "WritebackTmp") == 0) WritebackTmp = value;
80
- else if(!CommitLimit && strcmp(name, "CommitLimit") == 0) CommitLimit = value;
81
- else if(!Committed_AS && strcmp(name, "Committed_AS") == 0) Committed_AS = value;
82
- else if(!VmallocTotal && strcmp(name, "VmallocTotal") == 0) VmallocTotal = value;
83
- else if(!VmallocUsed && strcmp(name, "VmallocUsed") == 0) VmallocUsed = value;
84
- else if(!VmallocChunk && strcmp(name, "VmallocChunk") == 0) VmallocChunk = value;
85
- else if(!HardwareCorrupted && strcmp(name, "HardwareCorrupted") == 0) { HardwareCorrupted = value; hwcorrupted = 1; }
86
- else if(!AnonHugePages && strcmp(name, "AnonHugePages") == 0) AnonHugePages = value;
87
- else if(!HugePages_Total && strcmp(name, "HugePages_Total") == 0) HugePages_Total = value;
88
- else if(!HugePages_Free && strcmp(name, "HugePages_Free") == 0) HugePages_Free = value;
89
- else if(!HugePages_Rsvd && strcmp(name, "HugePages_Rsvd") == 0) HugePages_Rsvd = value;
90
- else if(!HugePages_Surp && strcmp(name, "HugePages_Surp") == 0) HugePages_Surp = value;
91
- else if(!Hugepagesize && strcmp(name, "Hugepagesize") == 0) Hugepagesize = value;
92
- else if(!DirectMap4k && strcmp(name, "DirectMap4k") == 0) DirectMap4k = value;
93
- else if(!DirectMap2M && strcmp(name, "DirectMap2M") == 0) DirectMap2M = value;
94
- }
95
-
96
- RRDSET *st;
97
-
98
- // --------------------------------------------------------------------
99
-
100
- // http://stackoverflow.com/questions/3019748/how-to-reliably-measure-available-memory-in-linux
101
- unsigned long long MemUsed = MemTotal - MemFree - Cached - Buffers;
102
-
103
- if(do_ram) {
104
- st = rrdset_find("system.ram");
105
- if(!st) {
106
- st = rrdset_create("system", "ram", NULL, "ram", NULL, "System RAM", "MB", 200, update_every, RRDSET_TYPE_STACKED);
107
-
108
- rrddim_add(st, "buffers", NULL, 1, 1024, RRDDIM_ABSOLUTE);
109
- rrddim_add(st, "used", NULL, 1, 1024, RRDDIM_ABSOLUTE);
110
- rrddim_add(st, "cached", NULL, 1, 1024, RRDDIM_ABSOLUTE);
111
- rrddim_add(st, "free", NULL, 1, 1024, RRDDIM_ABSOLUTE);
112
- }
113
- else rrdset_next(st);
114
-
115
- rrddim_set(st, "used", MemUsed);
116
- rrddim_set(st, "free", MemFree);
117
- rrddim_set(st, "cached", Cached);
118
- rrddim_set(st, "buffers", Buffers);
119
- rrdset_done(st);
120
- }
121
-
122
- // --------------------------------------------------------------------
123
-
124
- unsigned long long SwapUsed = SwapTotal - SwapFree;
125
-
126
- if(do_swap) {
127
- st = rrdset_find("system.swap");
128
- if(!st) {
129
- st = rrdset_create("system", "swap", NULL, "swap", NULL, "System Swap", "MB", 201, update_every, RRDSET_TYPE_STACKED);
130
- st->isdetail = 1;
131
-
132
- rrddim_add(st, "free", NULL, 1, 1024, RRDDIM_ABSOLUTE);
133
- rrddim_add(st, "used", NULL, 1, 1024, RRDDIM_ABSOLUTE);
134
- }
135
- else rrdset_next(st);
136
-
137
- rrddim_set(st, "used", SwapUsed);
138
- rrddim_set(st, "free", SwapFree);
139
- rrdset_done(st);
140
- }
141
-
142
- // --------------------------------------------------------------------
143
-
144
- if(hwcorrupted && do_hwcorrupt && HardwareCorrupted > 0) {
145
- do_hwcorrupt = CONFIG_ONDEMAND_YES;
146
-
147
- st = rrdset_find("mem.hwcorrupt");
148
- if(!st) {
149
- st = rrdset_create("mem", "hwcorrupt", NULL, "errors", NULL, "Hardware Corrupted ECC", "MB", 9000, update_every, RRDSET_TYPE_LINE);
150
- st->isdetail = 1;
151
-
152
- rrddim_add(st, "HardwareCorrupted", NULL, 1, 1024, RRDDIM_ABSOLUTE);
153
- }
154
- else rrdset_next(st);
155
-
156
- rrddim_set(st, "HardwareCorrupted", HardwareCorrupted);
157
- rrdset_done(st);
158
- }
159
-
160
- // --------------------------------------------------------------------
161
-
162
- if(do_committed) {
163
- st = rrdset_find("mem.committed");
164
- if(!st) {
165
- st = rrdset_create("mem", "committed", NULL, "system", NULL, "Committed (Allocated) Memory", "MB", 5000, update_every, RRDSET_TYPE_AREA);
166
- st->isdetail = 1;
167
-
168
- rrddim_add(st, "Committed_AS", NULL, 1, 1024, RRDDIM_ABSOLUTE);
169
- }
170
- else rrdset_next(st);
171
-
172
- rrddim_set(st, "Committed_AS", Committed_AS);
173
- rrdset_done(st);
174
- }
175
-
176
- // --------------------------------------------------------------------
177
-
178
- if(do_writeback) {
179
- st = rrdset_find("mem.writeback");
180
- if(!st) {
181
- st = rrdset_create("mem", "writeback", NULL, "kernel", NULL, "Writeback Memory", "MB", 4000, update_every, RRDSET_TYPE_LINE);
182
- st->isdetail = 1;
183
-
184
- rrddim_add(st, "Dirty", NULL, 1, 1024, RRDDIM_ABSOLUTE);
185
- rrddim_add(st, "Writeback", NULL, 1, 1024, RRDDIM_ABSOLUTE);
186
- rrddim_add(st, "FuseWriteback", NULL, 1, 1024, RRDDIM_ABSOLUTE);
187
- rrddim_add(st, "NfsWriteback", NULL, 1, 1024, RRDDIM_ABSOLUTE);
188
- rrddim_add(st, "Bounce", NULL, 1, 1024, RRDDIM_ABSOLUTE);
189
- }
190
- else rrdset_next(st);
191
-
192
- rrddim_set(st, "Dirty", Dirty);
193
- rrddim_set(st, "Writeback", Writeback);
194
- rrddim_set(st, "FuseWriteback", WritebackTmp);
195
- rrddim_set(st, "NfsWriteback", NFS_Unstable);
196
- rrddim_set(st, "Bounce", Bounce);
197
- rrdset_done(st);
198
- }
199
-
200
- // --------------------------------------------------------------------
201
-
202
- if(do_kernel) {
203
- st = rrdset_find("mem.kernel");
204
- if(!st) {
205
- st = rrdset_create("mem", "kernel", NULL, "kernel", NULL, "Memory Used by Kernel", "MB", 6000, update_every, RRDSET_TYPE_STACKED);
206
- st->isdetail = 1;
207
-
208
- rrddim_add(st, "Slab", NULL, 1, 1024, RRDDIM_ABSOLUTE);
209
- rrddim_add(st, "KernelStack", NULL, 1, 1024, RRDDIM_ABSOLUTE);
210
- rrddim_add(st, "PageTables", NULL, 1, 1024, RRDDIM_ABSOLUTE);
211
- rrddim_add(st, "VmallocUsed", NULL, 1, 1024, RRDDIM_ABSOLUTE);
212
- }
213
- else rrdset_next(st);
214
-
215
- rrddim_set(st, "KernelStack", KernelStack);
216
- rrddim_set(st, "Slab", Slab);
217
- rrddim_set(st, "PageTables", PageTables);
218
- rrddim_set(st, "VmallocUsed", VmallocUsed);
219
- rrdset_done(st);
220
- }
221
-
222
- // --------------------------------------------------------------------
223
-
224
- if(do_slab) {
225
- st = rrdset_find("mem.slab");
226
- if(!st) {
227
- st = rrdset_create("mem", "slab", NULL, "slab", NULL, "Reclaimable Kernel Memory", "MB", 6500, update_every, RRDSET_TYPE_STACKED);
228
- st->isdetail = 1;
229
-
230
- rrddim_add(st, "reclaimable", NULL, 1, 1024, RRDDIM_ABSOLUTE);
231
- rrddim_add(st, "unreclaimable", NULL, 1, 1024, RRDDIM_ABSOLUTE);
232
- }
233
- else rrdset_next(st);
234
-
235
- rrddim_set(st, "reclaimable", SReclaimable);
236
- rrddim_set(st, "unreclaimable", SUnreclaim);
237
- rrdset_done(st);
238
- }
239
-
240
- return 0;
7
+ static procfile *ff = NULL;
8
+
9
+ static int do_ram = -1, do_swap = -1, do_hwcorrupt = -1, do_committed = -1, do_writeback = -1, do_kernel = -1, do_slab = -1;
10
+
11
+ if(do_ram == -1) do_ram = config_get_boolean("plugin:proc:/proc/meminfo", "system ram", 1);
12
+ if(do_swap == -1) do_swap = config_get_boolean("plugin:proc:/proc/meminfo", "system swap", 1);
13
+ if(do_hwcorrupt == -1) do_hwcorrupt = config_get_boolean_ondemand("plugin:proc:/proc/meminfo", "hardware corrupted ECC", CONFIG_ONDEMAND_ONDEMAND);
14
+ if(do_committed == -1) do_committed = config_get_boolean("plugin:proc:/proc/meminfo", "committed memory", 1);
15
+ if(do_writeback == -1) do_writeback = config_get_boolean("plugin:proc:/proc/meminfo", "writeback memory", 1);
16
+ if(do_kernel == -1) do_kernel = config_get_boolean("plugin:proc:/proc/meminfo", "kernel memory", 1);
17
+ if(do_slab == -1) do_slab = config_get_boolean("plugin:proc:/proc/meminfo", "slab memory", 1);
18
+
19
+ if(dt) {};
20
+
21
+ if(!ff) {
22
+ char filename[FILENAME_MAX + 1];
23
+ snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/meminfo");
24
+ ff = procfile_open(config_get("plugin:proc:/proc/meminfo", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
25
+ }
26
+ if(!ff) return 1;
27
+
28
+ ff = procfile_readall(ff);
29
+ if(!ff) return 0; // we return 0, so that we will retry to open it next time
30
+
31
+ uint32_t lines = procfile_lines(ff), l;
32
+ uint32_t words;
33
+
34
+ int hwcorrupted = 0;
35
+
36
+ unsigned long long MemTotal = 0, MemFree = 0, Buffers = 0, Cached = 0, SwapCached = 0,
37
+ Active = 0, Inactive = 0, ActiveAnon = 0, InactiveAnon = 0, ActiveFile = 0, InactiveFile = 0,
38
+ Unevictable = 0, Mlocked = 0, SwapTotal = 0, SwapFree = 0, Dirty = 0, Writeback = 0, AnonPages = 0,
39
+ Mapped = 0, Shmem = 0, Slab = 0, SReclaimable = 0, SUnreclaim = 0, KernelStack = 0, PageTables = 0,
40
+ NFS_Unstable = 0, Bounce = 0, WritebackTmp = 0, CommitLimit = 0, Committed_AS = 0,
41
+ VmallocTotal = 0, VmallocUsed = 0, VmallocChunk = 0,
42
+ AnonHugePages = 0, HugePages_Total = 0, HugePages_Free = 0, HugePages_Rsvd = 0, HugePages_Surp = 0, Hugepagesize = 0,
43
+ DirectMap4k = 0, DirectMap2M = 0, HardwareCorrupted = 0;
44
+
45
+ for(l = 0; l < lines ;l++) {
46
+ words = procfile_linewords(ff, l);
47
+ if(words < 2) continue;
48
+
49
+ char *name = procfile_lineword(ff, l, 0);
50
+ unsigned long long value = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
51
+
52
+ if(!MemTotal && strcmp(name, "MemTotal") == 0) MemTotal = value;
53
+ else if(!MemFree && strcmp(name, "MemFree") == 0) MemFree = value;
54
+ else if(!Buffers && strcmp(name, "Buffers") == 0) Buffers = value;
55
+ else if(!Cached && strcmp(name, "Cached") == 0) Cached = value;
56
+ else if(!SwapCached && strcmp(name, "SwapCached") == 0) SwapCached = value;
57
+ else if(!Active && strcmp(name, "Active") == 0) Active = value;
58
+ else if(!Inactive && strcmp(name, "Inactive") == 0) Inactive = value;
59
+ else if(!ActiveAnon && strcmp(name, "ActiveAnon") == 0) ActiveAnon = value;
60
+ else if(!InactiveAnon && strcmp(name, "InactiveAnon") == 0) InactiveAnon = value;
61
+ else if(!ActiveFile && strcmp(name, "ActiveFile") == 0) ActiveFile = value;
62
+ else if(!InactiveFile && strcmp(name, "InactiveFile") == 0) InactiveFile = value;
63
+ else if(!Unevictable && strcmp(name, "Unevictable") == 0) Unevictable = value;
64
+ else if(!Mlocked && strcmp(name, "Mlocked") == 0) Mlocked = value;
65
+ else if(!SwapTotal && strcmp(name, "SwapTotal") == 0) SwapTotal = value;
66
+ else if(!SwapFree && strcmp(name, "SwapFree") == 0) SwapFree = value;
67
+ else if(!Dirty && strcmp(name, "Dirty") == 0) Dirty = value;
68
+ else if(!Writeback && strcmp(name, "Writeback") == 0) Writeback = value;
69
+ else if(!AnonPages && strcmp(name, "AnonPages") == 0) AnonPages = value;
70
+ else if(!Mapped && strcmp(name, "Mapped") == 0) Mapped = value;
71
+ else if(!Shmem && strcmp(name, "Shmem") == 0) Shmem = value;
72
+ else if(!Slab && strcmp(name, "Slab") == 0) Slab = value;
73
+ else if(!SReclaimable && strcmp(name, "SReclaimable") == 0) SReclaimable = value;
74
+ else if(!SUnreclaim && strcmp(name, "SUnreclaim") == 0) SUnreclaim = value;
75
+ else if(!KernelStack && strcmp(name, "KernelStack") == 0) KernelStack = value;
76
+ else if(!PageTables && strcmp(name, "PageTables") == 0) PageTables = value;
77
+ else if(!NFS_Unstable && strcmp(name, "NFS_Unstable") == 0) NFS_Unstable = value;
78
+ else if(!Bounce && strcmp(name, "Bounce") == 0) Bounce = value;
79
+ else if(!WritebackTmp && strcmp(name, "WritebackTmp") == 0) WritebackTmp = value;
80
+ else if(!CommitLimit && strcmp(name, "CommitLimit") == 0) CommitLimit = value;
81
+ else if(!Committed_AS && strcmp(name, "Committed_AS") == 0) Committed_AS = value;
82
+ else if(!VmallocTotal && strcmp(name, "VmallocTotal") == 0) VmallocTotal = value;
83
+ else if(!VmallocUsed && strcmp(name, "VmallocUsed") == 0) VmallocUsed = value;
84
+ else if(!VmallocChunk && strcmp(name, "VmallocChunk") == 0) VmallocChunk = value;
85
+ else if(!HardwareCorrupted && strcmp(name, "HardwareCorrupted") == 0) { HardwareCorrupted = value; hwcorrupted = 1; }
86
+ else if(!AnonHugePages && strcmp(name, "AnonHugePages") == 0) AnonHugePages = value;
87
+ else if(!HugePages_Total && strcmp(name, "HugePages_Total") == 0) HugePages_Total = value;
88
+ else if(!HugePages_Free && strcmp(name, "HugePages_Free") == 0) HugePages_Free = value;
89
+ else if(!HugePages_Rsvd && strcmp(name, "HugePages_Rsvd") == 0) HugePages_Rsvd = value;
90
+ else if(!HugePages_Surp && strcmp(name, "HugePages_Surp") == 0) HugePages_Surp = value;
91
+ else if(!Hugepagesize && strcmp(name, "Hugepagesize") == 0) Hugepagesize = value;
92
+ else if(!DirectMap4k && strcmp(name, "DirectMap4k") == 0) DirectMap4k = value;
93
+ else if(!DirectMap2M && strcmp(name, "DirectMap2M") == 0) DirectMap2M = value;
94
+ }
95
+
96
+ RRDSET *st;
97
+
98
+ // --------------------------------------------------------------------
99
+
100
+ // http://stackoverflow.com/questions/3019748/how-to-reliably-measure-available-memory-in-linux
101
+ unsigned long long MemUsed = MemTotal - MemFree - Cached - Buffers;
102
+
103
+ if(do_ram) {
104
+ st = rrdset_find("system.ram");
105
+ if(!st) {
106
+ st = rrdset_create("system", "ram", NULL, "ram", NULL, "System RAM", "MB", 200, update_every, RRDSET_TYPE_STACKED);
107
+
108
+ rrddim_add(st, "buffers", NULL, 1, 1024, RRDDIM_ABSOLUTE);
109
+ rrddim_add(st, "used", NULL, 1, 1024, RRDDIM_ABSOLUTE);
110
+ rrddim_add(st, "cached", NULL, 1, 1024, RRDDIM_ABSOLUTE);
111
+ rrddim_add(st, "free", NULL, 1, 1024, RRDDIM_ABSOLUTE);
112
+ }
113
+ else rrdset_next(st);
114
+
115
+ rrddim_set(st, "used", MemUsed);
116
+ rrddim_set(st, "free", MemFree);
117
+ rrddim_set(st, "cached", Cached);
118
+ rrddim_set(st, "buffers", Buffers);
119
+ rrdset_done(st);
120
+ }
121
+
122
+ // --------------------------------------------------------------------
123
+
124
+ unsigned long long SwapUsed = SwapTotal - SwapFree;
125
+
126
+ if(do_swap) {
127
+ st = rrdset_find("system.swap");
128
+ if(!st) {
129
+ st = rrdset_create("system", "swap", NULL, "swap", NULL, "System Swap", "MB", 201, update_every, RRDSET_TYPE_STACKED);
130
+ st->isdetail = 1;
131
+
132
+ rrddim_add(st, "free", NULL, 1, 1024, RRDDIM_ABSOLUTE);
133
+ rrddim_add(st, "used", NULL, 1, 1024, RRDDIM_ABSOLUTE);
134
+ }
135
+ else rrdset_next(st);
136
+
137
+ rrddim_set(st, "used", SwapUsed);
138
+ rrddim_set(st, "free", SwapFree);
139
+ rrdset_done(st);
140
+ }
141
+
142
+ // --------------------------------------------------------------------
143
+
144
+ if(hwcorrupted && do_hwcorrupt && HardwareCorrupted > 0) {
145
+ do_hwcorrupt = CONFIG_ONDEMAND_YES;
146
+
147
+ st = rrdset_find("mem.hwcorrupt");
148
+ if(!st) {
149
+ st = rrdset_create("mem", "hwcorrupt", NULL, "errors", NULL, "Hardware Corrupted ECC", "MB", 9000, update_every, RRDSET_TYPE_LINE);
150
+ st->isdetail = 1;
151
+
152
+ rrddim_add(st, "HardwareCorrupted", NULL, 1, 1024, RRDDIM_ABSOLUTE);
153
+ }
154
+ else rrdset_next(st);
155
+
156
+ rrddim_set(st, "HardwareCorrupted", HardwareCorrupted);
157
+ rrdset_done(st);
158
+ }
159
+
160
+ // --------------------------------------------------------------------
161
+
162
+ if(do_committed) {
163
+ st = rrdset_find("mem.committed");
164
+ if(!st) {
165
+ st = rrdset_create("mem", "committed", NULL, "system", NULL, "Committed (Allocated) Memory", "MB", 5000, update_every, RRDSET_TYPE_AREA);
166
+ st->isdetail = 1;
167
+
168
+ rrddim_add(st, "Committed_AS", NULL, 1, 1024, RRDDIM_ABSOLUTE);
169
+ }
170
+ else rrdset_next(st);
171
+
172
+ rrddim_set(st, "Committed_AS", Committed_AS);
173
+ rrdset_done(st);
174
+ }
175
+
176
+ // --------------------------------------------------------------------
177
+
178
+ if(do_writeback) {
179
+ st = rrdset_find("mem.writeback");
180
+ if(!st) {
181
+ st = rrdset_create("mem", "writeback", NULL, "kernel", NULL, "Writeback Memory", "MB", 4000, update_every, RRDSET_TYPE_LINE);
182
+ st->isdetail = 1;
183
+
184
+ rrddim_add(st, "Dirty", NULL, 1, 1024, RRDDIM_ABSOLUTE);
185
+ rrddim_add(st, "Writeback", NULL, 1, 1024, RRDDIM_ABSOLUTE);
186
+ rrddim_add(st, "FuseWriteback", NULL, 1, 1024, RRDDIM_ABSOLUTE);
187
+ rrddim_add(st, "NfsWriteback", NULL, 1, 1024, RRDDIM_ABSOLUTE);
188
+ rrddim_add(st, "Bounce", NULL, 1, 1024, RRDDIM_ABSOLUTE);
189
+ }
190
+ else rrdset_next(st);
191
+
192
+ rrddim_set(st, "Dirty", Dirty);
193
+ rrddim_set(st, "Writeback", Writeback);
194
+ rrddim_set(st, "FuseWriteback", WritebackTmp);
195
+ rrddim_set(st, "NfsWriteback", NFS_Unstable);
196
+ rrddim_set(st, "Bounce", Bounce);
197
+ rrdset_done(st);
198
+ }
199
+
200
+ // --------------------------------------------------------------------
201
+
202
+ if(do_kernel) {
203
+ st = rrdset_find("mem.kernel");
204
+ if(!st) {
205
+ st = rrdset_create("mem", "kernel", NULL, "kernel", NULL, "Memory Used by Kernel", "MB", 6000, update_every, RRDSET_TYPE_STACKED);
206
+ st->isdetail = 1;
207
+
208
+ rrddim_add(st, "Slab", NULL, 1, 1024, RRDDIM_ABSOLUTE);
209
+ rrddim_add(st, "KernelStack", NULL, 1, 1024, RRDDIM_ABSOLUTE);
210
+ rrddim_add(st, "PageTables", NULL, 1, 1024, RRDDIM_ABSOLUTE);
211
+ rrddim_add(st, "VmallocUsed", NULL, 1, 1024, RRDDIM_ABSOLUTE);
212
+ }
213
+ else rrdset_next(st);
214
+
215
+ rrddim_set(st, "KernelStack", KernelStack);
216
+ rrddim_set(st, "Slab", Slab);
217
+ rrddim_set(st, "PageTables", PageTables);
218
+ rrddim_set(st, "VmallocUsed", VmallocUsed);
219
+ rrdset_done(st);
220
+ }
221
+
222
+ // --------------------------------------------------------------------
223
+
224
+ if(do_slab) {
225
+ st = rrdset_find("mem.slab");
226
+ if(!st) {
227
+ st = rrdset_create("mem", "slab", NULL, "slab", NULL, "Reclaimable Kernel Memory", "MB", 6500, update_every, RRDSET_TYPE_STACKED);
228
+ st->isdetail = 1;
229
+
230
+ rrddim_add(st, "reclaimable", NULL, 1, 1024, RRDDIM_ABSOLUTE);
231
+ rrddim_add(st, "unreclaimable", NULL, 1, 1024, RRDDIM_ABSOLUTE);
232
+ }
233
+ else rrdset_next(st);
234
+
235
+ rrddim_set(st, "reclaimable", SReclaimable);
236
+ rrddim_set(st, "unreclaimable", SUnreclaim);
237
+ rrdset_done(st);
238
+ }
239
+
240
+ return 0;
241
}
242
src/proc_net_dev.c
+232
-232
@@ -1,236 +1,236 @@
1
#include "common.h"
2
3
int do_proc_net_dev(int update_every, unsigned long long dt) {
4
- static procfile *ff = NULL;
5
- static int enable_new_interfaces = -1, enable_ifb_interfaces = -1;
6
- static int do_bandwidth = -1, do_packets = -1, do_errors = -1, do_drops = -1, do_fifo = -1, do_compressed = -1, do_events = -1;
7
-
8
- if(dt) {};
9
-
10
- if(!ff) {
11
- char filename[FILENAME_MAX + 1];
12
- snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/dev");
13
- ff = procfile_open(config_get("plugin:proc:/proc/net/dev", "filename to monitor", filename), " \t,:|", PROCFILE_FLAG_DEFAULT);
14
- }
15
- if(!ff) return 1;
16
-
17
- ff = procfile_readall(ff);
18
- if(!ff) return 0; // we return 0, so that we will retry to open it next time
19
-
20
- if(enable_new_interfaces == -1) enable_new_interfaces = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "enable new interfaces detected at runtime", CONFIG_ONDEMAND_ONDEMAND);
21
- if(enable_ifb_interfaces == -1) enable_ifb_interfaces = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "enable ifb interfaces", CONFIG_ONDEMAND_NO);
22
-
23
- if(do_bandwidth == -1) do_bandwidth = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "bandwidth for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
24
- if(do_packets == -1) do_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "packets for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
25
- if(do_errors == -1) do_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "errors for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
26
- if(do_drops == -1) do_drops = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "drops for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
27
- if(do_fifo == -1) do_fifo = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "fifo for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
28
- if(do_compressed == -1) do_compressed = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "compressed packets for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
29
- if(do_events == -1) do_events = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "frames, collisions, carrier counters for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
30
-
31
- uint32_t lines = procfile_lines(ff), l;
32
- uint32_t words;
33
-
34
- char *iface;
35
- unsigned long long rbytes, rpackets, rerrors, rdrops, rfifo, rframe, rcompressed, rmulticast;
36
- unsigned long long tbytes, tpackets, terrors, tdrops, tfifo, tcollisions, tcarrier, tcompressed;
37
-
38
- for(l = 2; l < lines ;l++) {
39
- words = procfile_linewords(ff, l);
40
- if(words < 17) continue;
41
-
42
- iface = procfile_lineword(ff, l, 0);
43
-
44
- rbytes = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
45
- rpackets = strtoull(procfile_lineword(ff, l, 2), NULL, 10);
46
- rerrors = strtoull(procfile_lineword(ff, l, 3), NULL, 10);
47
- rdrops = strtoull(procfile_lineword(ff, l, 4), NULL, 10);
48
- rfifo = strtoull(procfile_lineword(ff, l, 5), NULL, 10);
49
- rframe = strtoull(procfile_lineword(ff, l, 6), NULL, 10);
50
- rcompressed = strtoull(procfile_lineword(ff, l, 7), NULL, 10);
51
- rmulticast = strtoull(procfile_lineword(ff, l, 8), NULL, 10);
52
-
53
- tbytes = strtoull(procfile_lineword(ff, l, 9), NULL, 10);
54
- tpackets = strtoull(procfile_lineword(ff, l, 10), NULL, 10);
55
- terrors = strtoull(procfile_lineword(ff, l, 11), NULL, 10);
56
- tdrops = strtoull(procfile_lineword(ff, l, 12), NULL, 10);
57
- tfifo = strtoull(procfile_lineword(ff, l, 13), NULL, 10);
58
- tcollisions = strtoull(procfile_lineword(ff, l, 14), NULL, 10);
59
- tcarrier = strtoull(procfile_lineword(ff, l, 15), NULL, 10);
60
- tcompressed = strtoull(procfile_lineword(ff, l, 16), NULL, 10);
61
-
62
- int ddo_bandwidth = do_bandwidth, ddo_packets = do_packets, ddo_errors = do_errors, ddo_drops = do_drops, ddo_fifo = do_fifo, ddo_compressed = do_compressed, ddo_events = do_events;
63
-
64
- int default_enable = enable_new_interfaces;
65
-
66
- // prevent unused interfaces from creating charts
67
- if(strcmp(iface, "lo") == 0)
68
- default_enable = 0;
69
- else {
70
- int len = strlen(iface);
71
- if(len >= 4 && strcmp(&iface[len-4], "-ifb") == 0)
72
- default_enable = enable_ifb_interfaces;
73
- }
74
-
75
- // check if the user wants it
76
- {
77
- char var_name[512 + 1];
78
- snprintfz(var_name, 512, "plugin:proc:/proc/net/dev:%s", iface);
79
- default_enable = config_get_boolean_ondemand(var_name, "enabled", default_enable);
80
- if(default_enable == CONFIG_ONDEMAND_NO) continue;
81
- if(default_enable == CONFIG_ONDEMAND_ONDEMAND && !rbytes && !tbytes) continue;
82
-
83
- ddo_bandwidth = config_get_boolean_ondemand(var_name, "bandwidth", ddo_bandwidth);
84
- ddo_packets = config_get_boolean_ondemand(var_name, "packets", ddo_packets);
85
- ddo_errors = config_get_boolean_ondemand(var_name, "errors", ddo_errors);
86
- ddo_drops = config_get_boolean_ondemand(var_name, "drops", ddo_drops);
87
- ddo_fifo = config_get_boolean_ondemand(var_name, "fifo", ddo_fifo);
88
- ddo_compressed = config_get_boolean_ondemand(var_name, "compressed", ddo_compressed);
89
- ddo_events = config_get_boolean_ondemand(var_name, "events", ddo_events);
90
-
91
- if(ddo_bandwidth == CONFIG_ONDEMAND_ONDEMAND && rbytes == 0 && tbytes == 0) ddo_bandwidth = 0;
92
- if(ddo_errors == CONFIG_ONDEMAND_ONDEMAND && rerrors == 0 && terrors == 0) ddo_errors = 0;
93
- if(ddo_drops == CONFIG_ONDEMAND_ONDEMAND && rdrops == 0 && tdrops == 0) ddo_drops = 0;
94
- if(ddo_fifo == CONFIG_ONDEMAND_ONDEMAND && rfifo == 0 && tfifo == 0) ddo_fifo = 0;
95
- if(ddo_compressed == CONFIG_ONDEMAND_ONDEMAND && rcompressed == 0 && tcompressed == 0) ddo_compressed = 0;
96
- if(ddo_events == CONFIG_ONDEMAND_ONDEMAND && rframe == 0 && tcollisions == 0 && tcarrier == 0) ddo_events = 0;
97
-
98
- // for absolute values, we need to switch the setting to 'yes'
99
- // to allow it refresh from now on
100
- // if(ddo_fifo == CONFIG_ONDEMAND_ONDEMAND) config_set(var_name, "fifo", "yes");
101
- }
102
-
103
- RRDSET *st;
104
-
105
- // --------------------------------------------------------------------
106
-
107
- if(ddo_bandwidth) {
108
- st = rrdset_find_bytype("net", iface);
109
- if(!st) {
110
- st = rrdset_create("net", iface, NULL, iface, "net.net", "Bandwidth", "kilobits/s", 7000, update_every, RRDSET_TYPE_AREA);
111
-
112
- rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL);
113
- rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL);
114
- }
115
- else rrdset_next(st);
116
-
117
- rrddim_set(st, "received", rbytes);
118
- rrddim_set(st, "sent", tbytes);
119
- rrdset_done(st);
120
- }
121
-
122
- // --------------------------------------------------------------------
123
-
124
- if(ddo_packets) {
125
- st = rrdset_find_bytype("net_packets", iface);
126
- if(!st) {
127
- st = rrdset_create("net_packets", iface, NULL, iface, "net.packets", "Packets", "packets/s", 7001, update_every, RRDSET_TYPE_LINE);
128
- st->isdetail = 1;
129
-
130
- rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
131
- rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
132
- rrddim_add(st, "multicast", NULL, 1, 1, RRDDIM_INCREMENTAL);
133
- }
134
- else rrdset_next(st);
135
-
136
- rrddim_set(st, "received", rpackets);
137
- rrddim_set(st, "sent", tpackets);
138
- rrddim_set(st, "multicast", rmulticast);
139
- rrdset_done(st);
140
- }
141
-
142
- // --------------------------------------------------------------------
143
-
144
- if(ddo_errors) {
145
- st = rrdset_find_bytype("net_errors", iface);
146
- if(!st) {
147
- st = rrdset_create("net_errors", iface, NULL, iface, "net.errors", "Interface Errors", "errors/s", 7002, update_every, RRDSET_TYPE_LINE);
148
- st->isdetail = 1;
149
-
150
- rrddim_add(st, "inbound", NULL, 1, 1, RRDDIM_INCREMENTAL);
151
- rrddim_add(st, "outbound", NULL, -1, 1, RRDDIM_INCREMENTAL);
152
- }
153
- else rrdset_next(st);
154
-
155
- rrddim_set(st, "inbound", rerrors);
156
- rrddim_set(st, "outbound", terrors);
157
- rrdset_done(st);
158
- }
159
-
160
- // --------------------------------------------------------------------
161
-
162
- if(ddo_drops) {
163
- st = rrdset_find_bytype("net_drops", iface);
164
- if(!st) {
165
- st = rrdset_create("net_drops", iface, NULL, iface, "net.drops", "Interface Drops", "drops/s", 7003, update_every, RRDSET_TYPE_LINE);
166
- st->isdetail = 1;
167
-
168
- rrddim_add(st, "inbound", NULL, 1, 1, RRDDIM_INCREMENTAL);
169
- rrddim_add(st, "outbound", NULL, -1, 1, RRDDIM_INCREMENTAL);
170
- }
171
- else rrdset_next(st);
172
-
173
- rrddim_set(st, "inbound", rdrops);
174
- rrddim_set(st, "outbound", tdrops);
175
- rrdset_done(st);
176
- }
177
-
178
- // --------------------------------------------------------------------
179
-
180
- if(ddo_fifo) {
181
- st = rrdset_find_bytype("net_fifo", iface);
182
- if(!st) {
183
- st = rrdset_create("net_fifo", iface, NULL, iface, "net.fifo", "Interface FIFO Buffer Errors", "errors", 7004, update_every, RRDSET_TYPE_LINE);
184
- st->isdetail = 1;
185
-
186
- rrddim_add(st, "receive", NULL, 1, 1, RRDDIM_INCREMENTAL);
187
- rrddim_add(st, "transmit", NULL, -1, 1, RRDDIM_INCREMENTAL);
188
- }
189
- else rrdset_next(st);
190
-
191
- rrddim_set(st, "receive", rfifo);
192
- rrddim_set(st, "transmit", tfifo);
193
- rrdset_done(st);
194
- }
195
-
196
- // --------------------------------------------------------------------
197
-
198
- if(ddo_compressed) {
199
- st = rrdset_find_bytype("net_compressed", iface);
200
- if(!st) {
201
- st = rrdset_create("net_compressed", iface, NULL, iface, "net.compressed", "Compressed Packets", "packets/s", 7005, update_every, RRDSET_TYPE_LINE);
202
- st->isdetail = 1;
203
-
204
- rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
205
- rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
206
- }
207
- else rrdset_next(st);
208
-
209
- rrddim_set(st, "received", rcompressed);
210
- rrddim_set(st, "sent", tcompressed);
211
- rrdset_done(st);
212
- }
213
-
214
- // --------------------------------------------------------------------
215
-
216
- if(ddo_events) {
217
- st = rrdset_find_bytype("net_events", iface);
218
- if(!st) {
219
- st = rrdset_create("net_events", iface, NULL, iface, "net.events", "Network Interface Events", "events/s", 7006, update_every, RRDSET_TYPE_LINE);
220
- st->isdetail = 1;
221
-
222
- rrddim_add(st, "frames", NULL, 1, 1, RRDDIM_INCREMENTAL);
223
- rrddim_add(st, "collisions", NULL, -1, 1, RRDDIM_INCREMENTAL);
224
- rrddim_add(st, "carrier", NULL, -1, 1, RRDDIM_INCREMENTAL);
225
- }
226
- else rrdset_next(st);
227
-
228
- rrddim_set(st, "frames", rframe);
229
- rrddim_set(st, "collisions", tcollisions);
230
- rrddim_set(st, "carrier", tcarrier);
231
- rrdset_done(st);
232
- }
233
- }
234
-
235
- return 0;
4
+ static procfile *ff = NULL;
5
+ static int enable_new_interfaces = -1, enable_ifb_interfaces = -1;
6
+ static int do_bandwidth = -1, do_packets = -1, do_errors = -1, do_drops = -1, do_fifo = -1, do_compressed = -1, do_events = -1;
7
+
8
+ if(dt) {};
9
+
10
+ if(!ff) {
11
+ char filename[FILENAME_MAX + 1];
12
+ snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/dev");
13
+ ff = procfile_open(config_get("plugin:proc:/proc/net/dev", "filename to monitor", filename), " \t,:|", PROCFILE_FLAG_DEFAULT);
14
+ }
15
+ if(!ff) return 1;
16
+
17
+ ff = procfile_readall(ff);
18
+ if(!ff) return 0; // we return 0, so that we will retry to open it next time
19
+
20
+ if(enable_new_interfaces == -1) enable_new_interfaces = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "enable new interfaces detected at runtime", CONFIG_ONDEMAND_ONDEMAND);
21
+ if(enable_ifb_interfaces == -1) enable_ifb_interfaces = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "enable ifb interfaces", CONFIG_ONDEMAND_NO);
22
+
23
+ if(do_bandwidth == -1) do_bandwidth = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "bandwidth for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
24
+ if(do_packets == -1) do_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "packets for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
25
+ if(do_errors == -1) do_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "errors for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
26
+ if(do_drops == -1) do_drops = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "drops for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
27
+ if(do_fifo == -1) do_fifo = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "fifo for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
28
+ if(do_compressed == -1) do_compressed = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "compressed packets for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
29
+ if(do_events == -1) do_events = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "frames, collisions, carrier counters for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
30
+
31
+ uint32_t lines = procfile_lines(ff), l;
32
+ uint32_t words;
33
+
34
+ char *iface;
35
+ unsigned long long rbytes, rpackets, rerrors, rdrops, rfifo, rframe, rcompressed, rmulticast;
36
+ unsigned long long tbytes, tpackets, terrors, tdrops, tfifo, tcollisions, tcarrier, tcompressed;
37
+
38
+ for(l = 2; l < lines ;l++) {
39
+ words = procfile_linewords(ff, l);
40
+ if(words < 17) continue;
41
+
42
+ iface = procfile_lineword(ff, l, 0);
43
+
44
+ rbytes = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
45
+ rpackets = strtoull(procfile_lineword(ff, l, 2), NULL, 10);
46
+ rerrors = strtoull(procfile_lineword(ff, l, 3), NULL, 10);
47
+ rdrops = strtoull(procfile_lineword(ff, l, 4), NULL, 10);
48
+ rfifo = strtoull(procfile_lineword(ff, l, 5), NULL, 10);
49
+ rframe = strtoull(procfile_lineword(ff, l, 6), NULL, 10);
50
+ rcompressed = strtoull(procfile_lineword(ff, l, 7), NULL, 10);
51
+ rmulticast = strtoull(procfile_lineword(ff, l, 8), NULL, 10);
52
+
53
+ tbytes = strtoull(procfile_lineword(ff, l, 9), NULL, 10);
54
+ tpackets = strtoull(procfile_lineword(ff, l, 10), NULL, 10);
55
+ terrors = strtoull(procfile_lineword(ff, l, 11), NULL, 10);
56
+ tdrops = strtoull(procfile_lineword(ff, l, 12), NULL, 10);
57
+ tfifo = strtoull(procfile_lineword(ff, l, 13), NULL, 10);
58
+ tcollisions = strtoull(procfile_lineword(ff, l, 14), NULL, 10);
59
+ tcarrier = strtoull(procfile_lineword(ff, l, 15), NULL, 10);
60
+ tcompressed = strtoull(procfile_lineword(ff, l, 16), NULL, 10);
61
+
62
+ int ddo_bandwidth = do_bandwidth, ddo_packets = do_packets, ddo_errors = do_errors, ddo_drops = do_drops, ddo_fifo = do_fifo, ddo_compressed = do_compressed, ddo_events = do_events;
63
+
64
+ int default_enable = enable_new_interfaces;
65
+
66
+ // prevent unused interfaces from creating charts
67
+ if(strcmp(iface, "lo") == 0)
68
+ default_enable = 0;
69
+ else {
70
+ int len = strlen(iface);
71
+ if(len >= 4 && strcmp(&iface[len-4], "-ifb") == 0)
72
+ default_enable = enable_ifb_interfaces;
73
+ }
74
+
75
+ // check if the user wants it
76
+ {
77
+ char var_name[512 + 1];
78
+ snprintfz(var_name, 512, "plugin:proc:/proc/net/dev:%s", iface);
79
+ default_enable = config_get_boolean_ondemand(var_name, "enabled", default_enable);
80
+ if(default_enable == CONFIG_ONDEMAND_NO) continue;
81
+ if(default_enable == CONFIG_ONDEMAND_ONDEMAND && !rbytes && !tbytes) continue;
82
+
83
+ ddo_bandwidth = config_get_boolean_ondemand(var_name, "bandwidth", ddo_bandwidth);
84
+ ddo_packets = config_get_boolean_ondemand(var_name, "packets", ddo_packets);
85
+ ddo_errors = config_get_boolean_ondemand(var_name, "errors", ddo_errors);
86
+ ddo_drops = config_get_boolean_ondemand(var_name, "drops", ddo_drops);
87
+ ddo_fifo = config_get_boolean_ondemand(var_name, "fifo", ddo_fifo);
88
+ ddo_compressed = config_get_boolean_ondemand(var_name, "compressed", ddo_compressed);
89
+ ddo_events = config_get_boolean_ondemand(var_name, "events", ddo_events);
90
+
91
+ if(ddo_bandwidth == CONFIG_ONDEMAND_ONDEMAND && rbytes == 0 && tbytes == 0) ddo_bandwidth = 0;
92
+ if(ddo_errors == CONFIG_ONDEMAND_ONDEMAND && rerrors == 0 && terrors == 0) ddo_errors = 0;
93
+ if(ddo_drops == CONFIG_ONDEMAND_ONDEMAND && rdrops == 0 && tdrops == 0) ddo_drops = 0;
94
+ if(ddo_fifo == CONFIG_ONDEMAND_ONDEMAND && rfifo == 0 && tfifo == 0) ddo_fifo = 0;
95
+ if(ddo_compressed == CONFIG_ONDEMAND_ONDEMAND && rcompressed == 0 && tcompressed == 0) ddo_compressed = 0;
96
+ if(ddo_events == CONFIG_ONDEMAND_ONDEMAND && rframe == 0 && tcollisions == 0 && tcarrier == 0) ddo_events = 0;
97
+
98
+ // for absolute values, we need to switch the setting to 'yes'
99
+ // to allow it refresh from now on
100
+ // if(ddo_fifo == CONFIG_ONDEMAND_ONDEMAND) config_set(var_name, "fifo", "yes");
101
+ }
102
+
103
+ RRDSET *st;
104
+
105
+ // --------------------------------------------------------------------
106
+
107
+ if(ddo_bandwidth) {
108
+ st = rrdset_find_bytype("net", iface);
109
+ if(!st) {
110
+ st = rrdset_create("net", iface, NULL, iface, "net.net", "Bandwidth", "kilobits/s", 7000, update_every, RRDSET_TYPE_AREA);
111
+
112
+ rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL);
113
+ rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL);
114
+ }
115
+ else rrdset_next(st);
116
+
117
+ rrddim_set(st, "received", rbytes);
118
+ rrddim_set(st, "sent", tbytes);
119
+ rrdset_done(st);
120
+ }
121
+
122
+ // --------------------------------------------------------------------
123
+
124
+ if(ddo_packets) {
125
+ st = rrdset_find_bytype("net_packets", iface);
126
+ if(!st) {
127
+ st = rrdset_create("net_packets", iface, NULL, iface, "net.packets", "Packets", "packets/s", 7001, update_every, RRDSET_TYPE_LINE);
128
+ st->isdetail = 1;
129
+
130
+ rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
131
+ rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
132
+ rrddim_add(st, "multicast", NULL, 1, 1, RRDDIM_INCREMENTAL);
133
+ }
134
+ else rrdset_next(st);
135
+
136
+ rrddim_set(st, "received", rpackets);
137
+ rrddim_set(st, "sent", tpackets);
138
+ rrddim_set(st, "multicast", rmulticast);
139
+ rrdset_done(st);
140
+ }
141
+
142
+ // --------------------------------------------------------------------
143
+
144
+ if(ddo_errors) {
145
+ st = rrdset_find_bytype("net_errors", iface);
146
+ if(!st) {
147
+ st = rrdset_create("net_errors", iface, NULL, iface, "net.errors", "Interface Errors", "errors/s", 7002, update_every, RRDSET_TYPE_LINE);
148
+ st->isdetail = 1;
149
+
150
+ rrddim_add(st, "inbound", NULL, 1, 1, RRDDIM_INCREMENTAL);
151
+ rrddim_add(st, "outbound", NULL, -1, 1, RRDDIM_INCREMENTAL);
152
+ }
153
+ else rrdset_next(st);
154
+
155
+ rrddim_set(st, "inbound", rerrors);
156
+ rrddim_set(st, "outbound", terrors);
157
+ rrdset_done(st);
158
+ }
159
+
160
+ // --------------------------------------------------------------------
161
+
162
+ if(ddo_drops) {
163
+ st = rrdset_find_bytype("net_drops", iface);
164
+ if(!st) {
165
+ st = rrdset_create("net_drops", iface, NULL, iface, "net.drops", "Interface Drops", "drops/s", 7003, update_every, RRDSET_TYPE_LINE);
166
+ st->isdetail = 1;
167
+
168
+ rrddim_add(st, "inbound", NULL, 1, 1, RRDDIM_INCREMENTAL);
169
+ rrddim_add(st, "outbound", NULL, -1, 1, RRDDIM_INCREMENTAL);
170
+ }
171
+ else rrdset_next(st);
172
+
173
+ rrddim_set(st, "inbound", rdrops);
174
+ rrddim_set(st, "outbound", tdrops);
175
+ rrdset_done(st);
176
+ }
177
+
178
+ // --------------------------------------------------------------------
179
+
180
+ if(ddo_fifo) {
181
+ st = rrdset_find_bytype("net_fifo", iface);
182
+ if(!st) {
183
+ st = rrdset_create("net_fifo", iface, NULL, iface, "net.fifo", "Interface FIFO Buffer Errors", "errors", 7004, update_every, RRDSET_TYPE_LINE);
184
+ st->isdetail = 1;
185
+
186
+ rrddim_add(st, "receive", NULL, 1, 1, RRDDIM_INCREMENTAL);
187
+ rrddim_add(st, "transmit", NULL, -1, 1, RRDDIM_INCREMENTAL);
188
+ }
189
+ else rrdset_next(st);
190
+
191
+ rrddim_set(st, "receive", rfifo);
192
+ rrddim_set(st, "transmit", tfifo);
193
+ rrdset_done(st);
194
+ }
195
+
196
+ // --------------------------------------------------------------------
197
+
198
+ if(ddo_compressed) {
199
+ st = rrdset_find_bytype("net_compressed", iface);
200
+ if(!st) {
201
+ st = rrdset_create("net_compressed", iface, NULL, iface, "net.compressed", "Compressed Packets", "packets/s", 7005, update_every, RRDSET_TYPE_LINE);
202
+ st->isdetail = 1;
203
+
204
+ rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
205
+ rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
206
+ }
207
+ else rrdset_next(st);
208
+
209
+ rrddim_set(st, "received", rcompressed);
210
+ rrddim_set(st, "sent", tcompressed);
211
+ rrdset_done(st);
212
+ }
213
+
214
+ // --------------------------------------------------------------------
215
+
216
+ if(ddo_events) {
217
+ st = rrdset_find_bytype("net_events", iface);
218
+ if(!st) {
219
+ st = rrdset_create("net_events", iface, NULL, iface, "net.events", "Network Interface Events", "events/s", 7006, update_every, RRDSET_TYPE_LINE);
220
+ st->isdetail = 1;
221
+
222
+ rrddim_add(st, "frames", NULL, 1, 1, RRDDIM_INCREMENTAL);
223
+ rrddim_add(st, "collisions", NULL, -1, 1, RRDDIM_INCREMENTAL);
224
+ rrddim_add(st, "carrier", NULL, -1, 1, RRDDIM_INCREMENTAL);
225
+ }
226
+ else rrdset_next(st);
227
+
228
+ rrddim_set(st, "frames", rframe);
229
+ rrddim_set(st, "collisions", tcollisions);
230
+ rrddim_set(st, "carrier", tcarrier);
231
+ rrdset_done(st);
232
+ }
233
+ }
234
+
235
+ return 0;
236
}
src/proc_net_ip_vs_stats.c
+65
-65
@@ -1,92 +1,92 @@
1
#include "common.h"
2
3
-#define RRD_TYPE_NET_IPVS "ipvs"
4
-#define RRD_TYPE_NET_IPVS_LEN strlen(RRD_TYPE_NET_IPVS)
3
+#define RRD_TYPE_NET_IPVS "ipvs"
4
+#define RRD_TYPE_NET_IPVS_LEN strlen(RRD_TYPE_NET_IPVS)
5
6
int do_proc_net_ip_vs_stats(int update_every, unsigned long long dt) {
7
- static int do_bandwidth = -1, do_sockets = -1, do_packets = -1;
8
- static procfile *ff = NULL;
7
+ static int do_bandwidth = -1, do_sockets = -1, do_packets = -1;
8
+ static procfile *ff = NULL;
9
10
- if(do_bandwidth == -1) do_bandwidth = config_get_boolean("plugin:proc:/proc/net/ip_vs_stats", "IPVS bandwidth", 1);
11
- if(do_sockets == -1) do_sockets = config_get_boolean("plugin:proc:/proc/net/ip_vs_stats", "IPVS connections", 1);
12
- if(do_packets == -1) do_packets = config_get_boolean("plugin:proc:/proc/net/ip_vs_stats", "IPVS packets", 1);
10
+ if(do_bandwidth == -1) do_bandwidth = config_get_boolean("plugin:proc:/proc/net/ip_vs_stats", "IPVS bandwidth", 1);
11
+ if(do_sockets == -1) do_sockets = config_get_boolean("plugin:proc:/proc/net/ip_vs_stats", "IPVS connections", 1);
12
+ if(do_packets == -1) do_packets = config_get_boolean("plugin:proc:/proc/net/ip_vs_stats", "IPVS packets", 1);
13
14
- if(dt) {};
14
+ if(dt) {};
15
16
- if(!ff) {
17
- char filename[FILENAME_MAX + 1];
18
- snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/ip_vs_stats");
19
- ff = procfile_open(config_get("plugin:proc:/proc/net/ip_vs_stats", "filename to monitor", filename), " \t,:|", PROCFILE_FLAG_DEFAULT);
20
- }
21
- if(!ff) return 1;
16
+ if(!ff) {
17
+ char filename[FILENAME_MAX + 1];
18
+ snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/ip_vs_stats");
19
+ ff = procfile_open(config_get("plugin:proc:/proc/net/ip_vs_stats", "filename to monitor", filename), " \t,:|", PROCFILE_FLAG_DEFAULT);
20
+ }
21
+ if(!ff) return 1;
22
23
- ff = procfile_readall(ff);
24
- if(!ff) return 0; // we return 0, so that we will retry to open it next time
23
+ ff = procfile_readall(ff);
24
+ if(!ff) return 0; // we return 0, so that we will retry to open it next time
25
26
- // make sure we have 3 lines
27
- if(procfile_lines(ff) < 3) return 1;
26
+ // make sure we have 3 lines
27
+ if(procfile_lines(ff) < 3) return 1;
28
29
- // make sure we have 5 words on the 3rd line
30
- if(procfile_linewords(ff, 2) < 5) return 1;
29
+ // make sure we have 5 words on the 3rd line
30
+ if(procfile_linewords(ff, 2) < 5) return 1;
31
32
- unsigned long long entries, InPackets, OutPackets, InBytes, OutBytes;
32
+ unsigned long long entries, InPackets, OutPackets, InBytes, OutBytes;
33
34
- entries = strtoull(procfile_lineword(ff, 2, 0), NULL, 16);
35
- InPackets = strtoull(procfile_lineword(ff, 2, 1), NULL, 16);
36
- OutPackets = strtoull(procfile_lineword(ff, 2, 2), NULL, 16);
37
- InBytes = strtoull(procfile_lineword(ff, 2, 3), NULL, 16);
38
- OutBytes = strtoull(procfile_lineword(ff, 2, 4), NULL, 16);
34
+ entries = strtoull(procfile_lineword(ff, 2, 0), NULL, 16);
35
+ InPackets = strtoull(procfile_lineword(ff, 2, 1), NULL, 16);
36
+ OutPackets = strtoull(procfile_lineword(ff, 2, 2), NULL, 16);
37
+ InBytes = strtoull(procfile_lineword(ff, 2, 3), NULL, 16);
38
+ OutBytes = strtoull(procfile_lineword(ff, 2, 4), NULL, 16);
39
40
- RRDSET *st;
40
+ RRDSET *st;
41
42
- // --------------------------------------------------------------------
42
+ // --------------------------------------------------------------------
43
44
- if(do_sockets) {
45
- st = rrdset_find(RRD_TYPE_NET_IPVS ".sockets");
46
- if(!st) {
47
- st = rrdset_create(RRD_TYPE_NET_IPVS, "sockets", NULL, RRD_TYPE_NET_IPVS, NULL, "IPVS New Connections", "connections/s", 1001, update_every, RRDSET_TYPE_LINE);
44
+ if(do_sockets) {
45
+ st = rrdset_find(RRD_TYPE_NET_IPVS ".sockets");
46
+ if(!st) {
47
+ st = rrdset_create(RRD_TYPE_NET_IPVS, "sockets", NULL, RRD_TYPE_NET_IPVS, NULL, "IPVS New Connections", "connections/s", 1001, update_every, RRDSET_TYPE_LINE);
48
49
- rrddim_add(st, "connections", NULL, 1, 1, RRDDIM_INCREMENTAL);
50
- }
51
- else rrdset_next(st);
49
+ rrddim_add(st, "connections", NULL, 1, 1, RRDDIM_INCREMENTAL);
50
+ }
51
+ else rrdset_next(st);
52
53
- rrddim_set(st, "connections", entries);
54
- rrdset_done(st);
55
- }
53
+ rrddim_set(st, "connections", entries);
54
+ rrdset_done(st);
55
+ }
56
57
- // --------------------------------------------------------------------
57
+ // --------------------------------------------------------------------
58
59
- if(do_packets) {
60
- st = rrdset_find(RRD_TYPE_NET_IPVS ".packets");
61
- if(!st) {
62
- st = rrdset_create(RRD_TYPE_NET_IPVS, "packets", NULL, RRD_TYPE_NET_IPVS, NULL, "IPVS Packets", "packets/s", 1002, update_every, RRDSET_TYPE_LINE);
59
+ if(do_packets) {
60
+ st = rrdset_find(RRD_TYPE_NET_IPVS ".packets");
61
+ if(!st) {
62
+ st = rrdset_create(RRD_TYPE_NET_IPVS, "packets", NULL, RRD_TYPE_NET_IPVS, NULL, "IPVS Packets", "packets/s", 1002, update_every, RRDSET_TYPE_LINE);
63
64
- rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
65
- rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
66
- }
67
- else rrdset_next(st);
64
+ rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
65
+ rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
66
+ }
67
+ else rrdset_next(st);
68
69
- rrddim_set(st, "received", InPackets);
70
- rrddim_set(st, "sent", OutPackets);
71
- rrdset_done(st);
72
- }
69
+ rrddim_set(st, "received", InPackets);
70
+ rrddim_set(st, "sent", OutPackets);
71
+ rrdset_done(st);
72
+ }
73
74
- // --------------------------------------------------------------------
74
+ // --------------------------------------------------------------------
75
76
- if(do_bandwidth) {
77
- st = rrdset_find(RRD_TYPE_NET_IPVS ".net");
78
- if(!st) {
79
- st = rrdset_create(RRD_TYPE_NET_IPVS, "net", NULL, RRD_TYPE_NET_IPVS, NULL, "IPVS Bandwidth", "kilobits/s", 1000, update_every, RRDSET_TYPE_AREA);
76
+ if(do_bandwidth) {
77
+ st = rrdset_find(RRD_TYPE_NET_IPVS ".net");
78
+ if(!st) {
79
+ st = rrdset_create(RRD_TYPE_NET_IPVS, "net", NULL, RRD_TYPE_NET_IPVS, NULL, "IPVS Bandwidth", "kilobits/s", 1000, update_every, RRDSET_TYPE_AREA);
80
81
- rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL);
82
- rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL);
83
- }
84
- else rrdset_next(st);
81
+ rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL);
82
+ rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL);
83
+ }
84
+ else rrdset_next(st);
85
86
- rrddim_set(st, "received", InBytes);
87
- rrddim_set(st, "sent", OutBytes);
88
- rrdset_done(st);
89
- }
86
+ rrddim_set(st, "received", InBytes);
87
+ rrddim_set(st, "sent", OutBytes);
88
+ rrdset_done(st);
89
+ }
90
91
- return 0;
91
+ return 0;
92
}
src/proc_net_netstat.c
+175
-175
@@ -1,179 +1,179 @@
1
#include "common.h"
2
3
int do_proc_net_netstat(int update_every, unsigned long long dt) {
4
- static int do_bandwidth = -1, do_inerrors = -1, do_mcast = -1, do_bcast = -1, do_mcast_p = -1, do_bcast_p = -1;
5
- static procfile *ff = NULL;
6
-
7
- if(do_bandwidth == -1) do_bandwidth = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "bandwidth", CONFIG_ONDEMAND_ONDEMAND);
8
- if(do_inerrors == -1) do_inerrors = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "input errors", CONFIG_ONDEMAND_ONDEMAND);
9
- if(do_mcast == -1) do_mcast = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "multicast bandwidth", CONFIG_ONDEMAND_ONDEMAND);
10
- if(do_bcast == -1) do_bcast = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "broadcast bandwidth", CONFIG_ONDEMAND_ONDEMAND);
11
- if(do_mcast_p == -1) do_mcast_p = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "multicast packets", CONFIG_ONDEMAND_ONDEMAND);
12
- if(do_bcast_p == -1) do_bcast_p = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "broadcast packets", CONFIG_ONDEMAND_ONDEMAND);
13
-
14
- if(dt) {};
15
-
16
- if(!ff) {
17
- char filename[FILENAME_MAX + 1];
18
- snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/netstat");
19
- ff = procfile_open(config_get("plugin:proc:/proc/net/netstat", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
20
- }
21
- if(!ff) return 1;
22
-
23
- ff = procfile_readall(ff);
24
- if(!ff) return 0; // we return 0, so that we will retry to open it next time
25
-
26
- uint32_t lines = procfile_lines(ff), l;
27
- uint32_t words;
28
-
29
- for(l = 0; l < lines ;l++) {
30
- if(strcmp(procfile_lineword(ff, l, 0), "IpExt") == 0) {
31
- l++; // we need the next line
32
-
33
- if(strcmp(procfile_lineword(ff, l, 0), "IpExt") != 0) {
34
- error("Cannot read IpExt line from /proc/net/netstat.");
35
- break;
36
- }
37
- words = procfile_linewords(ff, l);
38
- if(words < 12) {
39
- error("Cannot read /proc/net/netstat IpExt line. Expected 12 params, read %u.", words);
40
- continue;
41
- }
42
-
43
- unsigned long long
44
- InNoRoutes = 0, InTruncatedPkts = 0,
45
- InOctets = 0, InMcastPkts = 0, InBcastPkts = 0, InMcastOctets = 0, InBcastOctets = 0,
46
- OutOctets = 0, OutMcastPkts = 0, OutBcastPkts = 0, OutMcastOctets = 0, OutBcastOctets = 0;
47
-
48
- InNoRoutes = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
49
- InTruncatedPkts = strtoull(procfile_lineword(ff, l, 2), NULL, 10);
50
- InMcastPkts = strtoull(procfile_lineword(ff, l, 3), NULL, 10);
51
- OutMcastPkts = strtoull(procfile_lineword(ff, l, 4), NULL, 10);
52
- InBcastPkts = strtoull(procfile_lineword(ff, l, 5), NULL, 10);
53
- OutBcastPkts = strtoull(procfile_lineword(ff, l, 6), NULL, 10);
54
- InOctets = strtoull(procfile_lineword(ff, l, 7), NULL, 10);
55
- OutOctets = strtoull(procfile_lineword(ff, l, 8), NULL, 10);
56
- InMcastOctets = strtoull(procfile_lineword(ff, l, 9), NULL, 10);
57
- OutMcastOctets = strtoull(procfile_lineword(ff, l, 10), NULL, 10);
58
- InBcastOctets = strtoull(procfile_lineword(ff, l, 11), NULL, 10);
59
- OutBcastOctets = strtoull(procfile_lineword(ff, l, 12), NULL, 10);
60
-
61
- RRDSET *st;
62
-
63
- // --------------------------------------------------------------------
64
-
65
- if(do_bandwidth == CONFIG_ONDEMAND_YES || (do_bandwidth == CONFIG_ONDEMAND_ONDEMAND && (InOctets || OutOctets))) {
66
- do_bandwidth = CONFIG_ONDEMAND_YES;
67
- st = rrdset_find("system.ipv4");
68
- if(!st) {
69
- st = rrdset_create("system", "ipv4", NULL, "network", NULL, "IPv4 Bandwidth", "kilobits/s", 500, update_every, RRDSET_TYPE_AREA);
70
-
71
- rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL);
72
- rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL);
73
- }
74
- else rrdset_next(st);
75
-
76
- rrddim_set(st, "sent", OutOctets);
77
- rrddim_set(st, "received", InOctets);
78
- rrdset_done(st);
79
- }
80
-
81
- // --------------------------------------------------------------------
82
-
83
- if(do_inerrors == CONFIG_ONDEMAND_YES || (do_inerrors == CONFIG_ONDEMAND_ONDEMAND && (InNoRoutes || InTruncatedPkts))) {
84
- do_inerrors = CONFIG_ONDEMAND_YES;
85
- st = rrdset_find("ipv4.inerrors");
86
- if(!st) {
87
- st = rrdset_create("ipv4", "inerrors", NULL, "errors", NULL, "IPv4 Input Errors", "packets/s", 4000, update_every, RRDSET_TYPE_LINE);
88
- st->isdetail = 1;
89
-
90
- rrddim_add(st, "noroutes", NULL, 1, 1, RRDDIM_INCREMENTAL);
91
- rrddim_add(st, "truncated", NULL, 1, 1, RRDDIM_INCREMENTAL);
92
- }
93
- else rrdset_next(st);
94
-
95
- rrddim_set(st, "noroutes", InNoRoutes);
96
- rrddim_set(st, "truncated", InTruncatedPkts);
97
- rrdset_done(st);
98
- }
99
-
100
- // --------------------------------------------------------------------
101
-
102
- if(do_mcast == CONFIG_ONDEMAND_YES || (do_mcast == CONFIG_ONDEMAND_ONDEMAND && (InMcastOctets || OutMcastOctets))) {
103
- do_mcast = CONFIG_ONDEMAND_YES;
104
- st = rrdset_find("ipv4.mcast");
105
- if(!st) {
106
- st = rrdset_create("ipv4", "mcast", NULL, "multicast", NULL, "IPv4 Multicast Bandwidth", "kilobits/s", 9000, update_every, RRDSET_TYPE_AREA);
107
- st->isdetail = 1;
108
-
109
- rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL);
110
- rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL);
111
- }
112
- else rrdset_next(st);
113
-
114
- rrddim_set(st, "sent", OutMcastOctets);
115
- rrddim_set(st, "received", InMcastOctets);
116
- rrdset_done(st);
117
- }
118
-
119
- // --------------------------------------------------------------------
120
-
121
- if(do_bcast == CONFIG_ONDEMAND_YES || (do_bcast == CONFIG_ONDEMAND_ONDEMAND && (InBcastOctets || OutBcastOctets))) {
122
- do_bcast = CONFIG_ONDEMAND_YES;
123
- st = rrdset_find("ipv4.bcast");
124
- if(!st) {
125
- st = rrdset_create("ipv4", "bcast", NULL, "broadcast", NULL, "IPv4 Broadcast Bandwidth", "kilobits/s", 8000, update_every, RRDSET_TYPE_AREA);
126
- st->isdetail = 1;
127
-
128
- rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL);
129
- rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL);
130
- }
131
- else rrdset_next(st);
132
-
133
- rrddim_set(st, "sent", OutBcastOctets);
134
- rrddim_set(st, "received", InBcastOctets);
135
- rrdset_done(st);
136
- }
137
-
138
- // --------------------------------------------------------------------
139
-
140
- if(do_mcast_p == CONFIG_ONDEMAND_YES || (do_mcast_p == CONFIG_ONDEMAND_ONDEMAND && (InMcastPkts || OutMcastPkts))) {
141
- do_mcast_p = CONFIG_ONDEMAND_YES;
142
- st = rrdset_find("ipv4.mcastpkts");
143
- if(!st) {
144
- st = rrdset_create("ipv4", "mcastpkts", NULL, "multicast", NULL, "IPv4 Multicast Packets", "packets/s", 9500, update_every, RRDSET_TYPE_LINE);
145
- st->isdetail = 1;
146
-
147
- rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
148
- rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
149
- }
150
- else rrdset_next(st);
151
-
152
- rrddim_set(st, "sent", OutMcastPkts);
153
- rrddim_set(st, "received", InMcastPkts);
154
- rrdset_done(st);
155
- }
156
-
157
- // --------------------------------------------------------------------
158
-
159
- if(do_bcast_p == CONFIG_ONDEMAND_YES || (do_bcast_p == CONFIG_ONDEMAND_ONDEMAND && (InBcastPkts || OutBcastPkts))) {
160
- do_bcast_p = CONFIG_ONDEMAND_YES;
161
- st = rrdset_find("ipv4.bcastpkts");
162
- if(!st) {
163
- st = rrdset_create("ipv4", "bcastpkts", NULL, "broadcast", NULL, "IPv4 Broadcast Packets", "packets/s", 8500, update_every, RRDSET_TYPE_LINE);
164
- st->isdetail = 1;
165
-
166
- rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
167
- rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
168
- }
169
- else rrdset_next(st);
170
-
171
- rrddim_set(st, "sent", OutBcastPkts);
172
- rrddim_set(st, "received", InBcastPkts);
173
- rrdset_done(st);
174
- }
175
- }
176
- }
177
-
178
- return 0;
4
+ static int do_bandwidth = -1, do_inerrors = -1, do_mcast = -1, do_bcast = -1, do_mcast_p = -1, do_bcast_p = -1;
5
+ static procfile *ff = NULL;
6
+
7
+ if(do_bandwidth == -1) do_bandwidth = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "bandwidth", CONFIG_ONDEMAND_ONDEMAND);
8
+ if(do_inerrors == -1) do_inerrors = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "input errors", CONFIG_ONDEMAND_ONDEMAND);
9
+ if(do_mcast == -1) do_mcast = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "multicast bandwidth", CONFIG_ONDEMAND_ONDEMAND);
10
+ if(do_bcast == -1) do_bcast = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "broadcast bandwidth", CONFIG_ONDEMAND_ONDEMAND);
11
+ if(do_mcast_p == -1) do_mcast_p = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "multicast packets", CONFIG_ONDEMAND_ONDEMAND);
12
+ if(do_bcast_p == -1) do_bcast_p = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "broadcast packets", CONFIG_ONDEMAND_ONDEMAND);
13
+
14
+ if(dt) {};
15
+
16
+ if(!ff) {
17
+ char filename[FILENAME_MAX + 1];
18
+ snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/netstat");
19
+ ff = procfile_open(config_get("plugin:proc:/proc/net/netstat", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
20
+ }
21
+ if(!ff) return 1;
22
+
23
+ ff = procfile_readall(ff);
24
+ if(!ff) return 0; // we return 0, so that we will retry to open it next time
25
+
26
+ uint32_t lines = procfile_lines(ff), l;
27
+ uint32_t words;
28
+
29
+ for(l = 0; l < lines ;l++) {
30
+ if(strcmp(procfile_lineword(ff, l, 0), "IpExt") == 0) {
31
+ l++; // we need the next line
32
+
33
+ if(strcmp(procfile_lineword(ff, l, 0), "IpExt") != 0) {
34
+ error("Cannot read IpExt line from /proc/net/netstat.");
35
+ break;
36
+ }
37
+ words = procfile_linewords(ff, l);
38
+ if(words < 12) {
39
+ error("Cannot read /proc/net/netstat IpExt line. Expected 12 params, read %u.", words);
40
+ continue;
41
+ }
42
+
43
+ unsigned long long
44
+ InNoRoutes = 0, InTruncatedPkts = 0,
45
+ InOctets = 0, InMcastPkts = 0, InBcastPkts = 0, InMcastOctets = 0, InBcastOctets = 0,
46
+ OutOctets = 0, OutMcastPkts = 0, OutBcastPkts = 0, OutMcastOctets = 0, OutBcastOctets = 0;
47
+
48
+ InNoRoutes = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
49
+ InTruncatedPkts = strtoull(procfile_lineword(ff, l, 2), NULL, 10);
50
+ InMcastPkts = strtoull(procfile_lineword(ff, l, 3), NULL, 10);
51
+ OutMcastPkts = strtoull(procfile_lineword(ff, l, 4), NULL, 10);
52
+ InBcastPkts = strtoull(procfile_lineword(ff, l, 5), NULL, 10);
53
+ OutBcastPkts = strtoull(procfile_lineword(ff, l, 6), NULL, 10);
54
+ InOctets = strtoull(procfile_lineword(ff, l, 7), NULL, 10);
55
+ OutOctets = strtoull(procfile_lineword(ff, l, 8), NULL, 10);
56
+ InMcastOctets = strtoull(procfile_lineword(ff, l, 9), NULL, 10);
57
+ OutMcastOctets = strtoull(procfile_lineword(ff, l, 10), NULL, 10);
58
+ InBcastOctets = strtoull(procfile_lineword(ff, l, 11), NULL, 10);
59
+ OutBcastOctets = strtoull(procfile_lineword(ff, l, 12), NULL, 10);
60
+
61
+ RRDSET *st;
62
+
63
+ // --------------------------------------------------------------------
64
+
65
+ if(do_bandwidth == CONFIG_ONDEMAND_YES || (do_bandwidth == CONFIG_ONDEMAND_ONDEMAND && (InOctets || OutOctets))) {
66
+ do_bandwidth = CONFIG_ONDEMAND_YES;
67
+ st = rrdset_find("system.ipv4");
68
+ if(!st) {
69
+ st = rrdset_create("system", "ipv4", NULL, "network", NULL, "IPv4 Bandwidth", "kilobits/s", 500, update_every, RRDSET_TYPE_AREA);
70
+
71
+ rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL);
72
+ rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL);
73
+ }
74
+ else rrdset_next(st);
75
+
76
+ rrddim_set(st, "sent", OutOctets);
77
+ rrddim_set(st, "received", InOctets);
78
+ rrdset_done(st);
79
+ }
80
+
81
+ // --------------------------------------------------------------------
82
+
83
+ if(do_inerrors == CONFIG_ONDEMAND_YES || (do_inerrors == CONFIG_ONDEMAND_ONDEMAND && (InNoRoutes || InTruncatedPkts))) {
84
+ do_inerrors = CONFIG_ONDEMAND_YES;
85
+ st = rrdset_find("ipv4.inerrors");
86
+ if(!st) {
87
+ st = rrdset_create("ipv4", "inerrors", NULL, "errors", NULL, "IPv4 Input Errors", "packets/s", 4000, update_every, RRDSET_TYPE_LINE);
88
+ st->isdetail = 1;
89
+
90
+ rrddim_add(st, "noroutes", NULL, 1, 1, RRDDIM_INCREMENTAL);
91
+ rrddim_add(st, "truncated", NULL, 1, 1, RRDDIM_INCREMENTAL);
92
+ }
93
+ else rrdset_next(st);
94
+
95
+ rrddim_set(st, "noroutes", InNoRoutes);
96
+ rrddim_set(st, "truncated", InTruncatedPkts);
97
+ rrdset_done(st);
98
+ }
99
+
100
+ // --------------------------------------------------------------------
101
+
102
+ if(do_mcast == CONFIG_ONDEMAND_YES || (do_mcast == CONFIG_ONDEMAND_ONDEMAND && (InMcastOctets || OutMcastOctets))) {
103
+ do_mcast = CONFIG_ONDEMAND_YES;
104
+ st = rrdset_find("ipv4.mcast");
105
+ if(!st) {
106
+ st = rrdset_create("ipv4", "mcast", NULL, "multicast", NULL, "IPv4 Multicast Bandwidth", "kilobits/s", 9000, update_every, RRDSET_TYPE_AREA);
107
+ st->isdetail = 1;
108
+
109
+ rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL);
110
+ rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL);
111
+ }
112
+ else rrdset_next(st);
113
+
114
+ rrddim_set(st, "sent", OutMcastOctets);
115
+ rrddim_set(st, "received", InMcastOctets);
116
+ rrdset_done(st);
117
+ }
118
+
119
+ // --------------------------------------------------------------------
120
+
121
+ if(do_bcast == CONFIG_ONDEMAND_YES || (do_bcast == CONFIG_ONDEMAND_ONDEMAND && (InBcastOctets || OutBcastOctets))) {
122
+ do_bcast = CONFIG_ONDEMAND_YES;
123
+ st = rrdset_find("ipv4.bcast");
124
+ if(!st) {
125
+ st = rrdset_create("ipv4", "bcast", NULL, "broadcast", NULL, "IPv4 Broadcast Bandwidth", "kilobits/s", 8000, update_every, RRDSET_TYPE_AREA);
126
+ st->isdetail = 1;
127
+
128
+ rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL);
129
+ rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL);
130
+ }
131
+ else rrdset_next(st);
132
+
133
+ rrddim_set(st, "sent", OutBcastOctets);
134
+ rrddim_set(st, "received", InBcastOctets);
135
+ rrdset_done(st);
136
+ }
137
+
138
+ // --------------------------------------------------------------------
139
+
140
+ if(do_mcast_p == CONFIG_ONDEMAND_YES || (do_mcast_p == CONFIG_ONDEMAND_ONDEMAND && (InMcastPkts || OutMcastPkts))) {
141
+ do_mcast_p = CONFIG_ONDEMAND_YES;
142
+ st = rrdset_find("ipv4.mcastpkts");
143
+ if(!st) {
144
+ st = rrdset_create("ipv4", "mcastpkts", NULL, "multicast", NULL, "IPv4 Multicast Packets", "packets/s", 9500, update_every, RRDSET_TYPE_LINE);
145
+ st->isdetail = 1;
146
+
147
+ rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
148
+ rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
149
+ }
150
+ else rrdset_next(st);
151
+
152
+ rrddim_set(st, "sent", OutMcastPkts);
153
+ rrddim_set(st, "received", InMcastPkts);
154
+ rrdset_done(st);
155
+ }
156
+
157
+ // --------------------------------------------------------------------
158
+
159
+ if(do_bcast_p == CONFIG_ONDEMAND_YES || (do_bcast_p == CONFIG_ONDEMAND_ONDEMAND && (InBcastPkts || OutBcastPkts))) {
160
+ do_bcast_p = CONFIG_ONDEMAND_YES;
161
+ st = rrdset_find("ipv4.bcastpkts");
162
+ if(!st) {
163
+ st = rrdset_create("ipv4", "bcastpkts", NULL, "broadcast", NULL, "IPv4 Broadcast Packets", "packets/s", 8500, update_every, RRDSET_TYPE_LINE);
164
+ st->isdetail = 1;
165
+
166
+ rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
167
+ rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
168
+ }
169
+ else rrdset_next(st);
170
+
171
+ rrddim_set(st, "sent", OutBcastPkts);
172
+ rrddim_set(st, "received", InBcastPkts);
173
+ rrdset_done(st);
174
+ }
175
+ }
176
+ }
177
+
178
+ return 0;
179
}
src/proc_net_rpc_nfsd.c
+656
-656
@@ -1,681 +1,681 @@
1
#include "common.h"
2
3
struct nfsd_procs {
4
- char name[30];
5
- unsigned long long proc2;
6
- unsigned long long proc3;
7
- unsigned long long proc4;
8
- int present2;
9
- int present3;
10
- int present4;
4
+ char name[30];
5
+ unsigned long long proc2;
6
+ unsigned long long proc3;
7
+ unsigned long long proc4;
8
+ int present2;
9
+ int present3;
10
+ int present4;
11
};
12
13
struct nfsd_procs nfsd_proc_values[] = {
14
- { "null", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
15
- { "getattr", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
16
- { "setattr", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
17
- { "lookup", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
18
- { "access", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
19
- { "readlink", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
20
- { "read", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
21
- { "write", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
22
- { "create", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
23
- { "mkdir", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
24
- { "symlink", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
25
- { "mknod", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
26
- { "remove", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
27
- { "rmdir", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
28
- { "rename", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
29
- { "link", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
30
- { "readdir", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
31
- { "readdirplus", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
32
- { "fsstat", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
33
- { "fsinfo", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
34
- { "pathconf", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
35
- { "commit", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
36
- { "", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
14
+ { "null", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
15
+ { "getattr", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
16
+ { "setattr", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
17
+ { "lookup", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
18
+ { "access", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
19
+ { "readlink", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
20
+ { "read", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
21
+ { "write", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
22
+ { "create", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
23
+ { "mkdir", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
24
+ { "symlink", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
25
+ { "mknod", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
26
+ { "remove", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
27
+ { "rmdir", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
28
+ { "rename", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
29
+ { "link", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
30
+ { "readdir", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
31
+ { "readdirplus", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
32
+ { "fsstat", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
33
+ { "fsinfo", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
34
+ { "pathconf", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
35
+ { "commit", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
36
+ { "", 0ULL, 0ULL, 0ULL, 0, 0, 0 },
37
};
38
39
struct nfsd4_ops {
40
- char name[30];
41
- unsigned long long value;
42
- int present;
40
+ char name[30];
41
+ unsigned long long value;
42
+ int present;
43
};
44
45
struct nfsd4_ops nfsd4_ops_values[] = {
46
- { "access", 0ULL, 0},
47
- { "close", 0ULL, 0},
48
- { "commit", 0ULL, 0},
49
- { "create", 0ULL, 0},
50
- { "delegpurge", 0ULL, 0},
51
- { "delegreturn", 0ULL, 0},
52
- { "getattr", 0ULL, 0},
53
- { "getfh", 0ULL, 0},
54
- { "link", 0ULL, 0},
55
- { "lock", 0ULL, 0},
56
- { "lockt", 0ULL, 0},
57
- { "locku", 0ULL, 0},
58
- { "lookup", 0ULL, 0},
59
- { "lookupp", 0ULL, 0},
60
- { "nverify", 0ULL, 0},
61
- { "open", 0ULL, 0},
62
- { "openattr", 0ULL, 0},
63
- { "open_confirm", 0ULL, 0},
64
- { "open_downgrade", 0ULL, 0},
65
- { "putfh", 0ULL, 0},
66
- { "putpubfh", 0ULL, 0},
67
- { "putrootfh", 0ULL, 0},
68
- { "read", 0ULL, 0},
69
- { "readdir", 0ULL, 0},
70
- { "readlink", 0ULL, 0},
71
- { "remove", 0ULL, 0},
72
- { "rename", 0ULL, 0},
73
- { "renew", 0ULL, 0},
74
- { "restorefh", 0ULL, 0},
75
- { "savefh", 0ULL, 0},
76
- { "secinfo", 0ULL, 0},
77
- { "setattr", 0ULL, 0},
78
- { "setclientid", 0ULL, 0},
79
- { "setclientid_confirm", 0ULL, 0},
80
- { "verify", 0ULL, 0},
81
- { "write", 0ULL, 0},
82
- { "release_lockowner", 0ULL, 0},
83
-
84
- /* nfs41 */
85
- { "backchannel_ctl", 0ULL, 0},
86
- { "bind_conn_to_session", 0ULL, 0},
87
- { "exchange_id", 0ULL, 0},
88
- { "create_session", 0ULL, 0},
89
- { "destroy_session", 0ULL, 0},
90
- { "free_stateid", 0ULL, 0},
91
- { "get_dir_delegation", 0ULL, 0},
92
- { "getdeviceinfo", 0ULL, 0},
93
- { "getdevicelist", 0ULL, 0},
94
- { "layoutcommit", 0ULL, 0},
95
- { "layoutget", 0ULL, 0},
96
- { "layoutreturn", 0ULL, 0},
97
- { "secinfo_no_name", 0ULL, 0},
98
- { "sequence", 0ULL, 0},
99
- { "set_ssv", 0ULL, 0},
100
- { "test_stateid", 0ULL, 0},
101
- { "want_delegation", 0ULL, 0},
102
- { "destroy_clientid", 0ULL, 0},
103
- { "reclaim_complete", 0ULL, 0},
104
-
105
- /* nfs42 */
106
- { "allocate", 0ULL, 0},
107
- { "copy", 0ULL, 0},
108
- { "copy_notify", 0ULL, 0},
109
- { "deallocate", 0ULL, 0},
110
- { "io_advise", 0ULL, 0},
111
- { "layouterror", 0ULL, 0},
112
- { "layoutstats", 0ULL, 0},
113
- { "offload_cancel", 0ULL, 0},
114
- { "offload_status", 0ULL, 0},
115
- { "read_plus", 0ULL, 0},
116
- { "seek", 0ULL, 0},
117
- { "write_same", 0ULL, 0},
118
-
119
- /* termination */
120
- { "", 0ULL, 0 }
46
+ { "access", 0ULL, 0},
47
+ { "close", 0ULL, 0},
48
+ { "commit", 0ULL, 0},
49
+ { "create", 0ULL, 0},
50
+ { "delegpurge", 0ULL, 0},
51
+ { "delegreturn", 0ULL, 0},
52
+ { "getattr", 0ULL, 0},
53
+ { "getfh", 0ULL, 0},
54
+ { "link", 0ULL, 0},
55
+ { "lock", 0ULL, 0},
56
+ { "lockt", 0ULL, 0},
57
+ { "locku", 0ULL, 0},
58
+ { "lookup", 0ULL, 0},
59
+ { "lookupp", 0ULL, 0},
60
+ { "nverify", 0ULL, 0},
61
+ { "open", 0ULL, 0},
62
+ { "openattr", 0ULL, 0},
63
+ { "open_confirm", 0ULL, 0},
64
+ { "open_downgrade", 0ULL, 0},
65
+ { "putfh", 0ULL, 0},
66
+ { "putpubfh", 0ULL, 0},
67
+ { "putrootfh", 0ULL, 0},
68
+ { "read", 0ULL, 0},
69
+ { "readdir", 0ULL, 0},
70
+ { "readlink", 0ULL, 0},
71
+ { "remove", 0ULL, 0},
72
+ { "rename", 0ULL, 0},
73
+ { "renew", 0ULL, 0},
74
+ { "restorefh", 0ULL, 0},
75
+ { "savefh", 0ULL, 0},
76
+ { "secinfo", 0ULL, 0},
77
+ { "setattr", 0ULL, 0},
78
+ { "setclientid", 0ULL, 0},
79
+ { "setclientid_confirm", 0ULL, 0},
80
+ { "verify", 0ULL, 0},
81
+ { "write", 0ULL, 0},
82
+ { "release_lockowner", 0ULL, 0},
83
+
84
+ /* nfs41 */
85
+ { "backchannel_ctl", 0ULL, 0},
86
+ { "bind_conn_to_session", 0ULL, 0},
87
+ { "exchange_id", 0ULL, 0},
88
+ { "create_session", 0ULL, 0},
89
+ { "destroy_session", 0ULL, 0},
90
+ { "free_stateid", 0ULL, 0},
91
+ { "get_dir_delegation", 0ULL, 0},
92
+ { "getdeviceinfo", 0ULL, 0},
93
+ { "getdevicelist", 0ULL, 0},
94
+ { "layoutcommit", 0ULL, 0},
95
+ { "layoutget", 0ULL, 0},
96
+ { "layoutreturn", 0ULL, 0},
97
+ { "secinfo_no_name", 0ULL, 0},
98
+ { "sequence", 0ULL, 0},
99
+ { "set_ssv", 0ULL, 0},
100
+ { "test_stateid", 0ULL, 0},
101
+ { "want_delegation", 0ULL, 0},
102
+ { "destroy_clientid", 0ULL, 0},
103
+ { "reclaim_complete", 0ULL, 0},
104
+
105
+ /* nfs42 */
106
+ { "allocate", 0ULL, 0},
107
+ { "copy", 0ULL, 0},
108
+ { "copy_notify", 0ULL, 0},
109
+ { "deallocate", 0ULL, 0},
110
+ { "io_advise", 0ULL, 0},
111
+ { "layouterror", 0ULL, 0},
112
+ { "layoutstats", 0ULL, 0},
113
+ { "offload_cancel", 0ULL, 0},
114
+ { "offload_status", 0ULL, 0},
115
+ { "read_plus", 0ULL, 0},
116
+ { "seek", 0ULL, 0},
117
+ { "write_same", 0ULL, 0},
118
+
119
+ /* termination */
120
+ { "", 0ULL, 0 }
121
};
122
123
124
int do_proc_net_rpc_nfsd(int update_every, unsigned long long dt) {
125
- static procfile *ff = NULL;
126
- static int do_rc = -1, do_fh = -1, do_io = -1, do_th = -1, do_ra = -1, do_net = -1, do_rpc = -1, do_proc2 = -1, do_proc3 = -1, do_proc4 = -1, do_proc4ops = -1;
127
- static int ra_warning = 0, th_warning = 0, proc2_warning = 0, proc3_warning = 0, proc4_warning = 0, proc4ops_warning = 0;
128
-
129
- if(dt) {};
130
-
131
- if(!ff) {
132
- char filename[FILENAME_MAX + 1];
133
- snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/rpc/nfsd");
134
- ff = procfile_open(config_get("plugin:proc:/proc/net/rpc/nfsd", "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT);
135
- }
136
- if(!ff) return 1;
137
-
138
- ff = procfile_readall(ff);
139
- if(!ff) return 0; // we return 0, so that we will retry to open it next time
140
-
141
- if(do_rc == -1) do_rc = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "read cache", 1);
142
- if(do_fh == -1) do_fh = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "file handles", 1);
143
- if(do_io == -1) do_io = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "I/O", 1);
144
- if(do_th == -1) do_th = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "threads", 1);
145
- if(do_ra == -1) do_ra = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "read ahead", 1);
146
- if(do_net == -1) do_net = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "network", 1);
147
- if(do_rpc == -1) do_rpc = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "rpc", 1);
148
- if(do_proc2 == -1) do_proc2 = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "NFS v2 procedures", 1);
149
- if(do_proc3 == -1) do_proc3 = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "NFS v3 procedures", 1);
150
- if(do_proc4 == -1) do_proc4 = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "NFS v4 procedures", 1);
151
- if(do_proc4ops == -1) do_proc4ops = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "NFS v4 operations", 1);
152
-
153
- // if they are enabled, reset them to 1
154
- // later we do them =2 to avoid doing strcmp for all lines
155
- if(do_rc) do_rc = 1;
156
- if(do_fh) do_fh = 1;
157
- if(do_io) do_io = 1;
158
- if(do_th) do_th = 1;
159
- if(do_ra) do_ra = 1;
160
- if(do_net) do_net = 1;
161
- if(do_rpc) do_rpc = 1;
162
- if(do_proc2) do_proc2 = 1;
163
- if(do_proc3) do_proc3 = 1;
164
- if(do_proc4) do_proc4 = 1;
165
- if(do_proc4ops) do_proc4ops = 1;
166
-
167
- uint32_t lines = procfile_lines(ff), l;
168
- uint32_t words;
169
-
170
- char *type;
171
- unsigned long long rc_hits = 0, rc_misses = 0, rc_nocache = 0;
172
- unsigned long long fh_stale = 0, fh_total_lookups = 0, fh_anonymous_lookups = 0, fh_dir_not_in_dcache = 0, fh_non_dir_not_in_dcache = 0;
173
- unsigned long long io_read = 0, io_write = 0;
174
- unsigned long long th_threads = 0, th_fullcnt = 0, th_hist10 = 0, th_hist20 = 0, th_hist30 = 0, th_hist40 = 0, th_hist50 = 0, th_hist60 = 0, th_hist70 = 0, th_hist80 = 0, th_hist90 = 0, th_hist100 = 0;
175
- unsigned long long ra_size = 0, ra_hist10 = 0, ra_hist20 = 0, ra_hist30 = 0, ra_hist40 = 0, ra_hist50 = 0, ra_hist60 = 0, ra_hist70 = 0, ra_hist80 = 0, ra_hist90 = 0, ra_hist100 = 0, ra_none = 0;
176
- unsigned long long net_count = 0, net_udp_count = 0, net_tcp_count = 0, net_tcp_connections = 0;
177
- unsigned long long rpc_count = 0, rpc_bad_format = 0, rpc_bad_auth = 0, rpc_bad_client = 0;
178
-
179
- for(l = 0; l < lines ;l++) {
180
- words = procfile_linewords(ff, l);
181
- if(!words) continue;
182
-
183
- type = procfile_lineword(ff, l, 0);
184
-
185
- if(do_rc == 1 && strcmp(type, "rc") == 0) {
186
- if(words < 4) {
187
- error("%s line of /proc/net/rpc/nfsd has %u words, expected %d", type, words, 4);
188
- continue;
189
- }
190
-
191
- rc_hits = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
192
- rc_misses = strtoull(procfile_lineword(ff, l, 2), NULL, 10);
193
- rc_nocache = strtoull(procfile_lineword(ff, l, 3), NULL, 10);
194
-
195
- unsigned long long sum = rc_hits + rc_misses + rc_nocache;
196
- if(sum == 0ULL) do_rc = -1;
197
- else do_rc = 2;
198
- }
199
- else if(do_fh == 1 && strcmp(type, "fh") == 0) {
200
- if(words < 6) {
201
- error("%s line of /proc/net/rpc/nfsd has %u words, expected %d", type, words, 6);
202
- continue;
203
- }
204
-
205
- fh_stale = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
206
- fh_total_lookups = strtoull(procfile_lineword(ff, l, 2), NULL, 10);
207
- fh_anonymous_lookups = strtoull(procfile_lineword(ff, l, 3), NULL, 10);
208
- fh_dir_not_in_dcache = strtoull(procfile_lineword(ff, l, 4), NULL, 10);
209
- fh_non_dir_not_in_dcache = strtoull(procfile_lineword(ff, l, 5), NULL, 10);
210
-
211
- unsigned long long sum = fh_stale + fh_total_lookups + fh_anonymous_lookups + fh_dir_not_in_dcache + fh_non_dir_not_in_dcache;
212
- if(sum == 0ULL) do_fh = -1;
213
- else do_fh = 2;
214
- }
215
- else if(do_io == 1 && strcmp(type, "io") == 0) {
216
- if(words < 3) {
217
- error("%s line of /proc/net/rpc/nfsd has %u words, expected %d", type, words, 3);
218
- continue;
219
- }
220
-
221
- io_read = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
222
- io_write = strtoull(procfile_lineword(ff, l, 2), NULL, 10);
223
-
224
- unsigned long long sum = io_read + io_write;
225
- if(sum == 0ULL) do_io = -1;
226
- else do_io = 2;
227
- }
228
- else if(do_th == 1 && strcmp(type, "th") == 0) {
229
- if(words < 13) {
230
- error("%s line of /proc/net/rpc/nfsd has %u words, expected %d", type, words, 13);
231
- continue;
232
- }
233
-
234
- th_threads = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
235
- th_fullcnt = strtoull(procfile_lineword(ff, l, 2), NULL, 10);
236
- th_hist10 = (unsigned long long)(atof(procfile_lineword(ff, l, 3)) * 1000.0);
237
- th_hist20 = (unsigned long long)(atof(procfile_lineword(ff, l, 4)) * 1000.0);
238
- th_hist30 = (unsigned long long)(atof(procfile_lineword(ff, l, 5)) * 1000.0);
239
- th_hist40 = (unsigned long long)(atof(procfile_lineword(ff, l, 6)) * 1000.0);
240
- th_hist50 = (unsigned long long)(atof(procfile_lineword(ff, l, 7)) * 1000.0);
241
- th_hist60 = (unsigned long long)(atof(procfile_lineword(ff, l, 8)) * 1000.0);
242
- th_hist70 = (unsigned long long)(atof(procfile_lineword(ff, l, 9)) * 1000.0);
243
- th_hist80 = (unsigned long long)(atof(procfile_lineword(ff, l, 10)) * 1000.0);
244
- th_hist90 = (unsigned long long)(atof(procfile_lineword(ff, l, 11)) * 1000.0);
245
- th_hist100 = (unsigned long long)(atof(procfile_lineword(ff, l, 12)) * 1000.0);
246
-
247
- // threads histogram has been disabled on recent kernels
248
- // http://permalink.gmane.org/gmane.linux.nfs/24528
249
- unsigned long long sum = th_hist10 + th_hist20 + th_hist30 + th_hist40 + th_hist50 + th_hist60 + th_hist70 + th_hist80 + th_hist90 + th_hist100;
250
- if(sum == 0ULL) {
251
- if(!th_warning) {
252
- info("Disabling /proc/net/rpc/nfsd threads histogram. It seems unused on this machine. It will be enabled automatically when found with data in it.");
253
- th_warning = 1;
254
- }
255
- do_th = -1;
256
- }
257
- else do_th = 2;
258
- }
259
- else if(do_ra == 1 && strcmp(type, "ra") == 0) {
260
- if(words < 13) {
261
- error("%s line of /proc/net/rpc/nfsd has %u words, expected %d", type, words, 13);
262
- continue;
263
- }
264
-
265
- ra_size = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
266
- ra_hist10 = strtoull(procfile_lineword(ff, l, 2), NULL, 10);
267
- ra_hist20 = strtoull(procfile_lineword(ff, l, 3), NULL, 10);
268
- ra_hist30 = strtoull(procfile_lineword(ff, l, 4), NULL, 10);
269
- ra_hist40 = strtoull(procfile_lineword(ff, l, 5), NULL, 10);
270
- ra_hist50 = strtoull(procfile_lineword(ff, l, 6), NULL, 10);
271
- ra_hist60 = strtoull(procfile_lineword(ff, l, 7), NULL, 10);
272
- ra_hist70 = strtoull(procfile_lineword(ff, l, 8), NULL, 10);
273
- ra_hist80 = strtoull(procfile_lineword(ff, l, 9), NULL, 10);
274
- ra_hist90 = strtoull(procfile_lineword(ff, l, 10), NULL, 10);
275
- ra_hist100 = strtoull(procfile_lineword(ff, l, 11), NULL, 10);
276
- ra_none = strtoull(procfile_lineword(ff, l, 12), NULL, 10);
277
-
278
- unsigned long long sum = ra_hist10 + ra_hist20 + ra_hist30 + ra_hist40 + ra_hist50 + ra_hist60 + ra_hist70 + ra_hist80 + ra_hist90 + ra_hist100 + ra_none;
279
- if(sum == 0ULL) {
280
- if(!ra_warning) {
281
- info("Disabling /proc/net/rpc/nfsd read ahead histogram. It seems unused on this machine. It will be enabled automatically when found with data in it.");
282
- ra_warning = 1;
283
- }
284
- do_ra = -1;
285
- }
286
- else do_ra = 2;
287
- }
288
- else if(do_net == 1 && strcmp(type, "net") == 0) {
289
- if(words < 5) {
290
- error("%s line of /proc/net/rpc/nfsd has %u words, expected %d", type, words, 5);
291
- continue;
292
- }
293
-
294
- net_count = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
295
- net_udp_count = strtoull(procfile_lineword(ff, l, 2), NULL, 10);
296
- net_tcp_count = strtoull(procfile_lineword(ff, l, 3), NULL, 10);
297
- net_tcp_connections = strtoull(procfile_lineword(ff, l, 4), NULL, 10);
298
-
299
- unsigned long long sum = net_count + net_udp_count + net_tcp_count + net_tcp_connections;
300
- if(sum == 0ULL) do_net = -1;
301
- else do_net = 2;
302
- }
303
- else if(do_rpc == 1 && strcmp(type, "rpc") == 0) {
304
- if(words < 6) {
305
- error("%s line of /proc/net/rpc/nfsd has %u words, expected %d", type, words, 6);
306
- continue;
307
- }
308
-
309
- rpc_count = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
310
- rpc_bad_format = strtoull(procfile_lineword(ff, l, 2), NULL, 10);
311
- rpc_bad_auth = strtoull(procfile_lineword(ff, l, 3), NULL, 10);
312
- rpc_bad_client = strtoull(procfile_lineword(ff, l, 4), NULL, 10);
313
-
314
- unsigned long long sum = rpc_count + rpc_bad_format + rpc_bad_auth + rpc_bad_client;
315
- if(sum == 0ULL) do_rpc = -1;
316
- else do_rpc = 2;
317
- }
318
- else if(do_proc2 == 1 && strcmp(type, "proc2") == 0) {
319
- // the first number is the count of numbers present
320
- // so we start for word 2
321
-
322
- unsigned long long sum = 0;
323
- unsigned int i, j;
324
- for(i = 0, j = 2; j < words && nfsd_proc_values[i].name[0] ; i++, j++) {
325
- nfsd_proc_values[i].proc2 = strtoull(procfile_lineword(ff, l, j), NULL, 10);
326
- nfsd_proc_values[i].present2 = 1;
327
- sum += nfsd_proc_values[i].proc2;
328
- }
329
-
330
- if(sum == 0ULL) {
331
- if(!proc2_warning) {
332
- error("Disabling /proc/net/rpc/nfsd v2 procedure calls chart. It seems unused on this machine. It will be enabled automatically when found with data in it.");
333
- proc2_warning = 1;
334
- }
335
- do_proc2 = 0;
336
- }
337
- else do_proc2 = 2;
338
- }
339
- else if(do_proc3 == 1 && strcmp(type, "proc3") == 0) {
340
- // the first number is the count of numbers present
341
- // so we start for word 2
342
-
343
- unsigned long long sum = 0;
344
- unsigned int i, j;
345
- for(i = 0, j = 2; j < words && nfsd_proc_values[i].name[0] ; i++, j++) {
346
- nfsd_proc_values[i].proc3 = strtoull(procfile_lineword(ff, l, j), NULL, 10);
347
- nfsd_proc_values[i].present3 = 1;
348
- sum += nfsd_proc_values[i].proc3;
349
- }
350
-
351
- if(sum == 0ULL) {
352
- if(!proc3_warning) {
353
- info("Disabling /proc/net/rpc/nfsd v3 procedure calls chart. It seems unused on this machine. It will be enabled automatically when found with data in it.");
354
- proc3_warning = 1;
355
- }
356
- do_proc3 = 0;
357
- }
358
- else do_proc3 = 2;
359
- }
360
- else if(do_proc4 == 1 && strcmp(type, "proc4") == 0) {
361
- // the first number is the count of numbers present
362
- // so we start for word 2
363
-
364
- unsigned long long sum = 0;
365
- unsigned int i, j;
366
- for(i = 0, j = 2; j < words && nfsd_proc_values[i].name[0] ; i++, j++) {
367
- nfsd_proc_values[i].proc4 = strtoull(procfile_lineword(ff, l, j), NULL, 10);
368
- nfsd_proc_values[i].present4 = 1;
369
- sum += nfsd_proc_values[i].proc4;
370
- }
371
-
372
- if(sum == 0ULL) {
373
- if(!proc4_warning) {
374
- info("Disabling /proc/net/rpc/nfsd v4 procedure calls chart. It seems unused on this machine. It will be enabled automatically when found with data in it.");
375
- proc4_warning = 1;
376
- }
377
- do_proc4 = 0;
378
- }
379
- else do_proc4 = 2;
380
- }
381
- else if(do_proc4ops == 1 && strcmp(type, "proc4ops") == 0) {
382
- // the first number is the count of numbers present
383
- // so we start for word 2
384
-
385
- unsigned long long sum = 0;
386
- unsigned int i, j;
387
- for(i = 0, j = 2; j < words && nfsd4_ops_values[i].name[0] ; i++, j++) {
388
- nfsd4_ops_values[i].value = strtoull(procfile_lineword(ff, l, j), NULL, 10);
389
- nfsd4_ops_values[i].present = 1;
390
- sum += nfsd4_ops_values[i].value;
391
- }
392
-
393
- if(sum == 0ULL) {
394
- if(!proc4ops_warning) {
395
- info("Disabling /proc/net/rpc/nfsd v4 operations chart. It seems unused on this machine. It will be enabled automatically when found with data in it.");
396
- proc4ops_warning = 1;
397
- }
398
- do_proc4ops = 0;
399
- }
400
- else do_proc4ops = 2;
401
- }
402
- }
403
-
404
- RRDSET *st;
405
-
406
- // --------------------------------------------------------------------
407
-
408
- if(do_rc == 2) {
409
- st = rrdset_find_bytype("nfsd", "readcache");
410
- if(!st) {
411
- st = rrdset_create("nfsd", "readcache", NULL, "nfsd", NULL, "Read Cache", "reads/s", 5000, update_every, RRDSET_TYPE_STACKED);
412
-
413
- rrddim_add(st, "hits", NULL, 1, 1, RRDDIM_INCREMENTAL);
414
- rrddim_add(st, "misses", NULL, 1, 1, RRDDIM_INCREMENTAL);
415
- rrddim_add(st, "nocache", NULL, 1, 1, RRDDIM_INCREMENTAL);
416
- }
417
- else rrdset_next(st);
418
-
419
- rrddim_set(st, "hits", rc_hits);
420
- rrddim_set(st, "misses", rc_misses);
421
- rrddim_set(st, "nocache", rc_nocache);
422
- rrdset_done(st);
423
- }
424
-
425
- // --------------------------------------------------------------------
426
-
427
- if(do_fh == 2) {
428
- st = rrdset_find_bytype("nfsd", "filehandles");
429
- if(!st) {
430
- st = rrdset_create("nfsd", "filehandles", NULL, "nfsd", NULL, "File Handles", "handles/s", 5001, update_every, RRDSET_TYPE_LINE);
431
- st->isdetail = 1;
432
-
433
- rrddim_add(st, "stale", NULL, 1, 1, RRDDIM_ABSOLUTE);
434
- rrddim_add(st, "total_lookups", NULL, 1, 1, RRDDIM_INCREMENTAL);
435
- rrddim_add(st, "anonymous_lookups", NULL, 1, 1, RRDDIM_INCREMENTAL);
436
- rrddim_add(st, "dir_not_in_dcache", NULL, -1, 1, RRDDIM_INCREMENTAL);
437
- rrddim_add(st, "non_dir_not_in_dcache", NULL, -1, 1, RRDDIM_INCREMENTAL);
438
- }
439
- else rrdset_next(st);
440
-
441
- rrddim_set(st, "stale", fh_stale);
442
- rrddim_set(st, "total_lookups", fh_total_lookups);
443
- rrddim_set(st, "anonymous_lookups", fh_anonymous_lookups);
444
- rrddim_set(st, "dir_not_in_dcache", fh_dir_not_in_dcache);
445
- rrddim_set(st, "non_dir_not_in_dcache", fh_non_dir_not_in_dcache);
446
- rrdset_done(st);
447
- }
448
-
449
- // --------------------------------------------------------------------
450
-
451
- if(do_io == 2) {
452
- st = rrdset_find_bytype("nfsd", "io");
453
- if(!st) {
454
- st = rrdset_create("nfsd", "io", NULL, "nfsd", NULL, "I/O", "kilobytes/s", 5002, update_every, RRDSET_TYPE_AREA);
455
-
456
- rrddim_add(st, "read", NULL, 1, 1000, RRDDIM_INCREMENTAL);
457
- rrddim_add(st, "write", NULL, -1, 1000, RRDDIM_INCREMENTAL);
458
- }
459
- else rrdset_next(st);
460
-
461
- rrddim_set(st, "read", io_read);
462
- rrddim_set(st, "write", io_write);
463
- rrdset_done(st);
464
- }
465
-
466
- // --------------------------------------------------------------------
467
-
468
- if(do_th == 2) {
469
- st = rrdset_find_bytype("nfsd", "threads");
470
- if(!st) {
471
- st = rrdset_create("nfsd", "threads", NULL, "nfsd", NULL, "Threads", "threads", 5003, update_every, RRDSET_TYPE_LINE);
472
-
473
- rrddim_add(st, "threads", NULL, 1, 1, RRDDIM_ABSOLUTE);
474
- }
475
- else rrdset_next(st);
476
-
477
- rrddim_set(st, "threads", th_threads);
478
- rrdset_done(st);
479
-
480
- st = rrdset_find_bytype("nfsd", "threads_fullcnt");
481
- if(!st) {
482
- st = rrdset_create("nfsd", "threads_fullcnt", NULL, "nfsd", NULL, "Threads Full Count", "ops/s", 5004, update_every, RRDSET_TYPE_LINE);
483
-
484
- rrddim_add(st, "full_count", NULL, 1, 1, RRDDIM_INCREMENTAL);
485
- }
486
- else rrdset_next(st);
487
-
488
- rrddim_set(st, "full_count", th_fullcnt);
489
- rrdset_done(st);
490
-
491
- st = rrdset_find_bytype("nfsd", "threads_histogram");
492
- if(!st) {
493
- st = rrdset_create("nfsd", "threads_histogram", NULL, "nfsd", NULL, "Threads Usage Histogram", "percentage", 5005, update_every, RRDSET_TYPE_LINE);
494
-
495
- rrddim_add(st, "0%-10%", NULL, 1, 1000, RRDDIM_ABSOLUTE);
496
- rrddim_add(st, "10%-20%", NULL, 1, 1000, RRDDIM_ABSOLUTE);
497
- rrddim_add(st, "20%-30%", NULL, 1, 1000, RRDDIM_ABSOLUTE);
498
- rrddim_add(st, "30%-40%", NULL, 1, 1000, RRDDIM_ABSOLUTE);
499
- rrddim_add(st, "40%-50%", NULL, 1, 1000, RRDDIM_ABSOLUTE);
500
- rrddim_add(st, "50%-60%", NULL, 1, 1000, RRDDIM_ABSOLUTE);
501
- rrddim_add(st, "60%-70%", NULL, 1, 1000, RRDDIM_ABSOLUTE);
502
- rrddim_add(st, "70%-80%", NULL, 1, 1000, RRDDIM_ABSOLUTE);
503
- rrddim_add(st, "80%-90%", NULL, 1, 1000, RRDDIM_ABSOLUTE);
504
- rrddim_add(st, "90%-100%", NULL, 1, 1000, RRDDIM_ABSOLUTE);
505
- }
506
- else rrdset_next(st);
507
-
508
- rrddim_set(st, "0%-10%", th_hist10);
509
- rrddim_set(st, "10%-20%", th_hist20);
510
- rrddim_set(st, "20%-30%", th_hist30);
511
- rrddim_set(st, "30%-40%", th_hist40);
512
- rrddim_set(st, "40%-50%", th_hist50);
513
- rrddim_set(st, "50%-60%", th_hist60);
514
- rrddim_set(st, "60%-70%", th_hist70);
515
- rrddim_set(st, "70%-80%", th_hist80);
516
- rrddim_set(st, "80%-90%", th_hist90);
517
- rrddim_set(st, "90%-100%", th_hist100);
518
- rrdset_done(st);
519
- }
520
-
521
- // --------------------------------------------------------------------
522
-
523
- if(do_ra == 2) {
524
- st = rrdset_find_bytype("nfsd", "readahead");
525
- if(!st) {
526
- st = rrdset_create("nfsd", "readahead", NULL, "nfsd", NULL, "Read Ahead Depth", "percentage", 5005, update_every, RRDSET_TYPE_STACKED);
527
-
528
- rrddim_add(st, "10%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
529
- rrddim_add(st, "20%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
530
- rrddim_add(st, "30%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
531
- rrddim_add(st, "40%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
532
- rrddim_add(st, "50%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
533
- rrddim_add(st, "60%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
534
- rrddim_add(st, "70%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
535
- rrddim_add(st, "80%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
536
- rrddim_add(st, "90%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
537
- rrddim_add(st, "100%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
538
- rrddim_add(st, "misses", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
539
- }
540
- else rrdset_next(st);
541
-
542
- // ignore ra_size
543
- if(ra_size) {};
544
-
545
- rrddim_set(st, "10%", ra_hist10);
546
- rrddim_set(st, "20%", ra_hist20);
547
- rrddim_set(st, "30%", ra_hist30);
548
- rrddim_set(st, "40%", ra_hist40);
549
- rrddim_set(st, "50%", ra_hist50);
550
- rrddim_set(st, "60%", ra_hist60);
551
- rrddim_set(st, "70%", ra_hist70);
552
- rrddim_set(st, "80%", ra_hist80);
553
- rrddim_set(st, "90%", ra_hist90);
554
- rrddim_set(st, "100%", ra_hist100);
555
- rrddim_set(st, "misses", ra_none);
556
- rrdset_done(st);
557
- }
558
-
559
- // --------------------------------------------------------------------
560
-
561
- if(do_net == 2) {
562
- st = rrdset_find_bytype("nfsd", "net");
563
- if(!st) {
564
- st = rrdset_create("nfsd", "net", NULL, "nfsd", NULL, "Network Reads", "reads/s", 5007, update_every, RRDSET_TYPE_STACKED);
565
- st->isdetail = 1;
566
-
567
- rrddim_add(st, "udp", NULL, 1, 1, RRDDIM_INCREMENTAL);
568
- rrddim_add(st, "tcp", NULL, 1, 1, RRDDIM_INCREMENTAL);
569
- }
570
- else rrdset_next(st);
571
-
572
- // ignore net_count, net_tcp_connections
573
- if(net_count) {};
574
- if(net_tcp_connections) {};
575
-
576
- rrddim_set(st, "udp", net_udp_count);
577
- rrddim_set(st, "tcp", net_tcp_count);
578
- rrdset_done(st);
579
- }
580
-
581
- // --------------------------------------------------------------------
582
-
583
- if(do_rpc == 2) {
584
- st = rrdset_find_bytype("nfsd", "rpc");
585
- if(!st) {
586
- st = rrdset_create("nfsd", "rpc", NULL, "nfsd", NULL, "Remote Procedure Calls", "calls/s", 5008, update_every, RRDSET_TYPE_LINE);
587
- st->isdetail = 1;
588
-
589
- rrddim_add(st, "all", NULL, 1, 1, RRDDIM_INCREMENTAL);
590
- rrddim_add(st, "bad_format", NULL, -1, 1, RRDDIM_INCREMENTAL);
591
- rrddim_add(st, "bad_auth", NULL, -1, 1, RRDDIM_INCREMENTAL);
592
- }
593
- else rrdset_next(st);
594
-
595
- // ignore rpc_bad_client
596
- if(rpc_bad_client) {};
597
-
598
- rrddim_set(st, "all", rpc_count);
599
- rrddim_set(st, "bad_format", rpc_bad_format);
600
- rrddim_set(st, "bad_auth", rpc_bad_auth);
601
- rrdset_done(st);
602
- }
603
-
604
- // --------------------------------------------------------------------
605
-
606
- if(do_proc2 == 2) {
607
- unsigned int i;
608
- st = rrdset_find_bytype("nfsd", "proc2");
609
- if(!st) {
610
- st = rrdset_create("nfsd", "proc2", NULL, "nfsd", NULL, "NFS v2 Calls", "calls/s", 5009, update_every, RRDSET_TYPE_STACKED);
611
-
612
- for(i = 0; nfsd_proc_values[i].present2 ; i++)
613
- rrddim_add(st, nfsd_proc_values[i].name, NULL, 1, 1, RRDDIM_INCREMENTAL);
614
- }
615
- else rrdset_next(st);
616
-
617
- for(i = 0; nfsd_proc_values[i].present2 ; i++)
618
- rrddim_set(st, nfsd_proc_values[i].name, nfsd_proc_values[i].proc2);
619
-
620
- rrdset_done(st);
621
- }
622
-
623
- // --------------------------------------------------------------------
624
-
625
- if(do_proc3 == 2) {
626
- unsigned int i;
627
- st = rrdset_find_bytype("nfsd", "proc3");
628
- if(!st) {
629
- st = rrdset_create("nfsd", "proc3", NULL, "nfsd", NULL, "NFS v3 Calls", "calls/s", 5010, update_every, RRDSET_TYPE_STACKED);
630
-
631
- for(i = 0; nfsd_proc_values[i].present3 ; i++)
632
- rrddim_add(st, nfsd_proc_values[i].name, NULL, 1, 1, RRDDIM_INCREMENTAL);
633
- }
634
- else rrdset_next(st);
635
-
636
- for(i = 0; nfsd_proc_values[i].present3 ; i++)
637
- rrddim_set(st, nfsd_proc_values[i].name, nfsd_proc_values[i].proc3);
638
-
639
- rrdset_done(st);
640
- }
641
-
642
- // --------------------------------------------------------------------
643
-
644
- if(do_proc4 == 2) {
645
- unsigned int i;
646
- st = rrdset_find_bytype("nfsd", "proc4");
647
- if(!st) {
648
- st = rrdset_create("nfsd", "proc4", NULL, "nfsd", NULL, "NFS v4 Calls", "calls/s", 5011, update_every, RRDSET_TYPE_STACKED);
649
-
650
- for(i = 0; nfsd_proc_values[i].present4 ; i++)
651
- rrddim_add(st, nfsd_proc_values[i].name, NULL, 1, 1, RRDDIM_INCREMENTAL);
652
- }
653
- else rrdset_next(st);
125
+ static procfile *ff = NULL;
126
+ static int do_rc = -1, do_fh = -1, do_io = -1, do_th = -1, do_ra = -1, do_net = -1, do_rpc = -1, do_proc2 = -1, do_proc3 = -1, do_proc4 = -1, do_proc4ops = -1;
127
+ static int ra_warning = 0, th_warning = 0, proc2_warning = 0, proc3_warning = 0, proc4_warning = 0, proc4ops_warning = 0;
128
+
129
+ if(dt) {};
130
+
131
+ if(!ff) {
132
+ char filename[FILENAME_MAX + 1];
133
+ snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/rpc/nfsd");
134
+ ff = procfile_open(config_get("plugin:proc:/proc/net/rpc/nfsd", "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT);
135
+ }
136
+ if(!ff) return 1;
137
+
138
+ ff = procfile_readall(ff);
139
+ if(!ff) return 0; // we return 0, so that we will retry to open it next time
140
+
141
+ if(do_rc == -1) do_rc = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "read cache", 1);
142
+ if(do_fh == -1) do_fh = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "file handles", 1);
143
+ if(do_io == -1) do_io = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "I/O", 1);
144
+ if(do_th == -1) do_th = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "threads", 1);
145
+ if(do_ra == -1) do_ra = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "read ahead", 1);
146
+ if(do_net == -1) do_net = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "network", 1);
147
+ if(do_rpc == -1) do_rpc = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "rpc", 1);
148
+ if(do_proc2 == -1) do_proc2 = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "NFS v2 procedures", 1);
149
+ if(do_proc3 == -1) do_proc3 = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "NFS v3 procedures", 1);
150
+ if(do_proc4 == -1) do_proc4 = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "NFS v4 procedures", 1);
151
+ if(do_proc4ops == -1) do_proc4ops = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "NFS v4 operations", 1);
152
+
153
+ // if they are enabled, reset them to 1
154
+ // later we do them =2 to avoid doing strcmp for all lines
155
+ if(do_rc) do_rc = 1;
156
+ if(do_fh) do_fh = 1;
157
+ if(do_io) do_io = 1;
158
+ if(do_th) do_th = 1;
159
+ if(do_ra) do_ra = 1;
160
+ if(do_net) do_net = 1;
161
+ if(do_rpc) do_rpc = 1;
162
+ if(do_proc2) do_proc2 = 1;
163
+ if(do_proc3) do_proc3 = 1;
164
+ if(do_proc4) do_proc4 = 1;
165
+ if(do_proc4ops) do_proc4ops = 1;
166
+
167
+ uint32_t lines = procfile_lines(ff), l;
168
+ uint32_t words;
169
+
170
+ char *type;
171
+ unsigned long long rc_hits = 0, rc_misses = 0, rc_nocache = 0;
172
+ unsigned long long fh_stale = 0, fh_total_lookups = 0, fh_anonymous_lookups = 0, fh_dir_not_in_dcache = 0, fh_non_dir_not_in_dcache = 0;
173
+ unsigned long long io_read = 0, io_write = 0;
174
+ unsigned long long th_threads = 0, th_fullcnt = 0, th_hist10 = 0, th_hist20 = 0, th_hist30 = 0, th_hist40 = 0, th_hist50 = 0, th_hist60 = 0, th_hist70 = 0, th_hist80 = 0, th_hist90 = 0, th_hist100 = 0;
175
+ unsigned long long ra_size = 0, ra_hist10 = 0, ra_hist20 = 0, ra_hist30 = 0, ra_hist40 = 0, ra_hist50 = 0, ra_hist60 = 0, ra_hist70 = 0, ra_hist80 = 0, ra_hist90 = 0, ra_hist100 = 0, ra_none = 0;
176
+ unsigned long long net_count = 0, net_udp_count = 0, net_tcp_count = 0, net_tcp_connections = 0;
177
+ unsigned long long rpc_count = 0, rpc_bad_format = 0, rpc_bad_auth = 0, rpc_bad_client = 0;
178
+
179
+ for(l = 0; l < lines ;l++) {
180
+ words = procfile_linewords(ff, l);
181
+ if(!words) continue;
182
+
183
+ type = procfile_lineword(ff, l, 0);
184
+
185
+ if(do_rc == 1 && strcmp(type, "rc") == 0) {
186
+ if(words < 4) {
187
+ error("%s line of /proc/net/rpc/nfsd has %u words, expected %d", type, words, 4);
188
+ continue;
189
+ }
190
+
191
+ rc_hits = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
192
+ rc_misses = strtoull(procfile_lineword(ff, l, 2), NULL, 10);
193
+ rc_nocache = strtoull(procfile_lineword(ff, l, 3), NULL, 10);
194
+
195
+ unsigned long long sum = rc_hits + rc_misses + rc_nocache;
196
+ if(sum == 0ULL) do_rc = -1;
197
+ else do_rc = 2;
198
+ }
199
+ else if(do_fh == 1 && strcmp(type, "fh") == 0) {
200
+ if(words < 6) {
201
+ error("%s line of /proc/net/rpc/nfsd has %u words, expected %d", type, words, 6);
202
+ continue;
203
+ }
204
+
205
+ fh_stale = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
206
+ fh_total_lookups = strtoull(procfile_lineword(ff, l, 2), NULL, 10);
207
+ fh_anonymous_lookups = strtoull(procfile_lineword(ff, l, 3), NULL, 10);
208
+ fh_dir_not_in_dcache = strtoull(procfile_lineword(ff, l, 4), NULL, 10);
209
+ fh_non_dir_not_in_dcache = strtoull(procfile_lineword(ff, l, 5), NULL, 10);
210
+
211
+ unsigned long long sum = fh_stale + fh_total_lookups + fh_anonymous_lookups + fh_dir_not_in_dcache + fh_non_dir_not_in_dcache;
212
+ if(sum == 0ULL) do_fh = -1;
213
+ else do_fh = 2;
214
+ }
215
+ else if(do_io == 1 && strcmp(type, "io") == 0) {
216
+ if(words < 3) {
217
+ error("%s line of /proc/net/rpc/nfsd has %u words, expected %d", type, words, 3);
218
+ continue;
219
+ }
220
+
221
+ io_read = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
222
+ io_write = strtoull(procfile_lineword(ff, l, 2), NULL, 10);
223
+
224
+ unsigned long long sum = io_read + io_write;
225
+ if(sum == 0ULL) do_io = -1;
226
+ else do_io = 2;
227
+ }
228
+ else if(do_th == 1 && strcmp(type, "th") == 0) {
229
+ if(words < 13) {
230
+ error("%s line of /proc/net/rpc/nfsd has %u words, expected %d", type, words, 13);
231
+ continue;
232
+ }
233
+
234
+ th_threads = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
235
+ th_fullcnt = strtoull(procfile_lineword(ff, l, 2), NULL, 10);
236
+ th_hist10 = (unsigned long long)(atof(procfile_lineword(ff, l, 3)) * 1000.0);
237
+ th_hist20 = (unsigned long long)(atof(procfile_lineword(ff, l, 4)) * 1000.0);
238
+ th_hist30 = (unsigned long long)(atof(procfile_lineword(ff, l, 5)) * 1000.0);
239
+ th_hist40 = (unsigned long long)(atof(procfile_lineword(ff, l, 6)) * 1000.0);
240
+ th_hist50 = (unsigned long long)(atof(procfile_lineword(ff, l, 7)) * 1000.0);
241
+ th_hist60 = (unsigned long long)(atof(procfile_lineword(ff, l, 8)) * 1000.0);
242
+ th_hist70 = (unsigned long long)(atof(procfile_lineword(ff, l, 9)) * 1000.0);
243
+ th_hist80 = (unsigned long long)(atof(procfile_lineword(ff, l, 10)) * 1000.0);
244
+ th_hist90 = (unsigned long long)(atof(procfile_lineword(ff, l, 11)) * 1000.0);
245
+ th_hist100 = (unsigned long long)(atof(procfile_lineword(ff, l, 12)) * 1000.0);
246
+
247
+ // threads histogram has been disabled on recent kernels
248
+ // http://permalink.gmane.org/gmane.linux.nfs/24528
249
+ unsigned long long sum = th_hist10 + th_hist20 + th_hist30 + th_hist40 + th_hist50 + th_hist60 + th_hist70 + th_hist80 + th_hist90 + th_hist100;
250
+ if(sum == 0ULL) {
251
+ if(!th_warning) {
252
+ info("Disabling /proc/net/rpc/nfsd threads histogram. It seems unused on this machine. It will be enabled automatically when found with data in it.");
253
+ th_warning = 1;
254
+ }
255
+ do_th = -1;
256
+ }
257
+ else do_th = 2;
258
+ }
259
+ else if(do_ra == 1 && strcmp(type, "ra") == 0) {
260
+ if(words < 13) {
261
+ error("%s line of /proc/net/rpc/nfsd has %u words, expected %d", type, words, 13);
262
+ continue;
263
+ }
264
+
265
+ ra_size = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
266
+ ra_hist10 = strtoull(procfile_lineword(ff, l, 2), NULL, 10);
267
+ ra_hist20 = strtoull(procfile_lineword(ff, l, 3), NULL, 10);
268
+ ra_hist30 = strtoull(procfile_lineword(ff, l, 4), NULL, 10);
269
+ ra_hist40 = strtoull(procfile_lineword(ff, l, 5), NULL, 10);
270
+ ra_hist50 = strtoull(procfile_lineword(ff, l, 6), NULL, 10);
271
+ ra_hist60 = strtoull(procfile_lineword(ff, l, 7), NULL, 10);
272
+ ra_hist70 = strtoull(procfile_lineword(ff, l, 8), NULL, 10);
273
+ ra_hist80 = strtoull(procfile_lineword(ff, l, 9), NULL, 10);
274
+ ra_hist90 = strtoull(procfile_lineword(ff, l, 10), NULL, 10);
275
+ ra_hist100 = strtoull(procfile_lineword(ff, l, 11), NULL, 10);
276
+ ra_none = strtoull(procfile_lineword(ff, l, 12), NULL, 10);
277
+
278
+ unsigned long long sum = ra_hist10 + ra_hist20 + ra_hist30 + ra_hist40 + ra_hist50 + ra_hist60 + ra_hist70 + ra_hist80 + ra_hist90 + ra_hist100 + ra_none;
279
+ if(sum == 0ULL) {
280
+ if(!ra_warning) {
281
+ info("Disabling /proc/net/rpc/nfsd read ahead histogram. It seems unused on this machine. It will be enabled automatically when found with data in it.");
282
+ ra_warning = 1;
283
+ }
284
+ do_ra = -1;
285
+ }
286
+ else do_ra = 2;
287
+ }
288
+ else if(do_net == 1 && strcmp(type, "net") == 0) {
289
+ if(words < 5) {
290
+ error("%s line of /proc/net/rpc/nfsd has %u words, expected %d", type, words, 5);
291
+ continue;
292
+ }
293
+
294
+ net_count = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
295
+ net_udp_count = strtoull(procfile_lineword(ff, l, 2), NULL, 10);
296
+ net_tcp_count = strtoull(procfile_lineword(ff, l, 3), NULL, 10);
297
+ net_tcp_connections = strtoull(procfile_lineword(ff, l, 4), NULL, 10);
298
+
299
+ unsigned long long sum = net_count + net_udp_count + net_tcp_count + net_tcp_connections;
300
+ if(sum == 0ULL) do_net = -1;
301
+ else do_net = 2;
302
+ }
303
+ else if(do_rpc == 1 && strcmp(type, "rpc") == 0) {
304
+ if(words < 6) {
305
+ error("%s line of /proc/net/rpc/nfsd has %u words, expected %d", type, words, 6);
306
+ continue;
307
+ }
308
+
309
+ rpc_count = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
310
+ rpc_bad_format = strtoull(procfile_lineword(ff, l, 2), NULL, 10);
311
+ rpc_bad_auth = strtoull(procfile_lineword(ff, l, 3), NULL, 10);
312
+ rpc_bad_client = strtoull(procfile_lineword(ff, l, 4), NULL, 10);
313
+
314
+ unsigned long long sum = rpc_count + rpc_bad_format + rpc_bad_auth + rpc_bad_client;
315
+ if(sum == 0ULL) do_rpc = -1;
316
+ else do_rpc = 2;
317
+ }
318
+ else if(do_proc2 == 1 && strcmp(type, "proc2") == 0) {
319
+ // the first number is the count of numbers present
320
+ // so we start for word 2
321
+
322
+ unsigned long long sum = 0;
323
+ unsigned int i, j;
324
+ for(i = 0, j = 2; j < words && nfsd_proc_values[i].name[0] ; i++, j++) {
325
+ nfsd_proc_values[i].proc2 = strtoull(procfile_lineword(ff, l, j), NULL, 10);
326
+ nfsd_proc_values[i].present2 = 1;
327
+ sum += nfsd_proc_values[i].proc2;
328
+ }
329
+
330
+ if(sum == 0ULL) {
331
+ if(!proc2_warning) {
332
+ error("Disabling /proc/net/rpc/nfsd v2 procedure calls chart. It seems unused on this machine. It will be enabled automatically when found with data in it.");
333
+ proc2_warning = 1;
334
+ }
335
+ do_proc2 = 0;
336
+ }
337
+ else do_proc2 = 2;
338
+ }
339
+ else if(do_proc3 == 1 && strcmp(type, "proc3") == 0) {
340
+ // the first number is the count of numbers present
341
+ // so we start for word 2
342
+
343
+ unsigned long long sum = 0;
344
+ unsigned int i, j;
345
+ for(i = 0, j = 2; j < words && nfsd_proc_values[i].name[0] ; i++, j++) {
346
+ nfsd_proc_values[i].proc3 = strtoull(procfile_lineword(ff, l, j), NULL, 10);
347
+ nfsd_proc_values[i].present3 = 1;
348
+ sum += nfsd_proc_values[i].proc3;
349
+ }
350
+
351
+ if(sum == 0ULL) {
352
+ if(!proc3_warning) {
353
+ info("Disabling /proc/net/rpc/nfsd v3 procedure calls chart. It seems unused on this machine. It will be enabled automatically when found with data in it.");
354
+ proc3_warning = 1;
355
+ }
356
+ do_proc3 = 0;
357
+ }
358
+ else do_proc3 = 2;
359
+ }
360
+ else if(do_proc4 == 1 && strcmp(type, "proc4") == 0) {
361
+ // the first number is the count of numbers present
362
+ // so we start for word 2
363
+
364
+ unsigned long long sum = 0;
365
+ unsigned int i, j;
366
+ for(i = 0, j = 2; j < words && nfsd_proc_values[i].name[0] ; i++, j++) {
367
+ nfsd_proc_values[i].proc4 = strtoull(procfile_lineword(ff, l, j), NULL, 10);
368
+ nfsd_proc_values[i].present4 = 1;
369
+ sum += nfsd_proc_values[i].proc4;
370
+ }
371
+
372
+ if(sum == 0ULL) {
373
+ if(!proc4_warning) {
374
+ info("Disabling /proc/net/rpc/nfsd v4 procedure calls chart. It seems unused on this machine. It will be enabled automatically when found with data in it.");
375
+ proc4_warning = 1;
376
+ }
377
+ do_proc4 = 0;
378
+ }
379
+ else do_proc4 = 2;
380
+ }
381
+ else if(do_proc4ops == 1 && strcmp(type, "proc4ops") == 0) {
382
+ // the first number is the count of numbers present
383
+ // so we start for word 2
384
+
385
+ unsigned long long sum = 0;
386
+ unsigned int i, j;
387
+ for(i = 0, j = 2; j < words && nfsd4_ops_values[i].name[0] ; i++, j++) {
388
+ nfsd4_ops_values[i].value = strtoull(procfile_lineword(ff, l, j), NULL, 10);
389
+ nfsd4_ops_values[i].present = 1;
390
+ sum += nfsd4_ops_values[i].value;
391
+ }
392
+
393
+ if(sum == 0ULL) {
394
+ if(!proc4ops_warning) {
395
+ info("Disabling /proc/net/rpc/nfsd v4 operations chart. It seems unused on this machine. It will be enabled automatically when found with data in it.");
396
+ proc4ops_warning = 1;
397
+ }
398
+ do_proc4ops = 0;
399
+ }
400
+ else do_proc4ops = 2;
401
+ }
402
+ }
403
+
404
+ RRDSET *st;
405
+
406
+ // --------------------------------------------------------------------
407
+
408
+ if(do_rc == 2) {
409
+ st = rrdset_find_bytype("nfsd", "readcache");
410
+ if(!st) {
411
+ st = rrdset_create("nfsd", "readcache", NULL, "nfsd", NULL, "Read Cache", "reads/s", 5000, update_every, RRDSET_TYPE_STACKED);
412
+
413
+ rrddim_add(st, "hits", NULL, 1, 1, RRDDIM_INCREMENTAL);
414
+ rrddim_add(st, "misses", NULL, 1, 1, RRDDIM_INCREMENTAL);
415
+ rrddim_add(st, "nocache", NULL, 1, 1, RRDDIM_INCREMENTAL);
416
+ }
417
+ else rrdset_next(st);
418
+
419
+ rrddim_set(st, "hits", rc_hits);
420
+ rrddim_set(st, "misses", rc_misses);
421
+ rrddim_set(st, "nocache", rc_nocache);
422
+ rrdset_done(st);
423
+ }
424
+
425
+ // --------------------------------------------------------------------
426
+
427
+ if(do_fh == 2) {
428
+ st = rrdset_find_bytype("nfsd", "filehandles");
429
+ if(!st) {
430
+ st = rrdset_create("nfsd", "filehandles", NULL, "nfsd", NULL, "File Handles", "handles/s", 5001, update_every, RRDSET_TYPE_LINE);
431
+ st->isdetail = 1;
432
+
433
+ rrddim_add(st, "stale", NULL, 1, 1, RRDDIM_ABSOLUTE);
434
+ rrddim_add(st, "total_lookups", NULL, 1, 1, RRDDIM_INCREMENTAL);
435
+ rrddim_add(st, "anonymous_lookups", NULL, 1, 1, RRDDIM_INCREMENTAL);
436
+ rrddim_add(st, "dir_not_in_dcache", NULL, -1, 1, RRDDIM_INCREMENTAL);
437
+ rrddim_add(st, "non_dir_not_in_dcache", NULL, -1, 1, RRDDIM_INCREMENTAL);
438
+ }
439
+ else rrdset_next(st);
440
+
441
+ rrddim_set(st, "stale", fh_stale);
442
+ rrddim_set(st, "total_lookups", fh_total_lookups);
443
+ rrddim_set(st, "anonymous_lookups", fh_anonymous_lookups);
444
+ rrddim_set(st, "dir_not_in_dcache", fh_dir_not_in_dcache);
445
+ rrddim_set(st, "non_dir_not_in_dcache", fh_non_dir_not_in_dcache);
446
+ rrdset_done(st);
447
+ }
448
+
449
+ // --------------------------------------------------------------------
450
+
451
+ if(do_io == 2) {
452
+ st = rrdset_find_bytype("nfsd", "io");
453
+ if(!st) {
454
+ st = rrdset_create("nfsd", "io", NULL, "nfsd", NULL, "I/O", "kilobytes/s", 5002, update_every, RRDSET_TYPE_AREA);
455
+
456
+ rrddim_add(st, "read", NULL, 1, 1000, RRDDIM_INCREMENTAL);
457
+ rrddim_add(st, "write", NULL, -1, 1000, RRDDIM_INCREMENTAL);
458
+ }
459
+ else rrdset_next(st);
460
+
461
+ rrddim_set(st, "read", io_read);
462
+ rrddim_set(st, "write", io_write);
463
+ rrdset_done(st);
464
+ }
465
+
466
+ // --------------------------------------------------------------------
467
+
468
+ if(do_th == 2) {
469
+ st = rrdset_find_bytype("nfsd", "threads");
470
+ if(!st) {
471
+ st = rrdset_create("nfsd", "threads", NULL, "nfsd", NULL, "Threads", "threads", 5003, update_every, RRDSET_TYPE_LINE);
472
+
473
+ rrddim_add(st, "threads", NULL, 1, 1, RRDDIM_ABSOLUTE);
474
+ }
475
+ else rrdset_next(st);
476
+
477
+ rrddim_set(st, "threads", th_threads);
478
+ rrdset_done(st);
479
+
480
+ st = rrdset_find_bytype("nfsd", "threads_fullcnt");
481
+ if(!st) {
482
+ st = rrdset_create("nfsd", "threads_fullcnt", NULL, "nfsd", NULL, "Threads Full Count", "ops/s", 5004, update_every, RRDSET_TYPE_LINE);
483
+
484
+ rrddim_add(st, "full_count", NULL, 1, 1, RRDDIM_INCREMENTAL);
485
+ }
486
+ else rrdset_next(st);
487
+
488
+ rrddim_set(st, "full_count", th_fullcnt);
489
+ rrdset_done(st);
490
+
491
+ st = rrdset_find_bytype("nfsd", "threads_histogram");
492
+ if(!st) {
493
+ st = rrdset_create("nfsd", "threads_histogram", NULL, "nfsd", NULL, "Threads Usage Histogram", "percentage", 5005, update_every, RRDSET_TYPE_LINE);
494
+
495
+ rrddim_add(st, "0%-10%", NULL, 1, 1000, RRDDIM_ABSOLUTE);
496
+ rrddim_add(st, "10%-20%", NULL, 1, 1000, RRDDIM_ABSOLUTE);
497
+ rrddim_add(st, "20%-30%", NULL, 1, 1000, RRDDIM_ABSOLUTE);
498
+ rrddim_add(st, "30%-40%", NULL, 1, 1000, RRDDIM_ABSOLUTE);
499
+ rrddim_add(st, "40%-50%", NULL, 1, 1000, RRDDIM_ABSOLUTE);
500
+ rrddim_add(st, "50%-60%", NULL, 1, 1000, RRDDIM_ABSOLUTE);
501
+ rrddim_add(st, "60%-70%", NULL, 1, 1000, RRDDIM_ABSOLUTE);
502
+ rrddim_add(st, "70%-80%", NULL, 1, 1000, RRDDIM_ABSOLUTE);
503
+ rrddim_add(st, "80%-90%", NULL, 1, 1000, RRDDIM_ABSOLUTE);
504
+ rrddim_add(st, "90%-100%", NULL, 1, 1000, RRDDIM_ABSOLUTE);
505
+ }
506
+ else rrdset_next(st);
507
+
508
+ rrddim_set(st, "0%-10%", th_hist10);
509
+ rrddim_set(st, "10%-20%", th_hist20);
510
+ rrddim_set(st, "20%-30%", th_hist30);
511
+ rrddim_set(st, "30%-40%", th_hist40);
512
+ rrddim_set(st, "40%-50%", th_hist50);
513
+ rrddim_set(st, "50%-60%", th_hist60);
514
+ rrddim_set(st, "60%-70%", th_hist70);
515
+ rrddim_set(st, "70%-80%", th_hist80);
516
+ rrddim_set(st, "80%-90%", th_hist90);
517
+ rrddim_set(st, "90%-100%", th_hist100);
518
+ rrdset_done(st);
519
+ }
520
+
521
+ // --------------------------------------------------------------------
522
+
523
+ if(do_ra == 2) {
524
+ st = rrdset_find_bytype("nfsd", "readahead");
525
+ if(!st) {
526
+ st = rrdset_create("nfsd", "readahead", NULL, "nfsd", NULL, "Read Ahead Depth", "percentage", 5005, update_every, RRDSET_TYPE_STACKED);
527
+
528
+ rrddim_add(st, "10%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
529
+ rrddim_add(st, "20%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
530
+ rrddim_add(st, "30%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
531
+ rrddim_add(st, "40%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
532
+ rrddim_add(st, "50%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
533
+ rrddim_add(st, "60%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
534
+ rrddim_add(st, "70%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
535
+ rrddim_add(st, "80%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
536
+ rrddim_add(st, "90%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
537
+ rrddim_add(st, "100%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
538
+ rrddim_add(st, "misses", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
539
+ }
540
+ else rrdset_next(st);
541
+
542
+ // ignore ra_size
543
+ if(ra_size) {};
544
+
545
+ rrddim_set(st, "10%", ra_hist10);
546
+ rrddim_set(st, "20%", ra_hist20);
547
+ rrddim_set(st, "30%", ra_hist30);
548
+ rrddim_set(st, "40%", ra_hist40);
549
+ rrddim_set(st, "50%", ra_hist50);
550
+ rrddim_set(st, "60%", ra_hist60);
551
+ rrddim_set(st, "70%", ra_hist70);
552
+ rrddim_set(st, "80%", ra_hist80);
553
+ rrddim_set(st, "90%", ra_hist90);
554
+ rrddim_set(st, "100%", ra_hist100);
555
+ rrddim_set(st, "misses", ra_none);
556
+ rrdset_done(st);
557
+ }
558
+
559
+ // --------------------------------------------------------------------
560
+
561
+ if(do_net == 2) {
562
+ st = rrdset_find_bytype("nfsd", "net");
563
+ if(!st) {
564
+ st = rrdset_create("nfsd", "net", NULL, "nfsd", NULL, "Network Reads", "reads/s", 5007, update_every, RRDSET_TYPE_STACKED);
565
+ st->isdetail = 1;
566
+
567
+ rrddim_add(st, "udp", NULL, 1, 1, RRDDIM_INCREMENTAL);
568
+ rrddim_add(st, "tcp", NULL, 1, 1, RRDDIM_INCREMENTAL);
569
+ }
570
+ else rrdset_next(st);
571
+
572
+ // ignore net_count, net_tcp_connections
573
+ if(net_count) {};
574
+ if(net_tcp_connections) {};
575
+
576
+ rrddim_set(st, "udp", net_udp_count);
577
+ rrddim_set(st, "tcp", net_tcp_count);
578
+ rrdset_done(st);
579
+ }
580
+
581
+ // --------------------------------------------------------------------
582
+
583
+ if(do_rpc == 2) {
584
+ st = rrdset_find_bytype("nfsd", "rpc");
585
+ if(!st) {
586
+ st = rrdset_create("nfsd", "rpc", NULL, "nfsd", NULL, "Remote Procedure Calls", "calls/s", 5008, update_every, RRDSET_TYPE_LINE);
587
+ st->isdetail = 1;
588
+
589
+ rrddim_add(st, "all", NULL, 1, 1, RRDDIM_INCREMENTAL);
590
+ rrddim_add(st, "bad_format", NULL, -1, 1, RRDDIM_INCREMENTAL);
591
+ rrddim_add(st, "bad_auth", NULL, -1, 1, RRDDIM_INCREMENTAL);
592
+ }
593
+ else rrdset_next(st);
594
+
595
+ // ignore rpc_bad_client
596
+ if(rpc_bad_client) {};
597
+
598
+ rrddim_set(st, "all", rpc_count);
599
+ rrddim_set(st, "bad_format", rpc_bad_format);
600
+ rrddim_set(st, "bad_auth", rpc_bad_auth);
601
+ rrdset_done(st);
602
+ }
603
+
604
+ // --------------------------------------------------------------------
605
+
606
+ if(do_proc2 == 2) {
607
+ unsigned int i;
608
+ st = rrdset_find_bytype("nfsd", "proc2");
609
+ if(!st) {
610
+ st = rrdset_create("nfsd", "proc2", NULL, "nfsd", NULL, "NFS v2 Calls", "calls/s", 5009, update_every, RRDSET_TYPE_STACKED);
611
+
612
+ for(i = 0; nfsd_proc_values[i].present2 ; i++)
613
+ rrddim_add(st, nfsd_proc_values[i].name, NULL, 1, 1, RRDDIM_INCREMENTAL);
614
+ }
615
+ else rrdset_next(st);
616
+
617
+ for(i = 0; nfsd_proc_values[i].present2 ; i++)
618
+ rrddim_set(st, nfsd_proc_values[i].name, nfsd_proc_values[i].proc2);
619
+
620
+ rrdset_done(st);
621
+ }
622
+
623
+ // --------------------------------------------------------------------
624
+
625
+ if(do_proc3 == 2) {
626
+ unsigned int i;
627
+ st = rrdset_find_bytype("nfsd", "proc3");
628
+ if(!st) {
629
+ st = rrdset_create("nfsd", "proc3", NULL, "nfsd", NULL, "NFS v3 Calls", "calls/s", 5010, update_every, RRDSET_TYPE_STACKED);
630
+
631
+ for(i = 0; nfsd_proc_values[i].present3 ; i++)
632
+ rrddim_add(st, nfsd_proc_values[i].name, NULL, 1, 1, RRDDIM_INCREMENTAL);
633
+ }
634
+ else rrdset_next(st);
635
+
636
+ for(i = 0; nfsd_proc_values[i].present3 ; i++)
637
+ rrddim_set(st, nfsd_proc_values[i].name, nfsd_proc_values[i].proc3);
638
+
639
+ rrdset_done(st);
640
+ }
641
+
642
+ // --------------------------------------------------------------------
643
+
644
+ if(do_proc4 == 2) {
645
+ unsigned int i;
646
+ st = rrdset_find_bytype("nfsd", "proc4");
647
+ if(!st) {
648
+ st = rrdset_create("nfsd", "proc4", NULL, "nfsd", NULL, "NFS v4 Calls", "calls/s", 5011, update_every, RRDSET_TYPE_STACKED);
649
+
650
+ for(i = 0; nfsd_proc_values[i].present4 ; i++)
651
+ rrddim_add(st, nfsd_proc_values[i].name, NULL, 1, 1, RRDDIM_INCREMENTAL);
652
+ }
653
+ else rrdset_next(st);
654
655
- for(i = 0; nfsd_proc_values[i].present4 ; i++)
656
- rrddim_set(st, nfsd_proc_values[i].name, nfsd_proc_values[i].proc4);
655
+ for(i = 0; nfsd_proc_values[i].present4 ; i++)
656
+ rrddim_set(st, nfsd_proc_values[i].name, nfsd_proc_values[i].proc4);
657
658
- rrdset_done(st);
659
- }
658
+ rrdset_done(st);
659
+ }
660
661
- // --------------------------------------------------------------------
661
+ // --------------------------------------------------------------------
662
663
- if(do_proc4ops == 2) {
664
- unsigned int i;
665
- st = rrdset_find_bytype("nfsd", "proc4ops");
666
- if(!st) {
667
- st = rrdset_create("nfsd", "proc4ops", NULL, "nfsd", NULL, "NFS v4 Operations", "operations/s", 5012, update_every, RRDSET_TYPE_STACKED);
663
+ if(do_proc4ops == 2) {
664
+ unsigned int i;
665
+ st = rrdset_find_bytype("nfsd", "proc4ops");
666
+ if(!st) {
667
+ st = rrdset_create("nfsd", "proc4ops", NULL, "nfsd", NULL, "NFS v4 Operations", "operations/s", 5012, update_every, RRDSET_TYPE_STACKED);
668
669
- for(i = 0; nfsd4_ops_values[i].present ; i++)
670
- rrddim_add(st, nfsd4_ops_values[i].name, NULL, 1, 1, RRDDIM_INCREMENTAL);
671
- }
672
- else rrdset_next(st);
669
+ for(i = 0; nfsd4_ops_values[i].present ; i++)
670
+ rrddim_add(st, nfsd4_ops_values[i].name, NULL, 1, 1, RRDDIM_INCREMENTAL);
671
+ }
672
+ else rrdset_next(st);
673
674
- for(i = 0; nfsd4_ops_values[i].present ; i++)
675
- rrddim_set(st, nfsd4_ops_values[i].name, nfsd4_ops_values[i].value);
674
+ for(i = 0; nfsd4_ops_values[i].present ; i++)
675
+ rrddim_set(st, nfsd4_ops_values[i].name, nfsd4_ops_values[i].value);
676
677
- rrdset_done(st);
678
- }
677
+ rrdset_done(st);
678
+ }
679
680
- return 0;
680
+ return 0;
681
}
src/proc_net_snmp.c
+348
-348
@@ -1,354 +1,354 @@
1
#include "common.h"
2
3
-#define RRD_TYPE_NET_SNMP "ipv4"
4
-#define RRD_TYPE_NET_SNMP_LEN strlen(RRD_TYPE_NET_SNMP)
3
+#define RRD_TYPE_NET_SNMP "ipv4"
4
+#define RRD_TYPE_NET_SNMP_LEN strlen(RRD_TYPE_NET_SNMP)
5
6
int do_proc_net_snmp(int update_every, unsigned long long dt) {
7
- static procfile *ff = NULL;
8
- static int do_ip_packets = -1, do_ip_fragsout = -1, do_ip_fragsin = -1, do_ip_errors = -1,
9
- do_tcp_sockets = -1, do_tcp_packets = -1, do_tcp_errors = -1, do_tcp_handshake = -1,
10
- do_udp_packets = -1, do_udp_errors = -1;
11
-
12
- if(do_ip_packets == -1) do_ip_packets = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 packets", 1);
13
- if(do_ip_fragsout == -1) do_ip_fragsout = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 fragments sent", 1);
14
- if(do_ip_fragsin == -1) do_ip_fragsin = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 fragments assembly", 1);
15
- if(do_ip_errors == -1) do_ip_errors = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 errors", 1);
16
- if(do_tcp_sockets == -1) do_tcp_sockets = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 TCP connections", 1);
17
- if(do_tcp_packets == -1) do_tcp_packets = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 TCP packets", 1);
18
- if(do_tcp_errors == -1) do_tcp_errors = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 TCP errors", 1);
19
- if(do_tcp_handshake == -1) do_tcp_handshake = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 TCP handshake issues", 1);
20
- if(do_udp_packets == -1) do_udp_packets = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 UDP packets", 1);
21
- if(do_udp_errors == -1) do_udp_errors = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 UDP errors", 1);
22
-
23
- if(dt) {};
24
-
25
- if(!ff) {
26
- char filename[FILENAME_MAX + 1];
27
- snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/snmp");
28
- ff = procfile_open(config_get("plugin:proc:/proc/net/snmp", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
29
- }
30
- if(!ff) return 1;
31
-
32
- ff = procfile_readall(ff);
33
- if(!ff) return 0; // we return 0, so that we will retry to open it next time
34
-
35
- uint32_t lines = procfile_lines(ff), l;
36
- uint32_t words;
37
-
38
- RRDSET *st;
39
-
40
- for(l = 0; l < lines ;l++) {
41
- if(strcmp(procfile_lineword(ff, l, 0), "Ip") == 0) {
42
- l++;
43
-
44
- if(strcmp(procfile_lineword(ff, l, 0), "Ip") != 0) {
45
- error("Cannot read Ip line from /proc/net/snmp.");
46
- break;
47
- }
48
-
49
- words = procfile_linewords(ff, l);
50
- if(words < 20) {
51
- error("Cannot read /proc/net/snmp Ip line. Expected 20 params, read %u.", words);
52
- continue;
53
- }
54
-
55
- // see also http://net-snmp.sourceforge.net/docs/mibs/ip.html
56
- unsigned long long Forwarding, DefaultTTL, InReceives, InHdrErrors, InAddrErrors, ForwDatagrams, InUnknownProtos, InDiscards, InDelivers,
57
- OutRequests, OutDiscards, OutNoRoutes, ReasmTimeout, ReasmReqds, ReasmOKs, ReasmFails, FragOKs, FragFails, FragCreates;
58
-
59
- Forwarding = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
60
- DefaultTTL = strtoull(procfile_lineword(ff, l, 2), NULL, 10);
61
- InReceives = strtoull(procfile_lineword(ff, l, 3), NULL, 10);
62
- InHdrErrors = strtoull(procfile_lineword(ff, l, 4), NULL, 10);
63
- InAddrErrors = strtoull(procfile_lineword(ff, l, 5), NULL, 10);
64
- ForwDatagrams = strtoull(procfile_lineword(ff, l, 6), NULL, 10);
65
- InUnknownProtos = strtoull(procfile_lineword(ff, l, 7), NULL, 10);
66
- InDiscards = strtoull(procfile_lineword(ff, l, 8), NULL, 10);
67
- InDelivers = strtoull(procfile_lineword(ff, l, 9), NULL, 10);
68
- OutRequests = strtoull(procfile_lineword(ff, l, 10), NULL, 10);
69
- OutDiscards = strtoull(procfile_lineword(ff, l, 11), NULL, 10);
70
- OutNoRoutes = strtoull(procfile_lineword(ff, l, 12), NULL, 10);
71
- ReasmTimeout = strtoull(procfile_lineword(ff, l, 13), NULL, 10);
72
- ReasmReqds = strtoull(procfile_lineword(ff, l, 14), NULL, 10);
73
- ReasmOKs = strtoull(procfile_lineword(ff, l, 15), NULL, 10);
74
- ReasmFails = strtoull(procfile_lineword(ff, l, 16), NULL, 10);
75
- FragOKs = strtoull(procfile_lineword(ff, l, 17), NULL, 10);
76
- FragFails = strtoull(procfile_lineword(ff, l, 18), NULL, 10);
77
- FragCreates = strtoull(procfile_lineword(ff, l, 19), NULL, 10);
78
-
79
- // these are not counters
80
- if(Forwarding) {}; // is forwarding enabled?
81
- if(DefaultTTL) {}; // the default ttl on packets
82
- if(ReasmTimeout) {}; // Reassembly timeout
83
-
84
- // this counter is not used
85
- if(InDelivers) {}; // total number of packets delivered to IP user-protocols
86
-
87
- // --------------------------------------------------------------------
88
-
89
- if(do_ip_packets) {
90
- st = rrdset_find(RRD_TYPE_NET_SNMP ".packets");
91
- if(!st) {
92
- st = rrdset_create(RRD_TYPE_NET_SNMP, "packets", NULL, "packets", NULL, "IPv4 Packets", "packets/s", 3000, update_every, RRDSET_TYPE_LINE);
93
-
94
- rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
95
- rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
96
- rrddim_add(st, "forwarded", NULL, 1, 1, RRDDIM_INCREMENTAL);
97
- }
98
- else rrdset_next(st);
99
-
100
- rrddim_set(st, "sent", OutRequests);
101
- rrddim_set(st, "received", InReceives);
102
- rrddim_set(st, "forwarded", ForwDatagrams);
103
- rrdset_done(st);
104
- }
105
-
106
- // --------------------------------------------------------------------
107
-
108
- if(do_ip_fragsout) {
109
- st = rrdset_find(RRD_TYPE_NET_SNMP ".fragsout");
110
- if(!st) {
111
- st = rrdset_create(RRD_TYPE_NET_SNMP, "fragsout", NULL, "fragments", NULL, "IPv4 Fragments Sent", "packets/s", 3010, update_every, RRDSET_TYPE_LINE);
112
- st->isdetail = 1;
113
-
114
- rrddim_add(st, "ok", NULL, 1, 1, RRDDIM_INCREMENTAL);
115
- rrddim_add(st, "failed", NULL, -1, 1, RRDDIM_INCREMENTAL);
116
- rrddim_add(st, "all", NULL, 1, 1, RRDDIM_INCREMENTAL);
117
- }
118
- else rrdset_next(st);
119
-
120
- rrddim_set(st, "ok", FragOKs);
121
- rrddim_set(st, "failed", FragFails);
122
- rrddim_set(st, "all", FragCreates);
123
- rrdset_done(st);
124
- }
125
-
126
- // --------------------------------------------------------------------
127
-
128
- if(do_ip_fragsin) {
129
- st = rrdset_find(RRD_TYPE_NET_SNMP ".fragsin");
130
- if(!st) {
131
- st = rrdset_create(RRD_TYPE_NET_SNMP, "fragsin", NULL, "fragments", NULL, "IPv4 Fragments Reassembly", "packets/s", 3011, update_every, RRDSET_TYPE_LINE);
132
- st->isdetail = 1;
133
-
134
- rrddim_add(st, "ok", NULL, 1, 1, RRDDIM_INCREMENTAL);
135
- rrddim_add(st, "failed", NULL, -1, 1, RRDDIM_INCREMENTAL);
136
- rrddim_add(st, "all", NULL, 1, 1, RRDDIM_INCREMENTAL);
137
- }
138
- else rrdset_next(st);
139
-
140
- rrddim_set(st, "ok", ReasmOKs);
141
- rrddim_set(st, "failed", ReasmFails);
142
- rrddim_set(st, "all", ReasmReqds);
143
- rrdset_done(st);
144
- }
145
-
146
- // --------------------------------------------------------------------
147
-
148
- if(do_ip_errors) {
149
- st = rrdset_find(RRD_TYPE_NET_SNMP ".errors");
150
- if(!st) {
151
- st = rrdset_create(RRD_TYPE_NET_SNMP, "errors", NULL, "errors", NULL, "IPv4 Errors", "packets/s", 3002, update_every, RRDSET_TYPE_LINE);
152
- st->isdetail = 1;
153
-
154
- rrddim_add(st, "InDiscards", NULL, 1, 1, RRDDIM_INCREMENTAL);
155
- rrddim_add(st, "OutDiscards", NULL, -1, 1, RRDDIM_INCREMENTAL);
156
-
157
- rrddim_add(st, "InHdrErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
158
- rrddim_add(st, "InAddrErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
159
- rrddim_add(st, "InUnknownProtos", NULL, 1, 1, RRDDIM_INCREMENTAL);
160
-
161
- rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRDDIM_INCREMENTAL);
162
- }
163
- else rrdset_next(st);
164
-
165
- rrddim_set(st, "InDiscards", InDiscards);
166
- rrddim_set(st, "OutDiscards", OutDiscards);
167
- rrddim_set(st, "InHdrErrors", InHdrErrors);
168
- rrddim_set(st, "InAddrErrors", InAddrErrors);
169
- rrddim_set(st, "InUnknownProtos", InUnknownProtos);
170
- rrddim_set(st, "OutNoRoutes", OutNoRoutes);
171
- rrdset_done(st);
172
- }
173
- }
174
- else if(strcmp(procfile_lineword(ff, l, 0), "Tcp") == 0) {
175
- l++;
176
-
177
- if(strcmp(procfile_lineword(ff, l, 0), "Tcp") != 0) {
178
- error("Cannot read Tcp line from /proc/net/snmp.");
179
- break;
180
- }
181
-
182
- words = procfile_linewords(ff, l);
183
- if(words < 15) {
184
- error("Cannot read /proc/net/snmp Tcp line. Expected 15 params, read %u.", words);
185
- continue;
186
- }
187
-
188
- unsigned long long RtoAlgorithm, RtoMin, RtoMax, MaxConn, ActiveOpens, PassiveOpens, AttemptFails, EstabResets,
189
- CurrEstab, InSegs, OutSegs, RetransSegs, InErrs, OutRsts;
190
-
191
- RtoAlgorithm = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
192
- RtoMin = strtoull(procfile_lineword(ff, l, 2), NULL, 10);
193
- RtoMax = strtoull(procfile_lineword(ff, l, 3), NULL, 10);
194
- MaxConn = strtoull(procfile_lineword(ff, l, 4), NULL, 10);
195
- ActiveOpens = strtoull(procfile_lineword(ff, l, 5), NULL, 10);
196
- PassiveOpens = strtoull(procfile_lineword(ff, l, 6), NULL, 10);
197
- AttemptFails = strtoull(procfile_lineword(ff, l, 7), NULL, 10);
198
- EstabResets = strtoull(procfile_lineword(ff, l, 8), NULL, 10);
199
- CurrEstab = strtoull(procfile_lineword(ff, l, 9), NULL, 10);
200
- InSegs = strtoull(procfile_lineword(ff, l, 10), NULL, 10);
201
- OutSegs = strtoull(procfile_lineword(ff, l, 11), NULL, 10);
202
- RetransSegs = strtoull(procfile_lineword(ff, l, 12), NULL, 10);
203
- InErrs = strtoull(procfile_lineword(ff, l, 13), NULL, 10);
204
- OutRsts = strtoull(procfile_lineword(ff, l, 14), NULL, 10);
205
-
206
- // these are not counters
207
- if(RtoAlgorithm) {};
208
- if(RtoMin) {};
209
- if(RtoMax) {};
210
- if(MaxConn) {};
211
-
212
- // --------------------------------------------------------------------
213
-
214
- // see http://net-snmp.sourceforge.net/docs/mibs/tcp.html
215
- if(do_tcp_sockets) {
216
- st = rrdset_find(RRD_TYPE_NET_SNMP ".tcpsock");
217
- if(!st) {
218
- st = rrdset_create(RRD_TYPE_NET_SNMP, "tcpsock", NULL, "tcp", NULL, "IPv4 TCP Connections", "active connections", 2500, update_every, RRDSET_TYPE_LINE);
219
-
220
- rrddim_add(st, "connections", NULL, 1, 1, RRDDIM_ABSOLUTE);
221
- }
222
- else rrdset_next(st);
223
-
224
- rrddim_set(st, "connections", CurrEstab);
225
- rrdset_done(st);
226
- }
227
-
228
- // --------------------------------------------------------------------
229
-
230
- if(do_tcp_packets) {
231
- st = rrdset_find(RRD_TYPE_NET_SNMP ".tcppackets");
232
- if(!st) {
233
- st = rrdset_create(RRD_TYPE_NET_SNMP, "tcppackets", NULL, "tcp", NULL, "IPv4 TCP Packets", "packets/s", 2600, update_every, RRDSET_TYPE_LINE);
234
-
235
- rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
236
- rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
237
- }
238
- else rrdset_next(st);
239
-
240
- rrddim_set(st, "received", InSegs);
241
- rrddim_set(st, "sent", OutSegs);
242
- rrdset_done(st);
243
- }
244
-
245
- // --------------------------------------------------------------------
246
-
247
- if(do_tcp_errors) {
248
- st = rrdset_find(RRD_TYPE_NET_SNMP ".tcperrors");
249
- if(!st) {
250
- st = rrdset_create(RRD_TYPE_NET_SNMP, "tcperrors", NULL, "tcp", NULL, "IPv4 TCP Errors", "packets/s", 2700, update_every, RRDSET_TYPE_LINE);
251
- st->isdetail = 1;
252
-
253
- rrddim_add(st, "InErrs", NULL, 1, 1, RRDDIM_INCREMENTAL);
254
- rrddim_add(st, "RetransSegs", NULL, -1, 1, RRDDIM_INCREMENTAL);
255
- }
256
- else rrdset_next(st);
257
-
258
- rrddim_set(st, "InErrs", InErrs);
259
- rrddim_set(st, "RetransSegs", RetransSegs);
260
- rrdset_done(st);
261
- }
262
-
263
- // --------------------------------------------------------------------
264
-
265
- if(do_tcp_handshake) {
266
- st = rrdset_find(RRD_TYPE_NET_SNMP ".tcphandshake");
267
- if(!st) {
268
- st = rrdset_create(RRD_TYPE_NET_SNMP, "tcphandshake", NULL, "tcp", NULL, "IPv4 TCP Handshake Issues", "events/s", 2900, update_every, RRDSET_TYPE_LINE);
269
- st->isdetail = 1;
270
-
271
- rrddim_add(st, "EstabResets", NULL, 1, 1, RRDDIM_INCREMENTAL);
272
- rrddim_add(st, "OutRsts", NULL, -1, 1, RRDDIM_INCREMENTAL);
273
- rrddim_add(st, "ActiveOpens", NULL, 1, 1, RRDDIM_INCREMENTAL);
274
- rrddim_add(st, "PassiveOpens", NULL, 1, 1, RRDDIM_INCREMENTAL);
275
- rrddim_add(st, "AttemptFails", NULL, 1, 1, RRDDIM_INCREMENTAL);
276
- }
277
- else rrdset_next(st);
278
-
279
- rrddim_set(st, "EstabResets", EstabResets);
280
- rrddim_set(st, "OutRsts", OutRsts);
281
- rrddim_set(st, "ActiveOpens", ActiveOpens);
282
- rrddim_set(st, "PassiveOpens", PassiveOpens);
283
- rrddim_set(st, "AttemptFails", AttemptFails);
284
- rrdset_done(st);
285
- }
286
- }
287
- else if(strcmp(procfile_lineword(ff, l, 0), "Udp") == 0) {
288
- l++;
289
-
290
- if(strcmp(procfile_lineword(ff, l, 0), "Udp") != 0) {
291
- error("Cannot read Udp line from /proc/net/snmp.");
292
- break;
293
- }
294
-
295
- words = procfile_linewords(ff, l);
296
- if(words < 7) {
297
- error("Cannot read /proc/net/snmp Udp line. Expected 7 params, read %u.", words);
298
- continue;
299
- }
300
-
301
- unsigned long long InDatagrams, NoPorts, InErrors, OutDatagrams, RcvbufErrors, SndbufErrors;
302
-
303
- InDatagrams = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
304
- NoPorts = strtoull(procfile_lineword(ff, l, 2), NULL, 10);
305
- InErrors = strtoull(procfile_lineword(ff, l, 3), NULL, 10);
306
- OutDatagrams = strtoull(procfile_lineword(ff, l, 4), NULL, 10);
307
- RcvbufErrors = strtoull(procfile_lineword(ff, l, 5), NULL, 10);
308
- SndbufErrors = strtoull(procfile_lineword(ff, l, 6), NULL, 10);
309
-
310
- // --------------------------------------------------------------------
311
-
312
- // see http://net-snmp.sourceforge.net/docs/mibs/udp.html
313
- if(do_udp_packets) {
314
- st = rrdset_find(RRD_TYPE_NET_SNMP ".udppackets");
315
- if(!st) {
316
- st = rrdset_create(RRD_TYPE_NET_SNMP, "udppackets", NULL, "udp", NULL, "IPv4 UDP Packets", "packets/s", 2601, update_every, RRDSET_TYPE_LINE);
317
-
318
- rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
319
- rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
320
- }
321
- else rrdset_next(st);
322
-
323
- rrddim_set(st, "received", InDatagrams);
324
- rrddim_set(st, "sent", OutDatagrams);
325
- rrdset_done(st);
326
- }
327
-
328
- // --------------------------------------------------------------------
329
-
330
- if(do_udp_errors) {
331
- st = rrdset_find(RRD_TYPE_NET_SNMP ".udperrors");
332
- if(!st) {
333
- st = rrdset_create(RRD_TYPE_NET_SNMP, "udperrors", NULL, "udp", NULL, "IPv4 UDP Errors", "events/s", 2701, update_every, RRDSET_TYPE_LINE);
334
- st->isdetail = 1;
335
-
336
- rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
337
- rrddim_add(st, "SndbufErrors", NULL, -1, 1, RRDDIM_INCREMENTAL);
338
- rrddim_add(st, "InErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
339
- rrddim_add(st, "NoPorts", NULL, 1, 1, RRDDIM_INCREMENTAL);
340
- }
341
- else rrdset_next(st);
342
-
343
- rrddim_set(st, "InErrors", InErrors);
344
- rrddim_set(st, "NoPorts", NoPorts);
345
- rrddim_set(st, "RcvbufErrors", RcvbufErrors);
346
- rrddim_set(st, "SndbufErrors", SndbufErrors);
347
- rrdset_done(st);
348
- }
349
- }
350
- }
351
-
352
- return 0;
7
+ static procfile *ff = NULL;
8
+ static int do_ip_packets = -1, do_ip_fragsout = -1, do_ip_fragsin = -1, do_ip_errors = -1,
9
+ do_tcp_sockets = -1, do_tcp_packets = -1, do_tcp_errors = -1, do_tcp_handshake = -1,
10
+ do_udp_packets = -1, do_udp_errors = -1;
11
+
12
+ if(do_ip_packets == -1) do_ip_packets = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 packets", 1);
13
+ if(do_ip_fragsout == -1) do_ip_fragsout = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 fragments sent", 1);
14
+ if(do_ip_fragsin == -1) do_ip_fragsin = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 fragments assembly", 1);
15
+ if(do_ip_errors == -1) do_ip_errors = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 errors", 1);
16
+ if(do_tcp_sockets == -1) do_tcp_sockets = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 TCP connections", 1);
17
+ if(do_tcp_packets == -1) do_tcp_packets = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 TCP packets", 1);
18
+ if(do_tcp_errors == -1) do_tcp_errors = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 TCP errors", 1);
19
+ if(do_tcp_handshake == -1) do_tcp_handshake = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 TCP handshake issues", 1);
20
+ if(do_udp_packets == -1) do_udp_packets = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 UDP packets", 1);
21
+ if(do_udp_errors == -1) do_udp_errors = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 UDP errors", 1);
22
+
23
+ if(dt) {};
24
+
25
+ if(!ff) {
26
+ char filename[FILENAME_MAX + 1];
27
+ snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/snmp");
28
+ ff = procfile_open(config_get("plugin:proc:/proc/net/snmp", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
29
+ }
30
+ if(!ff) return 1;
31
+
32
+ ff = procfile_readall(ff);
33
+ if(!ff) return 0; // we return 0, so that we will retry to open it next time
34
+
35
+ uint32_t lines = procfile_lines(ff), l;
36
+ uint32_t words;
37
+
38
+ RRDSET *st;
39
+
40
+ for(l = 0; l < lines ;l++) {
41
+ if(strcmp(procfile_lineword(ff, l, 0), "Ip") == 0) {
42
+ l++;
43
+
44
+ if(strcmp(procfile_lineword(ff, l, 0), "Ip") != 0) {
45
+ error("Cannot read Ip line from /proc/net/snmp.");
46
+ break;
47
+ }
48
+
49
+ words = procfile_linewords(ff, l);
50
+ if(words < 20) {
51
+ error("Cannot read /proc/net/snmp Ip line. Expected 20 params, read %u.", words);
52
+ continue;
53
+ }
54
+
55
+ // see also http://net-snmp.sourceforge.net/docs/mibs/ip.html
56
+ unsigned long long Forwarding, DefaultTTL, InReceives, InHdrErrors, InAddrErrors, ForwDatagrams, InUnknownProtos, InDiscards, InDelivers,
57
+ OutRequests, OutDiscards, OutNoRoutes, ReasmTimeout, ReasmReqds, ReasmOKs, ReasmFails, FragOKs, FragFails, FragCreates;
58
+
59
+ Forwarding = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
60
+ DefaultTTL = strtoull(procfile_lineword(ff, l, 2), NULL, 10);
61
+ InReceives = strtoull(procfile_lineword(ff, l, 3), NULL, 10);
62
+ InHdrErrors = strtoull(procfile_lineword(ff, l, 4), NULL, 10);
63
+ InAddrErrors = strtoull(procfile_lineword(ff, l, 5), NULL, 10);
64
+ ForwDatagrams = strtoull(procfile_lineword(ff, l, 6), NULL, 10);
65
+ InUnknownProtos = strtoull(procfile_lineword(ff, l, 7), NULL, 10);
66
+ InDiscards = strtoull(procfile_lineword(ff, l, 8), NULL, 10);
67
+ InDelivers = strtoull(procfile_lineword(ff, l, 9), NULL, 10);
68
+ OutRequests = strtoull(procfile_lineword(ff, l, 10), NULL, 10);
69
+ OutDiscards = strtoull(procfile_lineword(ff, l, 11), NULL, 10);
70
+ OutNoRoutes = strtoull(procfile_lineword(ff, l, 12), NULL, 10);
71
+ ReasmTimeout = strtoull(procfile_lineword(ff, l, 13), NULL, 10);
72
+ ReasmReqds = strtoull(procfile_lineword(ff, l, 14), NULL, 10);
73
+ ReasmOKs = strtoull(procfile_lineword(ff, l, 15), NULL, 10);
74
+ ReasmFails = strtoull(procfile_lineword(ff, l, 16), NULL, 10);
75
+ FragOKs = strtoull(procfile_lineword(ff, l, 17), NULL, 10);
76
+ FragFails = strtoull(procfile_lineword(ff, l, 18), NULL, 10);
77
+ FragCreates = strtoull(procfile_lineword(ff, l, 19), NULL, 10);
78
+
79
+ // these are not counters
80
+ if(Forwarding) {}; // is forwarding enabled?
81
+ if(DefaultTTL) {}; // the default ttl on packets
82
+ if(ReasmTimeout) {}; // Reassembly timeout
83
+
84
+ // this counter is not used
85
+ if(InDelivers) {}; // total number of packets delivered to IP user-protocols
86
+
87
+ // --------------------------------------------------------------------
88
+
89
+ if(do_ip_packets) {
90
+ st = rrdset_find(RRD_TYPE_NET_SNMP ".packets");
91
+ if(!st) {
92
+ st = rrdset_create(RRD_TYPE_NET_SNMP, "packets", NULL, "packets", NULL, "IPv4 Packets", "packets/s", 3000, update_every, RRDSET_TYPE_LINE);
93
+
94
+ rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
95
+ rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
96
+ rrddim_add(st, "forwarded", NULL, 1, 1, RRDDIM_INCREMENTAL);
97
+ }
98
+ else rrdset_next(st);
99
+
100
+ rrddim_set(st, "sent", OutRequests);
101
+ rrddim_set(st, "received", InReceives);
102
+ rrddim_set(st, "forwarded", ForwDatagrams);
103
+ rrdset_done(st);
104
+ }
105
+
106
+ // --------------------------------------------------------------------
107
+
108
+ if(do_ip_fragsout) {
109
+ st = rrdset_find(RRD_TYPE_NET_SNMP ".fragsout");
110
+ if(!st) {
111
+ st = rrdset_create(RRD_TYPE_NET_SNMP, "fragsout", NULL, "fragments", NULL, "IPv4 Fragments Sent", "packets/s", 3010, update_every, RRDSET_TYPE_LINE);
112
+ st->isdetail = 1;
113
+
114
+ rrddim_add(st, "ok", NULL, 1, 1, RRDDIM_INCREMENTAL);
115
+ rrddim_add(st, "failed", NULL, -1, 1, RRDDIM_INCREMENTAL);
116
+ rrddim_add(st, "all", NULL, 1, 1, RRDDIM_INCREMENTAL);
117
+ }
118
+ else rrdset_next(st);
119
+
120
+ rrddim_set(st, "ok", FragOKs);
121
+ rrddim_set(st, "failed", FragFails);
122
+ rrddim_set(st, "all", FragCreates);
123
+ rrdset_done(st);
124
+ }
125
+
126
+ // --------------------------------------------------------------------
127
+
128
+ if(do_ip_fragsin) {
129
+ st = rrdset_find(RRD_TYPE_NET_SNMP ".fragsin");
130
+ if(!st) {
131
+ st = rrdset_create(RRD_TYPE_NET_SNMP, "fragsin", NULL, "fragments", NULL, "IPv4 Fragments Reassembly", "packets/s", 3011, update_every, RRDSET_TYPE_LINE);
132
+ st->isdetail = 1;
133
+
134
+ rrddim_add(st, "ok", NULL, 1, 1, RRDDIM_INCREMENTAL);
135
+ rrddim_add(st, "failed", NULL, -1, 1, RRDDIM_INCREMENTAL);
136
+ rrddim_add(st, "all", NULL, 1, 1, RRDDIM_INCREMENTAL);
137
+ }
138
+ else rrdset_next(st);
139
+
140
+ rrddim_set(st, "ok", ReasmOKs);
141
+ rrddim_set(st, "failed", ReasmFails);
142
+ rrddim_set(st, "all", ReasmReqds);
143
+ rrdset_done(st);
144
+ }
145
+
146
+ // --------------------------------------------------------------------
147
+
148
+ if(do_ip_errors) {
149
+ st = rrdset_find(RRD_TYPE_NET_SNMP ".errors");
150
+ if(!st) {
151
+ st = rrdset_create(RRD_TYPE_NET_SNMP, "errors", NULL, "errors", NULL, "IPv4 Errors", "packets/s", 3002, update_every, RRDSET_TYPE_LINE);
152
+ st->isdetail = 1;
153
+
154
+ rrddim_add(st, "InDiscards", NULL, 1, 1, RRDDIM_INCREMENTAL);
155
+ rrddim_add(st, "OutDiscards", NULL, -1, 1, RRDDIM_INCREMENTAL);
156
+
157
+ rrddim_add(st, "InHdrErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
158
+ rrddim_add(st, "InAddrErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
159
+ rrddim_add(st, "InUnknownProtos", NULL, 1, 1, RRDDIM_INCREMENTAL);
160
+
161
+ rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRDDIM_INCREMENTAL);
162
+ }
163
+ else rrdset_next(st);
164
+
165
+ rrddim_set(st, "InDiscards", InDiscards);
166
+ rrddim_set(st, "OutDiscards", OutDiscards);
167
+ rrddim_set(st, "InHdrErrors", InHdrErrors);
168
+ rrddim_set(st, "InAddrErrors", InAddrErrors);
169
+ rrddim_set(st, "InUnknownProtos", InUnknownProtos);
170
+ rrddim_set(st, "OutNoRoutes", OutNoRoutes);
171
+ rrdset_done(st);
172
+ }
173
+ }
174
+ else if(strcmp(procfile_lineword(ff, l, 0), "Tcp") == 0) {
175
+ l++;
176
+
177
+ if(strcmp(procfile_lineword(ff, l, 0), "Tcp") != 0) {
178
+ error("Cannot read Tcp line from /proc/net/snmp.");
179
+ break;
180
+ }
181
+
182
+ words = procfile_linewords(ff, l);
183
+ if(words < 15) {
184
+ error("Cannot read /proc/net/snmp Tcp line. Expected 15 params, read %u.", words);
185
+ continue;
186
+ }
187
+
188
+ unsigned long long RtoAlgorithm, RtoMin, RtoMax, MaxConn, ActiveOpens, PassiveOpens, AttemptFails, EstabResets,
189
+ CurrEstab, InSegs, OutSegs, RetransSegs, InErrs, OutRsts;
190
+
191
+ RtoAlgorithm = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
192
+ RtoMin = strtoull(procfile_lineword(ff, l, 2), NULL, 10);
193
+ RtoMax = strtoull(procfile_lineword(ff, l, 3), NULL, 10);
194
+ MaxConn = strtoull(procfile_lineword(ff, l, 4), NULL, 10);
195
+ ActiveOpens = strtoull(procfile_lineword(ff, l, 5), NULL, 10);
196
+ PassiveOpens = strtoull(procfile_lineword(ff, l, 6), NULL, 10);
197
+ AttemptFails = strtoull(procfile_lineword(ff, l, 7), NULL, 10);
198
+ EstabResets = strtoull(procfile_lineword(ff, l, 8), NULL, 10);
199
+ CurrEstab = strtoull(procfile_lineword(ff, l, 9), NULL, 10);
200
+ InSegs = strtoull(procfile_lineword(ff, l, 10), NULL, 10);
201
+ OutSegs = strtoull(procfile_lineword(ff, l, 11), NULL, 10);
202
+ RetransSegs = strtoull(procfile_lineword(ff, l, 12), NULL, 10);
203
+ InErrs = strtoull(procfile_lineword(ff, l, 13), NULL, 10);
204
+ OutRsts = strtoull(procfile_lineword(ff, l, 14), NULL, 10);
205
+
206
+ // these are not counters
207
+ if(RtoAlgorithm) {};
208
+ if(RtoMin) {};
209
+ if(RtoMax) {};
210
+ if(MaxConn) {};
211
+
212
+ // --------------------------------------------------------------------
213
+
214
+ // see http://net-snmp.sourceforge.net/docs/mibs/tcp.html
215
+ if(do_tcp_sockets) {
216
+ st = rrdset_find(RRD_TYPE_NET_SNMP ".tcpsock");
217
+ if(!st) {
218
+ st = rrdset_create(RRD_TYPE_NET_SNMP, "tcpsock", NULL, "tcp", NULL, "IPv4 TCP Connections", "active connections", 2500, update_every, RRDSET_TYPE_LINE);
219
+
220
+ rrddim_add(st, "connections", NULL, 1, 1, RRDDIM_ABSOLUTE);
221
+ }
222
+ else rrdset_next(st);
223
+
224
+ rrddim_set(st, "connections", CurrEstab);
225
+ rrdset_done(st);
226
+ }
227
+
228
+ // --------------------------------------------------------------------
229
+
230
+ if(do_tcp_packets) {
231
+ st = rrdset_find(RRD_TYPE_NET_SNMP ".tcppackets");
232
+ if(!st) {
233
+ st = rrdset_create(RRD_TYPE_NET_SNMP, "tcppackets", NULL, "tcp", NULL, "IPv4 TCP Packets", "packets/s", 2600, update_every, RRDSET_TYPE_LINE);
234
+
235
+ rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
236
+ rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
237
+ }
238
+ else rrdset_next(st);
239
+
240
+ rrddim_set(st, "received", InSegs);
241
+ rrddim_set(st, "sent", OutSegs);
242
+ rrdset_done(st);
243
+ }
244
+
245
+ // --------------------------------------------------------------------
246
+
247
+ if(do_tcp_errors) {
248
+ st = rrdset_find(RRD_TYPE_NET_SNMP ".tcperrors");
249
+ if(!st) {
250
+ st = rrdset_create(RRD_TYPE_NET_SNMP, "tcperrors", NULL, "tcp", NULL, "IPv4 TCP Errors", "packets/s", 2700, update_every, RRDSET_TYPE_LINE);
251
+ st->isdetail = 1;
252
+
253
+ rrddim_add(st, "InErrs", NULL, 1, 1, RRDDIM_INCREMENTAL);
254
+ rrddim_add(st, "RetransSegs", NULL, -1, 1, RRDDIM_INCREMENTAL);
255
+ }
256
+ else rrdset_next(st);
257
+
258
+ rrddim_set(st, "InErrs", InErrs);
259
+ rrddim_set(st, "RetransSegs", RetransSegs);
260
+ rrdset_done(st);
261
+ }
262
+
263
+ // --------------------------------------------------------------------
264
+
265
+ if(do_tcp_handshake) {
266
+ st = rrdset_find(RRD_TYPE_NET_SNMP ".tcphandshake");
267
+ if(!st) {
268
+ st = rrdset_create(RRD_TYPE_NET_SNMP, "tcphandshake", NULL, "tcp", NULL, "IPv4 TCP Handshake Issues", "events/s", 2900, update_every, RRDSET_TYPE_LINE);
269
+ st->isdetail = 1;
270
+
271
+ rrddim_add(st, "EstabResets", NULL, 1, 1, RRDDIM_INCREMENTAL);
272
+ rrddim_add(st, "OutRsts", NULL, -1, 1, RRDDIM_INCREMENTAL);
273
+ rrddim_add(st, "ActiveOpens", NULL, 1, 1, RRDDIM_INCREMENTAL);
274
+ rrddim_add(st, "PassiveOpens", NULL, 1, 1, RRDDIM_INCREMENTAL);
275
+ rrddim_add(st, "AttemptFails", NULL, 1, 1, RRDDIM_INCREMENTAL);
276
+ }
277
+ else rrdset_next(st);
278
+
279
+ rrddim_set(st, "EstabResets", EstabResets);
280
+ rrddim_set(st, "OutRsts", OutRsts);
281
+ rrddim_set(st, "ActiveOpens", ActiveOpens);
282
+ rrddim_set(st, "PassiveOpens", PassiveOpens);
283
+ rrddim_set(st, "AttemptFails", AttemptFails);
284
+ rrdset_done(st);
285
+ }
286
+ }
287
+ else if(strcmp(procfile_lineword(ff, l, 0), "Udp") == 0) {
288
+ l++;
289
+
290
+ if(strcmp(procfile_lineword(ff, l, 0), "Udp") != 0) {
291
+ error("Cannot read Udp line from /proc/net/snmp.");
292
+ break;
293
+ }
294
+
295
+ words = procfile_linewords(ff, l);
296
+ if(words < 7) {
297
+ error("Cannot read /proc/net/snmp Udp line. Expected 7 params, read %u.", words);
298
+ continue;
299
+ }
300
+
301
+ unsigned long long InDatagrams, NoPorts, InErrors, OutDatagrams, RcvbufErrors, SndbufErrors;
302
+
303
+ InDatagrams = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
304
+ NoPorts = strtoull(procfile_lineword(ff, l, 2), NULL, 10);
305
+ InErrors = strtoull(procfile_lineword(ff, l, 3), NULL, 10);
306
+ OutDatagrams = strtoull(procfile_lineword(ff, l, 4), NULL, 10);
307
+ RcvbufErrors = strtoull(procfile_lineword(ff, l, 5), NULL, 10);
308
+ SndbufErrors = strtoull(procfile_lineword(ff, l, 6), NULL, 10);
309
+
310
+ // --------------------------------------------------------------------
311
+
312
+ // see http://net-snmp.sourceforge.net/docs/mibs/udp.html
313
+ if(do_udp_packets) {
314
+ st = rrdset_find(RRD_TYPE_NET_SNMP ".udppackets");
315
+ if(!st) {
316
+ st = rrdset_create(RRD_TYPE_NET_SNMP, "udppackets", NULL, "udp", NULL, "IPv4 UDP Packets", "packets/s", 2601, update_every, RRDSET_TYPE_LINE);
317
+
318
+ rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
319
+ rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
320
+ }
321
+ else rrdset_next(st);
322
+
323
+ rrddim_set(st, "received", InDatagrams);
324
+ rrddim_set(st, "sent", OutDatagrams);
325
+ rrdset_done(st);
326
+ }
327
+
328
+ // --------------------------------------------------------------------
329
+
330
+ if(do_udp_errors) {
331
+ st = rrdset_find(RRD_TYPE_NET_SNMP ".udperrors");
332
+ if(!st) {
333
+ st = rrdset_create(RRD_TYPE_NET_SNMP, "udperrors", NULL, "udp", NULL, "IPv4 UDP Errors", "events/s", 2701, update_every, RRDSET_TYPE_LINE);
334
+ st->isdetail = 1;
335
+
336
+ rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
337
+ rrddim_add(st, "SndbufErrors", NULL, -1, 1, RRDDIM_INCREMENTAL);
338
+ rrddim_add(st, "InErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
339
+ rrddim_add(st, "NoPorts", NULL, 1, 1, RRDDIM_INCREMENTAL);
340
+ }
341
+ else rrdset_next(st);
342
+
343
+ rrddim_set(st, "InErrors", InErrors);
344
+ rrddim_set(st, "NoPorts", NoPorts);
345
+ rrddim_set(st, "RcvbufErrors", RcvbufErrors);
346
+ rrddim_set(st, "SndbufErrors", SndbufErrors);
347
+ rrdset_done(st);
348
+ }
349
+ }
350
+ }
351
+
352
+ return 0;
353
}
354
src/proc_net_snmp6.c
+1048
-1048
@@ -1,1054 +1,1054 @@
1
#include "common.h"
2
3
-#define RRD_TYPE_NET_SNMP6 "ipv6"
4
-#define RRD_TYPE_NET_SNMP6_LEN strlen(RRD_TYPE_NET_SNMP6)
3
+#define RRD_TYPE_NET_SNMP6 "ipv6"
4
+#define RRD_TYPE_NET_SNMP6_LEN strlen(RRD_TYPE_NET_SNMP6)
5
6
int do_proc_net_snmp6(int update_every, unsigned long long dt) {
7
- static procfile *ff = NULL;
8
- static int gen_hashes = -1;
9
-
10
- static int do_ip_packets = -1, do_ip_fragsout = -1, do_ip_fragsin = -1, do_ip_errors = -1,
11
- do_udplite_packets = -1, do_udplite_errors = -1,
12
- do_udp_packets = -1, do_udp_errors = -1,
13
- do_bandwidth = -1, do_mcast = -1, do_bcast = -1, do_mcast_p = -1,
14
- do_icmp = -1, do_icmp_redir = -1, do_icmp_errors = -1, do_icmp_echos = -1, do_icmp_groupmemb = -1,
15
- do_icmp_router = -1, do_icmp_neighbor = -1, do_icmp_mldv2 = -1, do_icmp_types = -1, do_ect = -1;
16
-
17
- static uint32_t hash_Ip6InReceives = -1;
18
-
19
- static uint32_t hash_Ip6InHdrErrors = -1;
20
- static uint32_t hash_Ip6InTooBigErrors = -1;
21
- static uint32_t hash_Ip6InNoRoutes = -1;
22
- static uint32_t hash_Ip6InAddrErrors = -1;
23
- static uint32_t hash_Ip6InUnknownProtos = -1;
24
- static uint32_t hash_Ip6InTruncatedPkts = -1;
25
- static uint32_t hash_Ip6InDiscards = -1;
26
- static uint32_t hash_Ip6InDelivers = -1;
27
-
28
- static uint32_t hash_Ip6OutForwDatagrams = -1;
29
- static uint32_t hash_Ip6OutRequests = -1;
30
- static uint32_t hash_Ip6OutDiscards = -1;
31
- static uint32_t hash_Ip6OutNoRoutes = -1;
32
-
33
- static uint32_t hash_Ip6ReasmTimeout = -1;
34
- static uint32_t hash_Ip6ReasmReqds = -1;
35
- static uint32_t hash_Ip6ReasmOKs = -1;
36
- static uint32_t hash_Ip6ReasmFails = -1;
37
-
38
- static uint32_t hash_Ip6FragOKs = -1;
39
- static uint32_t hash_Ip6FragFails = -1;
40
- static uint32_t hash_Ip6FragCreates = -1;
41
-
42
- static uint32_t hash_Ip6InMcastPkts = -1;
43
- static uint32_t hash_Ip6OutMcastPkts = -1;
44
-
45
- static uint32_t hash_Ip6InOctets = -1;
46
- static uint32_t hash_Ip6OutOctets = -1;
47
-
48
- static uint32_t hash_Ip6InMcastOctets = -1;
49
- static uint32_t hash_Ip6OutMcastOctets = -1;
50
- static uint32_t hash_Ip6InBcastOctets = -1;
51
- static uint32_t hash_Ip6OutBcastOctets = -1;
52
-
53
- static uint32_t hash_Ip6InNoECTPkts = -1;
54
- static uint32_t hash_Ip6InECT1Pkts = -1;
55
- static uint32_t hash_Ip6InECT0Pkts = -1;
56
- static uint32_t hash_Ip6InCEPkts = -1;
57
-
58
- static uint32_t hash_Icmp6InMsgs = -1;
59
- static uint32_t hash_Icmp6InErrors = -1;
60
- static uint32_t hash_Icmp6OutMsgs = -1;
61
- static uint32_t hash_Icmp6OutErrors = -1;
62
- static uint32_t hash_Icmp6InCsumErrors = -1;
63
- static uint32_t hash_Icmp6InDestUnreachs = -1;
64
- static uint32_t hash_Icmp6InPktTooBigs = -1;
65
- static uint32_t hash_Icmp6InTimeExcds = -1;
66
- static uint32_t hash_Icmp6InParmProblems = -1;
67
- static uint32_t hash_Icmp6InEchos = -1;
68
- static uint32_t hash_Icmp6InEchoReplies = -1;
69
- static uint32_t hash_Icmp6InGroupMembQueries = -1;
70
- static uint32_t hash_Icmp6InGroupMembResponses = -1;
71
- static uint32_t hash_Icmp6InGroupMembReductions = -1;
72
- static uint32_t hash_Icmp6InRouterSolicits = -1;
73
- static uint32_t hash_Icmp6InRouterAdvertisements = -1;
74
- static uint32_t hash_Icmp6InNeighborSolicits = -1;
75
- static uint32_t hash_Icmp6InNeighborAdvertisements = -1;
76
- static uint32_t hash_Icmp6InRedirects = -1;
77
- static uint32_t hash_Icmp6InMLDv2Reports = -1;
78
- static uint32_t hash_Icmp6OutDestUnreachs = -1;
79
- static uint32_t hash_Icmp6OutPktTooBigs = -1;
80
- static uint32_t hash_Icmp6OutTimeExcds = -1;
81
- static uint32_t hash_Icmp6OutParmProblems = -1;
82
- static uint32_t hash_Icmp6OutEchos = -1;
83
- static uint32_t hash_Icmp6OutEchoReplies = -1;
84
- static uint32_t hash_Icmp6OutGroupMembQueries = -1;
85
- static uint32_t hash_Icmp6OutGroupMembResponses = -1;
86
- static uint32_t hash_Icmp6OutGroupMembReductions = -1;
87
- static uint32_t hash_Icmp6OutRouterSolicits = -1;
88
- static uint32_t hash_Icmp6OutRouterAdvertisements = -1;
89
- static uint32_t hash_Icmp6OutNeighborSolicits = -1;
90
- static uint32_t hash_Icmp6OutNeighborAdvertisements = -1;
91
- static uint32_t hash_Icmp6OutRedirects = -1;
92
- static uint32_t hash_Icmp6OutMLDv2Reports = -1;
93
- static uint32_t hash_Icmp6InType1 = -1;
94
- static uint32_t hash_Icmp6InType128 = -1;
95
- static uint32_t hash_Icmp6InType129 = -1;
96
- static uint32_t hash_Icmp6InType136 = -1;
97
- static uint32_t hash_Icmp6OutType1 = -1;
98
- static uint32_t hash_Icmp6OutType128 = -1;
99
- static uint32_t hash_Icmp6OutType129 = -1;
100
- static uint32_t hash_Icmp6OutType133 = -1;
101
- static uint32_t hash_Icmp6OutType135 = -1;
102
- static uint32_t hash_Icmp6OutType143 = -1;
103
-
104
- static uint32_t hash_Udp6InDatagrams = -1;
105
- static uint32_t hash_Udp6NoPorts = -1;
106
- static uint32_t hash_Udp6InErrors = -1;
107
- static uint32_t hash_Udp6OutDatagrams = -1;
108
- static uint32_t hash_Udp6RcvbufErrors = -1;
109
- static uint32_t hash_Udp6SndbufErrors = -1;
110
- static uint32_t hash_Udp6InCsumErrors = -1;
111
- static uint32_t hash_Udp6IgnoredMulti = -1;
112
-
113
- static uint32_t hash_UdpLite6InDatagrams = -1;
114
- static uint32_t hash_UdpLite6NoPorts = -1;
115
- static uint32_t hash_UdpLite6InErrors = -1;
116
- static uint32_t hash_UdpLite6OutDatagrams = -1;
117
- static uint32_t hash_UdpLite6RcvbufErrors = -1;
118
- static uint32_t hash_UdpLite6SndbufErrors = -1;
119
- static uint32_t hash_UdpLite6InCsumErrors = -1;
120
-
121
- if(gen_hashes != 1) {
122
- gen_hashes = 1;
123
- hash_Ip6InReceives = simple_hash("Ip6InReceives");
124
- hash_Ip6InHdrErrors = simple_hash("Ip6InHdrErrors");
125
- hash_Ip6InTooBigErrors = simple_hash("Ip6InTooBigErrors");
126
- hash_Ip6InNoRoutes = simple_hash("Ip6InNoRoutes");
127
- hash_Ip6InAddrErrors = simple_hash("Ip6InAddrErrors");
128
- hash_Ip6InUnknownProtos = simple_hash("Ip6InUnknownProtos");
129
- hash_Ip6InTruncatedPkts = simple_hash("Ip6InTruncatedPkts");
130
- hash_Ip6InDiscards = simple_hash("Ip6InDiscards");
131
- hash_Ip6InDelivers = simple_hash("Ip6InDelivers");
132
- hash_Ip6OutForwDatagrams = simple_hash("Ip6OutForwDatagrams");
133
- hash_Ip6OutRequests = simple_hash("Ip6OutRequests");
134
- hash_Ip6OutDiscards = simple_hash("Ip6OutDiscards");
135
- hash_Ip6OutNoRoutes = simple_hash("Ip6OutNoRoutes");
136
- hash_Ip6ReasmTimeout = simple_hash("Ip6ReasmTimeout");
137
- hash_Ip6ReasmReqds = simple_hash("Ip6ReasmReqds");
138
- hash_Ip6ReasmOKs = simple_hash("Ip6ReasmOKs");
139
- hash_Ip6ReasmFails = simple_hash("Ip6ReasmFails");
140
- hash_Ip6FragOKs = simple_hash("Ip6FragOKs");
141
- hash_Ip6FragFails = simple_hash("Ip6FragFails");
142
- hash_Ip6FragCreates = simple_hash("Ip6FragCreates");
143
- hash_Ip6InMcastPkts = simple_hash("Ip6InMcastPkts");
144
- hash_Ip6OutMcastPkts = simple_hash("Ip6OutMcastPkts");
145
- hash_Ip6InOctets = simple_hash("Ip6InOctets");
146
- hash_Ip6OutOctets = simple_hash("Ip6OutOctets");
147
- hash_Ip6InMcastOctets = simple_hash("Ip6InMcastOctets");
148
- hash_Ip6OutMcastOctets = simple_hash("Ip6OutMcastOctets");
149
- hash_Ip6InBcastOctets = simple_hash("Ip6InBcastOctets");
150
- hash_Ip6OutBcastOctets = simple_hash("Ip6OutBcastOctets");
151
- hash_Ip6InNoECTPkts = simple_hash("Ip6InNoECTPkts");
152
- hash_Ip6InECT1Pkts = simple_hash("Ip6InECT1Pkts");
153
- hash_Ip6InECT0Pkts = simple_hash("Ip6InECT0Pkts");
154
- hash_Ip6InCEPkts = simple_hash("Ip6InCEPkts");
155
- hash_Icmp6InMsgs = simple_hash("Icmp6InMsgs");
156
- hash_Icmp6InErrors = simple_hash("Icmp6InErrors");
157
- hash_Icmp6OutMsgs = simple_hash("Icmp6OutMsgs");
158
- hash_Icmp6OutErrors = simple_hash("Icmp6OutErrors");
159
- hash_Icmp6InCsumErrors = simple_hash("Icmp6InCsumErrors");
160
- hash_Icmp6InDestUnreachs = simple_hash("Icmp6InDestUnreachs");
161
- hash_Icmp6InPktTooBigs = simple_hash("Icmp6InPktTooBigs");
162
- hash_Icmp6InTimeExcds = simple_hash("Icmp6InTimeExcds");
163
- hash_Icmp6InParmProblems = simple_hash("Icmp6InParmProblems");
164
- hash_Icmp6InEchos = simple_hash("Icmp6InEchos");
165
- hash_Icmp6InEchoReplies = simple_hash("Icmp6InEchoReplies");
166
- hash_Icmp6InGroupMembQueries = simple_hash("Icmp6InGroupMembQueries");
167
- hash_Icmp6InGroupMembResponses = simple_hash("Icmp6InGroupMembResponses");
168
- hash_Icmp6InGroupMembReductions = simple_hash("Icmp6InGroupMembReductions");
169
- hash_Icmp6InRouterSolicits = simple_hash("Icmp6InRouterSolicits");
170
- hash_Icmp6InRouterAdvertisements = simple_hash("Icmp6InRouterAdvertisements");
171
- hash_Icmp6InNeighborSolicits = simple_hash("Icmp6InNeighborSolicits");
172
- hash_Icmp6InNeighborAdvertisements = simple_hash("Icmp6InNeighborAdvertisements");
173
- hash_Icmp6InRedirects = simple_hash("Icmp6InRedirects");
174
- hash_Icmp6InMLDv2Reports = simple_hash("Icmp6InMLDv2Reports");
175
- hash_Icmp6OutDestUnreachs = simple_hash("Icmp6OutDestUnreachs");
176
- hash_Icmp6OutPktTooBigs = simple_hash("Icmp6OutPktTooBigs");
177
- hash_Icmp6OutTimeExcds = simple_hash("Icmp6OutTimeExcds");
178
- hash_Icmp6OutParmProblems = simple_hash("Icmp6OutParmProblems");
179
- hash_Icmp6OutEchos = simple_hash("Icmp6OutEchos");
180
- hash_Icmp6OutEchoReplies = simple_hash("Icmp6OutEchoReplies");
181
- hash_Icmp6OutGroupMembQueries = simple_hash("Icmp6OutGroupMembQueries");
182
- hash_Icmp6OutGroupMembResponses = simple_hash("Icmp6OutGroupMembResponses");
183
- hash_Icmp6OutGroupMembReductions = simple_hash("Icmp6OutGroupMembReductions");
184
- hash_Icmp6OutRouterSolicits = simple_hash("Icmp6OutRouterSolicits");
185
- hash_Icmp6OutRouterAdvertisements = simple_hash("Icmp6OutRouterAdvertisements");
186
- hash_Icmp6OutNeighborSolicits = simple_hash("Icmp6OutNeighborSolicits");
187
- hash_Icmp6OutNeighborAdvertisements = simple_hash("Icmp6OutNeighborAdvertisements");
188
- hash_Icmp6OutRedirects = simple_hash("Icmp6OutRedirects");
189
- hash_Icmp6OutMLDv2Reports = simple_hash("Icmp6OutMLDv2Reports");
190
- hash_Icmp6InType1 = simple_hash("Icmp6InType1");
191
- hash_Icmp6InType128 = simple_hash("Icmp6InType128");
192
- hash_Icmp6InType129 = simple_hash("Icmp6InType129");
193
- hash_Icmp6InType136 = simple_hash("Icmp6InType136");
194
- hash_Icmp6OutType1 = simple_hash("Icmp6OutType1");
195
- hash_Icmp6OutType128 = simple_hash("Icmp6OutType128");
196
- hash_Icmp6OutType129 = simple_hash("Icmp6OutType129");
197
- hash_Icmp6OutType133 = simple_hash("Icmp6OutType133");
198
- hash_Icmp6OutType135 = simple_hash("Icmp6OutType135");
199
- hash_Icmp6OutType143 = simple_hash("Icmp6OutType143");
200
- hash_Udp6InDatagrams = simple_hash("Udp6InDatagrams");
201
- hash_Udp6NoPorts = simple_hash("Udp6NoPorts");
202
- hash_Udp6InErrors = simple_hash("Udp6InErrors");
203
- hash_Udp6OutDatagrams = simple_hash("Udp6OutDatagrams");
204
- hash_Udp6RcvbufErrors = simple_hash("Udp6RcvbufErrors");
205
- hash_Udp6SndbufErrors = simple_hash("Udp6SndbufErrors");
206
- hash_Udp6InCsumErrors = simple_hash("Udp6InCsumErrors");
207
- hash_Udp6IgnoredMulti = simple_hash("Udp6IgnoredMulti");
208
- hash_UdpLite6InDatagrams = simple_hash("UdpLite6InDatagrams");
209
- hash_UdpLite6NoPorts = simple_hash("UdpLite6NoPorts");
210
- hash_UdpLite6InErrors = simple_hash("UdpLite6InErrors");
211
- hash_UdpLite6OutDatagrams = simple_hash("UdpLite6OutDatagrams");
212
- hash_UdpLite6RcvbufErrors = simple_hash("UdpLite6RcvbufErrors");
213
- hash_UdpLite6SndbufErrors = simple_hash("UdpLite6SndbufErrors");
214
- hash_UdpLite6InCsumErrors = simple_hash("UdpLite6InCsumErrors");
215
- }
216
-
217
- if(do_ip_packets == -1) do_ip_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 packets", CONFIG_ONDEMAND_ONDEMAND);
218
- if(do_ip_fragsout == -1) do_ip_fragsout = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 fragments sent", CONFIG_ONDEMAND_ONDEMAND);
219
- if(do_ip_fragsin == -1) do_ip_fragsin = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 fragments assembly", CONFIG_ONDEMAND_ONDEMAND);
220
- if(do_ip_errors == -1) do_ip_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 errors", CONFIG_ONDEMAND_ONDEMAND);
221
- if(do_udp_packets == -1) do_udp_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDP packets", CONFIG_ONDEMAND_ONDEMAND);
222
- if(do_udp_errors == -1) do_udp_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDP errors", CONFIG_ONDEMAND_ONDEMAND);
223
- if(do_udplite_packets == -1) do_udplite_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDPlite packets", CONFIG_ONDEMAND_ONDEMAND);
224
- if(do_udplite_errors == -1) do_udplite_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDPlite errors", CONFIG_ONDEMAND_ONDEMAND);
225
- if(do_bandwidth == -1) do_bandwidth = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "bandwidth", CONFIG_ONDEMAND_ONDEMAND);
226
- if(do_mcast == -1) do_mcast = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "multicast bandwidth", CONFIG_ONDEMAND_ONDEMAND);
227
- if(do_bcast == -1) do_bcast = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "broadcast bandwidth", CONFIG_ONDEMAND_ONDEMAND);
228
- if(do_mcast_p == -1) do_mcast_p = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "multicast packets", CONFIG_ONDEMAND_ONDEMAND);
229
- if(do_icmp == -1) do_icmp = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp", CONFIG_ONDEMAND_ONDEMAND);
230
- if(do_icmp_redir == -1) do_icmp_redir = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp redirects", CONFIG_ONDEMAND_ONDEMAND);
231
- if(do_icmp_errors == -1) do_icmp_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp errors", CONFIG_ONDEMAND_ONDEMAND);
232
- if(do_icmp_echos == -1) do_icmp_echos = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp echos", CONFIG_ONDEMAND_ONDEMAND);
233
- if(do_icmp_groupmemb == -1) do_icmp_groupmemb = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp group membership", CONFIG_ONDEMAND_ONDEMAND);
234
- if(do_icmp_router == -1) do_icmp_router = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp router", CONFIG_ONDEMAND_ONDEMAND);
235
- if(do_icmp_neighbor == -1) do_icmp_neighbor = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp neighbor", CONFIG_ONDEMAND_ONDEMAND);
236
- if(do_icmp_mldv2 == -1) do_icmp_mldv2 = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp mldv2", CONFIG_ONDEMAND_ONDEMAND);
237
- if(do_icmp_types == -1) do_icmp_types = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp types", CONFIG_ONDEMAND_ONDEMAND);
238
- if(do_ect == -1) do_ect = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ect", CONFIG_ONDEMAND_ONDEMAND);
239
-
240
- if(dt) {};
241
-
242
- if(!ff) {
243
- char filename[FILENAME_MAX + 1];
244
- snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/snmp6");
245
- ff = procfile_open(config_get("plugin:proc:/proc/net/snmp6", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
246
- }
247
- if(!ff) return 1;
248
-
249
- ff = procfile_readall(ff);
250
- if(!ff) return 0; // we return 0, so that we will retry to open it next time
251
-
252
- uint32_t lines = procfile_lines(ff), l;
253
- uint32_t words;
254
-
255
- unsigned long long Ip6InReceives = 0ULL;
256
- unsigned long long Ip6InHdrErrors = 0ULL;
257
- unsigned long long Ip6InTooBigErrors = 0ULL;
258
- unsigned long long Ip6InNoRoutes = 0ULL;
259
- unsigned long long Ip6InAddrErrors = 0ULL;
260
- unsigned long long Ip6InUnknownProtos = 0ULL;
261
- unsigned long long Ip6InTruncatedPkts = 0ULL;
262
- unsigned long long Ip6InDiscards = 0ULL;
263
- unsigned long long Ip6InDelivers = 0ULL;
264
- unsigned long long Ip6OutForwDatagrams = 0ULL;
265
- unsigned long long Ip6OutRequests = 0ULL;
266
- unsigned long long Ip6OutDiscards = 0ULL;
267
- unsigned long long Ip6OutNoRoutes = 0ULL;
268
- unsigned long long Ip6ReasmTimeout = 0ULL;
269
- unsigned long long Ip6ReasmReqds = 0ULL;
270
- unsigned long long Ip6ReasmOKs = 0ULL;
271
- unsigned long long Ip6ReasmFails = 0ULL;
272
- unsigned long long Ip6FragOKs = 0ULL;
273
- unsigned long long Ip6FragFails = 0ULL;
274
- unsigned long long Ip6FragCreates = 0ULL;
275
- unsigned long long Ip6InMcastPkts = 0ULL;
276
- unsigned long long Ip6OutMcastPkts = 0ULL;
277
- unsigned long long Ip6InOctets = 0ULL;
278
- unsigned long long Ip6OutOctets = 0ULL;
279
- unsigned long long Ip6InMcastOctets = 0ULL;
280
- unsigned long long Ip6OutMcastOctets = 0ULL;
281
- unsigned long long Ip6InBcastOctets = 0ULL;
282
- unsigned long long Ip6OutBcastOctets = 0ULL;
283
- unsigned long long Ip6InNoECTPkts = 0ULL;
284
- unsigned long long Ip6InECT1Pkts = 0ULL;
285
- unsigned long long Ip6InECT0Pkts = 0ULL;
286
- unsigned long long Ip6InCEPkts = 0ULL;
287
- unsigned long long Icmp6InMsgs = 0ULL;
288
- unsigned long long Icmp6InErrors = 0ULL;
289
- unsigned long long Icmp6OutMsgs = 0ULL;
290
- unsigned long long Icmp6OutErrors = 0ULL;
291
- unsigned long long Icmp6InCsumErrors = 0ULL;
292
- unsigned long long Icmp6InDestUnreachs = 0ULL;
293
- unsigned long long Icmp6InPktTooBigs = 0ULL;
294
- unsigned long long Icmp6InTimeExcds = 0ULL;
295
- unsigned long long Icmp6InParmProblems = 0ULL;
296
- unsigned long long Icmp6InEchos = 0ULL;
297
- unsigned long long Icmp6InEchoReplies = 0ULL;
298
- unsigned long long Icmp6InGroupMembQueries = 0ULL;
299
- unsigned long long Icmp6InGroupMembResponses = 0ULL;
300
- unsigned long long Icmp6InGroupMembReductions = 0ULL;
301
- unsigned long long Icmp6InRouterSolicits = 0ULL;
302
- unsigned long long Icmp6InRouterAdvertisements = 0ULL;
303
- unsigned long long Icmp6InNeighborSolicits = 0ULL;
304
- unsigned long long Icmp6InNeighborAdvertisements = 0ULL;
305
- unsigned long long Icmp6InRedirects = 0ULL;
306
- unsigned long long Icmp6InMLDv2Reports = 0ULL;
307
- unsigned long long Icmp6OutDestUnreachs = 0ULL;
308
- unsigned long long Icmp6OutPktTooBigs = 0ULL;
309
- unsigned long long Icmp6OutTimeExcds = 0ULL;
310
- unsigned long long Icmp6OutParmProblems = 0ULL;
311
- unsigned long long Icmp6OutEchos = 0ULL;
312
- unsigned long long Icmp6OutEchoReplies = 0ULL;
313
- unsigned long long Icmp6OutGroupMembQueries = 0ULL;
314
- unsigned long long Icmp6OutGroupMembResponses = 0ULL;
315
- unsigned long long Icmp6OutGroupMembReductions = 0ULL;
316
- unsigned long long Icmp6OutRouterSolicits = 0ULL;
317
- unsigned long long Icmp6OutRouterAdvertisements = 0ULL;
318
- unsigned long long Icmp6OutNeighborSolicits = 0ULL;
319
- unsigned long long Icmp6OutNeighborAdvertisements = 0ULL;
320
- unsigned long long Icmp6OutRedirects = 0ULL;
321
- unsigned long long Icmp6OutMLDv2Reports = 0ULL;
322
- unsigned long long Icmp6InType1 = 0ULL;
323
- unsigned long long Icmp6InType128 = 0ULL;
324
- unsigned long long Icmp6InType129 = 0ULL;
325
- unsigned long long Icmp6InType136 = 0ULL;
326
- unsigned long long Icmp6OutType1 = 0ULL;
327
- unsigned long long Icmp6OutType128 = 0ULL;
328
- unsigned long long Icmp6OutType129 = 0ULL;
329
- unsigned long long Icmp6OutType133 = 0ULL;
330
- unsigned long long Icmp6OutType135 = 0ULL;
331
- unsigned long long Icmp6OutType143 = 0ULL;
332
- unsigned long long Udp6InDatagrams = 0ULL;
333
- unsigned long long Udp6NoPorts = 0ULL;
334
- unsigned long long Udp6InErrors = 0ULL;
335
- unsigned long long Udp6OutDatagrams = 0ULL;
336
- unsigned long long Udp6RcvbufErrors = 0ULL;
337
- unsigned long long Udp6SndbufErrors = 0ULL;
338
- unsigned long long Udp6InCsumErrors = 0ULL;
339
- unsigned long long Udp6IgnoredMulti = 0ULL;
340
- unsigned long long UdpLite6InDatagrams = 0ULL;
341
- unsigned long long UdpLite6NoPorts = 0ULL;
342
- unsigned long long UdpLite6InErrors = 0ULL;
343
- unsigned long long UdpLite6OutDatagrams = 0ULL;
344
- unsigned long long UdpLite6RcvbufErrors = 0ULL;
345
- unsigned long long UdpLite6SndbufErrors = 0ULL;
346
- unsigned long long UdpLite6InCsumErrors = 0ULL;
347
-
348
- for(l = 0; l < lines ;l++) {
349
- words = procfile_linewords(ff, l);
350
- if(words < 2) {
351
- if(words) error("Cannot read /proc/net/snmp6 line %u. Expected 2 params, read %u.", l, words);
352
- continue;
353
- }
354
-
355
- char *name = procfile_lineword(ff, l, 0);
356
- char * value = procfile_lineword(ff, l, 1);
357
- if(!name || !*name || !value || !*value) continue;
358
-
359
- uint32_t hash = simple_hash(name);
360
-
361
- if(0) ;
362
- else if(hash == hash_Ip6InReceives && strcmp(name, "Ip6InReceives") == 0) Ip6InReceives = strtoull(value, NULL, 10);
363
- else if(hash == hash_Ip6InHdrErrors && strcmp(name, "Ip6InHdrErrors") == 0) Ip6InHdrErrors = strtoull(value, NULL, 10);
364
- else if(hash == hash_Ip6InTooBigErrors && strcmp(name, "Ip6InTooBigErrors") == 0) Ip6InTooBigErrors = strtoull(value, NULL, 10);
365
- else if(hash == hash_Ip6InNoRoutes && strcmp(name, "Ip6InNoRoutes") == 0) Ip6InNoRoutes = strtoull(value, NULL, 10);
366
- else if(hash == hash_Ip6InAddrErrors && strcmp(name, "Ip6InAddrErrors") == 0) Ip6InAddrErrors = strtoull(value, NULL, 10);
367
- else if(hash == hash_Ip6InUnknownProtos && strcmp(name, "Ip6InUnknownProtos") == 0) Ip6InUnknownProtos = strtoull(value, NULL, 10);
368
- else if(hash == hash_Ip6InTruncatedPkts && strcmp(name, "Ip6InTruncatedPkts") == 0) Ip6InTruncatedPkts = strtoull(value, NULL, 10);
369
- else if(hash == hash_Ip6InDiscards && strcmp(name, "Ip6InDiscards") == 0) Ip6InDiscards = strtoull(value, NULL, 10);
370
- else if(hash == hash_Ip6InDelivers && strcmp(name, "Ip6InDelivers") == 0) Ip6InDelivers = strtoull(value, NULL, 10);
371
- else if(hash == hash_Ip6OutForwDatagrams && strcmp(name, "Ip6OutForwDatagrams") == 0) Ip6OutForwDatagrams = strtoull(value, NULL, 10);
372
- else if(hash == hash_Ip6OutRequests && strcmp(name, "Ip6OutRequests") == 0) Ip6OutRequests = strtoull(value, NULL, 10);
373
- else if(hash == hash_Ip6OutDiscards && strcmp(name, "Ip6OutDiscards") == 0) Ip6OutDiscards = strtoull(value, NULL, 10);
374
- else if(hash == hash_Ip6OutNoRoutes && strcmp(name, "Ip6OutNoRoutes") == 0) Ip6OutNoRoutes = strtoull(value, NULL, 10);
375
- else if(hash == hash_Ip6ReasmTimeout && strcmp(name, "Ip6ReasmTimeout") == 0) Ip6ReasmTimeout = strtoull(value, NULL, 10);
376
- else if(hash == hash_Ip6ReasmReqds && strcmp(name, "Ip6ReasmReqds") == 0) Ip6ReasmReqds = strtoull(value, NULL, 10);
377
- else if(hash == hash_Ip6ReasmOKs && strcmp(name, "Ip6ReasmOKs") == 0) Ip6ReasmOKs = strtoull(value, NULL, 10);
378
- else if(hash == hash_Ip6ReasmFails && strcmp(name, "Ip6ReasmFails") == 0) Ip6ReasmFails = strtoull(value, NULL, 10);
379
- else if(hash == hash_Ip6FragOKs && strcmp(name, "Ip6FragOKs") == 0) Ip6FragOKs = strtoull(value, NULL, 10);
380
- else if(hash == hash_Ip6FragFails && strcmp(name, "Ip6FragFails") == 0) Ip6FragFails = strtoull(value, NULL, 10);
381
- else if(hash == hash_Ip6FragCreates && strcmp(name, "Ip6FragCreates") == 0) Ip6FragCreates = strtoull(value, NULL, 10);
382
- else if(hash == hash_Ip6InMcastPkts && strcmp(name, "Ip6InMcastPkts") == 0) Ip6InMcastPkts = strtoull(value, NULL, 10);
383
- else if(hash == hash_Ip6OutMcastPkts && strcmp(name, "Ip6OutMcastPkts") == 0) Ip6OutMcastPkts = strtoull(value, NULL, 10);
384
- else if(hash == hash_Ip6InOctets && strcmp(name, "Ip6InOctets") == 0) Ip6InOctets = strtoull(value, NULL, 10);
385
- else if(hash == hash_Ip6OutOctets && strcmp(name, "Ip6OutOctets") == 0) Ip6OutOctets = strtoull(value, NULL, 10);
386
- else if(hash == hash_Ip6InMcastOctets && strcmp(name, "Ip6InMcastOctets") == 0) Ip6InMcastOctets = strtoull(value, NULL, 10);
387
- else if(hash == hash_Ip6OutMcastOctets && strcmp(name, "Ip6OutMcastOctets") == 0) Ip6OutMcastOctets = strtoull(value, NULL, 10);
388
- else if(hash == hash_Ip6InBcastOctets && strcmp(name, "Ip6InBcastOctets") == 0) Ip6InBcastOctets = strtoull(value, NULL, 10);
389
- else if(hash == hash_Ip6OutBcastOctets && strcmp(name, "Ip6OutBcastOctets") == 0) Ip6OutBcastOctets = strtoull(value, NULL, 10);
390
- else if(hash == hash_Ip6InNoECTPkts && strcmp(name, "Ip6InNoECTPkts") == 0) Ip6InNoECTPkts = strtoull(value, NULL, 10);
391
- else if(hash == hash_Ip6InECT1Pkts && strcmp(name, "Ip6InECT1Pkts") == 0) Ip6InECT1Pkts = strtoull(value, NULL, 10);
392
- else if(hash == hash_Ip6InECT0Pkts && strcmp(name, "Ip6InECT0Pkts") == 0) Ip6InECT0Pkts = strtoull(value, NULL, 10);
393
- else if(hash == hash_Ip6InCEPkts && strcmp(name, "Ip6InCEPkts") == 0) Ip6InCEPkts = strtoull(value, NULL, 10);
394
- else if(hash == hash_Icmp6InMsgs && strcmp(name, "Icmp6InMsgs") == 0) Icmp6InMsgs = strtoull(value, NULL, 10);
395
- else if(hash == hash_Icmp6InErrors && strcmp(name, "Icmp6InErrors") == 0) Icmp6InErrors = strtoull(value, NULL, 10);
396
- else if(hash == hash_Icmp6OutMsgs && strcmp(name, "Icmp6OutMsgs") == 0) Icmp6OutMsgs = strtoull(value, NULL, 10);
397
- else if(hash == hash_Icmp6OutErrors && strcmp(name, "Icmp6OutErrors") == 0) Icmp6OutErrors = strtoull(value, NULL, 10);
398
- else if(hash == hash_Icmp6InCsumErrors && strcmp(name, "Icmp6InCsumErrors") == 0) Icmp6InCsumErrors = strtoull(value, NULL, 10);
399
- else if(hash == hash_Icmp6InDestUnreachs && strcmp(name, "Icmp6InDestUnreachs") == 0) Icmp6InDestUnreachs = strtoull(value, NULL, 10);
400
- else if(hash == hash_Icmp6InPktTooBigs && strcmp(name, "Icmp6InPktTooBigs") == 0) Icmp6InPktTooBigs = strtoull(value, NULL, 10);
401
- else if(hash == hash_Icmp6InTimeExcds && strcmp(name, "Icmp6InTimeExcds") == 0) Icmp6InTimeExcds = strtoull(value, NULL, 10);
402
- else if(hash == hash_Icmp6InParmProblems && strcmp(name, "Icmp6InParmProblems") == 0) Icmp6InParmProblems = strtoull(value, NULL, 10);
403
- else if(hash == hash_Icmp6InEchos && strcmp(name, "Icmp6InEchos") == 0) Icmp6InEchos = strtoull(value, NULL, 10);
404
- else if(hash == hash_Icmp6InEchoReplies && strcmp(name, "Icmp6InEchoReplies") == 0) Icmp6InEchoReplies = strtoull(value, NULL, 10);
405
- else if(hash == hash_Icmp6InGroupMembQueries && strcmp(name, "Icmp6InGroupMembQueries") == 0) Icmp6InGroupMembQueries = strtoull(value, NULL, 10);
406
- else if(hash == hash_Icmp6InGroupMembResponses && strcmp(name, "Icmp6InGroupMembResponses") == 0) Icmp6InGroupMembResponses = strtoull(value, NULL, 10);
407
- else if(hash == hash_Icmp6InGroupMembReductions && strcmp(name, "Icmp6InGroupMembReductions") == 0) Icmp6InGroupMembReductions = strtoull(value, NULL, 10);
408
- else if(hash == hash_Icmp6InRouterSolicits && strcmp(name, "Icmp6InRouterSolicits") == 0) Icmp6InRouterSolicits = strtoull(value, NULL, 10);
409
- else if(hash == hash_Icmp6InRouterAdvertisements && strcmp(name, "Icmp6InRouterAdvertisements") == 0) Icmp6InRouterAdvertisements = strtoull(value, NULL, 10);
410
- else if(hash == hash_Icmp6InNeighborSolicits && strcmp(name, "Icmp6InNeighborSolicits") == 0) Icmp6InNeighborSolicits = strtoull(value, NULL, 10);
411
- else if(hash == hash_Icmp6InNeighborAdvertisements && strcmp(name, "Icmp6InNeighborAdvertisements") == 0) Icmp6InNeighborAdvertisements = strtoull(value, NULL, 10);
412
- else if(hash == hash_Icmp6InRedirects && strcmp(name, "Icmp6InRedirects") == 0) Icmp6InRedirects = strtoull(value, NULL, 10);
413
- else if(hash == hash_Icmp6InMLDv2Reports && strcmp(name, "Icmp6InMLDv2Reports") == 0) Icmp6InMLDv2Reports = strtoull(value, NULL, 10);
414
- else if(hash == hash_Icmp6OutDestUnreachs && strcmp(name, "Icmp6OutDestUnreachs") == 0) Icmp6OutDestUnreachs = strtoull(value, NULL, 10);
415
- else if(hash == hash_Icmp6OutPktTooBigs && strcmp(name, "Icmp6OutPktTooBigs") == 0) Icmp6OutPktTooBigs = strtoull(value, NULL, 10);
416
- else if(hash == hash_Icmp6OutTimeExcds && strcmp(name, "Icmp6OutTimeExcds") == 0) Icmp6OutTimeExcds = strtoull(value, NULL, 10);
417
- else if(hash == hash_Icmp6OutParmProblems && strcmp(name, "Icmp6OutParmProblems") == 0) Icmp6OutParmProblems = strtoull(value, NULL, 10);
418
- else if(hash == hash_Icmp6OutEchos && strcmp(name, "Icmp6OutEchos") == 0) Icmp6OutEchos = strtoull(value, NULL, 10);
419
- else if(hash == hash_Icmp6OutEchoReplies && strcmp(name, "Icmp6OutEchoReplies") == 0) Icmp6OutEchoReplies = strtoull(value, NULL, 10);
420
- else if(hash == hash_Icmp6OutGroupMembQueries && strcmp(name, "Icmp6OutGroupMembQueries") == 0) Icmp6OutGroupMembQueries = strtoull(value, NULL, 10);
421
- else if(hash == hash_Icmp6OutGroupMembResponses && strcmp(name, "Icmp6OutGroupMembResponses") == 0) Icmp6OutGroupMembResponses = strtoull(value, NULL, 10);
422
- else if(hash == hash_Icmp6OutGroupMembReductions && strcmp(name, "Icmp6OutGroupMembReductions") == 0) Icmp6OutGroupMembReductions = strtoull(value, NULL, 10);
423
- else if(hash == hash_Icmp6OutRouterSolicits && strcmp(name, "Icmp6OutRouterSolicits") == 0) Icmp6OutRouterSolicits = strtoull(value, NULL, 10);
424
- else if(hash == hash_Icmp6OutRouterAdvertisements && strcmp(name, "Icmp6OutRouterAdvertisements") == 0) Icmp6OutRouterAdvertisements = strtoull(value, NULL, 10);
425
- else if(hash == hash_Icmp6OutNeighborSolicits && strcmp(name, "Icmp6OutNeighborSolicits") == 0) Icmp6OutNeighborSolicits = strtoull(value, NULL, 10);
426
- else if(hash == hash_Icmp6OutNeighborAdvertisements && strcmp(name, "Icmp6OutNeighborAdvertisements") == 0) Icmp6OutNeighborAdvertisements = strtoull(value, NULL, 10);
427
- else if(hash == hash_Icmp6OutRedirects && strcmp(name, "Icmp6OutRedirects") == 0) Icmp6OutRedirects = strtoull(value, NULL, 10);
428
- else if(hash == hash_Icmp6OutMLDv2Reports && strcmp(name, "Icmp6OutMLDv2Reports") == 0) Icmp6OutMLDv2Reports = strtoull(value, NULL, 10);
429
- else if(hash == hash_Icmp6InType1 && strcmp(name, "Icmp6InType1") == 0) Icmp6InType1 = strtoull(value, NULL, 10);
430
- else if(hash == hash_Icmp6InType128 && strcmp(name, "Icmp6InType128") == 0) Icmp6InType128 = strtoull(value, NULL, 10);
431
- else if(hash == hash_Icmp6InType129 && strcmp(name, "Icmp6InType129") == 0) Icmp6InType129 = strtoull(value, NULL, 10);
432
- else if(hash == hash_Icmp6InType136 && strcmp(name, "Icmp6InType136") == 0) Icmp6InType136 = strtoull(value, NULL, 10);
433
- else if(hash == hash_Icmp6OutType1 && strcmp(name, "Icmp6OutType1") == 0) Icmp6OutType1 = strtoull(value, NULL, 10);
434
- else if(hash == hash_Icmp6OutType128 && strcmp(name, "Icmp6OutType128") == 0) Icmp6OutType128 = strtoull(value, NULL, 10);
435
- else if(hash == hash_Icmp6OutType129 && strcmp(name, "Icmp6OutType129") == 0) Icmp6OutType129 = strtoull(value, NULL, 10);
436
- else if(hash == hash_Icmp6OutType133 && strcmp(name, "Icmp6OutType133") == 0) Icmp6OutType133 = strtoull(value, NULL, 10);
437
- else if(hash == hash_Icmp6OutType135 && strcmp(name, "Icmp6OutType135") == 0) Icmp6OutType135 = strtoull(value, NULL, 10);
438
- else if(hash == hash_Icmp6OutType143 && strcmp(name, "Icmp6OutType143") == 0) Icmp6OutType143 = strtoull(value, NULL, 10);
439
- else if(hash == hash_Udp6InDatagrams && strcmp(name, "Udp6InDatagrams") == 0) Udp6InDatagrams = strtoull(value, NULL, 10);
440
- else if(hash == hash_Udp6NoPorts && strcmp(name, "Udp6NoPorts") == 0) Udp6NoPorts = strtoull(value, NULL, 10);
441
- else if(hash == hash_Udp6InErrors && strcmp(name, "Udp6InErrors") == 0) Udp6InErrors = strtoull(value, NULL, 10);
442
- else if(hash == hash_Udp6OutDatagrams && strcmp(name, "Udp6OutDatagrams") == 0) Udp6OutDatagrams = strtoull(value, NULL, 10);
443
- else if(hash == hash_Udp6RcvbufErrors && strcmp(name, "Udp6RcvbufErrors") == 0) Udp6RcvbufErrors = strtoull(value, NULL, 10);
444
- else if(hash == hash_Udp6SndbufErrors && strcmp(name, "Udp6SndbufErrors") == 0) Udp6SndbufErrors = strtoull(value, NULL, 10);
445
- else if(hash == hash_Udp6InCsumErrors && strcmp(name, "Udp6InCsumErrors") == 0) Udp6InCsumErrors = strtoull(value, NULL, 10);
446
- else if(hash == hash_Udp6IgnoredMulti && strcmp(name, "Udp6IgnoredMulti") == 0) Udp6IgnoredMulti = strtoull(value, NULL, 10);
447
- else if(hash == hash_UdpLite6InDatagrams && strcmp(name, "UdpLite6InDatagrams") == 0) UdpLite6InDatagrams = strtoull(value, NULL, 10);
448
- else if(hash == hash_UdpLite6NoPorts && strcmp(name, "UdpLite6NoPorts") == 0) UdpLite6NoPorts = strtoull(value, NULL, 10);
449
- else if(hash == hash_UdpLite6InErrors && strcmp(name, "UdpLite6InErrors") == 0) UdpLite6InErrors = strtoull(value, NULL, 10);
450
- else if(hash == hash_UdpLite6OutDatagrams && strcmp(name, "UdpLite6OutDatagrams") == 0) UdpLite6OutDatagrams = strtoull(value, NULL, 10);
451
- else if(hash == hash_UdpLite6RcvbufErrors && strcmp(name, "UdpLite6RcvbufErrors") == 0) UdpLite6RcvbufErrors = strtoull(value, NULL, 10);
452
- else if(hash == hash_UdpLite6SndbufErrors && strcmp(name, "UdpLite6SndbufErrors") == 0) UdpLite6SndbufErrors = strtoull(value, NULL, 10);
453
- else if(hash == hash_UdpLite6InCsumErrors && strcmp(name, "UdpLite6InCsumErrors") == 0) UdpLite6InCsumErrors = strtoull(value, NULL, 10);
454
- }
455
-
456
- RRDSET *st;
457
-
458
- // --------------------------------------------------------------------
459
-
460
- if(do_bandwidth == CONFIG_ONDEMAND_YES || (do_bandwidth == CONFIG_ONDEMAND_ONDEMAND && (Ip6InOctets || Ip6OutOctets))) {
461
- do_bandwidth = CONFIG_ONDEMAND_YES;
462
- st = rrdset_find("system.ipv6");
463
- if(!st) {
464
- st = rrdset_create("system", "ipv6", NULL, "network", NULL, "IPv6 Bandwidth", "kilobits/s", 500, update_every, RRDSET_TYPE_AREA);
465
-
466
- rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL);
467
- rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL);
468
- }
469
- else rrdset_next(st);
470
-
471
- rrddim_set(st, "sent", Ip6OutOctets);
472
- rrddim_set(st, "received", Ip6InOctets);
473
- rrdset_done(st);
474
- }
475
-
476
- // --------------------------------------------------------------------
477
-
478
- if(do_ip_packets == CONFIG_ONDEMAND_YES || (do_ip_packets == CONFIG_ONDEMAND_ONDEMAND && (Ip6InReceives || Ip6OutRequests || Ip6InDelivers || Ip6OutForwDatagrams))) {
479
- do_ip_packets = CONFIG_ONDEMAND_YES;
480
- st = rrdset_find(RRD_TYPE_NET_SNMP6 ".packets");
481
- if(!st) {
482
- st = rrdset_create(RRD_TYPE_NET_SNMP6, "packets", NULL, "packets", NULL, "IPv6 Packets", "packets/s", 3000, update_every, RRDSET_TYPE_LINE);
483
-
484
- rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
485
- rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
486
- rrddim_add(st, "forwarded", NULL, 1, 1, RRDDIM_INCREMENTAL);
487
- rrddim_add(st, "delivers", NULL, -1, 1, RRDDIM_INCREMENTAL);
488
- }
489
- else rrdset_next(st);
490
-
491
- rrddim_set(st, "sent", Ip6OutRequests);
492
- rrddim_set(st, "received", Ip6InReceives);
493
- rrddim_set(st, "forwarded", Ip6InDelivers);
494
- rrddim_set(st, "delivers", Ip6OutForwDatagrams);
495
- rrdset_done(st);
496
- }
497
-
498
- // --------------------------------------------------------------------
499
-
500
- if(do_ip_fragsout == CONFIG_ONDEMAND_YES || (do_ip_fragsout == CONFIG_ONDEMAND_ONDEMAND && (Ip6FragOKs || Ip6FragFails || Ip6FragCreates))) {
501
- do_ip_fragsout = CONFIG_ONDEMAND_YES;
502
- st = rrdset_find(RRD_TYPE_NET_SNMP6 ".fragsout");
503
- if(!st) {
504
- st = rrdset_create(RRD_TYPE_NET_SNMP6, "fragsout", NULL, "fragments", NULL, "IPv6 Fragments Sent", "packets/s", 3010, update_every, RRDSET_TYPE_LINE);
505
- st->isdetail = 1;
506
-
507
- rrddim_add(st, "ok", NULL, 1, 1, RRDDIM_INCREMENTAL);
508
- rrddim_add(st, "failed", NULL, -1, 1, RRDDIM_INCREMENTAL);
509
- rrddim_add(st, "all", NULL, 1, 1, RRDDIM_INCREMENTAL);
510
- }
511
- else rrdset_next(st);
512
-
513
- rrddim_set(st, "ok", Ip6FragOKs);
514
- rrddim_set(st, "failed", Ip6FragFails);
515
- rrddim_set(st, "all", Ip6FragCreates);
516
- rrdset_done(st);
517
- }
518
-
519
- // --------------------------------------------------------------------
520
-
521
- if(do_ip_fragsin == CONFIG_ONDEMAND_YES || (do_ip_fragsin == CONFIG_ONDEMAND_ONDEMAND
522
- && (
523
- Ip6ReasmOKs
524
- || Ip6ReasmFails
525
- || Ip6ReasmTimeout
526
- || Ip6ReasmReqds
527
- ))) {
528
- do_ip_fragsin = CONFIG_ONDEMAND_YES;
529
- st = rrdset_find(RRD_TYPE_NET_SNMP6 ".fragsin");
530
- if(!st) {
531
- st = rrdset_create(RRD_TYPE_NET_SNMP6, "fragsin", NULL, "fragments", NULL, "IPv6 Fragments Reassembly", "packets/s", 3011, update_every, RRDSET_TYPE_LINE);
532
- st->isdetail = 1;
533
-
534
- rrddim_add(st, "ok", NULL, 1, 1, RRDDIM_INCREMENTAL);
535
- rrddim_add(st, "failed", NULL, -1, 1, RRDDIM_INCREMENTAL);
536
- rrddim_add(st, "timeout", NULL, -1, 1, RRDDIM_INCREMENTAL);
537
- rrddim_add(st, "all", NULL, 1, 1, RRDDIM_INCREMENTAL);
538
- }
539
- else rrdset_next(st);
540
-
541
- rrddim_set(st, "ok", Ip6ReasmOKs);
542
- rrddim_set(st, "failed", Ip6ReasmFails);
543
- rrddim_set(st, "timeout", Ip6ReasmTimeout);
544
- rrddim_set(st, "all", Ip6ReasmReqds);
545
- rrdset_done(st);
546
- }
547
-
548
- // --------------------------------------------------------------------
549
-
550
- if(do_ip_errors == CONFIG_ONDEMAND_YES || (do_ip_errors == CONFIG_ONDEMAND_ONDEMAND
551
- && (
552
- Ip6InDiscards
553
- || Ip6OutDiscards
554
- || Ip6InHdrErrors
555
- || Ip6InAddrErrors
556
- || Ip6InUnknownProtos
557
- || Ip6InTooBigErrors
558
- || Ip6InTruncatedPkts
559
- || Ip6InNoRoutes
560
- ))) {
561
- do_ip_errors = CONFIG_ONDEMAND_YES;
562
- st = rrdset_find(RRD_TYPE_NET_SNMP6 ".errors");
563
- if(!st) {
564
- st = rrdset_create(RRD_TYPE_NET_SNMP6, "errors", NULL, "errors", NULL, "IPv6 Errors", "packets/s", 3002, update_every, RRDSET_TYPE_LINE);
565
- st->isdetail = 1;
566
-
567
- rrddim_add(st, "InDiscards", NULL, 1, 1, RRDDIM_INCREMENTAL);
568
- rrddim_add(st, "OutDiscards", NULL, -1, 1, RRDDIM_INCREMENTAL);
569
-
570
- rrddim_add(st, "InHdrErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
571
- rrddim_add(st, "InAddrErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
572
- rrddim_add(st, "InUnknownProtos", NULL, 1, 1, RRDDIM_INCREMENTAL);
573
- rrddim_add(st, "InTooBigErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
574
- rrddim_add(st, "InTruncatedPkts", NULL, 1, 1, RRDDIM_INCREMENTAL);
575
- rrddim_add(st, "InNoRoutes", NULL, 1, 1, RRDDIM_INCREMENTAL);
576
-
577
- rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRDDIM_INCREMENTAL);
578
- }
579
- else rrdset_next(st);
580
-
581
- rrddim_set(st, "InDiscards", Ip6InDiscards);
582
- rrddim_set(st, "OutDiscards", Ip6OutDiscards);
583
-
584
- rrddim_set(st, "InHdrErrors", Ip6InHdrErrors);
585
- rrddim_set(st, "InAddrErrors", Ip6InAddrErrors);
586
- rrddim_set(st, "InUnknownProtos", Ip6InUnknownProtos);
587
- rrddim_set(st, "InTooBigErrors", Ip6InTooBigErrors);
588
- rrddim_set(st, "InTruncatedPkts", Ip6InTruncatedPkts);
589
- rrddim_set(st, "InNoRoutes", Ip6InNoRoutes);
590
-
591
- rrddim_set(st, "OutNoRoutes", Ip6OutNoRoutes);
592
- rrdset_done(st);
593
- }
594
-
595
- // --------------------------------------------------------------------
596
-
597
- if(do_udp_packets == CONFIG_ONDEMAND_YES || (do_udp_packets == CONFIG_ONDEMAND_ONDEMAND && (Udp6InDatagrams || Udp6OutDatagrams))) {
598
- do_udp_packets = CONFIG_ONDEMAND_YES;
599
- st = rrdset_find(RRD_TYPE_NET_SNMP6 ".udppackets");
600
- if(!st) {
601
- st = rrdset_create(RRD_TYPE_NET_SNMP6, "udppackets", NULL, "udp", NULL, "IPv6 UDP Packets", "packets/s", 3601, update_every, RRDSET_TYPE_LINE);
602
-
603
- rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
604
- rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
605
- }
606
- else rrdset_next(st);
607
-
608
- rrddim_set(st, "received", Udp6InDatagrams);
609
- rrddim_set(st, "sent", Udp6OutDatagrams);
610
- rrdset_done(st);
611
- }
612
-
613
- // --------------------------------------------------------------------
614
-
615
- if(do_udp_errors == CONFIG_ONDEMAND_YES || (do_udp_errors == CONFIG_ONDEMAND_ONDEMAND
616
- && (
617
- Udp6InErrors
618
- || Udp6NoPorts
619
- || Udp6RcvbufErrors
620
- || Udp6SndbufErrors
621
- || Udp6InCsumErrors
622
- || Udp6IgnoredMulti
623
- ))) {
624
- do_udp_errors = CONFIG_ONDEMAND_YES;
625
- st = rrdset_find(RRD_TYPE_NET_SNMP6 ".udperrors");
626
- if(!st) {
627
- st = rrdset_create(RRD_TYPE_NET_SNMP6, "udperrors", NULL, "udp", NULL, "IPv6 UDP Errors", "events/s", 3701, update_every, RRDSET_TYPE_LINE);
628
- st->isdetail = 1;
629
-
630
- rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
631
- rrddim_add(st, "SndbufErrors", NULL, -1, 1, RRDDIM_INCREMENTAL);
632
- rrddim_add(st, "InErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
633
- rrddim_add(st, "NoPorts", NULL, 1, 1, RRDDIM_INCREMENTAL);
634
- rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
635
- rrddim_add(st, "IgnoredMulti", NULL, 1, 1, RRDDIM_INCREMENTAL);
636
- }
637
- else rrdset_next(st);
638
-
639
- rrddim_set(st, "InErrors", Udp6InErrors);
640
- rrddim_set(st, "NoPorts", Udp6NoPorts);
641
- rrddim_set(st, "RcvbufErrors", Udp6RcvbufErrors);
642
- rrddim_set(st, "SndbufErrors", Udp6SndbufErrors);
643
- rrddim_set(st, "InCsumErrors", Udp6InCsumErrors);
644
- rrddim_set(st, "IgnoredMulti", Udp6IgnoredMulti);
645
- rrdset_done(st);
646
- }
647
-
648
- // --------------------------------------------------------------------
649
-
650
- if(do_udplite_packets == CONFIG_ONDEMAND_YES || (do_udplite_packets == CONFIG_ONDEMAND_ONDEMAND && (UdpLite6InDatagrams || UdpLite6OutDatagrams))) {
651
- do_udplite_packets = CONFIG_ONDEMAND_YES;
652
- st = rrdset_find(RRD_TYPE_NET_SNMP6 ".udplitepackets");
653
- if(!st) {
654
- st = rrdset_create(RRD_TYPE_NET_SNMP6, "udplitepackets", NULL, "udplite", NULL, "IPv6 UDPlite Packets", "packets/s", 3601, update_every, RRDSET_TYPE_LINE);
655
-
656
- rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
657
- rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
658
- }
659
- else rrdset_next(st);
660
-
661
- rrddim_set(st, "received", UdpLite6InDatagrams);
662
- rrddim_set(st, "sent", UdpLite6OutDatagrams);
663
- rrdset_done(st);
664
- }
665
-
666
- // --------------------------------------------------------------------
667
-
668
- if(do_udplite_errors == CONFIG_ONDEMAND_YES || (do_udplite_errors == CONFIG_ONDEMAND_ONDEMAND
669
- && (
670
- UdpLite6InErrors
671
- || UdpLite6NoPorts
672
- || UdpLite6RcvbufErrors
673
- || UdpLite6SndbufErrors
674
- || Udp6InCsumErrors
675
- || UdpLite6InCsumErrors
676
- ))) {
677
- do_udplite_errors = CONFIG_ONDEMAND_YES;
678
- st = rrdset_find(RRD_TYPE_NET_SNMP6 ".udpliteerrors");
679
- if(!st) {
680
- st = rrdset_create(RRD_TYPE_NET_SNMP6, "udpliteerrors", NULL, "udplite", NULL, "IPv6 UDP Lite Errors", "events/s", 3701, update_every, RRDSET_TYPE_LINE);
681
- st->isdetail = 1;
682
-
683
- rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
684
- rrddim_add(st, "SndbufErrors", NULL, -1, 1, RRDDIM_INCREMENTAL);
685
- rrddim_add(st, "InErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
686
- rrddim_add(st, "NoPorts", NULL, 1, 1, RRDDIM_INCREMENTAL);
687
- rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
688
- }
689
- else rrdset_next(st);
690
-
691
- rrddim_set(st, "InErrors", UdpLite6InErrors);
692
- rrddim_set(st, "NoPorts", UdpLite6NoPorts);
693
- rrddim_set(st, "RcvbufErrors", UdpLite6RcvbufErrors);
694
- rrddim_set(st, "SndbufErrors", UdpLite6SndbufErrors);
695
- rrddim_set(st, "InCsumErrors", UdpLite6InCsumErrors);
696
- rrdset_done(st);
697
- }
698
-
699
- // --------------------------------------------------------------------
700
-
701
- if(do_mcast == CONFIG_ONDEMAND_YES || (do_mcast == CONFIG_ONDEMAND_ONDEMAND && (Ip6OutMcastOctets || Ip6InMcastOctets))) {
702
- do_mcast = CONFIG_ONDEMAND_YES;
703
- st = rrdset_find(RRD_TYPE_NET_SNMP6 ".mcast");
704
- if(!st) {
705
- st = rrdset_create(RRD_TYPE_NET_SNMP6, "mcast", NULL, "multicast", NULL, "IPv6 Multicast Bandwidth", "kilobits/s", 9000, update_every, RRDSET_TYPE_AREA);
706
- st->isdetail = 1;
707
-
708
- rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL);
709
- rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL);
710
- }
711
- else rrdset_next(st);
712
-
713
- rrddim_set(st, "sent", Ip6OutMcastOctets);
714
- rrddim_set(st, "received", Ip6InMcastOctets);
715
- rrdset_done(st);
716
- }
717
-
718
- // --------------------------------------------------------------------
719
-
720
- if(do_bcast == CONFIG_ONDEMAND_YES || (do_bcast == CONFIG_ONDEMAND_ONDEMAND && (Ip6OutBcastOctets || Ip6InBcastOctets))) {
721
- do_bcast = CONFIG_ONDEMAND_YES;
722
- st = rrdset_find(RRD_TYPE_NET_SNMP6 ".bcast");
723
- if(!st) {
724
- st = rrdset_create(RRD_TYPE_NET_SNMP6, "bcast", NULL, "broadcast", NULL, "IPv6 Broadcast Bandwidth", "kilobits/s", 8000, update_every, RRDSET_TYPE_AREA);
725
- st->isdetail = 1;
726
-
727
- rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL);
728
- rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL);
729
- }
730
- else rrdset_next(st);
731
-
732
- rrddim_set(st, "sent", Ip6OutBcastOctets);
733
- rrddim_set(st, "received", Ip6InBcastOctets);
734
- rrdset_done(st);
735
- }
736
-
737
- // --------------------------------------------------------------------
738
-
739
- if(do_mcast_p == CONFIG_ONDEMAND_YES || (do_mcast_p == CONFIG_ONDEMAND_ONDEMAND && (Ip6OutMcastPkts || Ip6InMcastPkts))) {
740
- do_mcast_p = CONFIG_ONDEMAND_YES;
741
- st = rrdset_find(RRD_TYPE_NET_SNMP6 ".mcastpkts");
742
- if(!st) {
743
- st = rrdset_create(RRD_TYPE_NET_SNMP6, "mcastpkts", NULL, "multicast", NULL, "IPv6 Multicast Packets", "packets/s", 9500, update_every, RRDSET_TYPE_LINE);
744
- st->isdetail = 1;
745
-
746
- rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
747
- rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
748
- }
749
- else rrdset_next(st);
750
-
751
- rrddim_set(st, "sent", Ip6OutMcastPkts);
752
- rrddim_set(st, "received", Ip6InMcastPkts);
753
- rrdset_done(st);
754
- }
755
-
756
- // --------------------------------------------------------------------
757
-
758
- if(do_icmp == CONFIG_ONDEMAND_YES || (do_icmp == CONFIG_ONDEMAND_ONDEMAND && (Icmp6InMsgs || Icmp6OutMsgs))) {
759
- do_icmp = CONFIG_ONDEMAND_YES;
760
- st = rrdset_find(RRD_TYPE_NET_SNMP6 ".icmp");
761
- if(!st) {
762
- st = rrdset_create(RRD_TYPE_NET_SNMP6, "icmp", NULL, "icmp", NULL, "IPv6 ICMP Messages", "messages/s", 10000, update_every, RRDSET_TYPE_LINE);
763
-
764
- rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
765
- rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
766
- }
767
- else rrdset_next(st);
768
-
769
- rrddim_set(st, "sent", Icmp6InMsgs);
770
- rrddim_set(st, "received", Icmp6OutMsgs);
771
- rrdset_done(st);
772
- }
773
-
774
- // --------------------------------------------------------------------
775
-
776
- if(do_icmp_redir == CONFIG_ONDEMAND_YES || (do_icmp_redir == CONFIG_ONDEMAND_ONDEMAND && (Icmp6InRedirects || Icmp6OutRedirects))) {
777
- do_icmp_redir = CONFIG_ONDEMAND_YES;
778
- st = rrdset_find(RRD_TYPE_NET_SNMP6 ".icmpredir");
779
- if(!st) {
780
- st = rrdset_create(RRD_TYPE_NET_SNMP6, "icmpredir", NULL, "icmp", NULL, "IPv6 ICMP Redirects", "redirects/s", 10050, update_every, RRDSET_TYPE_LINE);
781
-
782
- rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
783
- rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
784
- }
785
- else rrdset_next(st);
786
-
787
- rrddim_set(st, "sent", Icmp6InRedirects);
788
- rrddim_set(st, "received", Icmp6OutRedirects);
789
- rrdset_done(st);
790
- }
791
-
792
- // --------------------------------------------------------------------
793
-
794
- if(do_icmp_errors == CONFIG_ONDEMAND_YES || (do_icmp_errors == CONFIG_ONDEMAND_ONDEMAND
795
- && (
796
- Icmp6InErrors
797
- || Icmp6OutErrors
798
- || Icmp6InCsumErrors
799
- || Icmp6InDestUnreachs
800
- || Icmp6InPktTooBigs
801
- || Icmp6InTimeExcds
802
- || Icmp6InParmProblems
803
- || Icmp6OutDestUnreachs
804
- || Icmp6OutPktTooBigs
805
- || Icmp6OutTimeExcds
806
- || Icmp6OutParmProblems
807
- ))) {
808
- do_icmp_errors = CONFIG_ONDEMAND_YES;
809
- st = rrdset_find(RRD_TYPE_NET_SNMP6 ".icmperrors");
810
- if(!st) {
811
- st = rrdset_create(RRD_TYPE_NET_SNMP6, "icmperrors", NULL, "icmp", NULL, "IPv6 ICMP Errors", "errors/s", 10100, update_every, RRDSET_TYPE_LINE);
812
-
813
- rrddim_add(st, "InErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
814
- rrddim_add(st, "OutErrors", NULL, -1, 1, RRDDIM_INCREMENTAL);
815
-
816
- rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
817
- rrddim_add(st, "InDestUnreachs", NULL, 1, 1, RRDDIM_INCREMENTAL);
818
- rrddim_add(st, "InPktTooBigs", NULL, 1, 1, RRDDIM_INCREMENTAL);
819
- rrddim_add(st, "InTimeExcds", NULL, 1, 1, RRDDIM_INCREMENTAL);
820
- rrddim_add(st, "InParmProblems", NULL, 1, 1, RRDDIM_INCREMENTAL);
821
- rrddim_add(st, "OutDestUnreachs", NULL, -1, 1, RRDDIM_INCREMENTAL);
822
- rrddim_add(st, "OutPktTooBigs", NULL, -1, 1, RRDDIM_INCREMENTAL);
823
- rrddim_add(st, "OutTimeExcds", NULL, -1, 1, RRDDIM_INCREMENTAL);
824
- rrddim_add(st, "OutParmProblems", NULL, -1, 1, RRDDIM_INCREMENTAL);
825
- }
826
- else rrdset_next(st);
827
-
828
- rrddim_set(st, "InErrors", Icmp6InErrors);
829
- rrddim_set(st, "OutErrors", Icmp6OutErrors);
830
- rrddim_set(st, "InCsumErrors", Icmp6InCsumErrors);
831
- rrddim_set(st, "InDestUnreachs", Icmp6InDestUnreachs);
832
- rrddim_set(st, "InPktTooBigs", Icmp6InPktTooBigs);
833
- rrddim_set(st, "InTimeExcds", Icmp6InTimeExcds);
834
- rrddim_set(st, "InParmProblems", Icmp6InParmProblems);
835
- rrddim_set(st, "OutDestUnreachs", Icmp6OutDestUnreachs);
836
- rrddim_set(st, "OutPktTooBigs", Icmp6OutPktTooBigs);
837
- rrddim_set(st, "OutTimeExcds", Icmp6OutTimeExcds);
838
- rrddim_set(st, "OutParmProblems", Icmp6OutParmProblems);
839
- rrdset_done(st);
840
- }
841
-
842
- // --------------------------------------------------------------------
843
-
844
- if(do_icmp_echos == CONFIG_ONDEMAND_YES || (do_icmp_echos == CONFIG_ONDEMAND_ONDEMAND
845
- && (
846
- Icmp6InEchos
847
- || Icmp6OutEchos
848
- || Icmp6InEchoReplies
849
- || Icmp6OutEchoReplies
850
- ))) {
851
- do_icmp_echos = CONFIG_ONDEMAND_YES;
852
- st = rrdset_find(RRD_TYPE_NET_SNMP6 ".icmpechos");
853
- if(!st) {
854
- st = rrdset_create(RRD_TYPE_NET_SNMP6, "icmpechos", NULL, "icmp", NULL, "IPv6 ICMP Echo", "messages/s", 10200, update_every, RRDSET_TYPE_LINE);
855
-
856
- rrddim_add(st, "InEchos", NULL, 1, 1, RRDDIM_INCREMENTAL);
857
- rrddim_add(st, "OutEchos", NULL, -1, 1, RRDDIM_INCREMENTAL);
858
- rrddim_add(st, "InEchoReplies", NULL, 1, 1, RRDDIM_INCREMENTAL);
859
- rrddim_add(st, "OutEchoReplies", NULL, -1, 1, RRDDIM_INCREMENTAL);
860
- }
861
- else rrdset_next(st);
862
-
863
- rrddim_set(st, "InEchos", Icmp6InEchos);
864
- rrddim_set(st, "OutEchos", Icmp6OutEchos);
865
- rrddim_set(st, "InEchoReplies", Icmp6InEchoReplies);
866
- rrddim_set(st, "OutEchoReplies", Icmp6OutEchoReplies);
867
- rrdset_done(st);
868
- }
869
-
870
- // --------------------------------------------------------------------
871
-
872
- if(do_icmp_groupmemb == CONFIG_ONDEMAND_YES || (do_icmp_groupmemb == CONFIG_ONDEMAND_ONDEMAND
873
- && (
874
- Icmp6InGroupMembQueries
875
- || Icmp6OutGroupMembQueries
876
- || Icmp6InGroupMembResponses
877
- || Icmp6OutGroupMembResponses
878
- || Icmp6InGroupMembReductions
879
- || Icmp6OutGroupMembReductions
880
- ))) {
881
- do_icmp_groupmemb = CONFIG_ONDEMAND_YES;
882
- st = rrdset_find(RRD_TYPE_NET_SNMP6 ".groupmemb");
883
- if(!st) {
884
- st = rrdset_create(RRD_TYPE_NET_SNMP6, "groupmemb", NULL, "icmp", NULL, "IPv6 ICMP Group Membership", "messages/s", 10300, update_every, RRDSET_TYPE_LINE);
885
-
886
- rrddim_add(st, "InQueries", NULL, 1, 1, RRDDIM_INCREMENTAL);
887
- rrddim_add(st, "OutQueries", NULL, -1, 1, RRDDIM_INCREMENTAL);
888
- rrddim_add(st, "InResponses", NULL, 1, 1, RRDDIM_INCREMENTAL);
889
- rrddim_add(st, "OutResponses", NULL, -1, 1, RRDDIM_INCREMENTAL);
890
- rrddim_add(st, "InReductions", NULL, 1, 1, RRDDIM_INCREMENTAL);
891
- rrddim_add(st, "OutReductions", NULL, -1, 1, RRDDIM_INCREMENTAL);
892
- }
893
- else rrdset_next(st);
894
-
895
- rrddim_set(st, "InQueries", Icmp6InGroupMembQueries);
896
- rrddim_set(st, "OutQueries", Icmp6OutGroupMembQueries);
897
- rrddim_set(st, "InResponses", Icmp6InGroupMembResponses);
898
- rrddim_set(st, "OutResponses", Icmp6OutGroupMembResponses);
899
- rrddim_set(st, "InReductions", Icmp6InGroupMembReductions);
900
- rrddim_set(st, "OutReductions", Icmp6OutGroupMembReductions);
901
- rrdset_done(st);
902
- }
903
-
904
- // --------------------------------------------------------------------
905
-
906
- if(do_icmp_router == CONFIG_ONDEMAND_YES || (do_icmp_router == CONFIG_ONDEMAND_ONDEMAND
907
- && (
908
- Icmp6InRouterSolicits
909
- || Icmp6OutRouterSolicits
910
- || Icmp6InRouterAdvertisements
911
- || Icmp6OutRouterAdvertisements
912
- ))) {
913
- do_icmp_router = CONFIG_ONDEMAND_YES;
914
- st = rrdset_find(RRD_TYPE_NET_SNMP6 ".icmprouter");
915
- if(!st) {
916
- st = rrdset_create(RRD_TYPE_NET_SNMP6, "icmprouter", NULL, "icmp", NULL, "IPv6 Router Messages", "messages/s", 10400, update_every, RRDSET_TYPE_LINE);
917
-
918
- rrddim_add(st, "InSolicits", NULL, 1, 1, RRDDIM_INCREMENTAL);
919
- rrddim_add(st, "OutSolicits", NULL, -1, 1, RRDDIM_INCREMENTAL);
920
- rrddim_add(st, "InAdvertisements", NULL, 1, 1, RRDDIM_INCREMENTAL);
921
- rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRDDIM_INCREMENTAL);
922
- }
923
- else rrdset_next(st);
924
-
925
- rrddim_set(st, "InSolicits", Icmp6InRouterSolicits);
926
- rrddim_set(st, "OutSolicits", Icmp6OutRouterSolicits);
927
- rrddim_set(st, "InAdvertisements", Icmp6InRouterAdvertisements);
928
- rrddim_set(st, "OutAdvertisements", Icmp6OutRouterAdvertisements);
929
- rrdset_done(st);
930
- }
931
-
932
- // --------------------------------------------------------------------
933
-
934
- if(do_icmp_neighbor == CONFIG_ONDEMAND_YES || (do_icmp_neighbor == CONFIG_ONDEMAND_ONDEMAND
935
- && (
936
- Icmp6InNeighborSolicits
937
- || Icmp6OutNeighborSolicits
938
- || Icmp6InNeighborAdvertisements
939
- || Icmp6OutNeighborAdvertisements
940
- ))) {
941
- do_icmp_neighbor = CONFIG_ONDEMAND_YES;
942
- st = rrdset_find(RRD_TYPE_NET_SNMP6 ".icmpneighbor");
943
- if(!st) {
944
- st = rrdset_create(RRD_TYPE_NET_SNMP6, "icmpneighbor", NULL, "icmp", NULL, "IPv6 Neighbor Messages", "messages/s", 10500, update_every, RRDSET_TYPE_LINE);
945
-
946
- rrddim_add(st, "InSolicits", NULL, 1, 1, RRDDIM_INCREMENTAL);
947
- rrddim_add(st, "OutSolicits", NULL, -1, 1, RRDDIM_INCREMENTAL);
948
- rrddim_add(st, "InAdvertisements", NULL, 1, 1, RRDDIM_INCREMENTAL);
949
- rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRDDIM_INCREMENTAL);
950
- }
951
- else rrdset_next(st);
952
-
953
- rrddim_set(st, "InSolicits", Icmp6InNeighborSolicits);
954
- rrddim_set(st, "OutSolicits", Icmp6OutNeighborSolicits);
955
- rrddim_set(st, "InAdvertisements", Icmp6InNeighborAdvertisements);
956
- rrddim_set(st, "OutAdvertisements", Icmp6OutNeighborAdvertisements);
957
- rrdset_done(st);
958
- }
959
-
960
- // --------------------------------------------------------------------
961
-
962
- if(do_icmp_mldv2 == CONFIG_ONDEMAND_YES || (do_icmp_mldv2 == CONFIG_ONDEMAND_ONDEMAND && (Icmp6InMLDv2Reports || Icmp6OutMLDv2Reports))) {
963
- do_icmp_mldv2 = CONFIG_ONDEMAND_YES;
964
- st = rrdset_find(RRD_TYPE_NET_SNMP6 ".icmpmldv2");
965
- if(!st) {
966
- st = rrdset_create(RRD_TYPE_NET_SNMP6, "icmpmldv2", NULL, "icmp", NULL, "IPv6 ICMP MLDv2 Reports", "reports/s", 10600, update_every, RRDSET_TYPE_LINE);
967
-
968
- rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
969
- rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
970
- }
971
- else rrdset_next(st);
972
-
973
- rrddim_set(st, "sent", Icmp6InMLDv2Reports);
974
- rrddim_set(st, "received", Icmp6OutMLDv2Reports);
975
- rrdset_done(st);
976
- }
977
-
978
- // --------------------------------------------------------------------
979
-
980
- if(do_icmp_types == CONFIG_ONDEMAND_YES || (do_icmp_types == CONFIG_ONDEMAND_ONDEMAND
981
- && (
982
- Icmp6InType1
983
- || Icmp6InType128
984
- || Icmp6InType129
985
- || Icmp6InType136
986
- || Icmp6OutType1
987
- || Icmp6OutType128
988
- || Icmp6OutType129
989
- || Icmp6OutType133
990
- || Icmp6OutType135
991
- || Icmp6OutType143
992
- ))) {
993
- do_icmp_types = CONFIG_ONDEMAND_YES;
994
- st = rrdset_find(RRD_TYPE_NET_SNMP6 ".icmptypes");
995
- if(!st) {
996
- st = rrdset_create(RRD_TYPE_NET_SNMP6, "icmptypes", NULL, "icmp", NULL, "IPv6 ICMP Types", "messages/s", 10700, update_every, RRDSET_TYPE_LINE);
997
-
998
- rrddim_add(st, "InType1", NULL, 1, 1, RRDDIM_INCREMENTAL);
999
- rrddim_add(st, "InType128", NULL, 1, 1, RRDDIM_INCREMENTAL);
1000
- rrddim_add(st, "InType129", NULL, 1, 1, RRDDIM_INCREMENTAL);
1001
- rrddim_add(st, "InType136", NULL, 1, 1, RRDDIM_INCREMENTAL);
1002
- rrddim_add(st, "OutType1", NULL, -1, 1, RRDDIM_INCREMENTAL);
1003
- rrddim_add(st, "OutType128", NULL, -1, 1, RRDDIM_INCREMENTAL);
1004
- rrddim_add(st, "OutType129", NULL, -1, 1, RRDDIM_INCREMENTAL);
1005
- rrddim_add(st, "OutType133", NULL, -1, 1, RRDDIM_INCREMENTAL);
1006
- rrddim_add(st, "OutType135", NULL, -1, 1, RRDDIM_INCREMENTAL);
1007
- rrddim_add(st, "OutType143", NULL, -1, 1, RRDDIM_INCREMENTAL);
1008
- }
1009
- else rrdset_next(st);
1010
-
1011
- rrddim_set(st, "InType1", Icmp6InType1);
1012
- rrddim_set(st, "InType128", Icmp6InType128);
1013
- rrddim_set(st, "InType129", Icmp6InType129);
1014
- rrddim_set(st, "InType136", Icmp6InType136);
1015
- rrddim_set(st, "OutType1", Icmp6OutType1);
1016
- rrddim_set(st, "OutType128", Icmp6OutType128);
1017
- rrddim_set(st, "OutType129", Icmp6OutType129);
1018
- rrddim_set(st, "OutType133", Icmp6OutType133);
1019
- rrddim_set(st, "OutType135", Icmp6OutType135);
1020
- rrddim_set(st, "OutType143", Icmp6OutType143);
1021
- rrdset_done(st);
1022
- }
1023
-
1024
- // --------------------------------------------------------------------
1025
-
1026
- if(do_ect == CONFIG_ONDEMAND_YES || (do_ect == CONFIG_ONDEMAND_ONDEMAND
1027
- && (
1028
- Ip6InNoECTPkts
1029
- || Ip6InECT1Pkts
1030
- || Ip6InECT0Pkts
1031
- || Ip6InCEPkts
1032
- ))) {
1033
- do_ect = CONFIG_ONDEMAND_YES;
1034
- st = rrdset_find(RRD_TYPE_NET_SNMP6 ".ect");
1035
- if(!st) {
1036
- st = rrdset_create(RRD_TYPE_NET_SNMP6, "ect", NULL, "packets", NULL, "IPv6 ECT Packets", "packets/s", 10800, update_every, RRDSET_TYPE_LINE);
1037
-
1038
- rrddim_add(st, "InNoECTPkts", NULL, 1, 1, RRDDIM_INCREMENTAL);
1039
- rrddim_add(st, "InECT1Pkts", NULL, 1, 1, RRDDIM_INCREMENTAL);
1040
- rrddim_add(st, "InECT0Pkts", NULL, 1, 1, RRDDIM_INCREMENTAL);
1041
- rrddim_add(st, "InCEPkts", NULL, 1, 1, RRDDIM_INCREMENTAL);
1042
- }
1043
- else rrdset_next(st);
1044
-
1045
- rrddim_set(st, "InNoECTPkts", Ip6InNoECTPkts);
1046
- rrddim_set(st, "InECT1Pkts", Ip6InECT1Pkts);
1047
- rrddim_set(st, "InECT0Pkts", Ip6InECT0Pkts);
1048
- rrddim_set(st, "InCEPkts", Ip6InCEPkts);
1049
- rrdset_done(st);
1050
- }
1051
-
1052
- return 0;
7
+ static procfile *ff = NULL;
8
+ static int gen_hashes = -1;
9
+
10
+ static int do_ip_packets = -1, do_ip_fragsout = -1, do_ip_fragsin = -1, do_ip_errors = -1,
11
+ do_udplite_packets = -1, do_udplite_errors = -1,
12
+ do_udp_packets = -1, do_udp_errors = -1,
13
+ do_bandwidth = -1, do_mcast = -1, do_bcast = -1, do_mcast_p = -1,
14
+ do_icmp = -1, do_icmp_redir = -1, do_icmp_errors = -1, do_icmp_echos = -1, do_icmp_groupmemb = -1,
15
+ do_icmp_router = -1, do_icmp_neighbor = -1, do_icmp_mldv2 = -1, do_icmp_types = -1, do_ect = -1;
16
+
17
+ static uint32_t hash_Ip6InReceives = -1;
18
+
19
+ static uint32_t hash_Ip6InHdrErrors = -1;
20
+ static uint32_t hash_Ip6InTooBigErrors = -1;
21
+ static uint32_t hash_Ip6InNoRoutes = -1;
22
+ static uint32_t hash_Ip6InAddrErrors = -1;
23
+ static uint32_t hash_Ip6InUnknownProtos = -1;
24
+ static uint32_t hash_Ip6InTruncatedPkts = -1;
25
+ static uint32_t hash_Ip6InDiscards = -1;
26
+ static uint32_t hash_Ip6InDelivers = -1;
27
+
28
+ static uint32_t hash_Ip6OutForwDatagrams = -1;
29
+ static uint32_t hash_Ip6OutRequests = -1;
30
+ static uint32_t hash_Ip6OutDiscards = -1;
31
+ static uint32_t hash_Ip6OutNoRoutes = -1;
32
+
33
+ static uint32_t hash_Ip6ReasmTimeout = -1;
34
+ static uint32_t hash_Ip6ReasmReqds = -1;
35
+ static uint32_t hash_Ip6ReasmOKs = -1;
36
+ static uint32_t hash_Ip6ReasmFails = -1;
37
+
38
+ static uint32_t hash_Ip6FragOKs = -1;
39
+ static uint32_t hash_Ip6FragFails = -1;
40
+ static uint32_t hash_Ip6FragCreates = -1;
41
+
42
+ static uint32_t hash_Ip6InMcastPkts = -1;
43
+ static uint32_t hash_Ip6OutMcastPkts = -1;
44
+
45
+ static uint32_t hash_Ip6InOctets = -1;
46
+ static uint32_t hash_Ip6OutOctets = -1;
47
+
48
+ static uint32_t hash_Ip6InMcastOctets = -1;
49
+ static uint32_t hash_Ip6OutMcastOctets = -1;
50
+ static uint32_t hash_Ip6InBcastOctets = -1;
51
+ static uint32_t hash_Ip6OutBcastOctets = -1;
52
+
53
+ static uint32_t hash_Ip6InNoECTPkts = -1;
54
+ static uint32_t hash_Ip6InECT1Pkts = -1;
55
+ static uint32_t hash_Ip6InECT0Pkts = -1;
56
+ static uint32_t hash_Ip6InCEPkts = -1;
57
+
58
+ static uint32_t hash_Icmp6InMsgs = -1;
59
+ static uint32_t hash_Icmp6InErrors = -1;
60
+ static uint32_t hash_Icmp6OutMsgs = -1;
61
+ static uint32_t hash_Icmp6OutErrors = -1;
62
+ static uint32_t hash_Icmp6InCsumErrors = -1;
63
+ static uint32_t hash_Icmp6InDestUnreachs = -1;
64
+ static uint32_t hash_Icmp6InPktTooBigs = -1;
65
+ static uint32_t hash_Icmp6InTimeExcds = -1;
66
+ static uint32_t hash_Icmp6InParmProblems = -1;
67
+ static uint32_t hash_Icmp6InEchos = -1;
68
+ static uint32_t hash_Icmp6InEchoReplies = -1;
69
+ static uint32_t hash_Icmp6InGroupMembQueries = -1;
70
+ static uint32_t hash_Icmp6InGroupMembResponses = -1;
71
+ static uint32_t hash_Icmp6InGroupMembReductions = -1;
72
+ static uint32_t hash_Icmp6InRouterSolicits = -1;
73
+ static uint32_t hash_Icmp6InRouterAdvertisements = -1;
74
+ static uint32_t hash_Icmp6InNeighborSolicits = -1;
75
+ static uint32_t hash_Icmp6InNeighborAdvertisements = -1;
76
+ static uint32_t hash_Icmp6InRedirects = -1;
77
+ static uint32_t hash_Icmp6InMLDv2Reports = -1;
78
+ static uint32_t hash_Icmp6OutDestUnreachs = -1;
79
+ static uint32_t hash_Icmp6OutPktTooBigs = -1;
80
+ static uint32_t hash_Icmp6OutTimeExcds = -1;
81
+ static uint32_t hash_Icmp6OutParmProblems = -1;
82
+ static uint32_t hash_Icmp6OutEchos = -1;
83
+ static uint32_t hash_Icmp6OutEchoReplies = -1;
84
+ static uint32_t hash_Icmp6OutGroupMembQueries = -1;
85
+ static uint32_t hash_Icmp6OutGroupMembResponses = -1;
86
+ static uint32_t hash_Icmp6OutGroupMembReductions = -1;
87
+ static uint32_t hash_Icmp6OutRouterSolicits = -1;
88
+ static uint32_t hash_Icmp6OutRouterAdvertisements = -1;
89
+ static uint32_t hash_Icmp6OutNeighborSolicits = -1;
90
+ static uint32_t hash_Icmp6OutNeighborAdvertisements = -1;
91
+ static uint32_t hash_Icmp6OutRedirects = -1;
92
+ static uint32_t hash_Icmp6OutMLDv2Reports = -1;
93
+ static uint32_t hash_Icmp6InType1 = -1;
94
+ static uint32_t hash_Icmp6InType128 = -1;
95
+ static uint32_t hash_Icmp6InType129 = -1;
96
+ static uint32_t hash_Icmp6InType136 = -1;
97
+ static uint32_t hash_Icmp6OutType1 = -1;
98
+ static uint32_t hash_Icmp6OutType128 = -1;
99
+ static uint32_t hash_Icmp6OutType129 = -1;
100
+ static uint32_t hash_Icmp6OutType133 = -1;
101
+ static uint32_t hash_Icmp6OutType135 = -1;
102
+ static uint32_t hash_Icmp6OutType143 = -1;
103
+
104
+ static uint32_t hash_Udp6InDatagrams = -1;
105
+ static uint32_t hash_Udp6NoPorts = -1;
106
+ static uint32_t hash_Udp6InErrors = -1;
107
+ static uint32_t hash_Udp6OutDatagrams = -1;
108
+ static uint32_t hash_Udp6RcvbufErrors = -1;
109
+ static uint32_t hash_Udp6SndbufErrors = -1;
110
+ static uint32_t hash_Udp6InCsumErrors = -1;
111
+ static uint32_t hash_Udp6IgnoredMulti = -1;
112
+
113
+ static uint32_t hash_UdpLite6InDatagrams = -1;
114
+ static uint32_t hash_UdpLite6NoPorts = -1;
115
+ static uint32_t hash_UdpLite6InErrors = -1;
116
+ static uint32_t hash_UdpLite6OutDatagrams = -1;
117
+ static uint32_t hash_UdpLite6RcvbufErrors = -1;
118
+ static uint32_t hash_UdpLite6SndbufErrors = -1;
119
+ static uint32_t hash_UdpLite6InCsumErrors = -1;
120
+
121
+ if(gen_hashes != 1) {
122
+ gen_hashes = 1;
123
+ hash_Ip6InReceives = simple_hash("Ip6InReceives");
124
+ hash_Ip6InHdrErrors = simple_hash("Ip6InHdrErrors");
125
+ hash_Ip6InTooBigErrors = simple_hash("Ip6InTooBigErrors");
126
+ hash_Ip6InNoRoutes = simple_hash("Ip6InNoRoutes");
127
+ hash_Ip6InAddrErrors = simple_hash("Ip6InAddrErrors");
128
+ hash_Ip6InUnknownProtos = simple_hash("Ip6InUnknownProtos");
129
+ hash_Ip6InTruncatedPkts = simple_hash("Ip6InTruncatedPkts");
130
+ hash_Ip6InDiscards = simple_hash("Ip6InDiscards");
131
+ hash_Ip6InDelivers = simple_hash("Ip6InDelivers");
132
+ hash_Ip6OutForwDatagrams = simple_hash("Ip6OutForwDatagrams");
133
+ hash_Ip6OutRequests = simple_hash("Ip6OutRequests");
134
+ hash_Ip6OutDiscards = simple_hash("Ip6OutDiscards");
135
+ hash_Ip6OutNoRoutes = simple_hash("Ip6OutNoRoutes");
136
+ hash_Ip6ReasmTimeout = simple_hash("Ip6ReasmTimeout");
137
+ hash_Ip6ReasmReqds = simple_hash("Ip6ReasmReqds");
138
+ hash_Ip6ReasmOKs = simple_hash("Ip6ReasmOKs");
139
+ hash_Ip6ReasmFails = simple_hash("Ip6ReasmFails");
140
+ hash_Ip6FragOKs = simple_hash("Ip6FragOKs");
141
+ hash_Ip6FragFails = simple_hash("Ip6FragFails");
142
+ hash_Ip6FragCreates = simple_hash("Ip6FragCreates");
143
+ hash_Ip6InMcastPkts = simple_hash("Ip6InMcastPkts");
144
+ hash_Ip6OutMcastPkts = simple_hash("Ip6OutMcastPkts");
145
+ hash_Ip6InOctets = simple_hash("Ip6InOctets");
146
+ hash_Ip6OutOctets = simple_hash("Ip6OutOctets");
147
+ hash_Ip6InMcastOctets = simple_hash("Ip6InMcastOctets");
148
+ hash_Ip6OutMcastOctets = simple_hash("Ip6OutMcastOctets");
149
+ hash_Ip6InBcastOctets = simple_hash("Ip6InBcastOctets");
150
+ hash_Ip6OutBcastOctets = simple_hash("Ip6OutBcastOctets");
151
+ hash_Ip6InNoECTPkts = simple_hash("Ip6InNoECTPkts");
152
+ hash_Ip6InECT1Pkts = simple_hash("Ip6InECT1Pkts");
153
+ hash_Ip6InECT0Pkts = simple_hash("Ip6InECT0Pkts");
154
+ hash_Ip6InCEPkts = simple_hash("Ip6InCEPkts");
155
+ hash_Icmp6InMsgs = simple_hash("Icmp6InMsgs");
156
+ hash_Icmp6InErrors = simple_hash("Icmp6InErrors");
157
+ hash_Icmp6OutMsgs = simple_hash("Icmp6OutMsgs");
158
+ hash_Icmp6OutErrors = simple_hash("Icmp6OutErrors");
159
+ hash_Icmp6InCsumErrors = simple_hash("Icmp6InCsumErrors");
160
+ hash_Icmp6InDestUnreachs = simple_hash("Icmp6InDestUnreachs");
161
+ hash_Icmp6InPktTooBigs = simple_hash("Icmp6InPktTooBigs");
162
+ hash_Icmp6InTimeExcds = simple_hash("Icmp6InTimeExcds");
163
+ hash_Icmp6InParmProblems = simple_hash("Icmp6InParmProblems");
164
+ hash_Icmp6InEchos = simple_hash("Icmp6InEchos");
165
+ hash_Icmp6InEchoReplies = simple_hash("Icmp6InEchoReplies");
166
+ hash_Icmp6InGroupMembQueries = simple_hash("Icmp6InGroupMembQueries");
167
+ hash_Icmp6InGroupMembResponses = simple_hash("Icmp6InGroupMembResponses");
168
+ hash_Icmp6InGroupMembReductions = simple_hash("Icmp6InGroupMembReductions");
169
+ hash_Icmp6InRouterSolicits = simple_hash("Icmp6InRouterSolicits");
170
+ hash_Icmp6InRouterAdvertisements = simple_hash("Icmp6InRouterAdvertisements");
171
+ hash_Icmp6InNeighborSolicits = simple_hash("Icmp6InNeighborSolicits");
172
+ hash_Icmp6InNeighborAdvertisements = simple_hash("Icmp6InNeighborAdvertisements");
173
+ hash_Icmp6InRedirects = simple_hash("Icmp6InRedirects");
174
+ hash_Icmp6InMLDv2Reports = simple_hash("Icmp6InMLDv2Reports");
175
+ hash_Icmp6OutDestUnreachs = simple_hash("Icmp6OutDestUnreachs");
176
+ hash_Icmp6OutPktTooBigs = simple_hash("Icmp6OutPktTooBigs");
177
+ hash_Icmp6OutTimeExcds = simple_hash("Icmp6OutTimeExcds");
178
+ hash_Icmp6OutParmProblems = simple_hash("Icmp6OutParmProblems");
179
+ hash_Icmp6OutEchos = simple_hash("Icmp6OutEchos");
180
+ hash_Icmp6OutEchoReplies = simple_hash("Icmp6OutEchoReplies");
181
+ hash_Icmp6OutGroupMembQueries = simple_hash("Icmp6OutGroupMembQueries");
182
+ hash_Icmp6OutGroupMembResponses = simple_hash("Icmp6OutGroupMembResponses");
183
+ hash_Icmp6OutGroupMembReductions = simple_hash("Icmp6OutGroupMembReductions");
184
+ hash_Icmp6OutRouterSolicits = simple_hash("Icmp6OutRouterSolicits");
185
+ hash_Icmp6OutRouterAdvertisements = simple_hash("Icmp6OutRouterAdvertisements");
186
+ hash_Icmp6OutNeighborSolicits = simple_hash("Icmp6OutNeighborSolicits");
187
+ hash_Icmp6OutNeighborAdvertisements = simple_hash("Icmp6OutNeighborAdvertisements");
188
+ hash_Icmp6OutRedirects = simple_hash("Icmp6OutRedirects");
189
+ hash_Icmp6OutMLDv2Reports = simple_hash("Icmp6OutMLDv2Reports");
190
+ hash_Icmp6InType1 = simple_hash("Icmp6InType1");
191
+ hash_Icmp6InType128 = simple_hash("Icmp6InType128");
192
+ hash_Icmp6InType129 = simple_hash("Icmp6InType129");
193
+ hash_Icmp6InType136 = simple_hash("Icmp6InType136");
194
+ hash_Icmp6OutType1 = simple_hash("Icmp6OutType1");
195
+ hash_Icmp6OutType128 = simple_hash("Icmp6OutType128");
196
+ hash_Icmp6OutType129 = simple_hash("Icmp6OutType129");
197
+ hash_Icmp6OutType133 = simple_hash("Icmp6OutType133");
198
+ hash_Icmp6OutType135 = simple_hash("Icmp6OutType135");
199
+ hash_Icmp6OutType143 = simple_hash("Icmp6OutType143");
200
+ hash_Udp6InDatagrams = simple_hash("Udp6InDatagrams");
201
+ hash_Udp6NoPorts = simple_hash("Udp6NoPorts");
202
+ hash_Udp6InErrors = simple_hash("Udp6InErrors");
203
+ hash_Udp6OutDatagrams = simple_hash("Udp6OutDatagrams");
204
+ hash_Udp6RcvbufErrors = simple_hash("Udp6RcvbufErrors");
205
+ hash_Udp6SndbufErrors = simple_hash("Udp6SndbufErrors");
206
+ hash_Udp6InCsumErrors = simple_hash("Udp6InCsumErrors");
207
+ hash_Udp6IgnoredMulti = simple_hash("Udp6IgnoredMulti");
208
+ hash_UdpLite6InDatagrams = simple_hash("UdpLite6InDatagrams");
209
+ hash_UdpLite6NoPorts = simple_hash("UdpLite6NoPorts");
210
+ hash_UdpLite6InErrors = simple_hash("UdpLite6InErrors");
211
+ hash_UdpLite6OutDatagrams = simple_hash("UdpLite6OutDatagrams");
212
+ hash_UdpLite6RcvbufErrors = simple_hash("UdpLite6RcvbufErrors");
213
+ hash_UdpLite6SndbufErrors = simple_hash("UdpLite6SndbufErrors");
214
+ hash_UdpLite6InCsumErrors = simple_hash("UdpLite6InCsumErrors");
215
+ }
216
+
217
+ if(do_ip_packets == -1) do_ip_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 packets", CONFIG_ONDEMAND_ONDEMAND);
218
+ if(do_ip_fragsout == -1) do_ip_fragsout = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 fragments sent", CONFIG_ONDEMAND_ONDEMAND);
219
+ if(do_ip_fragsin == -1) do_ip_fragsin = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 fragments assembly", CONFIG_ONDEMAND_ONDEMAND);
220
+ if(do_ip_errors == -1) do_ip_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 errors", CONFIG_ONDEMAND_ONDEMAND);
221
+ if(do_udp_packets == -1) do_udp_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDP packets", CONFIG_ONDEMAND_ONDEMAND);
222
+ if(do_udp_errors == -1) do_udp_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDP errors", CONFIG_ONDEMAND_ONDEMAND);
223
+ if(do_udplite_packets == -1) do_udplite_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDPlite packets", CONFIG_ONDEMAND_ONDEMAND);
224
+ if(do_udplite_errors == -1) do_udplite_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDPlite errors", CONFIG_ONDEMAND_ONDEMAND);
225
+ if(do_bandwidth == -1) do_bandwidth = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "bandwidth", CONFIG_ONDEMAND_ONDEMAND);
226
+ if(do_mcast == -1) do_mcast = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "multicast bandwidth", CONFIG_ONDEMAND_ONDEMAND);
227
+ if(do_bcast == -1) do_bcast = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "broadcast bandwidth", CONFIG_ONDEMAND_ONDEMAND);
228
+ if(do_mcast_p == -1) do_mcast_p = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "multicast packets", CONFIG_ONDEMAND_ONDEMAND);
229
+ if(do_icmp == -1) do_icmp = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp", CONFIG_ONDEMAND_ONDEMAND);
230
+ if(do_icmp_redir == -1) do_icmp_redir = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp redirects", CONFIG_ONDEMAND_ONDEMAND);
231
+ if(do_icmp_errors == -1) do_icmp_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp errors", CONFIG_ONDEMAND_ONDEMAND);
232
+ if(do_icmp_echos == -1) do_icmp_echos = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp echos", CONFIG_ONDEMAND_ONDEMAND);
233
+ if(do_icmp_groupmemb == -1) do_icmp_groupmemb = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp group membership", CONFIG_ONDEMAND_ONDEMAND);
234
+ if(do_icmp_router == -1) do_icmp_router = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp router", CONFIG_ONDEMAND_ONDEMAND);
235
+ if(do_icmp_neighbor == -1) do_icmp_neighbor = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp neighbor", CONFIG_ONDEMAND_ONDEMAND);
236
+ if(do_icmp_mldv2 == -1) do_icmp_mldv2 = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp mldv2", CONFIG_ONDEMAND_ONDEMAND);
237
+ if(do_icmp_types == -1) do_icmp_types = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp types", CONFIG_ONDEMAND_ONDEMAND);
238
+ if(do_ect == -1) do_ect = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ect", CONFIG_ONDEMAND_ONDEMAND);
239
+
240
+ if(dt) {};
241
+
242
+ if(!ff) {
243
+ char filename[FILENAME_MAX + 1];
244
+ snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/snmp6");
245
+ ff = procfile_open(config_get("plugin:proc:/proc/net/snmp6", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
246
+ }
247
+ if(!ff) return 1;
248
+
249
+ ff = procfile_readall(ff);
250
+ if(!ff) return 0; // we return 0, so that we will retry to open it next time
251
+
252
+ uint32_t lines = procfile_lines(ff), l;
253
+ uint32_t words;
254
+
255
+ unsigned long long Ip6InReceives = 0ULL;
256
+ unsigned long long Ip6InHdrErrors = 0ULL;
257
+ unsigned long long Ip6InTooBigErrors = 0ULL;
258
+ unsigned long long Ip6InNoRoutes = 0ULL;
259
+ unsigned long long Ip6InAddrErrors = 0ULL;
260
+ unsigned long long Ip6InUnknownProtos = 0ULL;
261
+ unsigned long long Ip6InTruncatedPkts = 0ULL;
262
+ unsigned long long Ip6InDiscards = 0ULL;
263
+ unsigned long long Ip6InDelivers = 0ULL;
264
+ unsigned long long Ip6OutForwDatagrams = 0ULL;
265
+ unsigned long long Ip6OutRequests = 0ULL;
266
+ unsigned long long Ip6OutDiscards = 0ULL;
267
+ unsigned long long Ip6OutNoRoutes = 0ULL;
268
+ unsigned long long Ip6ReasmTimeout = 0ULL;
269
+ unsigned long long Ip6ReasmReqds = 0ULL;
270
+ unsigned long long Ip6ReasmOKs = 0ULL;
271
+ unsigned long long Ip6ReasmFails = 0ULL;
272
+ unsigned long long Ip6FragOKs = 0ULL;
273
+ unsigned long long Ip6FragFails = 0ULL;
274
+ unsigned long long Ip6FragCreates = 0ULL;
275
+ unsigned long long Ip6InMcastPkts = 0ULL;
276
+ unsigned long long Ip6OutMcastPkts = 0ULL;
277
+ unsigned long long Ip6InOctets = 0ULL;
278
+ unsigned long long Ip6OutOctets = 0ULL;
279
+ unsigned long long Ip6InMcastOctets = 0ULL;
280
+ unsigned long long Ip6OutMcastOctets = 0ULL;
281
+ unsigned long long Ip6InBcastOctets = 0ULL;
282
+ unsigned long long Ip6OutBcastOctets = 0ULL;
283
+ unsigned long long Ip6InNoECTPkts = 0ULL;
284
+ unsigned long long Ip6InECT1Pkts = 0ULL;
285
+ unsigned long long Ip6InECT0Pkts = 0ULL;
286
+ unsigned long long Ip6InCEPkts = 0ULL;
287
+ unsigned long long Icmp6InMsgs = 0ULL;
288
+ unsigned long long Icmp6InErrors = 0ULL;
289
+ unsigned long long Icmp6OutMsgs = 0ULL;
290
+ unsigned long long Icmp6OutErrors = 0ULL;
291
+ unsigned long long Icmp6InCsumErrors = 0ULL;
292
+ unsigned long long Icmp6InDestUnreachs = 0ULL;
293
+ unsigned long long Icmp6InPktTooBigs = 0ULL;
294
+ unsigned long long Icmp6InTimeExcds = 0ULL;
295
+ unsigned long long Icmp6InParmProblems = 0ULL;
296
+ unsigned long long Icmp6InEchos = 0ULL;
297
+ unsigned long long Icmp6InEchoReplies = 0ULL;
298
+ unsigned long long Icmp6InGroupMembQueries = 0ULL;
299
+ unsigned long long Icmp6InGroupMembResponses = 0ULL;
300
+ unsigned long long Icmp6InGroupMembReductions = 0ULL;
301
+ unsigned long long Icmp6InRouterSolicits = 0ULL;
302
+ unsigned long long Icmp6InRouterAdvertisements = 0ULL;
303
+ unsigned long long Icmp6InNeighborSolicits = 0ULL;
304
+ unsigned long long Icmp6InNeighborAdvertisements = 0ULL;
305
+ unsigned long long Icmp6InRedirects = 0ULL;
306
+ unsigned long long Icmp6InMLDv2Reports = 0ULL;
307
+ unsigned long long Icmp6OutDestUnreachs = 0ULL;
308
+ unsigned long long Icmp6OutPktTooBigs = 0ULL;
309
+ unsigned long long Icmp6OutTimeExcds = 0ULL;
310
+ unsigned long long Icmp6OutParmProblems = 0ULL;
311
+ unsigned long long Icmp6OutEchos = 0ULL;
312
+ unsigned long long Icmp6OutEchoReplies = 0ULL;
313
+ unsigned long long Icmp6OutGroupMembQueries = 0ULL;
314
+ unsigned long long Icmp6OutGroupMembResponses = 0ULL;
315
+ unsigned long long Icmp6OutGroupMembReductions = 0ULL;
316
+ unsigned long long Icmp6OutRouterSolicits = 0ULL;
317
+ unsigned long long Icmp6OutRouterAdvertisements = 0ULL;
318
+ unsigned long long Icmp6OutNeighborSolicits = 0ULL;
319
+ unsigned long long Icmp6OutNeighborAdvertisements = 0ULL;
320
+ unsigned long long Icmp6OutRedirects = 0ULL;
321
+ unsigned long long Icmp6OutMLDv2Reports = 0ULL;
322
+ unsigned long long Icmp6InType1 = 0ULL;
323
+ unsigned long long Icmp6InType128 = 0ULL;
324
+ unsigned long long Icmp6InType129 = 0ULL;
325
+ unsigned long long Icmp6InType136 = 0ULL;
326
+ unsigned long long Icmp6OutType1 = 0ULL;
327
+ unsigned long long Icmp6OutType128 = 0ULL;
328
+ unsigned long long Icmp6OutType129 = 0ULL;
329
+ unsigned long long Icmp6OutType133 = 0ULL;
330
+ unsigned long long Icmp6OutType135 = 0ULL;
331
+ unsigned long long Icmp6OutType143 = 0ULL;
332
+ unsigned long long Udp6InDatagrams = 0ULL;
333
+ unsigned long long Udp6NoPorts = 0ULL;
334
+ unsigned long long Udp6InErrors = 0ULL;
335
+ unsigned long long Udp6OutDatagrams = 0ULL;
336
+ unsigned long long Udp6RcvbufErrors = 0ULL;
337
+ unsigned long long Udp6SndbufErrors = 0ULL;
338
+ unsigned long long Udp6InCsumErrors = 0ULL;
339
+ unsigned long long Udp6IgnoredMulti = 0ULL;
340
+ unsigned long long UdpLite6InDatagrams = 0ULL;
341
+ unsigned long long UdpLite6NoPorts = 0ULL;
342
+ unsigned long long UdpLite6InErrors = 0ULL;
343
+ unsigned long long UdpLite6OutDatagrams = 0ULL;
344
+ unsigned long long UdpLite6RcvbufErrors = 0ULL;
345
+ unsigned long long UdpLite6SndbufErrors = 0ULL;
346
+ unsigned long long UdpLite6InCsumErrors = 0ULL;
347
+
348
+ for(l = 0; l < lines ;l++) {
349
+ words = procfile_linewords(ff, l);
350
+ if(words < 2) {
351
+ if(words) error("Cannot read /proc/net/snmp6 line %u. Expected 2 params, read %u.", l, words);
352
+ continue;
353
+ }
354
+
355
+ char *name = procfile_lineword(ff, l, 0);
356
+ char * value = procfile_lineword(ff, l, 1);
357
+ if(!name || !*name || !value || !*value) continue;
358
+
359
+ uint32_t hash = simple_hash(name);
360
+
361
+ if(0) ;
362
+ else if(hash == hash_Ip6InReceives && strcmp(name, "Ip6InReceives") == 0) Ip6InReceives = strtoull(value, NULL, 10);
363
+ else if(hash == hash_Ip6InHdrErrors && strcmp(name, "Ip6InHdrErrors") == 0) Ip6InHdrErrors = strtoull(value, NULL, 10);
364
+ else if(hash == hash_Ip6InTooBigErrors && strcmp(name, "Ip6InTooBigErrors") == 0) Ip6InTooBigErrors = strtoull(value, NULL, 10);
365
+ else if(hash == hash_Ip6InNoRoutes && strcmp(name, "Ip6InNoRoutes") == 0) Ip6InNoRoutes = strtoull(value, NULL, 10);
366
+ else if(hash == hash_Ip6InAddrErrors && strcmp(name, "Ip6InAddrErrors") == 0) Ip6InAddrErrors = strtoull(value, NULL, 10);
367
+ else if(hash == hash_Ip6InUnknownProtos && strcmp(name, "Ip6InUnknownProtos") == 0) Ip6InUnknownProtos = strtoull(value, NULL, 10);
368
+ else if(hash == hash_Ip6InTruncatedPkts && strcmp(name, "Ip6InTruncatedPkts") == 0) Ip6InTruncatedPkts = strtoull(value, NULL, 10);
369
+ else if(hash == hash_Ip6InDiscards && strcmp(name, "Ip6InDiscards") == 0) Ip6InDiscards = strtoull(value, NULL, 10);
370
+ else if(hash == hash_Ip6InDelivers && strcmp(name, "Ip6InDelivers") == 0) Ip6InDelivers = strtoull(value, NULL, 10);
371
+ else if(hash == hash_Ip6OutForwDatagrams && strcmp(name, "Ip6OutForwDatagrams") == 0) Ip6OutForwDatagrams = strtoull(value, NULL, 10);
372
+ else if(hash == hash_Ip6OutRequests && strcmp(name, "Ip6OutRequests") == 0) Ip6OutRequests = strtoull(value, NULL, 10);
373
+ else if(hash == hash_Ip6OutDiscards && strcmp(name, "Ip6OutDiscards") == 0) Ip6OutDiscards = strtoull(value, NULL, 10);
374
+ else if(hash == hash_Ip6OutNoRoutes && strcmp(name, "Ip6OutNoRoutes") == 0) Ip6OutNoRoutes = strtoull(value, NULL, 10);
375
+ else if(hash == hash_Ip6ReasmTimeout && strcmp(name, "Ip6ReasmTimeout") == 0) Ip6ReasmTimeout = strtoull(value, NULL, 10);
376
+ else if(hash == hash_Ip6ReasmReqds && strcmp(name, "Ip6ReasmReqds") == 0) Ip6ReasmReqds = strtoull(value, NULL, 10);
377
+ else if(hash == hash_Ip6ReasmOKs && strcmp(name, "Ip6ReasmOKs") == 0) Ip6ReasmOKs = strtoull(value, NULL, 10);
378
+ else if(hash == hash_Ip6ReasmFails && strcmp(name, "Ip6ReasmFails") == 0) Ip6ReasmFails = strtoull(value, NULL, 10);
379
+ else if(hash == hash_Ip6FragOKs && strcmp(name, "Ip6FragOKs") == 0) Ip6FragOKs = strtoull(value, NULL, 10);
380
+ else if(hash == hash_Ip6FragFails && strcmp(name, "Ip6FragFails") == 0) Ip6FragFails = strtoull(value, NULL, 10);
381
+ else if(hash == hash_Ip6FragCreates && strcmp(name, "Ip6FragCreates") == 0) Ip6FragCreates = strtoull(value, NULL, 10);
382
+ else if(hash == hash_Ip6InMcastPkts && strcmp(name, "Ip6InMcastPkts") == 0) Ip6InMcastPkts = strtoull(value, NULL, 10);
383
+ else if(hash == hash_Ip6OutMcastPkts && strcmp(name, "Ip6OutMcastPkts") == 0) Ip6OutMcastPkts = strtoull(value, NULL, 10);
384
+ else if(hash == hash_Ip6InOctets && strcmp(name, "Ip6InOctets") == 0) Ip6InOctets = strtoull(value, NULL, 10);
385
+ else if(hash == hash_Ip6OutOctets && strcmp(name, "Ip6OutOctets") == 0) Ip6OutOctets = strtoull(value, NULL, 10);
386
+ else if(hash == hash_Ip6InMcastOctets && strcmp(name, "Ip6InMcastOctets") == 0) Ip6InMcastOctets = strtoull(value, NULL, 10);
387
+ else if(hash == hash_Ip6OutMcastOctets && strcmp(name, "Ip6OutMcastOctets") == 0) Ip6OutMcastOctets = strtoull(value, NULL, 10);
388
+ else if(hash == hash_Ip6InBcastOctets && strcmp(name, "Ip6InBcastOctets") == 0) Ip6InBcastOctets = strtoull(value, NULL, 10);
389
+ else if(hash == hash_Ip6OutBcastOctets && strcmp(name, "Ip6OutBcastOctets") == 0) Ip6OutBcastOctets = strtoull(value, NULL, 10);
390
+ else if(hash == hash_Ip6InNoECTPkts && strcmp(name, "Ip6InNoECTPkts") == 0) Ip6InNoECTPkts = strtoull(value, NULL, 10);
391
+ else if(hash == hash_Ip6InECT1Pkts && strcmp(name, "Ip6InECT1Pkts") == 0) Ip6InECT1Pkts = strtoull(value, NULL, 10);
392
+ else if(hash == hash_Ip6InECT0Pkts && strcmp(name, "Ip6InECT0Pkts") == 0) Ip6InECT0Pkts = strtoull(value, NULL, 10);
393
+ else if(hash == hash_Ip6InCEPkts && strcmp(name, "Ip6InCEPkts") == 0) Ip6InCEPkts = strtoull(value, NULL, 10);
394
+ else if(hash == hash_Icmp6InMsgs && strcmp(name, "Icmp6InMsgs") == 0) Icmp6InMsgs = strtoull(value, NULL, 10);
395
+ else if(hash == hash_Icmp6InErrors && strcmp(name, "Icmp6InErrors") == 0) Icmp6InErrors = strtoull(value, NULL, 10);
396
+ else if(hash == hash_Icmp6OutMsgs && strcmp(name, "Icmp6OutMsgs") == 0) Icmp6OutMsgs = strtoull(value, NULL, 10);
397
+ else if(hash == hash_Icmp6OutErrors && strcmp(name, "Icmp6OutErrors") == 0) Icmp6OutErrors = strtoull(value, NULL, 10);
398
+ else if(hash == hash_Icmp6InCsumErrors && strcmp(name, "Icmp6InCsumErrors") == 0) Icmp6InCsumErrors = strtoull(value, NULL, 10);
399
+ else if(hash == hash_Icmp6InDestUnreachs && strcmp(name, "Icmp6InDestUnreachs") == 0) Icmp6InDestUnreachs = strtoull(value, NULL, 10);
400
+ else if(hash == hash_Icmp6InPktTooBigs && strcmp(name, "Icmp6InPktTooBigs") == 0) Icmp6InPktTooBigs = strtoull(value, NULL, 10);
401
+ else if(hash == hash_Icmp6InTimeExcds && strcmp(name, "Icmp6InTimeExcds") == 0) Icmp6InTimeExcds = strtoull(value, NULL, 10);
402
+ else if(hash == hash_Icmp6InParmProblems && strcmp(name, "Icmp6InParmProblems") == 0) Icmp6InParmProblems = strtoull(value, NULL, 10);
403
+ else if(hash == hash_Icmp6InEchos && strcmp(name, "Icmp6InEchos") == 0) Icmp6InEchos = strtoull(value, NULL, 10);
404
+ else if(hash == hash_Icmp6InEchoReplies && strcmp(name, "Icmp6InEchoReplies") == 0) Icmp6InEchoReplies = strtoull(value, NULL, 10);
405
+ else if(hash == hash_Icmp6InGroupMembQueries && strcmp(name, "Icmp6InGroupMembQueries") == 0) Icmp6InGroupMembQueries = strtoull(value, NULL, 10);
406
+ else if(hash == hash_Icmp6InGroupMembResponses && strcmp(name, "Icmp6InGroupMembResponses") == 0) Icmp6InGroupMembResponses = strtoull(value, NULL, 10);
407
+ else if(hash == hash_Icmp6InGroupMembReductions && strcmp(name, "Icmp6InGroupMembReductions") == 0) Icmp6InGroupMembReductions = strtoull(value, NULL, 10);
408
+ else if(hash == hash_Icmp6InRouterSolicits && strcmp(name, "Icmp6InRouterSolicits") == 0) Icmp6InRouterSolicits = strtoull(value, NULL, 10);
409
+ else if(hash == hash_Icmp6InRouterAdvertisements && strcmp(name, "Icmp6InRouterAdvertisements") == 0) Icmp6InRouterAdvertisements = strtoull(value, NULL, 10);
410
+ else if(hash == hash_Icmp6InNeighborSolicits && strcmp(name, "Icmp6InNeighborSolicits") == 0) Icmp6InNeighborSolicits = strtoull(value, NULL, 10);
411
+ else if(hash == hash_Icmp6InNeighborAdvertisements && strcmp(name, "Icmp6InNeighborAdvertisements") == 0) Icmp6InNeighborAdvertisements = strtoull(value, NULL, 10);
412
+ else if(hash == hash_Icmp6InRedirects && strcmp(name, "Icmp6InRedirects") == 0) Icmp6InRedirects = strtoull(value, NULL, 10);
413
+ else if(hash == hash_Icmp6InMLDv2Reports && strcmp(name, "Icmp6InMLDv2Reports") == 0) Icmp6InMLDv2Reports = strtoull(value, NULL, 10);
414
+ else if(hash == hash_Icmp6OutDestUnreachs && strcmp(name, "Icmp6OutDestUnreachs") == 0) Icmp6OutDestUnreachs = strtoull(value, NULL, 10);
415
+ else if(hash == hash_Icmp6OutPktTooBigs && strcmp(name, "Icmp6OutPktTooBigs") == 0) Icmp6OutPktTooBigs = strtoull(value, NULL, 10);
416
+ else if(hash == hash_Icmp6OutTimeExcds && strcmp(name, "Icmp6OutTimeExcds") == 0) Icmp6OutTimeExcds = strtoull(value, NULL, 10);
417
+ else if(hash == hash_Icmp6OutParmProblems && strcmp(name, "Icmp6OutParmProblems") == 0) Icmp6OutParmProblems = strtoull(value, NULL, 10);
418
+ else if(hash == hash_Icmp6OutEchos && strcmp(name, "Icmp6OutEchos") == 0) Icmp6OutEchos = strtoull(value, NULL, 10);
419
+ else if(hash == hash_Icmp6OutEchoReplies && strcmp(name, "Icmp6OutEchoReplies") == 0) Icmp6OutEchoReplies = strtoull(value, NULL, 10);
420
+ else if(hash == hash_Icmp6OutGroupMembQueries && strcmp(name, "Icmp6OutGroupMembQueries") == 0) Icmp6OutGroupMembQueries = strtoull(value, NULL, 10);
421
+ else if(hash == hash_Icmp6OutGroupMembResponses && strcmp(name, "Icmp6OutGroupMembResponses") == 0) Icmp6OutGroupMembResponses = strtoull(value, NULL, 10);
422
+ else if(hash == hash_Icmp6OutGroupMembReductions && strcmp(name, "Icmp6OutGroupMembReductions") == 0) Icmp6OutGroupMembReductions = strtoull(value, NULL, 10);
423
+ else if(hash == hash_Icmp6OutRouterSolicits && strcmp(name, "Icmp6OutRouterSolicits") == 0) Icmp6OutRouterSolicits = strtoull(value, NULL, 10);
424
+ else if(hash == hash_Icmp6OutRouterAdvertisements && strcmp(name, "Icmp6OutRouterAdvertisements") == 0) Icmp6OutRouterAdvertisements = strtoull(value, NULL, 10);
425
+ else if(hash == hash_Icmp6OutNeighborSolicits && strcmp(name, "Icmp6OutNeighborSolicits") == 0) Icmp6OutNeighborSolicits = strtoull(value, NULL, 10);
426
+ else if(hash == hash_Icmp6OutNeighborAdvertisements && strcmp(name, "Icmp6OutNeighborAdvertisements") == 0) Icmp6OutNeighborAdvertisements = strtoull(value, NULL, 10);
427
+ else if(hash == hash_Icmp6OutRedirects && strcmp(name, "Icmp6OutRedirects") == 0) Icmp6OutRedirects = strtoull(value, NULL, 10);
428
+ else if(hash == hash_Icmp6OutMLDv2Reports && strcmp(name, "Icmp6OutMLDv2Reports") == 0) Icmp6OutMLDv2Reports = strtoull(value, NULL, 10);
429
+ else if(hash == hash_Icmp6InType1 && strcmp(name, "Icmp6InType1") == 0) Icmp6InType1 = strtoull(value, NULL, 10);
430
+ else if(hash == hash_Icmp6InType128 && strcmp(name, "Icmp6InType128") == 0) Icmp6InType128 = strtoull(value, NULL, 10);
431
+ else if(hash == hash_Icmp6InType129 && strcmp(name, "Icmp6InType129") == 0) Icmp6InType129 = strtoull(value, NULL, 10);
432
+ else if(hash == hash_Icmp6InType136 && strcmp(name, "Icmp6InType136") == 0) Icmp6InType136 = strtoull(value, NULL, 10);
433
+ else if(hash == hash_Icmp6OutType1 && strcmp(name, "Icmp6OutType1") == 0) Icmp6OutType1 = strtoull(value, NULL, 10);
434
+ else if(hash == hash_Icmp6OutType128 && strcmp(name, "Icmp6OutType128") == 0) Icmp6OutType128 = strtoull(value, NULL, 10);
435
+ else if(hash == hash_Icmp6OutType129 && strcmp(name, "Icmp6OutType129") == 0) Icmp6OutType129 = strtoull(value, NULL, 10);
436
+ else if(hash == hash_Icmp6OutType133 && strcmp(name, "Icmp6OutType133") == 0) Icmp6OutType133 = strtoull(value, NULL, 10);
437
+ else if(hash == hash_Icmp6OutType135 && strcmp(name, "Icmp6OutType135") == 0) Icmp6OutType135 = strtoull(value, NULL, 10);
438
+ else if(hash == hash_Icmp6OutType143 && strcmp(name, "Icmp6OutType143") == 0) Icmp6OutType143 = strtoull(value, NULL, 10);
439
+ else if(hash == hash_Udp6InDatagrams && strcmp(name, "Udp6InDatagrams") == 0) Udp6InDatagrams = strtoull(value, NULL, 10);
440
+ else if(hash == hash_Udp6NoPorts && strcmp(name, "Udp6NoPorts") == 0) Udp6NoPorts = strtoull(value, NULL, 10);
441
+ else if(hash == hash_Udp6InErrors && strcmp(name, "Udp6InErrors") == 0) Udp6InErrors = strtoull(value, NULL, 10);
442
+ else if(hash == hash_Udp6OutDatagrams && strcmp(name, "Udp6OutDatagrams") == 0) Udp6OutDatagrams = strtoull(value, NULL, 10);
443
+ else if(hash == hash_Udp6RcvbufErrors && strcmp(name, "Udp6RcvbufErrors") == 0) Udp6RcvbufErrors = strtoull(value, NULL, 10);
444
+ else if(hash == hash_Udp6SndbufErrors && strcmp(name, "Udp6SndbufErrors") == 0) Udp6SndbufErrors = strtoull(value, NULL, 10);
445
+ else if(hash == hash_Udp6InCsumErrors && strcmp(name, "Udp6InCsumErrors") == 0) Udp6InCsumErrors = strtoull(value, NULL, 10);
446
+ else if(hash == hash_Udp6IgnoredMulti && strcmp(name, "Udp6IgnoredMulti") == 0) Udp6IgnoredMulti = strtoull(value, NULL, 10);
447
+ else if(hash == hash_UdpLite6InDatagrams && strcmp(name, "UdpLite6InDatagrams") == 0) UdpLite6InDatagrams = strtoull(value, NULL, 10);
448
+ else if(hash == hash_UdpLite6NoPorts && strcmp(name, "UdpLite6NoPorts") == 0) UdpLite6NoPorts = strtoull(value, NULL, 10);
449
+ else if(hash == hash_UdpLite6InErrors && strcmp(name, "UdpLite6InErrors") == 0) UdpLite6InErrors = strtoull(value, NULL, 10);
450
+ else if(hash == hash_UdpLite6OutDatagrams && strcmp(name, "UdpLite6OutDatagrams") == 0) UdpLite6OutDatagrams = strtoull(value, NULL, 10);
451
+ else if(hash == hash_UdpLite6RcvbufErrors && strcmp(name, "UdpLite6RcvbufErrors") == 0) UdpLite6RcvbufErrors = strtoull(value, NULL, 10);
452
+ else if(hash == hash_UdpLite6SndbufErrors && strcmp(name, "UdpLite6SndbufErrors") == 0) UdpLite6SndbufErrors = strtoull(value, NULL, 10);
453
+ else if(hash == hash_UdpLite6InCsumErrors && strcmp(name, "UdpLite6InCsumErrors") == 0) UdpLite6InCsumErrors = strtoull(value, NULL, 10);
454
+ }
455
+
456
+ RRDSET *st;
457
+
458
+ // --------------------------------------------------------------------
459
+
460
+ if(do_bandwidth == CONFIG_ONDEMAND_YES || (do_bandwidth == CONFIG_ONDEMAND_ONDEMAND && (Ip6InOctets || Ip6OutOctets))) {
461
+ do_bandwidth = CONFIG_ONDEMAND_YES;
462
+ st = rrdset_find("system.ipv6");
463
+ if(!st) {
464
+ st = rrdset_create("system", "ipv6", NULL, "network", NULL, "IPv6 Bandwidth", "kilobits/s", 500, update_every, RRDSET_TYPE_AREA);
465
+
466
+ rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL);
467
+ rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL);
468
+ }
469
+ else rrdset_next(st);
470
+
471
+ rrddim_set(st, "sent", Ip6OutOctets);
472
+ rrddim_set(st, "received", Ip6InOctets);
473
+ rrdset_done(st);
474
+ }
475
+
476
+ // --------------------------------------------------------------------
477
+
478
+ if(do_ip_packets == CONFIG_ONDEMAND_YES || (do_ip_packets == CONFIG_ONDEMAND_ONDEMAND && (Ip6InReceives || Ip6OutRequests || Ip6InDelivers || Ip6OutForwDatagrams))) {
479
+ do_ip_packets = CONFIG_ONDEMAND_YES;
480
+ st = rrdset_find(RRD_TYPE_NET_SNMP6 ".packets");
481
+ if(!st) {
482
+ st = rrdset_create(RRD_TYPE_NET_SNMP6, "packets", NULL, "packets", NULL, "IPv6 Packets", "packets/s", 3000, update_every, RRDSET_TYPE_LINE);
483
+
484
+ rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
485
+ rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
486
+ rrddim_add(st, "forwarded", NULL, 1, 1, RRDDIM_INCREMENTAL);
487
+ rrddim_add(st, "delivers", NULL, -1, 1, RRDDIM_INCREMENTAL);
488
+ }
489
+ else rrdset_next(st);
490
+
491
+ rrddim_set(st, "sent", Ip6OutRequests);
492
+ rrddim_set(st, "received", Ip6InReceives);
493
+ rrddim_set(st, "forwarded", Ip6InDelivers);
494
+ rrddim_set(st, "delivers", Ip6OutForwDatagrams);
495
+ rrdset_done(st);
496
+ }
497
+
498
+ // --------------------------------------------------------------------
499
+
500
+ if(do_ip_fragsout == CONFIG_ONDEMAND_YES || (do_ip_fragsout == CONFIG_ONDEMAND_ONDEMAND && (Ip6FragOKs || Ip6FragFails || Ip6FragCreates))) {
501
+ do_ip_fragsout = CONFIG_ONDEMAND_YES;
502
+ st = rrdset_find(RRD_TYPE_NET_SNMP6 ".fragsout");
503
+ if(!st) {
504
+ st = rrdset_create(RRD_TYPE_NET_SNMP6, "fragsout", NULL, "fragments", NULL, "IPv6 Fragments Sent", "packets/s", 3010, update_every, RRDSET_TYPE_LINE);
505
+ st->isdetail = 1;
506
+
507
+ rrddim_add(st, "ok", NULL, 1, 1, RRDDIM_INCREMENTAL);
508
+ rrddim_add(st, "failed", NULL, -1, 1, RRDDIM_INCREMENTAL);
509
+ rrddim_add(st, "all", NULL, 1, 1, RRDDIM_INCREMENTAL);
510
+ }
511
+ else rrdset_next(st);
512
+
513
+ rrddim_set(st, "ok", Ip6FragOKs);
514
+ rrddim_set(st, "failed", Ip6FragFails);
515
+ rrddim_set(st, "all", Ip6FragCreates);
516
+ rrdset_done(st);
517
+ }
518
+
519
+ // --------------------------------------------------------------------
520
+
521
+ if(do_ip_fragsin == CONFIG_ONDEMAND_YES || (do_ip_fragsin == CONFIG_ONDEMAND_ONDEMAND
522
+ && (
523
+ Ip6ReasmOKs
524
+ || Ip6ReasmFails
525
+ || Ip6ReasmTimeout
526
+ || Ip6ReasmReqds
527
+ ))) {
528
+ do_ip_fragsin = CONFIG_ONDEMAND_YES;
529
+ st = rrdset_find(RRD_TYPE_NET_SNMP6 ".fragsin");
530
+ if(!st) {
531
+ st = rrdset_create(RRD_TYPE_NET_SNMP6, "fragsin", NULL, "fragments", NULL, "IPv6 Fragments Reassembly", "packets/s", 3011, update_every, RRDSET_TYPE_LINE);
532
+ st->isdetail = 1;
533
+
534
+ rrddim_add(st, "ok", NULL, 1, 1, RRDDIM_INCREMENTAL);
535
+ rrddim_add(st, "failed", NULL, -1, 1, RRDDIM_INCREMENTAL);
536
+ rrddim_add(st, "timeout", NULL, -1, 1, RRDDIM_INCREMENTAL);
537
+ rrddim_add(st, "all", NULL, 1, 1, RRDDIM_INCREMENTAL);
538
+ }
539
+ else rrdset_next(st);
540
+
541
+ rrddim_set(st, "ok", Ip6ReasmOKs);
542
+ rrddim_set(st, "failed", Ip6ReasmFails);
543
+ rrddim_set(st, "timeout", Ip6ReasmTimeout);
544
+ rrddim_set(st, "all", Ip6ReasmReqds);
545
+ rrdset_done(st);
546
+ }
547
+
548
+ // --------------------------------------------------------------------
549
+
550
+ if(do_ip_errors == CONFIG_ONDEMAND_YES || (do_ip_errors == CONFIG_ONDEMAND_ONDEMAND
551
+ && (
552
+ Ip6InDiscards
553
+ || Ip6OutDiscards
554
+ || Ip6InHdrErrors
555
+ || Ip6InAddrErrors
556
+ || Ip6InUnknownProtos
557
+ || Ip6InTooBigErrors
558
+ || Ip6InTruncatedPkts
559
+ || Ip6InNoRoutes
560
+ ))) {
561
+ do_ip_errors = CONFIG_ONDEMAND_YES;
562
+ st = rrdset_find(RRD_TYPE_NET_SNMP6 ".errors");
563
+ if(!st) {
564
+ st = rrdset_create(RRD_TYPE_NET_SNMP6, "errors", NULL, "errors", NULL, "IPv6 Errors", "packets/s", 3002, update_every, RRDSET_TYPE_LINE);
565
+ st->isdetail = 1;
566
+
567
+ rrddim_add(st, "InDiscards", NULL, 1, 1, RRDDIM_INCREMENTAL);
568
+ rrddim_add(st, "OutDiscards", NULL, -1, 1, RRDDIM_INCREMENTAL);
569
+
570
+ rrddim_add(st, "InHdrErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
571
+ rrddim_add(st, "InAddrErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
572
+ rrddim_add(st, "InUnknownProtos", NULL, 1, 1, RRDDIM_INCREMENTAL);
573
+ rrddim_add(st, "InTooBigErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
574
+ rrddim_add(st, "InTruncatedPkts", NULL, 1, 1, RRDDIM_INCREMENTAL);
575
+ rrddim_add(st, "InNoRoutes", NULL, 1, 1, RRDDIM_INCREMENTAL);
576
+
577
+ rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRDDIM_INCREMENTAL);
578
+ }
579
+ else rrdset_next(st);
580
+
581
+ rrddim_set(st, "InDiscards", Ip6InDiscards);
582
+ rrddim_set(st, "OutDiscards", Ip6OutDiscards);
583
+
584
+ rrddim_set(st, "InHdrErrors", Ip6InHdrErrors);
585
+ rrddim_set(st, "InAddrErrors", Ip6InAddrErrors);
586
+ rrddim_set(st, "InUnknownProtos", Ip6InUnknownProtos);
587
+ rrddim_set(st, "InTooBigErrors", Ip6InTooBigErrors);
588
+ rrddim_set(st, "InTruncatedPkts", Ip6InTruncatedPkts);
589
+ rrddim_set(st, "InNoRoutes", Ip6InNoRoutes);
590
+
591
+ rrddim_set(st, "OutNoRoutes", Ip6OutNoRoutes);
592
+ rrdset_done(st);
593
+ }
594
+
595
+ // --------------------------------------------------------------------
596
+
597
+ if(do_udp_packets == CONFIG_ONDEMAND_YES || (do_udp_packets == CONFIG_ONDEMAND_ONDEMAND && (Udp6InDatagrams || Udp6OutDatagrams))) {
598
+ do_udp_packets = CONFIG_ONDEMAND_YES;
599
+ st = rrdset_find(RRD_TYPE_NET_SNMP6 ".udppackets");
600
+ if(!st) {
601
+ st = rrdset_create(RRD_TYPE_NET_SNMP6, "udppackets", NULL, "udp", NULL, "IPv6 UDP Packets", "packets/s", 3601, update_every, RRDSET_TYPE_LINE);
602
+
603
+ rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
604
+ rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
605
+ }
606
+ else rrdset_next(st);
607
+
608
+ rrddim_set(st, "received", Udp6InDatagrams);
609
+ rrddim_set(st, "sent", Udp6OutDatagrams);
610
+ rrdset_done(st);
611
+ }
612
+
613
+ // --------------------------------------------------------------------
614
+
615
+ if(do_udp_errors == CONFIG_ONDEMAND_YES || (do_udp_errors == CONFIG_ONDEMAND_ONDEMAND
616
+ && (
617
+ Udp6InErrors
618
+ || Udp6NoPorts
619
+ || Udp6RcvbufErrors
620
+ || Udp6SndbufErrors
621
+ || Udp6InCsumErrors
622
+ || Udp6IgnoredMulti
623
+ ))) {
624
+ do_udp_errors = CONFIG_ONDEMAND_YES;
625
+ st = rrdset_find(RRD_TYPE_NET_SNMP6 ".udperrors");
626
+ if(!st) {
627
+ st = rrdset_create(RRD_TYPE_NET_SNMP6, "udperrors", NULL, "udp", NULL, "IPv6 UDP Errors", "events/s", 3701, update_every, RRDSET_TYPE_LINE);
628
+ st->isdetail = 1;
629
+
630
+ rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
631
+ rrddim_add(st, "SndbufErrors", NULL, -1, 1, RRDDIM_INCREMENTAL);
632
+ rrddim_add(st, "InErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
633
+ rrddim_add(st, "NoPorts", NULL, 1, 1, RRDDIM_INCREMENTAL);
634
+ rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
635
+ rrddim_add(st, "IgnoredMulti", NULL, 1, 1, RRDDIM_INCREMENTAL);
636
+ }
637
+ else rrdset_next(st);
638
+
639
+ rrddim_set(st, "InErrors", Udp6InErrors);
640
+ rrddim_set(st, "NoPorts", Udp6NoPorts);
641
+ rrddim_set(st, "RcvbufErrors", Udp6RcvbufErrors);
642
+ rrddim_set(st, "SndbufErrors", Udp6SndbufErrors);
643
+ rrddim_set(st, "InCsumErrors", Udp6InCsumErrors);
644
+ rrddim_set(st, "IgnoredMulti", Udp6IgnoredMulti);
645
+ rrdset_done(st);
646
+ }
647
+
648
+ // --------------------------------------------------------------------
649
+
650
+ if(do_udplite_packets == CONFIG_ONDEMAND_YES || (do_udplite_packets == CONFIG_ONDEMAND_ONDEMAND && (UdpLite6InDatagrams || UdpLite6OutDatagrams))) {
651
+ do_udplite_packets = CONFIG_ONDEMAND_YES;
652
+ st = rrdset_find(RRD_TYPE_NET_SNMP6 ".udplitepackets");
653
+ if(!st) {
654
+ st = rrdset_create(RRD_TYPE_NET_SNMP6, "udplitepackets", NULL, "udplite", NULL, "IPv6 UDPlite Packets", "packets/s", 3601, update_every, RRDSET_TYPE_LINE);
655
+
656
+ rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
657
+ rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
658
+ }
659
+ else rrdset_next(st);
660
+
661
+ rrddim_set(st, "received", UdpLite6InDatagrams);
662
+ rrddim_set(st, "sent", UdpLite6OutDatagrams);
663
+ rrdset_done(st);
664
+ }
665
+
666
+ // --------------------------------------------------------------------
667
+
668
+ if(do_udplite_errors == CONFIG_ONDEMAND_YES || (do_udplite_errors == CONFIG_ONDEMAND_ONDEMAND
669
+ && (
670
+ UdpLite6InErrors
671
+ || UdpLite6NoPorts
672
+ || UdpLite6RcvbufErrors
673
+ || UdpLite6SndbufErrors
674
+ || Udp6InCsumErrors
675
+ || UdpLite6InCsumErrors
676
+ ))) {
677
+ do_udplite_errors = CONFIG_ONDEMAND_YES;
678
+ st = rrdset_find(RRD_TYPE_NET_SNMP6 ".udpliteerrors");
679
+ if(!st) {
680
+ st = rrdset_create(RRD_TYPE_NET_SNMP6, "udpliteerrors", NULL, "udplite", NULL, "IPv6 UDP Lite Errors", "events/s", 3701, update_every, RRDSET_TYPE_LINE);
681
+ st->isdetail = 1;
682
+
683
+ rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
684
+ rrddim_add(st, "SndbufErrors", NULL, -1, 1, RRDDIM_INCREMENTAL);
685
+ rrddim_add(st, "InErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
686
+ rrddim_add(st, "NoPorts", NULL, 1, 1, RRDDIM_INCREMENTAL);
687
+ rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
688
+ }
689
+ else rrdset_next(st);
690
+
691
+ rrddim_set(st, "InErrors", UdpLite6InErrors);
692
+ rrddim_set(st, "NoPorts", UdpLite6NoPorts);
693
+ rrddim_set(st, "RcvbufErrors", UdpLite6RcvbufErrors);
694
+ rrddim_set(st, "SndbufErrors", UdpLite6SndbufErrors);
695
+ rrddim_set(st, "InCsumErrors", UdpLite6InCsumErrors);
696
+ rrdset_done(st);
697
+ }
698
+
699
+ // --------------------------------------------------------------------
700
+
701
+ if(do_mcast == CONFIG_ONDEMAND_YES || (do_mcast == CONFIG_ONDEMAND_ONDEMAND && (Ip6OutMcastOctets || Ip6InMcastOctets))) {
702
+ do_mcast = CONFIG_ONDEMAND_YES;
703
+ st = rrdset_find(RRD_TYPE_NET_SNMP6 ".mcast");
704
+ if(!st) {
705
+ st = rrdset_create(RRD_TYPE_NET_SNMP6, "mcast", NULL, "multicast", NULL, "IPv6 Multicast Bandwidth", "kilobits/s", 9000, update_every, RRDSET_TYPE_AREA);
706
+ st->isdetail = 1;
707
+
708
+ rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL);
709
+ rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL);
710
+ }
711
+ else rrdset_next(st);
712
+
713
+ rrddim_set(st, "sent", Ip6OutMcastOctets);
714
+ rrddim_set(st, "received", Ip6InMcastOctets);
715
+ rrdset_done(st);
716
+ }
717
+
718
+ // --------------------------------------------------------------------
719
+
720
+ if(do_bcast == CONFIG_ONDEMAND_YES || (do_bcast == CONFIG_ONDEMAND_ONDEMAND && (Ip6OutBcastOctets || Ip6InBcastOctets))) {
721
+ do_bcast = CONFIG_ONDEMAND_YES;
722
+ st = rrdset_find(RRD_TYPE_NET_SNMP6 ".bcast");
723
+ if(!st) {
724
+ st = rrdset_create(RRD_TYPE_NET_SNMP6, "bcast", NULL, "broadcast", NULL, "IPv6 Broadcast Bandwidth", "kilobits/s", 8000, update_every, RRDSET_TYPE_AREA);
725
+ st->isdetail = 1;
726
+
727
+ rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL);
728
+ rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL);
729
+ }
730
+ else rrdset_next(st);
731
+
732
+ rrddim_set(st, "sent", Ip6OutBcastOctets);
733
+ rrddim_set(st, "received", Ip6InBcastOctets);
734
+ rrdset_done(st);
735
+ }
736
+
737
+ // --------------------------------------------------------------------
738
+
739
+ if(do_mcast_p == CONFIG_ONDEMAND_YES || (do_mcast_p == CONFIG_ONDEMAND_ONDEMAND && (Ip6OutMcastPkts || Ip6InMcastPkts))) {
740
+ do_mcast_p = CONFIG_ONDEMAND_YES;
741
+ st = rrdset_find(RRD_TYPE_NET_SNMP6 ".mcastpkts");
742
+ if(!st) {
743
+ st = rrdset_create(RRD_TYPE_NET_SNMP6, "mcastpkts", NULL, "multicast", NULL, "IPv6 Multicast Packets", "packets/s", 9500, update_every, RRDSET_TYPE_LINE);
744
+ st->isdetail = 1;
745
+
746
+ rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
747
+ rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
748
+ }
749
+ else rrdset_next(st);
750
+
751
+ rrddim_set(st, "sent", Ip6OutMcastPkts);
752
+ rrddim_set(st, "received", Ip6InMcastPkts);
753
+ rrdset_done(st);
754
+ }
755
+
756
+ // --------------------------------------------------------------------
757
+
758
+ if(do_icmp == CONFIG_ONDEMAND_YES || (do_icmp == CONFIG_ONDEMAND_ONDEMAND && (Icmp6InMsgs || Icmp6OutMsgs))) {
759
+ do_icmp = CONFIG_ONDEMAND_YES;
760
+ st = rrdset_find(RRD_TYPE_NET_SNMP6 ".icmp");
761
+ if(!st) {
762
+ st = rrdset_create(RRD_TYPE_NET_SNMP6, "icmp", NULL, "icmp", NULL, "IPv6 ICMP Messages", "messages/s", 10000, update_every, RRDSET_TYPE_LINE);
763
+
764
+ rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
765
+ rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
766
+ }
767
+ else rrdset_next(st);
768
+
769
+ rrddim_set(st, "sent", Icmp6InMsgs);
770
+ rrddim_set(st, "received", Icmp6OutMsgs);
771
+ rrdset_done(st);
772
+ }
773
+
774
+ // --------------------------------------------------------------------
775
+
776
+ if(do_icmp_redir == CONFIG_ONDEMAND_YES || (do_icmp_redir == CONFIG_ONDEMAND_ONDEMAND && (Icmp6InRedirects || Icmp6OutRedirects))) {
777
+ do_icmp_redir = CONFIG_ONDEMAND_YES;
778
+ st = rrdset_find(RRD_TYPE_NET_SNMP6 ".icmpredir");
779
+ if(!st) {
780
+ st = rrdset_create(RRD_TYPE_NET_SNMP6, "icmpredir", NULL, "icmp", NULL, "IPv6 ICMP Redirects", "redirects/s", 10050, update_every, RRDSET_TYPE_LINE);
781
+
782
+ rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
783
+ rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
784
+ }
785
+ else rrdset_next(st);
786
+
787
+ rrddim_set(st, "sent", Icmp6InRedirects);
788
+ rrddim_set(st, "received", Icmp6OutRedirects);
789
+ rrdset_done(st);
790
+ }
791
+
792
+ // --------------------------------------------------------------------
793
+
794
+ if(do_icmp_errors == CONFIG_ONDEMAND_YES || (do_icmp_errors == CONFIG_ONDEMAND_ONDEMAND
795
+ && (
796
+ Icmp6InErrors
797
+ || Icmp6OutErrors
798
+ || Icmp6InCsumErrors
799
+ || Icmp6InDestUnreachs
800
+ || Icmp6InPktTooBigs
801
+ || Icmp6InTimeExcds
802
+ || Icmp6InParmProblems
803
+ || Icmp6OutDestUnreachs
804
+ || Icmp6OutPktTooBigs
805
+ || Icmp6OutTimeExcds
806
+ || Icmp6OutParmProblems
807
+ ))) {
808
+ do_icmp_errors = CONFIG_ONDEMAND_YES;
809
+ st = rrdset_find(RRD_TYPE_NET_SNMP6 ".icmperrors");
810
+ if(!st) {
811
+ st = rrdset_create(RRD_TYPE_NET_SNMP6, "icmperrors", NULL, "icmp", NULL, "IPv6 ICMP Errors", "errors/s", 10100, update_every, RRDSET_TYPE_LINE);
812
+
813
+ rrddim_add(st, "InErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
814
+ rrddim_add(st, "OutErrors", NULL, -1, 1, RRDDIM_INCREMENTAL);
815
+
816
+ rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
817
+ rrddim_add(st, "InDestUnreachs", NULL, 1, 1, RRDDIM_INCREMENTAL);
818
+ rrddim_add(st, "InPktTooBigs", NULL, 1, 1, RRDDIM_INCREMENTAL);
819
+ rrddim_add(st, "InTimeExcds", NULL, 1, 1, RRDDIM_INCREMENTAL);
820
+ rrddim_add(st, "InParmProblems", NULL, 1, 1, RRDDIM_INCREMENTAL);
821
+ rrddim_add(st, "OutDestUnreachs", NULL, -1, 1, RRDDIM_INCREMENTAL);
822
+ rrddim_add(st, "OutPktTooBigs", NULL, -1, 1, RRDDIM_INCREMENTAL);
823
+ rrddim_add(st, "OutTimeExcds", NULL, -1, 1, RRDDIM_INCREMENTAL);
824
+ rrddim_add(st, "OutParmProblems", NULL, -1, 1, RRDDIM_INCREMENTAL);
825
+ }
826
+ else rrdset_next(st);
827
+
828
+ rrddim_set(st, "InErrors", Icmp6InErrors);
829
+ rrddim_set(st, "OutErrors", Icmp6OutErrors);
830
+ rrddim_set(st, "InCsumErrors", Icmp6InCsumErrors);
831
+ rrddim_set(st, "InDestUnreachs", Icmp6InDestUnreachs);
832
+ rrddim_set(st, "InPktTooBigs", Icmp6InPktTooBigs);
833
+ rrddim_set(st, "InTimeExcds", Icmp6InTimeExcds);
834
+ rrddim_set(st, "InParmProblems", Icmp6InParmProblems);
835
+ rrddim_set(st, "OutDestUnreachs", Icmp6OutDestUnreachs);
836
+ rrddim_set(st, "OutPktTooBigs", Icmp6OutPktTooBigs);
837
+ rrddim_set(st, "OutTimeExcds", Icmp6OutTimeExcds);
838
+ rrddim_set(st, "OutParmProblems", Icmp6OutParmProblems);
839
+ rrdset_done(st);
840
+ }
841
+
842
+ // --------------------------------------------------------------------
843
+
844
+ if(do_icmp_echos == CONFIG_ONDEMAND_YES || (do_icmp_echos == CONFIG_ONDEMAND_ONDEMAND
845
+ && (
846
+ Icmp6InEchos
847
+ || Icmp6OutEchos
848
+ || Icmp6InEchoReplies
849
+ || Icmp6OutEchoReplies
850
+ ))) {
851
+ do_icmp_echos = CONFIG_ONDEMAND_YES;
852
+ st = rrdset_find(RRD_TYPE_NET_SNMP6 ".icmpechos");
853
+ if(!st) {
854
+ st = rrdset_create(RRD_TYPE_NET_SNMP6, "icmpechos", NULL, "icmp", NULL, "IPv6 ICMP Echo", "messages/s", 10200, update_every, RRDSET_TYPE_LINE);
855
+
856
+ rrddim_add(st, "InEchos", NULL, 1, 1, RRDDIM_INCREMENTAL);
857
+ rrddim_add(st, "OutEchos", NULL, -1, 1, RRDDIM_INCREMENTAL);
858
+ rrddim_add(st, "InEchoReplies", NULL, 1, 1, RRDDIM_INCREMENTAL);
859
+ rrddim_add(st, "OutEchoReplies", NULL, -1, 1, RRDDIM_INCREMENTAL);
860
+ }
861
+ else rrdset_next(st);
862
+
863
+ rrddim_set(st, "InEchos", Icmp6InEchos);
864
+ rrddim_set(st, "OutEchos", Icmp6OutEchos);
865
+ rrddim_set(st, "InEchoReplies", Icmp6InEchoReplies);
866
+ rrddim_set(st, "OutEchoReplies", Icmp6OutEchoReplies);
867
+ rrdset_done(st);
868
+ }
869
+
870
+ // --------------------------------------------------------------------
871
+
872
+ if(do_icmp_groupmemb == CONFIG_ONDEMAND_YES || (do_icmp_groupmemb == CONFIG_ONDEMAND_ONDEMAND
873
+ && (
874
+ Icmp6InGroupMembQueries
875
+ || Icmp6OutGroupMembQueries
876
+ || Icmp6InGroupMembResponses
877
+ || Icmp6OutGroupMembResponses
878
+ || Icmp6InGroupMembReductions
879
+ || Icmp6OutGroupMembReductions
880
+ ))) {
881
+ do_icmp_groupmemb = CONFIG_ONDEMAND_YES;
882
+ st = rrdset_find(RRD_TYPE_NET_SNMP6 ".groupmemb");
883
+ if(!st) {
884
+ st = rrdset_create(RRD_TYPE_NET_SNMP6, "groupmemb", NULL, "icmp", NULL, "IPv6 ICMP Group Membership", "messages/s", 10300, update_every, RRDSET_TYPE_LINE);
885
+
886
+ rrddim_add(st, "InQueries", NULL, 1, 1, RRDDIM_INCREMENTAL);
887
+ rrddim_add(st, "OutQueries", NULL, -1, 1, RRDDIM_INCREMENTAL);
888
+ rrddim_add(st, "InResponses", NULL, 1, 1, RRDDIM_INCREMENTAL);
889
+ rrddim_add(st, "OutResponses", NULL, -1, 1, RRDDIM_INCREMENTAL);
890
+ rrddim_add(st, "InReductions", NULL, 1, 1, RRDDIM_INCREMENTAL);
891
+ rrddim_add(st, "OutReductions", NULL, -1, 1, RRDDIM_INCREMENTAL);
892
+ }
893
+ else rrdset_next(st);
894
+
895
+ rrddim_set(st, "InQueries", Icmp6InGroupMembQueries);
896
+ rrddim_set(st, "OutQueries", Icmp6OutGroupMembQueries);
897
+ rrddim_set(st, "InResponses", Icmp6InGroupMembResponses);
898
+ rrddim_set(st, "OutResponses", Icmp6OutGroupMembResponses);
899
+ rrddim_set(st, "InReductions", Icmp6InGroupMembReductions);
900
+ rrddim_set(st, "OutReductions", Icmp6OutGroupMembReductions);
901
+ rrdset_done(st);
902
+ }
903
+
904
+ // --------------------------------------------------------------------
905
+
906
+ if(do_icmp_router == CONFIG_ONDEMAND_YES || (do_icmp_router == CONFIG_ONDEMAND_ONDEMAND
907
+ && (
908
+ Icmp6InRouterSolicits
909
+ || Icmp6OutRouterSolicits
910
+ || Icmp6InRouterAdvertisements
911
+ || Icmp6OutRouterAdvertisements
912
+ ))) {
913
+ do_icmp_router = CONFIG_ONDEMAND_YES;
914
+ st = rrdset_find(RRD_TYPE_NET_SNMP6 ".icmprouter");
915
+ if(!st) {
916
+ st = rrdset_create(RRD_TYPE_NET_SNMP6, "icmprouter", NULL, "icmp", NULL, "IPv6 Router Messages", "messages/s", 10400, update_every, RRDSET_TYPE_LINE);
917
+
918
+ rrddim_add(st, "InSolicits", NULL, 1, 1, RRDDIM_INCREMENTAL);
919
+ rrddim_add(st, "OutSolicits", NULL, -1, 1, RRDDIM_INCREMENTAL);
920
+ rrddim_add(st, "InAdvertisements", NULL, 1, 1, RRDDIM_INCREMENTAL);
921
+ rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRDDIM_INCREMENTAL);
922
+ }
923
+ else rrdset_next(st);
924
+
925
+ rrddim_set(st, "InSolicits", Icmp6InRouterSolicits);
926
+ rrddim_set(st, "OutSolicits", Icmp6OutRouterSolicits);
927
+ rrddim_set(st, "InAdvertisements", Icmp6InRouterAdvertisements);
928
+ rrddim_set(st, "OutAdvertisements", Icmp6OutRouterAdvertisements);
929
+ rrdset_done(st);
930
+ }
931
+
932
+ // --------------------------------------------------------------------
933
+
934
+ if(do_icmp_neighbor == CONFIG_ONDEMAND_YES || (do_icmp_neighbor == CONFIG_ONDEMAND_ONDEMAND
935
+ && (
936
+ Icmp6InNeighborSolicits
937
+ || Icmp6OutNeighborSolicits
938
+ || Icmp6InNeighborAdvertisements
939
+ || Icmp6OutNeighborAdvertisements
940
+ ))) {
941
+ do_icmp_neighbor = CONFIG_ONDEMAND_YES;
942
+ st = rrdset_find(RRD_TYPE_NET_SNMP6 ".icmpneighbor");
943
+ if(!st) {
944
+ st = rrdset_create(RRD_TYPE_NET_SNMP6, "icmpneighbor", NULL, "icmp", NULL, "IPv6 Neighbor Messages", "messages/s", 10500, update_every, RRDSET_TYPE_LINE);
945
+
946
+ rrddim_add(st, "InSolicits", NULL, 1, 1, RRDDIM_INCREMENTAL);
947
+ rrddim_add(st, "OutSolicits", NULL, -1, 1, RRDDIM_INCREMENTAL);
948
+ rrddim_add(st, "InAdvertisements", NULL, 1, 1, RRDDIM_INCREMENTAL);
949
+ rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRDDIM_INCREMENTAL);
950
+ }
951
+ else rrdset_next(st);
952
+
953
+ rrddim_set(st, "InSolicits", Icmp6InNeighborSolicits);
954
+ rrddim_set(st, "OutSolicits", Icmp6OutNeighborSolicits);
955
+ rrddim_set(st, "InAdvertisements", Icmp6InNeighborAdvertisements);
956
+ rrddim_set(st, "OutAdvertisements", Icmp6OutNeighborAdvertisements);
957
+ rrdset_done(st);
958
+ }
959
+
960
+ // --------------------------------------------------------------------
961
+
962
+ if(do_icmp_mldv2 == CONFIG_ONDEMAND_YES || (do_icmp_mldv2 == CONFIG_ONDEMAND_ONDEMAND && (Icmp6InMLDv2Reports || Icmp6OutMLDv2Reports))) {
963
+ do_icmp_mldv2 = CONFIG_ONDEMAND_YES;
964
+ st = rrdset_find(RRD_TYPE_NET_SNMP6 ".icmpmldv2");
965
+ if(!st) {
966
+ st = rrdset_create(RRD_TYPE_NET_SNMP6, "icmpmldv2", NULL, "icmp", NULL, "IPv6 ICMP MLDv2 Reports", "reports/s", 10600, update_every, RRDSET_TYPE_LINE);
967
+
968
+ rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
969
+ rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
970
+ }
971
+ else rrdset_next(st);
972
+
973
+ rrddim_set(st, "sent", Icmp6InMLDv2Reports);
974
+ rrddim_set(st, "received", Icmp6OutMLDv2Reports);
975
+ rrdset_done(st);
976
+ }
977
+
978
+ // --------------------------------------------------------------------
979
+
980
+ if(do_icmp_types == CONFIG_ONDEMAND_YES || (do_icmp_types == CONFIG_ONDEMAND_ONDEMAND
981
+ && (
982
+ Icmp6InType1
983
+ || Icmp6InType128
984
+ || Icmp6InType129
985
+ || Icmp6InType136
986
+ || Icmp6OutType1
987
+ || Icmp6OutType128
988
+ || Icmp6OutType129
989
+ || Icmp6OutType133
990
+ || Icmp6OutType135
991
+ || Icmp6OutType143
992
+ ))) {
993
+ do_icmp_types = CONFIG_ONDEMAND_YES;
994
+ st = rrdset_find(RRD_TYPE_NET_SNMP6 ".icmptypes");
995
+ if(!st) {
996
+ st = rrdset_create(RRD_TYPE_NET_SNMP6, "icmptypes", NULL, "icmp", NULL, "IPv6 ICMP Types", "messages/s", 10700, update_every, RRDSET_TYPE_LINE);
997
+
998
+ rrddim_add(st, "InType1", NULL, 1, 1, RRDDIM_INCREMENTAL);
999
+ rrddim_add(st, "InType128", NULL, 1, 1, RRDDIM_INCREMENTAL);
1000
+ rrddim_add(st, "InType129", NULL, 1, 1, RRDDIM_INCREMENTAL);
1001
+ rrddim_add(st, "InType136", NULL, 1, 1, RRDDIM_INCREMENTAL);
1002
+ rrddim_add(st, "OutType1", NULL, -1, 1, RRDDIM_INCREMENTAL);
1003
+ rrddim_add(st, "OutType128", NULL, -1, 1, RRDDIM_INCREMENTAL);
1004
+ rrddim_add(st, "OutType129", NULL, -1, 1, RRDDIM_INCREMENTAL);
1005
+ rrddim_add(st, "OutType133", NULL, -1, 1, RRDDIM_INCREMENTAL);
1006
+ rrddim_add(st, "OutType135", NULL, -1, 1, RRDDIM_INCREMENTAL);
1007
+ rrddim_add(st, "OutType143", NULL, -1, 1, RRDDIM_INCREMENTAL);
1008
+ }
1009
+ else rrdset_next(st);
1010
+
1011
+ rrddim_set(st, "InType1", Icmp6InType1);
1012
+ rrddim_set(st, "InType128", Icmp6InType128);
1013
+ rrddim_set(st, "InType129", Icmp6InType129);
1014
+ rrddim_set(st, "InType136", Icmp6InType136);
1015
+ rrddim_set(st, "OutType1", Icmp6OutType1);
1016
+ rrddim_set(st, "OutType128", Icmp6OutType128);
1017
+ rrddim_set(st, "OutType129", Icmp6OutType129);
1018
+ rrddim_set(st, "OutType133", Icmp6OutType133);
1019
+ rrddim_set(st, "OutType135", Icmp6OutType135);
1020
+ rrddim_set(st, "OutType143", Icmp6OutType143);
1021
+ rrdset_done(st);
1022
+ }
1023
+
1024
+ // --------------------------------------------------------------------
1025
+
1026
+ if(do_ect == CONFIG_ONDEMAND_YES || (do_ect == CONFIG_ONDEMAND_ONDEMAND
1027
+ && (
1028
+ Ip6InNoECTPkts
1029
+ || Ip6InECT1Pkts
1030
+ || Ip6InECT0Pkts
1031
+ || Ip6InCEPkts
1032
+ ))) {
1033
+ do_ect = CONFIG_ONDEMAND_YES;
1034
+ st = rrdset_find(RRD_TYPE_NET_SNMP6 ".ect");
1035
+ if(!st) {
1036
+ st = rrdset_create(RRD_TYPE_NET_SNMP6, "ect", NULL, "packets", NULL, "IPv6 ECT Packets", "packets/s", 10800, update_every, RRDSET_TYPE_LINE);
1037
+
1038
+ rrddim_add(st, "InNoECTPkts", NULL, 1, 1, RRDDIM_INCREMENTAL);
1039
+ rrddim_add(st, "InECT1Pkts", NULL, 1, 1, RRDDIM_INCREMENTAL);
1040
+ rrddim_add(st, "InECT0Pkts", NULL, 1, 1, RRDDIM_INCREMENTAL);
1041
+ rrddim_add(st, "InCEPkts", NULL, 1, 1, RRDDIM_INCREMENTAL);
1042
+ }
1043
+ else rrdset_next(st);
1044
+
1045
+ rrddim_set(st, "InNoECTPkts", Ip6InNoECTPkts);
1046
+ rrddim_set(st, "InECT1Pkts", Ip6InECT1Pkts);
1047
+ rrddim_set(st, "InECT0Pkts", Ip6InECT0Pkts);
1048
+ rrddim_set(st, "InCEPkts", Ip6InCEPkts);
1049
+ rrdset_done(st);
1050
+ }
1051
+
1052
+ return 0;
1053
}
1054
src/proc_net_stat_conntrack.c
+198
-198
@@ -1,203 +1,203 @@
1
#include "common.h"
2
3
-#define RRD_TYPE_NET_STAT_NETFILTER "netfilter"
4
-#define RRD_TYPE_NET_STAT_CONNTRACK "conntrack"
5
-#define RRD_TYPE_NET_STAT_CONNTRACK_LEN strlen(RRD_TYPE_NET_STAT_CONNTRACK)
3
+#define RRD_TYPE_NET_STAT_NETFILTER "netfilter"
4
+#define RRD_TYPE_NET_STAT_CONNTRACK "conntrack"
5
+#define RRD_TYPE_NET_STAT_CONNTRACK_LEN strlen(RRD_TYPE_NET_STAT_CONNTRACK)
6
7
int do_proc_net_stat_conntrack(int update_every, unsigned long long dt) {
8
- static procfile *ff = NULL;
9
- static int do_sockets = -1, do_new = -1, do_changes = -1, do_expect = -1, do_search = -1, do_errors = -1;
10
-
11
- if(do_sockets == -1) do_sockets = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter connections", 1);
12
- if(do_new == -1) do_new = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter new connections", 1);
13
- if(do_changes == -1) do_changes = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter connection changes", 1);
14
- if(do_expect == -1) do_expect = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter connection expectations", 1);
15
- if(do_search == -1) do_search = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter connection searches", 1);
16
- if(do_errors == -1) do_errors = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter errors", 1);
17
-
18
- if(dt) {};
19
-
20
- if(!ff) {
21
- char filename[FILENAME_MAX + 1];
22
- snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/stat/nf_conntrack");
23
- ff = procfile_open(config_get("plugin:proc:/proc/net/stat/nf_conntrack", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
24
- }
25
- if(!ff) return 1;
26
-
27
- ff = procfile_readall(ff);
28
- if(!ff) return 0; // we return 0, so that we will retry to open it next time
29
-
30
- uint32_t lines = procfile_lines(ff), l;
31
- uint32_t words;
32
-
33
- unsigned long long aentries = 0, asearched = 0, afound = 0, anew = 0, ainvalid = 0, aignore = 0, adelete = 0, adelete_list = 0,
34
- ainsert = 0, ainsert_failed = 0, adrop = 0, aearly_drop = 0, aicmp_error = 0, aexpect_new = 0, aexpect_create = 0, aexpect_delete = 0, asearch_restart = 0;
35
-
36
- for(l = 1; l < lines ;l++) {
37
- words = procfile_linewords(ff, l);
38
- if(words < 17) {
39
- if(words) error("Cannot read /proc/net/stat/nf_conntrack line. Expected 17 params, read %u.", words);
40
- continue;
41
- }
42
-
43
- unsigned long long tentries = 0, tsearched = 0, tfound = 0, tnew = 0, tinvalid = 0, tignore = 0, tdelete = 0, tdelete_list = 0, tinsert = 0, tinsert_failed = 0, tdrop = 0, tearly_drop = 0, ticmp_error = 0, texpect_new = 0, texpect_create = 0, texpect_delete = 0, tsearch_restart = 0;
44
-
45
- tentries = strtoull(procfile_lineword(ff, l, 0), NULL, 16);
46
- tsearched = strtoull(procfile_lineword(ff, l, 1), NULL, 16);
47
- tfound = strtoull(procfile_lineword(ff, l, 2), NULL, 16);
48
- tnew = strtoull(procfile_lineword(ff, l, 3), NULL, 16);
49
- tinvalid = strtoull(procfile_lineword(ff, l, 4), NULL, 16);
50
- tignore = strtoull(procfile_lineword(ff, l, 5), NULL, 16);
51
- tdelete = strtoull(procfile_lineword(ff, l, 6), NULL, 16);
52
- tdelete_list = strtoull(procfile_lineword(ff, l, 7), NULL, 16);
53
- tinsert = strtoull(procfile_lineword(ff, l, 8), NULL, 16);
54
- tinsert_failed = strtoull(procfile_lineword(ff, l, 9), NULL, 16);
55
- tdrop = strtoull(procfile_lineword(ff, l, 10), NULL, 16);
56
- tearly_drop = strtoull(procfile_lineword(ff, l, 11), NULL, 16);
57
- ticmp_error = strtoull(procfile_lineword(ff, l, 12), NULL, 16);
58
- texpect_new = strtoull(procfile_lineword(ff, l, 13), NULL, 16);
59
- texpect_create = strtoull(procfile_lineword(ff, l, 14), NULL, 16);
60
- texpect_delete = strtoull(procfile_lineword(ff, l, 15), NULL, 16);
61
- tsearch_restart = strtoull(procfile_lineword(ff, l, 16), NULL, 16);
62
-
63
- if(!aentries) aentries = tentries;
64
-
65
- // sum all the cpus together
66
- asearched += tsearched; // conntrack.search
67
- afound += tfound; // conntrack.search
68
- anew += tnew; // conntrack.new
69
- ainvalid += tinvalid; // conntrack.new
70
- aignore += tignore; // conntrack.new
71
- adelete += tdelete; // conntrack.changes
72
- adelete_list += tdelete_list; // conntrack.changes
73
- ainsert += tinsert; // conntrack.changes
74
- ainsert_failed += tinsert_failed; // conntrack.errors
75
- adrop += tdrop; // conntrack.errors
76
- aearly_drop += tearly_drop; // conntrack.errors
77
- aicmp_error += ticmp_error; // conntrack.errors
78
- aexpect_new += texpect_new; // conntrack.expect
79
- aexpect_create += texpect_create; // conntrack.expect
80
- aexpect_delete += texpect_delete; // conntrack.expect
81
- asearch_restart += tsearch_restart; // conntrack.search
82
- }
83
-
84
- RRDSET *st;
85
-
86
- // --------------------------------------------------------------------
87
-
88
- if(do_sockets) {
89
- st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_sockets");
90
- if(!st) {
91
- st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_sockets", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Connections", "active connections", 1000, update_every, RRDSET_TYPE_LINE);
92
-
93
- rrddim_add(st, "connections", NULL, 1, 1, RRDDIM_ABSOLUTE);
94
- }
95
- else rrdset_next(st);
96
-
97
- rrddim_set(st, "connections", aentries);
98
- rrdset_done(st);
99
- }
100
-
101
- // --------------------------------------------------------------------
102
-
103
- if(do_new) {
104
- st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_new");
105
- if(!st) {
106
- st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_new", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker New Connections", "connections/s", 1001, update_every, RRDSET_TYPE_LINE);
107
-
108
- rrddim_add(st, "new", NULL, 1, 1, RRDDIM_INCREMENTAL);
109
- rrddim_add(st, "ignore", NULL, -1, 1, RRDDIM_INCREMENTAL);
110
- rrddim_add(st, "invalid", NULL, -1, 1, RRDDIM_INCREMENTAL);
111
- }
112
- else rrdset_next(st);
113
-
114
- rrddim_set(st, "new", anew);
115
- rrddim_set(st, "ignore", aignore);
116
- rrddim_set(st, "invalid", ainvalid);
117
- rrdset_done(st);
118
- }
119
-
120
- // --------------------------------------------------------------------
121
-
122
- if(do_changes) {
123
- st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_changes");
124
- if(!st) {
125
- st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_changes", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Changes", "changes/s", 1002, update_every, RRDSET_TYPE_LINE);
126
- st->isdetail = 1;
127
-
128
- rrddim_add(st, "inserted", NULL, 1, 1, RRDDIM_INCREMENTAL);
129
- rrddim_add(st, "deleted", NULL, -1, 1, RRDDIM_INCREMENTAL);
130
- rrddim_add(st, "delete_list", NULL, -1, 1, RRDDIM_INCREMENTAL);
131
- }
132
- else rrdset_next(st);
133
-
134
- rrddim_set(st, "inserted", ainsert);
135
- rrddim_set(st, "deleted", adelete);
136
- rrddim_set(st, "delete_list", adelete_list);
137
- rrdset_done(st);
138
- }
139
-
140
- // --------------------------------------------------------------------
141
-
142
- if(do_expect) {
143
- st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_expect");
144
- if(!st) {
145
- st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_expect", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Expectations", "expectations/s", 1003, update_every, RRDSET_TYPE_LINE);
146
- st->isdetail = 1;
147
-
148
- rrddim_add(st, "created", NULL, 1, 1, RRDDIM_INCREMENTAL);
149
- rrddim_add(st, "deleted", NULL, -1, 1, RRDDIM_INCREMENTAL);
150
- rrddim_add(st, "new", NULL, 1, 1, RRDDIM_INCREMENTAL);
151
- }
152
- else rrdset_next(st);
153
-
154
- rrddim_set(st, "created", aexpect_create);
155
- rrddim_set(st, "deleted", aexpect_delete);
156
- rrddim_set(st, "new", aexpect_new);
157
- rrdset_done(st);
158
- }
159
-
160
- // --------------------------------------------------------------------
161
-
162
- if(do_search) {
163
- st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_search");
164
- if(!st) {
165
- st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_search", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Searches", "searches/s", 1010, update_every, RRDSET_TYPE_LINE);
166
- st->isdetail = 1;
167
-
168
- rrddim_add(st, "searched", NULL, 1, 1, RRDDIM_INCREMENTAL);
169
- rrddim_add(st, "restarted", NULL, -1, 1, RRDDIM_INCREMENTAL);
170
- rrddim_add(st, "found", NULL, 1, 1, RRDDIM_INCREMENTAL);
171
- }
172
- else rrdset_next(st);
173
-
174
- rrddim_set(st, "searched", asearched);
175
- rrddim_set(st, "restarted", asearch_restart);
176
- rrddim_set(st, "found", afound);
177
- rrdset_done(st);
178
- }
179
-
180
- // --------------------------------------------------------------------
181
-
182
- if(do_errors) {
183
- st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_errors");
184
- if(!st) {
185
- st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_errors", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Errors", "events/s", 1005, update_every, RRDSET_TYPE_LINE);
186
- st->isdetail = 1;
187
-
188
- rrddim_add(st, "icmp_error", NULL, 1, 1, RRDDIM_INCREMENTAL);
189
- rrddim_add(st, "insert_failed", NULL, -1, 1, RRDDIM_INCREMENTAL);
190
- rrddim_add(st, "drop", NULL, -1, 1, RRDDIM_INCREMENTAL);
191
- rrddim_add(st, "early_drop", NULL, -1, 1, RRDDIM_INCREMENTAL);
192
- }
193
- else rrdset_next(st);
194
-
195
- rrddim_set(st, "icmp_error", aicmp_error);
196
- rrddim_set(st, "insert_failed", ainsert_failed);
197
- rrddim_set(st, "drop", adrop);
198
- rrddim_set(st, "early_drop", aearly_drop);
199
- rrdset_done(st);
200
- }
201
-
202
- return 0;
8
+ static procfile *ff = NULL;
9
+ static int do_sockets = -1, do_new = -1, do_changes = -1, do_expect = -1, do_search = -1, do_errors = -1;
10
+
11
+ if(do_sockets == -1) do_sockets = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter connections", 1);
12
+ if(do_new == -1) do_new = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter new connections", 1);
13
+ if(do_changes == -1) do_changes = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter connection changes", 1);
14
+ if(do_expect == -1) do_expect = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter connection expectations", 1);
15
+ if(do_search == -1) do_search = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter connection searches", 1);
16
+ if(do_errors == -1) do_errors = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter errors", 1);
17
+
18
+ if(dt) {};
19
+
20
+ if(!ff) {
21
+ char filename[FILENAME_MAX + 1];
22
+ snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/stat/nf_conntrack");
23
+ ff = procfile_open(config_get("plugin:proc:/proc/net/stat/nf_conntrack", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
24
+ }
25
+ if(!ff) return 1;
26
+
27
+ ff = procfile_readall(ff);
28
+ if(!ff) return 0; // we return 0, so that we will retry to open it next time
29
+
30
+ uint32_t lines = procfile_lines(ff), l;
31
+ uint32_t words;
32
+
33
+ unsigned long long aentries = 0, asearched = 0, afound = 0, anew = 0, ainvalid = 0, aignore = 0, adelete = 0, adelete_list = 0,
34
+ ainsert = 0, ainsert_failed = 0, adrop = 0, aearly_drop = 0, aicmp_error = 0, aexpect_new = 0, aexpect_create = 0, aexpect_delete = 0, asearch_restart = 0;
35
+
36
+ for(l = 1; l < lines ;l++) {
37
+ words = procfile_linewords(ff, l);
38
+ if(words < 17) {
39
+ if(words) error("Cannot read /proc/net/stat/nf_conntrack line. Expected 17 params, read %u.", words);
40
+ continue;
41
+ }
42
+
43
+ unsigned long long tentries = 0, tsearched = 0, tfound = 0, tnew = 0, tinvalid = 0, tignore = 0, tdelete = 0, tdelete_list = 0, tinsert = 0, tinsert_failed = 0, tdrop = 0, tearly_drop = 0, ticmp_error = 0, texpect_new = 0, texpect_create = 0, texpect_delete = 0, tsearch_restart = 0;
44
+
45
+ tentries = strtoull(procfile_lineword(ff, l, 0), NULL, 16);
46
+ tsearched = strtoull(procfile_lineword(ff, l, 1), NULL, 16);
47
+ tfound = strtoull(procfile_lineword(ff, l, 2), NULL, 16);
48
+ tnew = strtoull(procfile_lineword(ff, l, 3), NULL, 16);
49
+ tinvalid = strtoull(procfile_lineword(ff, l, 4), NULL, 16);
50
+ tignore = strtoull(procfile_lineword(ff, l, 5), NULL, 16);
51
+ tdelete = strtoull(procfile_lineword(ff, l, 6), NULL, 16);
52
+ tdelete_list = strtoull(procfile_lineword(ff, l, 7), NULL, 16);
53
+ tinsert = strtoull(procfile_lineword(ff, l, 8), NULL, 16);
54
+ tinsert_failed = strtoull(procfile_lineword(ff, l, 9), NULL, 16);
55
+ tdrop = strtoull(procfile_lineword(ff, l, 10), NULL, 16);
56
+ tearly_drop = strtoull(procfile_lineword(ff, l, 11), NULL, 16);
57
+ ticmp_error = strtoull(procfile_lineword(ff, l, 12), NULL, 16);
58
+ texpect_new = strtoull(procfile_lineword(ff, l, 13), NULL, 16);
59
+ texpect_create = strtoull(procfile_lineword(ff, l, 14), NULL, 16);
60
+ texpect_delete = strtoull(procfile_lineword(ff, l, 15), NULL, 16);
61
+ tsearch_restart = strtoull(procfile_lineword(ff, l, 16), NULL, 16);
62
+
63
+ if(!aentries) aentries = tentries;
64
+
65
+ // sum all the cpus together
66
+ asearched += tsearched; // conntrack.search
67
+ afound += tfound; // conntrack.search
68
+ anew += tnew; // conntrack.new
69
+ ainvalid += tinvalid; // conntrack.new
70
+ aignore += tignore; // conntrack.new
71
+ adelete += tdelete; // conntrack.changes
72
+ adelete_list += tdelete_list; // conntrack.changes
73
+ ainsert += tinsert; // conntrack.changes
74
+ ainsert_failed += tinsert_failed; // conntrack.errors
75
+ adrop += tdrop; // conntrack.errors
76
+ aearly_drop += tearly_drop; // conntrack.errors
77
+ aicmp_error += ticmp_error; // conntrack.errors
78
+ aexpect_new += texpect_new; // conntrack.expect
79
+ aexpect_create += texpect_create; // conntrack.expect
80
+ aexpect_delete += texpect_delete; // conntrack.expect
81
+ asearch_restart += tsearch_restart; // conntrack.search
82
+ }
83
+
84
+ RRDSET *st;
85
+
86
+ // --------------------------------------------------------------------
87
+
88
+ if(do_sockets) {
89
+ st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_sockets");
90
+ if(!st) {
91
+ st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_sockets", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Connections", "active connections", 1000, update_every, RRDSET_TYPE_LINE);
92
+
93
+ rrddim_add(st, "connections", NULL, 1, 1, RRDDIM_ABSOLUTE);
94
+ }
95
+ else rrdset_next(st);
96
+
97
+ rrddim_set(st, "connections", aentries);
98
+ rrdset_done(st);
99
+ }
100
+
101
+ // --------------------------------------------------------------------
102
+
103
+ if(do_new) {
104
+ st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_new");
105
+ if(!st) {
106
+ st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_new", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker New Connections", "connections/s", 1001, update_every, RRDSET_TYPE_LINE);
107
+
108
+ rrddim_add(st, "new", NULL, 1, 1, RRDDIM_INCREMENTAL);
109
+ rrddim_add(st, "ignore", NULL, -1, 1, RRDDIM_INCREMENTAL);
110
+ rrddim_add(st, "invalid", NULL, -1, 1, RRDDIM_INCREMENTAL);
111
+ }
112
+ else rrdset_next(st);
113
+
114
+ rrddim_set(st, "new", anew);
115
+ rrddim_set(st, "ignore", aignore);
116
+ rrddim_set(st, "invalid", ainvalid);
117
+ rrdset_done(st);
118
+ }
119
+
120
+ // --------------------------------------------------------------------
121
+
122
+ if(do_changes) {
123
+ st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_changes");
124
+ if(!st) {
125
+ st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_changes", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Changes", "changes/s", 1002, update_every, RRDSET_TYPE_LINE);
126
+ st->isdetail = 1;
127
+
128
+ rrddim_add(st, "inserted", NULL, 1, 1, RRDDIM_INCREMENTAL);
129
+ rrddim_add(st, "deleted", NULL, -1, 1, RRDDIM_INCREMENTAL);
130
+ rrddim_add(st, "delete_list", NULL, -1, 1, RRDDIM_INCREMENTAL);
131
+ }
132
+ else rrdset_next(st);
133
+
134
+ rrddim_set(st, "inserted", ainsert);
135
+ rrddim_set(st, "deleted", adelete);
136
+ rrddim_set(st, "delete_list", adelete_list);
137
+ rrdset_done(st);
138
+ }
139
+
140
+ // --------------------------------------------------------------------
141
+
142
+ if(do_expect) {
143
+ st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_expect");
144
+ if(!st) {
145
+ st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_expect", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Expectations", "expectations/s", 1003, update_every, RRDSET_TYPE_LINE);
146
+ st->isdetail = 1;
147
+
148
+ rrddim_add(st, "created", NULL, 1, 1, RRDDIM_INCREMENTAL);
149
+ rrddim_add(st, "deleted", NULL, -1, 1, RRDDIM_INCREMENTAL);
150
+ rrddim_add(st, "new", NULL, 1, 1, RRDDIM_INCREMENTAL);
151
+ }
152
+ else rrdset_next(st);
153
+
154
+ rrddim_set(st, "created", aexpect_create);
155
+ rrddim_set(st, "deleted", aexpect_delete);
156
+ rrddim_set(st, "new", aexpect_new);
157
+ rrdset_done(st);
158
+ }
159
+
160
+ // --------------------------------------------------------------------
161
+
162
+ if(do_search) {
163
+ st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_search");
164
+ if(!st) {
165
+ st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_search", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Searches", "searches/s", 1010, update_every, RRDSET_TYPE_LINE);
166
+ st->isdetail = 1;
167
+
168
+ rrddim_add(st, "searched", NULL, 1, 1, RRDDIM_INCREMENTAL);
169
+ rrddim_add(st, "restarted", NULL, -1, 1, RRDDIM_INCREMENTAL);
170
+ rrddim_add(st, "found", NULL, 1, 1, RRDDIM_INCREMENTAL);
171
+ }
172
+ else rrdset_next(st);
173
+
174
+ rrddim_set(st, "searched", asearched);
175
+ rrddim_set(st, "restarted", asearch_restart);
176
+ rrddim_set(st, "found", afound);
177
+ rrdset_done(st);
178
+ }
179
+
180
+ // --------------------------------------------------------------------
181
+
182
+ if(do_errors) {
183
+ st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_errors");
184
+ if(!st) {
185
+ st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_errors", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Errors", "events/s", 1005, update_every, RRDSET_TYPE_LINE);
186
+ st->isdetail = 1;
187
+
188
+ rrddim_add(st, "icmp_error", NULL, 1, 1, RRDDIM_INCREMENTAL);
189
+ rrddim_add(st, "insert_failed", NULL, -1, 1, RRDDIM_INCREMENTAL);
190
+ rrddim_add(st, "drop", NULL, -1, 1, RRDDIM_INCREMENTAL);
191
+ rrddim_add(st, "early_drop", NULL, -1, 1, RRDDIM_INCREMENTAL);
192
+ }
193
+ else rrdset_next(st);
194
+
195
+ rrddim_set(st, "icmp_error", aicmp_error);
196
+ rrddim_set(st, "insert_failed", ainsert_failed);
197
+ rrddim_set(st, "drop", adrop);
198
+ rrddim_set(st, "early_drop", aearly_drop);
199
+ rrdset_done(st);
200
+ }
201
+
202
+ return 0;
203
}
src/proc_net_stat_synproxy.c
+91
-91
@@ -1,127 +1,127 @@
1
#include "common.h"
2
3
-#define RRD_TYPE_NET_STAT_NETFILTER "netfilter"
4
-#define RRD_TYPE_NET_STAT_SYNPROXY "synproxy"
5
-#define RRD_TYPE_NET_STAT_SYNPROXY_LEN strlen(RRD_TYPE_NET_STAT_SYNPROXY)
3
+#define RRD_TYPE_NET_STAT_NETFILTER "netfilter"
4
+#define RRD_TYPE_NET_STAT_SYNPROXY "synproxy"
5
+#define RRD_TYPE_NET_STAT_SYNPROXY_LEN strlen(RRD_TYPE_NET_STAT_SYNPROXY)
6
7
int do_proc_net_stat_synproxy(int update_every, unsigned long long dt) {
8
- static int do_entries = -1, do_cookies = -1, do_syns = -1, do_reopened = -1;
9
- static procfile *ff = NULL;
8
+ static int do_entries = -1, do_cookies = -1, do_syns = -1, do_reopened = -1;
9
+ static procfile *ff = NULL;
10
11
- if(do_entries == -1) do_entries = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY entries", CONFIG_ONDEMAND_ONDEMAND);
12
- if(do_cookies == -1) do_cookies = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY cookies", CONFIG_ONDEMAND_ONDEMAND);
13
- if(do_syns == -1) do_syns = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY SYN received", CONFIG_ONDEMAND_ONDEMAND);
14
- if(do_reopened == -1) do_reopened = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY connections reopened", CONFIG_ONDEMAND_ONDEMAND);
11
+ if(do_entries == -1) do_entries = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY entries", CONFIG_ONDEMAND_ONDEMAND);
12
+ if(do_cookies == -1) do_cookies = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY cookies", CONFIG_ONDEMAND_ONDEMAND);
13
+ if(do_syns == -1) do_syns = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY SYN received", CONFIG_ONDEMAND_ONDEMAND);
14
+ if(do_reopened == -1) do_reopened = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY connections reopened", CONFIG_ONDEMAND_ONDEMAND);
15
16
- if(dt) {};
16
+ if(dt) {};
17
18
- if(!ff) {
19
- char filename[FILENAME_MAX + 1];
20
- snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/stat/synproxy");
21
- ff = procfile_open(config_get("plugin:proc:/proc/net/stat/synproxy", "filename to monitor", filename), " \t,:|", PROCFILE_FLAG_DEFAULT);
22
- }
23
- if(!ff) return 1;
18
+ if(!ff) {
19
+ char filename[FILENAME_MAX + 1];
20
+ snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/stat/synproxy");
21
+ ff = procfile_open(config_get("plugin:proc:/proc/net/stat/synproxy", "filename to monitor", filename), " \t,:|", PROCFILE_FLAG_DEFAULT);
22
+ }
23
+ if(!ff) return 1;
24
25
- ff = procfile_readall(ff);
26
- if(!ff) return 0; // we return 0, so that we will retry to open it next time
25
+ ff = procfile_readall(ff);
26
+ if(!ff) return 0; // we return 0, so that we will retry to open it next time
27
28
- // make sure we have 3 lines
29
- size_t lines = procfile_lines(ff), l;
30
- if(lines < 2) {
31
- error("/proc/net/stat/synproxy has %zu lines, expected no less than 2. Disabling it.", lines);
32
- return 1;
33
- }
28
+ // make sure we have 3 lines
29
+ size_t lines = procfile_lines(ff), l;
30
+ if(lines < 2) {
31
+ error("/proc/net/stat/synproxy has %zu lines, expected no less than 2. Disabling it.", lines);
32
+ return 1;
33
+ }
34
35
- unsigned long long entries = 0, syn_received = 0, cookie_invalid = 0, cookie_valid = 0, cookie_retrans = 0, conn_reopened = 0;
35
+ unsigned long long entries = 0, syn_received = 0, cookie_invalid = 0, cookie_valid = 0, cookie_retrans = 0, conn_reopened = 0;
36
37
- // synproxy gives its values per CPU
38
- for(l = 1; l < lines ;l++) {
39
- int words = procfile_linewords(ff, l);
40
- if(words < 6) continue;
37
+ // synproxy gives its values per CPU
38
+ for(l = 1; l < lines ;l++) {
39
+ int words = procfile_linewords(ff, l);
40
+ if(words < 6) continue;
41
42
- entries += strtoull(procfile_lineword(ff, l, 0), NULL, 16);
43
- syn_received += strtoull(procfile_lineword(ff, l, 1), NULL, 16);
44
- cookie_invalid += strtoull(procfile_lineword(ff, l, 2), NULL, 16);
45
- cookie_valid += strtoull(procfile_lineword(ff, l, 3), NULL, 16);
46
- cookie_retrans += strtoull(procfile_lineword(ff, l, 4), NULL, 16);
47
- conn_reopened += strtoull(procfile_lineword(ff, l, 5), NULL, 16);
48
- }
42
+ entries += strtoull(procfile_lineword(ff, l, 0), NULL, 16);
43
+ syn_received += strtoull(procfile_lineword(ff, l, 1), NULL, 16);
44
+ cookie_invalid += strtoull(procfile_lineword(ff, l, 2), NULL, 16);
45
+ cookie_valid += strtoull(procfile_lineword(ff, l, 3), NULL, 16);
46
+ cookie_retrans += strtoull(procfile_lineword(ff, l, 4), NULL, 16);
47
+ conn_reopened += strtoull(procfile_lineword(ff, l, 5), NULL, 16);
48
+ }
49
50
- unsigned long long events = entries + syn_received + cookie_invalid + cookie_valid + cookie_retrans + conn_reopened;
50
+ unsigned long long events = entries + syn_received + cookie_invalid + cookie_valid + cookie_retrans + conn_reopened;
51
52
- RRDSET *st;
52
+ RRDSET *st;
53
54
- // --------------------------------------------------------------------
54
+ // --------------------------------------------------------------------
55
56
- if((do_entries == CONFIG_ONDEMAND_ONDEMAND && events) || do_entries == CONFIG_ONDEMAND_YES) {
57
- do_entries = CONFIG_ONDEMAND_YES;
56
+ if((do_entries == CONFIG_ONDEMAND_ONDEMAND && events) || do_entries == CONFIG_ONDEMAND_YES) {
57
+ do_entries = CONFIG_ONDEMAND_YES;
58
59
- st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_entries");
60
- if(!st) {
61
- st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_entries", NULL, RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY Entries Used", "entries", 1004, update_every, RRDSET_TYPE_LINE);
59
+ st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_entries");
60
+ if(!st) {
61
+ st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_entries", NULL, RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY Entries Used", "entries", 1004, update_every, RRDSET_TYPE_LINE);
62
63
- rrddim_add(st, "entries", NULL, 1, 1, RRDDIM_ABSOLUTE);
64
- }
65
- else rrdset_next(st);
63
+ rrddim_add(st, "entries", NULL, 1, 1, RRDDIM_ABSOLUTE);
64
+ }
65
+ else rrdset_next(st);
66
67
- rrddim_set(st, "entries", entries);
68
- rrdset_done(st);
69
- }
67
+ rrddim_set(st, "entries", entries);
68
+ rrdset_done(st);
69
+ }
70
71
- // --------------------------------------------------------------------
71
+ // --------------------------------------------------------------------
72
73
- if((do_syns == CONFIG_ONDEMAND_ONDEMAND && events) || do_syns == CONFIG_ONDEMAND_YES) {
74
- do_syns = CONFIG_ONDEMAND_YES;
73
+ if((do_syns == CONFIG_ONDEMAND_ONDEMAND && events) || do_syns == CONFIG_ONDEMAND_YES) {
74
+ do_syns = CONFIG_ONDEMAND_YES;
75
76
- st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_syn_received");
77
- if(!st) {
78
- st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_syn_received", NULL, RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY SYN Packets received", "SYN/s", 1001, update_every, RRDSET_TYPE_LINE);
76
+ st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_syn_received");
77
+ if(!st) {
78
+ st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_syn_received", NULL, RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY SYN Packets received", "SYN/s", 1001, update_every, RRDSET_TYPE_LINE);
79
80
- rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
81
- }
82
- else rrdset_next(st);
80
+ rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
81
+ }
82
+ else rrdset_next(st);
83
84
- rrddim_set(st, "received", syn_received);
85
- rrdset_done(st);
86
- }
84
+ rrddim_set(st, "received", syn_received);
85
+ rrdset_done(st);
86
+ }
87
88
- // --------------------------------------------------------------------
88
+ // --------------------------------------------------------------------
89
90
- if((do_reopened == CONFIG_ONDEMAND_ONDEMAND && events) || do_reopened == CONFIG_ONDEMAND_YES) {
91
- do_reopened = CONFIG_ONDEMAND_YES;
90
+ if((do_reopened == CONFIG_ONDEMAND_ONDEMAND && events) || do_reopened == CONFIG_ONDEMAND_YES) {
91
+ do_reopened = CONFIG_ONDEMAND_YES;
92
93
- st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_conn_reopened");
94
- if(!st) {
95
- st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_conn_reopened", NULL, RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY Connections Reopened", "connections/s", 1003, update_every, RRDSET_TYPE_LINE);
93
+ st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_conn_reopened");
94
+ if(!st) {
95
+ st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_conn_reopened", NULL, RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY Connections Reopened", "connections/s", 1003, update_every, RRDSET_TYPE_LINE);
96
97
- rrddim_add(st, "reopened", NULL, 1, 1, RRDDIM_INCREMENTAL);
98
- }
99
- else rrdset_next(st);
97
+ rrddim_add(st, "reopened", NULL, 1, 1, RRDDIM_INCREMENTAL);
98
+ }
99
+ else rrdset_next(st);
100
101
- rrddim_set(st, "reopened", conn_reopened);
102
- rrdset_done(st);
103
- }
101
+ rrddim_set(st, "reopened", conn_reopened);
102
+ rrdset_done(st);
103
+ }
104
105
- // --------------------------------------------------------------------
105
+ // --------------------------------------------------------------------
106
107
- if((do_cookies == CONFIG_ONDEMAND_ONDEMAND && events) || do_cookies == CONFIG_ONDEMAND_YES) {
108
- do_cookies = CONFIG_ONDEMAND_YES;
107
+ if((do_cookies == CONFIG_ONDEMAND_ONDEMAND && events) || do_cookies == CONFIG_ONDEMAND_YES) {
108
+ do_cookies = CONFIG_ONDEMAND_YES;
109
110
- st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_cookies");
111
- if(!st) {
112
- st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_cookies", NULL, RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY TCP Cookies", "cookies/s", 1002, update_every, RRDSET_TYPE_LINE);
110
+ st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_cookies");
111
+ if(!st) {
112
+ st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_cookies", NULL, RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY TCP Cookies", "cookies/s", 1002, update_every, RRDSET_TYPE_LINE);
113
114
- rrddim_add(st, "valid", NULL, 1, 1, RRDDIM_INCREMENTAL);
115
- rrddim_add(st, "invalid", NULL, -1, 1, RRDDIM_INCREMENTAL);
116
- rrddim_add(st, "retransmits", NULL, 1, 1, RRDDIM_INCREMENTAL);
117
- }
118
- else rrdset_next(st);
114
+ rrddim_add(st, "valid", NULL, 1, 1, RRDDIM_INCREMENTAL);
115
+ rrddim_add(st, "invalid", NULL, -1, 1, RRDDIM_INCREMENTAL);
116
+ rrddim_add(st, "retransmits", NULL, 1, 1, RRDDIM_INCREMENTAL);
117
+ }
118
+ else rrdset_next(st);
119
120
- rrddim_set(st, "valid", cookie_valid);
121
- rrddim_set(st, "invalid", cookie_invalid);
122
- rrddim_set(st, "retransmits", cookie_retrans);
123
- rrdset_done(st);
124
- }
120
+ rrddim_set(st, "valid", cookie_valid);
121
+ rrddim_set(st, "invalid", cookie_invalid);
122
+ rrddim_set(st, "retransmits", cookie_retrans);
123
+ rrdset_done(st);
124
+ }
125
126
- return 0;
126
+ return 0;
127
}
src/proc_self_mountinfo.c
+170
-170
@@ -3,234 +3,234 @@
3
// find the mount info with the given major:minor
4
// in the supplied linked list of mountinfo structures
5
struct mountinfo *mountinfo_find(struct mountinfo *root, unsigned long major, unsigned long minor) {
6
- struct mountinfo *mi;
6
+ struct mountinfo *mi;
7
8
- for(mi = root; mi ; mi = mi->next)
9
- if(mi->major == major && mi->minor == minor)
10
- return mi;
8
+ for(mi = root; mi ; mi = mi->next)
9
+ if(mi->major == major && mi->minor == minor)
10
+ return mi;
11
12
- return NULL;
12
+ return NULL;
13
}
14
15
// find the mount info with the given filesystem and mount_source
16
// in the supplied linked list of mountinfo structures
17
struct mountinfo *mountinfo_find_by_filesystem_mount_source(struct mountinfo *root, const char *filesystem, const char *mount_source) {
18
- struct mountinfo *mi;
19
- uint32_t filesystem_hash = simple_hash(filesystem), mount_source_hash = simple_hash(mount_source);
20
-
21
- for(mi = root; mi ; mi = mi->next)
22
- if(mi->filesystem
23
- && mi->mount_source
24
- && mi->filesystem_hash == filesystem_hash
25
- && mi->mount_source_hash == mount_source_hash
26
- && !strcmp(mi->filesystem, filesystem)
27
- && !strcmp(mi->mount_source, mount_source))
28
- return mi;
29
-
30
- return NULL;
18
+ struct mountinfo *mi;
19
+ uint32_t filesystem_hash = simple_hash(filesystem), mount_source_hash = simple_hash(mount_source);
20
+
21
+ for(mi = root; mi ; mi = mi->next)
22
+ if(mi->filesystem
23
+ && mi->mount_source
24
+ && mi->filesystem_hash == filesystem_hash
25
+ && mi->mount_source_hash == mount_source_hash
26
+ && !strcmp(mi->filesystem, filesystem)
27
+ && !strcmp(mi->mount_source, mount_source))
28
+ return mi;
29
+
30
+ return NULL;
31
}
32
33
struct mountinfo *mountinfo_find_by_filesystem_super_option(struct mountinfo *root, const char *filesystem, const char *super_options) {
34
- struct mountinfo *mi;
35
- uint32_t filesystem_hash = simple_hash(filesystem);
34
+ struct mountinfo *mi;
35
+ uint32_t filesystem_hash = simple_hash(filesystem);
36
37
- size_t solen = strlen(super_options);
37
+ size_t solen = strlen(super_options);
38
39
- for(mi = root; mi ; mi = mi->next)
40
- if(mi->filesystem
41
- && mi->super_options
42
- && mi->filesystem_hash == filesystem_hash
43
- && !strcmp(mi->filesystem, filesystem)) {
39
+ for(mi = root; mi ; mi = mi->next)
40
+ if(mi->filesystem
41
+ && mi->super_options
42
+ && mi->filesystem_hash == filesystem_hash
43
+ && !strcmp(mi->filesystem, filesystem)) {
44
45
- // super_options is a comma separated list
46
- char *s = mi->super_options, *e;
47
- while(*s) {
48
- e = s + 1;
49
- while(*e && *e != ',') e++;
45
+ // super_options is a comma separated list
46
+ char *s = mi->super_options, *e;
47
+ while(*s) {
48
+ e = s + 1;
49
+ while(*e && *e != ',') e++;
50
51
- size_t len = e - s;
52
- if(len == solen && !strncmp(s, super_options, len))
53
- return mi;
51
+ size_t len = e - s;
52
+ if(len == solen && !strncmp(s, super_options, len))
53
+ return mi;
54
55
- if(*e == ',') s = ++e;
56
- else s = e;
57
- }
58
- }
55
+ if(*e == ',') s = ++e;
56
+ else s = e;
57
+ }
58
+ }
59
60
- return NULL;
60
+ return NULL;
61
}
62
63
64
// free a linked list of mountinfo structures
65
void mountinfo_free(struct mountinfo *mi) {
66
- if(unlikely(!mi))
67
- return;
66
+ if(unlikely(!mi))
67
+ return;
68
69
- if(likely(mi->next))
70
- mountinfo_free(mi->next);
69
+ if(likely(mi->next))
70
+ mountinfo_free(mi->next);
71
72
- freez(mi->root);
73
- freez(mi->mount_point);
74
- freez(mi->mount_options);
72
+ freez(mi->root);
73
+ freez(mi->mount_point);
74
+ freez(mi->mount_options);
75
76
/*
77
- if(mi->optional_fields_count) {
78
- int i;
79
- for(i = 0; i < mi->optional_fields_count ; i++)
80
- free(*mi->optional_fields[i]);
81
- }
82
- free(mi->optional_fields);
77
+ if(mi->optional_fields_count) {
78
+ int i;
79
+ for(i = 0; i < mi->optional_fields_count ; i++)
80
+ free(*mi->optional_fields[i]);
81
+ }
82
+ free(mi->optional_fields);
83
*/
84
- freez(mi->filesystem);
85
- freez(mi->mount_source);
86
- freez(mi->super_options);
87
- freez(mi);
84
+ freez(mi->filesystem);
85
+ freez(mi->mount_source);
86
+ freez(mi->super_options);
87
+ freez(mi);
88
}
89
90
static char *strdupz_decoding_octal(const char *string) {
91
- char *buffer = strdupz(string);
92
-
93
- char *d = buffer;
94
- const char *s = string;
95
-
96
- while(*s) {
97
- if(unlikely(*s == '\\')) {
98
- s++;
99
- if(likely(isdigit(*s) && isdigit(s[1]) && isdigit(s[2]))) {
100
- char c = *s++ - '0';
101
- c <<= 3;
102
- c |= *s++ - '0';
103
- c <<= 3;
104
- c |= *s++ - '0';
105
- *d++ = c;
106
- }
107
- else *d++ = '_';
108
- }
109
- else *d++ = *s++;
110
- }
111
- *d = '\0';
112
-
113
- return buffer;
91
+ char *buffer = strdupz(string);
92
+
93
+ char *d = buffer;
94
+ const char *s = string;
95
+
96
+ while(*s) {
97
+ if(unlikely(*s == '\\')) {
98
+ s++;
99
+ if(likely(isdigit(*s) && isdigit(s[1]) && isdigit(s[2]))) {
100
+ char c = *s++ - '0';
101
+ c <<= 3;
102
+ c |= *s++ - '0';
103
+ c <<= 3;
104
+ c |= *s++ - '0';
105
+ *d++ = c;
106
+ }
107
+ else *d++ = '_';
108
+ }
109
+ else *d++ = *s++;
110
+ }
111
+ *d = '\0';
112
+
113
+ return buffer;
114
}
115
116
// read the whole mountinfo into a linked list
117
struct mountinfo *mountinfo_read() {
118
- procfile *ff = NULL;
118
+ procfile *ff = NULL;
119
120
- char filename[FILENAME_MAX + 1];
121
- snprintfz(filename, FILENAME_MAX, "%s/proc/self/mountinfo", global_host_prefix);
122
- ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT);
123
- if(!ff) {
124
- snprintfz(filename, FILENAME_MAX, "%s/proc/1/mountinfo", global_host_prefix);
125
- ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT);
126
- if(!ff) return NULL;
127
- }
120
+ char filename[FILENAME_MAX + 1];
121
+ snprintfz(filename, FILENAME_MAX, "%s/proc/self/mountinfo", global_host_prefix);
122
+ ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT);
123
+ if(!ff) {
124
+ snprintfz(filename, FILENAME_MAX, "%s/proc/1/mountinfo", global_host_prefix);
125
+ ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT);
126
+ if(!ff) return NULL;
127
+ }
128
129
- ff = procfile_readall(ff);
130
- if(!ff) return NULL;
129
+ ff = procfile_readall(ff);
130
+ if(!ff) return NULL;
131
132
- struct mountinfo *root = NULL, *last = NULL, *mi = NULL;
132
+ struct mountinfo *root = NULL, *last = NULL, *mi = NULL;
133
134
- unsigned long l, lines = procfile_lines(ff);
135
- for(l = 0; l < lines ;l++) {
136
- if(procfile_linewords(ff, l) < 5)
137
- continue;
134
+ unsigned long l, lines = procfile_lines(ff);
135
+ for(l = 0; l < lines ;l++) {
136
+ if(procfile_linewords(ff, l) < 5)
137
+ continue;
138
139
- mi = mallocz(sizeof(struct mountinfo));
139
+ mi = mallocz(sizeof(struct mountinfo));
140
141
- if(unlikely(!root))
142
- root = last = mi;
143
- else
144
- last->next = mi;
141
+ if(unlikely(!root))
142
+ root = last = mi;
143
+ else
144
+ last->next = mi;
145
146
- last = mi;
147
- mi->next = NULL;
146
+ last = mi;
147
+ mi->next = NULL;
148
149
- unsigned long w = 0;
150
- mi->id = strtoul(procfile_lineword(ff, l, w), NULL, 10); w++;
151
- mi->parentid = strtoul(procfile_lineword(ff, l, w), NULL, 10); w++;
149
+ unsigned long w = 0;
150
+ mi->id = strtoul(procfile_lineword(ff, l, w), NULL, 10); w++;
151
+ mi->parentid = strtoul(procfile_lineword(ff, l, w), NULL, 10); w++;
152
153
- char *major = procfile_lineword(ff, l, w), *minor; w++;
154
- for(minor = major; *minor && *minor != ':' ;minor++) ;
155
- *minor = '\0';
156
- minor++;
153
+ char *major = procfile_lineword(ff, l, w), *minor; w++;
154
+ for(minor = major; *minor && *minor != ':' ;minor++) ;
155
+ *minor = '\0';
156
+ minor++;
157
158
- mi->major = strtoul(major, NULL, 10);
159
- mi->minor = strtoul(minor, NULL, 10);
158
+ mi->major = strtoul(major, NULL, 10);
159
+ mi->minor = strtoul(minor, NULL, 10);
160
161
- mi->root = strdupz(procfile_lineword(ff, l, w)); w++;
162
- mi->root_hash = simple_hash(mi->root);
161
+ mi->root = strdupz(procfile_lineword(ff, l, w)); w++;
162
+ mi->root_hash = simple_hash(mi->root);
163
164
- mi->mount_point = strdupz_decoding_octal(procfile_lineword(ff, l, w)); w++;
165
- mi->mount_point_hash = simple_hash(mi->mount_point);
164
+ mi->mount_point = strdupz_decoding_octal(procfile_lineword(ff, l, w)); w++;
165
+ mi->mount_point_hash = simple_hash(mi->mount_point);
166
167
- mi->mount_options = strdupz(procfile_lineword(ff, l, w)); w++;
167
+ mi->mount_options = strdupz(procfile_lineword(ff, l, w)); w++;
168
169
- // count the optional fields
169
+ // count the optional fields
170
/*
171
- unsigned long wo = w;
171
+ unsigned long wo = w;
172
*/
173
- mi->optional_fields_count = 0;
174
- char *s = procfile_lineword(ff, l, w);
175
- while(*s && *s != '-') {
176
- w++;
177
- s = procfile_lineword(ff, l, w);
178
- mi->optional_fields_count++;
179
- }
173
+ mi->optional_fields_count = 0;
174
+ char *s = procfile_lineword(ff, l, w);
175
+ while(*s && *s != '-') {
176
+ w++;
177
+ s = procfile_lineword(ff, l, w);
178
+ mi->optional_fields_count++;
179
+ }
180
181
/*
182
- if(unlikely(mi->optional_fields_count)) {
183
- // we have some optional fields
184
- // read them into a new array of pointers;
185
-
186
- mi->optional_fields = malloc(mi->optional_fields_count * sizeof(char *));
187
- if(unlikely(!mi->optional_fields))
188
- fatal("Cannot allocate memory for %d mountinfo optional fields", mi->optional_fields_count);
189
-
190
- int i;
191
- for(i = 0; i < mi->optional_fields_count ; i++) {
192
- *mi->optional_fields[wo] = strdup(procfile_lineword(ff, l, w));
193
- if(!mi->optional_fields[wo]) fatal("Cannot allocate memory");
194
- wo++;
195
- }
196
- }
197
- else
198
- mi->optional_fields = NULL;
182
+ if(unlikely(mi->optional_fields_count)) {
183
+ // we have some optional fields
184
+ // read them into a new array of pointers;
185
+
186
+ mi->optional_fields = malloc(mi->optional_fields_count * sizeof(char *));
187
+ if(unlikely(!mi->optional_fields))
188
+ fatal("Cannot allocate memory for %d mountinfo optional fields", mi->optional_fields_count);
189
+
190
+ int i;
191
+ for(i = 0; i < mi->optional_fields_count ; i++) {
192
+ *mi->optional_fields[wo] = strdup(procfile_lineword(ff, l, w));
193
+ if(!mi->optional_fields[wo]) fatal("Cannot allocate memory");
194
+ wo++;
195
+ }
196
+ }
197
+ else
198
+ mi->optional_fields = NULL;
199
*/
200
201
- if(likely(*s == '-')) {
202
- w++;
201
+ if(likely(*s == '-')) {
202
+ w++;
203
204
- mi->filesystem = strdupz(procfile_lineword(ff, l, w)); w++;
205
- mi->filesystem_hash = simple_hash(mi->filesystem);
204
+ mi->filesystem = strdupz(procfile_lineword(ff, l, w)); w++;
205
+ mi->filesystem_hash = simple_hash(mi->filesystem);
206
207
- mi->mount_source = strdupz(procfile_lineword(ff, l, w)); w++;
208
- mi->mount_source_hash = simple_hash(mi->mount_source);
207
+ mi->mount_source = strdupz(procfile_lineword(ff, l, w)); w++;
208
+ mi->mount_source_hash = simple_hash(mi->mount_source);
209
210
- mi->super_options = strdupz(procfile_lineword(ff, l, w)); w++;
211
- }
212
- else {
213
- mi->filesystem = NULL;
214
- mi->mount_source = NULL;
215
- mi->super_options = NULL;
216
- }
210
+ mi->super_options = strdupz(procfile_lineword(ff, l, w)); w++;
211
+ }
212
+ else {
213
+ mi->filesystem = NULL;
214
+ mi->mount_source = NULL;
215
+ mi->super_options = NULL;
216
+ }
217
218
/*
219
- info("MOUNTINFO: %u %u %u:%u root '%s', mount point '%s', mount options '%s', filesystem '%s', mount source '%s', super options '%s'",
220
- mi->id,
221
- mi->parentid,
222
- mi->major,
223
- mi->minor,
224
- mi->root,
225
- mi->mount_point,
226
- mi->mount_options,
227
- mi->filesystem,
228
- mi->mount_source,
229
- mi->super_options
230
- );
219
+ info("MOUNTINFO: %u %u %u:%u root '%s', mount point '%s', mount options '%s', filesystem '%s', mount source '%s', super options '%s'",
220
+ mi->id,
221
+ mi->parentid,
222
+ mi->major,
223
+ mi->minor,
224
+ mi->root,
225
+ mi->mount_point,
226
+ mi->mount_options,
227
+ mi->filesystem,
228
+ mi->mount_source,
229
+ mi->super_options
230
+ );
231
*/
232
- }
232
+ }
233
234
- procfile_close(ff);
235
- return root;
234
+ procfile_close(ff);
235
+ return root;
236
}
src/proc_self_mountinfo.h
+17
-17
@@ -2,32 +2,32 @@
2
#define NETDATA_PROC_SELF_MOUNTINFO_H 1
3
4
struct mountinfo {
5
- long id; // mount ID: unique identifier of the mount (may be reused after umount(2)).
6
- long parentid; // parent ID: ID of parent mount (or of self for the top of the mount tree).
7
- unsigned long major; // major:minor: value of st_dev for files on filesystem (see stat(2)).
8
- unsigned long minor;
5
+ long id; // mount ID: unique identifier of the mount (may be reused after umount(2)).
6
+ long parentid; // parent ID: ID of parent mount (or of self for the top of the mount tree).
7
+ unsigned long major; // major:minor: value of st_dev for files on filesystem (see stat(2)).
8
+ unsigned long minor;
9
10
- char *root; // root: root of the mount within the filesystem.
11
- uint32_t root_hash;
10
+ char *root; // root: root of the mount within the filesystem.
11
+ uint32_t root_hash;
12
13
- char *mount_point; // mount point: mount point relative to the process's root.
14
- uint32_t mount_point_hash;
13
+ char *mount_point; // mount point: mount point relative to the process's root.
14
+ uint32_t mount_point_hash;
15
16
- char *mount_options; // mount options: per-mount options.
16
+ char *mount_options; // mount options: per-mount options.
17
18
- int optional_fields_count;
18
+ int optional_fields_count;
19
/*
20
- char ***optional_fields; // optional fields: zero or more fields of the form "tag[:value]".
20
+ char ***optional_fields; // optional fields: zero or more fields of the form "tag[:value]".
21
*/
22
- char *filesystem; // filesystem type: name of filesystem in the form "type[.subtype]".
23
- uint32_t filesystem_hash;
22
+ char *filesystem; // filesystem type: name of filesystem in the form "type[.subtype]".
23
+ uint32_t filesystem_hash;
24
25
- char *mount_source; // mount source: filesystem-specific information or "none".
26
- uint32_t mount_source_hash;
25
+ char *mount_source; // mount source: filesystem-specific information or "none".
26
+ uint32_t mount_source_hash;
27
28
- char *super_options; // super options: per-superblock options.
28
+ char *super_options; // super options: per-superblock options.
29
30
- struct mountinfo *next;
30
+ struct mountinfo *next;
31
};
32
33
extern struct mountinfo *mountinfo_find(struct mountinfo *root, unsigned long major, unsigned long minor);
src/proc_softirqs.c
+151
-151
@@ -3,11 +3,11 @@
3
#define MAX_INTERRUPT_NAME 50
4
5
struct interrupt {
6
- int used;
7
- char *id;
8
- char name[MAX_INTERRUPT_NAME + 1];
9
- unsigned long long total;
10
- unsigned long long value[];
6
+ int used;
7
+ char *id;
8
+ char name[MAX_INTERRUPT_NAME + 1];
9
+ unsigned long long total;
10
+ unsigned long long value[];
11
};
12
13
// since each interrupt is variable in size
@@ -18,157 +18,157 @@ struct interrupt {
18
#define irrindex(base, line, cpus) ((struct interrupt *)&((char *)(base))[line * recordsize(cpus)])
19
20
static inline struct interrupt *get_interrupts_array(int lines, int cpus) {
21
- static struct interrupt *irrs = NULL;
22
- static int allocated = 0;
21
+ static struct interrupt *irrs = NULL;
22
+ static int allocated = 0;
23
24
- if(lines < allocated) return irrs;
25
- else {
26
- irrs = (struct interrupt *)reallocz(irrs, lines * recordsize(cpus));
27
- allocated = lines;
28
- }
24
+ if(lines < allocated) return irrs;
25
+ else {
26
+ irrs = (struct interrupt *)reallocz(irrs, lines * recordsize(cpus));
27
+ allocated = lines;
28
+ }
29
30
- return irrs;
30
+ return irrs;
31
}
32
33
int do_proc_softirqs(int update_every, unsigned long long dt) {
34
- static procfile *ff = NULL;
35
- static int cpus = -1, do_per_core = -1;
34
+ static procfile *ff = NULL;
35
+ static int cpus = -1, do_per_core = -1;
36
37
- struct interrupt *irrs = NULL;
38
-
39
- if(dt) {};
37
+ struct interrupt *irrs = NULL;
38
+
39
+ if(dt) {};
40
41
- if(do_per_core == -1) do_per_core = config_get_boolean("plugin:proc:/proc/softirqs", "interrupts per core", 1);
42
-
43
- if(!ff) {
44
- char filename[FILENAME_MAX + 1];
45
- snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/softirqs");
46
- ff = procfile_open(config_get("plugin:proc:/proc/softirqs", "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT);
47
- }
48
- if(!ff) return 1;
49
-
50
- ff = procfile_readall(ff);
51
- if(!ff) return 0; // we return 0, so that we will retry to open it next time
52
-
53
- uint32_t lines = procfile_lines(ff), l;
54
- uint32_t words = procfile_linewords(ff, 0), w;
55
-
56
- if(!lines) {
57
- error("Cannot read /proc/softirqs, zero lines reported.");
58
- return 1;
59
- }
60
-
61
- // find how many CPUs are there
62
- if(cpus == -1) {
63
- cpus = 0;
64
- for(w = 0; w < words ; w++) {
65
- if(strncmp(procfile_lineword(ff, 0, w), "CPU", 3) == 0)
66
- cpus++;
67
- }
68
- }
69
-
70
- if(!cpus) {
71
- error("PLUGIN: PROC_SOFTIRQS: Cannot find the number of CPUs in /proc/softirqs");
72
- return 1;
73
- }
74
-
75
- // allocate the size we need;
76
- irrs = get_interrupts_array(lines, cpus);
77
- irrs[0].used = 0;
78
-
79
- // loop through all lines
80
- for(l = 1; l < lines ;l++) {
81
- struct interrupt *irr = irrindex(irrs, l, cpus);
82
- irr->used = 0;
83
- irr->total = 0;
84
-
85
- words = procfile_linewords(ff, l);
86
- if(!words) continue;
87
-
88
- irr->id = procfile_lineword(ff, l, 0);
89
- if(!irr->id || !irr->id[0]) continue;
90
-
91
- int idlen = strlen(irr->id);
92
- if(irr->id[idlen - 1] == ':')
93
- irr->id[idlen - 1] = '\0';
94
-
95
- int c;
96
- for(c = 0; c < cpus ;c++) {
97
- if((c + 1) < (int)words)
98
- irr->value[c] = strtoull(procfile_lineword(ff, l, (uint32_t)(c + 1)), NULL, 10);
99
- else
100
- irr->value[c] = 0;
101
-
102
- irr->total += irr->value[c];
103
- }
104
-
105
- strncpyz(irr->name, irr->id, MAX_INTERRUPT_NAME);
106
-
107
- irr->used = 1;
108
- }
109
-
110
- RRDSET *st;
111
-
112
- // --------------------------------------------------------------------
113
-
114
- st = rrdset_find_bytype("system", "softirqs");
115
- if(!st) {
116
- st = rrdset_create("system", "softirqs", NULL, "softirqs", NULL, "System softirqs", "softirqs/s", 950, update_every, RRDSET_TYPE_STACKED);
117
-
118
- for(l = 0; l < lines ;l++) {
119
- struct interrupt *irr = irrindex(irrs, l, cpus);
120
- if(!irr->used) continue;
121
- rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL);
122
- }
123
- }
124
- else rrdset_next(st);
125
-
126
- for(l = 0; l < lines ;l++) {
127
- struct interrupt *irr = irrindex(irrs, l, cpus);
128
- if(!irr->used) continue;
129
- rrddim_set(st, irr->id, irr->total);
130
- }
131
- rrdset_done(st);
132
-
133
- if(do_per_core) {
134
- int c;
135
-
136
- for(c = 0; c < cpus ; c++) {
137
- char id[256+1];
138
- snprintfz(id, 256, "cpu%d_softirqs", c);
139
-
140
- st = rrdset_find_bytype("cpu", id);
141
- if(!st) {
142
- // find if everything is zero
143
- unsigned long long core_sum = 0 ;
144
- for(l = 0; l < lines ;l++) {
145
- struct interrupt *irr = irrindex(irrs, l, cpus);
146
- if(!irr->used) continue;
147
- core_sum += irr->value[c];
148
- }
149
- if(core_sum == 0) continue; // try next core
150
-
151
- char name[256+1], title[256+1];
152
- snprintfz(name, 256, "cpu%d_softirqs", c);
153
- snprintfz(title, 256, "CPU%d softirqs", c);
154
- st = rrdset_create("cpu", id, name, "softirqs", "cpu.softirqs", title, "softirqs/s", 3000 + c, update_every, RRDSET_TYPE_STACKED);
155
-
156
- for(l = 0; l < lines ;l++) {
157
- struct interrupt *irr = irrindex(irrs, l, cpus);
158
- if(!irr->used) continue;
159
- rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL);
160
- }
161
- }
162
- else rrdset_next(st);
163
-
164
- for(l = 0; l < lines ;l++) {
165
- struct interrupt *irr = irrindex(irrs, l, cpus);
166
- if(!irr->used) continue;
167
- rrddim_set(st, irr->id, irr->value[c]);
168
- }
169
- rrdset_done(st);
170
- }
171
- }
172
-
173
- return 0;
41
+ if(do_per_core == -1) do_per_core = config_get_boolean("plugin:proc:/proc/softirqs", "interrupts per core", 1);
42
+
43
+ if(!ff) {
44
+ char filename[FILENAME_MAX + 1];
45
+ snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/softirqs");
46
+ ff = procfile_open(config_get("plugin:proc:/proc/softirqs", "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT);
47
+ }
48
+ if(!ff) return 1;
49
+
50
+ ff = procfile_readall(ff);
51
+ if(!ff) return 0; // we return 0, so that we will retry to open it next time
52
+
53
+ uint32_t lines = procfile_lines(ff), l;
54
+ uint32_t words = procfile_linewords(ff, 0), w;
55
+
56
+ if(!lines) {
57
+ error("Cannot read /proc/softirqs, zero lines reported.");
58
+ return 1;
59
+ }
60
+
61
+ // find how many CPUs are there
62
+ if(cpus == -1) {
63
+ cpus = 0;
64
+ for(w = 0; w < words ; w++) {
65
+ if(strncmp(procfile_lineword(ff, 0, w), "CPU", 3) == 0)
66
+ cpus++;
67
+ }
68
+ }
69
+
70
+ if(!cpus) {
71
+ error("PLUGIN: PROC_SOFTIRQS: Cannot find the number of CPUs in /proc/softirqs");
72
+ return 1;
73
+ }
74
+
75
+ // allocate the size we need;
76
+ irrs = get_interrupts_array(lines, cpus);
77
+ irrs[0].used = 0;
78
+
79
+ // loop through all lines
80
+ for(l = 1; l < lines ;l++) {
81
+ struct interrupt *irr = irrindex(irrs, l, cpus);
82
+ irr->used = 0;
83
+ irr->total = 0;
84
+
85
+ words = procfile_linewords(ff, l);
86
+ if(!words) continue;
87
+
88
+ irr->id = procfile_lineword(ff, l, 0);
89
+ if(!irr->id || !irr->id[0]) continue;
90
+
91
+ int idlen = strlen(irr->id);
92
+ if(irr->id[idlen - 1] == ':')
93
+ irr->id[idlen - 1] = '\0';
94
+
95
+ int c;
96
+ for(c = 0; c < cpus ;c++) {
97
+ if((c + 1) < (int)words)
98
+ irr->value[c] = strtoull(procfile_lineword(ff, l, (uint32_t)(c + 1)), NULL, 10);
99
+ else
100
+ irr->value[c] = 0;
101
+
102
+ irr->total += irr->value[c];
103
+ }
104
+
105
+ strncpyz(irr->name, irr->id, MAX_INTERRUPT_NAME);
106
+
107
+ irr->used = 1;
108
+ }
109
+
110
+ RRDSET *st;
111
+
112
+ // --------------------------------------------------------------------
113
+
114
+ st = rrdset_find_bytype("system", "softirqs");
115
+ if(!st) {
116
+ st = rrdset_create("system", "softirqs", NULL, "softirqs", NULL, "System softirqs", "softirqs/s", 950, update_every, RRDSET_TYPE_STACKED);
117
+
118
+ for(l = 0; l < lines ;l++) {
119
+ struct interrupt *irr = irrindex(irrs, l, cpus);
120
+ if(!irr->used) continue;
121
+ rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL);
122
+ }
123
+ }
124
+ else rrdset_next(st);
125
+
126
+ for(l = 0; l < lines ;l++) {
127
+ struct interrupt *irr = irrindex(irrs, l, cpus);
128
+ if(!irr->used) continue;
129
+ rrddim_set(st, irr->id, irr->total);
130
+ }
131
+ rrdset_done(st);
132
+
133
+ if(do_per_core) {
134
+ int c;
135
+
136
+ for(c = 0; c < cpus ; c++) {
137
+ char id[256+1];
138
+ snprintfz(id, 256, "cpu%d_softirqs", c);
139
+
140
+ st = rrdset_find_bytype("cpu", id);
141
+ if(!st) {
142
+ // find if everything is zero
143
+ unsigned long long core_sum = 0 ;
144
+ for(l = 0; l < lines ;l++) {
145
+ struct interrupt *irr = irrindex(irrs, l, cpus);
146
+ if(!irr->used) continue;
147
+ core_sum += irr->value[c];
148
+ }
149
+ if(core_sum == 0) continue; // try next core
150
+
151
+ char name[256+1], title[256+1];
152
+ snprintfz(name, 256, "cpu%d_softirqs", c);
153
+ snprintfz(title, 256, "CPU%d softirqs", c);
154
+ st = rrdset_create("cpu", id, name, "softirqs", "cpu.softirqs", title, "softirqs/s", 3000 + c, update_every, RRDSET_TYPE_STACKED);
155
+
156
+ for(l = 0; l < lines ;l++) {
157
+ struct interrupt *irr = irrindex(irrs, l, cpus);
158
+ if(!irr->used) continue;
159
+ rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL);
160
+ }
161
+ }
162
+ else rrdset_next(st);
163
+
164
+ for(l = 0; l < lines ;l++) {
165
+ struct interrupt *irr = irrindex(irrs, l, cpus);
166
+ if(!irr->used) continue;
167
+ rrddim_set(st, irr->id, irr->value[c]);
168
+ }
169
+ rrdset_done(st);
170
+ }
171
+ }
172
+
173
+ return 0;
174
}
src/proc_stat.c
+207
-207
@@ -1,211 +1,211 @@
1
#include "common.h"
2
3
int do_proc_stat(int update_every, unsigned long long dt) {
4
- (void)dt;
5
-
6
- static procfile *ff = NULL;
7
- static int do_cpu = -1, do_cpu_cores = -1, do_interrupts = -1, do_context = -1, do_forks = -1, do_processes = -1;
8
- static uint32_t hash_intr, hash_ctxt, hash_processes, hash_procs_running, hash_procs_blocked;
9
-
10
- if(unlikely(do_cpu == -1)) {
11
- do_cpu = config_get_boolean("plugin:proc:/proc/stat", "cpu utilization", 1);
12
- do_cpu_cores = config_get_boolean("plugin:proc:/proc/stat", "per cpu core utilization", 1);
13
- do_interrupts = config_get_boolean("plugin:proc:/proc/stat", "cpu interrupts", 1);
14
- do_context = config_get_boolean("plugin:proc:/proc/stat", "context switches", 1);
15
- do_forks = config_get_boolean("plugin:proc:/proc/stat", "processes started", 1);
16
- do_processes = config_get_boolean("plugin:proc:/proc/stat", "processes running", 1);
17
-
18
- hash_intr = simple_hash("intr");
19
- hash_ctxt = simple_hash("ctxt");
20
- hash_processes = simple_hash("processes");
21
- hash_procs_running = simple_hash("procs_running");
22
- hash_procs_blocked = simple_hash("procs_blocked");
23
- }
24
-
25
- if(unlikely(!ff)) {
26
- char filename[FILENAME_MAX + 1];
27
- snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/stat");
28
- ff = procfile_open(config_get("plugin:proc:/proc/stat", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
29
- if(unlikely(!ff)) return 1;
30
- }
31
-
32
- ff = procfile_readall(ff);
33
- if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time
34
-
35
- uint32_t lines = procfile_lines(ff), l;
36
- uint32_t words;
37
-
38
- unsigned long long processes = 0, running = 0 , blocked = 0;
39
- RRDSET *st;
40
-
41
- for(l = 0; l < lines ;l++) {
42
- char *row_key = procfile_lineword(ff, l, 0);
43
- uint32_t hash = simple_hash(row_key);
44
-
45
- // faster strncmp(row_key, "cpu", 3) == 0
46
- if(likely(row_key[0] == 'c' && row_key[1] == 'p' && row_key[2] == 'u')) {
47
- words = procfile_linewords(ff, l);
48
- if(unlikely(words < 9)) {
49
- error("Cannot read /proc/stat cpu line. Expected 9 params, read %u.", words);
50
- continue;
51
- }
52
-
53
- char *id;
54
- unsigned long long user = 0, nice = 0, system = 0, idle = 0, iowait = 0, irq = 0, softirq = 0, steal = 0, guest = 0, guest_nice = 0;
55
-
56
- id = row_key;
57
- user = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
58
- nice = strtoull(procfile_lineword(ff, l, 2), NULL, 10);
59
- system = strtoull(procfile_lineword(ff, l, 3), NULL, 10);
60
- idle = strtoull(procfile_lineword(ff, l, 4), NULL, 10);
61
- iowait = strtoull(procfile_lineword(ff, l, 5), NULL, 10);
62
- irq = strtoull(procfile_lineword(ff, l, 6), NULL, 10);
63
- softirq = strtoull(procfile_lineword(ff, l, 7), NULL, 10);
64
- steal = strtoull(procfile_lineword(ff, l, 8), NULL, 10);
65
-
66
- guest = strtoull(procfile_lineword(ff, l, 9), NULL, 10);
67
- user -= guest;
68
-
69
- guest_nice = strtoull(procfile_lineword(ff, l, 10), NULL, 10);
70
- nice -= guest_nice;
71
-
72
- char *title, *type, *context, *family;
73
- long priority;
74
- int isthistotal;
75
-
76
- if(unlikely(strcmp(id, "cpu")) == 0) {
77
- title = "Total CPU utilization";
78
- type = "system";
79
- context = "system.cpu";
80
- family = id;
81
- priority = 100;
82
- isthistotal = 1;
83
- }
84
- else {
85
- title = "Core utilization";
86
- type = "cpu";
87
- context = "cpu.cpu";
88
- family = "utilization";
89
- priority = 1000;
90
- isthistotal = 0;
91
- }
92
-
93
- if(likely((isthistotal && do_cpu) || (!isthistotal && do_cpu_cores))) {
94
- st = rrdset_find_bytype(type, id);
95
- if(unlikely(!st)) {
96
- st = rrdset_create(type, id, NULL, family, context, title, "percentage", priority, update_every, RRDSET_TYPE_STACKED);
97
-
98
- long multiplier = 1;
99
- long divisor = 1; // sysconf(_SC_CLK_TCK);
100
-
101
- rrddim_add(st, "guest_nice", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL);
102
- rrddim_add(st, "guest", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL);
103
- rrddim_add(st, "steal", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL);
104
- rrddim_add(st, "softirq", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL);
105
- rrddim_add(st, "irq", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL);
106
- rrddim_add(st, "user", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL);
107
- rrddim_add(st, "system", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL);
108
- rrddim_add(st, "nice", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL);
109
- rrddim_add(st, "iowait", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL);
110
-
111
- rrddim_add(st, "idle", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL);
112
- rrddim_hide(st, "idle");
113
- }
114
- else rrdset_next(st);
115
-
116
- rrddim_set(st, "user", user);
117
- rrddim_set(st, "nice", nice);
118
- rrddim_set(st, "system", system);
119
- rrddim_set(st, "idle", idle);
120
- rrddim_set(st, "iowait", iowait);
121
- rrddim_set(st, "irq", irq);
122
- rrddim_set(st, "softirq", softirq);
123
- rrddim_set(st, "steal", steal);
124
- rrddim_set(st, "guest", guest);
125
- rrddim_set(st, "guest_nice", guest_nice);
126
- rrdset_done(st);
127
- }
128
- }
129
- else if(hash == hash_intr && strcmp(row_key, "intr") == 0) {
130
- unsigned long long value = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
131
-
132
- // --------------------------------------------------------------------
133
-
134
- if(likely(do_interrupts)) {
135
- st = rrdset_find_bytype("system", "intr");
136
- if(unlikely(!st)) {
137
- st = rrdset_create("system", "intr", NULL, "interrupts", NULL, "CPU Interrupts", "interrupts/s", 900, update_every, RRDSET_TYPE_LINE);
138
- st->isdetail = 1;
139
-
140
- rrddim_add(st, "interrupts", NULL, 1, 1, RRDDIM_INCREMENTAL);
141
- }
142
- else rrdset_next(st);
143
-
144
- rrddim_set(st, "interrupts", value);
145
- rrdset_done(st);
146
- }
147
- }
148
- else if(hash == hash_ctxt && strcmp(row_key, "ctxt") == 0) {
149
- unsigned long long value = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
150
-
151
- // --------------------------------------------------------------------
152
-
153
- if(likely(do_context)) {
154
- st = rrdset_find_bytype("system", "ctxt");
155
- if(unlikely(!st)) {
156
- st = rrdset_create("system", "ctxt", NULL, "processes", NULL, "CPU Context Switches", "context switches/s", 800, update_every, RRDSET_TYPE_LINE);
157
-
158
- rrddim_add(st, "switches", NULL, 1, 1, RRDDIM_INCREMENTAL);
159
- }
160
- else rrdset_next(st);
161
-
162
- rrddim_set(st, "switches", value);
163
- rrdset_done(st);
164
- }
165
- }
166
- else if(hash == hash_processes && !processes && strcmp(row_key, "processes") == 0) {
167
- processes = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
168
- }
169
- else if(hash == hash_procs_running && !running && strcmp(row_key, "procs_running") == 0) {
170
- running = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
171
- }
172
- else if(hash == hash_procs_blocked && !blocked && strcmp(row_key, "procs_blocked") == 0) {
173
- blocked = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
174
- }
175
- }
176
-
177
- // --------------------------------------------------------------------
178
-
179
- if(likely(do_forks)) {
180
- st = rrdset_find_bytype("system", "forks");
181
- if(unlikely(!st)) {
182
- st = rrdset_create("system", "forks", NULL, "processes", NULL, "Started Processes", "processes/s", 700, update_every, RRDSET_TYPE_LINE);
183
- st->isdetail = 1;
184
-
185
- rrddim_add(st, "started", NULL, 1, 1, RRDDIM_INCREMENTAL);
186
- }
187
- else rrdset_next(st);
188
-
189
- rrddim_set(st, "started", processes);
190
- rrdset_done(st);
191
- }
192
-
193
- // --------------------------------------------------------------------
194
-
195
- if(likely(do_processes)) {
196
- st = rrdset_find_bytype("system", "processes");
197
- if(unlikely(!st)) {
198
- st = rrdset_create("system", "processes", NULL, "processes", NULL, "System Processes", "processes", 600, update_every, RRDSET_TYPE_LINE);
199
-
200
- rrddim_add(st, "running", NULL, 1, 1, RRDDIM_ABSOLUTE);
201
- rrddim_add(st, "blocked", NULL, -1, 1, RRDDIM_ABSOLUTE);
202
- }
203
- else rrdset_next(st);
204
-
205
- rrddim_set(st, "running", running);
206
- rrddim_set(st, "blocked", blocked);
207
- rrdset_done(st);
208
- }
209
-
210
- return 0;
4
+ (void)dt;
5
+
6
+ static procfile *ff = NULL;
7
+ static int do_cpu = -1, do_cpu_cores = -1, do_interrupts = -1, do_context = -1, do_forks = -1, do_processes = -1;
8
+ static uint32_t hash_intr, hash_ctxt, hash_processes, hash_procs_running, hash_procs_blocked;
9
+
10
+ if(unlikely(do_cpu == -1)) {
11
+ do_cpu = config_get_boolean("plugin:proc:/proc/stat", "cpu utilization", 1);
12
+ do_cpu_cores = config_get_boolean("plugin:proc:/proc/stat", "per cpu core utilization", 1);
13
+ do_interrupts = config_get_boolean("plugin:proc:/proc/stat", "cpu interrupts", 1);
14
+ do_context = config_get_boolean("plugin:proc:/proc/stat", "context switches", 1);
15
+ do_forks = config_get_boolean("plugin:proc:/proc/stat", "processes started", 1);
16
+ do_processes = config_get_boolean("plugin:proc:/proc/stat", "processes running", 1);
17
+
18
+ hash_intr = simple_hash("intr");
19
+ hash_ctxt = simple_hash("ctxt");
20
+ hash_processes = simple_hash("processes");
21
+ hash_procs_running = simple_hash("procs_running");
22
+ hash_procs_blocked = simple_hash("procs_blocked");
23
+ }
24
+
25
+ if(unlikely(!ff)) {
26
+ char filename[FILENAME_MAX + 1];
27
+ snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/stat");
28
+ ff = procfile_open(config_get("plugin:proc:/proc/stat", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
29
+ if(unlikely(!ff)) return 1;
30
+ }
31
+
32
+ ff = procfile_readall(ff);
33
+ if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time
34
+
35
+ uint32_t lines = procfile_lines(ff), l;
36
+ uint32_t words;
37
+
38
+ unsigned long long processes = 0, running = 0 , blocked = 0;
39
+ RRDSET *st;
40
+
41
+ for(l = 0; l < lines ;l++) {
42
+ char *row_key = procfile_lineword(ff, l, 0);
43
+ uint32_t hash = simple_hash(row_key);
44
+
45
+ // faster strncmp(row_key, "cpu", 3) == 0
46
+ if(likely(row_key[0] == 'c' && row_key[1] == 'p' && row_key[2] == 'u')) {
47
+ words = procfile_linewords(ff, l);
48
+ if(unlikely(words < 9)) {
49
+ error("Cannot read /proc/stat cpu line. Expected 9 params, read %u.", words);
50
+ continue;
51
+ }
52
+
53
+ char *id;
54
+ unsigned long long user = 0, nice = 0, system = 0, idle = 0, iowait = 0, irq = 0, softirq = 0, steal = 0, guest = 0, guest_nice = 0;
55
+
56
+ id = row_key;
57
+ user = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
58
+ nice = strtoull(procfile_lineword(ff, l, 2), NULL, 10);
59
+ system = strtoull(procfile_lineword(ff, l, 3), NULL, 10);
60
+ idle = strtoull(procfile_lineword(ff, l, 4), NULL, 10);
61
+ iowait = strtoull(procfile_lineword(ff, l, 5), NULL, 10);
62
+ irq = strtoull(procfile_lineword(ff, l, 6), NULL, 10);
63
+ softirq = strtoull(procfile_lineword(ff, l, 7), NULL, 10);
64
+ steal = strtoull(procfile_lineword(ff, l, 8), NULL, 10);
65
+
66
+ guest = strtoull(procfile_lineword(ff, l, 9), NULL, 10);
67
+ user -= guest;
68
+
69
+ guest_nice = strtoull(procfile_lineword(ff, l, 10), NULL, 10);
70
+ nice -= guest_nice;
71
+
72
+ char *title, *type, *context, *family;
73
+ long priority;
74
+ int isthistotal;
75
+
76
+ if(unlikely(strcmp(id, "cpu")) == 0) {
77
+ title = "Total CPU utilization";
78
+ type = "system";
79
+ context = "system.cpu";
80
+ family = id;
81
+ priority = 100;
82
+ isthistotal = 1;
83
+ }
84
+ else {
85
+ title = "Core utilization";
86
+ type = "cpu";
87
+ context = "cpu.cpu";
88
+ family = "utilization";
89
+ priority = 1000;
90
+ isthistotal = 0;
91
+ }
92
+
93
+ if(likely((isthistotal && do_cpu) || (!isthistotal && do_cpu_cores))) {
94
+ st = rrdset_find_bytype(type, id);
95
+ if(unlikely(!st)) {
96
+ st = rrdset_create(type, id, NULL, family, context, title, "percentage", priority, update_every, RRDSET_TYPE_STACKED);
97
+
98
+ long multiplier = 1;
99
+ long divisor = 1; // sysconf(_SC_CLK_TCK);
100
+
101
+ rrddim_add(st, "guest_nice", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL);
102
+ rrddim_add(st, "guest", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL);
103
+ rrddim_add(st, "steal", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL);
104
+ rrddim_add(st, "softirq", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL);
105
+ rrddim_add(st, "irq", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL);
106
+ rrddim_add(st, "user", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL);
107
+ rrddim_add(st, "system", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL);
108
+ rrddim_add(st, "nice", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL);
109
+ rrddim_add(st, "iowait", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL);
110
+
111
+ rrddim_add(st, "idle", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL);
112
+ rrddim_hide(st, "idle");
113
+ }
114
+ else rrdset_next(st);
115
+
116
+ rrddim_set(st, "user", user);
117
+ rrddim_set(st, "nice", nice);
118
+ rrddim_set(st, "system", system);
119
+ rrddim_set(st, "idle", idle);
120
+ rrddim_set(st, "iowait", iowait);
121
+ rrddim_set(st, "irq", irq);
122
+ rrddim_set(st, "softirq", softirq);
123
+ rrddim_set(st, "steal", steal);
124
+ rrddim_set(st, "guest", guest);
125
+ rrddim_set(st, "guest_nice", guest_nice);
126
+ rrdset_done(st);
127
+ }
128
+ }
129
+ else if(hash == hash_intr && strcmp(row_key, "intr") == 0) {
130
+ unsigned long long value = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
131
+
132
+ // --------------------------------------------------------------------
133
+
134
+ if(likely(do_interrupts)) {
135
+ st = rrdset_find_bytype("system", "intr");
136
+ if(unlikely(!st)) {
137
+ st = rrdset_create("system", "intr", NULL, "interrupts", NULL, "CPU Interrupts", "interrupts/s", 900, update_every, RRDSET_TYPE_LINE);
138
+ st->isdetail = 1;
139
+
140
+ rrddim_add(st, "interrupts", NULL, 1, 1, RRDDIM_INCREMENTAL);
141
+ }
142
+ else rrdset_next(st);
143
+
144
+ rrddim_set(st, "interrupts", value);
145
+ rrdset_done(st);
146
+ }
147
+ }
148
+ else if(hash == hash_ctxt && strcmp(row_key, "ctxt") == 0) {
149
+ unsigned long long value = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
150
+
151
+ // --------------------------------------------------------------------
152
+
153
+ if(likely(do_context)) {
154
+ st = rrdset_find_bytype("system", "ctxt");
155
+ if(unlikely(!st)) {
156
+ st = rrdset_create("system", "ctxt", NULL, "processes", NULL, "CPU Context Switches", "context switches/s", 800, update_every, RRDSET_TYPE_LINE);
157
+
158
+ rrddim_add(st, "switches", NULL, 1, 1, RRDDIM_INCREMENTAL);
159
+ }
160
+ else rrdset_next(st);
161
+
162
+ rrddim_set(st, "switches", value);
163
+ rrdset_done(st);
164
+ }
165
+ }
166
+ else if(hash == hash_processes && !processes && strcmp(row_key, "processes") == 0) {
167
+ processes = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
168
+ }
169
+ else if(hash == hash_procs_running && !running && strcmp(row_key, "procs_running") == 0) {
170
+ running = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
171
+ }
172
+ else if(hash == hash_procs_blocked && !blocked && strcmp(row_key, "procs_blocked") == 0) {
173
+ blocked = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
174
+ }
175
+ }
176
+
177
+ // --------------------------------------------------------------------
178
+
179
+ if(likely(do_forks)) {
180
+ st = rrdset_find_bytype("system", "forks");
181
+ if(unlikely(!st)) {
182
+ st = rrdset_create("system", "forks", NULL, "processes", NULL, "Started Processes", "processes/s", 700, update_every, RRDSET_TYPE_LINE);
183
+ st->isdetail = 1;
184
+
185
+ rrddim_add(st, "started", NULL, 1, 1, RRDDIM_INCREMENTAL);
186
+ }
187
+ else rrdset_next(st);
188
+
189
+ rrddim_set(st, "started", processes);
190
+ rrdset_done(st);
191
+ }
192
+
193
+ // --------------------------------------------------------------------
194
+
195
+ if(likely(do_processes)) {
196
+ st = rrdset_find_bytype("system", "processes");
197
+ if(unlikely(!st)) {
198
+ st = rrdset_create("system", "processes", NULL, "processes", NULL, "System Processes", "processes", 600, update_every, RRDSET_TYPE_LINE);
199
+
200
+ rrddim_add(st, "running", NULL, 1, 1, RRDDIM_ABSOLUTE);
201
+ rrddim_add(st, "blocked", NULL, -1, 1, RRDDIM_ABSOLUTE);
202
+ }
203
+ else rrdset_next(st);
204
+
205
+ rrddim_set(st, "running", running);
206
+ rrddim_set(st, "blocked", blocked);
207
+ rrdset_done(st);
208
+ }
209
+
210
+ return 0;
211
}
src/proc_sys_kernel_random_entropy_avail.c
+20
-20
@@ -1,31 +1,31 @@
1
#include "common.h"
2
3
int do_proc_sys_kernel_random_entropy_avail(int update_every, unsigned long long dt) {
4
- static procfile *ff = NULL;
4
+ static procfile *ff = NULL;
5
6
- if(dt) {} ;
6
+ if(dt) {} ;
7
8
- if(!ff) {
9
- char filename[FILENAME_MAX + 1];
10
- snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/sys/kernel/random/entropy_avail");
11
- ff = procfile_open(config_get("plugin:proc:/proc/sys/kernel/random/entropy_avail", "filename to monitor", filename), "", PROCFILE_FLAG_DEFAULT);
12
- }
13
- if(!ff) return 1;
8
+ if(!ff) {
9
+ char filename[FILENAME_MAX + 1];
10
+ snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/sys/kernel/random/entropy_avail");
11
+ ff = procfile_open(config_get("plugin:proc:/proc/sys/kernel/random/entropy_avail", "filename to monitor", filename), "", PROCFILE_FLAG_DEFAULT);
12
+ }
13
+ if(!ff) return 1;
14
15
- ff = procfile_readall(ff);
16
- if(!ff) return 0; // we return 0, so that we will retry to open it next time
15
+ ff = procfile_readall(ff);
16
+ if(!ff) return 0; // we return 0, so that we will retry to open it next time
17
18
- unsigned long long entropy = strtoull(procfile_lineword(ff, 0, 0), NULL, 10);
18
+ unsigned long long entropy = strtoull(procfile_lineword(ff, 0, 0), NULL, 10);
19
20
- RRDSET *st = rrdset_find_bytype("system", "entropy");
21
- if(!st) {
22
- st = rrdset_create("system", "entropy", NULL, "entropy", NULL, "Available Entropy", "entropy", 1000, update_every, RRDSET_TYPE_LINE);
23
- rrddim_add(st, "entropy", NULL, 1, 1, RRDDIM_ABSOLUTE);
24
- }
25
- else rrdset_next(st);
20
+ RRDSET *st = rrdset_find_bytype("system", "entropy");
21
+ if(!st) {
22
+ st = rrdset_create("system", "entropy", NULL, "entropy", NULL, "Available Entropy", "entropy", 1000, update_every, RRDSET_TYPE_LINE);
23
+ rrddim_add(st, "entropy", NULL, 1, 1, RRDDIM_ABSOLUTE);
24
+ }
25
+ else rrdset_next(st);
26
27
- rrddim_set(st, "entropy", entropy);
28
- rrdset_done(st);
27
+ rrddim_set(st, "entropy", entropy);
28
+ rrdset_done(st);
29
30
- return 0;
30
+ return 0;
31
}
src/proc_vmstat.c
+440
-440
@@ -1,470 +1,470 @@
1
#include "common.h"
2
3
int do_proc_vmstat(int update_every, unsigned long long dt) {
4
- static procfile *ff = NULL;
5
- static int do_swapio = -1, do_io = -1, do_pgfaults = -1, gen_hashes = -1;
4
+ static procfile *ff = NULL;
5
+ static int do_swapio = -1, do_io = -1, do_pgfaults = -1, gen_hashes = -1;
6
7
- // static uint32_t hash_allocstall = -1;
8
- // static uint32_t hash_compact_blocks_moved = -1;
9
- // static uint32_t hash_compact_fail = -1;
10
- // static uint32_t hash_compact_pagemigrate_failed = -1;
11
- // static uint32_t hash_compact_pages_moved = -1;
12
- // static uint32_t hash_compact_stall = -1;
13
- // static uint32_t hash_compact_success = -1;
14
- // static uint32_t hash_htlb_buddy_alloc_fail = -1;
15
- // static uint32_t hash_htlb_buddy_alloc_success = -1;
16
- // static uint32_t hash_kswapd_high_wmark_hit_quickly = -1;
17
- // static uint32_t hash_kswapd_inodesteal = -1;
18
- // static uint32_t hash_kswapd_low_wmark_hit_quickly = -1;
19
- // static uint32_t hash_kswapd_skip_congestion_wait = -1;
20
- // static uint32_t hash_nr_active_anon = -1;
21
- // static uint32_t hash_nr_active_file = -1;
22
- // static uint32_t hash_nr_anon_pages = -1;
23
- // static uint32_t hash_nr_anon_transparent_hugepages = -1;
24
- // static uint32_t hash_nr_bounce = -1;
25
- // static uint32_t hash_nr_dirtied = -1;
26
- // static uint32_t hash_nr_dirty = -1;
27
- // static uint32_t hash_nr_dirty_background_threshold = -1;
28
- // static uint32_t hash_nr_dirty_threshold = -1;
29
- // static uint32_t hash_nr_file_pages = -1;
30
- // static uint32_t hash_nr_free_pages = -1;
31
- // static uint32_t hash_nr_inactive_anon = -1;
32
- // static uint32_t hash_nr_inactive_file = -1;
33
- // static uint32_t hash_nr_isolated_anon = -1;
34
- // static uint32_t hash_nr_isolated_file = -1;
35
- // static uint32_t hash_nr_kernel_stack = -1;
36
- // static uint32_t hash_nr_mapped = -1;
37
- // static uint32_t hash_nr_mlock = -1;
38
- // static uint32_t hash_nr_page_table_pages = -1;
39
- // static uint32_t hash_nr_shmem = -1;
40
- // static uint32_t hash_nr_slab_reclaimable = -1;
41
- // static uint32_t hash_nr_slab_unreclaimable = -1;
42
- // static uint32_t hash_nr_unevictable = -1;
43
- // static uint32_t hash_nr_unstable = -1;
44
- // static uint32_t hash_nr_vmscan_immediate_reclaim = -1;
45
- // static uint32_t hash_nr_vmscan_write = -1;
46
- // static uint32_t hash_nr_writeback = -1;
47
- // static uint32_t hash_nr_writeback_temp = -1;
48
- // static uint32_t hash_nr_written = -1;
49
- // static uint32_t hash_pageoutrun = -1;
50
- // static uint32_t hash_pgactivate = -1;
51
- // static uint32_t hash_pgalloc_dma = -1;
52
- // static uint32_t hash_pgalloc_dma32 = -1;
53
- // static uint32_t hash_pgalloc_movable = -1;
54
- // static uint32_t hash_pgalloc_normal = -1;
55
- // static uint32_t hash_pgdeactivate = -1;
56
- static uint32_t hash_pgfault = -1;
57
- // static uint32_t hash_pgfree = -1;
58
- // static uint32_t hash_pginodesteal = -1;
59
- static uint32_t hash_pgmajfault = -1;
60
- static uint32_t hash_pgpgin = -1;
61
- static uint32_t hash_pgpgout = -1;
62
- // static uint32_t hash_pgrefill_dma = -1;
63
- // static uint32_t hash_pgrefill_dma32 = -1;
64
- // static uint32_t hash_pgrefill_movable = -1;
65
- // static uint32_t hash_pgrefill_normal = -1;
66
- // static uint32_t hash_pgrotated = -1;
67
- // static uint32_t hash_pgscan_direct_dma = -1;
68
- // static uint32_t hash_pgscan_direct_dma32 = -1;
69
- // static uint32_t hash_pgscan_direct_movable = -1;
70
- // static uint32_t hash_pgscan_direct_normal = -1;
71
- // static uint32_t hash_pgscan_kswapd_dma = -1;
72
- // static uint32_t hash_pgscan_kswapd_dma32 = -1;
73
- // static uint32_t hash_pgscan_kswapd_movable = -1;
74
- // static uint32_t hash_pgscan_kswapd_normal = -1;
75
- // static uint32_t hash_pgsteal_direct_dma = -1;
76
- // static uint32_t hash_pgsteal_direct_dma32 = -1;
77
- // static uint32_t hash_pgsteal_direct_movable = -1;
78
- // static uint32_t hash_pgsteal_direct_normal = -1;
79
- // static uint32_t hash_pgsteal_kswapd_dma = -1;
80
- // static uint32_t hash_pgsteal_kswapd_dma32 = -1;
81
- // static uint32_t hash_pgsteal_kswapd_movable = -1;
82
- // static uint32_t hash_pgsteal_kswapd_normal = -1;
83
- static uint32_t hash_pswpin = -1;
84
- static uint32_t hash_pswpout = -1;
85
- // static uint32_t hash_slabs_scanned = -1;
86
- // static uint32_t hash_thp_collapse_alloc = -1;
87
- // static uint32_t hash_thp_collapse_alloc_failed = -1;
88
- // static uint32_t hash_thp_fault_alloc = -1;
89
- // static uint32_t hash_thp_fault_fallback = -1;
90
- // static uint32_t hash_thp_split = -1;
91
- // static uint32_t hash_unevictable_pgs_cleared = -1;
92
- // static uint32_t hash_unevictable_pgs_culled = -1;
93
- // static uint32_t hash_unevictable_pgs_mlocked = -1;
94
- // static uint32_t hash_unevictable_pgs_mlockfreed = -1;
95
- // static uint32_t hash_unevictable_pgs_munlocked = -1;
96
- // static uint32_t hash_unevictable_pgs_rescued = -1;
97
- // static uint32_t hash_unevictable_pgs_scanned = -1;
98
- // static uint32_t hash_unevictable_pgs_stranded = -1;
7
+ // static uint32_t hash_allocstall = -1;
8
+ // static uint32_t hash_compact_blocks_moved = -1;
9
+ // static uint32_t hash_compact_fail = -1;
10
+ // static uint32_t hash_compact_pagemigrate_failed = -1;
11
+ // static uint32_t hash_compact_pages_moved = -1;
12
+ // static uint32_t hash_compact_stall = -1;
13
+ // static uint32_t hash_compact_success = -1;
14
+ // static uint32_t hash_htlb_buddy_alloc_fail = -1;
15
+ // static uint32_t hash_htlb_buddy_alloc_success = -1;
16
+ // static uint32_t hash_kswapd_high_wmark_hit_quickly = -1;
17
+ // static uint32_t hash_kswapd_inodesteal = -1;
18
+ // static uint32_t hash_kswapd_low_wmark_hit_quickly = -1;
19
+ // static uint32_t hash_kswapd_skip_congestion_wait = -1;
20
+ // static uint32_t hash_nr_active_anon = -1;
21
+ // static uint32_t hash_nr_active_file = -1;
22
+ // static uint32_t hash_nr_anon_pages = -1;
23
+ // static uint32_t hash_nr_anon_transparent_hugepages = -1;
24
+ // static uint32_t hash_nr_bounce = -1;
25
+ // static uint32_t hash_nr_dirtied = -1;
26
+ // static uint32_t hash_nr_dirty = -1;
27
+ // static uint32_t hash_nr_dirty_background_threshold = -1;
28
+ // static uint32_t hash_nr_dirty_threshold = -1;
29
+ // static uint32_t hash_nr_file_pages = -1;
30
+ // static uint32_t hash_nr_free_pages = -1;
31
+ // static uint32_t hash_nr_inactive_anon = -1;
32
+ // static uint32_t hash_nr_inactive_file = -1;
33
+ // static uint32_t hash_nr_isolated_anon = -1;
34
+ // static uint32_t hash_nr_isolated_file = -1;
35
+ // static uint32_t hash_nr_kernel_stack = -1;
36
+ // static uint32_t hash_nr_mapped = -1;
37
+ // static uint32_t hash_nr_mlock = -1;
38
+ // static uint32_t hash_nr_page_table_pages = -1;
39
+ // static uint32_t hash_nr_shmem = -1;
40
+ // static uint32_t hash_nr_slab_reclaimable = -1;
41
+ // static uint32_t hash_nr_slab_unreclaimable = -1;
42
+ // static uint32_t hash_nr_unevictable = -1;
43
+ // static uint32_t hash_nr_unstable = -1;
44
+ // static uint32_t hash_nr_vmscan_immediate_reclaim = -1;
45
+ // static uint32_t hash_nr_vmscan_write = -1;
46
+ // static uint32_t hash_nr_writeback = -1;
47
+ // static uint32_t hash_nr_writeback_temp = -1;
48
+ // static uint32_t hash_nr_written = -1;
49
+ // static uint32_t hash_pageoutrun = -1;
50
+ // static uint32_t hash_pgactivate = -1;
51
+ // static uint32_t hash_pgalloc_dma = -1;
52
+ // static uint32_t hash_pgalloc_dma32 = -1;
53
+ // static uint32_t hash_pgalloc_movable = -1;
54
+ // static uint32_t hash_pgalloc_normal = -1;
55
+ // static uint32_t hash_pgdeactivate = -1;
56
+ static uint32_t hash_pgfault = -1;
57
+ // static uint32_t hash_pgfree = -1;
58
+ // static uint32_t hash_pginodesteal = -1;
59
+ static uint32_t hash_pgmajfault = -1;
60
+ static uint32_t hash_pgpgin = -1;
61
+ static uint32_t hash_pgpgout = -1;
62
+ // static uint32_t hash_pgrefill_dma = -1;
63
+ // static uint32_t hash_pgrefill_dma32 = -1;
64
+ // static uint32_t hash_pgrefill_movable = -1;
65
+ // static uint32_t hash_pgrefill_normal = -1;
66
+ // static uint32_t hash_pgrotated = -1;
67
+ // static uint32_t hash_pgscan_direct_dma = -1;
68
+ // static uint32_t hash_pgscan_direct_dma32 = -1;
69
+ // static uint32_t hash_pgscan_direct_movable = -1;
70
+ // static uint32_t hash_pgscan_direct_normal = -1;
71
+ // static uint32_t hash_pgscan_kswapd_dma = -1;
72
+ // static uint32_t hash_pgscan_kswapd_dma32 = -1;
73
+ // static uint32_t hash_pgscan_kswapd_movable = -1;
74
+ // static uint32_t hash_pgscan_kswapd_normal = -1;
75
+ // static uint32_t hash_pgsteal_direct_dma = -1;
76
+ // static uint32_t hash_pgsteal_direct_dma32 = -1;
77
+ // static uint32_t hash_pgsteal_direct_movable = -1;
78
+ // static uint32_t hash_pgsteal_direct_normal = -1;
79
+ // static uint32_t hash_pgsteal_kswapd_dma = -1;
80
+ // static uint32_t hash_pgsteal_kswapd_dma32 = -1;
81
+ // static uint32_t hash_pgsteal_kswapd_movable = -1;
82
+ // static uint32_t hash_pgsteal_kswapd_normal = -1;
83
+ static uint32_t hash_pswpin = -1;
84
+ static uint32_t hash_pswpout = -1;
85
+ // static uint32_t hash_slabs_scanned = -1;
86
+ // static uint32_t hash_thp_collapse_alloc = -1;
87
+ // static uint32_t hash_thp_collapse_alloc_failed = -1;
88
+ // static uint32_t hash_thp_fault_alloc = -1;
89
+ // static uint32_t hash_thp_fault_fallback = -1;
90
+ // static uint32_t hash_thp_split = -1;
91
+ // static uint32_t hash_unevictable_pgs_cleared = -1;
92
+ // static uint32_t hash_unevictable_pgs_culled = -1;
93
+ // static uint32_t hash_unevictable_pgs_mlocked = -1;
94
+ // static uint32_t hash_unevictable_pgs_mlockfreed = -1;
95
+ // static uint32_t hash_unevictable_pgs_munlocked = -1;
96
+ // static uint32_t hash_unevictable_pgs_rescued = -1;
97
+ // static uint32_t hash_unevictable_pgs_scanned = -1;
98
+ // static uint32_t hash_unevictable_pgs_stranded = -1;
99
100
- if(gen_hashes != 1) {
101
- gen_hashes = 1;
102
- // hash_allocstall = simple_hash("allocstall");
103
- // hash_compact_blocks_moved = simple_hash("compact_blocks_moved");
104
- // hash_compact_fail = simple_hash("compact_fail");
105
- // hash_compact_pagemigrate_failed = simple_hash("compact_pagemigrate_failed");
106
- // hash_compact_pages_moved = simple_hash("compact_pages_moved");
107
- // hash_compact_stall = simple_hash("compact_stall");
108
- // hash_compact_success = simple_hash("compact_success");
109
- // hash_htlb_buddy_alloc_fail = simple_hash("htlb_buddy_alloc_fail");
110
- // hash_htlb_buddy_alloc_success = simple_hash("htlb_buddy_alloc_success");
111
- // hash_kswapd_high_wmark_hit_quickly = simple_hash("kswapd_high_wmark_hit_quickly");
112
- // hash_kswapd_inodesteal = simple_hash("kswapd_inodesteal");
113
- // hash_kswapd_low_wmark_hit_quickly = simple_hash("kswapd_low_wmark_hit_quickly");
114
- // hash_kswapd_skip_congestion_wait = simple_hash("kswapd_skip_congestion_wait");
115
- // hash_nr_active_anon = simple_hash("nr_active_anon");
116
- // hash_nr_active_file = simple_hash("nr_active_file");
117
- // hash_nr_anon_pages = simple_hash("nr_anon_pages");
118
- // hash_nr_anon_transparent_hugepages = simple_hash("nr_anon_transparent_hugepages");
119
- // hash_nr_bounce = simple_hash("nr_bounce");
120
- // hash_nr_dirtied = simple_hash("nr_dirtied");
121
- // hash_nr_dirty = simple_hash("nr_dirty");
122
- // hash_nr_dirty_background_threshold = simple_hash("nr_dirty_background_threshold");
123
- // hash_nr_dirty_threshold = simple_hash("nr_dirty_threshold");
124
- // hash_nr_file_pages = simple_hash("nr_file_pages");
125
- // hash_nr_free_pages = simple_hash("nr_free_pages");
126
- // hash_nr_inactive_anon = simple_hash("nr_inactive_anon");
127
- // hash_nr_inactive_file = simple_hash("nr_inactive_file");
128
- // hash_nr_isolated_anon = simple_hash("nr_isolated_anon");
129
- // hash_nr_isolated_file = simple_hash("nr_isolated_file");
130
- // hash_nr_kernel_stack = simple_hash("nr_kernel_stack");
131
- // hash_nr_mapped = simple_hash("nr_mapped");
132
- // hash_nr_mlock = simple_hash("nr_mlock");
133
- // hash_nr_page_table_pages = simple_hash("nr_page_table_pages");
134
- // hash_nr_shmem = simple_hash("nr_shmem");
135
- // hash_nr_slab_reclaimable = simple_hash("nr_slab_reclaimable");
136
- // hash_nr_slab_unreclaimable = simple_hash("nr_slab_unreclaimable");
137
- // hash_nr_unevictable = simple_hash("nr_unevictable");
138
- // hash_nr_unstable = simple_hash("nr_unstable");
139
- // hash_nr_vmscan_immediate_reclaim = simple_hash("nr_vmscan_immediate_reclaim");
140
- // hash_nr_vmscan_write = simple_hash("nr_vmscan_write");
141
- // hash_nr_writeback = simple_hash("nr_writeback");
142
- // hash_nr_writeback_temp = simple_hash("nr_writeback_temp");
143
- // hash_nr_written = simple_hash("nr_written");
144
- // hash_pageoutrun = simple_hash("pageoutrun");
145
- // hash_pgactivate = simple_hash("pgactivate");
146
- // hash_pgalloc_dma = simple_hash("pgalloc_dma");
147
- // hash_pgalloc_dma32 = simple_hash("pgalloc_dma32");
148
- // hash_pgalloc_movable = simple_hash("pgalloc_movable");
149
- // hash_pgalloc_normal = simple_hash("pgalloc_normal");
150
- // hash_pgdeactivate = simple_hash("pgdeactivate");
151
- hash_pgfault = simple_hash("pgfault");
152
- // hash_pgfree = simple_hash("pgfree");
153
- // hash_pginodesteal = simple_hash("pginodesteal");
154
- hash_pgmajfault = simple_hash("pgmajfault");
155
- hash_pgpgin = simple_hash("pgpgin");
156
- hash_pgpgout = simple_hash("pgpgout");
157
- // hash_pgrefill_dma = simple_hash("pgrefill_dma");
158
- // hash_pgrefill_dma32 = simple_hash("pgrefill_dma32");
159
- // hash_pgrefill_movable = simple_hash("pgrefill_movable");
160
- // hash_pgrefill_normal = simple_hash("pgrefill_normal");
161
- // hash_pgrotated = simple_hash("pgrotated");
162
- // hash_pgscan_direct_dma = simple_hash("pgscan_direct_dma");
163
- // hash_pgscan_direct_dma32 = simple_hash("pgscan_direct_dma32");
164
- // hash_pgscan_direct_movable = simple_hash("pgscan_direct_movable");
165
- // hash_pgscan_direct_normal = simple_hash("pgscan_direct_normal");
166
- // hash_pgscan_kswapd_dma = simple_hash("pgscan_kswapd_dma");
167
- // hash_pgscan_kswapd_dma32 = simple_hash("pgscan_kswapd_dma32");
168
- // hash_pgscan_kswapd_movable = simple_hash("pgscan_kswapd_movable");
169
- // hash_pgscan_kswapd_normal = simple_hash("pgscan_kswapd_normal");
170
- // hash_pgsteal_direct_dma = simple_hash("pgsteal_direct_dma");
171
- // hash_pgsteal_direct_dma32 = simple_hash("pgsteal_direct_dma32");
172
- // hash_pgsteal_direct_movable = simple_hash("pgsteal_direct_movable");
173
- // hash_pgsteal_direct_normal = simple_hash("pgsteal_direct_normal");
174
- // hash_pgsteal_kswapd_dma = simple_hash("pgsteal_kswapd_dma");
175
- // hash_pgsteal_kswapd_dma32 = simple_hash("pgsteal_kswapd_dma32");
176
- // hash_pgsteal_kswapd_movable = simple_hash("pgsteal_kswapd_movable");
177
- // hash_pgsteal_kswapd_normal = simple_hash("pgsteal_kswapd_normal");
178
- hash_pswpin = simple_hash("pswpin");
179
- hash_pswpout = simple_hash("pswpout");
180
- // hash_slabs_scanned = simple_hash("slabs_scanned");
181
- // hash_thp_collapse_alloc = simple_hash("thp_collapse_alloc");
182
- // hash_thp_collapse_alloc_failed = simple_hash("thp_collapse_alloc_failed");
183
- // hash_thp_fault_alloc = simple_hash("thp_fault_alloc");
184
- // hash_thp_fault_fallback = simple_hash("thp_fault_fallback");
185
- // hash_thp_split = simple_hash("thp_split");
186
- // hash_unevictable_pgs_cleared = simple_hash("unevictable_pgs_cleared");
187
- // hash_unevictable_pgs_culled = simple_hash("unevictable_pgs_culled");
188
- // hash_unevictable_pgs_mlocked = simple_hash("unevictable_pgs_mlocked");
189
- // hash_unevictable_pgs_mlockfreed = simple_hash("unevictable_pgs_mlockfreed");
190
- // hash_unevictable_pgs_munlocked = simple_hash("unevictable_pgs_munlocked");
191
- // hash_unevictable_pgs_rescued = simple_hash("unevictable_pgs_rescued");
192
- // hash_unevictable_pgs_scanned = simple_hash("unevictable_pgs_scanned");
193
- // hash_unevictable_pgs_stranded = simple_hash("unevictable_pgs_stranded");
194
- }
100
+ if(gen_hashes != 1) {
101
+ gen_hashes = 1;
102
+ // hash_allocstall = simple_hash("allocstall");
103
+ // hash_compact_blocks_moved = simple_hash("compact_blocks_moved");
104
+ // hash_compact_fail = simple_hash("compact_fail");
105
+ // hash_compact_pagemigrate_failed = simple_hash("compact_pagemigrate_failed");
106
+ // hash_compact_pages_moved = simple_hash("compact_pages_moved");
107
+ // hash_compact_stall = simple_hash("compact_stall");
108
+ // hash_compact_success = simple_hash("compact_success");
109
+ // hash_htlb_buddy_alloc_fail = simple_hash("htlb_buddy_alloc_fail");
110
+ // hash_htlb_buddy_alloc_success = simple_hash("htlb_buddy_alloc_success");
111
+ // hash_kswapd_high_wmark_hit_quickly = simple_hash("kswapd_high_wmark_hit_quickly");
112
+ // hash_kswapd_inodesteal = simple_hash("kswapd_inodesteal");
113
+ // hash_kswapd_low_wmark_hit_quickly = simple_hash("kswapd_low_wmark_hit_quickly");
114
+ // hash_kswapd_skip_congestion_wait = simple_hash("kswapd_skip_congestion_wait");
115
+ // hash_nr_active_anon = simple_hash("nr_active_anon");
116
+ // hash_nr_active_file = simple_hash("nr_active_file");
117
+ // hash_nr_anon_pages = simple_hash("nr_anon_pages");
118
+ // hash_nr_anon_transparent_hugepages = simple_hash("nr_anon_transparent_hugepages");
119
+ // hash_nr_bounce = simple_hash("nr_bounce");
120
+ // hash_nr_dirtied = simple_hash("nr_dirtied");
121
+ // hash_nr_dirty = simple_hash("nr_dirty");
122
+ // hash_nr_dirty_background_threshold = simple_hash("nr_dirty_background_threshold");
123
+ // hash_nr_dirty_threshold = simple_hash("nr_dirty_threshold");
124
+ // hash_nr_file_pages = simple_hash("nr_file_pages");
125
+ // hash_nr_free_pages = simple_hash("nr_free_pages");
126
+ // hash_nr_inactive_anon = simple_hash("nr_inactive_anon");
127
+ // hash_nr_inactive_file = simple_hash("nr_inactive_file");
128
+ // hash_nr_isolated_anon = simple_hash("nr_isolated_anon");
129
+ // hash_nr_isolated_file = simple_hash("nr_isolated_file");
130
+ // hash_nr_kernel_stack = simple_hash("nr_kernel_stack");
131
+ // hash_nr_mapped = simple_hash("nr_mapped");
132
+ // hash_nr_mlock = simple_hash("nr_mlock");
133
+ // hash_nr_page_table_pages = simple_hash("nr_page_table_pages");
134
+ // hash_nr_shmem = simple_hash("nr_shmem");
135
+ // hash_nr_slab_reclaimable = simple_hash("nr_slab_reclaimable");
136
+ // hash_nr_slab_unreclaimable = simple_hash("nr_slab_unreclaimable");
137
+ // hash_nr_unevictable = simple_hash("nr_unevictable");
138
+ // hash_nr_unstable = simple_hash("nr_unstable");
139
+ // hash_nr_vmscan_immediate_reclaim = simple_hash("nr_vmscan_immediate_reclaim");
140
+ // hash_nr_vmscan_write = simple_hash("nr_vmscan_write");
141
+ // hash_nr_writeback = simple_hash("nr_writeback");
142
+ // hash_nr_writeback_temp = simple_hash("nr_writeback_temp");
143
+ // hash_nr_written = simple_hash("nr_written");
144
+ // hash_pageoutrun = simple_hash("pageoutrun");
145
+ // hash_pgactivate = simple_hash("pgactivate");
146
+ // hash_pgalloc_dma = simple_hash("pgalloc_dma");
147
+ // hash_pgalloc_dma32 = simple_hash("pgalloc_dma32");
148
+ // hash_pgalloc_movable = simple_hash("pgalloc_movable");
149
+ // hash_pgalloc_normal = simple_hash("pgalloc_normal");
150
+ // hash_pgdeactivate = simple_hash("pgdeactivate");
151
+ hash_pgfault = simple_hash("pgfault");
152
+ // hash_pgfree = simple_hash("pgfree");
153
+ // hash_pginodesteal = simple_hash("pginodesteal");
154
+ hash_pgmajfault = simple_hash("pgmajfault");
155
+ hash_pgpgin = simple_hash("pgpgin");
156
+ hash_pgpgout = simple_hash("pgpgout");
157
+ // hash_pgrefill_dma = simple_hash("pgrefill_dma");
158
+ // hash_pgrefill_dma32 = simple_hash("pgrefill_dma32");
159
+ // hash_pgrefill_movable = simple_hash("pgrefill_movable");
160
+ // hash_pgrefill_normal = simple_hash("pgrefill_normal");
161
+ // hash_pgrotated = simple_hash("pgrotated");
162
+ // hash_pgscan_direct_dma = simple_hash("pgscan_direct_dma");
163
+ // hash_pgscan_direct_dma32 = simple_hash("pgscan_direct_dma32");
164
+ // hash_pgscan_direct_movable = simple_hash("pgscan_direct_movable");
165
+ // hash_pgscan_direct_normal = simple_hash("pgscan_direct_normal");
166
+ // hash_pgscan_kswapd_dma = simple_hash("pgscan_kswapd_dma");
167
+ // hash_pgscan_kswapd_dma32 = simple_hash("pgscan_kswapd_dma32");
168
+ // hash_pgscan_kswapd_movable = simple_hash("pgscan_kswapd_movable");
169
+ // hash_pgscan_kswapd_normal = simple_hash("pgscan_kswapd_normal");
170
+ // hash_pgsteal_direct_dma = simple_hash("pgsteal_direct_dma");
171
+ // hash_pgsteal_direct_dma32 = simple_hash("pgsteal_direct_dma32");
172
+ // hash_pgsteal_direct_movable = simple_hash("pgsteal_direct_movable");
173
+ // hash_pgsteal_direct_normal = simple_hash("pgsteal_direct_normal");
174
+ // hash_pgsteal_kswapd_dma = simple_hash("pgsteal_kswapd_dma");
175
+ // hash_pgsteal_kswapd_dma32 = simple_hash("pgsteal_kswapd_dma32");
176
+ // hash_pgsteal_kswapd_movable = simple_hash("pgsteal_kswapd_movable");
177
+ // hash_pgsteal_kswapd_normal = simple_hash("pgsteal_kswapd_normal");
178
+ hash_pswpin = simple_hash("pswpin");
179
+ hash_pswpout = simple_hash("pswpout");
180
+ // hash_slabs_scanned = simple_hash("slabs_scanned");
181
+ // hash_thp_collapse_alloc = simple_hash("thp_collapse_alloc");
182
+ // hash_thp_collapse_alloc_failed = simple_hash("thp_collapse_alloc_failed");
183
+ // hash_thp_fault_alloc = simple_hash("thp_fault_alloc");
184
+ // hash_thp_fault_fallback = simple_hash("thp_fault_fallback");
185
+ // hash_thp_split = simple_hash("thp_split");
186
+ // hash_unevictable_pgs_cleared = simple_hash("unevictable_pgs_cleared");
187
+ // hash_unevictable_pgs_culled = simple_hash("unevictable_pgs_culled");
188
+ // hash_unevictable_pgs_mlocked = simple_hash("unevictable_pgs_mlocked");
189
+ // hash_unevictable_pgs_mlockfreed = simple_hash("unevictable_pgs_mlockfreed");
190
+ // hash_unevictable_pgs_munlocked = simple_hash("unevictable_pgs_munlocked");
191
+ // hash_unevictable_pgs_rescued = simple_hash("unevictable_pgs_rescued");
192
+ // hash_unevictable_pgs_scanned = simple_hash("unevictable_pgs_scanned");
193
+ // hash_unevictable_pgs_stranded = simple_hash("unevictable_pgs_stranded");
194
+ }
195
196
- if(do_swapio == -1) do_swapio = config_get_boolean("plugin:proc:/proc/vmstat", "swap i/o", 1);
197
- if(do_io == -1) do_io = config_get_boolean("plugin:proc:/proc/vmstat", "disk i/o", 1);
198
- if(do_pgfaults == -1) do_pgfaults = config_get_boolean("plugin:proc:/proc/vmstat", "memory page faults", 1);
196
+ if(do_swapio == -1) do_swapio = config_get_boolean("plugin:proc:/proc/vmstat", "swap i/o", 1);
197
+ if(do_io == -1) do_io = config_get_boolean("plugin:proc:/proc/vmstat", "disk i/o", 1);
198
+ if(do_pgfaults == -1) do_pgfaults = config_get_boolean("plugin:proc:/proc/vmstat", "memory page faults", 1);
199
200
- if(dt) {};
200
+ if(dt) {};
201
202
- if(!ff) {
203
- char filename[FILENAME_MAX + 1];
204
- snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/vmstat");
205
- ff = procfile_open(config_get("plugin:proc:/proc/vmstat", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
206
- }
207
- if(!ff) return 1;
202
+ if(!ff) {
203
+ char filename[FILENAME_MAX + 1];
204
+ snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/vmstat");
205
+ ff = procfile_open(config_get("plugin:proc:/proc/vmstat", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
206
+ }
207
+ if(!ff) return 1;
208
209
- ff = procfile_readall(ff);
210
- if(!ff) return 0; // we return 0, so that we will retry to open it next time
209
+ ff = procfile_readall(ff);
210
+ if(!ff) return 0; // we return 0, so that we will retry to open it next time
211
212
- uint32_t lines = procfile_lines(ff), l;
213
- uint32_t words;
212
+ uint32_t lines = procfile_lines(ff), l;
213
+ uint32_t words;
214
215
- // unsigned long long allocstall = 0ULL;
216
- // unsigned long long compact_blocks_moved = 0ULL;
217
- // unsigned long long compact_fail = 0ULL;
218
- // unsigned long long compact_pagemigrate_failed = 0ULL;
219
- // unsigned long long compact_pages_moved = 0ULL;
220
- // unsigned long long compact_stall = 0ULL;
221
- // unsigned long long compact_success = 0ULL;
222
- // unsigned long long htlb_buddy_alloc_fail = 0ULL;
223
- // unsigned long long htlb_buddy_alloc_success = 0ULL;
224
- // unsigned long long kswapd_high_wmark_hit_quickly = 0ULL;
225
- // unsigned long long kswapd_inodesteal = 0ULL;
226
- // unsigned long long kswapd_low_wmark_hit_quickly = 0ULL;
227
- // unsigned long long kswapd_skip_congestion_wait = 0ULL;
228
- // unsigned long long nr_active_anon = 0ULL;
229
- // unsigned long long nr_active_file = 0ULL;
230
- // unsigned long long nr_anon_pages = 0ULL;
231
- // unsigned long long nr_anon_transparent_hugepages = 0ULL;
232
- // unsigned long long nr_bounce = 0ULL;
233
- // unsigned long long nr_dirtied = 0ULL;
234
- // unsigned long long nr_dirty = 0ULL;
235
- // unsigned long long nr_dirty_background_threshold = 0ULL;
236
- // unsigned long long nr_dirty_threshold = 0ULL;
237
- // unsigned long long nr_file_pages = 0ULL;
238
- // unsigned long long nr_free_pages = 0ULL;
239
- // unsigned long long nr_inactive_anon = 0ULL;
240
- // unsigned long long nr_inactive_file = 0ULL;
241
- // unsigned long long nr_isolated_anon = 0ULL;
242
- // unsigned long long nr_isolated_file = 0ULL;
243
- // unsigned long long nr_kernel_stack = 0ULL;
244
- // unsigned long long nr_mapped = 0ULL;
245
- // unsigned long long nr_mlock = 0ULL;
246
- // unsigned long long nr_page_table_pages = 0ULL;
247
- // unsigned long long nr_shmem = 0ULL;
248
- // unsigned long long nr_slab_reclaimable = 0ULL;
249
- // unsigned long long nr_slab_unreclaimable = 0ULL;
250
- // unsigned long long nr_unevictable = 0ULL;
251
- // unsigned long long nr_unstable = 0ULL;
252
- // unsigned long long nr_vmscan_immediate_reclaim = 0ULL;
253
- // unsigned long long nr_vmscan_write = 0ULL;
254
- // unsigned long long nr_writeback = 0ULL;
255
- // unsigned long long nr_writeback_temp = 0ULL;
256
- // unsigned long long nr_written = 0ULL;
257
- // unsigned long long pageoutrun = 0ULL;
258
- // unsigned long long pgactivate = 0ULL;
259
- // unsigned long long pgalloc_dma = 0ULL;
260
- // unsigned long long pgalloc_dma32 = 0ULL;
261
- // unsigned long long pgalloc_movable = 0ULL;
262
- // unsigned long long pgalloc_normal = 0ULL;
263
- // unsigned long long pgdeactivate = 0ULL;
264
- unsigned long long pgfault = 0ULL;
265
- // unsigned long long pgfree = 0ULL;
266
- // unsigned long long pginodesteal = 0ULL;
267
- unsigned long long pgmajfault = 0ULL;
268
- unsigned long long pgpgin = 0ULL;
269
- unsigned long long pgpgout = 0ULL;
270
- // unsigned long long pgrefill_dma = 0ULL;
271
- // unsigned long long pgrefill_dma32 = 0ULL;
272
- // unsigned long long pgrefill_movable = 0ULL;
273
- // unsigned long long pgrefill_normal = 0ULL;
274
- // unsigned long long pgrotated = 0ULL;
275
- // unsigned long long pgscan_direct_dma = 0ULL;
276
- // unsigned long long pgscan_direct_dma32 = 0ULL;
277
- // unsigned long long pgscan_direct_movable = 0ULL;
278
- // unsigned long long pgscan_direct_normal = 0ULL;
279
- // unsigned long long pgscan_kswapd_dma = 0ULL;
280
- // unsigned long long pgscan_kswapd_dma32 = 0ULL;
281
- // unsigned long long pgscan_kswapd_movable = 0ULL;
282
- // unsigned long long pgscan_kswapd_normal = 0ULL;
283
- // unsigned long long pgsteal_direct_dma = 0ULL;
284
- // unsigned long long pgsteal_direct_dma32 = 0ULL;
285
- // unsigned long long pgsteal_direct_movable = 0ULL;
286
- // unsigned long long pgsteal_direct_normal = 0ULL;
287
- // unsigned long long pgsteal_kswapd_dma = 0ULL;
288
- // unsigned long long pgsteal_kswapd_dma32 = 0ULL;
289
- // unsigned long long pgsteal_kswapd_movable = 0ULL;
290
- // unsigned long long pgsteal_kswapd_normal = 0ULL;
291
- unsigned long long pswpin = 0ULL;
292
- unsigned long long pswpout = 0ULL;
293
- // unsigned long long slabs_scanned = 0ULL;
294
- // unsigned long long thp_collapse_alloc = 0ULL;
295
- // unsigned long long thp_collapse_alloc_failed = 0ULL;
296
- // unsigned long long thp_fault_alloc = 0ULL;
297
- // unsigned long long thp_fault_fallback = 0ULL;
298
- // unsigned long long thp_split = 0ULL;
299
- // unsigned long long unevictable_pgs_cleared = 0ULL;
300
- // unsigned long long unevictable_pgs_culled = 0ULL;
301
- // unsigned long long unevictable_pgs_mlocked = 0ULL;
302
- // unsigned long long unevictable_pgs_mlockfreed = 0ULL;
303
- // unsigned long long unevictable_pgs_munlocked = 0ULL;
304
- // unsigned long long unevictable_pgs_rescued = 0ULL;
305
- // unsigned long long unevictable_pgs_scanned = 0ULL;
306
- // unsigned long long unevictable_pgs_stranded = 0ULL;
215
+ // unsigned long long allocstall = 0ULL;
216
+ // unsigned long long compact_blocks_moved = 0ULL;
217
+ // unsigned long long compact_fail = 0ULL;
218
+ // unsigned long long compact_pagemigrate_failed = 0ULL;
219
+ // unsigned long long compact_pages_moved = 0ULL;
220
+ // unsigned long long compact_stall = 0ULL;
221
+ // unsigned long long compact_success = 0ULL;
222
+ // unsigned long long htlb_buddy_alloc_fail = 0ULL;
223
+ // unsigned long long htlb_buddy_alloc_success = 0ULL;
224
+ // unsigned long long kswapd_high_wmark_hit_quickly = 0ULL;
225
+ // unsigned long long kswapd_inodesteal = 0ULL;
226
+ // unsigned long long kswapd_low_wmark_hit_quickly = 0ULL;
227
+ // unsigned long long kswapd_skip_congestion_wait = 0ULL;
228
+ // unsigned long long nr_active_anon = 0ULL;
229
+ // unsigned long long nr_active_file = 0ULL;
230
+ // unsigned long long nr_anon_pages = 0ULL;
231
+ // unsigned long long nr_anon_transparent_hugepages = 0ULL;
232
+ // unsigned long long nr_bounce = 0ULL;
233
+ // unsigned long long nr_dirtied = 0ULL;
234
+ // unsigned long long nr_dirty = 0ULL;
235
+ // unsigned long long nr_dirty_background_threshold = 0ULL;
236
+ // unsigned long long nr_dirty_threshold = 0ULL;
237
+ // unsigned long long nr_file_pages = 0ULL;
238
+ // unsigned long long nr_free_pages = 0ULL;
239
+ // unsigned long long nr_inactive_anon = 0ULL;
240
+ // unsigned long long nr_inactive_file = 0ULL;
241
+ // unsigned long long nr_isolated_anon = 0ULL;
242
+ // unsigned long long nr_isolated_file = 0ULL;
243
+ // unsigned long long nr_kernel_stack = 0ULL;
244
+ // unsigned long long nr_mapped = 0ULL;
245
+ // unsigned long long nr_mlock = 0ULL;
246
+ // unsigned long long nr_page_table_pages = 0ULL;
247
+ // unsigned long long nr_shmem = 0ULL;
248
+ // unsigned long long nr_slab_reclaimable = 0ULL;
249
+ // unsigned long long nr_slab_unreclaimable = 0ULL;
250
+ // unsigned long long nr_unevictable = 0ULL;
251
+ // unsigned long long nr_unstable = 0ULL;
252
+ // unsigned long long nr_vmscan_immediate_reclaim = 0ULL;
253
+ // unsigned long long nr_vmscan_write = 0ULL;
254
+ // unsigned long long nr_writeback = 0ULL;
255
+ // unsigned long long nr_writeback_temp = 0ULL;
256
+ // unsigned long long nr_written = 0ULL;
257
+ // unsigned long long pageoutrun = 0ULL;
258
+ // unsigned long long pgactivate = 0ULL;
259
+ // unsigned long long pgalloc_dma = 0ULL;
260
+ // unsigned long long pgalloc_dma32 = 0ULL;
261
+ // unsigned long long pgalloc_movable = 0ULL;
262
+ // unsigned long long pgalloc_normal = 0ULL;
263
+ // unsigned long long pgdeactivate = 0ULL;
264
+ unsigned long long pgfault = 0ULL;
265
+ // unsigned long long pgfree = 0ULL;
266
+ // unsigned long long pginodesteal = 0ULL;
267
+ unsigned long long pgmajfault = 0ULL;
268
+ unsigned long long pgpgin = 0ULL;
269
+ unsigned long long pgpgout = 0ULL;
270
+ // unsigned long long pgrefill_dma = 0ULL;
271
+ // unsigned long long pgrefill_dma32 = 0ULL;
272
+ // unsigned long long pgrefill_movable = 0ULL;
273
+ // unsigned long long pgrefill_normal = 0ULL;
274
+ // unsigned long long pgrotated = 0ULL;
275
+ // unsigned long long pgscan_direct_dma = 0ULL;
276
+ // unsigned long long pgscan_direct_dma32 = 0ULL;
277
+ // unsigned long long pgscan_direct_movable = 0ULL;
278
+ // unsigned long long pgscan_direct_normal = 0ULL;
279
+ // unsigned long long pgscan_kswapd_dma = 0ULL;
280
+ // unsigned long long pgscan_kswapd_dma32 = 0ULL;
281
+ // unsigned long long pgscan_kswapd_movable = 0ULL;
282
+ // unsigned long long pgscan_kswapd_normal = 0ULL;
283
+ // unsigned long long pgsteal_direct_dma = 0ULL;
284
+ // unsigned long long pgsteal_direct_dma32 = 0ULL;
285
+ // unsigned long long pgsteal_direct_movable = 0ULL;
286
+ // unsigned long long pgsteal_direct_normal = 0ULL;
287
+ // unsigned long long pgsteal_kswapd_dma = 0ULL;
288
+ // unsigned long long pgsteal_kswapd_dma32 = 0ULL;
289
+ // unsigned long long pgsteal_kswapd_movable = 0ULL;
290
+ // unsigned long long pgsteal_kswapd_normal = 0ULL;
291
+ unsigned long long pswpin = 0ULL;
292
+ unsigned long long pswpout = 0ULL;
293
+ // unsigned long long slabs_scanned = 0ULL;
294
+ // unsigned long long thp_collapse_alloc = 0ULL;
295
+ // unsigned long long thp_collapse_alloc_failed = 0ULL;
296
+ // unsigned long long thp_fault_alloc = 0ULL;
297
+ // unsigned long long thp_fault_fallback = 0ULL;
298
+ // unsigned long long thp_split = 0ULL;
299
+ // unsigned long long unevictable_pgs_cleared = 0ULL;
300
+ // unsigned long long unevictable_pgs_culled = 0ULL;
301
+ // unsigned long long unevictable_pgs_mlocked = 0ULL;
302
+ // unsigned long long unevictable_pgs_mlockfreed = 0ULL;
303
+ // unsigned long long unevictable_pgs_munlocked = 0ULL;
304
+ // unsigned long long unevictable_pgs_rescued = 0ULL;
305
+ // unsigned long long unevictable_pgs_scanned = 0ULL;
306
+ // unsigned long long unevictable_pgs_stranded = 0ULL;
307
308
- for(l = 0; l < lines ;l++) {
309
- words = procfile_linewords(ff, l);
310
- if(words < 2) {
311
- if(words) error("Cannot read /proc/vmstat line %u. Expected 2 params, read %u.", l, words);
312
- continue;
313
- }
308
+ for(l = 0; l < lines ;l++) {
309
+ words = procfile_linewords(ff, l);
310
+ if(words < 2) {
311
+ if(words) error("Cannot read /proc/vmstat line %u. Expected 2 params, read %u.", l, words);
312
+ continue;
313
+ }
314
315
- char *name = procfile_lineword(ff, l, 0);
316
- char * value = procfile_lineword(ff, l, 1);
317
- if(!name || !*name || !value || !*value) continue;
315
+ char *name = procfile_lineword(ff, l, 0);
316
+ char * value = procfile_lineword(ff, l, 1);
317
+ if(!name || !*name || !value || !*value) continue;
318
319
- uint32_t hash = simple_hash(name);
319
+ uint32_t hash = simple_hash(name);
320
321
- if(0) ;
322
- // else if(hash == hash_allocstall && strcmp(name, "allocstall") == 0) allocstall = strtoull(value, NULL, 10);
323
- // else if(hash == hash_compact_blocks_moved && strcmp(name, "compact_blocks_moved") == 0) compact_blocks_moved = strtoull(value, NULL, 10);
324
- // else if(hash == hash_compact_fail && strcmp(name, "compact_fail") == 0) compact_fail = strtoull(value, NULL, 10);
325
- // else if(hash == hash_compact_pagemigrate_failed && strcmp(name, "compact_pagemigrate_failed") == 0) compact_pagemigrate_failed = strtoull(value, NULL, 10);
326
- // else if(hash == hash_compact_pages_moved && strcmp(name, "compact_pages_moved") == 0) compact_pages_moved = strtoull(value, NULL, 10);
327
- // else if(hash == hash_compact_stall && strcmp(name, "compact_stall") == 0) compact_stall = strtoull(value, NULL, 10);
328
- // else if(hash == hash_compact_success && strcmp(name, "compact_success") == 0) compact_success = strtoull(value, NULL, 10);
329
- // else if(hash == hash_htlb_buddy_alloc_fail && strcmp(name, "htlb_buddy_alloc_fail") == 0) htlb_buddy_alloc_fail = strtoull(value, NULL, 10);
330
- // else if(hash == hash_htlb_buddy_alloc_success && strcmp(name, "htlb_buddy_alloc_success") == 0) htlb_buddy_alloc_success = strtoull(value, NULL, 10);
331
- // else if(hash == hash_kswapd_high_wmark_hit_quickly && strcmp(name, "kswapd_high_wmark_hit_quickly") == 0) kswapd_high_wmark_hit_quickly = strtoull(value, NULL, 10);
332
- // else if(hash == hash_kswapd_inodesteal && strcmp(name, "kswapd_inodesteal") == 0) kswapd_inodesteal = strtoull(value, NULL, 10);
333
- // else if(hash == hash_kswapd_low_wmark_hit_quickly && strcmp(name, "kswapd_low_wmark_hit_quickly") == 0) kswapd_low_wmark_hit_quickly = strtoull(value, NULL, 10);
334
- // else if(hash == hash_kswapd_skip_congestion_wait && strcmp(name, "kswapd_skip_congestion_wait") == 0) kswapd_skip_congestion_wait = strtoull(value, NULL, 10);
335
- // else if(hash == hash_nr_active_anon && strcmp(name, "nr_active_anon") == 0) nr_active_anon = strtoull(value, NULL, 10);
336
- // else if(hash == hash_nr_active_file && strcmp(name, "nr_active_file") == 0) nr_active_file = strtoull(value, NULL, 10);
337
- // else if(hash == hash_nr_anon_pages && strcmp(name, "nr_anon_pages") == 0) nr_anon_pages = strtoull(value, NULL, 10);
338
- // else if(hash == hash_nr_anon_transparent_hugepages && strcmp(name, "nr_anon_transparent_hugepages") == 0) nr_anon_transparent_hugepages = strtoull(value, NULL, 10);
339
- // else if(hash == hash_nr_bounce && strcmp(name, "nr_bounce") == 0) nr_bounce = strtoull(value, NULL, 10);
340
- // else if(hash == hash_nr_dirtied && strcmp(name, "nr_dirtied") == 0) nr_dirtied = strtoull(value, NULL, 10);
341
- // else if(hash == hash_nr_dirty && strcmp(name, "nr_dirty") == 0) nr_dirty = strtoull(value, NULL, 10);
342
- // else if(hash == hash_nr_dirty_background_threshold && strcmp(name, "nr_dirty_background_threshold") == 0) nr_dirty_background_threshold = strtoull(value, NULL, 10);
343
- // else if(hash == hash_nr_dirty_threshold && strcmp(name, "nr_dirty_threshold") == 0) nr_dirty_threshold = strtoull(value, NULL, 10);
344
- // else if(hash == hash_nr_file_pages && strcmp(name, "nr_file_pages") == 0) nr_file_pages = strtoull(value, NULL, 10);
345
- // else if(hash == hash_nr_free_pages && strcmp(name, "nr_free_pages") == 0) nr_free_pages = strtoull(value, NULL, 10);
346
- // else if(hash == hash_nr_inactive_anon && strcmp(name, "nr_inactive_anon") == 0) nr_inactive_anon = strtoull(value, NULL, 10);
347
- // else if(hash == hash_nr_inactive_file && strcmp(name, "nr_inactive_file") == 0) nr_inactive_file = strtoull(value, NULL, 10);
348
- // else if(hash == hash_nr_isolated_anon && strcmp(name, "nr_isolated_anon") == 0) nr_isolated_anon = strtoull(value, NULL, 10);
349
- // else if(hash == hash_nr_isolated_file && strcmp(name, "nr_isolated_file") == 0) nr_isolated_file = strtoull(value, NULL, 10);
350
- // else if(hash == hash_nr_kernel_stack && strcmp(name, "nr_kernel_stack") == 0) nr_kernel_stack = strtoull(value, NULL, 10);
351
- // else if(hash == hash_nr_mapped && strcmp(name, "nr_mapped") == 0) nr_mapped = strtoull(value, NULL, 10);
352
- // else if(hash == hash_nr_mlock && strcmp(name, "nr_mlock") == 0) nr_mlock = strtoull(value, NULL, 10);
353
- // else if(hash == hash_nr_page_table_pages && strcmp(name, "nr_page_table_pages") == 0) nr_page_table_pages = strtoull(value, NULL, 10);
354
- // else if(hash == hash_nr_shmem && strcmp(name, "nr_shmem") == 0) nr_shmem = strtoull(value, NULL, 10);
355
- // else if(hash == hash_nr_slab_reclaimable && strcmp(name, "nr_slab_reclaimable") == 0) nr_slab_reclaimable = strtoull(value, NULL, 10);
356
- // else if(hash == hash_nr_slab_unreclaimable && strcmp(name, "nr_slab_unreclaimable") == 0) nr_slab_unreclaimable = strtoull(value, NULL, 10);
357
- // else if(hash == hash_nr_unevictable && strcmp(name, "nr_unevictable") == 0) nr_unevictable = strtoull(value, NULL, 10);
358
- // else if(hash == hash_nr_unstable && strcmp(name, "nr_unstable") == 0) nr_unstable = strtoull(value, NULL, 10);
359
- // else if(hash == hash_nr_vmscan_immediate_reclaim && strcmp(name, "nr_vmscan_immediate_reclaim") == 0) nr_vmscan_immediate_reclaim = strtoull(value, NULL, 10);
360
- // else if(hash == hash_nr_vmscan_write && strcmp(name, "nr_vmscan_write") == 0) nr_vmscan_write = strtoull(value, NULL, 10);
361
- // else if(hash == hash_nr_writeback && strcmp(name, "nr_writeback") == 0) nr_writeback = strtoull(value, NULL, 10);
362
- // else if(hash == hash_nr_writeback_temp && strcmp(name, "nr_writeback_temp") == 0) nr_writeback_temp = strtoull(value, NULL, 10);
363
- // else if(hash == hash_nr_written && strcmp(name, "nr_written") == 0) nr_written = strtoull(value, NULL, 10);
364
- // else if(hash == hash_pageoutrun && strcmp(name, "pageoutrun") == 0) pageoutrun = strtoull(value, NULL, 10);
365
- // else if(hash == hash_pgactivate && strcmp(name, "pgactivate") == 0) pgactivate = strtoull(value, NULL, 10);
366
- // else if(hash == hash_pgalloc_dma && strcmp(name, "pgalloc_dma") == 0) pgalloc_dma = strtoull(value, NULL, 10);
367
- // else if(hash == hash_pgalloc_dma32 && strcmp(name, "pgalloc_dma32") == 0) pgalloc_dma32 = strtoull(value, NULL, 10);
368
- // else if(hash == hash_pgalloc_movable && strcmp(name, "pgalloc_movable") == 0) pgalloc_movable = strtoull(value, NULL, 10);
369
- // else if(hash == hash_pgalloc_normal && strcmp(name, "pgalloc_normal") == 0) pgalloc_normal = strtoull(value, NULL, 10);
370
- // else if(hash == hash_pgdeactivate && strcmp(name, "pgdeactivate") == 0) pgdeactivate = strtoull(value, NULL, 10);
371
- else if(hash == hash_pgfault && strcmp(name, "pgfault") == 0) pgfault = strtoull(value, NULL, 10);
372
- // else if(hash == hash_pgfree && strcmp(name, "pgfree") == 0) pgfree = strtoull(value, NULL, 10);
373
- // else if(hash == hash_pginodesteal && strcmp(name, "pginodesteal") == 0) pginodesteal = strtoull(value, NULL, 10);
374
- else if(hash == hash_pgmajfault && strcmp(name, "pgmajfault") == 0) pgmajfault = strtoull(value, NULL, 10);
375
- else if(hash == hash_pgpgin && strcmp(name, "pgpgin") == 0) pgpgin = strtoull(value, NULL, 10);
376
- else if(hash == hash_pgpgout && strcmp(name, "pgpgout") == 0) pgpgout = strtoull(value, NULL, 10);
377
- // else if(hash == hash_pgrefill_dma && strcmp(name, "pgrefill_dma") == 0) pgrefill_dma = strtoull(value, NULL, 10);
378
- // else if(hash == hash_pgrefill_dma32 && strcmp(name, "pgrefill_dma32") == 0) pgrefill_dma32 = strtoull(value, NULL, 10);
379
- // else if(hash == hash_pgrefill_movable && strcmp(name, "pgrefill_movable") == 0) pgrefill_movable = strtoull(value, NULL, 10);
380
- // else if(hash == hash_pgrefill_normal && strcmp(name, "pgrefill_normal") == 0) pgrefill_normal = strtoull(value, NULL, 10);
381
- // else if(hash == hash_pgrotated && strcmp(name, "pgrotated") == 0) pgrotated = strtoull(value, NULL, 10);
382
- // else if(hash == hash_pgscan_direct_dma && strcmp(name, "pgscan_direct_dma") == 0) pgscan_direct_dma = strtoull(value, NULL, 10);
383
- // else if(hash == hash_pgscan_direct_dma32 && strcmp(name, "pgscan_direct_dma32") == 0) pgscan_direct_dma32 = strtoull(value, NULL, 10);
384
- // else if(hash == hash_pgscan_direct_movable && strcmp(name, "pgscan_direct_movable") == 0) pgscan_direct_movable = strtoull(value, NULL, 10);
385
- // else if(hash == hash_pgscan_direct_normal && strcmp(name, "pgscan_direct_normal") == 0) pgscan_direct_normal = strtoull(value, NULL, 10);
386
- // else if(hash == hash_pgscan_kswapd_dma && strcmp(name, "pgscan_kswapd_dma") == 0) pgscan_kswapd_dma = strtoull(value, NULL, 10);
387
- // else if(hash == hash_pgscan_kswapd_dma32 && strcmp(name, "pgscan_kswapd_dma32") == 0) pgscan_kswapd_dma32 = strtoull(value, NULL, 10);
388
- // else if(hash == hash_pgscan_kswapd_movable && strcmp(name, "pgscan_kswapd_movable") == 0) pgscan_kswapd_movable = strtoull(value, NULL, 10);
389
- // else if(hash == hash_pgscan_kswapd_normal && strcmp(name, "pgscan_kswapd_normal") == 0) pgscan_kswapd_normal = strtoull(value, NULL, 10);
390
- // else if(hash == hash_pgsteal_direct_dma && strcmp(name, "pgsteal_direct_dma") == 0) pgsteal_direct_dma = strtoull(value, NULL, 10);
391
- // else if(hash == hash_pgsteal_direct_dma32 && strcmp(name, "pgsteal_direct_dma32") == 0) pgsteal_direct_dma32 = strtoull(value, NULL, 10);
392
- // else if(hash == hash_pgsteal_direct_movable && strcmp(name, "pgsteal_direct_movable") == 0) pgsteal_direct_movable = strtoull(value, NULL, 10);
393
- // else if(hash == hash_pgsteal_direct_normal && strcmp(name, "pgsteal_direct_normal") == 0) pgsteal_direct_normal = strtoull(value, NULL, 10);
394
- // else if(hash == hash_pgsteal_kswapd_dma && strcmp(name, "pgsteal_kswapd_dma") == 0) pgsteal_kswapd_dma = strtoull(value, NULL, 10);
395
- // else if(hash == hash_pgsteal_kswapd_dma32 && strcmp(name, "pgsteal_kswapd_dma32") == 0) pgsteal_kswapd_dma32 = strtoull(value, NULL, 10);
396
- // else if(hash == hash_pgsteal_kswapd_movable && strcmp(name, "pgsteal_kswapd_movable") == 0) pgsteal_kswapd_movable = strtoull(value, NULL, 10);
397
- // else if(hash == hash_pgsteal_kswapd_normal && strcmp(name, "pgsteal_kswapd_normal") == 0) pgsteal_kswapd_normal = strtoull(value, NULL, 10);
398
- else if(hash == hash_pswpin && strcmp(name, "pswpin") == 0) pswpin = strtoull(value, NULL, 10);
399
- else if(hash == hash_pswpout && strcmp(name, "pswpout") == 0) pswpout = strtoull(value, NULL, 10);
400
- // else if(hash == hash_slabs_scanned && strcmp(name, "slabs_scanned") == 0) slabs_scanned = strtoull(value, NULL, 10);
401
- // else if(hash == hash_thp_collapse_alloc && strcmp(name, "thp_collapse_alloc") == 0) thp_collapse_alloc = strtoull(value, NULL, 10);
402
- // else if(hash == hash_thp_collapse_alloc_failed && strcmp(name, "thp_collapse_alloc_failed") == 0) thp_collapse_alloc_failed = strtoull(value, NULL, 10);
403
- // else if(hash == hash_thp_fault_alloc && strcmp(name, "thp_fault_alloc") == 0) thp_fault_alloc = strtoull(value, NULL, 10);
404
- // else if(hash == hash_thp_fault_fallback && strcmp(name, "thp_fault_fallback") == 0) thp_fault_fallback = strtoull(value, NULL, 10);
405
- // else if(hash == hash_thp_split && strcmp(name, "thp_split") == 0) thp_split = strtoull(value, NULL, 10);
406
- // else if(hash == hash_unevictable_pgs_cleared && strcmp(name, "unevictable_pgs_cleared") == 0) unevictable_pgs_cleared = strtoull(value, NULL, 10);
407
- // else if(hash == hash_unevictable_pgs_culled && strcmp(name, "unevictable_pgs_culled") == 0) unevictable_pgs_culled = strtoull(value, NULL, 10);
408
- // else if(hash == hash_unevictable_pgs_mlocked && strcmp(name, "unevictable_pgs_mlocked") == 0) unevictable_pgs_mlocked = strtoull(value, NULL, 10);
409
- // else if(hash == hash_unevictable_pgs_mlockfreed && strcmp(name, "unevictable_pgs_mlockfreed") == 0) unevictable_pgs_mlockfreed = strtoull(value, NULL, 10);
410
- // else if(hash == hash_unevictable_pgs_munlocked && strcmp(name, "unevictable_pgs_munlocked") == 0) unevictable_pgs_munlocked = strtoull(value, NULL, 10);
411
- // else if(hash == hash_unevictable_pgs_rescued && strcmp(name, "unevictable_pgs_rescued") == 0) unevictable_pgs_rescued = strtoull(value, NULL, 10);
412
- // else if(hash == hash_unevictable_pgs_scanned && strcmp(name, "unevictable_pgs_scanned") == 0) unevictable_pgs_scanned = strtoull(value, NULL, 10);
413
- // else if(hash == hash_unevictable_pgs_stranded && strcmp(name, "unevictable_pgs_stranded") == 0) unevictable_pgs_stranded = strtoull(value, NULL, 10);
414
- }
321
+ if(0) ;
322
+ // else if(hash == hash_allocstall && strcmp(name, "allocstall") == 0) allocstall = strtoull(value, NULL, 10);
323
+ // else if(hash == hash_compact_blocks_moved && strcmp(name, "compact_blocks_moved") == 0) compact_blocks_moved = strtoull(value, NULL, 10);
324
+ // else if(hash == hash_compact_fail && strcmp(name, "compact_fail") == 0) compact_fail = strtoull(value, NULL, 10);
325
+ // else if(hash == hash_compact_pagemigrate_failed && strcmp(name, "compact_pagemigrate_failed") == 0) compact_pagemigrate_failed = strtoull(value, NULL, 10);
326
+ // else if(hash == hash_compact_pages_moved && strcmp(name, "compact_pages_moved") == 0) compact_pages_moved = strtoull(value, NULL, 10);
327
+ // else if(hash == hash_compact_stall && strcmp(name, "compact_stall") == 0) compact_stall = strtoull(value, NULL, 10);
328
+ // else if(hash == hash_compact_success && strcmp(name, "compact_success") == 0) compact_success = strtoull(value, NULL, 10);
329
+ // else if(hash == hash_htlb_buddy_alloc_fail && strcmp(name, "htlb_buddy_alloc_fail") == 0) htlb_buddy_alloc_fail = strtoull(value, NULL, 10);
330
+ // else if(hash == hash_htlb_buddy_alloc_success && strcmp(name, "htlb_buddy_alloc_success") == 0) htlb_buddy_alloc_success = strtoull(value, NULL, 10);
331
+ // else if(hash == hash_kswapd_high_wmark_hit_quickly && strcmp(name, "kswapd_high_wmark_hit_quickly") == 0) kswapd_high_wmark_hit_quickly = strtoull(value, NULL, 10);
332
+ // else if(hash == hash_kswapd_inodesteal && strcmp(name, "kswapd_inodesteal") == 0) kswapd_inodesteal = strtoull(value, NULL, 10);
333
+ // else if(hash == hash_kswapd_low_wmark_hit_quickly && strcmp(name, "kswapd_low_wmark_hit_quickly") == 0) kswapd_low_wmark_hit_quickly = strtoull(value, NULL, 10);
334
+ // else if(hash == hash_kswapd_skip_congestion_wait && strcmp(name, "kswapd_skip_congestion_wait") == 0) kswapd_skip_congestion_wait = strtoull(value, NULL, 10);
335
+ // else if(hash == hash_nr_active_anon && strcmp(name, "nr_active_anon") == 0) nr_active_anon = strtoull(value, NULL, 10);
336
+ // else if(hash == hash_nr_active_file && strcmp(name, "nr_active_file") == 0) nr_active_file = strtoull(value, NULL, 10);
337
+ // else if(hash == hash_nr_anon_pages && strcmp(name, "nr_anon_pages") == 0) nr_anon_pages = strtoull(value, NULL, 10);
338
+ // else if(hash == hash_nr_anon_transparent_hugepages && strcmp(name, "nr_anon_transparent_hugepages") == 0) nr_anon_transparent_hugepages = strtoull(value, NULL, 10);
339
+ // else if(hash == hash_nr_bounce && strcmp(name, "nr_bounce") == 0) nr_bounce = strtoull(value, NULL, 10);
340
+ // else if(hash == hash_nr_dirtied && strcmp(name, "nr_dirtied") == 0) nr_dirtied = strtoull(value, NULL, 10);
341
+ // else if(hash == hash_nr_dirty && strcmp(name, "nr_dirty") == 0) nr_dirty = strtoull(value, NULL, 10);
342
+ // else if(hash == hash_nr_dirty_background_threshold && strcmp(name, "nr_dirty_background_threshold") == 0) nr_dirty_background_threshold = strtoull(value, NULL, 10);
343
+ // else if(hash == hash_nr_dirty_threshold && strcmp(name, "nr_dirty_threshold") == 0) nr_dirty_threshold = strtoull(value, NULL, 10);
344
+ // else if(hash == hash_nr_file_pages && strcmp(name, "nr_file_pages") == 0) nr_file_pages = strtoull(value, NULL, 10);
345
+ // else if(hash == hash_nr_free_pages && strcmp(name, "nr_free_pages") == 0) nr_free_pages = strtoull(value, NULL, 10);
346
+ // else if(hash == hash_nr_inactive_anon && strcmp(name, "nr_inactive_anon") == 0) nr_inactive_anon = strtoull(value, NULL, 10);
347
+ // else if(hash == hash_nr_inactive_file && strcmp(name, "nr_inactive_file") == 0) nr_inactive_file = strtoull(value, NULL, 10);
348
+ // else if(hash == hash_nr_isolated_anon && strcmp(name, "nr_isolated_anon") == 0) nr_isolated_anon = strtoull(value, NULL, 10);
349
+ // else if(hash == hash_nr_isolated_file && strcmp(name, "nr_isolated_file") == 0) nr_isolated_file = strtoull(value, NULL, 10);
350
+ // else if(hash == hash_nr_kernel_stack && strcmp(name, "nr_kernel_stack") == 0) nr_kernel_stack = strtoull(value, NULL, 10);
351
+ // else if(hash == hash_nr_mapped && strcmp(name, "nr_mapped") == 0) nr_mapped = strtoull(value, NULL, 10);
352
+ // else if(hash == hash_nr_mlock && strcmp(name, "nr_mlock") == 0) nr_mlock = strtoull(value, NULL, 10);
353
+ // else if(hash == hash_nr_page_table_pages && strcmp(name, "nr_page_table_pages") == 0) nr_page_table_pages = strtoull(value, NULL, 10);
354
+ // else if(hash == hash_nr_shmem && strcmp(name, "nr_shmem") == 0) nr_shmem = strtoull(value, NULL, 10);
355
+ // else if(hash == hash_nr_slab_reclaimable && strcmp(name, "nr_slab_reclaimable") == 0) nr_slab_reclaimable = strtoull(value, NULL, 10);
356
+ // else if(hash == hash_nr_slab_unreclaimable && strcmp(name, "nr_slab_unreclaimable") == 0) nr_slab_unreclaimable = strtoull(value, NULL, 10);
357
+ // else if(hash == hash_nr_unevictable && strcmp(name, "nr_unevictable") == 0) nr_unevictable = strtoull(value, NULL, 10);
358
+ // else if(hash == hash_nr_unstable && strcmp(name, "nr_unstable") == 0) nr_unstable = strtoull(value, NULL, 10);
359
+ // else if(hash == hash_nr_vmscan_immediate_reclaim && strcmp(name, "nr_vmscan_immediate_reclaim") == 0) nr_vmscan_immediate_reclaim = strtoull(value, NULL, 10);
360
+ // else if(hash == hash_nr_vmscan_write && strcmp(name, "nr_vmscan_write") == 0) nr_vmscan_write = strtoull(value, NULL, 10);
361
+ // else if(hash == hash_nr_writeback && strcmp(name, "nr_writeback") == 0) nr_writeback = strtoull(value, NULL, 10);
362
+ // else if(hash == hash_nr_writeback_temp && strcmp(name, "nr_writeback_temp") == 0) nr_writeback_temp = strtoull(value, NULL, 10);
363
+ // else if(hash == hash_nr_written && strcmp(name, "nr_written") == 0) nr_written = strtoull(value, NULL, 10);
364
+ // else if(hash == hash_pageoutrun && strcmp(name, "pageoutrun") == 0) pageoutrun = strtoull(value, NULL, 10);
365
+ // else if(hash == hash_pgactivate && strcmp(name, "pgactivate") == 0) pgactivate = strtoull(value, NULL, 10);
366
+ // else if(hash == hash_pgalloc_dma && strcmp(name, "pgalloc_dma") == 0) pgalloc_dma = strtoull(value, NULL, 10);
367
+ // else if(hash == hash_pgalloc_dma32 && strcmp(name, "pgalloc_dma32") == 0) pgalloc_dma32 = strtoull(value, NULL, 10);
368
+ // else if(hash == hash_pgalloc_movable && strcmp(name, "pgalloc_movable") == 0) pgalloc_movable = strtoull(value, NULL, 10);
369
+ // else if(hash == hash_pgalloc_normal && strcmp(name, "pgalloc_normal") == 0) pgalloc_normal = strtoull(value, NULL, 10);
370
+ // else if(hash == hash_pgdeactivate && strcmp(name, "pgdeactivate") == 0) pgdeactivate = strtoull(value, NULL, 10);
371
+ else if(hash == hash_pgfault && strcmp(name, "pgfault") == 0) pgfault = strtoull(value, NULL, 10);
372
+ // else if(hash == hash_pgfree && strcmp(name, "pgfree") == 0) pgfree = strtoull(value, NULL, 10);
373
+ // else if(hash == hash_pginodesteal && strcmp(name, "pginodesteal") == 0) pginodesteal = strtoull(value, NULL, 10);
374
+ else if(hash == hash_pgmajfault && strcmp(name, "pgmajfault") == 0) pgmajfault = strtoull(value, NULL, 10);
375
+ else if(hash == hash_pgpgin && strcmp(name, "pgpgin") == 0) pgpgin = strtoull(value, NULL, 10);
376
+ else if(hash == hash_pgpgout && strcmp(name, "pgpgout") == 0) pgpgout = strtoull(value, NULL, 10);
377
+ // else if(hash == hash_pgrefill_dma && strcmp(name, "pgrefill_dma") == 0) pgrefill_dma = strtoull(value, NULL, 10);
378
+ // else if(hash == hash_pgrefill_dma32 && strcmp(name, "pgrefill_dma32") == 0) pgrefill_dma32 = strtoull(value, NULL, 10);
379
+ // else if(hash == hash_pgrefill_movable && strcmp(name, "pgrefill_movable") == 0) pgrefill_movable = strtoull(value, NULL, 10);
380
+ // else if(hash == hash_pgrefill_normal && strcmp(name, "pgrefill_normal") == 0) pgrefill_normal = strtoull(value, NULL, 10);
381
+ // else if(hash == hash_pgrotated && strcmp(name, "pgrotated") == 0) pgrotated = strtoull(value, NULL, 10);
382
+ // else if(hash == hash_pgscan_direct_dma && strcmp(name, "pgscan_direct_dma") == 0) pgscan_direct_dma = strtoull(value, NULL, 10);
383
+ // else if(hash == hash_pgscan_direct_dma32 && strcmp(name, "pgscan_direct_dma32") == 0) pgscan_direct_dma32 = strtoull(value, NULL, 10);
384
+ // else if(hash == hash_pgscan_direct_movable && strcmp(name, "pgscan_direct_movable") == 0) pgscan_direct_movable = strtoull(value, NULL, 10);
385
+ // else if(hash == hash_pgscan_direct_normal && strcmp(name, "pgscan_direct_normal") == 0) pgscan_direct_normal = strtoull(value, NULL, 10);
386
+ // else if(hash == hash_pgscan_kswapd_dma && strcmp(name, "pgscan_kswapd_dma") == 0) pgscan_kswapd_dma = strtoull(value, NULL, 10);
387
+ // else if(hash == hash_pgscan_kswapd_dma32 && strcmp(name, "pgscan_kswapd_dma32") == 0) pgscan_kswapd_dma32 = strtoull(value, NULL, 10);
388
+ // else if(hash == hash_pgscan_kswapd_movable && strcmp(name, "pgscan_kswapd_movable") == 0) pgscan_kswapd_movable = strtoull(value, NULL, 10);
389
+ // else if(hash == hash_pgscan_kswapd_normal && strcmp(name, "pgscan_kswapd_normal") == 0) pgscan_kswapd_normal = strtoull(value, NULL, 10);
390
+ // else if(hash == hash_pgsteal_direct_dma && strcmp(name, "pgsteal_direct_dma") == 0) pgsteal_direct_dma = strtoull(value, NULL, 10);
391
+ // else if(hash == hash_pgsteal_direct_dma32 && strcmp(name, "pgsteal_direct_dma32") == 0) pgsteal_direct_dma32 = strtoull(value, NULL, 10);
392
+ // else if(hash == hash_pgsteal_direct_movable && strcmp(name, "pgsteal_direct_movable") == 0) pgsteal_direct_movable = strtoull(value, NULL, 10);
393
+ // else if(hash == hash_pgsteal_direct_normal && strcmp(name, "pgsteal_direct_normal") == 0) pgsteal_direct_normal = strtoull(value, NULL, 10);
394
+ // else if(hash == hash_pgsteal_kswapd_dma && strcmp(name, "pgsteal_kswapd_dma") == 0) pgsteal_kswapd_dma = strtoull(value, NULL, 10);
395
+ // else if(hash == hash_pgsteal_kswapd_dma32 && strcmp(name, "pgsteal_kswapd_dma32") == 0) pgsteal_kswapd_dma32 = strtoull(value, NULL, 10);
396
+ // else if(hash == hash_pgsteal_kswapd_movable && strcmp(name, "pgsteal_kswapd_movable") == 0) pgsteal_kswapd_movable = strtoull(value, NULL, 10);
397
+ // else if(hash == hash_pgsteal_kswapd_normal && strcmp(name, "pgsteal_kswapd_normal") == 0) pgsteal_kswapd_normal = strtoull(value, NULL, 10);
398
+ else if(hash == hash_pswpin && strcmp(name, "pswpin") == 0) pswpin = strtoull(value, NULL, 10);
399
+ else if(hash == hash_pswpout && strcmp(name, "pswpout") == 0) pswpout = strtoull(value, NULL, 10);
400
+ // else if(hash == hash_slabs_scanned && strcmp(name, "slabs_scanned") == 0) slabs_scanned = strtoull(value, NULL, 10);
401
+ // else if(hash == hash_thp_collapse_alloc && strcmp(name, "thp_collapse_alloc") == 0) thp_collapse_alloc = strtoull(value, NULL, 10);
402
+ // else if(hash == hash_thp_collapse_alloc_failed && strcmp(name, "thp_collapse_alloc_failed") == 0) thp_collapse_alloc_failed = strtoull(value, NULL, 10);
403
+ // else if(hash == hash_thp_fault_alloc && strcmp(name, "thp_fault_alloc") == 0) thp_fault_alloc = strtoull(value, NULL, 10);
404
+ // else if(hash == hash_thp_fault_fallback && strcmp(name, "thp_fault_fallback") == 0) thp_fault_fallback = strtoull(value, NULL, 10);
405
+ // else if(hash == hash_thp_split && strcmp(name, "thp_split") == 0) thp_split = strtoull(value, NULL, 10);
406
+ // else if(hash == hash_unevictable_pgs_cleared && strcmp(name, "unevictable_pgs_cleared") == 0) unevictable_pgs_cleared = strtoull(value, NULL, 10);
407
+ // else if(hash == hash_unevictable_pgs_culled && strcmp(name, "unevictable_pgs_culled") == 0) unevictable_pgs_culled = strtoull(value, NULL, 10);
408
+ // else if(hash == hash_unevictable_pgs_mlocked && strcmp(name, "unevictable_pgs_mlocked") == 0) unevictable_pgs_mlocked = strtoull(value, NULL, 10);
409
+ // else if(hash == hash_unevictable_pgs_mlockfreed && strcmp(name, "unevictable_pgs_mlockfreed") == 0) unevictable_pgs_mlockfreed = strtoull(value, NULL, 10);
410
+ // else if(hash == hash_unevictable_pgs_munlocked && strcmp(name, "unevictable_pgs_munlocked") == 0) unevictable_pgs_munlocked = strtoull(value, NULL, 10);
411
+ // else if(hash == hash_unevictable_pgs_rescued && strcmp(name, "unevictable_pgs_rescued") == 0) unevictable_pgs_rescued = strtoull(value, NULL, 10);
412
+ // else if(hash == hash_unevictable_pgs_scanned && strcmp(name, "unevictable_pgs_scanned") == 0) unevictable_pgs_scanned = strtoull(value, NULL, 10);
413
+ // else if(hash == hash_unevictable_pgs_stranded && strcmp(name, "unevictable_pgs_stranded") == 0) unevictable_pgs_stranded = strtoull(value, NULL, 10);
414
+ }
415
416
- // --------------------------------------------------------------------
416
+ // --------------------------------------------------------------------
417
418
- if(do_swapio) {
419
- static RRDSET *st_swapio = NULL;
420
- if(!st_swapio) {
421
- st_swapio = rrdset_create("system", "swapio", NULL, "swap", NULL, "Swap I/O", "kilobytes/s", 250, update_every, RRDSET_TYPE_AREA);
418
+ if(do_swapio) {
419
+ static RRDSET *st_swapio = NULL;
420
+ if(!st_swapio) {
421
+ st_swapio = rrdset_create("system", "swapio", NULL, "swap", NULL, "Swap I/O", "kilobytes/s", 250, update_every, RRDSET_TYPE_AREA);
422
423
- rrddim_add(st_swapio, "in", NULL, sysconf(_SC_PAGESIZE), 1024, RRDDIM_INCREMENTAL);
424
- rrddim_add(st_swapio, "out", NULL, -sysconf(_SC_PAGESIZE), 1024, RRDDIM_INCREMENTAL);
425
- }
426
- else rrdset_next(st_swapio);
423
+ rrddim_add(st_swapio, "in", NULL, sysconf(_SC_PAGESIZE), 1024, RRDDIM_INCREMENTAL);
424
+ rrddim_add(st_swapio, "out", NULL, -sysconf(_SC_PAGESIZE), 1024, RRDDIM_INCREMENTAL);
425
+ }
426
+ else rrdset_next(st_swapio);
427
428
- rrddim_set(st_swapio, "in", pswpin);
429
- rrddim_set(st_swapio, "out", pswpout);
430
- rrdset_done(st_swapio);
431
- }
428
+ rrddim_set(st_swapio, "in", pswpin);
429
+ rrddim_set(st_swapio, "out", pswpout);
430
+ rrdset_done(st_swapio);
431
+ }
432
433
- // --------------------------------------------------------------------
433
+ // --------------------------------------------------------------------
434
435
- if(do_io) {
436
- static RRDSET *st_io = NULL;
437
- if(!st_io) {
438
- st_io = rrdset_create("system", "io", NULL, "disk", NULL, "Disk I/O", "kilobytes/s", 150, update_every, RRDSET_TYPE_AREA);
435
+ if(do_io) {
436
+ static RRDSET *st_io = NULL;
437
+ if(!st_io) {
438
+ st_io = rrdset_create("system", "io", NULL, "disk", NULL, "Disk I/O", "kilobytes/s", 150, update_every, RRDSET_TYPE_AREA);
439
440
- rrddim_add(st_io, "in", NULL, 1, 1, RRDDIM_INCREMENTAL);
441
- rrddim_add(st_io, "out", NULL, -1, 1, RRDDIM_INCREMENTAL);
442
- }
443
- else rrdset_next(st_io);
440
+ rrddim_add(st_io, "in", NULL, 1, 1, RRDDIM_INCREMENTAL);
441
+ rrddim_add(st_io, "out", NULL, -1, 1, RRDDIM_INCREMENTAL);
442
+ }
443
+ else rrdset_next(st_io);
444
445
- rrddim_set(st_io, "in", pgpgin);
446
- rrddim_set(st_io, "out", pgpgout);
447
- rrdset_done(st_io);
448
- }
445
+ rrddim_set(st_io, "in", pgpgin);
446
+ rrddim_set(st_io, "out", pgpgout);
447
+ rrdset_done(st_io);
448
+ }
449
450
- // --------------------------------------------------------------------
450
+ // --------------------------------------------------------------------
451
452
- if(do_pgfaults) {
453
- static RRDSET *st_pgfaults = NULL;
454
- if(!st_pgfaults) {
455
- st_pgfaults = rrdset_create("mem", "pgfaults", NULL, "system", NULL, "Memory Page Faults", "page faults/s", 500, update_every, RRDSET_TYPE_LINE);
456
- st_pgfaults->isdetail = 1;
452
+ if(do_pgfaults) {
453
+ static RRDSET *st_pgfaults = NULL;
454
+ if(!st_pgfaults) {
455
+ st_pgfaults = rrdset_create("mem", "pgfaults", NULL, "system", NULL, "Memory Page Faults", "page faults/s", 500, update_every, RRDSET_TYPE_LINE);
456
+ st_pgfaults->isdetail = 1;
457
458
- rrddim_add(st_pgfaults, "minor", NULL, 1, 1, RRDDIM_INCREMENTAL);
459
- rrddim_add(st_pgfaults, "major", NULL, -1, 1, RRDDIM_INCREMENTAL);
460
- }
461
- else rrdset_next(st_pgfaults);
458
+ rrddim_add(st_pgfaults, "minor", NULL, 1, 1, RRDDIM_INCREMENTAL);
459
+ rrddim_add(st_pgfaults, "major", NULL, -1, 1, RRDDIM_INCREMENTAL);
460
+ }
461
+ else rrdset_next(st_pgfaults);
462
463
- rrddim_set(st_pgfaults, "minor", pgfault);
464
- rrddim_set(st_pgfaults, "major", pgmajfault);
465
- rrdset_done(st_pgfaults);
466
- }
463
+ rrddim_set(st_pgfaults, "minor", pgfault);
464
+ rrddim_set(st_pgfaults, "major", pgmajfault);
465
+ rrdset_done(st_pgfaults);
466
+ }
467
468
- return 0;
468
+ return 0;
469
}
470
src/procfile.c
+329
-329
@@ -19,40 +19,40 @@ size_t procfile_max_allocation = PROCFILE_INCREMENT_BUFFER;
19
20
21
pfwords *pfwords_add(pfwords *fw, char *str) {
22
- // debug(D_PROCFILE, PF_PREFIX ": adding word No %d: '%s'", fw->len, str);
22
+ // debug(D_PROCFILE, PF_PREFIX ": adding word No %d: '%s'", fw->len, str);
23
24
- if(unlikely(fw->len == fw->size)) {
25
- // debug(D_PROCFILE, PF_PREFIX ": expanding words");
24
+ if(unlikely(fw->len == fw->size)) {
25
+ // debug(D_PROCFILE, PF_PREFIX ": expanding words");
26
27
- fw = reallocz(fw, sizeof(pfwords) + (fw->size + PFWORDS_INCREASE_STEP) * sizeof(char *));
28
- fw->size += PFWORDS_INCREASE_STEP;
29
- }
27
+ fw = reallocz(fw, sizeof(pfwords) + (fw->size + PFWORDS_INCREASE_STEP) * sizeof(char *));
28
+ fw->size += PFWORDS_INCREASE_STEP;
29
+ }
30
31
- fw->words[fw->len++] = str;
31
+ fw->words[fw->len++] = str;
32
33
- return fw;
33
+ return fw;
34
}
35
36
pfwords *pfwords_new(void) {
37
- // debug(D_PROCFILE, PF_PREFIX ": initializing words");
37
+ // debug(D_PROCFILE, PF_PREFIX ": initializing words");
38
39
- uint32_t size = (procfile_adaptive_initial_allocation) ? procfile_max_words : PFWORDS_INCREASE_STEP;
39
+ uint32_t size = (procfile_adaptive_initial_allocation) ? procfile_max_words : PFWORDS_INCREASE_STEP;
40
41
- pfwords *new = mallocz(sizeof(pfwords) + size * sizeof(char *));
42
- new->len = 0;
43
- new->size = size;
44
- return new;
41
+ pfwords *new = mallocz(sizeof(pfwords) + size * sizeof(char *));
42
+ new->len = 0;
43
+ new->size = size;
44
+ return new;
45
}
46
47
void pfwords_reset(pfwords *fw) {
48
- // debug(D_PROCFILE, PF_PREFIX ": reseting words");
49
- fw->len = 0;
48
+ // debug(D_PROCFILE, PF_PREFIX ": reseting words");
49
+ fw->len = 0;
50
}
51
52
void pfwords_free(pfwords *fw) {
53
- // debug(D_PROCFILE, PF_PREFIX ": freeing words");
53
+ // debug(D_PROCFILE, PF_PREFIX ": freeing words");
54
55
- freez(fw);
55
+ freez(fw);
56
}
57
58
@@ -60,402 +60,402 @@ void pfwords_free(pfwords *fw) {
60
// An array of lines
61
62
pflines *pflines_add(pflines *fl, uint32_t first_word) {
63
- // debug(D_PROCFILE, PF_PREFIX ": adding line %d at word %d", fl->len, first_word);
63
+ // debug(D_PROCFILE, PF_PREFIX ": adding line %d at word %d", fl->len, first_word);
64
65
- if(unlikely(fl->len == fl->size)) {
66
- // debug(D_PROCFILE, PF_PREFIX ": expanding lines");
65
+ if(unlikely(fl->len == fl->size)) {
66
+ // debug(D_PROCFILE, PF_PREFIX ": expanding lines");
67
68
- fl = reallocz(fl, sizeof(pflines) + (fl->size + PFLINES_INCREASE_STEP) * sizeof(ffline));
69
- fl->size += PFLINES_INCREASE_STEP;
70
- }
68
+ fl = reallocz(fl, sizeof(pflines) + (fl->size + PFLINES_INCREASE_STEP) * sizeof(ffline));
69
+ fl->size += PFLINES_INCREASE_STEP;
70
+ }
71
72
- fl->lines[fl->len].words = 0;
73
- fl->lines[fl->len++].first = first_word;
72
+ fl->lines[fl->len].words = 0;
73
+ fl->lines[fl->len++].first = first_word;
74
75
- return fl;
75
+ return fl;
76
}
77
78
pflines *pflines_new(void) {
79
- // debug(D_PROCFILE, PF_PREFIX ": initializing lines");
79
+ // debug(D_PROCFILE, PF_PREFIX ": initializing lines");
80
81
- uint32_t size = (unlikely(procfile_adaptive_initial_allocation)) ? procfile_max_words : PFLINES_INCREASE_STEP;
81
+ uint32_t size = (unlikely(procfile_adaptive_initial_allocation)) ? procfile_max_words : PFLINES_INCREASE_STEP;
82
83
- pflines *new = mallocz(sizeof(pflines) + size * sizeof(ffline));
84
- new->len = 0;
85
- new->size = size;
86
- return new;
83
+ pflines *new = mallocz(sizeof(pflines) + size * sizeof(ffline));
84
+ new->len = 0;
85
+ new->size = size;
86
+ return new;
87
}
88
89
void pflines_reset(pflines *fl) {
90
- // debug(D_PROCFILE, PF_PREFIX ": reseting lines");
90
+ // debug(D_PROCFILE, PF_PREFIX ": reseting lines");
91
92
- fl->len = 0;
92
+ fl->len = 0;
93
}
94
95
void pflines_free(pflines *fl) {
96
- // debug(D_PROCFILE, PF_PREFIX ": freeing lines");
96
+ // debug(D_PROCFILE, PF_PREFIX ": freeing lines");
97
98
- freez(fl);
98
+ freez(fl);
99
}
100
101
102
// ----------------------------------------------------------------------------
103
// The procfile
104
105
-#define PF_CHAR_IS_SEPARATOR ' '
106
-#define PF_CHAR_IS_NEWLINE 'N'
107
-#define PF_CHAR_IS_WORD 'W'
105
+#define PF_CHAR_IS_SEPARATOR ' '
106
+#define PF_CHAR_IS_NEWLINE 'N'
107
+#define PF_CHAR_IS_WORD 'W'
108
#define PF_CHAR_IS_QUOTE 'Q'
109
#define PF_CHAR_IS_OPEN 'O'
110
#define PF_CHAR_IS_CLOSE 'C'
111
112
void procfile_close(procfile *ff) {
113
- debug(D_PROCFILE, PF_PREFIX ": Closing file '%s'", ff->filename);
113
+ debug(D_PROCFILE, PF_PREFIX ": Closing file '%s'", ff->filename);
114
115
- if(likely(ff->lines)) pflines_free(ff->lines);
116
- if(likely(ff->words)) pfwords_free(ff->words);
115
+ if(likely(ff->lines)) pflines_free(ff->lines);
116
+ if(likely(ff->words)) pfwords_free(ff->words);
117
118
- if(likely(ff->fd != -1)) close(ff->fd);
119
- freez(ff);
118
+ if(likely(ff->fd != -1)) close(ff->fd);
119
+ freez(ff);
120
}
121
122
procfile *procfile_parser(procfile *ff) {
123
- debug(D_PROCFILE, PF_PREFIX ": Parsing file '%s'", ff->filename);
124
-
125
- char *s = ff->data, *e = &ff->data[ff->len], *t = ff->data, quote = 0;
126
- uint32_t l = 0, w = 0;
127
- int opened = 0;
128
-
129
- ff->lines = pflines_add(ff->lines, w);
130
- if(unlikely(!ff->lines)) goto cleanup;
131
-
132
- while(likely(s < e)) {
133
- // we are not at the end
134
-
135
- switch(ff->separators[(uint8_t)(*s)]) {
136
- case PF_CHAR_IS_OPEN:
137
- if(s == t) {
138
- opened++;
139
- t = ++s;
140
- }
141
- else if(opened) {
142
- opened++;
143
- s++;
144
- }
145
- else
146
- s++;
147
- continue;
148
-
149
- case PF_CHAR_IS_CLOSE:
150
- if(opened) {
151
- opened--;
152
-
153
- if(!opened) {
154
- *s = '\0';
155
- ff->words = pfwords_add(ff->words, t);
156
- if(unlikely(!ff->words)) goto cleanup;
157
-
158
- ff->lines->lines[l].words++;
159
- w++;
160
-
161
- t = ++s;
162
- }
163
- else
164
- s++;
165
- }
166
- else
167
- s++;
168
- continue;
169
-
170
- case PF_CHAR_IS_QUOTE:
171
- if(unlikely(!quote && s == t)) {
172
- // quote opened at the beginning
173
- quote = *s;
174
- t = ++s;
175
- }
176
- else if(unlikely(quote && quote == *s)) {
177
- // quote closed
178
- quote = 0;
179
-
180
- *s = '\0';
181
- ff->words = pfwords_add(ff->words, t);
182
- if(unlikely(!ff->words)) goto cleanup;
183
-
184
- ff->lines->lines[l].words++;
185
- w++;
186
-
187
- t = ++s;
188
- }
189
- else
190
- s++;
191
- continue;
192
-
193
- case PF_CHAR_IS_SEPARATOR:
194
- if(unlikely(quote || opened)) {
195
- // we are inside a quote
196
- s++;
197
- continue;
198
- }
199
-
200
- if(unlikely(s == t)) {
201
- // skip all leading white spaces
202
- t = ++s;
203
- continue;
204
- }
205
-
206
- // end of word
207
- *s = '\0';
208
-
209
- ff->words = pfwords_add(ff->words, t);
210
- if(unlikely(!ff->words)) goto cleanup;
211
-
212
- ff->lines->lines[l].words++;
213
- w++;
214
-
215
- t = ++s;
216
- continue;
217
-
218
- case PF_CHAR_IS_NEWLINE:
219
- // end of line
220
- *s = '\0';
221
-
222
- ff->words = pfwords_add(ff->words, t);
223
- if(unlikely(!ff->words)) goto cleanup;
224
-
225
- ff->lines->lines[l].words++;
226
- w++;
227
-
228
- // debug(D_PROCFILE, PF_PREFIX ": ended line %d with %d words", l, ff->lines->lines[l].words);
229
-
230
- ff->lines = pflines_add(ff->lines, w);
231
- if(unlikely(!ff->lines)) goto cleanup;
232
- l++;
233
-
234
- t = ++s;
235
- continue;
236
-
237
- default:
238
- s++;
239
- continue;
240
- }
241
- }
242
-
243
- if(likely(s > t && t < e)) {
244
- // the last word
245
- if(likely(ff->len < ff->size))
246
- *s = '\0';
247
- else {
248
- // we are going to loose the last byte
249
- ff->data[ff->size - 1] = '\0';
250
- }
251
-
252
- ff->words = pfwords_add(ff->words, t);
253
- if(unlikely(!ff->words)) goto cleanup;
254
-
255
- ff->lines->lines[l].words++;
256
- w++;
257
- }
258
-
259
- return ff;
123
+ debug(D_PROCFILE, PF_PREFIX ": Parsing file '%s'", ff->filename);
124
+
125
+ char *s = ff->data, *e = &ff->data[ff->len], *t = ff->data, quote = 0;
126
+ uint32_t l = 0, w = 0;
127
+ int opened = 0;
128
+
129
+ ff->lines = pflines_add(ff->lines, w);
130
+ if(unlikely(!ff->lines)) goto cleanup;
131
+
132
+ while(likely(s < e)) {
133
+ // we are not at the end
134
+
135
+ switch(ff->separators[(uint8_t)(*s)]) {
136
+ case PF_CHAR_IS_OPEN:
137
+ if(s == t) {
138
+ opened++;
139
+ t = ++s;
140
+ }
141
+ else if(opened) {
142
+ opened++;
143
+ s++;
144
+ }
145
+ else
146
+ s++;
147
+ continue;
148
+
149
+ case PF_CHAR_IS_CLOSE:
150
+ if(opened) {
151
+ opened--;
152
+
153
+ if(!opened) {
154
+ *s = '\0';
155
+ ff->words = pfwords_add(ff->words, t);
156
+ if(unlikely(!ff->words)) goto cleanup;
157
+
158
+ ff->lines->lines[l].words++;
159
+ w++;
160
+
161
+ t = ++s;
162
+ }
163
+ else
164
+ s++;
165
+ }
166
+ else
167
+ s++;
168
+ continue;
169
+
170
+ case PF_CHAR_IS_QUOTE:
171
+ if(unlikely(!quote && s == t)) {
172
+ // quote opened at the beginning
173
+ quote = *s;
174
+ t = ++s;
175
+ }
176
+ else if(unlikely(quote && quote == *s)) {
177
+ // quote closed
178
+ quote = 0;
179
+
180
+ *s = '\0';
181
+ ff->words = pfwords_add(ff->words, t);
182
+ if(unlikely(!ff->words)) goto cleanup;
183
+
184
+ ff->lines->lines[l].words++;
185
+ w++;
186
+
187
+ t = ++s;
188
+ }
189
+ else
190
+ s++;
191
+ continue;
192
+
193
+ case PF_CHAR_IS_SEPARATOR:
194
+ if(unlikely(quote || opened)) {
195
+ // we are inside a quote
196
+ s++;
197
+ continue;
198
+ }
199
+
200
+ if(unlikely(s == t)) {
201
+ // skip all leading white spaces
202
+ t = ++s;
203
+ continue;
204
+ }
205
+
206
+ // end of word
207
+ *s = '\0';
208
+
209
+ ff->words = pfwords_add(ff->words, t);
210
+ if(unlikely(!ff->words)) goto cleanup;
211
+
212
+ ff->lines->lines[l].words++;
213
+ w++;
214
+
215
+ t = ++s;
216
+ continue;
217
+
218
+ case PF_CHAR_IS_NEWLINE:
219
+ // end of line
220
+ *s = '\0';
221
+
222
+ ff->words = pfwords_add(ff->words, t);
223
+ if(unlikely(!ff->words)) goto cleanup;
224
+
225
+ ff->lines->lines[l].words++;
226
+ w++;
227
+
228
+ // debug(D_PROCFILE, PF_PREFIX ": ended line %d with %d words", l, ff->lines->lines[l].words);
229
+
230
+ ff->lines = pflines_add(ff->lines, w);
231
+ if(unlikely(!ff->lines)) goto cleanup;
232
+ l++;
233
+
234
+ t = ++s;
235
+ continue;
236
+
237
+ default:
238
+ s++;
239
+ continue;
240
+ }
241
+ }
242
+
243
+ if(likely(s > t && t < e)) {
244
+ // the last word
245
+ if(likely(ff->len < ff->size))
246
+ *s = '\0';
247
+ else {
248
+ // we are going to loose the last byte
249
+ ff->data[ff->size - 1] = '\0';
250
+ }
251
+
252
+ ff->words = pfwords_add(ff->words, t);
253
+ if(unlikely(!ff->words)) goto cleanup;
254
+
255
+ ff->lines->lines[l].words++;
256
+ w++;
257
+ }
258
+
259
+ return ff;
260
261
cleanup:
262
- error(PF_PREFIX ": Failed to parse file '%s'", ff->filename);
263
- procfile_close(ff);
264
- return NULL;
262
+ error(PF_PREFIX ": Failed to parse file '%s'", ff->filename);
263
+ procfile_close(ff);
264
+ return NULL;
265
}
266
267
procfile *procfile_readall(procfile *ff) {
268
- debug(D_PROCFILE, PF_PREFIX ": Reading file '%s'.", ff->filename);
268
+ debug(D_PROCFILE, PF_PREFIX ": Reading file '%s'.", ff->filename);
269
270
- ssize_t s, r = 1, x;
271
- ff->len = 0;
270
+ ssize_t s, r = 1, x;
271
+ ff->len = 0;
272
273
- while(likely(r > 0)) {
274
- s = ff->len;
275
- x = ff->size - s;
273
+ while(likely(r > 0)) {
274
+ s = ff->len;
275
+ x = ff->size - s;
276
277
- if(!x) {
278
- debug(D_PROCFILE, PF_PREFIX ": Expanding data buffer for file '%s'.", ff->filename);
277
+ if(!x) {
278
+ debug(D_PROCFILE, PF_PREFIX ": Expanding data buffer for file '%s'.", ff->filename);
279
280
- ff = reallocz(ff, sizeof(procfile) + ff->size + PROCFILE_INCREMENT_BUFFER);
281
- ff->size += PROCFILE_INCREMENT_BUFFER;
282
- }
280
+ ff = reallocz(ff, sizeof(procfile) + ff->size + PROCFILE_INCREMENT_BUFFER);
281
+ ff->size += PROCFILE_INCREMENT_BUFFER;
282
+ }
283
284
- debug(D_PROCFILE, "Reading file '%s', from position %ld with length %lu", ff->filename, s, ff->size - s);
285
- r = read(ff->fd, &ff->data[s], ff->size - s);
286
- if(unlikely(r == -1)) {
287
- if(unlikely(!(ff->flags & PROCFILE_FLAG_NO_ERROR_ON_FILE_IO))) error(PF_PREFIX ": Cannot read from file '%s'", ff->filename);
288
- procfile_close(ff);
289
- return NULL;
290
- }
284
+ debug(D_PROCFILE, "Reading file '%s', from position %ld with length %lu", ff->filename, s, ff->size - s);
285
+ r = read(ff->fd, &ff->data[s], ff->size - s);
286
+ if(unlikely(r == -1)) {
287
+ if(unlikely(!(ff->flags & PROCFILE_FLAG_NO_ERROR_ON_FILE_IO))) error(PF_PREFIX ": Cannot read from file '%s'", ff->filename);
288
+ procfile_close(ff);
289
+ return NULL;
290
+ }
291
292
- ff->len += r;
293
- }
292
+ ff->len += r;
293
+ }
294
295
- debug(D_PROCFILE, "Rewinding file '%s'", ff->filename);
296
- if(unlikely(lseek(ff->fd, 0, SEEK_SET) == -1)) {
297
- if(unlikely(!(ff->flags & PROCFILE_FLAG_NO_ERROR_ON_FILE_IO))) error(PF_PREFIX ": Cannot rewind on file '%s'.", ff->filename);
298
- procfile_close(ff);
299
- return NULL;
300
- }
295
+ debug(D_PROCFILE, "Rewinding file '%s'", ff->filename);
296
+ if(unlikely(lseek(ff->fd, 0, SEEK_SET) == -1)) {
297
+ if(unlikely(!(ff->flags & PROCFILE_FLAG_NO_ERROR_ON_FILE_IO))) error(PF_PREFIX ": Cannot rewind on file '%s'.", ff->filename);
298
+ procfile_close(ff);
299
+ return NULL;
300
+ }
301
302
- pflines_reset(ff->lines);
303
- pfwords_reset(ff->words);
302
+ pflines_reset(ff->lines);
303
+ pfwords_reset(ff->words);
304
305
- ff = procfile_parser(ff);
305
+ ff = procfile_parser(ff);
306
307
- if(unlikely(procfile_adaptive_initial_allocation)) {
308
- if(unlikely(ff->len > procfile_max_allocation)) procfile_max_allocation = ff->len;
309
- if(unlikely(ff->lines->len > procfile_max_lines)) procfile_max_lines = ff->lines->len;
310
- if(unlikely(ff->words->len > procfile_max_words)) procfile_max_words = ff->words->len;
311
- }
307
+ if(unlikely(procfile_adaptive_initial_allocation)) {
308
+ if(unlikely(ff->len > procfile_max_allocation)) procfile_max_allocation = ff->len;
309
+ if(unlikely(ff->lines->len > procfile_max_lines)) procfile_max_lines = ff->lines->len;
310
+ if(unlikely(ff->words->len > procfile_max_words)) procfile_max_words = ff->words->len;
311
+ }
312
313
- debug(D_PROCFILE, "File '%s' updated.", ff->filename);
314
- return ff;
313
+ debug(D_PROCFILE, "File '%s' updated.", ff->filename);
314
+ return ff;
315
}
316
317
static void procfile_set_separators(procfile *ff, const char *separators) {
318
- static char def[256] = { [0 ... 255] = 0 };
319
- int i;
320
-
321
- if(unlikely(!def[255])) {
322
- // this is thread safe
323
- // we check that the last byte is non-zero
324
- // if it is zero, multiple threads may be executing this at the same time
325
- // setting in def[] the exact same values
326
- for(i = 0; likely(i < 256) ;i++) {
327
- if(unlikely(i == '\n' || i == '\r')) def[i] = PF_CHAR_IS_NEWLINE;
328
- else if(unlikely(isspace(i) || !isprint(i))) def[i] = PF_CHAR_IS_SEPARATOR;
329
- else def[i] = PF_CHAR_IS_WORD;
330
- }
331
- }
332
-
333
- // copy the default
334
- char *ffs = ff->separators, *ffd = def, *ffe = &def[256];
335
- while(likely(ffd != ffe)) *ffs++ = *ffd++;
336
-
337
- // set the separators
338
- if(unlikely(!separators))
339
- separators = " \t=|";
340
-
341
- ffs = ff->separators;
342
- const char *s = separators;
343
- while(likely(*s))
344
- ffs[(int)*s++] = PF_CHAR_IS_SEPARATOR;
318
+ static char def[256] = { [0 ... 255] = 0 };
319
+ int i;
320
+
321
+ if(unlikely(!def[255])) {
322
+ // this is thread safe
323
+ // we check that the last byte is non-zero
324
+ // if it is zero, multiple threads may be executing this at the same time
325
+ // setting in def[] the exact same values
326
+ for(i = 0; likely(i < 256) ;i++) {
327
+ if(unlikely(i == '\n' || i == '\r')) def[i] = PF_CHAR_IS_NEWLINE;
328
+ else if(unlikely(isspace(i) || !isprint(i))) def[i] = PF_CHAR_IS_SEPARATOR;
329
+ else def[i] = PF_CHAR_IS_WORD;
330
+ }
331
+ }
332
+
333
+ // copy the default
334
+ char *ffs = ff->separators, *ffd = def, *ffe = &def[256];
335
+ while(likely(ffd != ffe)) *ffs++ = *ffd++;
336
+
337
+ // set the separators
338
+ if(unlikely(!separators))
339
+ separators = " \t=|";
340
+
341
+ ffs = ff->separators;
342
+ const char *s = separators;
343
+ while(likely(*s))
344
+ ffs[(int)*s++] = PF_CHAR_IS_SEPARATOR;
345
}
346
347
void procfile_set_quotes(procfile *ff, const char *quotes) {
348
- // remove all quotes
349
- int i;
350
- for(i = 0; i < 256 ; i++)
351
- if(ff->separators[i] == PF_CHAR_IS_QUOTE)
352
- ff->separators[i] = PF_CHAR_IS_WORD;
353
-
354
- // if nothing given, return
355
- if(unlikely(!quotes || !*quotes))
356
- return;
357
-
358
- // set the quotes
359
- char *ffs = ff->separators;
360
- const char *s = quotes;
361
- while(likely(*s))
362
- ffs[(int)*s++] = PF_CHAR_IS_QUOTE;
348
+ // remove all quotes
349
+ int i;
350
+ for(i = 0; i < 256 ; i++)
351
+ if(ff->separators[i] == PF_CHAR_IS_QUOTE)
352
+ ff->separators[i] = PF_CHAR_IS_WORD;
353
+
354
+ // if nothing given, return
355
+ if(unlikely(!quotes || !*quotes))
356
+ return;
357
+
358
+ // set the quotes
359
+ char *ffs = ff->separators;
360
+ const char *s = quotes;
361
+ while(likely(*s))
362
+ ffs[(int)*s++] = PF_CHAR_IS_QUOTE;
363
}
364
365
void procfile_set_open_close(procfile *ff, const char *open, const char *close) {
366
- // remove all open/close
367
- int i;
368
- for(i = 0; i < 256 ; i++)
369
- if(ff->separators[i] == PF_CHAR_IS_OPEN || ff->separators[i] == PF_CHAR_IS_CLOSE)
370
- ff->separators[i] = PF_CHAR_IS_WORD;
371
-
372
- // if nothing given, return
373
- if(unlikely(!open || !*open || !close || !*close))
374
- return;
375
-
376
- // set the openings
377
- char *ffs = ff->separators;
378
- const char *s = open;
379
- while(likely(*s))
380
- ffs[(int)*s++] = PF_CHAR_IS_OPEN;
381
-
382
- s = close;
383
- while(likely(*s))
384
- ffs[(int)*s++] = PF_CHAR_IS_CLOSE;
366
+ // remove all open/close
367
+ int i;
368
+ for(i = 0; i < 256 ; i++)
369
+ if(ff->separators[i] == PF_CHAR_IS_OPEN || ff->separators[i] == PF_CHAR_IS_CLOSE)
370
+ ff->separators[i] = PF_CHAR_IS_WORD;
371
+
372
+ // if nothing given, return
373
+ if(unlikely(!open || !*open || !close || !*close))
374
+ return;
375
+
376
+ // set the openings
377
+ char *ffs = ff->separators;
378
+ const char *s = open;
379
+ while(likely(*s))
380
+ ffs[(int)*s++] = PF_CHAR_IS_OPEN;
381
+
382
+ s = close;
383
+ while(likely(*s))
384
+ ffs[(int)*s++] = PF_CHAR_IS_CLOSE;
385
}
386
387
procfile *procfile_open(const char *filename, const char *separators, uint32_t flags) {
388
- debug(D_PROCFILE, PF_PREFIX ": Opening file '%s'", filename);
388
+ debug(D_PROCFILE, PF_PREFIX ": Opening file '%s'", filename);
389
390
- int fd = open(filename, O_RDONLY, 0666);
391
- if(unlikely(fd == -1)) {
392
- if(unlikely(!(flags & PROCFILE_FLAG_NO_ERROR_ON_FILE_IO))) error(PF_PREFIX ": Cannot open file '%s'", filename);
393
- return NULL;
394
- }
390
+ int fd = open(filename, O_RDONLY, 0666);
391
+ if(unlikely(fd == -1)) {
392
+ if(unlikely(!(flags & PROCFILE_FLAG_NO_ERROR_ON_FILE_IO))) error(PF_PREFIX ": Cannot open file '%s'", filename);
393
+ return NULL;
394
+ }
395
396
- size_t size = (unlikely(procfile_adaptive_initial_allocation)) ? procfile_max_allocation : PROCFILE_INCREMENT_BUFFER;
397
- procfile *ff = mallocz(sizeof(procfile) + size);
398
- strncpyz(ff->filename, filename, FILENAME_MAX);
396
+ size_t size = (unlikely(procfile_adaptive_initial_allocation)) ? procfile_max_allocation : PROCFILE_INCREMENT_BUFFER;
397
+ procfile *ff = mallocz(sizeof(procfile) + size);
398
+ strncpyz(ff->filename, filename, FILENAME_MAX);
399
400
- ff->fd = fd;
401
- ff->size = size;
402
- ff->len = 0;
403
- ff->flags = flags;
400
+ ff->fd = fd;
401
+ ff->size = size;
402
+ ff->len = 0;
403
+ ff->flags = flags;
404
405
- ff->lines = pflines_new();
406
- ff->words = pfwords_new();
405
+ ff->lines = pflines_new();
406
+ ff->words = pfwords_new();
407
408
- if(unlikely(!ff->lines || !ff->words)) {
409
- error(PF_PREFIX ": Cannot initialize parser for file '%s'", filename);
410
- procfile_close(ff);
411
- return NULL;
412
- }
408
+ if(unlikely(!ff->lines || !ff->words)) {
409
+ error(PF_PREFIX ": Cannot initialize parser for file '%s'", filename);
410
+ procfile_close(ff);
411
+ return NULL;
412
+ }
413
414
- procfile_set_separators(ff, separators);
414
+ procfile_set_separators(ff, separators);
415
416
- debug(D_PROCFILE, "File '%s' opened.", filename);
417
- return ff;
416
+ debug(D_PROCFILE, "File '%s' opened.", filename);
417
+ return ff;
418
}
419
420
procfile *procfile_reopen(procfile *ff, const char *filename, const char *separators, uint32_t flags) {
421
- if(unlikely(!ff)) return procfile_open(filename, separators, flags);
421
+ if(unlikely(!ff)) return procfile_open(filename, separators, flags);
422
423
- if(likely(ff->fd != -1)) close(ff->fd);
423
+ if(likely(ff->fd != -1)) close(ff->fd);
424
425
- ff->fd = open(filename, O_RDONLY, 0666);
426
- if(unlikely(ff->fd == -1)) {
427
- procfile_close(ff);
428
- return NULL;
429
- }
425
+ ff->fd = open(filename, O_RDONLY, 0666);
426
+ if(unlikely(ff->fd == -1)) {
427
+ procfile_close(ff);
428
+ return NULL;
429
+ }
430
431
- strncpyz(ff->filename, filename, FILENAME_MAX);
431
+ strncpyz(ff->filename, filename, FILENAME_MAX);
432
433
- ff->flags = flags;
433
+ ff->flags = flags;
434
435
- // do not do the separators again if NULL is given
436
- if(likely(separators)) procfile_set_separators(ff, separators);
435
+ // do not do the separators again if NULL is given
436
+ if(likely(separators)) procfile_set_separators(ff, separators);
437
438
- return ff;
438
+ return ff;
439
}
440
441
// ----------------------------------------------------------------------------
442
// example parsing of procfile data
443
444
void procfile_print(procfile *ff) {
445
- uint32_t lines = procfile_lines(ff), l;
446
- uint32_t words, w;
447
- char *s;
445
+ uint32_t lines = procfile_lines(ff), l;
446
+ uint32_t words, w;
447
+ char *s;
448
449
- debug(D_PROCFILE, "File '%s' with %u lines and %u words", ff->filename, ff->lines->len, ff->words->len);
449
+ debug(D_PROCFILE, "File '%s' with %u lines and %u words", ff->filename, ff->lines->len, ff->words->len);
450
451
- for(l = 0; likely(l < lines) ;l++) {
452
- words = procfile_linewords(ff, l);
451
+ for(l = 0; likely(l < lines) ;l++) {
452
+ words = procfile_linewords(ff, l);
453
454
- debug(D_PROCFILE, " line %u starts at word %u and has %u words", l, ff->lines->lines[l].first, ff->lines->lines[l].words);
454
+ debug(D_PROCFILE, " line %u starts at word %u and has %u words", l, ff->lines->lines[l].first, ff->lines->lines[l].words);
455
456
- for(w = 0; likely(w < words) ;w++) {
457
- s = procfile_lineword(ff, l, w);
458
- debug(D_PROCFILE, " [%u.%u] '%s'", l, w, s);
459
- }
460
- }
456
+ for(w = 0; likely(w < words) ;w++) {
457
+ s = procfile_lineword(ff, l, w);
458
+ debug(D_PROCFILE, " [%u.%u] '%s'", l, w, s);
459
+ }
460
+ }
461
}
src/procfile.h
+18
-18
@@ -30,9 +30,9 @@
30
// An array of words
31
32
typedef struct {
33
- uint32_t len; // used entries
34
- uint32_t size; // capacity
35
- char *words[]; // array of pointers
33
+ uint32_t len; // used entries
34
+ uint32_t size; // capacity
35
+ char *words[]; // array of pointers
36
} pfwords;
37
38
@@ -40,15 +40,15 @@ typedef struct {
40
// An array of lines
41
42
typedef struct {
43
- uint32_t words; // how many words this line has
44
- uint32_t first; // the id of the first word of this line
45
- // in the words array
43
+ uint32_t words; // how many words this line has
44
+ uint32_t first; // the id of the first word of this line
45
+ // in the words array
46
} ffline;
47
48
typedef struct {
49
- uint32_t len; // used entries
50
- uint32_t size; // capacity
51
- ffline lines[]; // array of lines
49
+ uint32_t len; // used entries
50
+ uint32_t size; // capacity
51
+ ffline lines[]; // array of lines
52
} pflines;
53
54
@@ -59,15 +59,15 @@ typedef struct {
59
#define PROCFILE_FLAG_NO_ERROR_ON_FILE_IO 0x00000001
60
61
typedef struct {
62
- char filename[FILENAME_MAX + 1];
63
- uint32_t flags;
64
- int fd; // the file desriptor
65
- size_t len; // the bytes we have placed into data
66
- size_t size; // the bytes we have allocated for data
67
- pflines *lines;
68
- pfwords *words;
69
- char separators[256];
70
- char data[]; // allocated buffer to keep file contents
62
+ char filename[FILENAME_MAX + 1];
63
+ uint32_t flags;
64
+ int fd; // the file desriptor
65
+ size_t len; // the bytes we have placed into data
66
+ size_t size; // the bytes we have allocated for data
67
+ pflines *lines;
68
+ pfwords *words;
69
+ char separators[256];
70
+ char data[]; // allocated buffer to keep file contents
71
} procfile;
72
73
// close the proc file and free all related memory
src/registry.c
+1267
-1267
@@ -39,60 +39,60 @@
39
// COMMON structures
40
41
struct registry {
42
- int enabled;
43
-
44
- char machine_guid[36 + 1];
45
-
46
- // entries counters / statistics
47
- unsigned long long persons_count;
48
- unsigned long long machines_count;
49
- unsigned long long usages_count;
50
- unsigned long long urls_count;
51
- unsigned long long persons_urls_count;
52
- unsigned long long machines_urls_count;
53
- unsigned long long log_count;
54
-
55
- // memory counters / statistics
56
- unsigned long long persons_memory;
57
- unsigned long long machines_memory;
58
- unsigned long long urls_memory;
59
- unsigned long long persons_urls_memory;
60
- unsigned long long machines_urls_memory;
61
-
62
- // configuration
63
- unsigned long long save_registry_every_entries;
64
- char *registry_domain;
65
- char *hostname;
66
- char *registry_to_announce;
67
- time_t persons_expiration; // seconds to expire idle persons
68
- int verify_cookies_redirects;
69
-
70
- size_t max_url_length;
71
- size_t max_name_length;
72
-
73
- // file/path names
74
- char *pathname;
75
- char *db_filename;
76
- char *log_filename;
77
- char *machine_guid_filename;
78
-
79
- // open files
80
- FILE *log_fp;
81
-
82
- // the database
83
- DICTIONARY *persons; // dictionary of PERSON *, with key the PERSON.guid
84
- DICTIONARY *machines; // dictionary of MACHINE *, with key the MACHINE.guid
85
- DICTIONARY *urls; // dictionary of URL *, with key the URL.url
86
-
87
- // concurrency locking
88
- // we keep different locks for different things
89
- // so that many tasks can be completed in parallel
90
- pthread_mutex_t persons_lock;
91
- pthread_mutex_t machines_lock;
92
- pthread_mutex_t urls_lock;
93
- pthread_mutex_t person_urls_lock;
94
- pthread_mutex_t machine_urls_lock;
95
- pthread_mutex_t log_lock;
42
+ int enabled;
43
+
44
+ char machine_guid[36 + 1];
45
+
46
+ // entries counters / statistics
47
+ unsigned long long persons_count;
48
+ unsigned long long machines_count;
49
+ unsigned long long usages_count;
50
+ unsigned long long urls_count;
51
+ unsigned long long persons_urls_count;
52
+ unsigned long long machines_urls_count;
53
+ unsigned long long log_count;
54
+
55
+ // memory counters / statistics
56
+ unsigned long long persons_memory;
57
+ unsigned long long machines_memory;
58
+ unsigned long long urls_memory;
59
+ unsigned long long persons_urls_memory;
60
+ unsigned long long machines_urls_memory;
61
+
62
+ // configuration
63
+ unsigned long long save_registry_every_entries;
64
+ char *registry_domain;
65
+ char *hostname;
66
+ char *registry_to_announce;
67
+ time_t persons_expiration; // seconds to expire idle persons
68
+ int verify_cookies_redirects;
69
+
70
+ size_t max_url_length;
71
+ size_t max_name_length;
72
+
73
+ // file/path names
74
+ char *pathname;
75
+ char *db_filename;
76
+ char *log_filename;
77
+ char *machine_guid_filename;
78
+
79
+ // open files
80
+ FILE *log_fp;
81
+
82
+ // the database
83
+ DICTIONARY *persons; // dictionary of PERSON *, with key the PERSON.guid
84
+ DICTIONARY *machines; // dictionary of MACHINE *, with key the MACHINE.guid
85
+ DICTIONARY *urls; // dictionary of URL *, with key the URL.url
86
+
87
+ // concurrency locking
88
+ // we keep different locks for different things
89
+ // so that many tasks can be completed in parallel
90
+ pthread_mutex_t persons_lock;
91
+ pthread_mutex_t machines_lock;
92
+ pthread_mutex_t urls_lock;
93
+ pthread_mutex_t person_urls_lock;
94
+ pthread_mutex_t machine_urls_lock;
95
+ pthread_mutex_t log_lock;
96
} registry;
97
98
@@ -103,9 +103,9 @@ struct registry {
103
// we store them here and we keep pointers elsewhere
104
105
struct url {
106
- uint32_t links; // the number of links to this URL - when none is left, we free it
107
- uint16_t len; // the length of the URL in bytes
108
- char url[1]; // the URL - dynamically allocated to more size
106
+ uint32_t links; // the number of links to this URL - when none is left, we free it
107
+ uint16_t len; // the length of the URL in bytes
108
+ char url[1]; // the URL - dynamically allocated to more size
109
};
110
typedef struct url URL;
111
@@ -115,27 +115,27 @@ typedef struct url URL;
115
116
// For each MACHINE-URL pair we keep this
117
struct machine_url {
118
- URL *url; // de-duplicated URL
119
-// DICTIONARY *persons; // dictionary of PERSON *
118
+ URL *url; // de-duplicated URL
119
+// DICTIONARY *persons; // dictionary of PERSON *
120
121
- uint8_t flags;
122
- uint32_t first_t; // the first time we saw this
123
- uint32_t last_t; // the last time we saw this
124
- uint32_t usages; // how many times this has been accessed
121
+ uint8_t flags;
122
+ uint32_t first_t; // the first time we saw this
123
+ uint32_t last_t; // the last time we saw this
124
+ uint32_t usages; // how many times this has been accessed
125
};
126
typedef struct machine_url MACHINE_URL;
127
128
// A machine
129
struct machine {
130
- char guid[36 + 1]; // the GUID
130
+ char guid[36 + 1]; // the GUID
131
132
- uint32_t links; // the number of PERSON_URLs linked to this machine
132
+ uint32_t links; // the number of PERSON_URLs linked to this machine
133
134
- DICTIONARY *urls; // MACHINE_URL *
134
+ DICTIONARY *urls; // MACHINE_URL *
135
136
- uint32_t first_t; // the first time we saw this
137
- uint32_t last_t; // the last time we saw this
138
- uint32_t usages; // how many times this has been accessed
136
+ uint32_t first_t; // the first time we saw this
137
+ uint32_t last_t; // the last time we saw this
138
+ uint32_t usages; // how many times this has been accessed
139
};
140
typedef struct machine MACHINE;
141
@@ -145,28 +145,28 @@ typedef struct machine MACHINE;
145
146
// for each PERSON-URL pair we keep this
147
struct person_url {
148
- URL *url; // de-duplicated URL
149
- MACHINE *machine; // link the MACHINE of this URL
148
+ URL *url; // de-duplicated URL
149
+ MACHINE *machine; // link the MACHINE of this URL
150
151
- uint8_t flags;
152
- uint32_t first_t; // the first time we saw this
153
- uint32_t last_t; // the last time we saw this
154
- uint32_t usages; // how many times this has been accessed
151
+ uint8_t flags;
152
+ uint32_t first_t; // the first time we saw this
153
+ uint32_t last_t; // the last time we saw this
154
+ uint32_t usages; // how many times this has been accessed
155
156
- char name[1]; // the name of the URL, as known by the user
157
- // dynamically allocated to fit properly
156
+ char name[1]; // the name of the URL, as known by the user
157
+ // dynamically allocated to fit properly
158
};
159
typedef struct person_url PERSON_URL;
160
161
// A person
162
struct person {
163
- char guid[36 + 1]; // the person GUID
163
+ char guid[36 + 1]; // the person GUID
164
165
- DICTIONARY *urls; // dictionary of PERSON_URL *
165
+ DICTIONARY *urls; // dictionary of PERSON_URL *
166
167
- uint32_t first_t; // the first time we saw this
168
- uint32_t last_t; // the last time we saw this
169
- uint32_t usages; // how many times this has been accessed
167
+ uint32_t first_t; // the first time we saw this
168
+ uint32_t last_t; // the last time we saw this
169
+ uint32_t usages; // how many times this has been accessed
170
};
171
typedef struct person PERSON;
172
@@ -175,27 +175,27 @@ typedef struct person PERSON;
175
// REGISTRY concurrency locking
176
177
static inline void registry_persons_lock(void) {
178
- pthread_mutex_lock(®istry.persons_lock);
178
+ pthread_mutex_lock(®istry.persons_lock);
179
}
180
181
static inline void registry_persons_unlock(void) {
182
- pthread_mutex_unlock(®istry.persons_lock);
182
+ pthread_mutex_unlock(®istry.persons_lock);
183
}
184
185
static inline void registry_machines_lock(void) {
186
- pthread_mutex_lock(®istry.machines_lock);
186
+ pthread_mutex_lock(®istry.machines_lock);
187
}
188
189
static inline void registry_machines_unlock(void) {
190
- pthread_mutex_unlock(®istry.machines_lock);
190
+ pthread_mutex_unlock(®istry.machines_lock);
191
}
192
193
static inline void registry_urls_lock(void) {
194
- pthread_mutex_lock(®istry.urls_lock);
194
+ pthread_mutex_lock(®istry.urls_lock);
195
}
196
197
static inline void registry_urls_unlock(void) {
198
- pthread_mutex_unlock(®istry.urls_lock);
198
+ pthread_mutex_unlock(®istry.urls_lock);
199
}
200
201
// ideally, we should not lock the whole registry for
@@ -203,13 +203,13 @@ static inline void registry_urls_unlock(void) {
203
// however, to save the memory required for keeping a
204
// mutex (40 bytes) per person, we do...
205
static inline void registry_person_urls_lock(PERSON *p) {
206
- (void)p;
207
- pthread_mutex_lock(®istry.person_urls_lock);
206
+ (void)p;
207
+ pthread_mutex_lock(®istry.person_urls_lock);
208
}
209
210
static inline void registry_person_urls_unlock(PERSON *p) {
211
- (void)p;
212
- pthread_mutex_unlock(®istry.person_urls_lock);
211
+ (void)p;
212
+ pthread_mutex_unlock(®istry.person_urls_lock);
213
}
214
215
// ideally, we should not lock the whole registry for
@@ -217,21 +217,21 @@ static inline void registry_person_urls_unlock(PERSON *p) {
217
// however, to save the memory required for keeping a
218
// mutex (40 bytes) per machine, we do...
219
static inline void registry_machine_urls_lock(MACHINE *m) {
220
- (void)m;
221
- pthread_mutex_lock(®istry.machine_urls_lock);
220
+ (void)m;
221
+ pthread_mutex_lock(®istry.machine_urls_lock);
222
}
223
224
static inline void registry_machine_urls_unlock(MACHINE *m) {
225
- (void)m;
226
- pthread_mutex_unlock(®istry.machine_urls_lock);
225
+ (void)m;
226
+ pthread_mutex_unlock(®istry.machine_urls_lock);
227
}
228
229
static inline void registry_log_lock(void) {
230
- pthread_mutex_lock(®istry.log_lock);
230
+ pthread_mutex_lock(®istry.log_lock);
231
}
232
233
static inline void registry_log_unlock(void) {
234
- pthread_mutex_unlock(®istry.log_lock);
234
+ pthread_mutex_unlock(®istry.log_lock);
235
}
236
237
@@ -241,58 +241,58 @@ static inline void registry_log_unlock(void) {
241
// parse a GUID and re-generated to be always lower case
242
// this is used as a protection against the variations of GUIDs
243
static inline int registry_regenerate_guid(const char *guid, char *result) {
244
- uuid_t uuid;
245
- if(unlikely(uuid_parse(guid, uuid) == -1)) {
246
- info("Registry: GUID '%s' is not a valid GUID.", guid);
247
- return -1;
248
- }
249
- else {
250
- uuid_unparse_lower(uuid, result);
244
+ uuid_t uuid;
245
+ if(unlikely(uuid_parse(guid, uuid) == -1)) {
246
+ info("Registry: GUID '%s' is not a valid GUID.", guid);
247
+ return -1;
248
+ }
249
+ else {
250
+ uuid_unparse_lower(uuid, result);
251
252
#ifdef NETDATA_INTERNAL_CHECKS
253
- if(strcmp(guid, result))
254
- info("Registry: source GUID '%s' and re-generated GUID '%s' differ!", guid, result);
253
+ if(strcmp(guid, result))
254
+ info("Registry: source GUID '%s' and re-generated GUID '%s' differ!", guid, result);
255
#endif /* NETDATA_INTERNAL_CHECKS */
256
- }
256
+ }
257
258
- return 0;
258
+ return 0;
259
}
260
261
// make sure the names of the machines / URLs do not contain any tabs
262
// (which are used as our separator in the database files)
263
// and are properly trimmed (before and after)
264
static inline char *registry_fix_machine_name(char *name, size_t *len) {
265
- char *s = name?name:"";
265
+ char *s = name?name:"";
266
267
- // skip leading spaces
268
- while(*s && isspace(*s)) s++;
267
+ // skip leading spaces
268
+ while(*s && isspace(*s)) s++;
269
270
- // make sure all spaces are a SPACE
271
- char *t = s;
272
- while(*t) {
273
- if(unlikely(isspace(*t)))
274
- *t = ' ';
270
+ // make sure all spaces are a SPACE
271
+ char *t = s;
272
+ while(*t) {
273
+ if(unlikely(isspace(*t)))
274
+ *t = ' ';
275
276
- t++;
277
- }
276
+ t++;
277
+ }
278
279
- // remove trailing spaces
280
- while(--t >= s) {
281
- if(*t == ' ')
282
- *t = '\0';
283
- else
284
- break;
285
- }
286
- t++;
279
+ // remove trailing spaces
280
+ while(--t >= s) {
281
+ if(*t == ' ')
282
+ *t = '\0';
283
+ else
284
+ break;
285
+ }
286
+ t++;
287
288
- if(likely(len))
289
- *len = (t - s);
288
+ if(likely(len))
289
+ *len = (t - s);
290
291
- return s;
291
+ return s;
292
}
293
294
static inline char *registry_fix_url(char *url, size_t *len) {
295
- return registry_fix_machine_name(url, len);
295
+ return registry_fix_machine_name(url, len);
296
}
297
298
@@ -307,57 +307,57 @@ extern PERSON *registry_request_delete(char *person_guid, char *machine_guid, ch
307
// URL
308
309
static inline URL *registry_url_allocate_nolock(const char *url, size_t urllen) {
310
- // protection from too big URLs
311
- if(urllen > registry.max_url_length)
312
- urllen = registry.max_url_length;
310
+ // protection from too big URLs
311
+ if(urllen > registry.max_url_length)
312
+ urllen = registry.max_url_length;
313
314
- debug(D_REGISTRY, "Registry: registry_url_allocate_nolock('%s'): allocating %zu bytes", url, sizeof(URL) + urllen);
315
- URL *u = mallocz(sizeof(URL) + urllen);
314
+ debug(D_REGISTRY, "Registry: registry_url_allocate_nolock('%s'): allocating %zu bytes", url, sizeof(URL) + urllen);
315
+ URL *u = mallocz(sizeof(URL) + urllen);
316
317
- // a simple strcpy() should do the job
318
- // but I prefer to be safe, since the caller specified urllen
319
- u->len = (uint16_t)urllen;
320
- strncpyz(u->url, url, u->len);
321
- u->links = 0;
317
+ // a simple strcpy() should do the job
318
+ // but I prefer to be safe, since the caller specified urllen
319
+ u->len = (uint16_t)urllen;
320
+ strncpyz(u->url, url, u->len);
321
+ u->links = 0;
322
323
- registry.urls_memory += sizeof(URL) + urllen;
323
+ registry.urls_memory += sizeof(URL) + urllen;
324
325
- debug(D_REGISTRY, "Registry: registry_url_allocate_nolock('%s'): indexing it", url);
326
- dictionary_set(registry.urls, u->url, u, sizeof(URL));
325
+ debug(D_REGISTRY, "Registry: registry_url_allocate_nolock('%s'): indexing it", url);
326
+ dictionary_set(registry.urls, u->url, u, sizeof(URL));
327
328
- return u;
328
+ return u;
329
}
330
331
static inline URL *registry_url_get(const char *url, size_t urllen) {
332
- debug(D_REGISTRY, "Registry: registry_url_get('%s')", url);
332
+ debug(D_REGISTRY, "Registry: registry_url_get('%s')", url);
333
334
- registry_urls_lock();
334
+ registry_urls_lock();
335
336
- URL *u = dictionary_get(registry.urls, url);
337
- if(!u) {
338
- u = registry_url_allocate_nolock(url, urllen);
339
- registry.urls_count++;
340
- }
336
+ URL *u = dictionary_get(registry.urls, url);
337
+ if(!u) {
338
+ u = registry_url_allocate_nolock(url, urllen);
339
+ registry.urls_count++;
340
+ }
341
342
- registry_urls_unlock();
342
+ registry_urls_unlock();
343
344
- return u;
344
+ return u;
345
}
346
347
static inline void registry_url_link_nolock(URL *u) {
348
- u->links++;
349
- debug(D_REGISTRY, "Registry: registry_url_link_nolock('%s'): URL has now %u links", u->url, u->links);
348
+ u->links++;
349
+ debug(D_REGISTRY, "Registry: registry_url_link_nolock('%s'): URL has now %u links", u->url, u->links);
350
}
351
352
static inline void registry_url_unlink_nolock(URL *u) {
353
- u->links--;
354
- if(!u->links) {
355
- debug(D_REGISTRY, "Registry: registry_url_unlink_nolock('%s'): No more links for this URL", u->url);
356
- dictionary_del(registry.urls, u->url);
357
- freez(u);
358
- }
359
- else
360
- debug(D_REGISTRY, "Registry: registry_url_unlink_nolock('%s'): URL has %u links left", u->url, u->links);
353
+ u->links--;
354
+ if(!u->links) {
355
+ debug(D_REGISTRY, "Registry: registry_url_unlink_nolock('%s'): No more links for this URL", u->url);
356
+ dictionary_del(registry.urls, u->url);
357
+ freez(u);
358
+ }
359
+ else
360
+ debug(D_REGISTRY, "Registry: registry_url_unlink_nolock('%s'): URL has %u links left", u->url, u->links);
361
}
362
363
@@ -365,76 +365,76 @@ static inline void registry_url_unlink_nolock(URL *u) {
365
// MACHINE
366
367
static inline MACHINE *registry_machine_find(const char *machine_guid) {
368
- debug(D_REGISTRY, "Registry: registry_machine_find('%s')", machine_guid);
369
- return dictionary_get(registry.machines, machine_guid);
368
+ debug(D_REGISTRY, "Registry: registry_machine_find('%s')", machine_guid);
369
+ return dictionary_get(registry.machines, machine_guid);
370
}
371
372
static inline MACHINE_URL *registry_machine_url_allocate(MACHINE *m, URL *u, time_t when) {
373
- debug(D_REGISTRY, "registry_machine_link_to_url('%s', '%s'): allocating %zu bytes", m->guid, u->url, sizeof(MACHINE_URL));
373
+ debug(D_REGISTRY, "registry_machine_link_to_url('%s', '%s'): allocating %zu bytes", m->guid, u->url, sizeof(MACHINE_URL));
374
375
- MACHINE_URL *mu = mallocz(sizeof(MACHINE_URL));
375
+ MACHINE_URL *mu = mallocz(sizeof(MACHINE_URL));
376
377
- // mu->persons = dictionary_create(DICTIONARY_FLAGS);
378
- // dictionary_set(mu->persons, p->guid, p, sizeof(PERSON));
377
+ // mu->persons = dictionary_create(DICTIONARY_FLAGS);
378
+ // dictionary_set(mu->persons, p->guid, p, sizeof(PERSON));
379
380
- mu->first_t = mu->last_t = (uint32_t)when;
381
- mu->usages = 1;
382
- mu->url = u;
383
- mu->flags = REGISTRY_URL_FLAGS_DEFAULT;
380
+ mu->first_t = mu->last_t = (uint32_t)when;
381
+ mu->usages = 1;
382
+ mu->url = u;
383
+ mu->flags = REGISTRY_URL_FLAGS_DEFAULT;
384
385
- registry.machines_urls_memory += sizeof(MACHINE_URL);
385
+ registry.machines_urls_memory += sizeof(MACHINE_URL);
386
387
- debug(D_REGISTRY, "registry_machine_link_to_url('%s', '%s'): indexing URL in machine", m->guid, u->url);
388
- dictionary_set(m->urls, u->url, mu, sizeof(MACHINE_URL));
389
- registry_url_link_nolock(u);
387
+ debug(D_REGISTRY, "registry_machine_link_to_url('%s', '%s'): indexing URL in machine", m->guid, u->url);
388
+ dictionary_set(m->urls, u->url, mu, sizeof(MACHINE_URL));
389
+ registry_url_link_nolock(u);
390
391
- return mu;
391
+ return mu;
392
}
393
394
static inline MACHINE *registry_machine_allocate(const char *machine_guid, time_t when) {
395
- debug(D_REGISTRY, "Registry: registry_machine_allocate('%s'): creating new machine, sizeof(MACHINE)=%zu", machine_guid, sizeof(MACHINE));
395
+ debug(D_REGISTRY, "Registry: registry_machine_allocate('%s'): creating new machine, sizeof(MACHINE)=%zu", machine_guid, sizeof(MACHINE));
396
397
- MACHINE *m = mallocz(sizeof(MACHINE));
397
+ MACHINE *m = mallocz(sizeof(MACHINE));
398
399
- strncpyz(m->guid, machine_guid, 36);
399
+ strncpyz(m->guid, machine_guid, 36);
400
401
- debug(D_REGISTRY, "Registry: registry_machine_allocate('%s'): creating dictionary of urls", machine_guid);
402
- m->urls = dictionary_create(DICTIONARY_FLAGS);
401
+ debug(D_REGISTRY, "Registry: registry_machine_allocate('%s'): creating dictionary of urls", machine_guid);
402
+ m->urls = dictionary_create(DICTIONARY_FLAGS);
403
404
- m->first_t = m->last_t = (uint32_t)when;
405
- m->usages = 0;
404
+ m->first_t = m->last_t = (uint32_t)when;
405
+ m->usages = 0;
406
407
- registry.machines_memory += sizeof(MACHINE);
407
+ registry.machines_memory += sizeof(MACHINE);
408
409
- registry.machines_count++;
410
- dictionary_set(registry.machines, m->guid, m, sizeof(MACHINE));
409
+ registry.machines_count++;
410
+ dictionary_set(registry.machines, m->guid, m, sizeof(MACHINE));
411
412
- return m;
412
+ return m;
413
}
414
415
// 1. validate machine GUID
416
// 2. if it is valid, find it or create it and return it
417
// 3. if it is not valid, return NULL
418
static inline MACHINE *registry_machine_get(const char *machine_guid, time_t when) {
419
- MACHINE *m = NULL;
419
+ MACHINE *m = NULL;
420
421
- registry_machines_lock();
421
+ registry_machines_lock();
422
423
- if(likely(machine_guid && *machine_guid)) {
424
- // validate it is a GUID
425
- char buf[36 + 1];
426
- if(unlikely(registry_regenerate_guid(machine_guid, buf) == -1))
427
- info("Registry: machine guid '%s' is not a valid guid. Ignoring it.", machine_guid);
428
- else {
429
- machine_guid = buf;
430
- m = registry_machine_find(machine_guid);
431
- if(!m) m = registry_machine_allocate(machine_guid, when);
432
- }
433
- }
423
+ if(likely(machine_guid && *machine_guid)) {
424
+ // validate it is a GUID
425
+ char buf[36 + 1];
426
+ if(unlikely(registry_regenerate_guid(machine_guid, buf) == -1))
427
+ info("Registry: machine guid '%s' is not a valid guid. Ignoring it.", machine_guid);
428
+ else {
429
+ machine_guid = buf;
430
+ m = registry_machine_find(machine_guid);
431
+ if(!m) m = registry_machine_allocate(machine_guid, when);
432
+ }
433
+ }
434
435
- registry_machines_unlock();
435
+ registry_machines_unlock();
436
437
- return m;
437
+ return m;
438
}
439
440
@@ -442,99 +442,99 @@ static inline MACHINE *registry_machine_get(const char *machine_guid, time_t whe
442
// PERSON
443
444
static inline PERSON *registry_person_find(const char *person_guid) {
445
- debug(D_REGISTRY, "Registry: registry_person_find('%s')", person_guid);
446
- return dictionary_get(registry.persons, person_guid);
445
+ debug(D_REGISTRY, "Registry: registry_person_find('%s')", person_guid);
446
+ return dictionary_get(registry.persons, person_guid);
447
}
448
449
static inline PERSON_URL *registry_person_url_allocate(PERSON *p, MACHINE *m, URL *u, char *name, size_t namelen, time_t when) {
450
- // protection from too big names
451
- if(namelen > registry.max_name_length)
452
- namelen = registry.max_name_length;
450
+ // protection from too big names
451
+ if(namelen > registry.max_name_length)
452
+ namelen = registry.max_name_length;
453
454
- debug(D_REGISTRY, "registry_person_url_allocate('%s', '%s', '%s'): allocating %zu bytes", p->guid, m->guid, u->url,
455
- sizeof(PERSON_URL) + namelen);
454
+ debug(D_REGISTRY, "registry_person_url_allocate('%s', '%s', '%s'): allocating %zu bytes", p->guid, m->guid, u->url,
455
+ sizeof(PERSON_URL) + namelen);
456
457
- PERSON_URL *pu = mallocz(sizeof(PERSON_URL) + namelen);
457
+ PERSON_URL *pu = mallocz(sizeof(PERSON_URL) + namelen);
458
459
- // a simple strcpy() should do the job
460
- // but I prefer to be safe, since the caller specified urllen
461
- strncpyz(pu->name, name, namelen);
459
+ // a simple strcpy() should do the job
460
+ // but I prefer to be safe, since the caller specified urllen
461
+ strncpyz(pu->name, name, namelen);
462
463
- pu->machine = m;
464
- pu->first_t = pu->last_t = when;
465
- pu->usages = 1;
466
- pu->url = u;
467
- pu->flags = REGISTRY_URL_FLAGS_DEFAULT;
468
- m->links++;
463
+ pu->machine = m;
464
+ pu->first_t = pu->last_t = when;
465
+ pu->usages = 1;
466
+ pu->url = u;
467
+ pu->flags = REGISTRY_URL_FLAGS_DEFAULT;
468
+ m->links++;
469
470
- registry.persons_urls_memory += sizeof(PERSON_URL) + namelen;
470
+ registry.persons_urls_memory += sizeof(PERSON_URL) + namelen;
471
472
- debug(D_REGISTRY, "registry_person_url_allocate('%s', '%s', '%s'): indexing URL in person", p->guid, m->guid, u->url);
473
- dictionary_set(p->urls, u->url, pu, sizeof(PERSON_URL));
474
- registry_url_link_nolock(u);
472
+ debug(D_REGISTRY, "registry_person_url_allocate('%s', '%s', '%s'): indexing URL in person", p->guid, m->guid, u->url);
473
+ dictionary_set(p->urls, u->url, pu, sizeof(PERSON_URL));
474
+ registry_url_link_nolock(u);
475
476
- return pu;
476
+ return pu;
477
}
478
479
static inline PERSON_URL *registry_person_url_reallocate(PERSON *p, MACHINE *m, URL *u, char *name, size_t namelen, time_t when, PERSON_URL *pu) {
480
- // this function is needed to change the name of a PERSON_URL
480
+ // this function is needed to change the name of a PERSON_URL
481
482
- debug(D_REGISTRY, "registry_person_url_reallocate('%s', '%s', '%s'): allocating %zu bytes", p->guid, m->guid, u->url,
483
- sizeof(PERSON_URL) + namelen);
482
+ debug(D_REGISTRY, "registry_person_url_reallocate('%s', '%s', '%s'): allocating %zu bytes", p->guid, m->guid, u->url,
483
+ sizeof(PERSON_URL) + namelen);
484
485
- PERSON_URL *tpu = registry_person_url_allocate(p, m, u, name, namelen, when);
486
- tpu->first_t = pu->first_t;
487
- tpu->last_t = pu->last_t;
488
- tpu->usages = pu->usages;
485
+ PERSON_URL *tpu = registry_person_url_allocate(p, m, u, name, namelen, when);
486
+ tpu->first_t = pu->first_t;
487
+ tpu->last_t = pu->last_t;
488
+ tpu->usages = pu->usages;
489
490
- // ok, these are a hack - since the registry_person_url_allocate() is
491
- // adding these, we have to subtract them
492
- tpu->machine->links--;
493
- registry.persons_urls_memory -= sizeof(PERSON_URL) + strlen(pu->name);
494
- registry_url_unlink_nolock(u);
490
+ // ok, these are a hack - since the registry_person_url_allocate() is
491
+ // adding these, we have to subtract them
492
+ tpu->machine->links--;
493
+ registry.persons_urls_memory -= sizeof(PERSON_URL) + strlen(pu->name);
494
+ registry_url_unlink_nolock(u);
495
496
- freez(pu);
496
+ freez(pu);
497
498
- return tpu;
498
+ return tpu;
499
}
500
501
static inline PERSON *registry_person_allocate(const char *person_guid, time_t when) {
502
- PERSON *p = NULL;
502
+ PERSON *p = NULL;
503
504
- debug(D_REGISTRY, "Registry: registry_person_allocate('%s'): allocating new person, sizeof(PERSON)=%zu", (person_guid)?person_guid:"", sizeof(PERSON));
504
+ debug(D_REGISTRY, "Registry: registry_person_allocate('%s'): allocating new person, sizeof(PERSON)=%zu", (person_guid)?person_guid:"", sizeof(PERSON));
505
506
- p = mallocz(sizeof(PERSON));
506
+ p = mallocz(sizeof(PERSON));
507
508
- if(!person_guid) {
509
- for (; ;) {
510
- uuid_t uuid;
511
- uuid_generate(uuid);
512
- uuid_unparse_lower(uuid, p->guid);
508
+ if(!person_guid) {
509
+ for (; ;) {
510
+ uuid_t uuid;
511
+ uuid_generate(uuid);
512
+ uuid_unparse_lower(uuid, p->guid);
513
514
- debug(D_REGISTRY, "Registry: Checking if the generated person guid '%s' is unique", p->guid);
515
- if (!dictionary_get(registry.persons, p->guid)) {
516
- debug(D_REGISTRY, "Registry: generated person guid '%s' is unique", p->guid);
517
- break;
518
- }
519
- else
520
- info("Registry: generated person guid '%s' found in the registry. Retrying...", p->guid);
521
- }
522
- }
523
- else
524
- strncpyz(p->guid, person_guid, 36);
514
+ debug(D_REGISTRY, "Registry: Checking if the generated person guid '%s' is unique", p->guid);
515
+ if (!dictionary_get(registry.persons, p->guid)) {
516
+ debug(D_REGISTRY, "Registry: generated person guid '%s' is unique", p->guid);
517
+ break;
518
+ }
519
+ else
520
+ info("Registry: generated person guid '%s' found in the registry. Retrying...", p->guid);
521
+ }
522
+ }
523
+ else
524
+ strncpyz(p->guid, person_guid, 36);
525
526
- debug(D_REGISTRY, "Registry: registry_person_allocate('%s'): creating dictionary of urls", p->guid);
527
- p->urls = dictionary_create(DICTIONARY_FLAGS);
526
+ debug(D_REGISTRY, "Registry: registry_person_allocate('%s'): creating dictionary of urls", p->guid);
527
+ p->urls = dictionary_create(DICTIONARY_FLAGS);
528
529
- p->first_t = p->last_t = when;
530
- p->usages = 0;
529
+ p->first_t = p->last_t = when;
530
+ p->usages = 0;
531
532
- registry.persons_memory += sizeof(PERSON);
532
+ registry.persons_memory += sizeof(PERSON);
533
534
- registry.persons_count++;
535
- dictionary_set(registry.persons, p->guid, p, sizeof(PERSON));
534
+ registry.persons_count++;
535
+ dictionary_set(registry.persons, p->guid, p, sizeof(PERSON));
536
537
- return p;
537
+ return p;
538
}
539
540
@@ -543,260 +543,260 @@ static inline PERSON *registry_person_allocate(const char *person_guid, time_t w
543
// 3. if it is not valid, create a new one
544
// 4. return it
545
static inline PERSON *registry_person_get(const char *person_guid, time_t when) {
546
- PERSON *p = NULL;
546
+ PERSON *p = NULL;
547
548
- registry_persons_lock();
548
+ registry_persons_lock();
549
550
- if(person_guid && *person_guid) {
551
- char buf[36 + 1];
552
- // validate it is a GUID
553
- if(unlikely(registry_regenerate_guid(person_guid, buf) == -1))
554
- info("Registry: person guid '%s' is not a valid guid. Ignoring it.", person_guid);
555
- else {
556
- person_guid = buf;
557
- p = registry_person_find(person_guid);
558
- if(!p) person_guid = NULL;
559
- }
560
- }
550
+ if(person_guid && *person_guid) {
551
+ char buf[36 + 1];
552
+ // validate it is a GUID
553
+ if(unlikely(registry_regenerate_guid(person_guid, buf) == -1))
554
+ info("Registry: person guid '%s' is not a valid guid. Ignoring it.", person_guid);
555
+ else {
556
+ person_guid = buf;
557
+ p = registry_person_find(person_guid);
558
+ if(!p) person_guid = NULL;
559
+ }
560
+ }
561
562
- if(!p) p = registry_person_allocate(NULL, when);
562
+ if(!p) p = registry_person_allocate(NULL, when);
563
564
- registry_persons_unlock();
564
+ registry_persons_unlock();
565
566
- return p;
566
+ return p;
567
}
568
569
// ----------------------------------------------------------------------------
570
// LINKING OF OBJECTS
571
572
static inline PERSON_URL *registry_person_link_to_url(PERSON *p, MACHINE *m, URL *u, char *name, size_t namelen, time_t when) {
573
- debug(D_REGISTRY, "registry_person_link_to_url('%s', '%s', '%s'): searching for URL in person", p->guid, m->guid, u->url);
574
-
575
- registry_person_urls_lock(p);
576
-
577
- PERSON_URL *pu = dictionary_get(p->urls, u->url);
578
- if(!pu) {
579
- debug(D_REGISTRY, "registry_person_link_to_url('%s', '%s', '%s'): not found", p->guid, m->guid, u->url);
580
- pu = registry_person_url_allocate(p, m, u, name, namelen, when);
581
- registry.persons_urls_count++;
582
- }
583
- else {
584
- debug(D_REGISTRY, "registry_person_link_to_url('%s', '%s', '%s'): found", p->guid, m->guid, u->url);
585
- pu->usages++;
586
- if(likely(pu->last_t < (uint32_t)when)) pu->last_t = when;
587
-
588
- if(pu->machine != m) {
589
- MACHINE_URL *mu = dictionary_get(pu->machine->urls, u->url);
590
- if(mu) {
591
- info("registry_person_link_to_url('%s', '%s', '%s'): URL switched machines (old was '%s') - expiring it from previous machine.",
592
- p->guid, m->guid, u->url, pu->machine->guid);
593
- mu->flags |= REGISTRY_URL_FLAGS_EXPIRED;
594
- }
595
- else {
596
- info("registry_person_link_to_url('%s', '%s', '%s'): URL switched machines (old was '%s') - but the URL is not linked to the old machine.",
597
- p->guid, m->guid, u->url, pu->machine->guid);
598
- }
599
-
600
- pu->machine->links--;
601
- pu->machine = m;
602
- }
603
-
604
- if(strcmp(pu->name, name)) {
605
- // the name of the PERSON_URL has changed !
606
- pu = registry_person_url_reallocate(p, m, u, name, namelen, when, pu);
607
- }
608
- }
609
-
610
- p->usages++;
611
- if(likely(p->last_t < (uint32_t)when)) p->last_t = when;
612
-
613
- if(pu->flags & REGISTRY_URL_FLAGS_EXPIRED) {
614
- info("registry_person_link_to_url('%s', '%s', '%s'): accessing an expired URL. Re-enabling URL.", p->guid, m->guid, u->url);
615
- pu->flags &= ~REGISTRY_URL_FLAGS_EXPIRED;
616
- }
617
-
618
- registry_person_urls_unlock(p);
619
-
620
- return pu;
573
+ debug(D_REGISTRY, "registry_person_link_to_url('%s', '%s', '%s'): searching for URL in person", p->guid, m->guid, u->url);
574
+
575
+ registry_person_urls_lock(p);
576
+
577
+ PERSON_URL *pu = dictionary_get(p->urls, u->url);
578
+ if(!pu) {
579
+ debug(D_REGISTRY, "registry_person_link_to_url('%s', '%s', '%s'): not found", p->guid, m->guid, u->url);
580
+ pu = registry_person_url_allocate(p, m, u, name, namelen, when);
581
+ registry.persons_urls_count++;
582
+ }
583
+ else {
584
+ debug(D_REGISTRY, "registry_person_link_to_url('%s', '%s', '%s'): found", p->guid, m->guid, u->url);
585
+ pu->usages++;
586
+ if(likely(pu->last_t < (uint32_t)when)) pu->last_t = when;
587
+
588
+ if(pu->machine != m) {
589
+ MACHINE_URL *mu = dictionary_get(pu->machine->urls, u->url);
590
+ if(mu) {
591
+ info("registry_person_link_to_url('%s', '%s', '%s'): URL switched machines (old was '%s') - expiring it from previous machine.",
592
+ p->guid, m->guid, u->url, pu->machine->guid);
593
+ mu->flags |= REGISTRY_URL_FLAGS_EXPIRED;
594
+ }
595
+ else {
596
+ info("registry_person_link_to_url('%s', '%s', '%s'): URL switched machines (old was '%s') - but the URL is not linked to the old machine.",
597
+ p->guid, m->guid, u->url, pu->machine->guid);
598
+ }
599
+
600
+ pu->machine->links--;
601
+ pu->machine = m;
602
+ }
603
+
604
+ if(strcmp(pu->name, name)) {
605
+ // the name of the PERSON_URL has changed !
606
+ pu = registry_person_url_reallocate(p, m, u, name, namelen, when, pu);
607
+ }
608
+ }
609
+
610
+ p->usages++;
611
+ if(likely(p->last_t < (uint32_t)when)) p->last_t = when;
612
+
613
+ if(pu->flags & REGISTRY_URL_FLAGS_EXPIRED) {
614
+ info("registry_person_link_to_url('%s', '%s', '%s'): accessing an expired URL. Re-enabling URL.", p->guid, m->guid, u->url);
615
+ pu->flags &= ~REGISTRY_URL_FLAGS_EXPIRED;
616
+ }
617
+
618
+ registry_person_urls_unlock(p);
619
+
620
+ return pu;
621
}
622
623
static inline MACHINE_URL *registry_machine_link_to_url(PERSON *p, MACHINE *m, URL *u, time_t when) {
624
- debug(D_REGISTRY, "registry_machine_link_to_url('%s', '%s', '%s'): searching for URL in machine", p->guid, m->guid, u->url);
624
+ debug(D_REGISTRY, "registry_machine_link_to_url('%s', '%s', '%s'): searching for URL in machine", p->guid, m->guid, u->url);
625
626
- registry_machine_urls_lock(m);
626
+ registry_machine_urls_lock(m);
627
628
- MACHINE_URL *mu = dictionary_get(m->urls, u->url);
629
- if(!mu) {
630
- debug(D_REGISTRY, "registry_machine_link_to_url('%s', '%s', '%s'): not found", p->guid, m->guid, u->url);
631
- mu = registry_machine_url_allocate(m, u, when);
632
- registry.machines_urls_count++;
633
- }
634
- else {
635
- debug(D_REGISTRY, "registry_machine_link_to_url('%s', '%s', '%s'): found", p->guid, m->guid, u->url);
636
- mu->usages++;
637
- if(likely(mu->last_t < (uint32_t)when)) mu->last_t = when;
638
- }
628
+ MACHINE_URL *mu = dictionary_get(m->urls, u->url);
629
+ if(!mu) {
630
+ debug(D_REGISTRY, "registry_machine_link_to_url('%s', '%s', '%s'): not found", p->guid, m->guid, u->url);
631
+ mu = registry_machine_url_allocate(m, u, when);
632
+ registry.machines_urls_count++;
633
+ }
634
+ else {
635
+ debug(D_REGISTRY, "registry_machine_link_to_url('%s', '%s', '%s'): found", p->guid, m->guid, u->url);
636
+ mu->usages++;
637
+ if(likely(mu->last_t < (uint32_t)when)) mu->last_t = when;
638
+ }
639
640
- //debug(D_REGISTRY, "registry_machine_link_to_url('%s', '%s', '%s'): indexing person in machine", p->guid, m->guid, u->url);
641
- //dictionary_set(mu->persons, p->guid, p, sizeof(PERSON));
640
+ //debug(D_REGISTRY, "registry_machine_link_to_url('%s', '%s', '%s'): indexing person in machine", p->guid, m->guid, u->url);
641
+ //dictionary_set(mu->persons, p->guid, p, sizeof(PERSON));
642
643
- m->usages++;
644
- if(likely(m->last_t < (uint32_t)when)) m->last_t = when;
643
+ m->usages++;
644
+ if(likely(m->last_t < (uint32_t)when)) m->last_t = when;
645
646
- if(mu->flags & REGISTRY_URL_FLAGS_EXPIRED) {
647
- info("registry_machine_link_to_url('%s', '%s', '%s'): accessing an expired URL.", p->guid, m->guid, u->url);
648
- mu->flags &= ~REGISTRY_URL_FLAGS_EXPIRED;
649
- }
646
+ if(mu->flags & REGISTRY_URL_FLAGS_EXPIRED) {
647
+ info("registry_machine_link_to_url('%s', '%s', '%s'): accessing an expired URL.", p->guid, m->guid, u->url);
648
+ mu->flags &= ~REGISTRY_URL_FLAGS_EXPIRED;
649
+ }
650
651
- registry_machine_urls_unlock(m);
651
+ registry_machine_urls_unlock(m);
652
653
- return mu;
653
+ return mu;
654
}
655
656
// ----------------------------------------------------------------------------
657
// REGISTRY LOG LOAD/SAVE
658
659
static inline int registry_should_save_db(void) {
660
- debug(D_REGISTRY, "log entries %llu, max %llu", registry.log_count, registry.save_registry_every_entries);
661
- return registry.log_count > registry.save_registry_every_entries;
660
+ debug(D_REGISTRY, "log entries %llu, max %llu", registry.log_count, registry.save_registry_every_entries);
661
+ return registry.log_count > registry.save_registry_every_entries;
662
}
663
664
static inline void registry_log(const char action, PERSON *p, MACHINE *m, URL *u, char *name) {
665
- if(likely(registry.log_fp)) {
666
- // we lock only if the file is open
667
- // to allow replaying the log at registry_log_load()
668
- registry_log_lock();
669
-
670
- if(unlikely(fprintf(registry.log_fp, "%c\t%08x\t%s\t%s\t%s\t%s\n",
671
- action,
672
- p->last_t,
673
- p->guid,
674
- m->guid,
675
- name,
676
- u->url) < 0))
677
- error("Registry: failed to save log. Registry data may be lost in case of abnormal restart.");
678
-
679
- // we increase the counter even on failures
680
- // so that the registry will be saved periodically
681
- registry.log_count++;
682
-
683
- registry_log_unlock();
684
-
685
- // this must be outside the log_lock(), or a deadlock will happen.
686
- // registry_save() checks the same inside the log_lock, so only
687
- // one thread will save the db
688
- if(unlikely(registry_should_save_db()))
689
- registry_save();
690
- }
665
+ if(likely(registry.log_fp)) {
666
+ // we lock only if the file is open
667
+ // to allow replaying the log at registry_log_load()
668
+ registry_log_lock();
669
+
670
+ if(unlikely(fprintf(registry.log_fp, "%c\t%08x\t%s\t%s\t%s\t%s\n",
671
+ action,
672
+ p->last_t,
673
+ p->guid,
674
+ m->guid,
675
+ name,
676
+ u->url) < 0))
677
+ error("Registry: failed to save log. Registry data may be lost in case of abnormal restart.");
678
+
679
+ // we increase the counter even on failures
680
+ // so that the registry will be saved periodically
681
+ registry.log_count++;
682
+
683
+ registry_log_unlock();
684
+
685
+ // this must be outside the log_lock(), or a deadlock will happen.
686
+ // registry_save() checks the same inside the log_lock, so only
687
+ // one thread will save the db
688
+ if(unlikely(registry_should_save_db()))
689
+ registry_save();
690
+ }
691
}
692
693
static inline int registry_log_open_nolock(void) {
694
- if(registry.log_fp)
695
- fclose(registry.log_fp);
694
+ if(registry.log_fp)
695
+ fclose(registry.log_fp);
696
697
- registry.log_fp = fopen(registry.log_filename, "a");
697
+ registry.log_fp = fopen(registry.log_filename, "a");
698
699
- if(registry.log_fp) {
700
- if (setvbuf(registry.log_fp, NULL, _IOLBF, 0) != 0)
701
- error("Cannot set line buffering on registry log file.");
702
- return 0;
703
- }
699
+ if(registry.log_fp) {
700
+ if (setvbuf(registry.log_fp, NULL, _IOLBF, 0) != 0)
701
+ error("Cannot set line buffering on registry log file.");
702
+ return 0;
703
+ }
704
705
- error("Cannot open registry log file '%s'. Registry data will be lost in case of netdata or server crash.", registry.log_filename);
706
- return -1;
705
+ error("Cannot open registry log file '%s'. Registry data will be lost in case of netdata or server crash.", registry.log_filename);
706
+ return -1;
707
}
708
709
static inline void registry_log_close_nolock(void) {
710
- if(registry.log_fp) {
711
- fclose(registry.log_fp);
712
- registry.log_fp = NULL;
713
- }
710
+ if(registry.log_fp) {
711
+ fclose(registry.log_fp);
712
+ registry.log_fp = NULL;
713
+ }
714
}
715
716
static inline void registry_log_recreate_nolock(void) {
717
- if(registry.log_fp != NULL) {
718
- registry_log_close_nolock();
717
+ if(registry.log_fp != NULL) {
718
+ registry_log_close_nolock();
719
720
- // open it with truncate
721
- registry.log_fp = fopen(registry.log_filename, "w");
722
- if(registry.log_fp) fclose(registry.log_fp);
723
- else error("Cannot truncate registry log '%s'", registry.log_filename);
720
+ // open it with truncate
721
+ registry.log_fp = fopen(registry.log_filename, "w");
722
+ if(registry.log_fp) fclose(registry.log_fp);
723
+ else error("Cannot truncate registry log '%s'", registry.log_filename);
724
725
- registry.log_fp = NULL;
725
+ registry.log_fp = NULL;
726
727
- registry_log_open_nolock();
728
- }
727
+ registry_log_open_nolock();
728
+ }
729
}
730
731
int registry_log_load(void) {
732
- char *s, buf[4096 + 1];
733
- size_t line = -1;
734
-
735
- // closing the log is required here
736
- // otherwise we will append to it the values we read
737
- registry_log_close_nolock();
738
-
739
- debug(D_REGISTRY, "Registry: loading active db from: %s", registry.log_filename);
740
- FILE *fp = fopen(registry.log_filename, "r");
741
- if(!fp)
742
- error("Registry: cannot open registry file: %s", registry.log_filename);
743
- else {
744
- line = 0;
745
- size_t len = 0;
746
- while ((s = fgets_trim_len(buf, 4096, fp, &len))) {
747
- line++;
748
-
749
- switch (s[0]) {
750
- case 'A': // accesses
751
- case 'D': // deletes
752
-
753
- // verify it is valid
754
- if (unlikely(len < 85 || s[1] != '\t' || s[10] != '\t' || s[47] != '\t' || s[84] != '\t')) {
755
- error("Registry: log line %zu is wrong (len = %zu).", line, len);
756
- continue;
757
- }
758
- s[1] = s[10] = s[47] = s[84] = '\0';
759
-
760
- // get the variables
761
- time_t when = strtoul(&s[2], NULL, 16);
762
- char *person_guid = &s[11];
763
- char *machine_guid = &s[48];
764
- char *name = &s[85];
765
-
766
- // skip the name to find the url
767
- char *url = name;
768
- while(*url && *url != '\t') url++;
769
- if(!*url) {
770
- error("Registry: log line %zu does not have a url.", line);
771
- continue;
772
- }
773
- *url++ = '\0';
774
-
775
- // make sure the person exists
776
- // without this, a new person guid will be created
777
- PERSON *p = registry_person_find(person_guid);
778
- if(!p) p = registry_person_allocate(person_guid, when);
779
-
780
- if(s[0] == 'A')
781
- registry_request_access(p->guid, machine_guid, url, name, when);
782
- else
783
- registry_request_delete(p->guid, machine_guid, url, name, when);
784
-
785
- break;
786
-
787
- default:
788
- error("Registry: ignoring line %zu of filename '%s': %s.", line, registry.log_filename, s);
789
- break;
790
- }
791
- }
792
-
793
- fclose(fp);
794
- }
795
-
796
- // open the log again
797
- registry_log_open_nolock();
798
-
799
- return line;
732
+ char *s, buf[4096 + 1];
733
+ size_t line = -1;
734
+
735
+ // closing the log is required here
736
+ // otherwise we will append to it the values we read
737
+ registry_log_close_nolock();
738
+
739
+ debug(D_REGISTRY, "Registry: loading active db from: %s", registry.log_filename);
740
+ FILE *fp = fopen(registry.log_filename, "r");
741
+ if(!fp)
742
+ error("Registry: cannot open registry file: %s", registry.log_filename);
743
+ else {
744
+ line = 0;
745
+ size_t len = 0;
746
+ while ((s = fgets_trim_len(buf, 4096, fp, &len))) {
747
+ line++;
748
+
749
+ switch (s[0]) {
750
+ case 'A': // accesses
751
+ case 'D': // deletes
752
+
753
+ // verify it is valid
754
+ if (unlikely(len < 85 || s[1] != '\t' || s[10] != '\t' || s[47] != '\t' || s[84] != '\t')) {
755
+ error("Registry: log line %zu is wrong (len = %zu).", line, len);
756
+ continue;
757
+ }
758
+ s[1] = s[10] = s[47] = s[84] = '\0';
759
+
760
+ // get the variables
761
+ time_t when = strtoul(&s[2], NULL, 16);
762
+ char *person_guid = &s[11];
763
+ char *machine_guid = &s[48];
764
+ char *name = &s[85];
765
+
766
+ // skip the name to find the url
767
+ char *url = name;
768
+ while(*url && *url != '\t') url++;
769
+ if(!*url) {
770
+ error("Registry: log line %zu does not have a url.", line);
771
+ continue;
772
+ }
773
+ *url++ = '\0';
774
+
775
+ // make sure the person exists
776
+ // without this, a new person guid will be created
777
+ PERSON *p = registry_person_find(person_guid);
778
+ if(!p) p = registry_person_allocate(person_guid, when);
779
+
780
+ if(s[0] == 'A')
781
+ registry_request_access(p->guid, machine_guid, url, name, when);
782
+ else
783
+ registry_request_delete(p->guid, machine_guid, url, name, when);
784
+
785
+ break;
786
+
787
+ default:
788
+ error("Registry: ignoring line %zu of filename '%s': %s.", line, registry.log_filename, s);
789
+ break;
790
+ }
791
+ }
792
+
793
+ fclose(fp);
794
+ }
795
+
796
+ // open the log again
797
+ registry_log_open_nolock();
798
+
799
+ return line;
800
}
801
802
@@ -804,176 +804,176 @@ int registry_log_load(void) {
804
// REGISTRY REQUESTS
805
806
PERSON *registry_request_access(char *person_guid, char *machine_guid, char *url, char *name, time_t when) {
807
- debug(D_REGISTRY, "registry_request_access('%s', '%s', '%s'): NEW REQUEST", (person_guid)?person_guid:"", machine_guid, url);
807
+ debug(D_REGISTRY, "registry_request_access('%s', '%s', '%s'): NEW REQUEST", (person_guid)?person_guid:"", machine_guid, url);
808
809
- MACHINE *m = registry_machine_get(machine_guid, when);
810
- if(!m) return NULL;
809
+ MACHINE *m = registry_machine_get(machine_guid, when);
810
+ if(!m) return NULL;
811
812
- // make sure the name is valid
813
- size_t namelen;
814
- name = registry_fix_machine_name(name, &namelen);
812
+ // make sure the name is valid
813
+ size_t namelen;
814
+ name = registry_fix_machine_name(name, &namelen);
815
816
- size_t urllen;
817
- url = registry_fix_url(url, &urllen);
816
+ size_t urllen;
817
+ url = registry_fix_url(url, &urllen);
818
819
- URL *u = registry_url_get(url, urllen);
820
- PERSON *p = registry_person_get(person_guid, when);
819
+ URL *u = registry_url_get(url, urllen);
820
+ PERSON *p = registry_person_get(person_guid, when);
821
822
- registry_person_link_to_url(p, m, u, name, namelen, when);
823
- registry_machine_link_to_url(p, m, u, when);
822
+ registry_person_link_to_url(p, m, u, name, namelen, when);
823
+ registry_machine_link_to_url(p, m, u, when);
824
825
- registry_log('A', p, m, u, name);
825
+ registry_log('A', p, m, u, name);
826
827
- registry.usages_count++;
828
- return p;
827
+ registry.usages_count++;
828
+ return p;
829
}
830
831
// verify the person, the machine and the URL exist in our DB
832
PERSON_URL *registry_verify_request(char *person_guid, char *machine_guid, char *url, PERSON **pp, MACHINE **mm) {
833
- char pbuf[36 + 1], mbuf[36 + 1];
834
-
835
- if(!person_guid || !*person_guid || !machine_guid || !*machine_guid || !url || !*url) {
836
- info("Registry Request Verification: invalid request! person: '%s', machine '%s', url '%s'", person_guid?person_guid:"UNSET", machine_guid?machine_guid:"UNSET", url?url:"UNSET");
837
- return NULL;
838
- }
839
-
840
- // normalize the url
841
- url = registry_fix_url(url, NULL);
842
-
843
- // make sure the person GUID is valid
844
- if(registry_regenerate_guid(person_guid, pbuf) == -1) {
845
- info("Registry Request Verification: invalid person GUID, person: '%s', machine '%s', url '%s'", person_guid, machine_guid, url);
846
- return NULL;
847
- }
848
- person_guid = pbuf;
849
-
850
- // make sure the machine GUID is valid
851
- if(registry_regenerate_guid(machine_guid, mbuf) == -1) {
852
- info("Registry Request Verification: invalid machine GUID, person: '%s', machine '%s', url '%s'", person_guid, machine_guid, url);
853
- return NULL;
854
- }
855
- machine_guid = mbuf;
856
-
857
- // make sure the machine exists
858
- MACHINE *m = registry_machine_find(machine_guid);
859
- if(!m) {
860
- info("Registry Request Verification: machine not found, person: '%s', machine '%s', url '%s'", person_guid, machine_guid, url);
861
- return NULL;
862
- }
863
- if(mm) *mm = m;
864
-
865
- // make sure the person exist
866
- PERSON *p = registry_person_find(person_guid);
867
- if(!p) {
868
- info("Registry Request Verification: person not found, person: '%s', machine '%s', url '%s'", person_guid, machine_guid, url);
869
- return NULL;
870
- }
871
- if(pp) *pp = p;
872
-
873
- PERSON_URL *pu = dictionary_get(p->urls, url);
874
- if(!pu) {
875
- info("Registry Request Verification: URL not found for person, person: '%s', machine '%s', url '%s'", person_guid, machine_guid, url);
876
- return NULL;
877
- }
878
- return pu;
833
+ char pbuf[36 + 1], mbuf[36 + 1];
834
+
835
+ if(!person_guid || !*person_guid || !machine_guid || !*machine_guid || !url || !*url) {
836
+ info("Registry Request Verification: invalid request! person: '%s', machine '%s', url '%s'", person_guid?person_guid:"UNSET", machine_guid?machine_guid:"UNSET", url?url:"UNSET");
837
+ return NULL;
838
+ }
839
+
840
+ // normalize the url
841
+ url = registry_fix_url(url, NULL);
842
+
843
+ // make sure the person GUID is valid
844
+ if(registry_regenerate_guid(person_guid, pbuf) == -1) {
845
+ info("Registry Request Verification: invalid person GUID, person: '%s', machine '%s', url '%s'", person_guid, machine_guid, url);
846
+ return NULL;
847
+ }
848
+ person_guid = pbuf;
849
+
850
+ // make sure the machine GUID is valid
851
+ if(registry_regenerate_guid(machine_guid, mbuf) == -1) {
852
+ info("Registry Request Verification: invalid machine GUID, person: '%s', machine '%s', url '%s'", person_guid, machine_guid, url);
853
+ return NULL;
854
+ }
855
+ machine_guid = mbuf;
856
+
857
+ // make sure the machine exists
858
+ MACHINE *m = registry_machine_find(machine_guid);
859
+ if(!m) {
860
+ info("Registry Request Verification: machine not found, person: '%s', machine '%s', url '%s'", person_guid, machine_guid, url);
861
+ return NULL;
862
+ }
863
+ if(mm) *mm = m;
864
+
865
+ // make sure the person exist
866
+ PERSON *p = registry_person_find(person_guid);
867
+ if(!p) {
868
+ info("Registry Request Verification: person not found, person: '%s', machine '%s', url '%s'", person_guid, machine_guid, url);
869
+ return NULL;
870
+ }
871
+ if(pp) *pp = p;
872
+
873
+ PERSON_URL *pu = dictionary_get(p->urls, url);
874
+ if(!pu) {
875
+ info("Registry Request Verification: URL not found for person, person: '%s', machine '%s', url '%s'", person_guid, machine_guid, url);
876
+ return NULL;
877
+ }
878
+ return pu;
879
}
880
881
PERSON *registry_request_delete(char *person_guid, char *machine_guid, char *url, char *delete_url, time_t when) {
882
- (void)when;
882
+ (void)when;
883
884
- PERSON *p = NULL;
885
- MACHINE *m = NULL;
886
- PERSON_URL *pu = registry_verify_request(person_guid, machine_guid, url, &p, &m);
887
- if(!pu || !p || !m) return NULL;
884
+ PERSON *p = NULL;
885
+ MACHINE *m = NULL;
886
+ PERSON_URL *pu = registry_verify_request(person_guid, machine_guid, url, &p, &m);
887
+ if(!pu || !p || !m) return NULL;
888
889
- // normalize the url
890
- delete_url = registry_fix_url(delete_url, NULL);
889
+ // normalize the url
890
+ delete_url = registry_fix_url(delete_url, NULL);
891
892
- // make sure the user is not deleting the url it uses
893
- if(!strcmp(delete_url, pu->url->url)) {
894
- info("Registry Delete Request: delete URL is the one currently accessed, person: '%s', machine '%s', url '%s', delete url '%s'", p->guid, m->guid, pu->url->url, delete_url);
895
- return NULL;
896
- }
892
+ // make sure the user is not deleting the url it uses
893
+ if(!strcmp(delete_url, pu->url->url)) {
894
+ info("Registry Delete Request: delete URL is the one currently accessed, person: '%s', machine '%s', url '%s', delete url '%s'", p->guid, m->guid, pu->url->url, delete_url);
895
+ return NULL;
896
+ }
897
898
- registry_person_urls_lock(p);
898
+ registry_person_urls_lock(p);
899
900
- PERSON_URL *dpu = dictionary_get(p->urls, delete_url);
901
- if(!dpu) {
902
- info("Registry Delete Request: URL not found for person: '%s', machine '%s', url '%s', delete url '%s'", p->guid, m->guid, pu->url->url, delete_url);
903
- registry_person_urls_unlock(p);
904
- return NULL;
905
- }
900
+ PERSON_URL *dpu = dictionary_get(p->urls, delete_url);
901
+ if(!dpu) {
902
+ info("Registry Delete Request: URL not found for person: '%s', machine '%s', url '%s', delete url '%s'", p->guid, m->guid, pu->url->url, delete_url);
903
+ registry_person_urls_unlock(p);
904
+ return NULL;
905
+ }
906
907
- registry_log('D', p, m, pu->url, dpu->url->url);
907
+ registry_log('D', p, m, pu->url, dpu->url->url);
908
909
- dictionary_del(p->urls, dpu->url->url);
910
- registry_url_unlink_nolock(dpu->url);
911
- freez(dpu);
909
+ dictionary_del(p->urls, dpu->url->url);
910
+ registry_url_unlink_nolock(dpu->url);
911
+ freez(dpu);
912
913
- registry_person_urls_unlock(p);
914
- return p;
913
+ registry_person_urls_unlock(p);
914
+ return p;
915
}
916
917
918
// a structure to pass to the dictionary_get_all() callback handler
919
struct machine_request_callback_data {
920
- MACHINE *find_this_machine;
921
- PERSON_URL *result;
920
+ MACHINE *find_this_machine;
921
+ PERSON_URL *result;
922
};
923
924
// the callback function
925
// this will be run for every PERSON_URL of this PERSON
926
int machine_request_callback(void *entry, void *data) {
927
- PERSON_URL *mypu = (PERSON_URL *)entry;
928
- struct machine_request_callback_data *myrdata = (struct machine_request_callback_data *)data;
927
+ PERSON_URL *mypu = (PERSON_URL *)entry;
928
+ struct machine_request_callback_data *myrdata = (struct machine_request_callback_data *)data;
929
930
- if(mypu->machine == myrdata->find_this_machine) {
931
- myrdata->result = mypu;
932
- return -1; // this will also stop the walk through
933
- }
930
+ if(mypu->machine == myrdata->find_this_machine) {
931
+ myrdata->result = mypu;
932
+ return -1; // this will also stop the walk through
933
+ }
934
935
- return 0; // continue
935
+ return 0; // continue
936
}
937
938
MACHINE *registry_request_machine(char *person_guid, char *machine_guid, char *url, char *request_machine, time_t when) {
939
- (void)when;
939
+ (void)when;
940
941
- char mbuf[36 + 1];
941
+ char mbuf[36 + 1];
942
943
- PERSON *p = NULL;
944
- MACHINE *m = NULL;
945
- PERSON_URL *pu = registry_verify_request(person_guid, machine_guid, url, &p, &m);
946
- if(!pu || !p || !m) return NULL;
943
+ PERSON *p = NULL;
944
+ MACHINE *m = NULL;
945
+ PERSON_URL *pu = registry_verify_request(person_guid, machine_guid, url, &p, &m);
946
+ if(!pu || !p || !m) return NULL;
947
948
- // make sure the machine GUID is valid
949
- if(registry_regenerate_guid(request_machine, mbuf) == -1) {
950
- info("Registry Machine URLs request: invalid machine GUID, person: '%s', machine '%s', url '%s', request machine '%s'", p->guid, m->guid, pu->url->url, request_machine);
951
- return NULL;
952
- }
953
- request_machine = mbuf;
948
+ // make sure the machine GUID is valid
949
+ if(registry_regenerate_guid(request_machine, mbuf) == -1) {
950
+ info("Registry Machine URLs request: invalid machine GUID, person: '%s', machine '%s', url '%s', request machine '%s'", p->guid, m->guid, pu->url->url, request_machine);
951
+ return NULL;
952
+ }
953
+ request_machine = mbuf;
954
955
- // make sure the machine exists
956
- m = registry_machine_find(request_machine);
957
- if(!m) {
958
- info("Registry Machine URLs request: machine not found, person: '%s', machine '%s', url '%s', request machine '%s'", p->guid, m->guid, pu->url->url, request_machine);
959
- return NULL;
960
- }
955
+ // make sure the machine exists
956
+ m = registry_machine_find(request_machine);
957
+ if(!m) {
958
+ info("Registry Machine URLs request: machine not found, person: '%s', machine '%s', url '%s', request machine '%s'", p->guid, m->guid, pu->url->url, request_machine);
959
+ return NULL;
960
+ }
961
962
- // Verify the user has in the past accessed this machine
963
- // We will walk through the PERSON_URLs to find the machine
964
- // linking to our machine
962
+ // Verify the user has in the past accessed this machine
963
+ // We will walk through the PERSON_URLs to find the machine
964
+ // linking to our machine
965
966
- // a structure to pass to the dictionary_get_all() callback handler
967
- struct machine_request_callback_data rdata = { m, NULL };
966
+ // a structure to pass to the dictionary_get_all() callback handler
967
+ struct machine_request_callback_data rdata = { m, NULL };
968
969
- // request a walk through on the dictionary
970
- // no need for locking here, the underlying dictionary has its own
971
- dictionary_get_all(p->urls, machine_request_callback, &rdata);
969
+ // request a walk through on the dictionary
970
+ // no need for locking here, the underlying dictionary has its own
971
+ dictionary_get_all(p->urls, machine_request_callback, &rdata);
972
973
- if(rdata.result)
974
- return m;
973
+ if(rdata.result)
974
+ return m;
975
976
- return NULL;
976
+ return NULL;
977
}
978
979
@@ -985,242 +985,242 @@ MACHINE *registry_request_machine(char *person_guid, char *machine_guid, char *u
985
#define REGISTRY_STATUS_DISABLED "disabled"
986
987
int registry_verify_cookies_redirects(void) {
988
- return registry.verify_cookies_redirects;
988
+ return registry.verify_cookies_redirects;
989
}
990
991
const char *registry_to_announce(void) {
992
- return registry.registry_to_announce;
992
+ return registry.registry_to_announce;
993
}
994
995
void registry_set_cookie(struct web_client *w, const char *guid) {
996
- char edate[100];
997
- time_t et = time(NULL) + registry.persons_expiration;
998
- struct tm etmbuf, *etm = gmtime_r(&et, &etmbuf);
999
- strftime(edate, sizeof(edate), "%a, %d %b %Y %H:%M:%S %Z", etm);
996
+ char edate[100];
997
+ time_t et = time(NULL) + registry.persons_expiration;
998
+ struct tm etmbuf, *etm = gmtime_r(&et, &etmbuf);
999
+ strftime(edate, sizeof(edate), "%a, %d %b %Y %H:%M:%S %Z", etm);
1000
1001
- snprintfz(w->cookie1, COOKIE_MAX, NETDATA_REGISTRY_COOKIE_NAME "=%s; Expires=%s", guid, edate);
1001
+ snprintfz(w->cookie1, COOKIE_MAX, NETDATA_REGISTRY_COOKIE_NAME "=%s; Expires=%s", guid, edate);
1002
1003
- if(registry.registry_domain && registry.registry_domain[0])
1004
- snprintfz(w->cookie2, COOKIE_MAX, NETDATA_REGISTRY_COOKIE_NAME "=%s; Domain=%s; Expires=%s", guid, registry.registry_domain, edate);
1003
+ if(registry.registry_domain && registry.registry_domain[0])
1004
+ snprintfz(w->cookie2, COOKIE_MAX, NETDATA_REGISTRY_COOKIE_NAME "=%s; Domain=%s; Expires=%s", guid, registry.registry_domain, edate);
1005
}
1006
1007
static inline void registry_set_person_cookie(struct web_client *w, PERSON *p) {
1008
- registry_set_cookie(w, p->guid);
1008
+ registry_set_cookie(w, p->guid);
1009
}
1010
1011
static inline void registry_json_header(struct web_client *w, const char *action, const char *status) {
1012
- buffer_flush(w->response.data);
1013
- w->response.data->contenttype = CT_APPLICATION_JSON;
1014
- buffer_sprintf(w->response.data, "{\n\t\"action\": \"%s\",\n\t\"status\": \"%s\",\n\t\"hostname\": \"%s\",\n\t\"machine_guid\": \"%s\"",
1015
- action, status, registry.hostname, registry.machine_guid);
1012
+ buffer_flush(w->response.data);
1013
+ w->response.data->contenttype = CT_APPLICATION_JSON;
1014
+ buffer_sprintf(w->response.data, "{\n\t\"action\": \"%s\",\n\t\"status\": \"%s\",\n\t\"hostname\": \"%s\",\n\t\"machine_guid\": \"%s\"",
1015
+ action, status, registry.hostname, registry.machine_guid);
1016
}
1017
1018
static inline void registry_json_footer(struct web_client *w) {
1019
- buffer_strcat(w->response.data, "\n}\n");
1019
+ buffer_strcat(w->response.data, "\n}\n");
1020
}
1021
1022
int registry_request_hello_json(struct web_client *w) {
1023
- registry_json_header(w, "hello", REGISTRY_STATUS_OK);
1023
+ registry_json_header(w, "hello", REGISTRY_STATUS_OK);
1024
1025
- buffer_sprintf(w->response.data, ",\n\t\"registry\": \"%s\"",
1026
- registry.registry_to_announce);
1025
+ buffer_sprintf(w->response.data, ",\n\t\"registry\": \"%s\"",
1026
+ registry.registry_to_announce);
1027
1028
- registry_json_footer(w);
1029
- return 200;
1028
+ registry_json_footer(w);
1029
+ return 200;
1030
}
1031
1032
static inline int registry_json_disabled(struct web_client *w, const char *action) {
1033
- registry_json_header(w, action, REGISTRY_STATUS_DISABLED);
1033
+ registry_json_header(w, action, REGISTRY_STATUS_DISABLED);
1034
1035
- buffer_sprintf(w->response.data, ",\n\t\"registry\": \"%s\"",
1036
- registry.registry_to_announce);
1035
+ buffer_sprintf(w->response.data, ",\n\t\"registry\": \"%s\"",
1036
+ registry.registry_to_announce);
1037
1038
- registry_json_footer(w);
1039
- return 200;
1038
+ registry_json_footer(w);
1039
+ return 200;
1040
}
1041
1042
// structure used be the callbacks below
1043
struct registry_json_walk_person_urls_callback {
1044
- PERSON *p;
1045
- MACHINE *m;
1046
- struct web_client *w;
1047
- int count;
1044
+ PERSON *p;
1045
+ MACHINE *m;
1046
+ struct web_client *w;
1047
+ int count;
1048
};
1049
1050
// callback for rendering PERSON_URLs
1051
static inline int registry_json_person_url_callback(void *entry, void *data) {
1052
- PERSON_URL *pu = (PERSON_URL *)entry;
1053
- struct registry_json_walk_person_urls_callback *c = (struct registry_json_walk_person_urls_callback *)data;
1054
- struct web_client *w = c->w;
1052
+ PERSON_URL *pu = (PERSON_URL *)entry;
1053
+ struct registry_json_walk_person_urls_callback *c = (struct registry_json_walk_person_urls_callback *)data;
1054
+ struct web_client *w = c->w;
1055
1056
- if(unlikely(c->count++))
1057
- buffer_strcat(w->response.data, ",");
1056
+ if(unlikely(c->count++))
1057
+ buffer_strcat(w->response.data, ",");
1058
1059
- buffer_sprintf(w->response.data, "\n\t\t[ \"%s\", \"%s\", %u000, %u, \"%s\" ]",
1060
- pu->machine->guid, pu->url->url, pu->last_t, pu->usages, pu->name);
1059
+ buffer_sprintf(w->response.data, "\n\t\t[ \"%s\", \"%s\", %u000, %u, \"%s\" ]",
1060
+ pu->machine->guid, pu->url->url, pu->last_t, pu->usages, pu->name);
1061
1062
- return 1;
1062
+ return 1;
1063
}
1064
1065
// callback for rendering MACHINE_URLs
1066
static inline int registry_json_machine_url_callback(void *entry, void *data) {
1067
- MACHINE_URL *mu = (MACHINE_URL *)entry;
1068
- struct registry_json_walk_person_urls_callback *c = (struct registry_json_walk_person_urls_callback *)data;
1069
- struct web_client *w = c->w;
1070
- MACHINE *m = c->m;
1067
+ MACHINE_URL *mu = (MACHINE_URL *)entry;
1068
+ struct registry_json_walk_person_urls_callback *c = (struct registry_json_walk_person_urls_callback *)data;
1069
+ struct web_client *w = c->w;
1070
+ MACHINE *m = c->m;
1071
1072
- if(unlikely(c->count++))
1073
- buffer_strcat(w->response.data, ",");
1072
+ if(unlikely(c->count++))
1073
+ buffer_strcat(w->response.data, ",");
1074
1075
- buffer_sprintf(w->response.data, "\n\t\t[ \"%s\", \"%s\", %u000, %u ]",
1076
- m->guid, mu->url->url, mu->last_t, mu->usages);
1075
+ buffer_sprintf(w->response.data, "\n\t\t[ \"%s\", \"%s\", %u000, %u ]",
1076
+ m->guid, mu->url->url, mu->last_t, mu->usages);
1077
1078
- return 1;
1078
+ return 1;
1079
}
1080
1081
1082
// the main method for registering an access
1083
int registry_request_access_json(struct web_client *w, char *person_guid, char *machine_guid, char *url, char *name, time_t when) {
1084
- if(!registry.enabled)
1085
- return registry_json_disabled(w, "access");
1084
+ if(!registry.enabled)
1085
+ return registry_json_disabled(w, "access");
1086
1087
- PERSON *p = registry_request_access(person_guid, machine_guid, url, name, when);
1088
- if(!p) {
1089
- registry_json_header(w, "access", REGISTRY_STATUS_FAILED);
1090
- registry_json_footer(w);
1091
- return 412;
1092
- }
1087
+ PERSON *p = registry_request_access(person_guid, machine_guid, url, name, when);
1088
+ if(!p) {
1089
+ registry_json_header(w, "access", REGISTRY_STATUS_FAILED);
1090
+ registry_json_footer(w);
1091
+ return 412;
1092
+ }
1093
1094
- // set the cookie
1095
- registry_set_person_cookie(w, p);
1094
+ // set the cookie
1095
+ registry_set_person_cookie(w, p);
1096
1097
- // generate the response
1098
- registry_json_header(w, "access", REGISTRY_STATUS_OK);
1097
+ // generate the response
1098
+ registry_json_header(w, "access", REGISTRY_STATUS_OK);
1099
1100
- buffer_sprintf(w->response.data, ",\n\t\"person_guid\": \"%s\",\n\t\"urls\": [", p->guid);
1101
- struct registry_json_walk_person_urls_callback c = { p, NULL, w, 0 };
1102
- dictionary_get_all(p->urls, registry_json_person_url_callback, &c);
1103
- buffer_strcat(w->response.data, "\n\t]\n");
1100
+ buffer_sprintf(w->response.data, ",\n\t\"person_guid\": \"%s\",\n\t\"urls\": [", p->guid);
1101
+ struct registry_json_walk_person_urls_callback c = { p, NULL, w, 0 };
1102
+ dictionary_get_all(p->urls, registry_json_person_url_callback, &c);
1103
+ buffer_strcat(w->response.data, "\n\t]\n");
1104
1105
- registry_json_footer(w);
1106
- return 200;
1105
+ registry_json_footer(w);
1106
+ return 200;
1107
}
1108
1109
// the main method for deleting a URL from a person
1110
int registry_request_delete_json(struct web_client *w, char *person_guid, char *machine_guid, char *url, char *delete_url, time_t when) {
1111
- if(!registry.enabled)
1112
- return registry_json_disabled(w, "delete");
1111
+ if(!registry.enabled)
1112
+ return registry_json_disabled(w, "delete");
1113
1114
- PERSON *p = registry_request_delete(person_guid, machine_guid, url, delete_url, when);
1115
- if(!p) {
1116
- registry_json_header(w, "delete", REGISTRY_STATUS_FAILED);
1117
- registry_json_footer(w);
1118
- return 412;
1119
- }
1114
+ PERSON *p = registry_request_delete(person_guid, machine_guid, url, delete_url, when);
1115
+ if(!p) {
1116
+ registry_json_header(w, "delete", REGISTRY_STATUS_FAILED);
1117
+ registry_json_footer(w);
1118
+ return 412;
1119
+ }
1120
1121
- // generate the response
1122
- registry_json_header(w, "delete", REGISTRY_STATUS_OK);
1123
- registry_json_footer(w);
1124
- return 200;
1121
+ // generate the response
1122
+ registry_json_header(w, "delete", REGISTRY_STATUS_OK);
1123
+ registry_json_footer(w);
1124
+ return 200;
1125
}
1126
1127
// the main method for searching the URLs of a netdata
1128
int registry_request_search_json(struct web_client *w, char *person_guid, char *machine_guid, char *url, char *request_machine, time_t when) {
1129
- if(!registry.enabled)
1130
- return registry_json_disabled(w, "search");
1129
+ if(!registry.enabled)
1130
+ return registry_json_disabled(w, "search");
1131
1132
- MACHINE *m = registry_request_machine(person_guid, machine_guid, url, request_machine, when);
1133
- if(!m) {
1134
- registry_json_header(w, "search", REGISTRY_STATUS_FAILED);
1135
- registry_json_footer(w);
1136
- return 404;
1137
- }
1132
+ MACHINE *m = registry_request_machine(person_guid, machine_guid, url, request_machine, when);
1133
+ if(!m) {
1134
+ registry_json_header(w, "search", REGISTRY_STATUS_FAILED);
1135
+ registry_json_footer(w);
1136
+ return 404;
1137
+ }
1138
1139
- registry_json_header(w, "search", REGISTRY_STATUS_OK);
1139
+ registry_json_header(w, "search", REGISTRY_STATUS_OK);
1140
1141
- buffer_strcat(w->response.data, ",\n\t\"urls\": [");
1142
- struct registry_json_walk_person_urls_callback c = { NULL, m, w, 0 };
1143
- dictionary_get_all(m->urls, registry_json_machine_url_callback, &c);
1144
- buffer_strcat(w->response.data, "\n\t]\n");
1141
+ buffer_strcat(w->response.data, ",\n\t\"urls\": [");
1142
+ struct registry_json_walk_person_urls_callback c = { NULL, m, w, 0 };
1143
+ dictionary_get_all(m->urls, registry_json_machine_url_callback, &c);
1144
+ buffer_strcat(w->response.data, "\n\t]\n");
1145
1146
- registry_json_footer(w);
1147
- return 200;
1146
+ registry_json_footer(w);
1147
+ return 200;
1148
}
1149
1150
// structure used be the callbacks below
1151
struct registry_person_url_callback_verify_machine_exists_data {
1152
- MACHINE *m;
1153
- int count;
1152
+ MACHINE *m;
1153
+ int count;
1154
};
1155
1156
int registry_person_url_callback_verify_machine_exists(void *entry, void *data) {
1157
- struct registry_person_url_callback_verify_machine_exists_data *d = (struct registry_person_url_callback_verify_machine_exists_data *)data;
1158
- PERSON_URL *pu = (PERSON_URL *)entry;
1159
- MACHINE *m = d->m;
1157
+ struct registry_person_url_callback_verify_machine_exists_data *d = (struct registry_person_url_callback_verify_machine_exists_data *)data;
1158
+ PERSON_URL *pu = (PERSON_URL *)entry;
1159
+ MACHINE *m = d->m;
1160
1161
- if(pu->machine == m)
1162
- d->count++;
1161
+ if(pu->machine == m)
1162
+ d->count++;
1163
1164
- return 0;
1164
+ return 0;
1165
}
1166
1167
// the main method for switching user identity
1168
int registry_request_switch_json(struct web_client *w, char *person_guid, char *machine_guid, char *url, char *new_person_guid, time_t when) {
1169
- (void)url;
1170
- (void)when;
1171
-
1172
- if(!registry.enabled)
1173
- return registry_json_disabled(w, "switch");
1174
-
1175
- PERSON *op = registry_person_find(person_guid);
1176
- if(!op) {
1177
- registry_json_header(w, "switch", REGISTRY_STATUS_FAILED);
1178
- registry_json_footer(w);
1179
- return 430;
1180
- }
1181
-
1182
- PERSON *np = registry_person_find(new_person_guid);
1183
- if(!np) {
1184
- registry_json_header(w, "switch", REGISTRY_STATUS_FAILED);
1185
- registry_json_footer(w);
1186
- return 431;
1187
- }
1188
-
1189
- MACHINE *m = registry_machine_find(machine_guid);
1190
- if(!m) {
1191
- registry_json_header(w, "switch", REGISTRY_STATUS_FAILED);
1192
- registry_json_footer(w);
1193
- return 432;
1194
- }
1195
-
1196
- struct registry_person_url_callback_verify_machine_exists_data data = { m, 0 };
1197
-
1198
- // verify the old person has access to this machine
1199
- dictionary_get_all(op->urls, registry_person_url_callback_verify_machine_exists, &data);
1200
- if(!data.count) {
1201
- registry_json_header(w, "switch", REGISTRY_STATUS_FAILED);
1202
- registry_json_footer(w);
1203
- return 433;
1204
- }
1205
-
1206
- // verify the new person has access to this machine
1207
- data.count = 0;
1208
- dictionary_get_all(np->urls, registry_person_url_callback_verify_machine_exists, &data);
1209
- if(!data.count) {
1210
- registry_json_header(w, "switch", REGISTRY_STATUS_FAILED);
1211
- registry_json_footer(w);
1212
- return 434;
1213
- }
1214
-
1215
- // set the cookie of the new person
1216
- // the user just switched identity
1217
- registry_set_person_cookie(w, np);
1218
-
1219
- // generate the response
1220
- registry_json_header(w, "switch", REGISTRY_STATUS_OK);
1221
- buffer_sprintf(w->response.data, ",\n\t\"person_guid\": \"%s\"", np->guid);
1222
- registry_json_footer(w);
1223
- return 200;
1169
+ (void)url;
1170
+ (void)when;
1171
+
1172
+ if(!registry.enabled)
1173
+ return registry_json_disabled(w, "switch");
1174
+
1175
+ PERSON *op = registry_person_find(person_guid);
1176
+ if(!op) {
1177
+ registry_json_header(w, "switch", REGISTRY_STATUS_FAILED);
1178
+ registry_json_footer(w);
1179
+ return 430;
1180
+ }
1181
+
1182
+ PERSON *np = registry_person_find(new_person_guid);
1183
+ if(!np) {
1184
+ registry_json_header(w, "switch", REGISTRY_STATUS_FAILED);
1185
+ registry_json_footer(w);
1186
+ return 431;
1187
+ }
1188
+
1189
+ MACHINE *m = registry_machine_find(machine_guid);
1190
+ if(!m) {
1191
+ registry_json_header(w, "switch", REGISTRY_STATUS_FAILED);
1192
+ registry_json_footer(w);
1193
+ return 432;
1194
+ }
1195
+
1196
+ struct registry_person_url_callback_verify_machine_exists_data data = { m, 0 };
1197
+
1198
+ // verify the old person has access to this machine
1199
+ dictionary_get_all(op->urls, registry_person_url_callback_verify_machine_exists, &data);
1200
+ if(!data.count) {
1201
+ registry_json_header(w, "switch", REGISTRY_STATUS_FAILED);
1202
+ registry_json_footer(w);
1203
+ return 433;
1204
+ }
1205
+
1206
+ // verify the new person has access to this machine
1207
+ data.count = 0;
1208
+ dictionary_get_all(np->urls, registry_person_url_callback_verify_machine_exists, &data);
1209
+ if(!data.count) {
1210
+ registry_json_header(w, "switch", REGISTRY_STATUS_FAILED);
1211
+ registry_json_footer(w);
1212
+ return 434;
1213
+ }
1214
+
1215
+ // set the cookie of the new person
1216
+ // the user just switched identity
1217
+ registry_set_person_cookie(w, np);
1218
+
1219
+ // generate the response
1220
+ registry_json_header(w, "switch", REGISTRY_STATUS_OK);
1221
+ buffer_sprintf(w->response.data, ",\n\t\"person_guid\": \"%s\"", np->guid);
1222
+ registry_json_footer(w);
1223
+ return 200;
1224
}
1225
1226
@@ -1228,47 +1228,47 @@ int registry_request_switch_json(struct web_client *w, char *person_guid, char *
1228
// REGISTRY THIS MACHINE UNIQUE ID
1229
1230
char *registry_get_this_machine_guid(void) {
1231
- if(likely(registry.machine_guid[0]))
1232
- return registry.machine_guid;
1231
+ if(likely(registry.machine_guid[0]))
1232
+ return registry.machine_guid;
1233
1234
- // read it from disk
1235
- int fd = open(registry.machine_guid_filename, O_RDONLY);
1236
- if(fd != -1) {
1237
- char buf[36 + 1];
1238
- if(read(fd, buf, 36) != 36)
1239
- error("Failed to read machine GUID from '%s'", registry.machine_guid_filename);
1240
- else {
1241
- buf[36] = '\0';
1242
- if(registry_regenerate_guid(buf, registry.machine_guid) == -1) {
1243
- error("Failed to validate machine GUID '%s' from '%s'. Ignoring it - this might mean this netdata will appear as duplicate in the registry.",
1244
- buf, registry.machine_guid_filename);
1234
+ // read it from disk
1235
+ int fd = open(registry.machine_guid_filename, O_RDONLY);
1236
+ if(fd != -1) {
1237
+ char buf[36 + 1];
1238
+ if(read(fd, buf, 36) != 36)
1239
+ error("Failed to read machine GUID from '%s'", registry.machine_guid_filename);
1240
+ else {
1241
+ buf[36] = '\0';
1242
+ if(registry_regenerate_guid(buf, registry.machine_guid) == -1) {
1243
+ error("Failed to validate machine GUID '%s' from '%s'. Ignoring it - this might mean this netdata will appear as duplicate in the registry.",
1244
+ buf, registry.machine_guid_filename);
1245
1246
- registry.machine_guid[0] = '\0';
1247
- }
1248
- }
1249
- close(fd);
1250
- }
1246
+ registry.machine_guid[0] = '\0';
1247
+ }
1248
+ }
1249
+ close(fd);
1250
+ }
1251
1252
- // generate a new one?
1253
- if(!registry.machine_guid[0]) {
1254
- uuid_t uuid;
1252
+ // generate a new one?
1253
+ if(!registry.machine_guid[0]) {
1254
+ uuid_t uuid;
1255
1256
- uuid_generate_time(uuid);
1257
- uuid_unparse_lower(uuid, registry.machine_guid);
1258
- registry.machine_guid[36] = '\0';
1256
+ uuid_generate_time(uuid);
1257
+ uuid_unparse_lower(uuid, registry.machine_guid);
1258
+ registry.machine_guid[36] = '\0';
1259
1260
- // save it
1261
- fd = open(registry.machine_guid_filename, O_WRONLY|O_CREAT|O_TRUNC, 444);
1262
- if(fd == -1)
1263
- fatal("Cannot create unique machine id file '%s'. Please fix this.", registry.machine_guid_filename);
1260
+ // save it
1261
+ fd = open(registry.machine_guid_filename, O_WRONLY|O_CREAT|O_TRUNC, 444);
1262
+ if(fd == -1)
1263
+ fatal("Cannot create unique machine id file '%s'. Please fix this.", registry.machine_guid_filename);
1264
1265
- if(write(fd, registry.machine_guid, 36) != 36)
1266
- fatal("Cannot write the unique machine id file '%s'. Please fix this.", registry.machine_guid_filename);
1265
+ if(write(fd, registry.machine_guid, 36) != 36)
1266
+ fatal("Cannot write the unique machine id file '%s'. Please fix this.", registry.machine_guid_filename);
1267
1268
- close(fd);
1269
- }
1268
+ close(fd);
1269
+ }
1270
1271
- return registry.machine_guid;
1271
+ return registry.machine_guid;
1272
}
1273
1274
@@ -1276,560 +1276,560 @@ char *registry_get_this_machine_guid(void) {
1276
// REGISTRY LOAD/SAVE
1277
1278
int registry_machine_save_url(void *entry, void *file) {
1279
- MACHINE_URL *mu = entry;
1280
- FILE *fp = file;
1279
+ MACHINE_URL *mu = entry;
1280
+ FILE *fp = file;
1281
1282
- debug(D_REGISTRY, "Registry: registry_machine_save_url('%s')", mu->url->url);
1282
+ debug(D_REGISTRY, "Registry: registry_machine_save_url('%s')", mu->url->url);
1283
1284
- int ret = fprintf(fp, "V\t%08x\t%08x\t%08x\t%02x\t%s\n",
1285
- mu->first_t,
1286
- mu->last_t,
1287
- mu->usages,
1288
- mu->flags,
1289
- mu->url->url
1290
- );
1284
+ int ret = fprintf(fp, "V\t%08x\t%08x\t%08x\t%02x\t%s\n",
1285
+ mu->first_t,
1286
+ mu->last_t,
1287
+ mu->usages,
1288
+ mu->flags,
1289
+ mu->url->url
1290
+ );
1291
1292
- // error handling is done at registry_save()
1292
+ // error handling is done at registry_save()
1293
1294
- return ret;
1294
+ return ret;
1295
}
1296
1297
int registry_machine_save(void *entry, void *file) {
1298
- MACHINE *m = entry;
1299
- FILE *fp = file;
1298
+ MACHINE *m = entry;
1299
+ FILE *fp = file;
1300
1301
- debug(D_REGISTRY, "Registry: registry_machine_save('%s')", m->guid);
1301
+ debug(D_REGISTRY, "Registry: registry_machine_save('%s')", m->guid);
1302
1303
- int ret = fprintf(fp, "M\t%08x\t%08x\t%08x\t%s\n",
1304
- m->first_t,
1305
- m->last_t,
1306
- m->usages,
1307
- m->guid
1308
- );
1303
+ int ret = fprintf(fp, "M\t%08x\t%08x\t%08x\t%s\n",
1304
+ m->first_t,
1305
+ m->last_t,
1306
+ m->usages,
1307
+ m->guid
1308
+ );
1309
1310
- if(ret >= 0) {
1311
- int ret2 = dictionary_get_all(m->urls, registry_machine_save_url, fp);
1312
- if(ret2 < 0) return ret2;
1313
- ret += ret2;
1314
- }
1310
+ if(ret >= 0) {
1311
+ int ret2 = dictionary_get_all(m->urls, registry_machine_save_url, fp);
1312
+ if(ret2 < 0) return ret2;
1313
+ ret += ret2;
1314
+ }
1315
1316
- // error handling is done at registry_save()
1316
+ // error handling is done at registry_save()
1317
1318
- return ret;
1318
+ return ret;
1319
}
1320
1321
static inline int registry_person_save_url(void *entry, void *file) {
1322
- PERSON_URL *pu = entry;
1323
- FILE *fp = file;
1322
+ PERSON_URL *pu = entry;
1323
+ FILE *fp = file;
1324
1325
- debug(D_REGISTRY, "Registry: registry_person_save_url('%s')", pu->url->url);
1325
+ debug(D_REGISTRY, "Registry: registry_person_save_url('%s')", pu->url->url);
1326
1327
- int ret = fprintf(fp, "U\t%08x\t%08x\t%08x\t%02x\t%s\t%s\t%s\n",
1328
- pu->first_t,
1329
- pu->last_t,
1330
- pu->usages,
1331
- pu->flags,
1332
- pu->machine->guid,
1333
- pu->name,
1334
- pu->url->url
1335
- );
1327
+ int ret = fprintf(fp, "U\t%08x\t%08x\t%08x\t%02x\t%s\t%s\t%s\n",
1328
+ pu->first_t,
1329
+ pu->last_t,
1330
+ pu->usages,
1331
+ pu->flags,
1332
+ pu->machine->guid,
1333
+ pu->name,
1334
+ pu->url->url
1335
+ );
1336
1337
- // error handling is done at registry_save()
1337
+ // error handling is done at registry_save()
1338
1339
- return ret;
1339
+ return ret;
1340
}
1341
1342
static inline int registry_person_save(void *entry, void *file) {
1343
- PERSON *p = entry;
1344
- FILE *fp = file;
1343
+ PERSON *p = entry;
1344
+ FILE *fp = file;
1345
1346
- debug(D_REGISTRY, "Registry: registry_person_save('%s')", p->guid);
1346
+ debug(D_REGISTRY, "Registry: registry_person_save('%s')", p->guid);
1347
1348
- int ret = fprintf(fp, "P\t%08x\t%08x\t%08x\t%s\n",
1349
- p->first_t,
1350
- p->last_t,
1351
- p->usages,
1352
- p->guid
1353
- );
1348
+ int ret = fprintf(fp, "P\t%08x\t%08x\t%08x\t%s\n",
1349
+ p->first_t,
1350
+ p->last_t,
1351
+ p->usages,
1352
+ p->guid
1353
+ );
1354
1355
- if(ret >= 0) {
1356
- int ret2 = dictionary_get_all(p->urls, registry_person_save_url, fp);
1357
- if (ret2 < 0) return ret2;
1358
- ret += ret2;
1359
- }
1355
+ if(ret >= 0) {
1356
+ int ret2 = dictionary_get_all(p->urls, registry_person_save_url, fp);
1357
+ if (ret2 < 0) return ret2;
1358
+ ret += ret2;
1359
+ }
1360
1361
- // error handling is done at registry_save()
1361
+ // error handling is done at registry_save()
1362
1363
- return ret;
1363
+ return ret;
1364
}
1365
1366
int registry_save(void) {
1367
- if(!registry.enabled) return -1;
1368
-
1369
- // make sure the log is not updated
1370
- registry_log_lock();
1371
-
1372
- if(unlikely(!registry_should_save_db())) {
1373
- registry_log_unlock();
1374
- return -2;
1375
- }
1376
-
1377
- char tmp_filename[FILENAME_MAX + 1];
1378
- char old_filename[FILENAME_MAX + 1];
1379
-
1380
- snprintfz(old_filename, FILENAME_MAX, "%s.old", registry.db_filename);
1381
- snprintfz(tmp_filename, FILENAME_MAX, "%s.tmp", registry.db_filename);
1382
-
1383
- debug(D_REGISTRY, "Registry: Creating file '%s'", tmp_filename);
1384
- FILE *fp = fopen(tmp_filename, "w");
1385
- if(!fp) {
1386
- error("Registry: Cannot create file: %s", tmp_filename);
1387
- registry_log_unlock();
1388
- return -1;
1389
- }
1390
-
1391
- // dictionary_get_all() has its own locking, so this is safe to do
1392
-
1393
- debug(D_REGISTRY, "Saving all machines");
1394
- int bytes1 = dictionary_get_all(registry.machines, registry_machine_save, fp);
1395
- if(bytes1 < 0) {
1396
- error("Registry: Cannot save registry machines - return value %d", bytes1);
1397
- fclose(fp);
1398
- registry_log_unlock();
1399
- return bytes1;
1400
- }
1401
- debug(D_REGISTRY, "Registry: saving machines took %d bytes", bytes1);
1402
-
1403
- debug(D_REGISTRY, "Saving all persons");
1404
- int bytes2 = dictionary_get_all(registry.persons, registry_person_save, fp);
1405
- if(bytes2 < 0) {
1406
- error("Registry: Cannot save registry persons - return value %d", bytes2);
1407
- fclose(fp);
1408
- registry_log_unlock();
1409
- return bytes2;
1410
- }
1411
- debug(D_REGISTRY, "Registry: saving persons took %d bytes", bytes2);
1412
-
1413
- // save the totals
1414
- fprintf(fp, "T\t%016llx\t%016llx\t%016llx\t%016llx\t%016llx\t%016llx\n",
1415
- registry.persons_count,
1416
- registry.machines_count,
1417
- registry.usages_count + 1, // this is required - it is lost on db rotation
1418
- registry.urls_count,
1419
- registry.persons_urls_count,
1420
- registry.machines_urls_count
1421
- );
1422
-
1423
- fclose(fp);
1424
-
1425
- errno = 0;
1426
-
1427
- // remove the .old db
1428
- debug(D_REGISTRY, "Registry: Removing old db '%s'", old_filename);
1429
- if(unlink(old_filename) == -1 && errno != ENOENT)
1430
- error("Registry: cannot remove old registry file '%s'", old_filename);
1431
-
1432
- // rename the db to .old
1433
- debug(D_REGISTRY, "Registry: Link current db '%s' to .old: '%s'", registry.db_filename, old_filename);
1434
- if(link(registry.db_filename, old_filename) == -1 && errno != ENOENT)
1435
- error("Registry: cannot move file '%s' to '%s'. Saving registry DB failed!", tmp_filename, registry.db_filename);
1436
-
1437
- else {
1438
- // remove the database (it is saved in .old)
1439
- debug(D_REGISTRY, "Registry: removing db '%s'", registry.db_filename);
1440
- if (unlink(registry.db_filename) == -1 && errno != ENOENT)
1441
- error("Registry: cannot remove old registry file '%s'", registry.db_filename);
1442
-
1443
- // move the .tmp to make it active
1444
- debug(D_REGISTRY, "Registry: linking tmp db '%s' to active db '%s'", tmp_filename, registry.db_filename);
1445
- if (link(tmp_filename, registry.db_filename) == -1) {
1446
- error("Registry: cannot move file '%s' to '%s'. Saving registry DB failed!", tmp_filename,
1447
- registry.db_filename);
1448
-
1449
- // move the .old back
1450
- debug(D_REGISTRY, "Registry: linking old db '%s' to active db '%s'", old_filename, registry.db_filename);
1451
- if(link(old_filename, registry.db_filename) == -1)
1452
- error("Registry: cannot move file '%s' to '%s'. Recovering the old registry DB failed!", old_filename, registry.db_filename);
1453
- }
1454
- else {
1455
- debug(D_REGISTRY, "Registry: removing tmp db '%s'", tmp_filename);
1456
- if(unlink(tmp_filename) == -1)
1457
- error("Registry: cannot remove tmp registry file '%s'", tmp_filename);
1458
-
1459
- // it has been moved successfully
1460
- // discard the current registry log
1461
- registry_log_recreate_nolock();
1462
-
1463
- registry.log_count = 0;
1464
- }
1465
- }
1466
-
1467
- // continue operations
1468
- registry_log_unlock();
1469
-
1470
- return -1;
1367
+ if(!registry.enabled) return -1;
1368
+
1369
+ // make sure the log is not updated
1370
+ registry_log_lock();
1371
+
1372
+ if(unlikely(!registry_should_save_db())) {
1373
+ registry_log_unlock();
1374
+ return -2;
1375
+ }
1376
+
1377
+ char tmp_filename[FILENAME_MAX + 1];
1378
+ char old_filename[FILENAME_MAX + 1];
1379
+
1380
+ snprintfz(old_filename, FILENAME_MAX, "%s.old", registry.db_filename);
1381
+ snprintfz(tmp_filename, FILENAME_MAX, "%s.tmp", registry.db_filename);
1382
+
1383
+ debug(D_REGISTRY, "Registry: Creating file '%s'", tmp_filename);
1384
+ FILE *fp = fopen(tmp_filename, "w");
1385
+ if(!fp) {
1386
+ error("Registry: Cannot create file: %s", tmp_filename);
1387
+ registry_log_unlock();
1388
+ return -1;
1389
+ }
1390
+
1391
+ // dictionary_get_all() has its own locking, so this is safe to do
1392
+
1393
+ debug(D_REGISTRY, "Saving all machines");
1394
+ int bytes1 = dictionary_get_all(registry.machines, registry_machine_save, fp);
1395
+ if(bytes1 < 0) {
1396
+ error("Registry: Cannot save registry machines - return value %d", bytes1);
1397
+ fclose(fp);
1398
+ registry_log_unlock();
1399
+ return bytes1;
1400
+ }
1401
+ debug(D_REGISTRY, "Registry: saving machines took %d bytes", bytes1);
1402
+
1403
+ debug(D_REGISTRY, "Saving all persons");
1404
+ int bytes2 = dictionary_get_all(registry.persons, registry_person_save, fp);
1405
+ if(bytes2 < 0) {
1406
+ error("Registry: Cannot save registry persons - return value %d", bytes2);
1407
+ fclose(fp);
1408
+ registry_log_unlock();
1409
+ return bytes2;
1410
+ }
1411
+ debug(D_REGISTRY, "Registry: saving persons took %d bytes", bytes2);
1412
+
1413
+ // save the totals
1414
+ fprintf(fp, "T\t%016llx\t%016llx\t%016llx\t%016llx\t%016llx\t%016llx\n",
1415
+ registry.persons_count,
1416
+ registry.machines_count,
1417
+ registry.usages_count + 1, // this is required - it is lost on db rotation
1418
+ registry.urls_count,
1419
+ registry.persons_urls_count,
1420
+ registry.machines_urls_count
1421
+ );
1422
+
1423
+ fclose(fp);
1424
+
1425
+ errno = 0;
1426
+
1427
+ // remove the .old db
1428
+ debug(D_REGISTRY, "Registry: Removing old db '%s'", old_filename);
1429
+ if(unlink(old_filename) == -1 && errno != ENOENT)
1430
+ error("Registry: cannot remove old registry file '%s'", old_filename);
1431
+
1432
+ // rename the db to .old
1433
+ debug(D_REGISTRY, "Registry: Link current db '%s' to .old: '%s'", registry.db_filename, old_filename);
1434
+ if(link(registry.db_filename, old_filename) == -1 && errno != ENOENT)
1435
+ error("Registry: cannot move file '%s' to '%s'. Saving registry DB failed!", tmp_filename, registry.db_filename);
1436
+
1437
+ else {
1438
+ // remove the database (it is saved in .old)
1439
+ debug(D_REGISTRY, "Registry: removing db '%s'", registry.db_filename);
1440
+ if (unlink(registry.db_filename) == -1 && errno != ENOENT)
1441
+ error("Registry: cannot remove old registry file '%s'", registry.db_filename);
1442
+
1443
+ // move the .tmp to make it active
1444
+ debug(D_REGISTRY, "Registry: linking tmp db '%s' to active db '%s'", tmp_filename, registry.db_filename);
1445
+ if (link(tmp_filename, registry.db_filename) == -1) {
1446
+ error("Registry: cannot move file '%s' to '%s'. Saving registry DB failed!", tmp_filename,
1447
+ registry.db_filename);
1448
+
1449
+ // move the .old back
1450
+ debug(D_REGISTRY, "Registry: linking old db '%s' to active db '%s'", old_filename, registry.db_filename);
1451
+ if(link(old_filename, registry.db_filename) == -1)
1452
+ error("Registry: cannot move file '%s' to '%s'. Recovering the old registry DB failed!", old_filename, registry.db_filename);
1453
+ }
1454
+ else {
1455
+ debug(D_REGISTRY, "Registry: removing tmp db '%s'", tmp_filename);
1456
+ if(unlink(tmp_filename) == -1)
1457
+ error("Registry: cannot remove tmp registry file '%s'", tmp_filename);
1458
+
1459
+ // it has been moved successfully
1460
+ // discard the current registry log
1461
+ registry_log_recreate_nolock();
1462
+
1463
+ registry.log_count = 0;
1464
+ }
1465
+ }
1466
+
1467
+ // continue operations
1468
+ registry_log_unlock();
1469
+
1470
+ return -1;
1471
}
1472
1473
static inline size_t registry_load(void) {
1474
- char *s, buf[4096 + 1];
1475
- PERSON *p = NULL;
1476
- MACHINE *m = NULL;
1477
- URL *u = NULL;
1478
- size_t line = 0;
1479
-
1480
- debug(D_REGISTRY, "Registry: loading active db from: '%s'", registry.db_filename);
1481
- FILE *fp = fopen(registry.db_filename, "r");
1482
- if(!fp) {
1483
- error("Registry: cannot open registry file: '%s'", registry.db_filename);
1484
- return 0;
1485
- }
1486
-
1487
- size_t len = 0;
1488
- buf[4096] = '\0';
1489
- while((s = fgets_trim_len(buf, 4096, fp, &len))) {
1490
- line++;
1491
-
1492
- debug(D_REGISTRY, "Registry: read line %zu to length %zu: %s", line, len, s);
1493
- switch(*s) {
1494
- case 'T': // totals
1495
- if(unlikely(len != 103 || s[1] != '\t' || s[18] != '\t' || s[35] != '\t' || s[52] != '\t' || s[69] != '\t' || s[86] != '\t' || s[103] != '\0')) {
1496
- error("Registry totals line %zu is wrong (len = %zu).", line, len);
1497
- continue;
1498
- }
1499
- registry.persons_count = strtoull(&s[2], NULL, 16);
1500
- registry.machines_count = strtoull(&s[19], NULL, 16);
1501
- registry.usages_count = strtoull(&s[36], NULL, 16);
1502
- registry.urls_count = strtoull(&s[53], NULL, 16);
1503
- registry.persons_urls_count = strtoull(&s[70], NULL, 16);
1504
- registry.machines_urls_count = strtoull(&s[87], NULL, 16);
1505
- break;
1506
-
1507
- case 'P': // person
1508
- m = NULL;
1509
- // verify it is valid
1510
- if(unlikely(len != 65 || s[1] != '\t' || s[10] != '\t' || s[19] != '\t' || s[28] != '\t' || s[65] != '\0')) {
1511
- error("Registry person line %zu is wrong (len = %zu).", line, len);
1512
- continue;
1513
- }
1514
-
1515
- s[1] = s[10] = s[19] = s[28] = '\0';
1516
- p = registry_person_allocate(&s[29], strtoul(&s[2], NULL, 16));
1517
- p->last_t = strtoul(&s[11], NULL, 16);
1518
- p->usages = strtoul(&s[20], NULL, 16);
1519
- debug(D_REGISTRY, "Registry loaded person '%s', first: %u, last: %u, usages: %u", p->guid, p->first_t, p->last_t, p->usages);
1520
- break;
1521
-
1522
- case 'M': // machine
1523
- p = NULL;
1524
- // verify it is valid
1525
- if(unlikely(len != 65 || s[1] != '\t' || s[10] != '\t' || s[19] != '\t' || s[28] != '\t' || s[65] != '\0')) {
1526
- error("Registry person line %zu is wrong (len = %zu).", line, len);
1527
- continue;
1528
- }
1529
-
1530
- s[1] = s[10] = s[19] = s[28] = '\0';
1531
- m = registry_machine_allocate(&s[29], strtoul(&s[2], NULL, 16));
1532
- m->last_t = strtoul(&s[11], NULL, 16);
1533
- m->usages = strtoul(&s[20], NULL, 16);
1534
- debug(D_REGISTRY, "Registry loaded machine '%s', first: %u, last: %u, usages: %u", m->guid, m->first_t, m->last_t, m->usages);
1535
- break;
1536
-
1537
- case 'U': // person URL
1538
- if(unlikely(!p)) {
1539
- error("Registry: ignoring line %zu, no person loaded: %s", line, s);
1540
- continue;
1541
- }
1542
-
1543
- // verify it is valid
1544
- if(len < 69 || s[1] != '\t' || s[10] != '\t' || s[19] != '\t' || s[28] != '\t' || s[31] != '\t' || s[68] != '\t') {
1545
- error("Registry person URL line %zu is wrong (len = %zu).", line, len);
1546
- continue;
1547
- }
1548
-
1549
- s[1] = s[10] = s[19] = s[28] = s[31] = s[68] = '\0';
1550
-
1551
- // skip the name to find the url
1552
- char *url = &s[69];
1553
- while(*url && *url != '\t') url++;
1554
- if(!*url) {
1555
- error("Registry person URL line %zu does not have a url.", line);
1556
- continue;
1557
- }
1558
- *url++ = '\0';
1559
-
1560
- u = registry_url_allocate_nolock(url, strlen(url));
1561
-
1562
- time_t first_t = strtoul(&s[2], NULL, 16);
1563
-
1564
- m = registry_machine_find(&s[32]);
1565
- if(!m) m = registry_machine_allocate(&s[32], first_t);
1566
-
1567
- PERSON_URL *pu = registry_person_url_allocate(p, m, u, &s[69], strlen(&s[69]), first_t);
1568
- pu->last_t = strtoul(&s[11], NULL, 16);
1569
- pu->usages = strtoul(&s[20], NULL, 16);
1570
- pu->flags = strtoul(&s[29], NULL, 16);
1571
- debug(D_REGISTRY, "Registry loaded person URL '%s' with name '%s' of machine '%s', first: %u, last: %u, usages: %u, flags: %02x", u->url, pu->name, m->guid, pu->first_t, pu->last_t, pu->usages, pu->flags);
1572
- break;
1573
-
1574
- case 'V': // machine URL
1575
- if(unlikely(!m)) {
1576
- error("Registry: ignoring line %zu, no machine loaded: %s", line, s);
1577
- continue;
1578
- }
1579
-
1580
- // verify it is valid
1581
- if(len < 32 || s[1] != '\t' || s[10] != '\t' || s[19] != '\t' || s[28] != '\t' || s[31] != '\t') {
1582
- error("Registry person URL line %zu is wrong (len = %zu).", line, len);
1583
- continue;
1584
- }
1585
-
1586
- s[1] = s[10] = s[19] = s[28] = s[31] = '\0';
1587
- u = registry_url_allocate_nolock(&s[32], strlen(&s[32]));
1588
-
1589
- MACHINE_URL *mu = registry_machine_url_allocate(m, u, strtoul(&s[2], NULL, 16));
1590
- mu->last_t = strtoul(&s[11], NULL, 16);
1591
- mu->usages = strtoul(&s[20], NULL, 16);
1592
- mu->flags = strtoul(&s[29], NULL, 16);
1593
- debug(D_REGISTRY, "Registry loaded machine URL '%s', machine '%s', first: %u, last: %u, usages: %u, flags: %02x", u->url, m->guid, mu->first_t, mu->last_t, mu->usages, mu->flags);
1594
- break;
1595
-
1596
- default:
1597
- error("Registry: ignoring line %zu of filename '%s': %s.", line, registry.db_filename, s);
1598
- break;
1599
- }
1600
- }
1601
- fclose(fp);
1602
-
1603
- return line;
1474
+ char *s, buf[4096 + 1];
1475
+ PERSON *p = NULL;
1476
+ MACHINE *m = NULL;
1477
+ URL *u = NULL;
1478
+ size_t line = 0;
1479
+
1480
+ debug(D_REGISTRY, "Registry: loading active db from: '%s'", registry.db_filename);
1481
+ FILE *fp = fopen(registry.db_filename, "r");
1482
+ if(!fp) {
1483
+ error("Registry: cannot open registry file: '%s'", registry.db_filename);
1484
+ return 0;
1485
+ }
1486
+
1487
+ size_t len = 0;
1488
+ buf[4096] = '\0';
1489
+ while((s = fgets_trim_len(buf, 4096, fp, &len))) {
1490
+ line++;
1491
+
1492
+ debug(D_REGISTRY, "Registry: read line %zu to length %zu: %s", line, len, s);
1493
+ switch(*s) {
1494
+ case 'T': // totals
1495
+ if(unlikely(len != 103 || s[1] != '\t' || s[18] != '\t' || s[35] != '\t' || s[52] != '\t' || s[69] != '\t' || s[86] != '\t' || s[103] != '\0')) {
1496
+ error("Registry totals line %zu is wrong (len = %zu).", line, len);
1497
+ continue;
1498
+ }
1499
+ registry.persons_count = strtoull(&s[2], NULL, 16);
1500
+ registry.machines_count = strtoull(&s[19], NULL, 16);
1501
+ registry.usages_count = strtoull(&s[36], NULL, 16);
1502
+ registry.urls_count = strtoull(&s[53], NULL, 16);
1503
+ registry.persons_urls_count = strtoull(&s[70], NULL, 16);
1504
+ registry.machines_urls_count = strtoull(&s[87], NULL, 16);
1505
+ break;
1506
+
1507
+ case 'P': // person
1508
+ m = NULL;
1509
+ // verify it is valid
1510
+ if(unlikely(len != 65 || s[1] != '\t' || s[10] != '\t' || s[19] != '\t' || s[28] != '\t' || s[65] != '\0')) {
1511
+ error("Registry person line %zu is wrong (len = %zu).", line, len);
1512
+ continue;
1513
+ }
1514
+
1515
+ s[1] = s[10] = s[19] = s[28] = '\0';
1516
+ p = registry_person_allocate(&s[29], strtoul(&s[2], NULL, 16));
1517
+ p->last_t = strtoul(&s[11], NULL, 16);
1518
+ p->usages = strtoul(&s[20], NULL, 16);
1519
+ debug(D_REGISTRY, "Registry loaded person '%s', first: %u, last: %u, usages: %u", p->guid, p->first_t, p->last_t, p->usages);
1520
+ break;
1521
+
1522
+ case 'M': // machine
1523
+ p = NULL;
1524
+ // verify it is valid
1525
+ if(unlikely(len != 65 || s[1] != '\t' || s[10] != '\t' || s[19] != '\t' || s[28] != '\t' || s[65] != '\0')) {
1526
+ error("Registry person line %zu is wrong (len = %zu).", line, len);
1527
+ continue;
1528
+ }
1529
+
1530
+ s[1] = s[10] = s[19] = s[28] = '\0';
1531
+ m = registry_machine_allocate(&s[29], strtoul(&s[2], NULL, 16));
1532
+ m->last_t = strtoul(&s[11], NULL, 16);
1533
+ m->usages = strtoul(&s[20], NULL, 16);
1534
+ debug(D_REGISTRY, "Registry loaded machine '%s', first: %u, last: %u, usages: %u", m->guid, m->first_t, m->last_t, m->usages);
1535
+ break;
1536
+
1537
+ case 'U': // person URL
1538
+ if(unlikely(!p)) {
1539
+ error("Registry: ignoring line %zu, no person loaded: %s", line, s);
1540
+ continue;
1541
+ }
1542
+
1543
+ // verify it is valid
1544
+ if(len < 69 || s[1] != '\t' || s[10] != '\t' || s[19] != '\t' || s[28] != '\t' || s[31] != '\t' || s[68] != '\t') {
1545
+ error("Registry person URL line %zu is wrong (len = %zu).", line, len);
1546
+ continue;
1547
+ }
1548
+
1549
+ s[1] = s[10] = s[19] = s[28] = s[31] = s[68] = '\0';
1550
+
1551
+ // skip the name to find the url
1552
+ char *url = &s[69];
1553
+ while(*url && *url != '\t') url++;
1554
+ if(!*url) {
1555
+ error("Registry person URL line %zu does not have a url.", line);
1556
+ continue;
1557
+ }
1558
+ *url++ = '\0';
1559
+
1560
+ u = registry_url_allocate_nolock(url, strlen(url));
1561
+
1562
+ time_t first_t = strtoul(&s[2], NULL, 16);
1563
+
1564
+ m = registry_machine_find(&s[32]);
1565
+ if(!m) m = registry_machine_allocate(&s[32], first_t);
1566
+
1567
+ PERSON_URL *pu = registry_person_url_allocate(p, m, u, &s[69], strlen(&s[69]), first_t);
1568
+ pu->last_t = strtoul(&s[11], NULL, 16);
1569
+ pu->usages = strtoul(&s[20], NULL, 16);
1570
+ pu->flags = strtoul(&s[29], NULL, 16);
1571
+ debug(D_REGISTRY, "Registry loaded person URL '%s' with name '%s' of machine '%s', first: %u, last: %u, usages: %u, flags: %02x", u->url, pu->name, m->guid, pu->first_t, pu->last_t, pu->usages, pu->flags);
1572
+ break;
1573
+
1574
+ case 'V': // machine URL
1575
+ if(unlikely(!m)) {
1576
+ error("Registry: ignoring line %zu, no machine loaded: %s", line, s);
1577
+ continue;
1578
+ }
1579
+
1580
+ // verify it is valid
1581
+ if(len < 32 || s[1] != '\t' || s[10] != '\t' || s[19] != '\t' || s[28] != '\t' || s[31] != '\t') {
1582
+ error("Registry person URL line %zu is wrong (len = %zu).", line, len);
1583
+ continue;
1584
+ }
1585
+
1586
+ s[1] = s[10] = s[19] = s[28] = s[31] = '\0';
1587
+ u = registry_url_allocate_nolock(&s[32], strlen(&s[32]));
1588
+
1589
+ MACHINE_URL *mu = registry_machine_url_allocate(m, u, strtoul(&s[2], NULL, 16));
1590
+ mu->last_t = strtoul(&s[11], NULL, 16);
1591
+ mu->usages = strtoul(&s[20], NULL, 16);
1592
+ mu->flags = strtoul(&s[29], NULL, 16);
1593
+ debug(D_REGISTRY, "Registry loaded machine URL '%s', machine '%s', first: %u, last: %u, usages: %u, flags: %02x", u->url, m->guid, mu->first_t, mu->last_t, mu->usages, mu->flags);
1594
+ break;
1595
+
1596
+ default:
1597
+ error("Registry: ignoring line %zu of filename '%s': %s.", line, registry.db_filename, s);
1598
+ break;
1599
+ }
1600
+ }
1601
+ fclose(fp);
1602
+
1603
+ return line;
1604
}
1605
1606
// ----------------------------------------------------------------------------
1607
// REGISTRY
1608
1609
int registry_init(void) {
1610
- char filename[FILENAME_MAX + 1];
1611
-
1612
- // registry enabled?
1613
- registry.enabled = config_get_boolean("registry", "enabled", 0);
1614
-
1615
- if(mkdir(VARLIB_DIR, 0755) == -1 && errno != EEXIST)
1616
- error("Cannot create directory '" VARLIB_DIR "'");
1617
-
1618
- // pathnames
1619
- registry.pathname = config_get("registry", "registry db directory", VARLIB_DIR "/registry");
1620
- if(mkdir(registry.pathname, 0755) == -1 && errno != EEXIST) {
1621
- error("Cannot create directory '%s'. Registry disabled.", registry.pathname);
1622
- registry.enabled = 0;
1623
- return -1;
1624
- }
1625
-
1626
- // filenames
1627
- snprintfz(filename, FILENAME_MAX, "%s/netdata.public.unique.id", registry.pathname);
1628
- registry.machine_guid_filename = config_get("registry", "netdata unique id file", filename);
1629
- registry_get_this_machine_guid();
1630
-
1631
- snprintfz(filename, FILENAME_MAX, "%s/registry.db", registry.pathname);
1632
- registry.db_filename = config_get("registry", "registry db file", filename);
1633
-
1634
- snprintfz(filename, FILENAME_MAX, "%s/registry-log.db", registry.pathname);
1635
- registry.log_filename = config_get("registry", "registry log file", filename);
1636
-
1637
- // configuration options
1638
- registry.save_registry_every_entries = config_get_number("registry", "registry save db every new entries", 1000000);
1639
- registry.persons_expiration = config_get_number("registry", "registry expire idle persons days", 365) * 86400;
1640
- registry.registry_domain = config_get("registry", "registry domain", "");
1641
- registry.registry_to_announce = config_get("registry", "registry to announce", "https://registry.my-netdata.io");
1642
- registry.hostname = config_get("registry", "registry hostname", config_get("global", "hostname", hostname));
1643
- registry.verify_cookies_redirects = config_get_boolean("registry", "verify browser cookies support", 1);
1644
-
1645
- registry.max_url_length = config_get_number("registry", "max URL length", 1024);
1646
- if(registry.max_url_length < 10) {
1647
- registry.max_url_length = 10;
1648
- config_set_number("registry", "max URL length", registry.max_url_length);
1649
- }
1650
-
1651
- registry.max_name_length = config_get_number("registry", "max URL name length", 50);
1652
- if(registry.max_name_length < 10) {
1653
- registry.max_name_length = 10;
1654
- config_set_number("registry", "max URL name length", registry.max_name_length);
1655
- }
1656
-
1657
- // initialize entries counters
1658
- registry.persons_count = 0;
1659
- registry.machines_count = 0;
1660
- registry.usages_count = 0;
1661
- registry.urls_count = 0;
1662
- registry.persons_urls_count = 0;
1663
- registry.machines_urls_count = 0;
1664
-
1665
- // initialize memory counters
1666
- registry.persons_memory = 0;
1667
- registry.machines_memory = 0;
1668
- registry.urls_memory = 0;
1669
- registry.persons_urls_memory = 0;
1670
- registry.machines_urls_memory = 0;
1671
-
1672
- // initialize locks
1673
- pthread_mutex_init(®istry.persons_lock, NULL);
1674
- pthread_mutex_init(®istry.machines_lock, NULL);
1675
- pthread_mutex_init(®istry.urls_lock, NULL);
1676
- pthread_mutex_init(®istry.person_urls_lock, NULL);
1677
- pthread_mutex_init(®istry.machine_urls_lock, NULL);
1678
-
1679
- // create dictionaries
1680
- registry.persons = dictionary_create(DICTIONARY_FLAGS);
1681
- registry.machines = dictionary_create(DICTIONARY_FLAGS);
1682
- registry.urls = dictionary_create(DICTIONARY_FLAGS);
1683
-
1684
- // load the registry database
1685
- if(registry.enabled) {
1686
- registry_log_open_nolock();
1687
- registry_load();
1688
- registry_log_load();
1689
- }
1690
-
1691
- return 0;
1610
+ char filename[FILENAME_MAX + 1];
1611
+
1612
+ // registry enabled?
1613
+ registry.enabled = config_get_boolean("registry", "enabled", 0);
1614
+
1615
+ if(mkdir(VARLIB_DIR, 0755) == -1 && errno != EEXIST)
1616
+ error("Cannot create directory '" VARLIB_DIR "'");
1617
+
1618
+ // pathnames
1619
+ registry.pathname = config_get("registry", "registry db directory", VARLIB_DIR "/registry");
1620
+ if(mkdir(registry.pathname, 0755) == -1 && errno != EEXIST) {
1621
+ error("Cannot create directory '%s'. Registry disabled.", registry.pathname);
1622
+ registry.enabled = 0;
1623
+ return -1;
1624
+ }
1625
+
1626
+ // filenames
1627
+ snprintfz(filename, FILENAME_MAX, "%s/netdata.public.unique.id", registry.pathname);
1628
+ registry.machine_guid_filename = config_get("registry", "netdata unique id file", filename);
1629
+ registry_get_this_machine_guid();
1630
+
1631
+ snprintfz(filename, FILENAME_MAX, "%s/registry.db", registry.pathname);
1632
+ registry.db_filename = config_get("registry", "registry db file", filename);
1633
+
1634
+ snprintfz(filename, FILENAME_MAX, "%s/registry-log.db", registry.pathname);
1635
+ registry.log_filename = config_get("registry", "registry log file", filename);
1636
+
1637
+ // configuration options
1638
+ registry.save_registry_every_entries = config_get_number("registry", "registry save db every new entries", 1000000);
1639
+ registry.persons_expiration = config_get_number("registry", "registry expire idle persons days", 365) * 86400;
1640
+ registry.registry_domain = config_get("registry", "registry domain", "");
1641
+ registry.registry_to_announce = config_get("registry", "registry to announce", "https://registry.my-netdata.io");
1642
+ registry.hostname = config_get("registry", "registry hostname", config_get("global", "hostname", hostname));
1643
+ registry.verify_cookies_redirects = config_get_boolean("registry", "verify browser cookies support", 1);
1644
+
1645
+ registry.max_url_length = config_get_number("registry", "max URL length", 1024);
1646
+ if(registry.max_url_length < 10) {
1647
+ registry.max_url_length = 10;
1648
+ config_set_number("registry", "max URL length", registry.max_url_length);
1649
+ }
1650
+
1651
+ registry.max_name_length = config_get_number("registry", "max URL name length", 50);
1652
+ if(registry.max_name_length < 10) {
1653
+ registry.max_name_length = 10;
1654
+ config_set_number("registry", "max URL name length", registry.max_name_length);
1655
+ }
1656
+
1657
+ // initialize entries counters
1658
+ registry.persons_count = 0;
1659
+ registry.machines_count = 0;
1660
+ registry.usages_count = 0;
1661
+ registry.urls_count = 0;
1662
+ registry.persons_urls_count = 0;
1663
+ registry.machines_urls_count = 0;
1664
+
1665
+ // initialize memory counters
1666
+ registry.persons_memory = 0;
1667
+ registry.machines_memory = 0;
1668
+ registry.urls_memory = 0;
1669
+ registry.persons_urls_memory = 0;
1670
+ registry.machines_urls_memory = 0;
1671
+
1672
+ // initialize locks
1673
+ pthread_mutex_init(®istry.persons_lock, NULL);
1674
+ pthread_mutex_init(®istry.machines_lock, NULL);
1675
+ pthread_mutex_init(®istry.urls_lock, NULL);
1676
+ pthread_mutex_init(®istry.person_urls_lock, NULL);
1677
+ pthread_mutex_init(®istry.machine_urls_lock, NULL);
1678
+
1679
+ // create dictionaries
1680
+ registry.persons = dictionary_create(DICTIONARY_FLAGS);
1681
+ registry.machines = dictionary_create(DICTIONARY_FLAGS);
1682
+ registry.urls = dictionary_create(DICTIONARY_FLAGS);
1683
+
1684
+ // load the registry database
1685
+ if(registry.enabled) {
1686
+ registry_log_open_nolock();
1687
+ registry_load();
1688
+ registry_log_load();
1689
+ }
1690
+
1691
+ return 0;
1692
}
1693
1694
void registry_free(void) {
1695
- if(!registry.enabled) return;
1695
+ if(!registry.enabled) return;
1696
1697
- // we need to destroy the dictionaries ourselves
1698
- // since the dictionaries use memory we allocated
1697
+ // we need to destroy the dictionaries ourselves
1698
+ // since the dictionaries use memory we allocated
1699
1700
- while(registry.persons->values_index.root) {
1701
- PERSON *p = ((NAME_VALUE *)registry.persons->values_index.root)->value;
1700
+ while(registry.persons->values_index.root) {
1701
+ PERSON *p = ((NAME_VALUE *)registry.persons->values_index.root)->value;
1702
1703
- // fprintf(stderr, "\nPERSON: '%s', first: %u, last: %u, usages: %u\n", p->guid, p->first_t, p->last_t, p->usages);
1703
+ // fprintf(stderr, "\nPERSON: '%s', first: %u, last: %u, usages: %u\n", p->guid, p->first_t, p->last_t, p->usages);
1704
1705
- while(p->urls->values_index.root) {
1706
- PERSON_URL *pu = ((NAME_VALUE *)p->urls->values_index.root)->value;
1705
+ while(p->urls->values_index.root) {
1706
+ PERSON_URL *pu = ((NAME_VALUE *)p->urls->values_index.root)->value;
1707
1708
- // fprintf(stderr, "\tURL: '%s', first: %u, last: %u, usages: %u, flags: 0x%02x\n", pu->url->url, pu->first_t, pu->last_t, pu->usages, pu->flags);
1708
+ // fprintf(stderr, "\tURL: '%s', first: %u, last: %u, usages: %u, flags: 0x%02x\n", pu->url->url, pu->first_t, pu->last_t, pu->usages, pu->flags);
1709
1710
- debug(D_REGISTRY, "Registry: deleting url '%s' from person '%s'", pu->url->url, p->guid);
1711
- dictionary_del(p->urls, pu->url->url);
1710
+ debug(D_REGISTRY, "Registry: deleting url '%s' from person '%s'", pu->url->url, p->guid);
1711
+ dictionary_del(p->urls, pu->url->url);
1712
1713
- debug(D_REGISTRY, "Registry: unlinking url '%s' from person", pu->url->url);
1714
- registry_url_unlink_nolock(pu->url);
1713
+ debug(D_REGISTRY, "Registry: unlinking url '%s' from person", pu->url->url);
1714
+ registry_url_unlink_nolock(pu->url);
1715
1716
- debug(D_REGISTRY, "Registry: freeing person url");
1717
- freez(pu);
1718
- }
1716
+ debug(D_REGISTRY, "Registry: freeing person url");
1717
+ freez(pu);
1718
+ }
1719
1720
- debug(D_REGISTRY, "Registry: deleting person '%s' from persons registry", p->guid);
1721
- dictionary_del(registry.persons, p->guid);
1720
+ debug(D_REGISTRY, "Registry: deleting person '%s' from persons registry", p->guid);
1721
+ dictionary_del(registry.persons, p->guid);
1722
1723
- debug(D_REGISTRY, "Registry: destroying URL dictionary of person '%s'", p->guid);
1724
- dictionary_destroy(p->urls);
1723
+ debug(D_REGISTRY, "Registry: destroying URL dictionary of person '%s'", p->guid);
1724
+ dictionary_destroy(p->urls);
1725
1726
- debug(D_REGISTRY, "Registry: freeing person '%s'", p->guid);
1727
- freez(p);
1728
- }
1726
+ debug(D_REGISTRY, "Registry: freeing person '%s'", p->guid);
1727
+ freez(p);
1728
+ }
1729
1730
- while(registry.machines->values_index.root) {
1731
- MACHINE *m = ((NAME_VALUE *)registry.machines->values_index.root)->value;
1730
+ while(registry.machines->values_index.root) {
1731
+ MACHINE *m = ((NAME_VALUE *)registry.machines->values_index.root)->value;
1732
1733
- // fprintf(stderr, "\nMACHINE: '%s', first: %u, last: %u, usages: %u\n", m->guid, m->first_t, m->last_t, m->usages);
1733
+ // fprintf(stderr, "\nMACHINE: '%s', first: %u, last: %u, usages: %u\n", m->guid, m->first_t, m->last_t, m->usages);
1734
1735
- while(m->urls->values_index.root) {
1736
- MACHINE_URL *mu = ((NAME_VALUE *)m->urls->values_index.root)->value;
1735
+ while(m->urls->values_index.root) {
1736
+ MACHINE_URL *mu = ((NAME_VALUE *)m->urls->values_index.root)->value;
1737
1738
- // fprintf(stderr, "\tURL: '%s', first: %u, last: %u, usages: %u, flags: 0x%02x\n", mu->url->url, mu->first_t, mu->last_t, mu->usages, mu->flags);
1738
+ // fprintf(stderr, "\tURL: '%s', first: %u, last: %u, usages: %u, flags: 0x%02x\n", mu->url->url, mu->first_t, mu->last_t, mu->usages, mu->flags);
1739
1740
- //debug(D_REGISTRY, "Registry: destroying persons dictionary from url '%s'", mu->url->url);
1741
- //dictionary_destroy(mu->persons);
1740
+ //debug(D_REGISTRY, "Registry: destroying persons dictionary from url '%s'", mu->url->url);
1741
+ //dictionary_destroy(mu->persons);
1742
1743
- debug(D_REGISTRY, "Registry: deleting url '%s' from person '%s'", mu->url->url, m->guid);
1744
- dictionary_del(m->urls, mu->url->url);
1743
+ debug(D_REGISTRY, "Registry: deleting url '%s' from person '%s'", mu->url->url, m->guid);
1744
+ dictionary_del(m->urls, mu->url->url);
1745
1746
- debug(D_REGISTRY, "Registry: unlinking url '%s' from machine", mu->url->url);
1747
- registry_url_unlink_nolock(mu->url);
1746
+ debug(D_REGISTRY, "Registry: unlinking url '%s' from machine", mu->url->url);
1747
+ registry_url_unlink_nolock(mu->url);
1748
1749
- debug(D_REGISTRY, "Registry: freeing machine url");
1750
- freez(mu);
1751
- }
1749
+ debug(D_REGISTRY, "Registry: freeing machine url");
1750
+ freez(mu);
1751
+ }
1752
1753
- debug(D_REGISTRY, "Registry: deleting machine '%s' from machines registry", m->guid);
1754
- dictionary_del(registry.machines, m->guid);
1753
+ debug(D_REGISTRY, "Registry: deleting machine '%s' from machines registry", m->guid);
1754
+ dictionary_del(registry.machines, m->guid);
1755
1756
- debug(D_REGISTRY, "Registry: destroying URL dictionary of machine '%s'", m->guid);
1757
- dictionary_destroy(m->urls);
1756
+ debug(D_REGISTRY, "Registry: destroying URL dictionary of machine '%s'", m->guid);
1757
+ dictionary_destroy(m->urls);
1758
1759
- debug(D_REGISTRY, "Registry: freeing machine '%s'", m->guid);
1760
- freez(m);
1761
- }
1759
+ debug(D_REGISTRY, "Registry: freeing machine '%s'", m->guid);
1760
+ freez(m);
1761
+ }
1762
1763
- // and free the memory of remaining dictionary structures
1763
+ // and free the memory of remaining dictionary structures
1764
1765
- debug(D_REGISTRY, "Registry: destroying persons dictionary");
1766
- dictionary_destroy(registry.persons);
1765
+ debug(D_REGISTRY, "Registry: destroying persons dictionary");
1766
+ dictionary_destroy(registry.persons);
1767
1768
- debug(D_REGISTRY, "Registry: destroying machines dictionary");
1769
- dictionary_destroy(registry.machines);
1768
+ debug(D_REGISTRY, "Registry: destroying machines dictionary");
1769
+ dictionary_destroy(registry.machines);
1770
1771
- debug(D_REGISTRY, "Registry: destroying urls dictionary");
1772
- dictionary_destroy(registry.urls);
1771
+ debug(D_REGISTRY, "Registry: destroying urls dictionary");
1772
+ dictionary_destroy(registry.urls);
1773
}
1774
1775
// ----------------------------------------------------------------------------
1776
// STATISTICS
1777
1778
void registry_statistics(void) {
1779
- if(!registry.enabled) return;
1780
-
1781
- static RRDSET *sts = NULL, *stc = NULL, *stm = NULL;
1782
-
1783
- if(!sts) sts = rrdset_find("netdata.registry_sessions");
1784
- if(!sts) {
1785
- sts = rrdset_create("netdata", "registry_sessions", NULL, "registry", NULL, "NetData Registry Sessions", "session", 131000, rrd_update_every, RRDSET_TYPE_LINE);
1786
-
1787
- rrddim_add(sts, "sessions", NULL, 1, 1, RRDDIM_ABSOLUTE);
1788
- }
1789
- else rrdset_next(sts);
1790
-
1791
- rrddim_set(sts, "sessions", registry.usages_count);
1792
- rrdset_done(sts);
1793
-
1794
- // ------------------------------------------------------------------------
1795
-
1796
- if(!stc) stc = rrdset_find("netdata.registry_entries");
1797
- if(!stc) {
1798
- stc = rrdset_create("netdata", "registry_entries", NULL, "registry", NULL, "NetData Registry Entries", "entries", 131100, rrd_update_every, RRDSET_TYPE_LINE);
1799
-
1800
- rrddim_add(stc, "persons", NULL, 1, 1, RRDDIM_ABSOLUTE);
1801
- rrddim_add(stc, "machines", NULL, 1, 1, RRDDIM_ABSOLUTE);
1802
- rrddim_add(stc, "urls", NULL, 1, 1, RRDDIM_ABSOLUTE);
1803
- rrddim_add(stc, "persons_urls", NULL, 1, 1, RRDDIM_ABSOLUTE);
1804
- rrddim_add(stc, "machines_urls", NULL, 1, 1, RRDDIM_ABSOLUTE);
1805
- }
1806
- else rrdset_next(stc);
1807
-
1808
- rrddim_set(stc, "persons", registry.persons_count);
1809
- rrddim_set(stc, "machines", registry.machines_count);
1810
- rrddim_set(stc, "urls", registry.urls_count);
1811
- rrddim_set(stc, "persons_urls", registry.persons_urls_count);
1812
- rrddim_set(stc, "machines_urls", registry.machines_urls_count);
1813
- rrdset_done(stc);
1814
-
1815
- // ------------------------------------------------------------------------
1816
-
1817
- if(!stm) stm = rrdset_find("netdata.registry_mem");
1818
- if(!stm) {
1819
- stm = rrdset_create("netdata", "registry_mem", NULL, "registry", NULL, "NetData Registry Memory", "KB", 131300, rrd_update_every, RRDSET_TYPE_STACKED);
1820
-
1821
- rrddim_add(stm, "persons", NULL, 1, 1024, RRDDIM_ABSOLUTE);
1822
- rrddim_add(stm, "machines", NULL, 1, 1024, RRDDIM_ABSOLUTE);
1823
- rrddim_add(stm, "urls", NULL, 1, 1024, RRDDIM_ABSOLUTE);
1824
- rrddim_add(stm, "persons_urls", NULL, 1, 1024, RRDDIM_ABSOLUTE);
1825
- rrddim_add(stm, "machines_urls", NULL, 1, 1024, RRDDIM_ABSOLUTE);
1826
- }
1827
- else rrdset_next(stm);
1828
-
1829
- rrddim_set(stm, "persons", registry.persons_memory + registry.persons_count * sizeof(NAME_VALUE) + sizeof(DICTIONARY));
1830
- rrddim_set(stm, "machines", registry.machines_memory + registry.machines_count * sizeof(NAME_VALUE) + sizeof(DICTIONARY));
1831
- rrddim_set(stm, "urls", registry.urls_memory + registry.urls_count * sizeof(NAME_VALUE) + sizeof(DICTIONARY));
1832
- rrddim_set(stm, "persons_urls", registry.persons_urls_memory + registry.persons_count * sizeof(DICTIONARY) + registry.persons_urls_count * sizeof(NAME_VALUE));
1833
- rrddim_set(stm, "machines_urls", registry.machines_urls_memory + registry.machines_count * sizeof(DICTIONARY) + registry.machines_urls_count * sizeof(NAME_VALUE));
1834
- rrdset_done(stm);
1779
+ if(!registry.enabled) return;
1780
+
1781
+ static RRDSET *sts = NULL, *stc = NULL, *stm = NULL;
1782
+
1783
+ if(!sts) sts = rrdset_find("netdata.registry_sessions");
1784
+ if(!sts) {
1785
+ sts = rrdset_create("netdata", "registry_sessions", NULL, "registry", NULL, "NetData Registry Sessions", "session", 131000, rrd_update_every, RRDSET_TYPE_LINE);
1786
+
1787
+ rrddim_add(sts, "sessions", NULL, 1, 1, RRDDIM_ABSOLUTE);
1788
+ }
1789
+ else rrdset_next(sts);
1790
+
1791
+ rrddim_set(sts, "sessions", registry.usages_count);
1792
+ rrdset_done(sts);
1793
+
1794
+ // ------------------------------------------------------------------------
1795
+
1796
+ if(!stc) stc = rrdset_find("netdata.registry_entries");
1797
+ if(!stc) {
1798
+ stc = rrdset_create("netdata", "registry_entries", NULL, "registry", NULL, "NetData Registry Entries", "entries", 131100, rrd_update_every, RRDSET_TYPE_LINE);
1799
+
1800
+ rrddim_add(stc, "persons", NULL, 1, 1, RRDDIM_ABSOLUTE);
1801
+ rrddim_add(stc, "machines", NULL, 1, 1, RRDDIM_ABSOLUTE);
1802
+ rrddim_add(stc, "urls", NULL, 1, 1, RRDDIM_ABSOLUTE);
1803
+ rrddim_add(stc, "persons_urls", NULL, 1, 1, RRDDIM_ABSOLUTE);
1804
+ rrddim_add(stc, "machines_urls", NULL, 1, 1, RRDDIM_ABSOLUTE);
1805
+ }
1806
+ else rrdset_next(stc);
1807
+
1808
+ rrddim_set(stc, "persons", registry.persons_count);
1809
+ rrddim_set(stc, "machines", registry.machines_count);
1810
+ rrddim_set(stc, "urls", registry.urls_count);
1811
+ rrddim_set(stc, "persons_urls", registry.persons_urls_count);
1812
+ rrddim_set(stc, "machines_urls", registry.machines_urls_count);
1813
+ rrdset_done(stc);
1814
+
1815
+ // ------------------------------------------------------------------------
1816
+
1817
+ if(!stm) stm = rrdset_find("netdata.registry_mem");
1818
+ if(!stm) {
1819
+ stm = rrdset_create("netdata", "registry_mem", NULL, "registry", NULL, "NetData Registry Memory", "KB", 131300, rrd_update_every, RRDSET_TYPE_STACKED);
1820
+
1821
+ rrddim_add(stm, "persons", NULL, 1, 1024, RRDDIM_ABSOLUTE);
1822
+ rrddim_add(stm, "machines", NULL, 1, 1024, RRDDIM_ABSOLUTE);
1823
+ rrddim_add(stm, "urls", NULL, 1, 1024, RRDDIM_ABSOLUTE);
1824
+ rrddim_add(stm, "persons_urls", NULL, 1, 1024, RRDDIM_ABSOLUTE);
1825
+ rrddim_add(stm, "machines_urls", NULL, 1, 1024, RRDDIM_ABSOLUTE);
1826
+ }
1827
+ else rrdset_next(stm);
1828
+
1829
+ rrddim_set(stm, "persons", registry.persons_memory + registry.persons_count * sizeof(NAME_VALUE) + sizeof(DICTIONARY));
1830
+ rrddim_set(stm, "machines", registry.machines_memory + registry.machines_count * sizeof(NAME_VALUE) + sizeof(DICTIONARY));
1831
+ rrddim_set(stm, "urls", registry.urls_memory + registry.urls_count * sizeof(NAME_VALUE) + sizeof(DICTIONARY));
1832
+ rrddim_set(stm, "persons_urls", registry.persons_urls_memory + registry.persons_count * sizeof(DICTIONARY) + registry.persons_urls_count * sizeof(NAME_VALUE));
1833
+ rrddim_set(stm, "machines_urls", registry.machines_urls_memory + registry.machines_count * sizeof(DICTIONARY) + registry.machines_urls_count * sizeof(NAME_VALUE));
1834
+ rrdset_done(stm);
1835
}
src/rrd.c
+1048
-1048
@@ -22,9 +22,9 @@ static int rrdcontext_compare(void* a, void* b);
22
// RRDHOST
23
24
RRDHOST localhost = {
25
- .hostname = "localhost",
26
- .rrdset_root = NULL,
27
- .rrdset_root_rwlock = PTHREAD_RWLOCK_INITIALIZER,
25
+ .hostname = "localhost",
26
+ .rrdset_root = NULL,
27
+ .rrdset_root_rwlock = PTHREAD_RWLOCK_INITIALIZER,
28
.rrdset_root_index = {
29
{ NULL, rrdset_compare },
30
AVL_LOCK_INITIALIZER
@@ -44,21 +44,21 @@ RRDHOST localhost = {
44
};
45
46
void rrdhost_rwlock(RRDHOST *host) {
47
- pthread_rwlock_wrlock(&host->rrdset_root_rwlock);
47
+ pthread_rwlock_wrlock(&host->rrdset_root_rwlock);
48
}
49
50
void rrdhost_rdlock(RRDHOST *host) {
51
- pthread_rwlock_rdlock(&host->rrdset_root_rwlock);
51
+ pthread_rwlock_rdlock(&host->rrdset_root_rwlock);
52
}
53
54
void rrdhost_unlock(RRDHOST *host) {
55
- pthread_rwlock_unlock(&host->rrdset_root_rwlock);
55
+ pthread_rwlock_unlock(&host->rrdset_root_rwlock);
56
}
57
58
void rrdhost_check_wrlock_int(RRDHOST *host, const char *file, const char *function, const unsigned long line) {
59
- if(pthread_rwlock_tryrdlock(&host->rrdset_root_rwlock) == 0) {
60
- fatal("RRDHOST '%s' should be write-locked, but it is not, at function %s() at line %lu of file '%s'", host->hostname, function, line, file);
61
- }
59
+ if(pthread_rwlock_tryrdlock(&host->rrdset_root_rwlock) == 0) {
60
+ fatal("RRDHOST '%s' should be write-locked, but it is not, at function %s() at line %lu of file '%s'", host->hostname, function, line, file);
61
+ }
62
}
63
64
// ----------------------------------------------------------------------------
@@ -142,20 +142,20 @@ static RRDSET *rrdset_index_find(RRDHOST *host, const char *id, uint32_t hash) {
142
#define rrdset_from_avlname(avlname_ptr) ((RRDSET *)((avlname_ptr) - offsetof(RRDSET, avlname)))
143
144
static int rrdset_compare_name(void* a, void* b) {
145
- RRDSET *A = rrdset_from_avlname(a);
146
- RRDSET *B = rrdset_from_avlname(b);
145
+ RRDSET *A = rrdset_from_avlname(a);
146
+ RRDSET *B = rrdset_from_avlname(b);
147
148
- // fprintf(stderr, "COMPARING: %s with %s\n", A->name, B->name);
148
+ // fprintf(stderr, "COMPARING: %s with %s\n", A->name, B->name);
149
150
- if(A->hash_name < B->hash_name) return -1;
151
- else if(A->hash_name > B->hash_name) return 1;
152
- else return strcmp(A->name, B->name);
150
+ if(A->hash_name < B->hash_name) return -1;
151
+ else if(A->hash_name > B->hash_name) return 1;
152
+ else return strcmp(A->name, B->name);
153
}
154
155
RRDSET *rrdset_index_add_name(RRDHOST *host, RRDSET *st) {
156
void *result;
157
- // fprintf(stderr, "ADDING: %s (name: %s)\n", st->id, st->name);
158
- result = avl_insert_lock(&host->rrdset_root_index_name, (avl *) (&st->avlname));
157
+ // fprintf(stderr, "ADDING: %s (name: %s)\n", st->id, st->name);
158
+ result = avl_insert_lock(&host->rrdset_root_index_name, (avl *) (&st->avlname));
159
if(result) return rrdset_from_avlname(result);
160
return NULL;
161
}
@@ -169,23 +169,23 @@ RRDSET *rrdset_index_del_name(RRDHOST *host, RRDSET *st) {
169
}
170
171
static RRDSET *rrdset_index_find_name(RRDHOST *host, const char *name, uint32_t hash) {
172
- void *result = NULL;
173
- RRDSET tmp;
174
- tmp.name = name;
175
- tmp.hash_name = (hash)?hash:simple_hash(tmp.name);
176
-
177
- // fprintf(stderr, "SEARCHING: %s\n", name);
178
- result = avl_search_lock(&host->rrdset_root_index_name, (avl *) (&(tmp.avlname)));
179
- if(result) {
180
- RRDSET *st = rrdset_from_avlname(result);
181
- if(strcmp(st->magic, RRDSET_MAGIC))
182
- error("Search for RRDSET %s returned an invalid RRDSET %s (name %s)", name, st->id, st->name);
183
-
184
- // fprintf(stderr, "FOUND: %s\n", name);
185
- return rrdset_from_avlname(result);
186
- }
187
- // fprintf(stderr, "NOT FOUND: %s\n", name);
188
- return NULL;
172
+ void *result = NULL;
173
+ RRDSET tmp;
174
+ tmp.name = name;
175
+ tmp.hash_name = (hash)?hash:simple_hash(tmp.name);
176
+
177
+ // fprintf(stderr, "SEARCHING: %s\n", name);
178
+ result = avl_search_lock(&host->rrdset_root_index_name, (avl *) (&(tmp.avlname)));
179
+ if(result) {
180
+ RRDSET *st = rrdset_from_avlname(result);
181
+ if(strcmp(st->magic, RRDSET_MAGIC))
182
+ error("Search for RRDSET %s returned an invalid RRDSET %s (name %s)", name, st->id, st->name);
183
+
184
+ // fprintf(stderr, "FOUND: %s\n", name);
185
+ return rrdset_from_avlname(result);
186
+ }
187
+ // fprintf(stderr, "NOT FOUND: %s\n", name);
188
+ return NULL;
189
}
190
191
@@ -193,20 +193,20 @@ static RRDSET *rrdset_index_find_name(RRDHOST *host, const char *name, uint32_t
193
// RRDDIM index
194
195
static int rrddim_compare(void* a, void* b) {
196
- if(((RRDDIM *)a)->hash < ((RRDDIM *)b)->hash) return -1;
197
- else if(((RRDDIM *)a)->hash > ((RRDDIM *)b)->hash) return 1;
198
- else return strcmp(((RRDDIM *)a)->id, ((RRDDIM *)b)->id);
196
+ if(((RRDDIM *)a)->hash < ((RRDDIM *)b)->hash) return -1;
197
+ else if(((RRDDIM *)a)->hash > ((RRDDIM *)b)->hash) return 1;
198
+ else return strcmp(((RRDDIM *)a)->id, ((RRDDIM *)b)->id);
199
}
200
201
#define rrddim_index_add(st, rd) avl_insert_lock(&((st)->dimensions_index), (avl *)(rd))
202
#define rrddim_index_del(st,rd ) avl_remove_lock(&((st)->dimensions_index), (avl *)(rd))
203
204
static RRDDIM *rrddim_index_find(RRDSET *st, const char *id, uint32_t hash) {
205
- RRDDIM tmp;
206
- strncpyz(tmp.id, id, RRD_ID_LENGTH_MAX);
207
- tmp.hash = (hash)?hash:simple_hash(tmp.id);
205
+ RRDDIM tmp;
206
+ strncpyz(tmp.id, id, RRD_ID_LENGTH_MAX);
207
+ tmp.hash = (hash)?hash:simple_hash(tmp.id);
208
209
- return (RRDDIM *)avl_search_lock(&(st->dimensions_index), (avl *) &tmp);
209
+ return (RRDDIM *)avl_search_lock(&(st->dimensions_index), (avl *) &tmp);
210
}
211
212
// ----------------------------------------------------------------------------
@@ -214,29 +214,29 @@ static RRDDIM *rrddim_index_find(RRDSET *st, const char *id, uint32_t hash) {
214
215
int rrdset_type_id(const char *name)
216
{
217
- if(unlikely(strcmp(name, RRDSET_TYPE_AREA_NAME) == 0)) return RRDSET_TYPE_AREA;
218
- else if(unlikely(strcmp(name, RRDSET_TYPE_STACKED_NAME) == 0)) return RRDSET_TYPE_STACKED;
219
- else if(unlikely(strcmp(name, RRDSET_TYPE_LINE_NAME) == 0)) return RRDSET_TYPE_LINE;
220
- return RRDSET_TYPE_LINE;
217
+ if(unlikely(strcmp(name, RRDSET_TYPE_AREA_NAME) == 0)) return RRDSET_TYPE_AREA;
218
+ else if(unlikely(strcmp(name, RRDSET_TYPE_STACKED_NAME) == 0)) return RRDSET_TYPE_STACKED;
219
+ else if(unlikely(strcmp(name, RRDSET_TYPE_LINE_NAME) == 0)) return RRDSET_TYPE_LINE;
220
+ return RRDSET_TYPE_LINE;
221
}
222
223
const char *rrdset_type_name(int chart_type)
224
{
225
- static char line[] = RRDSET_TYPE_LINE_NAME;
226
- static char area[] = RRDSET_TYPE_AREA_NAME;
227
- static char stacked[] = RRDSET_TYPE_STACKED_NAME;
225
+ static char line[] = RRDSET_TYPE_LINE_NAME;
226
+ static char area[] = RRDSET_TYPE_AREA_NAME;
227
+ static char stacked[] = RRDSET_TYPE_STACKED_NAME;
228
229
- switch(chart_type) {
230
- case RRDSET_TYPE_LINE:
231
- return line;
229
+ switch(chart_type) {
230
+ case RRDSET_TYPE_LINE:
231
+ return line;
232
233
- case RRDSET_TYPE_AREA:
234
- return area;
233
+ case RRDSET_TYPE_AREA:
234
+ return area;
235
236
- case RRDSET_TYPE_STACKED:
237
- return stacked;
238
- }
239
- return line;
236
+ case RRDSET_TYPE_STACKED:
237
+ return stacked;
238
+ }
239
+ return line;
240
}
241
242
// ----------------------------------------------------------------------------
@@ -244,33 +244,33 @@ const char *rrdset_type_name(int chart_type)
244
245
const char *rrd_memory_mode_name(int id)
246
{
247
- static const char ram[] = RRD_MEMORY_MODE_RAM_NAME;
248
- static const char map[] = RRD_MEMORY_MODE_MAP_NAME;
249
- static const char save[] = RRD_MEMORY_MODE_SAVE_NAME;
247
+ static const char ram[] = RRD_MEMORY_MODE_RAM_NAME;
248
+ static const char map[] = RRD_MEMORY_MODE_MAP_NAME;
249
+ static const char save[] = RRD_MEMORY_MODE_SAVE_NAME;
250
251
- switch(id) {
252
- case RRD_MEMORY_MODE_RAM:
253
- return ram;
251
+ switch(id) {
252
+ case RRD_MEMORY_MODE_RAM:
253
+ return ram;
254
255
- case RRD_MEMORY_MODE_MAP:
256
- return map;
255
+ case RRD_MEMORY_MODE_MAP:
256
+ return map;
257
258
- case RRD_MEMORY_MODE_SAVE:
259
- default:
260
- return save;
261
- }
258
+ case RRD_MEMORY_MODE_SAVE:
259
+ default:
260
+ return save;
261
+ }
262
263
- return save;
263
+ return save;
264
}
265
266
int rrd_memory_mode_id(const char *name)
267
{
268
- if(unlikely(!strcmp(name, RRD_MEMORY_MODE_RAM_NAME)))
269
- return RRD_MEMORY_MODE_RAM;
270
- else if(unlikely(!strcmp(name, RRD_MEMORY_MODE_MAP_NAME)))
271
- return RRD_MEMORY_MODE_MAP;
268
+ if(unlikely(!strcmp(name, RRD_MEMORY_MODE_RAM_NAME)))
269
+ return RRD_MEMORY_MODE_RAM;
270
+ else if(unlikely(!strcmp(name, RRD_MEMORY_MODE_MAP_NAME)))
271
+ return RRD_MEMORY_MODE_MAP;
272
273
- return RRD_MEMORY_MODE_SAVE;
273
+ return RRD_MEMORY_MODE_SAVE;
274
}
275
276
// ----------------------------------------------------------------------------
@@ -278,34 +278,34 @@ int rrd_memory_mode_id(const char *name)
278
279
int rrddim_algorithm_id(const char *name)
280
{
281
- if(strcmp(name, RRDDIM_INCREMENTAL_NAME) == 0) return RRDDIM_INCREMENTAL;
282
- if(strcmp(name, RRDDIM_ABSOLUTE_NAME) == 0) return RRDDIM_ABSOLUTE;
283
- if(strcmp(name, RRDDIM_PCENT_OVER_ROW_TOTAL_NAME) == 0) return RRDDIM_PCENT_OVER_ROW_TOTAL;
284
- if(strcmp(name, RRDDIM_PCENT_OVER_DIFF_TOTAL_NAME) == 0) return RRDDIM_PCENT_OVER_DIFF_TOTAL;
285
- return RRDDIM_ABSOLUTE;
281
+ if(strcmp(name, RRDDIM_INCREMENTAL_NAME) == 0) return RRDDIM_INCREMENTAL;
282
+ if(strcmp(name, RRDDIM_ABSOLUTE_NAME) == 0) return RRDDIM_ABSOLUTE;
283
+ if(strcmp(name, RRDDIM_PCENT_OVER_ROW_TOTAL_NAME) == 0) return RRDDIM_PCENT_OVER_ROW_TOTAL;
284
+ if(strcmp(name, RRDDIM_PCENT_OVER_DIFF_TOTAL_NAME) == 0) return RRDDIM_PCENT_OVER_DIFF_TOTAL;
285
+ return RRDDIM_ABSOLUTE;
286
}
287
288
const char *rrddim_algorithm_name(int chart_type)
289
{
290
- static char absolute[] = RRDDIM_ABSOLUTE_NAME;
291
- static char incremental[] = RRDDIM_INCREMENTAL_NAME;
292
- static char percentage_of_absolute_row[] = RRDDIM_PCENT_OVER_ROW_TOTAL_NAME;
293
- static char percentage_of_incremental_row[] = RRDDIM_PCENT_OVER_DIFF_TOTAL_NAME;
290
+ static char absolute[] = RRDDIM_ABSOLUTE_NAME;
291
+ static char incremental[] = RRDDIM_INCREMENTAL_NAME;
292
+ static char percentage_of_absolute_row[] = RRDDIM_PCENT_OVER_ROW_TOTAL_NAME;
293
+ static char percentage_of_incremental_row[] = RRDDIM_PCENT_OVER_DIFF_TOTAL_NAME;
294
295
- switch(chart_type) {
296
- case RRDDIM_ABSOLUTE:
297
- return absolute;
295
+ switch(chart_type) {
296
+ case RRDDIM_ABSOLUTE:
297
+ return absolute;
298
299
- case RRDDIM_INCREMENTAL:
300
- return incremental;
299
+ case RRDDIM_INCREMENTAL:
300
+ return incremental;
301
302
- case RRDDIM_PCENT_OVER_ROW_TOTAL:
303
- return percentage_of_absolute_row;
302
+ case RRDDIM_PCENT_OVER_ROW_TOTAL:
303
+ return percentage_of_absolute_row;
304
305
- case RRDDIM_PCENT_OVER_DIFF_TOTAL:
306
- return percentage_of_incremental_row;
307
- }
308
- return absolute;
305
+ case RRDDIM_PCENT_OVER_DIFF_TOTAL:
306
+ return percentage_of_incremental_row;
307
+ }
308
+ return absolute;
309
}
310
311
// ----------------------------------------------------------------------------
@@ -313,38 +313,38 @@ const char *rrddim_algorithm_name(int chart_type)
313
314
char *rrdset_strncpyz_name(char *to, const char *from, size_t length)
315
{
316
- char c, *p = to;
316
+ char c, *p = to;
317
318
- while (length-- && (c = *from++)) {
319
- if(c != '.' && !isalnum(c))
320
- c = '_';
318
+ while (length-- && (c = *from++)) {
319
+ if(c != '.' && !isalnum(c))
320
+ c = '_';
321
322
- *p++ = c;
323
- }
322
+ *p++ = c;
323
+ }
324
325
- *p = '\0';
325
+ *p = '\0';
326
327
- return to;
327
+ return to;
328
}
329
330
void rrdset_set_name(RRDSET *st, const char *name)
331
{
332
- debug(D_RRD_CALLS, "rrdset_set_name() old: %s, new: %s", st->name, name);
332
+ debug(D_RRD_CALLS, "rrdset_set_name() old: %s, new: %s", st->name, name);
333
334
- if(st->name) {
334
+ if(st->name) {
335
rrdset_index_del_name(&localhost, st);
336
rrdsetvar_rename_all(st);
337
}
338
339
- char b[CONFIG_MAX_VALUE + 1];
340
- char n[RRD_ID_LENGTH_MAX + 1];
339
+ char b[CONFIG_MAX_VALUE + 1];
340
+ char n[RRD_ID_LENGTH_MAX + 1];
341
342
- snprintfz(n, RRD_ID_LENGTH_MAX, "%s.%s", st->type, name);
343
- rrdset_strncpyz_name(b, n, CONFIG_MAX_VALUE);
344
- st->name = config_get(st->id, "name", b);
345
- st->hash_name = simple_hash(st->name);
342
+ snprintfz(n, RRD_ID_LENGTH_MAX, "%s.%s", st->type, name);
343
+ rrdset_strncpyz_name(b, n, CONFIG_MAX_VALUE);
344
+ st->name = config_get(st->id, "name", b);
345
+ st->hash_name = simple_hash(st->name);
346
347
- rrdset_index_add_name(&localhost, st);
347
+ rrdset_index_add_name(&localhost, st);
348
}
349
350
// ----------------------------------------------------------------------------
@@ -352,30 +352,30 @@ void rrdset_set_name(RRDSET *st, const char *name)
352
353
char *rrdset_cache_dir(const char *id)
354
{
355
- char *ret = NULL;
356
-
357
- static char *cache_dir = NULL;
358
- if(!cache_dir) {
359
- cache_dir = config_get("global", "cache directory", CACHE_DIR);
360
- int r = mkdir(cache_dir, 0755);
361
- if(r != 0 && errno != EEXIST)
362
- error("Cannot create directory '%s'", cache_dir);
363
- }
364
-
365
- char b[FILENAME_MAX + 1];
366
- char n[FILENAME_MAX + 1];
367
- rrdset_strncpyz_name(b, id, FILENAME_MAX);
368
-
369
- snprintfz(n, FILENAME_MAX, "%s/%s", cache_dir, b);
370
- ret = config_get(id, "cache directory", n);
371
-
372
- if(rrd_memory_mode == RRD_MEMORY_MODE_MAP || rrd_memory_mode == RRD_MEMORY_MODE_SAVE) {
373
- int r = mkdir(ret, 0775);
374
- if(r != 0 && errno != EEXIST)
375
- error("Cannot create directory '%s'", ret);
376
- }
377
-
378
- return ret;
355
+ char *ret = NULL;
356
+
357
+ static char *cache_dir = NULL;
358
+ if(!cache_dir) {
359
+ cache_dir = config_get("global", "cache directory", CACHE_DIR);
360
+ int r = mkdir(cache_dir, 0755);
361
+ if(r != 0 && errno != EEXIST)
362
+ error("Cannot create directory '%s'", cache_dir);
363
+ }
364
+
365
+ char b[FILENAME_MAX + 1];
366
+ char n[FILENAME_MAX + 1];
367
+ rrdset_strncpyz_name(b, id, FILENAME_MAX);
368
+
369
+ snprintfz(n, FILENAME_MAX, "%s/%s", cache_dir, b);
370
+ ret = config_get(id, "cache directory", n);
371
+
372
+ if(rrd_memory_mode == RRD_MEMORY_MODE_MAP || rrd_memory_mode == RRD_MEMORY_MODE_SAVE) {
373
+ int r = mkdir(ret, 0775);
374
+ if(r != 0 && errno != EEXIST)
375
+ error("Cannot create directory '%s'", ret);
376
+ }
377
+
378
+ return ret;
379
}
380
381
// ----------------------------------------------------------------------------
@@ -383,156 +383,156 @@ char *rrdset_cache_dir(const char *id)
383
384
void rrdset_reset(RRDSET *st)
385
{
386
- debug(D_RRD_CALLS, "rrdset_reset() %s", st->name);
387
-
388
- st->last_collected_time.tv_sec = 0;
389
- st->last_collected_time.tv_usec = 0;
390
- st->last_updated.tv_sec = 0;
391
- st->last_updated.tv_usec = 0;
392
- st->current_entry = 0;
393
- st->counter = 0;
394
- st->counter_done = 0;
395
-
396
- RRDDIM *rd;
397
- for(rd = st->dimensions; rd ; rd = rd->next) {
398
- rd->last_collected_time.tv_sec = 0;
399
- rd->last_collected_time.tv_usec = 0;
400
- rd->counter = 0;
401
- bzero(rd->values, rd->entries * sizeof(storage_number));
402
- }
386
+ debug(D_RRD_CALLS, "rrdset_reset() %s", st->name);
387
+
388
+ st->last_collected_time.tv_sec = 0;
389
+ st->last_collected_time.tv_usec = 0;
390
+ st->last_updated.tv_sec = 0;
391
+ st->last_updated.tv_usec = 0;
392
+ st->current_entry = 0;
393
+ st->counter = 0;
394
+ st->counter_done = 0;
395
+
396
+ RRDDIM *rd;
397
+ for(rd = st->dimensions; rd ; rd = rd->next) {
398
+ rd->last_collected_time.tv_sec = 0;
399
+ rd->last_collected_time.tv_usec = 0;
400
+ rd->counter = 0;
401
+ bzero(rd->values, rd->entries * sizeof(storage_number));
402
+ }
403
}
404
405
RRDSET *rrdset_create(const char *type, const char *id, const char *name, const char *family, const char *context, const char *title, const char *units, long priority, int update_every, int chart_type)
406
{
407
- if(!type || !type[0]) {
408
- fatal("Cannot create rrd stats without a type.");
409
- return NULL;
410
- }
411
-
412
- if(!id || !id[0]) {
413
- fatal("Cannot create rrd stats without an id.");
414
- return NULL;
415
- }
416
-
417
- char fullid[RRD_ID_LENGTH_MAX + 1];
418
- char fullfilename[FILENAME_MAX + 1];
419
- RRDSET *st = NULL;
420
-
421
- snprintfz(fullid, RRD_ID_LENGTH_MAX, "%s.%s", type, id);
422
-
423
- st = rrdset_find(fullid);
424
- if(st) {
425
- error("Cannot create rrd stats for '%s', it already exists.", fullid);
426
- return st;
427
- }
428
-
429
- long entries = config_get_number(fullid, "history", rrd_default_history_entries);
430
- if(entries < 5) entries = config_set_number(fullid, "history", 5);
431
- if(entries > RRD_HISTORY_ENTRIES_MAX) entries = config_set_number(fullid, "history", RRD_HISTORY_ENTRIES_MAX);
432
-
433
- int enabled = config_get_boolean(fullid, "enabled", 1);
434
- if(!enabled) entries = 5;
435
-
436
- unsigned long size = sizeof(RRDSET);
437
- char *cache_dir = rrdset_cache_dir(fullid);
438
-
439
- debug(D_RRD_CALLS, "Creating RRD_STATS for '%s.%s'.", type, id);
440
-
441
- snprintfz(fullfilename, FILENAME_MAX, "%s/main.db", cache_dir);
442
- if(rrd_memory_mode != RRD_MEMORY_MODE_RAM) st = (RRDSET *)mymmap(fullfilename, size, ((rrd_memory_mode == RRD_MEMORY_MODE_MAP)?MAP_SHARED:MAP_PRIVATE), 0);
443
- if(st) {
444
- if(strcmp(st->magic, RRDSET_MAGIC) != 0) {
445
- errno = 0;
446
- info("Initializing file %s.", fullfilename);
447
- bzero(st, size);
448
- }
449
- else if(strcmp(st->id, fullid) != 0) {
450
- errno = 0;
451
- error("File %s contents are not for chart %s. Clearing it.", fullfilename, fullid);
452
- // munmap(st, size);
453
- // st = NULL;
454
- bzero(st, size);
455
- }
456
- else if(st->memsize != size || st->entries != entries) {
457
- errno = 0;
458
- error("File %s does not have the desired size. Clearing it.", fullfilename);
459
- bzero(st, size);
460
- }
461
- else if(st->update_every != update_every) {
462
- errno = 0;
463
- error("File %s does not have the desired update frequency. Clearing it.", fullfilename);
464
- bzero(st, size);
465
- }
466
- else if((time(NULL) - st->last_updated.tv_sec) > update_every * entries) {
467
- errno = 0;
468
- error("File %s is too old. Clearing it.", fullfilename);
469
- bzero(st, size);
470
- }
471
- }
472
-
473
- if(st) {
474
- st->name = NULL;
475
- st->type = NULL;
476
- st->family = NULL;
477
- st->context = NULL;
478
- st->title = NULL;
479
- st->units = NULL;
480
- st->dimensions = NULL;
481
- st->next = NULL;
482
- st->mapped = rrd_memory_mode;
407
+ if(!type || !type[0]) {
408
+ fatal("Cannot create rrd stats without a type.");
409
+ return NULL;
410
+ }
411
+
412
+ if(!id || !id[0]) {
413
+ fatal("Cannot create rrd stats without an id.");
414
+ return NULL;
415
+ }
416
+
417
+ char fullid[RRD_ID_LENGTH_MAX + 1];
418
+ char fullfilename[FILENAME_MAX + 1];
419
+ RRDSET *st = NULL;
420
+
421
+ snprintfz(fullid, RRD_ID_LENGTH_MAX, "%s.%s", type, id);
422
+
423
+ st = rrdset_find(fullid);
424
+ if(st) {
425
+ error("Cannot create rrd stats for '%s', it already exists.", fullid);
426
+ return st;
427
+ }
428
+
429
+ long entries = config_get_number(fullid, "history", rrd_default_history_entries);
430
+ if(entries < 5) entries = config_set_number(fullid, "history", 5);
431
+ if(entries > RRD_HISTORY_ENTRIES_MAX) entries = config_set_number(fullid, "history", RRD_HISTORY_ENTRIES_MAX);
432
+
433
+ int enabled = config_get_boolean(fullid, "enabled", 1);
434
+ if(!enabled) entries = 5;
435
+
436
+ unsigned long size = sizeof(RRDSET);
437
+ char *cache_dir = rrdset_cache_dir(fullid);
438
+
439
+ debug(D_RRD_CALLS, "Creating RRD_STATS for '%s.%s'.", type, id);
440
+
441
+ snprintfz(fullfilename, FILENAME_MAX, "%s/main.db", cache_dir);
442
+ if(rrd_memory_mode != RRD_MEMORY_MODE_RAM) st = (RRDSET *)mymmap(fullfilename, size, ((rrd_memory_mode == RRD_MEMORY_MODE_MAP)?MAP_SHARED:MAP_PRIVATE), 0);
443
+ if(st) {
444
+ if(strcmp(st->magic, RRDSET_MAGIC) != 0) {
445
+ errno = 0;
446
+ info("Initializing file %s.", fullfilename);
447
+ bzero(st, size);
448
+ }
449
+ else if(strcmp(st->id, fullid) != 0) {
450
+ errno = 0;
451
+ error("File %s contents are not for chart %s. Clearing it.", fullfilename, fullid);
452
+ // munmap(st, size);
453
+ // st = NULL;
454
+ bzero(st, size);
455
+ }
456
+ else if(st->memsize != size || st->entries != entries) {
457
+ errno = 0;
458
+ error("File %s does not have the desired size. Clearing it.", fullfilename);
459
+ bzero(st, size);
460
+ }
461
+ else if(st->update_every != update_every) {
462
+ errno = 0;
463
+ error("File %s does not have the desired update frequency. Clearing it.", fullfilename);
464
+ bzero(st, size);
465
+ }
466
+ else if((time(NULL) - st->last_updated.tv_sec) > update_every * entries) {
467
+ errno = 0;
468
+ error("File %s is too old. Clearing it.", fullfilename);
469
+ bzero(st, size);
470
+ }
471
+ }
472
+
473
+ if(st) {
474
+ st->name = NULL;
475
+ st->type = NULL;
476
+ st->family = NULL;
477
+ st->context = NULL;
478
+ st->title = NULL;
479
+ st->units = NULL;
480
+ st->dimensions = NULL;
481
+ st->next = NULL;
482
+ st->mapped = rrd_memory_mode;
483
st->variables = NULL;
484
- }
485
- else {
486
- st = callocz(1, size);
487
- st->mapped = RRD_MEMORY_MODE_RAM;
488
- }
489
- st->memsize = size;
490
- st->entries = entries;
491
- st->update_every = update_every;
484
+ }
485
+ else {
486
+ st = callocz(1, size);
487
+ st->mapped = RRD_MEMORY_MODE_RAM;
488
+ }
489
+ st->memsize = size;
490
+ st->entries = entries;
491
+ st->update_every = update_every;
492
493
- if(st->current_entry >= st->entries) st->current_entry = 0;
493
+ if(st->current_entry >= st->entries) st->current_entry = 0;
494
495
- strcpy(st->cache_filename, fullfilename);
496
- strcpy(st->magic, RRDSET_MAGIC);
495
+ strcpy(st->cache_filename, fullfilename);
496
+ strcpy(st->magic, RRDSET_MAGIC);
497
498
- strcpy(st->id, fullid);
499
- st->hash = simple_hash(st->id);
498
+ strcpy(st->id, fullid);
499
+ st->hash = simple_hash(st->id);
500
501
- st->cache_dir = cache_dir;
501
+ st->cache_dir = cache_dir;
502
503
- st->chart_type = rrdset_type_id(config_get(st->id, "chart type", rrdset_type_name(chart_type)));
504
- st->type = config_get(st->id, "type", type);
505
- st->family = config_get(st->id, "family", family?family:st->type);
506
- st->context = config_get(st->id, "context", context?context:st->id);
507
- st->units = config_get(st->id, "units", units?units:"");
503
+ st->chart_type = rrdset_type_id(config_get(st->id, "chart type", rrdset_type_name(chart_type)));
504
+ st->type = config_get(st->id, "type", type);
505
+ st->family = config_get(st->id, "family", family?family:st->type);
506
+ st->context = config_get(st->id, "context", context?context:st->id);
507
+ st->units = config_get(st->id, "units", units?units:"");
508
509
- st->priority = config_get_number(st->id, "priority", priority);
510
- st->enabled = enabled;
509
+ st->priority = config_get_number(st->id, "priority", priority);
510
+ st->enabled = enabled;
511
512
- st->isdetail = 0;
513
- st->debug = 0;
512
+ st->isdetail = 0;
513
+ st->debug = 0;
514
515
- st->last_collected_time.tv_sec = 0;
516
- st->last_collected_time.tv_usec = 0;
517
- st->counter_done = 0;
515
+ st->last_collected_time.tv_sec = 0;
516
+ st->last_collected_time.tv_usec = 0;
517
+ st->counter_done = 0;
518
519
- st->gap_when_lost_iterations_above = (int) (
520
- config_get_number(st->id, "gap when lost iterations above", RRD_DEFAULT_GAP_INTERPOLATIONS) + 2);
519
+ st->gap_when_lost_iterations_above = (int) (
520
+ config_get_number(st->id, "gap when lost iterations above", RRD_DEFAULT_GAP_INTERPOLATIONS) + 2);
521
522
- avl_init_lock(&st->dimensions_index, rrddim_compare);
522
+ avl_init_lock(&st->dimensions_index, rrddim_compare);
523
avl_init_lock(&st->variables_root_index, rrdvar_compare);
524
525
- pthread_rwlock_init(&st->rwlock, NULL);
526
- pthread_rwlock_wrlock(&localhost.rrdset_root_rwlock);
525
+ pthread_rwlock_init(&st->rwlock, NULL);
526
+ pthread_rwlock_wrlock(&localhost.rrdset_root_rwlock);
527
528
- if(name && *name) rrdset_set_name(st, name);
529
- else rrdset_set_name(st, id);
528
+ if(name && *name) rrdset_set_name(st, name);
529
+ else rrdset_set_name(st, id);
530
531
- {
532
- char varvalue[CONFIG_MAX_VALUE + 1];
533
- snprintfz(varvalue, CONFIG_MAX_VALUE, "%s (%s)", title?title:"", st->name);
534
- st->title = config_get(st->id, "title", varvalue);
535
- }
531
+ {
532
+ char varvalue[CONFIG_MAX_VALUE + 1];
533
+ snprintfz(varvalue, CONFIG_MAX_VALUE, "%s (%s)", title?title:"", st->name);
534
+ st->title = config_get(st->id, "title", varvalue);
535
+ }
536
537
st->rrdcontext = rrdcontext_create(st->context);
538
st->rrdhost = &localhost;
@@ -547,204 +547,204 @@ RRDSET *rrdset_create(const char *type, const char *id, const char *name, const
547
548
rrdsetcalc_link_matching(st);
549
550
- pthread_rwlock_unlock(&localhost.rrdset_root_rwlock);
550
+ pthread_rwlock_unlock(&localhost.rrdset_root_rwlock);
551
552
- return(st);
552
+ return(st);
553
}
554
555
RRDDIM *rrddim_add(RRDSET *st, const char *id, const char *name, long multiplier, long divisor, int algorithm)
556
{
557
- char filename[FILENAME_MAX + 1];
558
- char fullfilename[FILENAME_MAX + 1];
559
-
560
- char varname[CONFIG_MAX_NAME + 1];
561
- RRDDIM *rd = NULL;
562
- unsigned long size = sizeof(RRDDIM) + (st->entries * sizeof(storage_number));
563
-
564
- debug(D_RRD_CALLS, "Adding dimension '%s/%s'.", st->id, id);
565
-
566
- rrdset_strncpyz_name(filename, id, FILENAME_MAX);
567
- snprintfz(fullfilename, FILENAME_MAX, "%s/%s.db", st->cache_dir, filename);
568
- if(rrd_memory_mode != RRD_MEMORY_MODE_RAM) rd = (RRDDIM *)mymmap(fullfilename, size, ((rrd_memory_mode == RRD_MEMORY_MODE_MAP)?MAP_SHARED:MAP_PRIVATE), 1);
569
- if(rd) {
570
- struct timeval now;
571
- gettimeofday(&now, NULL);
572
-
573
- if(strcmp(rd->magic, RRDDIMENSION_MAGIC) != 0) {
574
- errno = 0;
575
- info("Initializing file %s.", fullfilename);
576
- bzero(rd, size);
577
- }
578
- else if(rd->memsize != size) {
579
- errno = 0;
580
- error("File %s does not have the desired size. Clearing it.", fullfilename);
581
- bzero(rd, size);
582
- }
583
- else if(rd->multiplier != multiplier) {
584
- errno = 0;
585
- error("File %s does not have the same multiplier. Clearing it.", fullfilename);
586
- bzero(rd, size);
587
- }
588
- else if(rd->divisor != divisor) {
589
- errno = 0;
590
- error("File %s does not have the same divisor. Clearing it.", fullfilename);
591
- bzero(rd, size);
592
- }
593
- else if(rd->algorithm != algorithm) {
594
- errno = 0;
595
- error("File %s does not have the same algorithm. Clearing it.", fullfilename);
596
- bzero(rd, size);
597
- }
598
- else if(rd->update_every != st->update_every) {
599
- errno = 0;
600
- error("File %s does not have the same refresh frequency. Clearing it.", fullfilename);
601
- bzero(rd, size);
602
- }
603
- else if(usec_dt(&now, &rd->last_collected_time) > (rd->entries * rd->update_every * 1000000ULL)) {
604
- errno = 0;
605
- error("File %s is too old. Clearing it.", fullfilename);
606
- bzero(rd, size);
607
- }
608
- else if(strcmp(rd->id, id) != 0) {
609
- errno = 0;
610
- error("File %s contents are not for dimension %s. Clearing it.", fullfilename, id);
611
- // munmap(rd, size);
612
- // rd = NULL;
613
- bzero(rd, size);
614
- }
615
- }
616
-
617
- if(rd) {
618
- // we have a file mapped for rd
619
- rd->mapped = rrd_memory_mode;
620
- rd->flags = 0x00000000;
557
+ char filename[FILENAME_MAX + 1];
558
+ char fullfilename[FILENAME_MAX + 1];
559
+
560
+ char varname[CONFIG_MAX_NAME + 1];
561
+ RRDDIM *rd = NULL;
562
+ unsigned long size = sizeof(RRDDIM) + (st->entries * sizeof(storage_number));
563
+
564
+ debug(D_RRD_CALLS, "Adding dimension '%s/%s'.", st->id, id);
565
+
566
+ rrdset_strncpyz_name(filename, id, FILENAME_MAX);
567
+ snprintfz(fullfilename, FILENAME_MAX, "%s/%s.db", st->cache_dir, filename);
568
+ if(rrd_memory_mode != RRD_MEMORY_MODE_RAM) rd = (RRDDIM *)mymmap(fullfilename, size, ((rrd_memory_mode == RRD_MEMORY_MODE_MAP)?MAP_SHARED:MAP_PRIVATE), 1);
569
+ if(rd) {
570
+ struct timeval now;
571
+ gettimeofday(&now, NULL);
572
+
573
+ if(strcmp(rd->magic, RRDDIMENSION_MAGIC) != 0) {
574
+ errno = 0;
575
+ info("Initializing file %s.", fullfilename);
576
+ bzero(rd, size);
577
+ }
578
+ else if(rd->memsize != size) {
579
+ errno = 0;
580
+ error("File %s does not have the desired size. Clearing it.", fullfilename);
581
+ bzero(rd, size);
582
+ }
583
+ else if(rd->multiplier != multiplier) {
584
+ errno = 0;
585
+ error("File %s does not have the same multiplier. Clearing it.", fullfilename);
586
+ bzero(rd, size);
587
+ }
588
+ else if(rd->divisor != divisor) {
589
+ errno = 0;
590
+ error("File %s does not have the same divisor. Clearing it.", fullfilename);
591
+ bzero(rd, size);
592
+ }
593
+ else if(rd->algorithm != algorithm) {
594
+ errno = 0;
595
+ error("File %s does not have the same algorithm. Clearing it.", fullfilename);
596
+ bzero(rd, size);
597
+ }
598
+ else if(rd->update_every != st->update_every) {
599
+ errno = 0;
600
+ error("File %s does not have the same refresh frequency. Clearing it.", fullfilename);
601
+ bzero(rd, size);
602
+ }
603
+ else if(usec_dt(&now, &rd->last_collected_time) > (rd->entries * rd->update_every * 1000000ULL)) {
604
+ errno = 0;
605
+ error("File %s is too old. Clearing it.", fullfilename);
606
+ bzero(rd, size);
607
+ }
608
+ else if(strcmp(rd->id, id) != 0) {
609
+ errno = 0;
610
+ error("File %s contents are not for dimension %s. Clearing it.", fullfilename, id);
611
+ // munmap(rd, size);
612
+ // rd = NULL;
613
+ bzero(rd, size);
614
+ }
615
+ }
616
+
617
+ if(rd) {
618
+ // we have a file mapped for rd
619
+ rd->mapped = rrd_memory_mode;
620
+ rd->flags = 0x00000000;
621
rd->variables = NULL;
622
- rd->next = NULL;
623
- rd->name = NULL;
624
- }
625
- else {
626
- // if we didn't manage to get a mmap'd dimension, just create one
627
-
628
- rd = callocz(1, size);
629
- rd->mapped = RRD_MEMORY_MODE_RAM;
630
- }
631
- rd->memsize = size;
632
-
633
- strcpy(rd->magic, RRDDIMENSION_MAGIC);
634
- strcpy(rd->cache_filename, fullfilename);
635
- strncpyz(rd->id, id, RRD_ID_LENGTH_MAX);
636
- rd->hash = simple_hash(rd->id);
637
-
638
- snprintfz(varname, CONFIG_MAX_NAME, "dim %s name", rd->id);
639
- rd->name = config_get(st->id, varname, (name && *name)?name:rd->id);
640
-
641
- snprintfz(varname, CONFIG_MAX_NAME, "dim %s algorithm", rd->id);
642
- rd->algorithm = rrddim_algorithm_id(config_get(st->id, varname, rrddim_algorithm_name(algorithm)));
643
-
644
- snprintfz(varname, CONFIG_MAX_NAME, "dim %s multiplier", rd->id);
645
- rd->multiplier = config_get_number(st->id, varname, multiplier);
646
-
647
- snprintfz(varname, CONFIG_MAX_NAME, "dim %s divisor", rd->id);
648
- rd->divisor = config_get_number(st->id, varname, divisor);
649
- if(!rd->divisor) rd->divisor = 1;
650
-
651
- rd->entries = st->entries;
652
- rd->update_every = st->update_every;
653
-
654
- // prevent incremental calculation spikes
655
- rd->counter = 0;
656
- rd->updated = 0;
657
- rd->calculated_value = 0;
658
- rd->last_calculated_value = 0;
659
- rd->collected_value = 0;
660
- rd->last_collected_value = 0;
661
- rd->collected_volume = 0;
662
- rd->stored_volume = 0;
663
- rd->values[st->current_entry] = pack_storage_number(0, SN_NOT_EXISTS);
664
- rd->last_collected_time.tv_sec = 0;
665
- rd->last_collected_time.tv_usec = 0;
622
+ rd->next = NULL;
623
+ rd->name = NULL;
624
+ }
625
+ else {
626
+ // if we didn't manage to get a mmap'd dimension, just create one
627
+
628
+ rd = callocz(1, size);
629
+ rd->mapped = RRD_MEMORY_MODE_RAM;
630
+ }
631
+ rd->memsize = size;
632
+
633
+ strcpy(rd->magic, RRDDIMENSION_MAGIC);
634
+ strcpy(rd->cache_filename, fullfilename);
635
+ strncpyz(rd->id, id, RRD_ID_LENGTH_MAX);
636
+ rd->hash = simple_hash(rd->id);
637
+
638
+ snprintfz(varname, CONFIG_MAX_NAME, "dim %s name", rd->id);
639
+ rd->name = config_get(st->id, varname, (name && *name)?name:rd->id);
640
+
641
+ snprintfz(varname, CONFIG_MAX_NAME, "dim %s algorithm", rd->id);
642
+ rd->algorithm = rrddim_algorithm_id(config_get(st->id, varname, rrddim_algorithm_name(algorithm)));
643
+
644
+ snprintfz(varname, CONFIG_MAX_NAME, "dim %s multiplier", rd->id);
645
+ rd->multiplier = config_get_number(st->id, varname, multiplier);
646
+
647
+ snprintfz(varname, CONFIG_MAX_NAME, "dim %s divisor", rd->id);
648
+ rd->divisor = config_get_number(st->id, varname, divisor);
649
+ if(!rd->divisor) rd->divisor = 1;
650
+
651
+ rd->entries = st->entries;
652
+ rd->update_every = st->update_every;
653
+
654
+ // prevent incremental calculation spikes
655
+ rd->counter = 0;
656
+ rd->updated = 0;
657
+ rd->calculated_value = 0;
658
+ rd->last_calculated_value = 0;
659
+ rd->collected_value = 0;
660
+ rd->last_collected_value = 0;
661
+ rd->collected_volume = 0;
662
+ rd->stored_volume = 0;
663
+ rd->values[st->current_entry] = pack_storage_number(0, SN_NOT_EXISTS);
664
+ rd->last_collected_time.tv_sec = 0;
665
+ rd->last_collected_time.tv_usec = 0;
666
rd->rrdset = st;
667
668
// append this dimension
669
- pthread_rwlock_wrlock(&st->rwlock);
670
- if(!st->dimensions)
671
- st->dimensions = rd;
672
- else {
673
- RRDDIM *td = st->dimensions;
674
- for(; td->next; td = td->next) ;
675
- td->next = rd;
676
- }
669
+ pthread_rwlock_wrlock(&st->rwlock);
670
+ if(!st->dimensions)
671
+ st->dimensions = rd;
672
+ else {
673
+ RRDDIM *td = st->dimensions;
674
+ for(; td->next; td = td->next) ;
675
+ td->next = rd;
676
+ }
677
678
rrddimvar_create(rd, RRDVAR_TYPE_CALCULATED, NULL, NULL, &rd->calculated_value, 0);
679
rrddimvar_create(rd, RRDVAR_TYPE_COLLECTED, NULL, "_raw", &rd->collected_value, 0);
680
rrddimvar_create(rd, RRDVAR_TYPE_TIME_T, NULL, "_last_collected", &rd->last_collected_time.tv_sec, 0);
681
682
- pthread_rwlock_unlock(&st->rwlock);
682
+ pthread_rwlock_unlock(&st->rwlock);
683
684
- rrddim_index_add(st, rd);
684
+ rrddim_index_add(st, rd);
685
686
- return(rd);
686
+ return(rd);
687
}
688
689
void rrddim_set_name(RRDSET *st, RRDDIM *rd, const char *name)
690
{
691
- debug(D_RRD_CALLS, "rrddim_set_name() %s.%s", st->name, rd->name);
691
+ debug(D_RRD_CALLS, "rrddim_set_name() %s.%s", st->name, rd->name);
692
693
- char varname[CONFIG_MAX_NAME + 1];
694
- snprintfz(varname, CONFIG_MAX_NAME, "dim %s name", rd->id);
695
- config_set_default(st->id, varname, name);
693
+ char varname[CONFIG_MAX_NAME + 1];
694
+ snprintfz(varname, CONFIG_MAX_NAME, "dim %s name", rd->id);
695
+ config_set_default(st->id, varname, name);
696
697
rrddimvar_rename_all(rd);
698
}
699
700
void rrddim_free(RRDSET *st, RRDDIM *rd)
701
{
702
- debug(D_RRD_CALLS, "rrddim_free() %s.%s", st->name, rd->name);
702
+ debug(D_RRD_CALLS, "rrddim_free() %s.%s", st->name, rd->name);
703
704
- RRDDIM *i, *last = NULL;
705
- for(i = st->dimensions; i && i != rd ; i = i->next) last = i;
704
+ RRDDIM *i, *last = NULL;
705
+ for(i = st->dimensions; i && i != rd ; i = i->next) last = i;
706
707
- if(!i) {
708
- error("Request to free dimension %s.%s but it is not linked.", st->id, rd->name);
709
- return;
710
- }
707
+ if(!i) {
708
+ error("Request to free dimension %s.%s but it is not linked.", st->id, rd->name);
709
+ return;
710
+ }
711
712
- if(last) last->next = rd->next;
713
- else st->dimensions = rd->next;
714
- rd->next = NULL;
712
+ if(last) last->next = rd->next;
713
+ else st->dimensions = rd->next;
714
+ rd->next = NULL;
715
716
while(rd->variables)
717
rrddimvar_free(rd->variables);
718
719
rrddim_index_del(st, rd);
720
721
- // free(rd->annotations);
722
- if(rd->mapped == RRD_MEMORY_MODE_SAVE) {
723
- debug(D_RRD_CALLS, "Saving dimension '%s' to '%s'.", rd->name, rd->cache_filename);
724
- savememory(rd->cache_filename, rd, rd->memsize);
725
-
726
- debug(D_RRD_CALLS, "Unmapping dimension '%s'.", rd->name);
727
- munmap(rd, rd->memsize);
728
- }
729
- else if(rd->mapped == RRD_MEMORY_MODE_MAP) {
730
- debug(D_RRD_CALLS, "Unmapping dimension '%s'.", rd->name);
731
- munmap(rd, rd->memsize);
732
- }
733
- else {
734
- debug(D_RRD_CALLS, "Removing dimension '%s'.", rd->name);
735
- freez(rd);
736
- }
721
+ // free(rd->annotations);
722
+ if(rd->mapped == RRD_MEMORY_MODE_SAVE) {
723
+ debug(D_RRD_CALLS, "Saving dimension '%s' to '%s'.", rd->name, rd->cache_filename);
724
+ savememory(rd->cache_filename, rd, rd->memsize);
725
+
726
+ debug(D_RRD_CALLS, "Unmapping dimension '%s'.", rd->name);
727
+ munmap(rd, rd->memsize);
728
+ }
729
+ else if(rd->mapped == RRD_MEMORY_MODE_MAP) {
730
+ debug(D_RRD_CALLS, "Unmapping dimension '%s'.", rd->name);
731
+ munmap(rd, rd->memsize);
732
+ }
733
+ else {
734
+ debug(D_RRD_CALLS, "Removing dimension '%s'.", rd->name);
735
+ freez(rd);
736
+ }
737
}
738
739
void rrdset_free_all(void)
740
{
741
- info("Freeing all memory...");
741
+ info("Freeing all memory...");
742
743
pthread_rwlock_wrlock(&localhost.rrdset_root_rwlock);
744
745
- RRDSET *st;
746
- for(st = localhost.rrdset_root; st ;) {
747
- RRDSET *next = st->next;
745
+ RRDSET *st;
746
+ for(st = localhost.rrdset_root; st ;) {
747
+ RRDSET *next = st->next;
748
749
pthread_rwlock_wrlock(&st->rwlock);
750
@@ -755,7 +755,7 @@ void rrdset_free_all(void)
755
rrdsetcalc_unlink(st->calculations);
756
757
while(st->dimensions)
758
- rrddim_free(st, st->dimensions);
758
+ rrddim_free(st, st->dimensions);
759
760
rrdset_index_del(&localhost, st);
761
@@ -765,704 +765,704 @@ void rrdset_free_all(void)
765
766
pthread_rwlock_unlock(&st->rwlock);
767
768
- if(st->mapped == RRD_MEMORY_MODE_SAVE) {
769
- debug(D_RRD_CALLS, "Saving stats '%s' to '%s'.", st->name, st->cache_filename);
770
- savememory(st->cache_filename, st, st->memsize);
771
-
772
- debug(D_RRD_CALLS, "Unmapping stats '%s'.", st->name);
773
- munmap(st, st->memsize);
774
- }
775
- else if(st->mapped == RRD_MEMORY_MODE_MAP) {
776
- debug(D_RRD_CALLS, "Unmapping stats '%s'.", st->name);
777
- munmap(st, st->memsize);
778
- }
779
- else
780
- freez(st);
781
-
782
- st = next;
783
- }
768
+ if(st->mapped == RRD_MEMORY_MODE_SAVE) {
769
+ debug(D_RRD_CALLS, "Saving stats '%s' to '%s'.", st->name, st->cache_filename);
770
+ savememory(st->cache_filename, st, st->memsize);
771
+
772
+ debug(D_RRD_CALLS, "Unmapping stats '%s'.", st->name);
773
+ munmap(st, st->memsize);
774
+ }
775
+ else if(st->mapped == RRD_MEMORY_MODE_MAP) {
776
+ debug(D_RRD_CALLS, "Unmapping stats '%s'.", st->name);
777
+ munmap(st, st->memsize);
778
+ }
779
+ else
780
+ freez(st);
781
+
782
+ st = next;
783
+ }
784
localhost.rrdset_root = NULL;
785
786
pthread_rwlock_unlock(&localhost.rrdset_root_rwlock);
787
788
- info("Memory cleanup completed...");
788
+ info("Memory cleanup completed...");
789
}
790
791
void rrdset_save_all(void) {
792
- info("Saving database...");
793
-
794
- RRDSET *st;
795
- RRDDIM *rd;
796
-
797
- pthread_rwlock_wrlock(&localhost.rrdset_root_rwlock);
798
- for(st = localhost.rrdset_root; st ; st = st->next) {
799
- pthread_rwlock_wrlock(&st->rwlock);
800
-
801
- if(st->mapped == RRD_MEMORY_MODE_SAVE) {
802
- debug(D_RRD_CALLS, "Saving stats '%s' to '%s'.", st->name, st->cache_filename);
803
- savememory(st->cache_filename, st, st->memsize);
804
- }
805
-
806
- for(rd = st->dimensions; rd ; rd = rd->next) {
807
- if(likely(rd->mapped == RRD_MEMORY_MODE_SAVE)) {
808
- debug(D_RRD_CALLS, "Saving dimension '%s' to '%s'.", rd->name, rd->cache_filename);
809
- savememory(rd->cache_filename, rd, rd->memsize);
810
- }
811
- }
812
-
813
- pthread_rwlock_unlock(&st->rwlock);
814
- }
815
- pthread_rwlock_unlock(&localhost.rrdset_root_rwlock);
792
+ info("Saving database...");
793
+
794
+ RRDSET *st;
795
+ RRDDIM *rd;
796
+
797
+ pthread_rwlock_wrlock(&localhost.rrdset_root_rwlock);
798
+ for(st = localhost.rrdset_root; st ; st = st->next) {
799
+ pthread_rwlock_wrlock(&st->rwlock);
800
+
801
+ if(st->mapped == RRD_MEMORY_MODE_SAVE) {
802
+ debug(D_RRD_CALLS, "Saving stats '%s' to '%s'.", st->name, st->cache_filename);
803
+ savememory(st->cache_filename, st, st->memsize);
804
+ }
805
+
806
+ for(rd = st->dimensions; rd ; rd = rd->next) {
807
+ if(likely(rd->mapped == RRD_MEMORY_MODE_SAVE)) {
808
+ debug(D_RRD_CALLS, "Saving dimension '%s' to '%s'.", rd->name, rd->cache_filename);
809
+ savememory(rd->cache_filename, rd, rd->memsize);
810
+ }
811
+ }
812
+
813
+ pthread_rwlock_unlock(&st->rwlock);
814
+ }
815
+ pthread_rwlock_unlock(&localhost.rrdset_root_rwlock);
816
}
817
818
819
RRDSET *rrdset_find(const char *id)
820
{
821
- debug(D_RRD_CALLS, "rrdset_find() for chart %s", id);
821
+ debug(D_RRD_CALLS, "rrdset_find() for chart %s", id);
822
823
- RRDSET *st = rrdset_index_find(&localhost, id, 0);
824
- return(st);
823
+ RRDSET *st = rrdset_index_find(&localhost, id, 0);
824
+ return(st);
825
}
826
827
RRDSET *rrdset_find_bytype(const char *type, const char *id)
828
{
829
- debug(D_RRD_CALLS, "rrdset_find_bytype() for chart %s.%s", type, id);
829
+ debug(D_RRD_CALLS, "rrdset_find_bytype() for chart %s.%s", type, id);
830
831
- char buf[RRD_ID_LENGTH_MAX + 1];
831
+ char buf[RRD_ID_LENGTH_MAX + 1];
832
833
- strncpyz(buf, type, RRD_ID_LENGTH_MAX - 1);
834
- strcat(buf, ".");
835
- int len = (int) strlen(buf);
836
- strncpyz(&buf[len], id, (size_t) (RRD_ID_LENGTH_MAX - len));
833
+ strncpyz(buf, type, RRD_ID_LENGTH_MAX - 1);
834
+ strcat(buf, ".");
835
+ int len = (int) strlen(buf);
836
+ strncpyz(&buf[len], id, (size_t) (RRD_ID_LENGTH_MAX - len));
837
838
- return(rrdset_find(buf));
838
+ return(rrdset_find(buf));
839
}
840
841
RRDSET *rrdset_find_byname(const char *name)
842
{
843
- debug(D_RRD_CALLS, "rrdset_find_byname() for chart %s", name);
843
+ debug(D_RRD_CALLS, "rrdset_find_byname() for chart %s", name);
844
845
- RRDSET *st = rrdset_index_find_name(&localhost, name, 0);
846
- return(st);
845
+ RRDSET *st = rrdset_index_find_name(&localhost, name, 0);
846
+ return(st);
847
}
848
849
RRDDIM *rrddim_find(RRDSET *st, const char *id)
850
{
851
- debug(D_RRD_CALLS, "rrddim_find() for chart %s, dimension %s", st->name, id);
851
+ debug(D_RRD_CALLS, "rrddim_find() for chart %s, dimension %s", st->name, id);
852
853
- return rrddim_index_find(st, id, 0);
853
+ return rrddim_index_find(st, id, 0);
854
}
855
856
int rrddim_hide(RRDSET *st, const char *id)
857
{
858
- debug(D_RRD_CALLS, "rrddim_hide() for chart %s, dimension %s", st->name, id);
858
+ debug(D_RRD_CALLS, "rrddim_hide() for chart %s, dimension %s", st->name, id);
859
860
- RRDDIM *rd = rrddim_find(st, id);
861
- if(unlikely(!rd)) {
862
- error("Cannot find dimension with id '%s' on stats '%s' (%s).", id, st->name, st->id);
863
- return 1;
864
- }
860
+ RRDDIM *rd = rrddim_find(st, id);
861
+ if(unlikely(!rd)) {
862
+ error("Cannot find dimension with id '%s' on stats '%s' (%s).", id, st->name, st->id);
863
+ return 1;
864
+ }
865
866
- rd->flags |= RRDDIM_FLAG_HIDDEN;
867
- return 0;
866
+ rd->flags |= RRDDIM_FLAG_HIDDEN;
867
+ return 0;
868
}
869
870
int rrddim_unhide(RRDSET *st, const char *id)
871
{
872
- debug(D_RRD_CALLS, "rrddim_unhide() for chart %s, dimension %s", st->name, id);
872
+ debug(D_RRD_CALLS, "rrddim_unhide() for chart %s, dimension %s", st->name, id);
873
874
- RRDDIM *rd = rrddim_find(st, id);
875
- if(unlikely(!rd)) {
876
- error("Cannot find dimension with id '%s' on stats '%s' (%s).", id, st->name, st->id);
877
- return 1;
878
- }
874
+ RRDDIM *rd = rrddim_find(st, id);
875
+ if(unlikely(!rd)) {
876
+ error("Cannot find dimension with id '%s' on stats '%s' (%s).", id, st->name, st->id);
877
+ return 1;
878
+ }
879
880
- if(rd->flags & RRDDIM_FLAG_HIDDEN) rd->flags ^= RRDDIM_FLAG_HIDDEN;
881
- return 0;
880
+ if(rd->flags & RRDDIM_FLAG_HIDDEN) rd->flags ^= RRDDIM_FLAG_HIDDEN;
881
+ return 0;
882
}
883
884
collected_number rrddim_set_by_pointer(RRDSET *st, RRDDIM *rd, collected_number value)
885
{
886
- debug(D_RRD_CALLS, "rrddim_set_by_pointer() for chart %s, dimension %s, value " COLLECTED_NUMBER_FORMAT, st->name, rd->name, value);
886
+ debug(D_RRD_CALLS, "rrddim_set_by_pointer() for chart %s, dimension %s, value " COLLECTED_NUMBER_FORMAT, st->name, rd->name, value);
887
888
- gettimeofday(&rd->last_collected_time, NULL);
889
- rd->collected_value = value;
890
- rd->updated = 1;
891
- rd->counter++;
888
+ gettimeofday(&rd->last_collected_time, NULL);
889
+ rd->collected_value = value;
890
+ rd->updated = 1;
891
+ rd->counter++;
892
893
- return rd->last_collected_value;
893
+ return rd->last_collected_value;
894
}
895
896
collected_number rrddim_set(RRDSET *st, const char *id, collected_number value)
897
{
898
- RRDDIM *rd = rrddim_find(st, id);
899
- if(unlikely(!rd)) {
900
- error("Cannot find dimension with id '%s' on stats '%s' (%s).", id, st->name, st->id);
901
- return 0;
902
- }
898
+ RRDDIM *rd = rrddim_find(st, id);
899
+ if(unlikely(!rd)) {
900
+ error("Cannot find dimension with id '%s' on stats '%s' (%s).", id, st->name, st->id);
901
+ return 0;
902
+ }
903
904
- return rrddim_set_by_pointer(st, rd, value);
904
+ return rrddim_set_by_pointer(st, rd, value);
905
}
906
907
void rrdset_next_usec(RRDSET *st, unsigned long long microseconds)
908
{
909
- if(!microseconds) rrdset_next(st);
910
- else {
911
- debug(D_RRD_CALLS, "rrdset_next_usec() for chart %s with microseconds %llu", st->name, microseconds);
909
+ if(!microseconds) rrdset_next(st);
910
+ else {
911
+ debug(D_RRD_CALLS, "rrdset_next_usec() for chart %s with microseconds %llu", st->name, microseconds);
912
913
- if(unlikely(st->debug)) debug(D_RRD_STATS, "%s: NEXT: %llu microseconds", st->name, microseconds);
914
- st->usec_since_last_update = microseconds;
915
- }
913
+ if(unlikely(st->debug)) debug(D_RRD_STATS, "%s: NEXT: %llu microseconds", st->name, microseconds);
914
+ st->usec_since_last_update = microseconds;
915
+ }
916
}
917
918
void rrdset_next(RRDSET *st)
919
{
920
- unsigned long long microseconds = 0;
920
+ unsigned long long microseconds = 0;
921
922
- if(likely(st->last_collected_time.tv_sec)) {
923
- struct timeval now;
924
- gettimeofday(&now, NULL);
925
- microseconds = usec_dt(&now, &st->last_collected_time);
926
- }
927
- // prevent infinite loop
928
- else microseconds = st->update_every * 1000000ULL;
922
+ if(likely(st->last_collected_time.tv_sec)) {
923
+ struct timeval now;
924
+ gettimeofday(&now, NULL);
925
+ microseconds = usec_dt(&now, &st->last_collected_time);
926
+ }
927
+ // prevent infinite loop
928
+ else microseconds = st->update_every * 1000000ULL;
929
930
- rrdset_next_usec(st, microseconds);
930
+ rrdset_next_usec(st, microseconds);
931
}
932
933
void rrdset_next_plugins(RRDSET *st)
934
{
935
- rrdset_next(st);
935
+ rrdset_next(st);
936
}
937
938
unsigned long long rrdset_done(RRDSET *st)
939
{
940
- if(unlikely(netdata_exit)) return 0;
941
-
942
- debug(D_RRD_CALLS, "rrdset_done() for chart %s", st->name);
943
-
944
- RRDDIM *rd, *last;
945
- int oldstate, store_this_entry = 1, first_entry = 0;
946
- unsigned long long last_ut, now_ut, next_ut, stored_entries = 0;
947
-
948
- if(unlikely(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate) != 0))
949
- error("Cannot set pthread cancel state to DISABLE.");
950
-
951
- // a read lock is OK here
952
- pthread_rwlock_rdlock(&st->rwlock);
953
-
954
- // enable the chart, if it was disabled
955
- if(unlikely(rrd_delete_unupdated_dimensions) && !st->enabled)
956
- st->enabled = 1;
957
-
958
- // check if the chart has a long time to be updated
959
- if(unlikely(st->usec_since_last_update > st->entries * st->update_every * 1000000ULL)) {
960
- info("%s: took too long to be updated (%0.3Lf secs). Reseting it.", st->name, (long double)(st->usec_since_last_update / 1000000.0));
961
- rrdset_reset(st);
962
- st->usec_since_last_update = st->update_every * 1000000ULL;
963
- first_entry = 1;
964
- }
965
- if(unlikely(st->debug)) debug(D_RRD_STATS, "%s: microseconds since last update: %llu", st->name, st->usec_since_last_update);
966
-
967
- // set last_collected_time
968
- if(unlikely(!st->last_collected_time.tv_sec)) {
969
- // it is the first entry
970
- // set the last_collected_time to now
971
- gettimeofday(&st->last_collected_time, NULL);
972
-
973
- // the first entry should not be stored
974
- store_this_entry = 0;
975
- first_entry = 1;
976
-
977
- if(unlikely(st->debug)) debug(D_RRD_STATS, "%s: has not set last_collected_time. Setting it now. Will not store the next entry.", st->name);
978
- }
979
- else {
980
- // it is not the first entry
981
- // calculate the proper last_collected_time, using usec_since_last_update
982
- unsigned long long ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec + st->usec_since_last_update;
983
- st->last_collected_time.tv_sec = (time_t) (ut / 1000000ULL);
984
- st->last_collected_time.tv_usec = (suseconds_t) (ut % 1000000ULL);
985
- }
986
-
987
- // if this set has not been updated in the past
988
- // we fake the last_update time to be = now - usec_since_last_update
989
- if(unlikely(!st->last_updated.tv_sec)) {
990
- // it has never been updated before
991
- // set a fake last_updated, in the past using usec_since_last_update
992
- unsigned long long ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec - st->usec_since_last_update;
993
- st->last_updated.tv_sec = (time_t) (ut / 1000000ULL);
994
- st->last_updated.tv_usec = (suseconds_t) (ut % 1000000ULL);
995
-
996
- // the first entry should not be stored
997
- store_this_entry = 0;
998
- first_entry = 1;
999
-
1000
- if(unlikely(st->debug)) debug(D_RRD_STATS, "%s: initializing last_updated to now - %llu microseconds (%0.3Lf). Will not store the next entry.", st->name, st->usec_since_last_update, (long double)ut/1000000.0);
1001
- }
1002
-
1003
- // check if we will re-write the entire data set
1004
- if(unlikely(usec_dt(&st->last_collected_time, &st->last_updated) > st->update_every * st->entries * 1000000ULL)) {
1005
- info("%s: too old data (last updated at %ld.%ld, last collected at %ld.%ld). Reseting it. Will not store the next entry.", st->name, st->last_updated.tv_sec, st->last_updated.tv_usec, st->last_collected_time.tv_sec, st->last_collected_time.tv_usec);
1006
- rrdset_reset(st);
1007
-
1008
- st->usec_since_last_update = st->update_every * 1000000ULL;
1009
-
1010
- gettimeofday(&st->last_collected_time, NULL);
1011
-
1012
- unsigned long long ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec - st->usec_since_last_update;
1013
- st->last_updated.tv_sec = (time_t) (ut / 1000000ULL);
1014
- st->last_updated.tv_usec = (suseconds_t) (ut % 1000000ULL);
1015
-
1016
- // the first entry should not be stored
1017
- store_this_entry = 0;
1018
- first_entry = 1;
1019
- }
1020
-
1021
- // these are the 3 variables that will help us in interpolation
1022
- // last_ut = the last time we added a value to the storage
1023
- // now_ut = the time the current value is taken at
1024
- // next_ut = the time of the next interpolation point
1025
- last_ut = st->last_updated.tv_sec * 1000000ULL + st->last_updated.tv_usec;
1026
- now_ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec;
1027
- next_ut = (st->last_updated.tv_sec + st->update_every) * 1000000ULL;
1028
-
1029
- if(unlikely(!first_entry && now_ut < next_ut)) {
1030
- if(unlikely(st->debug)) debug(D_RRD_STATS, "%s: THIS IS IN THE SAME INTERPOLATION POINT", st->name);
1031
- }
1032
-
1033
- if(unlikely(st->debug)) {
1034
- debug(D_RRD_STATS, "%s: last ut = %0.3Lf (last updated time)", st->name, (long double)last_ut/1000000.0);
1035
- debug(D_RRD_STATS, "%s: now ut = %0.3Lf (current update time)", st->name, (long double)now_ut/1000000.0);
1036
- debug(D_RRD_STATS, "%s: next ut = %0.3Lf (next interpolation point)", st->name, (long double)next_ut/1000000.0);
1037
- }
1038
-
1039
- if(unlikely(!st->counter_done)) {
1040
- store_this_entry = 0;
1041
- if(unlikely(st->debug)) debug(D_RRD_STATS, "%s: Will not store the next entry.", st->name);
1042
- }
1043
- st->counter_done++;
1044
-
1045
- // calculate totals and count the dimensions
1046
- int dimensions;
1047
- st->collected_total = 0;
1048
- for( rd = st->dimensions, dimensions = 0 ; likely(rd) ; rd = rd->next, dimensions++ )
1049
- if(likely(rd->updated)) st->collected_total += rd->collected_value;
1050
-
1051
- uint32_t storage_flags = SN_EXISTS;
1052
-
1053
- // process all dimensions to calculate their values
1054
- // based on the collected figures only
1055
- // at this stage we do not interpolate anything
1056
- for( rd = st->dimensions ; likely(rd) ; rd = rd->next ) {
1057
-
1058
- if(unlikely(!rd->updated)) {
1059
- rd->calculated_value = 0;
1060
- continue;
1061
- }
1062
-
1063
- if(unlikely(st->debug)) debug(D_RRD_STATS, "%s/%s: START "
1064
- " last_collected_value = " COLLECTED_NUMBER_FORMAT
1065
- " collected_value = " COLLECTED_NUMBER_FORMAT
1066
- " last_calculated_value = " CALCULATED_NUMBER_FORMAT
1067
- " calculated_value = " CALCULATED_NUMBER_FORMAT
1068
- , st->id, rd->name
1069
- , rd->last_collected_value
1070
- , rd->collected_value
1071
- , rd->last_calculated_value
1072
- , rd->calculated_value
1073
- );
1074
-
1075
- switch(rd->algorithm) {
1076
- case RRDDIM_ABSOLUTE:
1077
- rd->calculated_value = (calculated_number)rd->collected_value
1078
- * (calculated_number)rd->multiplier
1079
- / (calculated_number)rd->divisor;
1080
-
1081
- if(unlikely(st->debug))
1082
- debug(D_RRD_STATS, "%s/%s: CALC ABS/ABS-NO-IN "
1083
- CALCULATED_NUMBER_FORMAT " = "
1084
- COLLECTED_NUMBER_FORMAT
1085
- " * " CALCULATED_NUMBER_FORMAT
1086
- " / " CALCULATED_NUMBER_FORMAT
1087
- , st->id, rd->name
1088
- , rd->calculated_value
1089
- , rd->collected_value
1090
- , (calculated_number)rd->multiplier
1091
- , (calculated_number)rd->divisor
1092
- );
1093
- break;
1094
-
1095
- case RRDDIM_PCENT_OVER_ROW_TOTAL:
1096
- if(unlikely(!st->collected_total))
1097
- rd->calculated_value = 0;
1098
- else
1099
- // the percentage of the current value
1100
- // over the total of all dimensions
1101
- rd->calculated_value =
1102
- (calculated_number)100
1103
- * (calculated_number)rd->collected_value
1104
- / (calculated_number)st->collected_total;
1105
-
1106
- if(unlikely(st->debug))
1107
- debug(D_RRD_STATS, "%s/%s: CALC PCENT-ROW "
1108
- CALCULATED_NUMBER_FORMAT " = 100"
1109
- " * " COLLECTED_NUMBER_FORMAT
1110
- " / " COLLECTED_NUMBER_FORMAT
1111
- , st->id, rd->name
1112
- , rd->calculated_value
1113
- , rd->collected_value
1114
- , st->collected_total
1115
- );
1116
- break;
1117
-
1118
- case RRDDIM_INCREMENTAL:
1119
- if(unlikely(rd->counter <= 1)) {
1120
- rd->calculated_value = 0;
1121
- continue;
1122
- }
1123
-
1124
- // if the new is smaller than the old (an overflow, or reset), set the old equal to the new
1125
- // to reset the calculation (it will give zero as the calculation for this second)
1126
- if(unlikely(rd->last_collected_value > rd->collected_value)) {
1127
- debug(D_RRD_STATS, "%s.%s: RESET or OVERFLOW. Last collected value = " COLLECTED_NUMBER_FORMAT ", current = " COLLECTED_NUMBER_FORMAT
1128
- , st->name, rd->name
1129
- , rd->last_collected_value
1130
- , rd->collected_value);
1131
- if(!(rd->flags & RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS)) storage_flags = SN_EXISTS_RESET;
1132
- rd->last_collected_value = rd->collected_value;
1133
- }
1134
-
1135
- rd->calculated_value =
1136
- (calculated_number)(rd->collected_value - rd->last_collected_value)
1137
- * (calculated_number)rd->multiplier
1138
- / (calculated_number)rd->divisor;
1139
-
1140
- if(unlikely(st->debug))
1141
- debug(D_RRD_STATS, "%s/%s: CALC INC PRE "
1142
- CALCULATED_NUMBER_FORMAT " = ("
1143
- COLLECTED_NUMBER_FORMAT " - " COLLECTED_NUMBER_FORMAT
1144
- ")"
1145
- " * " CALCULATED_NUMBER_FORMAT
1146
- " / " CALCULATED_NUMBER_FORMAT
1147
- , st->id, rd->name
1148
- , rd->calculated_value
1149
- , rd->collected_value, rd->last_collected_value
1150
- , (calculated_number)rd->multiplier
1151
- , (calculated_number)rd->divisor
1152
- );
1153
- break;
1154
-
1155
- case RRDDIM_PCENT_OVER_DIFF_TOTAL:
1156
- if(unlikely(rd->counter <= 1)) {
1157
- rd->calculated_value = 0;
1158
- continue;
1159
- }
1160
-
1161
- // if the new is smaller than the old (an overflow, or reset), set the old equal to the new
1162
- // to reset the calculation (it will give zero as the calculation for this second)
1163
- if(unlikely(rd->last_collected_value > rd->collected_value)) {
1164
- debug(D_RRD_STATS, "%s.%s: RESET or OVERFLOW. Last collected value = " COLLECTED_NUMBER_FORMAT ", current = " COLLECTED_NUMBER_FORMAT
1165
- , st->name, rd->name
1166
- , rd->last_collected_value
1167
- , rd->collected_value);
1168
- if(!(rd->flags & RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS)) storage_flags = SN_EXISTS_RESET;
1169
- rd->last_collected_value = rd->collected_value;
1170
- }
1171
-
1172
- // the percentage of the current increment
1173
- // over the increment of all dimensions together
1174
- if(unlikely(st->collected_total == st->last_collected_total))
1175
- rd->calculated_value = 0;
1176
- else
1177
- rd->calculated_value =
1178
- (calculated_number)100
1179
- * (calculated_number)(rd->collected_value - rd->last_collected_value)
1180
- / (calculated_number)(st->collected_total - st->last_collected_total);
1181
-
1182
- if(unlikely(st->debug))
1183
- debug(D_RRD_STATS, "%s/%s: CALC PCENT-DIFF "
1184
- CALCULATED_NUMBER_FORMAT " = 100"
1185
- " * (" COLLECTED_NUMBER_FORMAT " - " COLLECTED_NUMBER_FORMAT ")"
1186
- " / (" COLLECTED_NUMBER_FORMAT " - " COLLECTED_NUMBER_FORMAT ")"
1187
- , st->id, rd->name
1188
- , rd->calculated_value
1189
- , rd->collected_value, rd->last_collected_value
1190
- , st->collected_total, st->last_collected_total
1191
- );
1192
- break;
1193
-
1194
- default:
1195
- // make the default zero, to make sure
1196
- // it gets noticed when we add new types
1197
- rd->calculated_value = 0;
1198
-
1199
- if(unlikely(st->debug))
1200
- debug(D_RRD_STATS, "%s/%s: CALC "
1201
- CALCULATED_NUMBER_FORMAT " = 0"
1202
- , st->id, rd->name
1203
- , rd->calculated_value
1204
- );
1205
- break;
1206
- }
1207
-
1208
- if(unlikely(st->debug)) debug(D_RRD_STATS, "%s/%s: PHASE2 "
1209
- " last_collected_value = " COLLECTED_NUMBER_FORMAT
1210
- " collected_value = " COLLECTED_NUMBER_FORMAT
1211
- " last_calculated_value = " CALCULATED_NUMBER_FORMAT
1212
- " calculated_value = " CALCULATED_NUMBER_FORMAT
1213
- , st->id, rd->name
1214
- , rd->last_collected_value
1215
- , rd->collected_value
1216
- , rd->last_calculated_value
1217
- , rd->calculated_value
1218
- );
1219
-
1220
- }
1221
-
1222
- // at this point we have all the calculated values ready
1223
- // it is now time to interpolate values on a second boundary
1224
-
1225
- unsigned long long first_ut = last_ut;
1226
- long long iterations = (now_ut - last_ut) / (st->update_every * 1000000ULL);
1227
- if((now_ut % (st->update_every * 1000000ULL)) == 0) iterations++;
1228
-
1229
- for( ; likely(next_ut <= now_ut) ; next_ut += st->update_every * 1000000ULL, iterations-- ) {
940
+ if(unlikely(netdata_exit)) return 0;
941
+
942
+ debug(D_RRD_CALLS, "rrdset_done() for chart %s", st->name);
943
+
944
+ RRDDIM *rd, *last;
945
+ int oldstate, store_this_entry = 1, first_entry = 0;
946
+ unsigned long long last_ut, now_ut, next_ut, stored_entries = 0;
947
+
948
+ if(unlikely(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate) != 0))
949
+ error("Cannot set pthread cancel state to DISABLE.");
950
+
951
+ // a read lock is OK here
952
+ pthread_rwlock_rdlock(&st->rwlock);
953
+
954
+ // enable the chart, if it was disabled
955
+ if(unlikely(rrd_delete_unupdated_dimensions) && !st->enabled)
956
+ st->enabled = 1;
957
+
958
+ // check if the chart has a long time to be updated
959
+ if(unlikely(st->usec_since_last_update > st->entries * st->update_every * 1000000ULL)) {
960
+ info("%s: took too long to be updated (%0.3Lf secs). Reseting it.", st->name, (long double)(st->usec_since_last_update / 1000000.0));
961
+ rrdset_reset(st);
962
+ st->usec_since_last_update = st->update_every * 1000000ULL;
963
+ first_entry = 1;
964
+ }
965
+ if(unlikely(st->debug)) debug(D_RRD_STATS, "%s: microseconds since last update: %llu", st->name, st->usec_since_last_update);
966
+
967
+ // set last_collected_time
968
+ if(unlikely(!st->last_collected_time.tv_sec)) {
969
+ // it is the first entry
970
+ // set the last_collected_time to now
971
+ gettimeofday(&st->last_collected_time, NULL);
972
+
973
+ // the first entry should not be stored
974
+ store_this_entry = 0;
975
+ first_entry = 1;
976
+
977
+ if(unlikely(st->debug)) debug(D_RRD_STATS, "%s: has not set last_collected_time. Setting it now. Will not store the next entry.", st->name);
978
+ }
979
+ else {
980
+ // it is not the first entry
981
+ // calculate the proper last_collected_time, using usec_since_last_update
982
+ unsigned long long ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec + st->usec_since_last_update;
983
+ st->last_collected_time.tv_sec = (time_t) (ut / 1000000ULL);
984
+ st->last_collected_time.tv_usec = (suseconds_t) (ut % 1000000ULL);
985
+ }
986
+
987
+ // if this set has not been updated in the past
988
+ // we fake the last_update time to be = now - usec_since_last_update
989
+ if(unlikely(!st->last_updated.tv_sec)) {
990
+ // it has never been updated before
991
+ // set a fake last_updated, in the past using usec_since_last_update
992
+ unsigned long long ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec - st->usec_since_last_update;
993
+ st->last_updated.tv_sec = (time_t) (ut / 1000000ULL);
994
+ st->last_updated.tv_usec = (suseconds_t) (ut % 1000000ULL);
995
+
996
+ // the first entry should not be stored
997
+ store_this_entry = 0;
998
+ first_entry = 1;
999
+
1000
+ if(unlikely(st->debug)) debug(D_RRD_STATS, "%s: initializing last_updated to now - %llu microseconds (%0.3Lf). Will not store the next entry.", st->name, st->usec_since_last_update, (long double)ut/1000000.0);
1001
+ }
1002
+
1003
+ // check if we will re-write the entire data set
1004
+ if(unlikely(usec_dt(&st->last_collected_time, &st->last_updated) > st->update_every * st->entries * 1000000ULL)) {
1005
+ info("%s: too old data (last updated at %ld.%ld, last collected at %ld.%ld). Reseting it. Will not store the next entry.", st->name, st->last_updated.tv_sec, st->last_updated.tv_usec, st->last_collected_time.tv_sec, st->last_collected_time.tv_usec);
1006
+ rrdset_reset(st);
1007
+
1008
+ st->usec_since_last_update = st->update_every * 1000000ULL;
1009
+
1010
+ gettimeofday(&st->last_collected_time, NULL);
1011
+
1012
+ unsigned long long ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec - st->usec_since_last_update;
1013
+ st->last_updated.tv_sec = (time_t) (ut / 1000000ULL);
1014
+ st->last_updated.tv_usec = (suseconds_t) (ut % 1000000ULL);
1015
+
1016
+ // the first entry should not be stored
1017
+ store_this_entry = 0;
1018
+ first_entry = 1;
1019
+ }
1020
+
1021
+ // these are the 3 variables that will help us in interpolation
1022
+ // last_ut = the last time we added a value to the storage
1023
+ // now_ut = the time the current value is taken at
1024
+ // next_ut = the time of the next interpolation point
1025
+ last_ut = st->last_updated.tv_sec * 1000000ULL + st->last_updated.tv_usec;
1026
+ now_ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec;
1027
+ next_ut = (st->last_updated.tv_sec + st->update_every) * 1000000ULL;
1028
+
1029
+ if(unlikely(!first_entry && now_ut < next_ut)) {
1030
+ if(unlikely(st->debug)) debug(D_RRD_STATS, "%s: THIS IS IN THE SAME INTERPOLATION POINT", st->name);
1031
+ }
1032
+
1033
+ if(unlikely(st->debug)) {
1034
+ debug(D_RRD_STATS, "%s: last ut = %0.3Lf (last updated time)", st->name, (long double)last_ut/1000000.0);
1035
+ debug(D_RRD_STATS, "%s: now ut = %0.3Lf (current update time)", st->name, (long double)now_ut/1000000.0);
1036
+ debug(D_RRD_STATS, "%s: next ut = %0.3Lf (next interpolation point)", st->name, (long double)next_ut/1000000.0);
1037
+ }
1038
+
1039
+ if(unlikely(!st->counter_done)) {
1040
+ store_this_entry = 0;
1041
+ if(unlikely(st->debug)) debug(D_RRD_STATS, "%s: Will not store the next entry.", st->name);
1042
+ }
1043
+ st->counter_done++;
1044
+
1045
+ // calculate totals and count the dimensions
1046
+ int dimensions;
1047
+ st->collected_total = 0;
1048
+ for( rd = st->dimensions, dimensions = 0 ; likely(rd) ; rd = rd->next, dimensions++ )
1049
+ if(likely(rd->updated)) st->collected_total += rd->collected_value;
1050
+
1051
+ uint32_t storage_flags = SN_EXISTS;
1052
+
1053
+ // process all dimensions to calculate their values
1054
+ // based on the collected figures only
1055
+ // at this stage we do not interpolate anything
1056
+ for( rd = st->dimensions ; likely(rd) ; rd = rd->next ) {
1057
+
1058
+ if(unlikely(!rd->updated)) {
1059
+ rd->calculated_value = 0;
1060
+ continue;
1061
+ }
1062
+
1063
+ if(unlikely(st->debug)) debug(D_RRD_STATS, "%s/%s: START "
1064
+ " last_collected_value = " COLLECTED_NUMBER_FORMAT
1065
+ " collected_value = " COLLECTED_NUMBER_FORMAT
1066
+ " last_calculated_value = " CALCULATED_NUMBER_FORMAT
1067
+ " calculated_value = " CALCULATED_NUMBER_FORMAT
1068
+ , st->id, rd->name
1069
+ , rd->last_collected_value
1070
+ , rd->collected_value
1071
+ , rd->last_calculated_value
1072
+ , rd->calculated_value
1073
+ );
1074
+
1075
+ switch(rd->algorithm) {
1076
+ case RRDDIM_ABSOLUTE:
1077
+ rd->calculated_value = (calculated_number)rd->collected_value
1078
+ * (calculated_number)rd->multiplier
1079
+ / (calculated_number)rd->divisor;
1080
+
1081
+ if(unlikely(st->debug))
1082
+ debug(D_RRD_STATS, "%s/%s: CALC ABS/ABS-NO-IN "
1083
+ CALCULATED_NUMBER_FORMAT " = "
1084
+ COLLECTED_NUMBER_FORMAT
1085
+ " * " CALCULATED_NUMBER_FORMAT
1086
+ " / " CALCULATED_NUMBER_FORMAT
1087
+ , st->id, rd->name
1088
+ , rd->calculated_value
1089
+ , rd->collected_value
1090
+ , (calculated_number)rd->multiplier
1091
+ , (calculated_number)rd->divisor
1092
+ );
1093
+ break;
1094
+
1095
+ case RRDDIM_PCENT_OVER_ROW_TOTAL:
1096
+ if(unlikely(!st->collected_total))
1097
+ rd->calculated_value = 0;
1098
+ else
1099
+ // the percentage of the current value
1100
+ // over the total of all dimensions
1101
+ rd->calculated_value =
1102
+ (calculated_number)100
1103
+ * (calculated_number)rd->collected_value
1104
+ / (calculated_number)st->collected_total;
1105
+
1106
+ if(unlikely(st->debug))
1107
+ debug(D_RRD_STATS, "%s/%s: CALC PCENT-ROW "
1108
+ CALCULATED_NUMBER_FORMAT " = 100"
1109
+ " * " COLLECTED_NUMBER_FORMAT
1110
+ " / " COLLECTED_NUMBER_FORMAT
1111
+ , st->id, rd->name
1112
+ , rd->calculated_value
1113
+ , rd->collected_value
1114
+ , st->collected_total
1115
+ );
1116
+ break;
1117
+
1118
+ case RRDDIM_INCREMENTAL:
1119
+ if(unlikely(rd->counter <= 1)) {
1120
+ rd->calculated_value = 0;
1121
+ continue;
1122
+ }
1123
+
1124
+ // if the new is smaller than the old (an overflow, or reset), set the old equal to the new
1125
+ // to reset the calculation (it will give zero as the calculation for this second)
1126
+ if(unlikely(rd->last_collected_value > rd->collected_value)) {
1127
+ debug(D_RRD_STATS, "%s.%s: RESET or OVERFLOW. Last collected value = " COLLECTED_NUMBER_FORMAT ", current = " COLLECTED_NUMBER_FORMAT
1128
+ , st->name, rd->name
1129
+ , rd->last_collected_value
1130
+ , rd->collected_value);
1131
+ if(!(rd->flags & RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS)) storage_flags = SN_EXISTS_RESET;
1132
+ rd->last_collected_value = rd->collected_value;
1133
+ }
1134
+
1135
+ rd->calculated_value =
1136
+ (calculated_number)(rd->collected_value - rd->last_collected_value)
1137
+ * (calculated_number)rd->multiplier
1138
+ / (calculated_number)rd->divisor;
1139
+
1140
+ if(unlikely(st->debug))
1141
+ debug(D_RRD_STATS, "%s/%s: CALC INC PRE "
1142
+ CALCULATED_NUMBER_FORMAT " = ("
1143
+ COLLECTED_NUMBER_FORMAT " - " COLLECTED_NUMBER_FORMAT
1144
+ ")"
1145
+ " * " CALCULATED_NUMBER_FORMAT
1146
+ " / " CALCULATED_NUMBER_FORMAT
1147
+ , st->id, rd->name
1148
+ , rd->calculated_value
1149
+ , rd->collected_value, rd->last_collected_value
1150
+ , (calculated_number)rd->multiplier
1151
+ , (calculated_number)rd->divisor
1152
+ );
1153
+ break;
1154
+
1155
+ case RRDDIM_PCENT_OVER_DIFF_TOTAL:
1156
+ if(unlikely(rd->counter <= 1)) {
1157
+ rd->calculated_value = 0;
1158
+ continue;
1159
+ }
1160
+
1161
+ // if the new is smaller than the old (an overflow, or reset), set the old equal to the new
1162
+ // to reset the calculation (it will give zero as the calculation for this second)
1163
+ if(unlikely(rd->last_collected_value > rd->collected_value)) {
1164
+ debug(D_RRD_STATS, "%s.%s: RESET or OVERFLOW. Last collected value = " COLLECTED_NUMBER_FORMAT ", current = " COLLECTED_NUMBER_FORMAT
1165
+ , st->name, rd->name
1166
+ , rd->last_collected_value
1167
+ , rd->collected_value);
1168
+ if(!(rd->flags & RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS)) storage_flags = SN_EXISTS_RESET;
1169
+ rd->last_collected_value = rd->collected_value;
1170
+ }
1171
+
1172
+ // the percentage of the current increment
1173
+ // over the increment of all dimensions together
1174
+ if(unlikely(st->collected_total == st->last_collected_total))
1175
+ rd->calculated_value = 0;
1176
+ else
1177
+ rd->calculated_value =
1178
+ (calculated_number)100
1179
+ * (calculated_number)(rd->collected_value - rd->last_collected_value)
1180
+ / (calculated_number)(st->collected_total - st->last_collected_total);
1181
+
1182
+ if(unlikely(st->debug))
1183
+ debug(D_RRD_STATS, "%s/%s: CALC PCENT-DIFF "
1184
+ CALCULATED_NUMBER_FORMAT " = 100"
1185
+ " * (" COLLECTED_NUMBER_FORMAT " - " COLLECTED_NUMBER_FORMAT ")"
1186
+ " / (" COLLECTED_NUMBER_FORMAT " - " COLLECTED_NUMBER_FORMAT ")"
1187
+ , st->id, rd->name
1188
+ , rd->calculated_value
1189
+ , rd->collected_value, rd->last_collected_value
1190
+ , st->collected_total, st->last_collected_total
1191
+ );
1192
+ break;
1193
+
1194
+ default:
1195
+ // make the default zero, to make sure
1196
+ // it gets noticed when we add new types
1197
+ rd->calculated_value = 0;
1198
+
1199
+ if(unlikely(st->debug))
1200
+ debug(D_RRD_STATS, "%s/%s: CALC "
1201
+ CALCULATED_NUMBER_FORMAT " = 0"
1202
+ , st->id, rd->name
1203
+ , rd->calculated_value
1204
+ );
1205
+ break;
1206
+ }
1207
+
1208
+ if(unlikely(st->debug)) debug(D_RRD_STATS, "%s/%s: PHASE2 "
1209
+ " last_collected_value = " COLLECTED_NUMBER_FORMAT
1210
+ " collected_value = " COLLECTED_NUMBER_FORMAT
1211
+ " last_calculated_value = " CALCULATED_NUMBER_FORMAT
1212
+ " calculated_value = " CALCULATED_NUMBER_FORMAT
1213
+ , st->id, rd->name
1214
+ , rd->last_collected_value
1215
+ , rd->collected_value
1216
+ , rd->last_calculated_value
1217
+ , rd->calculated_value
1218
+ );
1219
+
1220
+ }
1221
+
1222
+ // at this point we have all the calculated values ready
1223
+ // it is now time to interpolate values on a second boundary
1224
+
1225
+ unsigned long long first_ut = last_ut;
1226
+ long long iterations = (now_ut - last_ut) / (st->update_every * 1000000ULL);
1227
+ if((now_ut % (st->update_every * 1000000ULL)) == 0) iterations++;
1228
+
1229
+ for( ; likely(next_ut <= now_ut) ; next_ut += st->update_every * 1000000ULL, iterations-- ) {
1230
#ifdef NETDATA_INTERNAL_CHECKS
1231
- if(iterations < 0) { error("%s: iterations calculation wrapped! first_ut = %llu, last_ut = %llu, next_ut = %llu, now_ut = %llu", st->name, first_ut, last_ut, next_ut, now_ut); }
1231
+ if(iterations < 0) { error("%s: iterations calculation wrapped! first_ut = %llu, last_ut = %llu, next_ut = %llu, now_ut = %llu", st->name, first_ut, last_ut, next_ut, now_ut); }
1232
#endif
1233
1234
- if(unlikely(st->debug)) {
1235
- debug(D_RRD_STATS, "%s: last ut = %0.3Lf (last updated time)", st->name, (long double)last_ut/1000000.0);
1236
- debug(D_RRD_STATS, "%s: next ut = %0.3Lf (next interpolation point)", st->name, (long double)next_ut/1000000.0);
1237
- }
1238
-
1239
- st->last_updated.tv_sec = (time_t) (next_ut / 1000000ULL);
1240
- st->last_updated.tv_usec = 0;
1241
-
1242
- for( rd = st->dimensions ; likely(rd) ; rd = rd->next ) {
1243
- calculated_number new_value;
1244
-
1245
- switch(rd->algorithm) {
1246
- case RRDDIM_INCREMENTAL:
1247
- new_value = (calculated_number)
1248
- ( rd->calculated_value
1249
- * (calculated_number)(next_ut - last_ut)
1250
- / (calculated_number)(now_ut - last_ut)
1251
- );
1252
-
1253
- if(unlikely(st->debug))
1254
- debug(D_RRD_STATS, "%s/%s: CALC2 INC "
1255
- CALCULATED_NUMBER_FORMAT " = "
1256
- CALCULATED_NUMBER_FORMAT
1257
- " * %llu"
1258
- " / %llu"
1259
- , st->id, rd->name
1260
- , new_value
1261
- , rd->calculated_value
1262
- , (next_ut - last_ut)
1263
- , (now_ut - last_ut)
1264
- );
1265
-
1266
- rd->calculated_value -= new_value;
1267
- new_value += rd->last_calculated_value;
1268
- rd->last_calculated_value = 0;
1269
- new_value /= (calculated_number)st->update_every;
1270
- break;
1271
-
1272
- case RRDDIM_ABSOLUTE:
1273
- case RRDDIM_PCENT_OVER_ROW_TOTAL:
1274
- case RRDDIM_PCENT_OVER_DIFF_TOTAL:
1275
- default:
1276
- if(iterations == 1) {
1277
- // this is the last iteration
1278
- // do not interpolate
1279
- // just show the calculated value
1280
-
1281
- new_value = rd->calculated_value;
1282
- }
1283
- else {
1284
- // we have missed an update
1285
- // interpolate in the middle values
1286
-
1287
- new_value = (calculated_number)
1288
- ( ( (rd->calculated_value - rd->last_calculated_value)
1289
- * (calculated_number)(next_ut - first_ut)
1290
- / (calculated_number)(now_ut - first_ut)
1291
- )
1292
- + rd->last_calculated_value
1293
- );
1294
-
1295
- if(unlikely(st->debug))
1296
- debug(D_RRD_STATS, "%s/%s: CALC2 DEF "
1297
- CALCULATED_NUMBER_FORMAT " = ((("
1298
- "(" CALCULATED_NUMBER_FORMAT " - " CALCULATED_NUMBER_FORMAT ")"
1299
- " * %llu"
1300
- " / %llu) + " CALCULATED_NUMBER_FORMAT
1301
- , st->id, rd->name
1302
- , new_value
1303
- , rd->calculated_value, rd->last_calculated_value
1304
- , (next_ut - first_ut)
1305
- , (now_ut - first_ut), rd->last_calculated_value
1306
- );
1307
-
1308
- // this is wrong
1309
- // it fades the value towards the target
1310
- // while we know the calculated value is different
1311
- // if(likely(next_ut + st->update_every * 1000000ULL > now_ut)) rd->calculated_value = new_value;
1312
- }
1313
- break;
1314
- }
1315
-
1316
- if(unlikely(!store_this_entry)) {
1317
- store_this_entry = 1;
1318
- continue;
1319
- }
1320
-
1321
- if(likely(rd->updated && rd->counter > 1 && iterations < st->gap_when_lost_iterations_above)) {
1322
- rd->values[st->current_entry] = pack_storage_number(new_value, storage_flags );
1323
-
1324
- if(unlikely(st->debug))
1325
- debug(D_RRD_STATS, "%s/%s: STORE[%ld] "
1326
- CALCULATED_NUMBER_FORMAT " = " CALCULATED_NUMBER_FORMAT
1327
- , st->id, rd->name
1328
- , st->current_entry
1329
- , unpack_storage_number(rd->values[st->current_entry]), new_value
1330
- );
1331
- }
1332
- else {
1333
- if(unlikely(st->debug)) debug(D_RRD_STATS, "%s/%s: STORE[%ld] = NON EXISTING "
1334
- , st->id, rd->name
1335
- , st->current_entry
1336
- );
1337
- rd->values[st->current_entry] = pack_storage_number(0, SN_NOT_EXISTS);
1338
- }
1339
-
1340
- stored_entries++;
1341
-
1342
- if(unlikely(st->debug)) {
1343
- calculated_number t1 = new_value * (calculated_number)rd->multiplier / (calculated_number)rd->divisor;
1344
- calculated_number t2 = unpack_storage_number(rd->values[st->current_entry]);
1345
- calculated_number accuracy = accuracy_loss(t1, t2);
1346
- debug(D_RRD_STATS, "%s/%s: UNPACK[%ld] = " CALCULATED_NUMBER_FORMAT " FLAGS=0x%08x (original = " CALCULATED_NUMBER_FORMAT ", accuracy loss = " CALCULATED_NUMBER_FORMAT "%%%s)"
1347
- , st->id, rd->name
1348
- , st->current_entry
1349
- , t2
1350
- , get_storage_number_flags(rd->values[st->current_entry])
1351
- , t1
1352
- , accuracy
1353
- , (accuracy > ACCURACY_LOSS) ? " **TOO BIG** " : ""
1354
- );
1355
-
1356
- rd->collected_volume += t1;
1357
- rd->stored_volume += t2;
1358
- accuracy = accuracy_loss(rd->collected_volume, rd->stored_volume);
1359
- debug(D_RRD_STATS, "%s/%s: VOLUME[%ld] = " CALCULATED_NUMBER_FORMAT ", calculated = " CALCULATED_NUMBER_FORMAT ", accuracy loss = " CALCULATED_NUMBER_FORMAT "%%%s"
1360
- , st->id, rd->name
1361
- , st->current_entry
1362
- , rd->stored_volume
1363
- , rd->collected_volume
1364
- , accuracy
1365
- , (accuracy > ACCURACY_LOSS) ? " **TOO BIG** " : ""
1366
- );
1367
-
1368
- }
1369
- }
1370
- // reset the storage flags for the next point, if any;
1371
- storage_flags = SN_EXISTS;
1372
-
1373
- st->counter++;
1374
- st->current_entry = ((st->current_entry + 1) >= st->entries) ? 0 : st->current_entry + 1;
1375
- last_ut = next_ut;
1376
- }
1377
-
1378
- // align next interpolation to last collection point
1379
- if(likely(stored_entries || !store_this_entry)) {
1380
- st->last_updated.tv_sec = st->last_collected_time.tv_sec;
1381
- st->last_updated.tv_usec = st->last_collected_time.tv_usec;
1382
- st->last_collected_total = st->collected_total;
1383
- }
1384
-
1385
- for( rd = st->dimensions; likely(rd) ; rd = rd->next ) {
1386
- if(unlikely(!rd->updated)) continue;
1387
-
1388
- if(likely(stored_entries || !store_this_entry)) {
1389
- if(unlikely(st->debug)) debug(D_RRD_STATS, "%s/%s: setting last_collected_value (old: " COLLECTED_NUMBER_FORMAT ") to last_collected_value (new: " COLLECTED_NUMBER_FORMAT ")", st->id, rd->name, rd->last_collected_value, rd->collected_value);
1390
- rd->last_collected_value = rd->collected_value;
1391
-
1392
- if(unlikely(st->debug)) debug(D_RRD_STATS, "%s/%s: setting last_calculated_value (old: " CALCULATED_NUMBER_FORMAT ") to last_calculated_value (new: " CALCULATED_NUMBER_FORMAT ")", st->id, rd->name, rd->last_calculated_value, rd->calculated_value);
1393
- rd->last_calculated_value = rd->calculated_value;
1394
- }
1395
-
1396
- rd->calculated_value = 0;
1397
- rd->collected_value = 0;
1398
- rd->updated = 0;
1399
-
1400
- if(unlikely(st->debug)) debug(D_RRD_STATS, "%s/%s: END "
1401
- " last_collected_value = " COLLECTED_NUMBER_FORMAT
1402
- " collected_value = " COLLECTED_NUMBER_FORMAT
1403
- " last_calculated_value = " CALCULATED_NUMBER_FORMAT
1404
- " calculated_value = " CALCULATED_NUMBER_FORMAT
1405
- , st->id, rd->name
1406
- , rd->last_collected_value
1407
- , rd->collected_value
1408
- , rd->last_calculated_value
1409
- , rd->calculated_value
1410
- );
1411
- }
1412
-
1413
- // ALL DONE ABOUT THE DATA UPDATE
1414
- // --------------------------------------------------------------------
1415
-
1416
- // find if there are any obsolete dimensions (not updated recently)
1417
- if(unlikely(rrd_delete_unupdated_dimensions)) {
1418
-
1419
- for( rd = st->dimensions; likely(rd) ; rd = rd->next )
1420
- if((rd->last_collected_time.tv_sec + (rrd_delete_unupdated_dimensions * st->update_every)) < st->last_collected_time.tv_sec)
1421
- break;
1422
-
1423
- if(unlikely(rd)) {
1424
- // there is dimension to free
1425
- // upgrade our read lock to a write lock
1426
- pthread_rwlock_unlock(&st->rwlock);
1427
- pthread_rwlock_wrlock(&st->rwlock);
1428
-
1429
- for( rd = st->dimensions, last = NULL ; likely(rd) ; ) {
1430
- // remove it only it is not updated in rrd_delete_unupdated_dimensions seconds
1431
-
1432
- if(unlikely((rd->last_collected_time.tv_sec + (rrd_delete_unupdated_dimensions * st->update_every)) < st->last_collected_time.tv_sec)) {
1433
- info("Removing obsolete dimension '%s' (%s) of '%s' (%s).", rd->name, rd->id, st->name, st->id);
1434
-
1435
- if(unlikely(!last)) {
1436
- st->dimensions = rd->next;
1437
- rd->next = NULL;
1438
- rrddim_free(st, rd);
1439
- rd = st->dimensions;
1440
- continue;
1441
- }
1442
- else {
1443
- last->next = rd->next;
1444
- rd->next = NULL;
1445
- rrddim_free(st, rd);
1446
- rd = last->next;
1447
- continue;
1448
- }
1449
- }
1450
-
1451
- last = rd;
1452
- rd = rd->next;
1453
- }
1454
-
1455
- if(unlikely(!st->dimensions)) {
1456
- info("Disabling chart %s (%s) since it does not have any dimensions", st->name, st->id);
1457
- st->enabled = 0;
1458
- }
1459
- }
1460
- }
1461
-
1462
- pthread_rwlock_unlock(&st->rwlock);
1463
-
1464
- if(unlikely(pthread_setcancelstate(oldstate, NULL) != 0))
1465
- error("Cannot set pthread cancel state to RESTORE (%d).", oldstate);
1466
-
1467
- return(st->usec_since_last_update);
1234
+ if(unlikely(st->debug)) {
1235
+ debug(D_RRD_STATS, "%s: last ut = %0.3Lf (last updated time)", st->name, (long double)last_ut/1000000.0);
1236
+ debug(D_RRD_STATS, "%s: next ut = %0.3Lf (next interpolation point)", st->name, (long double)next_ut/1000000.0);
1237
+ }
1238
+
1239
+ st->last_updated.tv_sec = (time_t) (next_ut / 1000000ULL);
1240
+ st->last_updated.tv_usec = 0;
1241
+
1242
+ for( rd = st->dimensions ; likely(rd) ; rd = rd->next ) {
1243
+ calculated_number new_value;
1244
+
1245
+ switch(rd->algorithm) {
1246
+ case RRDDIM_INCREMENTAL:
1247
+ new_value = (calculated_number)
1248
+ ( rd->calculated_value
1249
+ * (calculated_number)(next_ut - last_ut)
1250
+ / (calculated_number)(now_ut - last_ut)
1251
+ );
1252
+
1253
+ if(unlikely(st->debug))
1254
+ debug(D_RRD_STATS, "%s/%s: CALC2 INC "
1255
+ CALCULATED_NUMBER_FORMAT " = "
1256
+ CALCULATED_NUMBER_FORMAT
1257
+ " * %llu"
1258
+ " / %llu"
1259
+ , st->id, rd->name
1260
+ , new_value
1261
+ , rd->calculated_value
1262
+ , (next_ut - last_ut)
1263
+ , (now_ut - last_ut)
1264
+ );
1265
+
1266
+ rd->calculated_value -= new_value;
1267
+ new_value += rd->last_calculated_value;
1268
+ rd->last_calculated_value = 0;
1269
+ new_value /= (calculated_number)st->update_every;
1270
+ break;
1271
+
1272
+ case RRDDIM_ABSOLUTE:
1273
+ case RRDDIM_PCENT_OVER_ROW_TOTAL:
1274
+ case RRDDIM_PCENT_OVER_DIFF_TOTAL:
1275
+ default:
1276
+ if(iterations == 1) {
1277
+ // this is the last iteration
1278
+ // do not interpolate
1279
+ // just show the calculated value
1280
+
1281
+ new_value = rd->calculated_value;
1282
+ }
1283
+ else {
1284
+ // we have missed an update
1285
+ // interpolate in the middle values
1286
+
1287
+ new_value = (calculated_number)
1288
+ ( ( (rd->calculated_value - rd->last_calculated_value)
1289
+ * (calculated_number)(next_ut - first_ut)
1290
+ / (calculated_number)(now_ut - first_ut)
1291
+ )
1292
+ + rd->last_calculated_value
1293
+ );
1294
+
1295
+ if(unlikely(st->debug))
1296
+ debug(D_RRD_STATS, "%s/%s: CALC2 DEF "
1297
+ CALCULATED_NUMBER_FORMAT " = ((("
1298
+ "(" CALCULATED_NUMBER_FORMAT " - " CALCULATED_NUMBER_FORMAT ")"
1299
+ " * %llu"
1300
+ " / %llu) + " CALCULATED_NUMBER_FORMAT
1301
+ , st->id, rd->name
1302
+ , new_value
1303
+ , rd->calculated_value, rd->last_calculated_value
1304
+ , (next_ut - first_ut)
1305
+ , (now_ut - first_ut), rd->last_calculated_value
1306
+ );
1307
+
1308
+ // this is wrong
1309
+ // it fades the value towards the target
1310
+ // while we know the calculated value is different
1311
+ // if(likely(next_ut + st->update_every * 1000000ULL > now_ut)) rd->calculated_value = new_value;
1312
+ }
1313
+ break;
1314
+ }
1315
+
1316
+ if(unlikely(!store_this_entry)) {
1317
+ store_this_entry = 1;
1318
+ continue;
1319
+ }
1320
+
1321
+ if(likely(rd->updated && rd->counter > 1 && iterations < st->gap_when_lost_iterations_above)) {
1322
+ rd->values[st->current_entry] = pack_storage_number(new_value, storage_flags );
1323
+
1324
+ if(unlikely(st->debug))
1325
+ debug(D_RRD_STATS, "%s/%s: STORE[%ld] "
1326
+ CALCULATED_NUMBER_FORMAT " = " CALCULATED_NUMBER_FORMAT
1327
+ , st->id, rd->name
1328
+ , st->current_entry
1329
+ , unpack_storage_number(rd->values[st->current_entry]), new_value
1330
+ );
1331
+ }
1332
+ else {
1333
+ if(unlikely(st->debug)) debug(D_RRD_STATS, "%s/%s: STORE[%ld] = NON EXISTING "
1334
+ , st->id, rd->name
1335
+ , st->current_entry
1336
+ );
1337
+ rd->values[st->current_entry] = pack_storage_number(0, SN_NOT_EXISTS);
1338
+ }
1339
+
1340
+ stored_entries++;
1341
+
1342
+ if(unlikely(st->debug)) {
1343
+ calculated_number t1 = new_value * (calculated_number)rd->multiplier / (calculated_number)rd->divisor;
1344
+ calculated_number t2 = unpack_storage_number(rd->values[st->current_entry]);
1345
+ calculated_number accuracy = accuracy_loss(t1, t2);
1346
+ debug(D_RRD_STATS, "%s/%s: UNPACK[%ld] = " CALCULATED_NUMBER_FORMAT " FLAGS=0x%08x (original = " CALCULATED_NUMBER_FORMAT ", accuracy loss = " CALCULATED_NUMBER_FORMAT "%%%s)"
1347
+ , st->id, rd->name
1348
+ , st->current_entry
1349
+ , t2
1350
+ , get_storage_number_flags(rd->values[st->current_entry])
1351
+ , t1
1352
+ , accuracy
1353
+ , (accuracy > ACCURACY_LOSS) ? " **TOO BIG** " : ""
1354
+ );
1355
+
1356
+ rd->collected_volume += t1;
1357
+ rd->stored_volume += t2;
1358
+ accuracy = accuracy_loss(rd->collected_volume, rd->stored_volume);
1359
+ debug(D_RRD_STATS, "%s/%s: VOLUME[%ld] = " CALCULATED_NUMBER_FORMAT ", calculated = " CALCULATED_NUMBER_FORMAT ", accuracy loss = " CALCULATED_NUMBER_FORMAT "%%%s"
1360
+ , st->id, rd->name
1361
+ , st->current_entry
1362
+ , rd->stored_volume
1363
+ , rd->collected_volume
1364
+ , accuracy
1365
+ , (accuracy > ACCURACY_LOSS) ? " **TOO BIG** " : ""
1366
+ );
1367
+
1368
+ }
1369
+ }
1370
+ // reset the storage flags for the next point, if any;
1371
+ storage_flags = SN_EXISTS;
1372
+
1373
+ st->counter++;
1374
+ st->current_entry = ((st->current_entry + 1) >= st->entries) ? 0 : st->current_entry + 1;
1375
+ last_ut = next_ut;
1376
+ }
1377
+
1378
+ // align next interpolation to last collection point
1379
+ if(likely(stored_entries || !store_this_entry)) {
1380
+ st->last_updated.tv_sec = st->last_collected_time.tv_sec;
1381
+ st->last_updated.tv_usec = st->last_collected_time.tv_usec;
1382
+ st->last_collected_total = st->collected_total;
1383
+ }
1384
+
1385
+ for( rd = st->dimensions; likely(rd) ; rd = rd->next ) {
1386
+ if(unlikely(!rd->updated)) continue;
1387
+
1388
+ if(likely(stored_entries || !store_this_entry)) {
1389
+ if(unlikely(st->debug)) debug(D_RRD_STATS, "%s/%s: setting last_collected_value (old: " COLLECTED_NUMBER_FORMAT ") to last_collected_value (new: " COLLECTED_NUMBER_FORMAT ")", st->id, rd->name, rd->last_collected_value, rd->collected_value);
1390
+ rd->last_collected_value = rd->collected_value;
1391
+
1392
+ if(unlikely(st->debug)) debug(D_RRD_STATS, "%s/%s: setting last_calculated_value (old: " CALCULATED_NUMBER_FORMAT ") to last_calculated_value (new: " CALCULATED_NUMBER_FORMAT ")", st->id, rd->name, rd->last_calculated_value, rd->calculated_value);
1393
+ rd->last_calculated_value = rd->calculated_value;
1394
+ }
1395
+
1396
+ rd->calculated_value = 0;
1397
+ rd->collected_value = 0;
1398
+ rd->updated = 0;
1399
+
1400
+ if(unlikely(st->debug)) debug(D_RRD_STATS, "%s/%s: END "
1401
+ " last_collected_value = " COLLECTED_NUMBER_FORMAT
1402
+ " collected_value = " COLLECTED_NUMBER_FORMAT
1403
+ " last_calculated_value = " CALCULATED_NUMBER_FORMAT
1404
+ " calculated_value = " CALCULATED_NUMBER_FORMAT
1405
+ , st->id, rd->name
1406
+ , rd->last_collected_value
1407
+ , rd->collected_value
1408
+ , rd->last_calculated_value
1409
+ , rd->calculated_value
1410
+ );
1411
+ }
1412
+
1413
+ // ALL DONE ABOUT THE DATA UPDATE
1414
+ // --------------------------------------------------------------------
1415
+
1416
+ // find if there are any obsolete dimensions (not updated recently)
1417
+ if(unlikely(rrd_delete_unupdated_dimensions)) {
1418
+
1419
+ for( rd = st->dimensions; likely(rd) ; rd = rd->next )
1420
+ if((rd->last_collected_time.tv_sec + (rrd_delete_unupdated_dimensions * st->update_every)) < st->last_collected_time.tv_sec)
1421
+ break;
1422
+
1423
+ if(unlikely(rd)) {
1424
+ // there is dimension to free
1425
+ // upgrade our read lock to a write lock
1426
+ pthread_rwlock_unlock(&st->rwlock);
1427
+ pthread_rwlock_wrlock(&st->rwlock);
1428
+
1429
+ for( rd = st->dimensions, last = NULL ; likely(rd) ; ) {
1430
+ // remove it only it is not updated in rrd_delete_unupdated_dimensions seconds
1431
+
1432
+ if(unlikely((rd->last_collected_time.tv_sec + (rrd_delete_unupdated_dimensions * st->update_every)) < st->last_collected_time.tv_sec)) {
1433
+ info("Removing obsolete dimension '%s' (%s) of '%s' (%s).", rd->name, rd->id, st->name, st->id);
1434
+
1435
+ if(unlikely(!last)) {
1436
+ st->dimensions = rd->next;
1437
+ rd->next = NULL;
1438
+ rrddim_free(st, rd);
1439
+ rd = st->dimensions;
1440
+ continue;
1441
+ }
1442
+ else {
1443
+ last->next = rd->next;
1444
+ rd->next = NULL;
1445
+ rrddim_free(st, rd);
1446
+ rd = last->next;
1447
+ continue;
1448
+ }
1449
+ }
1450
+
1451
+ last = rd;
1452
+ rd = rd->next;
1453
+ }
1454
+
1455
+ if(unlikely(!st->dimensions)) {
1456
+ info("Disabling chart %s (%s) since it does not have any dimensions", st->name, st->id);
1457
+ st->enabled = 0;
1458
+ }
1459
+ }
1460
+ }
1461
+
1462
+ pthread_rwlock_unlock(&st->rwlock);
1463
+
1464
+ if(unlikely(pthread_setcancelstate(oldstate, NULL) != 0))
1465
+ error("Cannot set pthread cancel state to RESTORE (%d).", oldstate);
1466
+
1467
+ return(st->usec_since_last_update);
1468
}
src/rrd.h
+143
-143
@@ -15,8 +15,8 @@ extern int rrd_delete_unupdated_dimensions;
15
16
#define RRD_ID_LENGTH_MAX 1024
17
18
-#define RRDSET_MAGIC "NETDATA RRD SET FILE V018"
19
-#define RRDDIMENSION_MAGIC "NETDATA RRD DIMENSION FILE V018"
18
+#define RRDSET_MAGIC "NETDATA RRD SET FILE V018"
19
+#define RRDDIMENSION_MAGIC "NETDATA RRD DIMENSION FILE V018"
20
21
typedef long long total_number;
22
#define TOTAL_NUMBER_FORMAT "%lld"
@@ -28,8 +28,8 @@ typedef long long total_number;
28
#define RRDSET_TYPE_AREA_NAME "area"
29
#define RRDSET_TYPE_STACKED_NAME "stacked"
30
31
-#define RRDSET_TYPE_LINE 0
32
-#define RRDSET_TYPE_AREA 1
31
+#define RRDSET_TYPE_LINE 0
32
+#define RRDSET_TYPE_AREA 1
33
#define RRDSET_TYPE_STACKED 2
34
35
int rrdset_type_id(const char *name);
@@ -56,15 +56,15 @@ extern int rrd_memory_mode_id(const char *name);
56
// ----------------------------------------------------------------------------
57
// algorithms types
58
59
-#define RRDDIM_ABSOLUTE_NAME "absolute"
60
-#define RRDDIM_INCREMENTAL_NAME "incremental"
61
-#define RRDDIM_PCENT_OVER_DIFF_TOTAL_NAME "percentage-of-incremental-row"
62
-#define RRDDIM_PCENT_OVER_ROW_TOTAL_NAME "percentage-of-absolute-row"
59
+#define RRDDIM_ABSOLUTE_NAME "absolute"
60
+#define RRDDIM_INCREMENTAL_NAME "incremental"
61
+#define RRDDIM_PCENT_OVER_DIFF_TOTAL_NAME "percentage-of-incremental-row"
62
+#define RRDDIM_PCENT_OVER_ROW_TOTAL_NAME "percentage-of-absolute-row"
63
64
-#define RRDDIM_ABSOLUTE 0
65
-#define RRDDIM_INCREMENTAL 1
66
-#define RRDDIM_PCENT_OVER_DIFF_TOTAL 2
67
-#define RRDDIM_PCENT_OVER_ROW_TOTAL 3
64
+#define RRDDIM_ABSOLUTE 0
65
+#define RRDDIM_INCREMENTAL 1
66
+#define RRDDIM_PCENT_OVER_DIFF_TOTAL 2
67
+#define RRDDIM_PCENT_OVER_ROW_TOTAL 3
68
69
extern int rrddim_algorithm_id(const char *name);
70
extern const char *rrddim_algorithm_name(int chart_type);
@@ -94,83 +94,83 @@ typedef struct rrdcontext RRDCONTEXT;
94
// RRD DIMENSION
95
96
struct rrddim {
97
- // ------------------------------------------------------------------------
98
- // binary indexing structures
97
+ // ------------------------------------------------------------------------
98
+ // binary indexing structures
99
100
- avl avl; // the binary index - this has to be first member!
100
+ avl avl; // the binary index - this has to be first member!
101
102
- // ------------------------------------------------------------------------
103
- // the dimension definition
102
+ // ------------------------------------------------------------------------
103
+ // the dimension definition
104
105
- char id[RRD_ID_LENGTH_MAX + 1]; // the id of this dimension (for internal identification)
105
+ char id[RRD_ID_LENGTH_MAX + 1]; // the id of this dimension (for internal identification)
106
107
- const char *name; // the name of this dimension (as presented to user)
108
- // this is a pointer to the config structure
109
- // since the config always has a higher priority
110
- // (the user overwrites the name of the charts)
107
+ const char *name; // the name of this dimension (as presented to user)
108
+ // this is a pointer to the config structure
109
+ // since the config always has a higher priority
110
+ // (the user overwrites the name of the charts)
111
112
- int algorithm; // the algorithm that is applied to add new collected values
113
- long multiplier; // the multiplier of the collected values
114
- long divisor; // the divider of the collected values
112
+ int algorithm; // the algorithm that is applied to add new collected values
113
+ long multiplier; // the multiplier of the collected values
114
+ long divisor; // the divider of the collected values
115
116
- int mapped; // if set to non zero, this dimension is mapped to a file
116
+ int mapped; // if set to non zero, this dimension is mapped to a file
117
118
- // ------------------------------------------------------------------------
119
- // members for temporary data we need for calculations
118
+ // ------------------------------------------------------------------------
119
+ // members for temporary data we need for calculations
120
121
- uint32_t hash; // a simple hash of the id, to speed up searching / indexing
122
- // instead of strcmp() every item in the binary index
123
- // we first compare the hashes
121
+ uint32_t hash; // a simple hash of the id, to speed up searching / indexing
122
+ // instead of strcmp() every item in the binary index
123
+ // we first compare the hashes
124
125
- // FIXME
126
- // we need the hash_name too!
125
+ // FIXME
126
+ // we need the hash_name too!
127
128
- uint32_t flags;
128
+ uint32_t flags;
129
130
- char cache_filename[FILENAME_MAX+1]; // the filename we load/save from/to this set
130
+ char cache_filename[FILENAME_MAX+1]; // the filename we load/save from/to this set
131
132
- unsigned long counter; // the number of times we added values to this rrdim
132
+ unsigned long counter; // the number of times we added values to this rrdim
133
134
- int updated; // set to 0 after each calculation, to 1 after each collected value
135
- // we use this to detect that a dimension is not updated
134
+ int updated; // set to 0 after each calculation, to 1 after each collected value
135
+ // we use this to detect that a dimension is not updated
136
137
- struct timeval last_collected_time; // when was this dimension last updated
138
- // this is actual date time we updated the last_collected_value
139
- // THIS IS DIFFERENT FROM THE SAME MEMBER OF RRDSET
137
+ struct timeval last_collected_time; // when was this dimension last updated
138
+ // this is actual date time we updated the last_collected_value
139
+ // THIS IS DIFFERENT FROM THE SAME MEMBER OF RRDSET
140
141
- calculated_number calculated_value; // the current calculated value, after applying the algorithm
142
- calculated_number last_calculated_value; // the last calculated value
141
+ calculated_number calculated_value; // the current calculated value, after applying the algorithm
142
+ calculated_number last_calculated_value; // the last calculated value
143
144
- collected_number collected_value; // the current value, as collected
145
- collected_number last_collected_value; // the last value that was collected
144
+ collected_number collected_value; // the current value, as collected
145
+ collected_number last_collected_value; // the last value that was collected
146
147
- // the *_volume members are used to calculate the accuracy of the rounding done by the
148
- // storage number - they are printed to debug.log when debug is enabled for a set.
149
- calculated_number collected_volume; // the sum of all collected values so far
150
- calculated_number stored_volume; // the sum of all stored values so far
147
+ // the *_volume members are used to calculate the accuracy of the rounding done by the
148
+ // storage number - they are printed to debug.log when debug is enabled for a set.
149
+ calculated_number collected_volume; // the sum of all collected values so far
150
+ calculated_number stored_volume; // the sum of all stored values so far
151
152
- struct rrddim *next; // linking of dimensions within the same data set
152
+ struct rrddim *next; // linking of dimensions within the same data set
153
struct rrdset *rrdset;
154
155
- // ------------------------------------------------------------------------
156
- // members for checking the data when loading from disk
155
+ // ------------------------------------------------------------------------
156
+ // members for checking the data when loading from disk
157
158
- long entries; // how many entries this dimension has in ram
159
- // this is the same to the entries of the data set
160
- // we set it here, to check the data when we load it from disk.
158
+ long entries; // how many entries this dimension has in ram
159
+ // this is the same to the entries of the data set
160
+ // we set it here, to check the data when we load it from disk.
161
162
- int update_every; // every how many seconds is this updated
162
+ int update_every; // every how many seconds is this updated
163
164
- unsigned long memsize; // the memory allocated for this dimension
164
+ unsigned long memsize; // the memory allocated for this dimension
165
166
- char magic[sizeof(RRDDIMENSION_MAGIC) + 1]; // a string to be saved, used to identify our data file
166
+ char magic[sizeof(RRDDIMENSION_MAGIC) + 1]; // a string to be saved, used to identify our data file
167
168
struct rrddimvar *variables;
169
170
- // ------------------------------------------------------------------------
171
- // the values stored in this dimension, using our floating point numbers
170
+ // ------------------------------------------------------------------------
171
+ // the values stored in this dimension, using our floating point numbers
172
173
- storage_number values[]; // the array of values - THIS HAS TO BE THE LAST MEMBER
173
+ storage_number values[]; // the array of values - THIS HAS TO BE THE LAST MEMBER
174
};
175
typedef struct rrddim RRDDIM;
176
@@ -179,99 +179,99 @@ typedef struct rrddim RRDDIM;
179
// RRDSET
180
181
struct rrdset {
182
- // ------------------------------------------------------------------------
183
- // binary indexing structures
182
+ // ------------------------------------------------------------------------
183
+ // binary indexing structures
184
185
- avl avl; // the index, with key the id - this has to be first!
186
- avl avlname; // the index, with key the name
185
+ avl avl; // the index, with key the id - this has to be first!
186
+ avl avlname; // the index, with key the name
187
188
- // ------------------------------------------------------------------------
189
- // the set configuration
188
+ // ------------------------------------------------------------------------
189
+ // the set configuration
190
191
- char id[RRD_ID_LENGTH_MAX + 1]; // id of the data set
191
+ char id[RRD_ID_LENGTH_MAX + 1]; // id of the data set
192
193
- const char *name; // the name of this dimension (as presented to user)
194
- // this is a pointer to the config structure
195
- // since the config always has a higher priority
196
- // (the user overwrites the name of the charts)
193
+ const char *name; // the name of this dimension (as presented to user)
194
+ // this is a pointer to the config structure
195
+ // since the config always has a higher priority
196
+ // (the user overwrites the name of the charts)
197
198
- char *type; // the type of graph RRD_TYPE_* (a category, for determining graphing options)
199
- char *family; // grouping sets under the same family
200
- char *context; // the template of this data set
201
- char *title; // title shown to user
202
- char *units; // units of measurement
198
+ char *type; // the type of graph RRD_TYPE_* (a category, for determining graphing options)
199
+ char *family; // grouping sets under the same family
200
+ char *context; // the template of this data set
201
+ char *title; // title shown to user
202
+ char *units; // units of measurement
203
204
- int chart_type;
204
+ int chart_type;
205
206
- int update_every; // every how many seconds is this updated?
206
+ int update_every; // every how many seconds is this updated?
207
208
- long entries; // total number of entries in the data set
208
+ long entries; // total number of entries in the data set
209
210
- long current_entry; // the entry that is currently being updated
211
- // it goes around in a round-robin fashion
210
+ long current_entry; // the entry that is currently being updated
211
+ // it goes around in a round-robin fashion
212
213
- int enabled;
213
+ int enabled;
214
215
- int gap_when_lost_iterations_above; // after how many lost iterations a gap should be stored
216
- // netdata will interpolate values for gaps lower than this
215
+ int gap_when_lost_iterations_above; // after how many lost iterations a gap should be stored
216
+ // netdata will interpolate values for gaps lower than this
217
218
- long priority;
218
+ long priority;
219
220
- int isdetail; // if set, the data set should be considered as a detail of another
221
- // (the master data set should be the one that has the same family and is not detail)
220
+ int isdetail; // if set, the data set should be considered as a detail of another
221
+ // (the master data set should be the one that has the same family and is not detail)
222
223
- // ------------------------------------------------------------------------
224
- // members for temporary data we need for calculations
223
+ // ------------------------------------------------------------------------
224
+ // members for temporary data we need for calculations
225
226
- int mapped; // if set to 1, this is memory mapped
226
+ int mapped; // if set to 1, this is memory mapped
227
228
- int debug;
228
+ int debug;
229
230
- char *cache_dir; // the directory to store dimensions
231
- char cache_filename[FILENAME_MAX+1]; // the filename to store this set
230
+ char *cache_dir; // the directory to store dimensions
231
+ char cache_filename[FILENAME_MAX+1]; // the filename to store this set
232
233
- pthread_rwlock_t rwlock;
233
+ pthread_rwlock_t rwlock;
234
235
- unsigned long counter; // the number of times we added values to this rrd
236
- unsigned long counter_done; // the number of times we added values to this rrd
235
+ unsigned long counter; // the number of times we added values to this rrd
236
+ unsigned long counter_done; // the number of times we added values to this rrd
237
238
- uint32_t hash; // a simple hash on the id, to speed up searching
239
- // we first compare hashes, and only if the hashes are equal we do string comparisons
238
+ uint32_t hash; // a simple hash on the id, to speed up searching
239
+ // we first compare hashes, and only if the hashes are equal we do string comparisons
240
241
- uint32_t hash_name; // a simple hash on the name
241
+ uint32_t hash_name; // a simple hash on the name
242
243
- unsigned long long usec_since_last_update; // the time in microseconds since the last collection of data
243
+ unsigned long long usec_since_last_update; // the time in microseconds since the last collection of data
244
245
- struct timeval last_updated; // when this data set was last updated (updated every time the rrd_stats_done() function)
246
- struct timeval last_collected_time; // when did this data set last collected values
245
+ struct timeval last_updated; // when this data set was last updated (updated every time the rrd_stats_done() function)
246
+ struct timeval last_collected_time; // when did this data set last collected values
247
248
- total_number collected_total; // used internally to calculate percentages
249
- total_number last_collected_total; // used internally to calculate percentages
248
+ total_number collected_total; // used internally to calculate percentages
249
+ total_number last_collected_total; // used internally to calculate percentages
250
251
RRDCONTEXT *rrdcontext;
252
struct rrdhost *rrdhost;
253
254
- struct rrdset *next; // linking of rrdsets
254
+ struct rrdset *next; // linking of rrdsets
255
256
- // ------------------------------------------------------------------------
257
- // local variables
256
+ // ------------------------------------------------------------------------
257
+ // local variables
258
259
- avl_tree_lock variables_root_index;
260
- RRDSETVAR *variables;
261
- RRDCALC *calculations;
259
+ avl_tree_lock variables_root_index;
260
+ RRDSETVAR *variables;
261
+ RRDCALC *calculations;
262
263
- // ------------------------------------------------------------------------
264
- // members for checking the data when loading from disk
263
+ // ------------------------------------------------------------------------
264
+ // members for checking the data when loading from disk
265
266
- unsigned long memsize; // how much mem we have allocated for this (without dimensions)
266
+ unsigned long memsize; // how much mem we have allocated for this (without dimensions)
267
268
- char magic[sizeof(RRDSET_MAGIC) + 1]; // our magic
268
+ char magic[sizeof(RRDSET_MAGIC) + 1]; // our magic
269
270
- // ------------------------------------------------------------------------
271
- // the dimensions
270
+ // ------------------------------------------------------------------------
271
+ // the dimensions
272
273
- avl_tree_lock dimensions_index; // the root of the dimensions index
274
- RRDDIM *dimensions; // the actual data for every dimension
273
+ avl_tree_lock dimensions_index; // the root of the dimensions index
274
+ RRDDIM *dimensions; // the actual data for every dimension
275
276
};
277
typedef struct rrdset RRDSET;
@@ -293,10 +293,10 @@ struct rrdhost {
293
avl_tree_lock rrdcontext_root_index;
294
avl_tree_lock variables_root_index;
295
296
- // all RRDCALCs are primarily allocated and linked here
297
- // RRDCALCs may be linked to charts at any point
298
- // (charts may or may not exist when these are loaded)
299
- RRDCALC *calculations;
296
+ // all RRDCALCs are primarily allocated and linked here
297
+ // RRDCALCs may be linked to charts at any point
298
+ // (charts may or may not exist when these are loaded)
299
+ RRDCALC *calculations;
300
301
// all variable references are linked here
302
// RRDVARs may be free'd, so every time this happens
@@ -324,15 +324,15 @@ extern char *rrdset_cache_dir(const char *id);
324
extern void rrdset_reset(RRDSET *st);
325
326
extern RRDSET *rrdset_create(const char *type
327
- , const char *id
328
- , const char *name
329
- , const char *family
330
- , const char *context
331
- , const char *title
332
- , const char *units
333
- , long priority
334
- , int update_every
335
- , int chart_type);
327
+ , const char *id
328
+ , const char *name
329
+ , const char *family
330
+ , const char *context
331
+ , const char *title
332
+ , const char *units
333
+ , long priority
334
+ , int update_every
335
+ , int chart_type);
336
337
extern void rrdset_free_all(void);
338
extern void rrdset_save_all(void);
@@ -365,20 +365,20 @@ extern unsigned long long rrdset_done(RRDSET *st);
365
// get the slot of the round robin database, for the given timestamp (t)
366
// it always returns a valid slot, although may not be for the time requested if the time is outside the round robin database
367
#define rrdset_time2slot(st, t) ( \
368
- ( (time_t)(t) >= rrdset_last_entry_t(st)) ? ( rrdset_last_slot(st) ) : \
369
- ( ((time_t)(t) <= rrdset_first_entry_t(st)) ? rrdset_first_slot(st) : \
370
- ( (rrdset_last_slot(st) >= (unsigned long)((rrdset_last_entry_t(st) - (time_t)(t)) / (unsigned long)((st)->update_every)) ) ? \
371
- (rrdset_last_slot(st) - (unsigned long)((rrdset_last_entry_t(st) - (time_t)(t)) / (unsigned long)((st)->update_every)) ) : \
372
- (rrdset_last_slot(st) - (unsigned long)((rrdset_last_entry_t(st) - (time_t)(t)) / (unsigned long)((st)->update_every)) + (unsigned long)(st)->entries ) \
373
- )))
368
+ ( (time_t)(t) >= rrdset_last_entry_t(st)) ? ( rrdset_last_slot(st) ) : \
369
+ ( ((time_t)(t) <= rrdset_first_entry_t(st)) ? rrdset_first_slot(st) : \
370
+ ( (rrdset_last_slot(st) >= (unsigned long)((rrdset_last_entry_t(st) - (time_t)(t)) / (unsigned long)((st)->update_every)) ) ? \
371
+ (rrdset_last_slot(st) - (unsigned long)((rrdset_last_entry_t(st) - (time_t)(t)) / (unsigned long)((st)->update_every)) ) : \
372
+ (rrdset_last_slot(st) - (unsigned long)((rrdset_last_entry_t(st) - (time_t)(t)) / (unsigned long)((st)->update_every)) + (unsigned long)(st)->entries ) \
373
+ )))
374
375
// get the timestamp of a specific slot in the round robin database
376
#define rrdset_slot2time(st, slot) ( rrdset_last_entry_t(st) - \
377
- ((unsigned long)(st)->update_every * ( \
378
- ( (unsigned long)(slot) > rrdset_last_slot(st)) ? \
379
- ( (rrdset_last_slot(st) - (unsigned long)(slot) + (unsigned long)(st)->entries) ) : \
380
- ( (rrdset_last_slot(st) - (unsigned long)(slot)) )) \
381
- ))
377
+ ((unsigned long)(st)->update_every * ( \
378
+ ( (unsigned long)(slot) > rrdset_last_slot(st)) ? \
379
+ ( (rrdset_last_slot(st) - (unsigned long)(slot) + (unsigned long)(st)->entries) ) : \
380
+ ( (rrdset_last_slot(st) - (unsigned long)(slot)) )) \
381
+ ))
382
383
// ----------------------------------------------------------------------------
384
// RRD DIMENSION functions
src/rrd2json.c
+1851
-1851
@@ -5,207 +5,207 @@ char *hostname = "unknown";
5
6
void rrd_stats_api_v1_chart(RRDSET *st, BUFFER *wb)
7
{
8
- pthread_rwlock_rdlock(&st->rwlock);
9
-
10
- buffer_sprintf(wb,
11
- "\t\t{\n"
12
- "\t\t\t\"id\": \"%s\",\n"
13
- "\t\t\t\"name\": \"%s\",\n"
14
- "\t\t\t\"type\": \"%s\",\n"
15
- "\t\t\t\"family\": \"%s\",\n"
16
- "\t\t\t\"context\": \"%s\",\n"
17
- "\t\t\t\"title\": \"%s\",\n"
18
- "\t\t\t\"priority\": %ld,\n"
19
- "\t\t\t\"enabled\": %s,\n"
20
- "\t\t\t\"units\": \"%s\",\n"
21
- "\t\t\t\"data_url\": \"/api/v1/data?chart=%s\",\n"
22
- "\t\t\t\"chart_type\": \"%s\",\n"
23
- "\t\t\t\"duration\": %ld,\n"
24
- "\t\t\t\"first_entry\": %ld,\n"
25
- "\t\t\t\"last_entry\": %ld,\n"
26
- "\t\t\t\"update_every\": %d,\n"
27
- "\t\t\t\"dimensions\": {\n"
28
- , st->id
29
- , st->name
30
- , st->type
31
- , st->family
32
- , st->context
33
- , st->title
34
- , st->priority
35
- , st->enabled?"true":"false"
36
- , st->units
37
- , st->name
38
- , rrdset_type_name(st->chart_type)
39
- , st->entries * st->update_every
40
- , rrdset_first_entry_t(st)
41
- , rrdset_last_entry_t(st)
42
- , st->update_every
43
- );
44
-
45
- unsigned long memory = st->memsize;
46
-
47
- int c = 0;
48
- RRDDIM *rd;
49
- for(rd = st->dimensions; rd ; rd = rd->next) {
50
- if(rd->flags & RRDDIM_FLAG_HIDDEN) continue;
51
-
52
- memory += rd->memsize;
53
-
54
- buffer_sprintf(wb,
55
- "%s"
56
- "\t\t\t\t\"%s\": { \"name\": \"%s\" }"
57
- , c?",\n":""
58
- , rd->id
59
- , rd->name
60
- );
61
-
62
- c++;
63
- }
64
-
65
- buffer_sprintf(wb,
66
- "\n\t\t\t}\n"
67
- "\t\t}"
68
- );
69
-
70
- pthread_rwlock_unlock(&st->rwlock);
8
+ pthread_rwlock_rdlock(&st->rwlock);
9
+
10
+ buffer_sprintf(wb,
11
+ "\t\t{\n"
12
+ "\t\t\t\"id\": \"%s\",\n"
13
+ "\t\t\t\"name\": \"%s\",\n"
14
+ "\t\t\t\"type\": \"%s\",\n"
15
+ "\t\t\t\"family\": \"%s\",\n"
16
+ "\t\t\t\"context\": \"%s\",\n"
17
+ "\t\t\t\"title\": \"%s\",\n"
18
+ "\t\t\t\"priority\": %ld,\n"
19
+ "\t\t\t\"enabled\": %s,\n"
20
+ "\t\t\t\"units\": \"%s\",\n"
21
+ "\t\t\t\"data_url\": \"/api/v1/data?chart=%s\",\n"
22
+ "\t\t\t\"chart_type\": \"%s\",\n"
23
+ "\t\t\t\"duration\": %ld,\n"
24
+ "\t\t\t\"first_entry\": %ld,\n"
25
+ "\t\t\t\"last_entry\": %ld,\n"
26
+ "\t\t\t\"update_every\": %d,\n"
27
+ "\t\t\t\"dimensions\": {\n"
28
+ , st->id
29
+ , st->name
30
+ , st->type
31
+ , st->family
32
+ , st->context
33
+ , st->title
34
+ , st->priority
35
+ , st->enabled?"true":"false"
36
+ , st->units
37
+ , st->name
38
+ , rrdset_type_name(st->chart_type)
39
+ , st->entries * st->update_every
40
+ , rrdset_first_entry_t(st)
41
+ , rrdset_last_entry_t(st)
42
+ , st->update_every
43
+ );
44
+
45
+ unsigned long memory = st->memsize;
46
+
47
+ int c = 0;
48
+ RRDDIM *rd;
49
+ for(rd = st->dimensions; rd ; rd = rd->next) {
50
+ if(rd->flags & RRDDIM_FLAG_HIDDEN) continue;
51
+
52
+ memory += rd->memsize;
53
+
54
+ buffer_sprintf(wb,
55
+ "%s"
56
+ "\t\t\t\t\"%s\": { \"name\": \"%s\" }"
57
+ , c?",\n":""
58
+ , rd->id
59
+ , rd->name
60
+ );
61
+
62
+ c++;
63
+ }
64
+
65
+ buffer_sprintf(wb,
66
+ "\n\t\t\t}\n"
67
+ "\t\t}"
68
+ );
69
+
70
+ pthread_rwlock_unlock(&st->rwlock);
71
}
72
73
void rrd_stats_api_v1_charts(BUFFER *wb)
74
{
75
- long c;
76
- RRDSET *st;
77
-
78
- buffer_sprintf(wb, "{\n"
79
- "\t\"hostname\": \"%s\""
80
- ",\n\t\"update_every\": %d"
81
- ",\n\t\"history\": %d"
82
- ",\n\t\"charts\": {"
83
- , hostname
84
- , rrd_update_every
85
- , rrd_default_history_entries
86
- );
87
-
88
- pthread_rwlock_rdlock(&localhost.rrdset_root_rwlock);
89
- for(st = localhost.rrdset_root, c = 0; st ; st = st->next) {
90
- if(st->enabled && st->dimensions) {
91
- if(c) buffer_strcat(wb, ",");
92
- buffer_strcat(wb, "\n\t\t\"");
93
- buffer_strcat(wb, st->id);
94
- buffer_strcat(wb, "\": ");
95
- rrd_stats_api_v1_chart(st, wb);
96
- c++;
97
- }
98
- }
99
- pthread_rwlock_unlock(&localhost.rrdset_root_rwlock);
100
-
101
- buffer_strcat(wb, "\n\t}\n}\n");
75
+ long c;
76
+ RRDSET *st;
77
+
78
+ buffer_sprintf(wb, "{\n"
79
+ "\t\"hostname\": \"%s\""
80
+ ",\n\t\"update_every\": %d"
81
+ ",\n\t\"history\": %d"
82
+ ",\n\t\"charts\": {"
83
+ , hostname
84
+ , rrd_update_every
85
+ , rrd_default_history_entries
86
+ );
87
+
88
+ pthread_rwlock_rdlock(&localhost.rrdset_root_rwlock);
89
+ for(st = localhost.rrdset_root, c = 0; st ; st = st->next) {
90
+ if(st->enabled && st->dimensions) {
91
+ if(c) buffer_strcat(wb, ",");
92
+ buffer_strcat(wb, "\n\t\t\"");
93
+ buffer_strcat(wb, st->id);
94
+ buffer_strcat(wb, "\": ");
95
+ rrd_stats_api_v1_chart(st, wb);
96
+ c++;
97
+ }
98
+ }
99
+ pthread_rwlock_unlock(&localhost.rrdset_root_rwlock);
100
+
101
+ buffer_strcat(wb, "\n\t}\n}\n");
102
}
103
104
105
unsigned long rrd_stats_one_json(RRDSET *st, char *options, BUFFER *wb)
106
{
107
- time_t now = time(NULL);
108
-
109
- pthread_rwlock_rdlock(&st->rwlock);
110
-
111
- buffer_sprintf(wb,
112
- "\t\t{\n"
113
- "\t\t\t\"id\": \"%s\",\n"
114
- "\t\t\t\"name\": \"%s\",\n"
115
- "\t\t\t\"type\": \"%s\",\n"
116
- "\t\t\t\"family\": \"%s\",\n"
117
- "\t\t\t\"context\": \"%s\",\n"
118
- "\t\t\t\"title\": \"%s\",\n"
119
- "\t\t\t\"priority\": %ld,\n"
120
- "\t\t\t\"enabled\": %d,\n"
121
- "\t\t\t\"units\": \"%s\",\n"
122
- "\t\t\t\"url\": \"/data/%s/%s\",\n"
123
- "\t\t\t\"chart_type\": \"%s\",\n"
124
- "\t\t\t\"counter\": %lu,\n"
125
- "\t\t\t\"entries\": %ld,\n"
126
- "\t\t\t\"first_entry_t\": %ld,\n"
127
- "\t\t\t\"last_entry\": %lu,\n"
128
- "\t\t\t\"last_entry_t\": %ld,\n"
129
- "\t\t\t\"last_entry_secs_ago\": %ld,\n"
130
- "\t\t\t\"update_every\": %d,\n"
131
- "\t\t\t\"isdetail\": %d,\n"
132
- "\t\t\t\"usec_since_last_update\": %llu,\n"
133
- "\t\t\t\"collected_total\": " TOTAL_NUMBER_FORMAT ",\n"
134
- "\t\t\t\"last_collected_total\": " TOTAL_NUMBER_FORMAT ",\n"
135
- "\t\t\t\"dimensions\": [\n"
136
- , st->id
137
- , st->name
138
- , st->type
139
- , st->family
140
- , st->context
141
- , st->title
142
- , st->priority
143
- , st->enabled
144
- , st->units
145
- , st->name, options?options:""
146
- , rrdset_type_name(st->chart_type)
147
- , st->counter
148
- , st->entries
149
- , rrdset_first_entry_t(st)
150
- , rrdset_last_slot(st)
151
- , rrdset_last_entry_t(st)
152
- , (now < rrdset_last_entry_t(st)) ? (time_t)0 : now - rrdset_last_entry_t(st)
153
- , st->update_every
154
- , st->isdetail
155
- , st->usec_since_last_update
156
- , st->collected_total
157
- , st->last_collected_total
158
- );
159
-
160
- unsigned long memory = st->memsize;
161
-
162
- RRDDIM *rd;
163
- for(rd = st->dimensions; rd ; rd = rd->next) {
164
-
165
- memory += rd->memsize;
166
-
167
- buffer_sprintf(wb,
168
- "\t\t\t\t{\n"
169
- "\t\t\t\t\t\"id\": \"%s\",\n"
170
- "\t\t\t\t\t\"name\": \"%s\",\n"
171
- "\t\t\t\t\t\"entries\": %ld,\n"
172
- "\t\t\t\t\t\"isHidden\": %d,\n"
173
- "\t\t\t\t\t\"algorithm\": \"%s\",\n"
174
- "\t\t\t\t\t\"multiplier\": %ld,\n"
175
- "\t\t\t\t\t\"divisor\": %ld,\n"
176
- "\t\t\t\t\t\"last_entry_t\": %ld,\n"
177
- "\t\t\t\t\t\"collected_value\": " COLLECTED_NUMBER_FORMAT ",\n"
178
- "\t\t\t\t\t\"calculated_value\": " CALCULATED_NUMBER_FORMAT ",\n"
179
- "\t\t\t\t\t\"last_collected_value\": " COLLECTED_NUMBER_FORMAT ",\n"
180
- "\t\t\t\t\t\"last_calculated_value\": " CALCULATED_NUMBER_FORMAT ",\n"
181
- "\t\t\t\t\t\"memory\": %lu\n"
182
- "\t\t\t\t}%s\n"
183
- , rd->id
184
- , rd->name
185
- , rd->entries
186
- , (rd->flags & RRDDIM_FLAG_HIDDEN)?1:0
187
- , rrddim_algorithm_name(rd->algorithm)
188
- , rd->multiplier
189
- , rd->divisor
190
- , rd->last_collected_time.tv_sec
191
- , rd->collected_value
192
- , rd->calculated_value
193
- , rd->last_collected_value
194
- , rd->last_calculated_value
195
- , rd->memsize
196
- , rd->next?",":""
197
- );
198
- }
199
-
200
- buffer_sprintf(wb,
201
- "\t\t\t],\n"
202
- "\t\t\t\"memory\" : %lu\n"
203
- "\t\t}"
204
- , memory
205
- );
206
-
207
- pthread_rwlock_unlock(&st->rwlock);
208
- return memory;
107
+ time_t now = time(NULL);
108
+
109
+ pthread_rwlock_rdlock(&st->rwlock);
110
+
111
+ buffer_sprintf(wb,
112
+ "\t\t{\n"
113
+ "\t\t\t\"id\": \"%s\",\n"
114
+ "\t\t\t\"name\": \"%s\",\n"
115
+ "\t\t\t\"type\": \"%s\",\n"
116
+ "\t\t\t\"family\": \"%s\",\n"
117
+ "\t\t\t\"context\": \"%s\",\n"
118
+ "\t\t\t\"title\": \"%s\",\n"
119
+ "\t\t\t\"priority\": %ld,\n"
120
+ "\t\t\t\"enabled\": %d,\n"
121
+ "\t\t\t\"units\": \"%s\",\n"
122
+ "\t\t\t\"url\": \"/data/%s/%s\",\n"
123
+ "\t\t\t\"chart_type\": \"%s\",\n"
124
+ "\t\t\t\"counter\": %lu,\n"
125
+ "\t\t\t\"entries\": %ld,\n"
126
+ "\t\t\t\"first_entry_t\": %ld,\n"
127
+ "\t\t\t\"last_entry\": %lu,\n"
128
+ "\t\t\t\"last_entry_t\": %ld,\n"
129
+ "\t\t\t\"last_entry_secs_ago\": %ld,\n"
130
+ "\t\t\t\"update_every\": %d,\n"
131
+ "\t\t\t\"isdetail\": %d,\n"
132
+ "\t\t\t\"usec_since_last_update\": %llu,\n"
133
+ "\t\t\t\"collected_total\": " TOTAL_NUMBER_FORMAT ",\n"
134
+ "\t\t\t\"last_collected_total\": " TOTAL_NUMBER_FORMAT ",\n"
135
+ "\t\t\t\"dimensions\": [\n"
136
+ , st->id
137
+ , st->name
138
+ , st->type
139
+ , st->family
140
+ , st->context
141
+ , st->title
142
+ , st->priority
143
+ , st->enabled
144
+ , st->units
145
+ , st->name, options?options:""
146
+ , rrdset_type_name(st->chart_type)
147
+ , st->counter
148
+ , st->entries
149
+ , rrdset_first_entry_t(st)
150
+ , rrdset_last_slot(st)
151
+ , rrdset_last_entry_t(st)
152
+ , (now < rrdset_last_entry_t(st)) ? (time_t)0 : now - rrdset_last_entry_t(st)
153
+ , st->update_every
154
+ , st->isdetail
155
+ , st->usec_since_last_update
156
+ , st->collected_total
157
+ , st->last_collected_total
158
+ );
159
+
160
+ unsigned long memory = st->memsize;
161
+
162
+ RRDDIM *rd;
163
+ for(rd = st->dimensions; rd ; rd = rd->next) {
164
+
165
+ memory += rd->memsize;
166
+
167
+ buffer_sprintf(wb,
168
+ "\t\t\t\t{\n"
169
+ "\t\t\t\t\t\"id\": \"%s\",\n"
170
+ "\t\t\t\t\t\"name\": \"%s\",\n"
171
+ "\t\t\t\t\t\"entries\": %ld,\n"
172
+ "\t\t\t\t\t\"isHidden\": %d,\n"
173
+ "\t\t\t\t\t\"algorithm\": \"%s\",\n"
174
+ "\t\t\t\t\t\"multiplier\": %ld,\n"
175
+ "\t\t\t\t\t\"divisor\": %ld,\n"
176
+ "\t\t\t\t\t\"last_entry_t\": %ld,\n"
177
+ "\t\t\t\t\t\"collected_value\": " COLLECTED_NUMBER_FORMAT ",\n"
178
+ "\t\t\t\t\t\"calculated_value\": " CALCULATED_NUMBER_FORMAT ",\n"
179
+ "\t\t\t\t\t\"last_collected_value\": " COLLECTED_NUMBER_FORMAT ",\n"
180
+ "\t\t\t\t\t\"last_calculated_value\": " CALCULATED_NUMBER_FORMAT ",\n"
181
+ "\t\t\t\t\t\"memory\": %lu\n"
182
+ "\t\t\t\t}%s\n"
183
+ , rd->id
184
+ , rd->name
185
+ , rd->entries
186
+ , (rd->flags & RRDDIM_FLAG_HIDDEN)?1:0
187
+ , rrddim_algorithm_name(rd->algorithm)
188
+ , rd->multiplier
189
+ , rd->divisor
190
+ , rd->last_collected_time.tv_sec
191
+ , rd->collected_value
192
+ , rd->calculated_value
193
+ , rd->last_collected_value
194
+ , rd->last_calculated_value
195
+ , rd->memsize
196
+ , rd->next?",":""
197
+ );
198
+ }
199
+
200
+ buffer_sprintf(wb,
201
+ "\t\t\t],\n"
202
+ "\t\t\t\"memory\" : %lu\n"
203
+ "\t\t}"
204
+ , memory
205
+ );
206
+
207
+ pthread_rwlock_unlock(&st->rwlock);
208
+ return memory;
209
}
210
211
#define RRD_GRAPH_JSON_HEADER "{\n\t\"charts\": [\n"
@@ -213,40 +213,40 @@ unsigned long rrd_stats_one_json(RRDSET *st, char *options, BUFFER *wb)
213
214
void rrd_stats_graph_json(RRDSET *st, char *options, BUFFER *wb)
215
{
216
- buffer_strcat(wb, RRD_GRAPH_JSON_HEADER);
217
- rrd_stats_one_json(st, options, wb);
218
- buffer_strcat(wb, RRD_GRAPH_JSON_FOOTER);
216
+ buffer_strcat(wb, RRD_GRAPH_JSON_HEADER);
217
+ rrd_stats_one_json(st, options, wb);
218
+ buffer_strcat(wb, RRD_GRAPH_JSON_FOOTER);
219
}
220
221
void rrd_stats_all_json(BUFFER *wb)
222
{
223
- unsigned long memory = 0;
224
- long c;
225
- RRDSET *st;
226
-
227
- buffer_strcat(wb, RRD_GRAPH_JSON_HEADER);
228
-
229
- pthread_rwlock_rdlock(&localhost.rrdset_root_rwlock);
230
- for(st = localhost.rrdset_root, c = 0; st ; st = st->next) {
231
- if(st->enabled && st->dimensions) {
232
- if(c) buffer_strcat(wb, ",\n");
233
- memory += rrd_stats_one_json(st, NULL, wb);
234
- c++;
235
- }
236
- }
237
- pthread_rwlock_unlock(&localhost.rrdset_root_rwlock);
238
-
239
- buffer_sprintf(wb, "\n\t],\n"
240
- "\t\"hostname\": \"%s\",\n"
241
- "\t\"update_every\": %d,\n"
242
- "\t\"history\": %d,\n"
243
- "\t\"memory\": %lu\n"
244
- "}\n"
245
- , hostname
246
- , rrd_update_every
247
- , rrd_default_history_entries
248
- , memory
249
- );
223
+ unsigned long memory = 0;
224
+ long c;
225
+ RRDSET *st;
226
+
227
+ buffer_strcat(wb, RRD_GRAPH_JSON_HEADER);
228
+
229
+ pthread_rwlock_rdlock(&localhost.rrdset_root_rwlock);
230
+ for(st = localhost.rrdset_root, c = 0; st ; st = st->next) {
231
+ if(st->enabled && st->dimensions) {
232
+ if(c) buffer_strcat(wb, ",\n");
233
+ memory += rrd_stats_one_json(st, NULL, wb);
234
+ c++;
235
+ }
236
+ }
237
+ pthread_rwlock_unlock(&localhost.rrdset_root_rwlock);
238
+
239
+ buffer_sprintf(wb, "\n\t],\n"
240
+ "\t\"hostname\": \"%s\",\n"
241
+ "\t\"update_every\": %d,\n"
242
+ "\t\"history\": %d,\n"
243
+ "\t\"memory\": %lu\n"
244
+ "}\n"
245
+ , hostname
246
+ , rrd_update_every
247
+ , rrd_default_history_entries
248
+ , memory
249
+ );
250
}
251
252
@@ -254,42 +254,42 @@ void rrd_stats_all_json(BUFFER *wb)
254
// ----------------------------------------------------------------------------
255
256
// RRDR dimension options
257
-#define RRDR_EMPTY 0x01 // the dimension contains / the value is empty (null)
258
-#define RRDR_RESET 0x02 // the dimension contains / the value is reset
259
-#define RRDR_HIDDEN 0x04 // the dimension contains / the value is hidden
260
-#define RRDR_NONZERO 0x08 // the dimension contains / the value is non-zero
257
+#define RRDR_EMPTY 0x01 // the dimension contains / the value is empty (null)
258
+#define RRDR_RESET 0x02 // the dimension contains / the value is reset
259
+#define RRDR_HIDDEN 0x04 // the dimension contains / the value is hidden
260
+#define RRDR_NONZERO 0x08 // the dimension contains / the value is non-zero
261
262
// RRDR result options
263
#define RRDR_RESULT_OPTION_ABSOLUTE 0x00000001
264
#define RRDR_RESULT_OPTION_RELATIVE 0x00000002
265
266
typedef struct rrdresult {
267
- RRDSET *st; // the chart this result refers to
267
+ RRDSET *st; // the chart this result refers to
268
269
- uint32_t result_options; // RRDR_RESULT_OPTION_*
269
+ uint32_t result_options; // RRDR_RESULT_OPTION_*
270
271
- int d; // the number of dimensions
272
- long n; // the number of values in the arrays
273
- long rows; // the number of rows used
271
+ int d; // the number of dimensions
272
+ long n; // the number of values in the arrays
273
+ long rows; // the number of rows used
274
275
- uint8_t *od; // the options for the dimensions
275
+ uint8_t *od; // the options for the dimensions
276
277
- time_t *t; // array of n timestamps
278
- calculated_number *v; // array n x d values
279
- uint8_t *o; // array n x d options
277
+ time_t *t; // array of n timestamps
278
+ calculated_number *v; // array n x d values
279
+ uint8_t *o; // array n x d options
280
281
- long c; // current line ( -1 ~ n ), ( -1 = none, use rrdr_rows() to get number of rows )
281
+ long c; // current line ( -1 ~ n ), ( -1 = none, use rrdr_rows() to get number of rows )
282
283
- long group; // how many collected values were grouped for each row
284
- int update_every; // what is the suggested update frequency in seconds
283
+ long group; // how many collected values were grouped for each row
284
+ int update_every; // what is the suggested update frequency in seconds
285
286
- calculated_number min;
287
- calculated_number max;
286
+ calculated_number min;
287
+ calculated_number max;
288
289
- time_t before;
290
- time_t after;
289
+ time_t before;
290
+ time_t after;
291
292
- int has_st_lock; // if st is read locked by us
292
+ int has_st_lock; // if st is read locked by us
293
} RRDR;
294
295
#define rrdr_rows(r) ((r)->rows)
@@ -297,347 +297,347 @@ typedef struct rrdresult {
297
/*
298
static void rrdr_dump(RRDR *r)
299
{
300
- long c, i;
301
- RRDDIM *d;
302
-
303
- fprintf(stderr, "\nCHART %s (%s)\n", r->st->id, r->st->name);
304
-
305
- for(c = 0, d = r->st->dimensions; d ;c++, d = d->next) {
306
- fprintf(stderr, "DIMENSION %s (%s), %s%s%s%s\n"
307
- , d->id
308
- , d->name
309
- , (r->od[c] & RRDR_EMPTY)?"EMPTY ":""
310
- , (r->od[c] & RRDR_RESET)?"RESET ":""
311
- , (r->od[c] & RRDR_HIDDEN)?"HIDDEN ":""
312
- , (r->od[c] & RRDR_NONZERO)?"NONZERO ":""
313
- );
314
- }
315
-
316
- if(r->rows <= 0) {
317
- fprintf(stderr, "RRDR does not have any values in it.\n");
318
- return;
319
- }
320
-
321
- fprintf(stderr, "RRDR includes %d values in it:\n", r->rows);
322
-
323
- // for each line in the array
324
- for(i = 0; i < r->rows ;i++) {
325
- calculated_number *cn = &r->v[ i * r->d ];
326
- uint8_t *co = &r->o[ i * r->d ];
327
-
328
- // print the id and the timestamp of the line
329
- fprintf(stderr, "%ld %ld ", i + 1, r->t[i]);
330
-
331
- // for each dimension
332
- for(c = 0, d = r->st->dimensions; d ;c++, d = d->next) {
333
- if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
334
- if(unlikely(!(r->od[c] & RRDR_NONZERO))) continue;
335
-
336
- if(co[c] & RRDR_EMPTY)
337
- fprintf(stderr, "null ");
338
- else
339
- fprintf(stderr, CALCULATED_NUMBER_FORMAT " %s%s%s%s "
340
- , cn[c]
341
- , (co[c] & RRDR_EMPTY)?"E":" "
342
- , (co[c] & RRDR_RESET)?"R":" "
343
- , (co[c] & RRDR_HIDDEN)?"H":" "
344
- , (co[c] & RRDR_NONZERO)?"N":" "
345
- );
346
- }
347
-
348
- fprintf(stderr, "\n");
349
- }
300
+ long c, i;
301
+ RRDDIM *d;
302
+
303
+ fprintf(stderr, "\nCHART %s (%s)\n", r->st->id, r->st->name);
304
+
305
+ for(c = 0, d = r->st->dimensions; d ;c++, d = d->next) {
306
+ fprintf(stderr, "DIMENSION %s (%s), %s%s%s%s\n"
307
+ , d->id
308
+ , d->name
309
+ , (r->od[c] & RRDR_EMPTY)?"EMPTY ":""
310
+ , (r->od[c] & RRDR_RESET)?"RESET ":""
311
+ , (r->od[c] & RRDR_HIDDEN)?"HIDDEN ":""
312
+ , (r->od[c] & RRDR_NONZERO)?"NONZERO ":""
313
+ );
314
+ }
315
+
316
+ if(r->rows <= 0) {
317
+ fprintf(stderr, "RRDR does not have any values in it.\n");
318
+ return;
319
+ }
320
+
321
+ fprintf(stderr, "RRDR includes %d values in it:\n", r->rows);
322
+
323
+ // for each line in the array
324
+ for(i = 0; i < r->rows ;i++) {
325
+ calculated_number *cn = &r->v[ i * r->d ];
326
+ uint8_t *co = &r->o[ i * r->d ];
327
+
328
+ // print the id and the timestamp of the line
329
+ fprintf(stderr, "%ld %ld ", i + 1, r->t[i]);
330
+
331
+ // for each dimension
332
+ for(c = 0, d = r->st->dimensions; d ;c++, d = d->next) {
333
+ if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
334
+ if(unlikely(!(r->od[c] & RRDR_NONZERO))) continue;
335
+
336
+ if(co[c] & RRDR_EMPTY)
337
+ fprintf(stderr, "null ");
338
+ else
339
+ fprintf(stderr, CALCULATED_NUMBER_FORMAT " %s%s%s%s "
340
+ , cn[c]
341
+ , (co[c] & RRDR_EMPTY)?"E":" "
342
+ , (co[c] & RRDR_RESET)?"R":" "
343
+ , (co[c] & RRDR_HIDDEN)?"H":" "
344
+ , (co[c] & RRDR_NONZERO)?"N":" "
345
+ );
346
+ }
347
+
348
+ fprintf(stderr, "\n");
349
+ }
350
}
351
*/
352
353
void rrdr_disable_not_selected_dimensions(RRDR *r, const char *dims)
354
{
355
- char b[strlen(dims) + 1];
356
- char *o = b, *tok;
357
- strcpy(o, dims);
358
-
359
- long c;
360
- RRDDIM *d;
361
-
362
- // disable all of them
363
- for(c = 0, d = r->st->dimensions; d ;c++, d = d->next)
364
- r->od[c] |= RRDR_HIDDEN;
365
-
366
- while(o && *o && (tok = mystrsep(&o, ",|"))) {
367
- if(!*tok) continue;
368
-
369
- uint32_t hash = simple_hash(tok);
370
-
371
- // find it and enable it
372
- for(c = 0, d = r->st->dimensions; d ;c++, d = d->next) {
373
- if(unlikely((hash == d->hash && !strcmp(d->id, tok)) || !strcmp(d->name, tok))) {
374
- r->od[c] &= ~RRDR_HIDDEN;
375
-
376
- // since the user needs this dimension
377
- // make it appear as NONZERO, to return it
378
- // even if the dimension has only zeros
379
- r->od[c] |= RRDR_NONZERO;
380
- }
381
- }
382
- }
355
+ char b[strlen(dims) + 1];
356
+ char *o = b, *tok;
357
+ strcpy(o, dims);
358
+
359
+ long c;
360
+ RRDDIM *d;
361
+
362
+ // disable all of them
363
+ for(c = 0, d = r->st->dimensions; d ;c++, d = d->next)
364
+ r->od[c] |= RRDR_HIDDEN;
365
+
366
+ while(o && *o && (tok = mystrsep(&o, ",|"))) {
367
+ if(!*tok) continue;
368
+
369
+ uint32_t hash = simple_hash(tok);
370
+
371
+ // find it and enable it
372
+ for(c = 0, d = r->st->dimensions; d ;c++, d = d->next) {
373
+ if(unlikely((hash == d->hash && !strcmp(d->id, tok)) || !strcmp(d->name, tok))) {
374
+ r->od[c] &= ~RRDR_HIDDEN;
375
+
376
+ // since the user needs this dimension
377
+ // make it appear as NONZERO, to return it
378
+ // even if the dimension has only zeros
379
+ r->od[c] |= RRDR_NONZERO;
380
+ }
381
+ }
382
+ }
383
}
384
385
void rrdr_buffer_print_format(BUFFER *wb, uint32_t format)
386
{
387
- switch(format) {
388
- case DATASOURCE_JSON:
389
- buffer_strcat(wb, DATASOURCE_FORMAT_JSON);
390
- break;
391
-
392
- case DATASOURCE_DATATABLE_JSON:
393
- buffer_strcat(wb, DATASOURCE_FORMAT_DATATABLE_JSON);
394
- break;
395
-
396
- case DATASOURCE_DATATABLE_JSONP:
397
- buffer_strcat(wb, DATASOURCE_FORMAT_DATATABLE_JSONP);
398
- break;
399
-
400
- case DATASOURCE_JSONP:
401
- buffer_strcat(wb, DATASOURCE_FORMAT_JSONP);
402
- break;
403
-
404
- case DATASOURCE_SSV:
405
- buffer_strcat(wb, DATASOURCE_FORMAT_SSV);
406
- break;
407
-
408
- case DATASOURCE_CSV:
409
- buffer_strcat(wb, DATASOURCE_FORMAT_CSV);
410
- break;
411
-
412
- case DATASOURCE_TSV:
413
- buffer_strcat(wb, DATASOURCE_FORMAT_TSV);
414
- break;
415
-
416
- case DATASOURCE_HTML:
417
- buffer_strcat(wb, DATASOURCE_FORMAT_HTML);
418
- break;
419
-
420
- case DATASOURCE_JS_ARRAY:
421
- buffer_strcat(wb, DATASOURCE_FORMAT_JS_ARRAY);
422
- break;
423
-
424
- case DATASOURCE_SSV_COMMA:
425
- buffer_strcat(wb, DATASOURCE_FORMAT_SSV_COMMA);
426
- break;
427
-
428
- default:
429
- buffer_strcat(wb, "unknown");
430
- break;
431
- }
387
+ switch(format) {
388
+ case DATASOURCE_JSON:
389
+ buffer_strcat(wb, DATASOURCE_FORMAT_JSON);
390
+ break;
391
+
392
+ case DATASOURCE_DATATABLE_JSON:
393
+ buffer_strcat(wb, DATASOURCE_FORMAT_DATATABLE_JSON);
394
+ break;
395
+
396
+ case DATASOURCE_DATATABLE_JSONP:
397
+ buffer_strcat(wb, DATASOURCE_FORMAT_DATATABLE_JSONP);
398
+ break;
399
+
400
+ case DATASOURCE_JSONP:
401
+ buffer_strcat(wb, DATASOURCE_FORMAT_JSONP);
402
+ break;
403
+
404
+ case DATASOURCE_SSV:
405
+ buffer_strcat(wb, DATASOURCE_FORMAT_SSV);
406
+ break;
407
+
408
+ case DATASOURCE_CSV:
409
+ buffer_strcat(wb, DATASOURCE_FORMAT_CSV);
410
+ break;
411
+
412
+ case DATASOURCE_TSV:
413
+ buffer_strcat(wb, DATASOURCE_FORMAT_TSV);
414
+ break;
415
+
416
+ case DATASOURCE_HTML:
417
+ buffer_strcat(wb, DATASOURCE_FORMAT_HTML);
418
+ break;
419
+
420
+ case DATASOURCE_JS_ARRAY:
421
+ buffer_strcat(wb, DATASOURCE_FORMAT_JS_ARRAY);
422
+ break;
423
+
424
+ case DATASOURCE_SSV_COMMA:
425
+ buffer_strcat(wb, DATASOURCE_FORMAT_SSV_COMMA);
426
+ break;
427
+
428
+ default:
429
+ buffer_strcat(wb, "unknown");
430
+ break;
431
+ }
432
}
433
434
uint32_t rrdr_check_options(RRDR *r, uint32_t options, const char *dims)
435
{
436
- if(options & RRDR_OPTION_NONZERO) {
437
- long i;
438
-
439
- if(dims && *dims) {
440
- // the caller wants specific dimensions
441
- // disable NONZERO option
442
- // to make sure we don't accidentally prevent
443
- // the specific dimensions from being returned
444
- i = 0;
445
- }
446
- else {
447
- // find how many dimensions are not zero
448
- long c;
449
- RRDDIM *rd;
450
- for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ; c++, rd = rd->next) {
451
- if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
452
- if(unlikely(!(r->od[c] & RRDR_NONZERO))) continue;
453
- i++;
454
- }
455
- }
456
-
457
- // if with nonzero we get i = 0 (no dimensions will be returned)
458
- // disable nonzero to show all dimensions
459
- if(!i) options &= ~RRDR_OPTION_NONZERO;
460
- }
461
-
462
- return options;
436
+ if(options & RRDR_OPTION_NONZERO) {
437
+ long i;
438
+
439
+ if(dims && *dims) {
440
+ // the caller wants specific dimensions
441
+ // disable NONZERO option
442
+ // to make sure we don't accidentally prevent
443
+ // the specific dimensions from being returned
444
+ i = 0;
445
+ }
446
+ else {
447
+ // find how many dimensions are not zero
448
+ long c;
449
+ RRDDIM *rd;
450
+ for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ; c++, rd = rd->next) {
451
+ if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
452
+ if(unlikely(!(r->od[c] & RRDR_NONZERO))) continue;
453
+ i++;
454
+ }
455
+ }
456
+
457
+ // if with nonzero we get i = 0 (no dimensions will be returned)
458
+ // disable nonzero to show all dimensions
459
+ if(!i) options &= ~RRDR_OPTION_NONZERO;
460
+ }
461
+
462
+ return options;
463
}
464
465
void rrdr_json_wrapper_begin(RRDR *r, BUFFER *wb, uint32_t format, uint32_t options, int string_value)
466
{
467
- long rows = rrdr_rows(r);
468
- long c, i;
469
- RRDDIM *rd;
470
-
471
- //info("JSONWRAPPER(): %s: BEGIN", r->st->id);
472
- char kq[2] = "", // key quote
473
- sq[2] = ""; // string quote
474
-
475
- if( options & RRDR_OPTION_GOOGLE_JSON ) {
476
- kq[0] = '\0';
477
- sq[0] = '\'';
478
- }
479
- else {
480
- kq[0] = '"';
481
- sq[0] = '"';
482
- }
483
-
484
- buffer_sprintf(wb, "{\n"
485
- " %sapi%s: 1,\n"
486
- " %sid%s: %s%s%s,\n"
487
- " %sname%s: %s%s%s,\n"
488
- " %sview_update_every%s: %d,\n"
489
- " %supdate_every%s: %d,\n"
490
- " %sfirst_entry%s: %u,\n"
491
- " %slast_entry%s: %u,\n"
492
- " %sbefore%s: %u,\n"
493
- " %safter%s: %u,\n"
494
- " %sdimension_names%s: ["
495
- , kq, kq
496
- , kq, kq, sq, r->st->id, sq
497
- , kq, kq, sq, r->st->name, sq
498
- , kq, kq, r->update_every
499
- , kq, kq, r->st->update_every
500
- , kq, kq, (uint32_t)rrdset_first_entry_t(r->st)
501
- , kq, kq, (uint32_t)rrdset_last_entry_t(r->st)
502
- , kq, kq, (uint32_t)r->before
503
- , kq, kq, (uint32_t)r->after
504
- , kq, kq);
505
-
506
- for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
507
- if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
508
- if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
509
-
510
- if(i) buffer_strcat(wb, ", ");
511
- buffer_strcat(wb, sq);
512
- buffer_strcat(wb, rd->name);
513
- buffer_strcat(wb, sq);
514
- i++;
515
- }
516
- if(!i) {
467
+ long rows = rrdr_rows(r);
468
+ long c, i;
469
+ RRDDIM *rd;
470
+
471
+ //info("JSONWRAPPER(): %s: BEGIN", r->st->id);
472
+ char kq[2] = "", // key quote
473
+ sq[2] = ""; // string quote
474
+
475
+ if( options & RRDR_OPTION_GOOGLE_JSON ) {
476
+ kq[0] = '\0';
477
+ sq[0] = '\'';
478
+ }
479
+ else {
480
+ kq[0] = '"';
481
+ sq[0] = '"';
482
+ }
483
+
484
+ buffer_sprintf(wb, "{\n"
485
+ " %sapi%s: 1,\n"
486
+ " %sid%s: %s%s%s,\n"
487
+ " %sname%s: %s%s%s,\n"
488
+ " %sview_update_every%s: %d,\n"
489
+ " %supdate_every%s: %d,\n"
490
+ " %sfirst_entry%s: %u,\n"
491
+ " %slast_entry%s: %u,\n"
492
+ " %sbefore%s: %u,\n"
493
+ " %safter%s: %u,\n"
494
+ " %sdimension_names%s: ["
495
+ , kq, kq
496
+ , kq, kq, sq, r->st->id, sq
497
+ , kq, kq, sq, r->st->name, sq
498
+ , kq, kq, r->update_every
499
+ , kq, kq, r->st->update_every
500
+ , kq, kq, (uint32_t)rrdset_first_entry_t(r->st)
501
+ , kq, kq, (uint32_t)rrdset_last_entry_t(r->st)
502
+ , kq, kq, (uint32_t)r->before
503
+ , kq, kq, (uint32_t)r->after
504
+ , kq, kq);
505
+
506
+ for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
507
+ if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
508
+ if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
509
+
510
+ if(i) buffer_strcat(wb, ", ");
511
+ buffer_strcat(wb, sq);
512
+ buffer_strcat(wb, rd->name);
513
+ buffer_strcat(wb, sq);
514
+ i++;
515
+ }
516
+ if(!i) {
517
#ifdef NETDATA_INTERNAL_CHECKS
518
- error("RRDR is empty for %s (RRDR has %d dimensions, options is 0x%08x)", r->st->id, r->d, options);
518
+ error("RRDR is empty for %s (RRDR has %d dimensions, options is 0x%08x)", r->st->id, r->d, options);
519
#endif
520
- rows = 0;
521
- buffer_strcat(wb, sq);
522
- buffer_strcat(wb, "no data");
523
- buffer_strcat(wb, sq);
524
- }
525
-
526
- buffer_sprintf(wb, "],\n"
527
- " %sdimension_ids%s: ["
528
- , kq, kq);
529
-
530
- for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
531
- if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
532
- if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
533
-
534
- if(i) buffer_strcat(wb, ", ");
535
- buffer_strcat(wb, sq);
536
- buffer_strcat(wb, rd->id);
537
- buffer_strcat(wb, sq);
538
- i++;
539
- }
540
- if(!i) {
541
- rows = 0;
542
- buffer_strcat(wb, sq);
543
- buffer_strcat(wb, "no data");
544
- buffer_strcat(wb, sq);
545
- }
546
-
547
- buffer_sprintf(wb, "],\n"
548
- " %slatest_values%s: ["
549
- , kq, kq);
550
-
551
- for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
552
- if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
553
- if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
554
-
555
- if(i) buffer_strcat(wb, ", ");
556
- i++;
557
-
558
- storage_number n = rd->values[rrdset_last_slot(r->st)];
559
-
560
- if(!does_storage_number_exist(n))
561
- buffer_strcat(wb, "null");
562
- else
563
- buffer_rrd_value(wb, unpack_storage_number(n));
564
- }
565
- if(!i) {
566
- rows = 0;
567
- buffer_strcat(wb, "null");
568
- }
569
-
570
- buffer_sprintf(wb, "],\n"
571
- " %sview_latest_values%s: ["
572
- , kq, kq);
573
-
574
- i = 0;
575
- if(rows) {
576
- for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
577
- if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
578
- if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
579
-
580
- if(i) buffer_strcat(wb, ", ");
581
- i++;
582
-
583
- calculated_number *cn = &r->v[ (0) * r->d ];
584
- uint8_t *co = &r->o[ (0) * r->d ];
585
-
586
- if(co[c] & RRDR_EMPTY)
587
- buffer_strcat(wb, "null");
588
- else
589
- buffer_rrd_value(wb, cn[c]);
590
- }
591
- }
592
- if(!i) {
593
- rows = 0;
594
- buffer_strcat(wb, "null");
595
- }
596
-
597
- buffer_sprintf(wb, "],\n"
598
- " %sdimensions%s: %ld,\n"
599
- " %spoints%s: %ld,\n"
600
- " %sformat%s: %s"
601
- , kq, kq, i
602
- , kq, kq, rows
603
- , kq, kq, sq
604
- );
605
-
606
- rrdr_buffer_print_format(wb, format);
607
-
608
- buffer_sprintf(wb, "%s,\n"
609
- " %sresult%s: "
610
- , sq
611
- , kq, kq
612
- );
613
-
614
- if(string_value) buffer_strcat(wb, sq);
615
- //info("JSONWRAPPER(): %s: END", r->st->id);
520
+ rows = 0;
521
+ buffer_strcat(wb, sq);
522
+ buffer_strcat(wb, "no data");
523
+ buffer_strcat(wb, sq);
524
+ }
525
+
526
+ buffer_sprintf(wb, "],\n"
527
+ " %sdimension_ids%s: ["
528
+ , kq, kq);
529
+
530
+ for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
531
+ if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
532
+ if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
533
+
534
+ if(i) buffer_strcat(wb, ", ");
535
+ buffer_strcat(wb, sq);
536
+ buffer_strcat(wb, rd->id);
537
+ buffer_strcat(wb, sq);
538
+ i++;
539
+ }
540
+ if(!i) {
541
+ rows = 0;
542
+ buffer_strcat(wb, sq);
543
+ buffer_strcat(wb, "no data");
544
+ buffer_strcat(wb, sq);
545
+ }
546
+
547
+ buffer_sprintf(wb, "],\n"
548
+ " %slatest_values%s: ["
549
+ , kq, kq);
550
+
551
+ for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
552
+ if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
553
+ if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
554
+
555
+ if(i) buffer_strcat(wb, ", ");
556
+ i++;
557
+
558
+ storage_number n = rd->values[rrdset_last_slot(r->st)];
559
+
560
+ if(!does_storage_number_exist(n))
561
+ buffer_strcat(wb, "null");
562
+ else
563
+ buffer_rrd_value(wb, unpack_storage_number(n));
564
+ }
565
+ if(!i) {
566
+ rows = 0;
567
+ buffer_strcat(wb, "null");
568
+ }
569
+
570
+ buffer_sprintf(wb, "],\n"
571
+ " %sview_latest_values%s: ["
572
+ , kq, kq);
573
+
574
+ i = 0;
575
+ if(rows) {
576
+ for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
577
+ if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
578
+ if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
579
+
580
+ if(i) buffer_strcat(wb, ", ");
581
+ i++;
582
+
583
+ calculated_number *cn = &r->v[ (0) * r->d ];
584
+ uint8_t *co = &r->o[ (0) * r->d ];
585
+
586
+ if(co[c] & RRDR_EMPTY)
587
+ buffer_strcat(wb, "null");
588
+ else
589
+ buffer_rrd_value(wb, cn[c]);
590
+ }
591
+ }
592
+ if(!i) {
593
+ rows = 0;
594
+ buffer_strcat(wb, "null");
595
+ }
596
+
597
+ buffer_sprintf(wb, "],\n"
598
+ " %sdimensions%s: %ld,\n"
599
+ " %spoints%s: %ld,\n"
600
+ " %sformat%s: %s"
601
+ , kq, kq, i
602
+ , kq, kq, rows
603
+ , kq, kq, sq
604
+ );
605
+
606
+ rrdr_buffer_print_format(wb, format);
607
+
608
+ buffer_sprintf(wb, "%s,\n"
609
+ " %sresult%s: "
610
+ , sq
611
+ , kq, kq
612
+ );
613
+
614
+ if(string_value) buffer_strcat(wb, sq);
615
+ //info("JSONWRAPPER(): %s: END", r->st->id);
616
}
617
618
void rrdr_json_wrapper_end(RRDR *r, BUFFER *wb, uint32_t format, uint32_t options, int string_value)
619
{
620
- (void)format;
621
-
622
- char kq[2] = "", // key quote
623
- sq[2] = ""; // string quote
624
-
625
- if( options & RRDR_OPTION_GOOGLE_JSON ) {
626
- kq[0] = '\0';
627
- sq[0] = '\'';
628
- }
629
- else {
630
- kq[0] = '"';
631
- sq[0] = '"';
632
- }
633
-
634
- if(string_value) buffer_strcat(wb, sq);
635
-
636
- buffer_sprintf(wb, ",\n %smin%s: ", kq, kq);
637
- buffer_rrd_value(wb, r->min);
638
- buffer_sprintf(wb, ",\n %smax%s: ", kq, kq);
639
- buffer_rrd_value(wb, r->max);
640
- buffer_strcat(wb, "\n}\n");
620
+ (void)format;
621
+
622
+ char kq[2] = "", // key quote
623
+ sq[2] = ""; // string quote
624
+
625
+ if( options & RRDR_OPTION_GOOGLE_JSON ) {
626
+ kq[0] = '\0';
627
+ sq[0] = '\'';
628
+ }
629
+ else {
630
+ kq[0] = '"';
631
+ sq[0] = '"';
632
+ }
633
+
634
+ if(string_value) buffer_strcat(wb, sq);
635
+
636
+ buffer_sprintf(wb, ",\n %smin%s: ", kq, kq);
637
+ buffer_rrd_value(wb, r->min);
638
+ buffer_sprintf(wb, ",\n %smax%s: ", kq, kq);
639
+ buffer_rrd_value(wb, r->max);
640
+ buffer_strcat(wb, "\n}\n");
641
}
642
643
#define JSON_DATES_JS 1
@@ -645,1407 +645,1407 @@ void rrdr_json_wrapper_end(RRDR *r, BUFFER *wb, uint32_t format, uint32_t option
645
646
static void rrdr2json(RRDR *r, BUFFER *wb, uint32_t options, int datatable)
647
{
648
- //info("RRD2JSON(): %s: BEGIN", r->st->id);
649
- int row_annotations = 0, dates, dates_with_new = 0;
650
- char kq[2] = "", // key quote
651
- sq[2] = "", // string quote
652
- pre_label[101] = "", // before each label
653
- post_label[101] = "", // after each label
654
- pre_date[101] = "", // the beginning of line, to the date
655
- post_date[101] = "", // closing the date
656
- pre_value[101] = "", // before each value
657
- post_value[101] = "", // after each value
658
- post_line[101] = "", // at the end of each row
659
- normal_annotation[201] = "", // default row annotation
660
- overflow_annotation[201] = "", // overflow row annotation
661
- data_begin[101] = "", // between labels and values
662
- finish[101] = ""; // at the end of everything
663
-
664
- if(datatable) {
665
- dates = JSON_DATES_JS;
666
- if( options & RRDR_OPTION_GOOGLE_JSON ) {
667
- kq[0] = '\0';
668
- sq[0] = '\'';
669
- }
670
- else {
671
- kq[0] = '"';
672
- sq[0] = '"';
673
- }
674
- row_annotations = 1;
675
- snprintfz(pre_date, 100, " {%sc%s:[{%sv%s:%s", kq, kq, kq, kq, sq);
676
- snprintfz(post_date, 100, "%s}", sq);
677
- snprintfz(pre_label, 100, ",\n {%sid%s:%s%s,%slabel%s:%s", kq, kq, sq, sq, kq, kq, sq);
678
- snprintfz(post_label, 100, "%s,%spattern%s:%s%s,%stype%s:%snumber%s}", sq, kq, kq, sq, sq, kq, kq, sq, sq);
679
- snprintfz(pre_value, 100, ",{%sv%s:", kq, kq);
680
- strcpy(post_value, "}");
681
- strcpy(post_line, "]}");
682
- snprintfz(data_begin, 100, "\n ],\n %srows%s:\n [\n", kq, kq);
683
- strcpy(finish, "\n ]\n}");
684
-
685
- snprintfz(overflow_annotation, 200, ",{%sv%s:%sRESET OR OVERFLOW%s},{%sv%s:%sThe counters have been wrapped.%s}", kq, kq, sq, sq, kq, kq, sq, sq);
686
- snprintfz(normal_annotation, 200, ",{%sv%s:null},{%sv%s:null}", kq, kq, kq, kq);
687
-
688
- buffer_sprintf(wb, "{\n %scols%s:\n [\n", kq, kq);
689
- buffer_sprintf(wb, " {%sid%s:%s%s,%slabel%s:%stime%s,%spattern%s:%s%s,%stype%s:%sdatetime%s},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq);
690
- buffer_sprintf(wb, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotation%s}},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
691
- buffer_sprintf(wb, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotationText%s}}", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
692
-
693
- // remove the valueobjects flag
694
- // google wants its own keys
695
- if(options & RRDR_OPTION_OBJECTSROWS)
696
- options &= ~RRDR_OPTION_OBJECTSROWS;
697
- }
698
- else {
699
- kq[0] = '"';
700
- sq[0] = '"';
701
- if((options & RRDR_OPTION_SECONDS) || (options & RRDR_OPTION_MILLISECONDS)) {
702
- dates = JSON_DATES_TIMESTAMP;
703
- dates_with_new = 0;
704
- }
705
- else {
706
- dates = JSON_DATES_JS;
707
- dates_with_new = 1;
708
- }
709
- if( options & RRDR_OPTION_OBJECTSROWS )
710
- strcpy(pre_date, " { ");
711
- else
712
- strcpy(pre_date, " [ ");
713
- strcpy(pre_label, ", \"");
714
- strcpy(post_label, "\"");
715
- strcpy(pre_value, ", ");
716
- if( options & RRDR_OPTION_OBJECTSROWS )
717
- strcpy(post_line, "}");
718
- else
719
- strcpy(post_line, "]");
720
- snprintfz(data_begin, 100, "],\n %sdata%s:\n [\n", kq, kq);
721
- strcpy(finish, "\n ]\n}");
722
-
723
- buffer_sprintf(wb, "{\n %slabels%s: [", kq, kq);
724
- buffer_sprintf(wb, "%stime%s", sq, sq);
725
- }
726
-
727
- // -------------------------------------------------------------------------
728
- // print the JSON header
729
-
730
- long c, i;
731
- RRDDIM *rd;
732
-
733
- // print the header lines
734
- for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
735
- if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
736
- if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
737
-
738
- buffer_strcat(wb, pre_label);
739
- buffer_strcat(wb, rd->name);
740
- buffer_strcat(wb, post_label);
741
- i++;
742
- }
743
- if(!i) {
744
- buffer_strcat(wb, pre_label);
745
- buffer_strcat(wb, "no data");
746
- buffer_strcat(wb, post_label);
747
- }
748
-
749
- // print the begin of row data
750
- buffer_strcat(wb, data_begin);
751
-
752
- // if all dimensions are hidden, print a null
753
- if(!i) {
754
- buffer_strcat(wb, finish);
755
- return;
756
- }
757
-
758
- long start = 0, end = rrdr_rows(r), step = 1;
759
- if((options & RRDR_OPTION_REVERSED)) {
760
- start = rrdr_rows(r) - 1;
761
- end = -1;
762
- step = -1;
763
- }
764
-
765
- // for each line in the array
766
- calculated_number total = 1;
767
- for(i = start; i != end ;i += step) {
768
- calculated_number *cn = &r->v[ i * r->d ];
769
- uint8_t *co = &r->o[ i * r->d ];
770
-
771
- time_t now = r->t[i];
772
-
773
- if(dates == JSON_DATES_JS) {
774
- // generate the local date time
775
- struct tm tmbuf, *tm = localtime_r(&now, &tmbuf);
776
- if(!tm) { error("localtime_r() failed."); continue; }
777
-
778
- if(likely(i != start)) buffer_strcat(wb, ",\n");
779
- buffer_strcat(wb, pre_date);
780
-
781
- if( options & RRDR_OPTION_OBJECTSROWS )
782
- buffer_sprintf(wb, "%stime%s: ", kq, kq);
783
-
784
- if(dates_with_new)
785
- buffer_strcat(wb, "new ");
786
-
787
- buffer_jsdate(wb, tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
788
-
789
- buffer_strcat(wb, post_date);
790
-
791
- if(row_annotations) {
792
- // google supports one annotation per row
793
- int annotation_found = 0;
794
- for(c = 0, rd = r->st->dimensions; rd ;c++, rd = rd->next) {
795
- if(co[c] & RRDR_RESET) {
796
- buffer_strcat(wb, overflow_annotation);
797
- annotation_found = 1;
798
- break;
799
- }
800
- }
801
- if(!annotation_found)
802
- buffer_strcat(wb, normal_annotation);
803
- }
804
- }
805
- else {
806
- // print the timestamp of the line
807
- if(likely(i != start)) buffer_strcat(wb, ",\n");
808
- buffer_strcat(wb, pre_date);
809
-
810
- if( options & RRDR_OPTION_OBJECTSROWS )
811
- buffer_sprintf(wb, "%stime%s: ", kq, kq);
812
-
813
- buffer_rrd_value(wb, (calculated_number)r->t[i]);
814
- // in ms
815
- if(options & RRDR_OPTION_MILLISECONDS) buffer_strcat(wb, "000");
816
-
817
- buffer_strcat(wb, post_date);
818
- }
819
-
820
- if(unlikely(options & RRDR_OPTION_PERCENTAGE)) {
821
- total = 0;
822
- for(c = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
823
- calculated_number n = cn[c];
824
-
825
- if(likely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
826
- n = -n;
827
-
828
- total += n;
829
- }
830
- // prevent a division by zero
831
- if(total == 0) total = 1;
832
- }
833
-
834
- // for each dimension
835
- for(c = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
836
- if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
837
- if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
838
-
839
- calculated_number n = cn[c];
840
-
841
- buffer_strcat(wb, pre_value);
842
-
843
- if( options & RRDR_OPTION_OBJECTSROWS )
844
- buffer_sprintf(wb, "%s%s%s: ", kq, rd->name, kq);
845
-
846
- if(co[c] & RRDR_EMPTY) {
847
- if(options & RRDR_OPTION_NULL2ZERO)
848
- buffer_strcat(wb, "0");
849
- else
850
- buffer_strcat(wb, "null");
851
- }
852
- else {
853
- if(unlikely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
854
- n = -n;
855
-
856
- if(unlikely(options & RRDR_OPTION_PERCENTAGE))
857
- n = n * 100 / total;
858
-
859
- buffer_rrd_value(wb, n);
860
- }
861
-
862
- buffer_strcat(wb, post_value);
863
- }
864
-
865
- buffer_strcat(wb, post_line);
866
- }
867
-
868
- buffer_strcat(wb, finish);
869
- //info("RRD2JSON(): %s: END", r->st->id);
648
+ //info("RRD2JSON(): %s: BEGIN", r->st->id);
649
+ int row_annotations = 0, dates, dates_with_new = 0;
650
+ char kq[2] = "", // key quote
651
+ sq[2] = "", // string quote
652
+ pre_label[101] = "", // before each label
653
+ post_label[101] = "", // after each label
654
+ pre_date[101] = "", // the beginning of line, to the date
655
+ post_date[101] = "", // closing the date
656
+ pre_value[101] = "", // before each value
657
+ post_value[101] = "", // after each value
658
+ post_line[101] = "", // at the end of each row
659
+ normal_annotation[201] = "", // default row annotation
660
+ overflow_annotation[201] = "", // overflow row annotation
661
+ data_begin[101] = "", // between labels and values
662
+ finish[101] = ""; // at the end of everything
663
+
664
+ if(datatable) {
665
+ dates = JSON_DATES_JS;
666
+ if( options & RRDR_OPTION_GOOGLE_JSON ) {
667
+ kq[0] = '\0';
668
+ sq[0] = '\'';
669
+ }
670
+ else {
671
+ kq[0] = '"';
672
+ sq[0] = '"';
673
+ }
674
+ row_annotations = 1;
675
+ snprintfz(pre_date, 100, " {%sc%s:[{%sv%s:%s", kq, kq, kq, kq, sq);
676
+ snprintfz(post_date, 100, "%s}", sq);
677
+ snprintfz(pre_label, 100, ",\n {%sid%s:%s%s,%slabel%s:%s", kq, kq, sq, sq, kq, kq, sq);
678
+ snprintfz(post_label, 100, "%s,%spattern%s:%s%s,%stype%s:%snumber%s}", sq, kq, kq, sq, sq, kq, kq, sq, sq);
679
+ snprintfz(pre_value, 100, ",{%sv%s:", kq, kq);
680
+ strcpy(post_value, "}");
681
+ strcpy(post_line, "]}");
682
+ snprintfz(data_begin, 100, "\n ],\n %srows%s:\n [\n", kq, kq);
683
+ strcpy(finish, "\n ]\n}");
684
+
685
+ snprintfz(overflow_annotation, 200, ",{%sv%s:%sRESET OR OVERFLOW%s},{%sv%s:%sThe counters have been wrapped.%s}", kq, kq, sq, sq, kq, kq, sq, sq);
686
+ snprintfz(normal_annotation, 200, ",{%sv%s:null},{%sv%s:null}", kq, kq, kq, kq);
687
+
688
+ buffer_sprintf(wb, "{\n %scols%s:\n [\n", kq, kq);
689
+ buffer_sprintf(wb, " {%sid%s:%s%s,%slabel%s:%stime%s,%spattern%s:%s%s,%stype%s:%sdatetime%s},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq);
690
+ buffer_sprintf(wb, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotation%s}},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
691
+ buffer_sprintf(wb, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotationText%s}}", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
692
+
693
+ // remove the valueobjects flag
694
+ // google wants its own keys
695
+ if(options & RRDR_OPTION_OBJECTSROWS)
696
+ options &= ~RRDR_OPTION_OBJECTSROWS;
697
+ }
698
+ else {
699
+ kq[0] = '"';
700
+ sq[0] = '"';
701
+ if((options & RRDR_OPTION_SECONDS) || (options & RRDR_OPTION_MILLISECONDS)) {
702
+ dates = JSON_DATES_TIMESTAMP;
703
+ dates_with_new = 0;
704
+ }
705
+ else {
706
+ dates = JSON_DATES_JS;
707
+ dates_with_new = 1;
708
+ }
709
+ if( options & RRDR_OPTION_OBJECTSROWS )
710
+ strcpy(pre_date, " { ");
711
+ else
712
+ strcpy(pre_date, " [ ");
713
+ strcpy(pre_label, ", \"");
714
+ strcpy(post_label, "\"");
715
+ strcpy(pre_value, ", ");
716
+ if( options & RRDR_OPTION_OBJECTSROWS )
717
+ strcpy(post_line, "}");
718
+ else
719
+ strcpy(post_line, "]");
720
+ snprintfz(data_begin, 100, "],\n %sdata%s:\n [\n", kq, kq);
721
+ strcpy(finish, "\n ]\n}");
722
+
723
+ buffer_sprintf(wb, "{\n %slabels%s: [", kq, kq);
724
+ buffer_sprintf(wb, "%stime%s", sq, sq);
725
+ }
726
+
727
+ // -------------------------------------------------------------------------
728
+ // print the JSON header
729
+
730
+ long c, i;
731
+ RRDDIM *rd;
732
+
733
+ // print the header lines
734
+ for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
735
+ if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
736
+ if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
737
+
738
+ buffer_strcat(wb, pre_label);
739
+ buffer_strcat(wb, rd->name);
740
+ buffer_strcat(wb, post_label);
741
+ i++;
742
+ }
743
+ if(!i) {
744
+ buffer_strcat(wb, pre_label);
745
+ buffer_strcat(wb, "no data");
746
+ buffer_strcat(wb, post_label);
747
+ }
748
+
749
+ // print the begin of row data
750
+ buffer_strcat(wb, data_begin);
751
+
752
+ // if all dimensions are hidden, print a null
753
+ if(!i) {
754
+ buffer_strcat(wb, finish);
755
+ return;
756
+ }
757
+
758
+ long start = 0, end = rrdr_rows(r), step = 1;
759
+ if((options & RRDR_OPTION_REVERSED)) {
760
+ start = rrdr_rows(r) - 1;
761
+ end = -1;
762
+ step = -1;
763
+ }
764
+
765
+ // for each line in the array
766
+ calculated_number total = 1;
767
+ for(i = start; i != end ;i += step) {
768
+ calculated_number *cn = &r->v[ i * r->d ];
769
+ uint8_t *co = &r->o[ i * r->d ];
770
+
771
+ time_t now = r->t[i];
772
+
773
+ if(dates == JSON_DATES_JS) {
774
+ // generate the local date time
775
+ struct tm tmbuf, *tm = localtime_r(&now, &tmbuf);
776
+ if(!tm) { error("localtime_r() failed."); continue; }
777
+
778
+ if(likely(i != start)) buffer_strcat(wb, ",\n");
779
+ buffer_strcat(wb, pre_date);
780
+
781
+ if( options & RRDR_OPTION_OBJECTSROWS )
782
+ buffer_sprintf(wb, "%stime%s: ", kq, kq);
783
+
784
+ if(dates_with_new)
785
+ buffer_strcat(wb, "new ");
786
+
787
+ buffer_jsdate(wb, tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
788
+
789
+ buffer_strcat(wb, post_date);
790
+
791
+ if(row_annotations) {
792
+ // google supports one annotation per row
793
+ int annotation_found = 0;
794
+ for(c = 0, rd = r->st->dimensions; rd ;c++, rd = rd->next) {
795
+ if(co[c] & RRDR_RESET) {
796
+ buffer_strcat(wb, overflow_annotation);
797
+ annotation_found = 1;
798
+ break;
799
+ }
800
+ }
801
+ if(!annotation_found)
802
+ buffer_strcat(wb, normal_annotation);
803
+ }
804
+ }
805
+ else {
806
+ // print the timestamp of the line
807
+ if(likely(i != start)) buffer_strcat(wb, ",\n");
808
+ buffer_strcat(wb, pre_date);
809
+
810
+ if( options & RRDR_OPTION_OBJECTSROWS )
811
+ buffer_sprintf(wb, "%stime%s: ", kq, kq);
812
+
813
+ buffer_rrd_value(wb, (calculated_number)r->t[i]);
814
+ // in ms
815
+ if(options & RRDR_OPTION_MILLISECONDS) buffer_strcat(wb, "000");
816
+
817
+ buffer_strcat(wb, post_date);
818
+ }
819
+
820
+ if(unlikely(options & RRDR_OPTION_PERCENTAGE)) {
821
+ total = 0;
822
+ for(c = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
823
+ calculated_number n = cn[c];
824
+
825
+ if(likely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
826
+ n = -n;
827
+
828
+ total += n;
829
+ }
830
+ // prevent a division by zero
831
+ if(total == 0) total = 1;
832
+ }
833
+
834
+ // for each dimension
835
+ for(c = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
836
+ if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
837
+ if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
838
+
839
+ calculated_number n = cn[c];
840
+
841
+ buffer_strcat(wb, pre_value);
842
+
843
+ if( options & RRDR_OPTION_OBJECTSROWS )
844
+ buffer_sprintf(wb, "%s%s%s: ", kq, rd->name, kq);
845
+
846
+ if(co[c] & RRDR_EMPTY) {
847
+ if(options & RRDR_OPTION_NULL2ZERO)
848
+ buffer_strcat(wb, "0");
849
+ else
850
+ buffer_strcat(wb, "null");
851
+ }
852
+ else {
853
+ if(unlikely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
854
+ n = -n;
855
+
856
+ if(unlikely(options & RRDR_OPTION_PERCENTAGE))
857
+ n = n * 100 / total;
858
+
859
+ buffer_rrd_value(wb, n);
860
+ }
861
+
862
+ buffer_strcat(wb, post_value);
863
+ }
864
+
865
+ buffer_strcat(wb, post_line);
866
+ }
867
+
868
+ buffer_strcat(wb, finish);
869
+ //info("RRD2JSON(): %s: END", r->st->id);
870
}
871
872
static void rrdr2csv(RRDR *r, BUFFER *wb, uint32_t options, const char *startline, const char *separator, const char *endline, const char *betweenlines)
873
{
874
- //info("RRD2CSV(): %s: BEGIN", r->st->id);
875
- long c, i;
876
- RRDDIM *d;
877
-
878
- // print the csv header
879
- for(c = 0, i = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) {
880
- if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
881
- if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
882
-
883
- if(!i) {
884
- buffer_strcat(wb, startline);
885
- if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\"");
886
- buffer_strcat(wb, "time");
887
- if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\"");
888
- }
889
- buffer_strcat(wb, separator);
890
- if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\"");
891
- buffer_strcat(wb, d->name);
892
- if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\"");
893
- i++;
894
- }
895
- buffer_strcat(wb, endline);
896
-
897
- if(!i) {
898
- // no dimensions present
899
- return;
900
- }
901
-
902
- long start = 0, end = rrdr_rows(r), step = 1;
903
- if((options & RRDR_OPTION_REVERSED)) {
904
- start = rrdr_rows(r) - 1;
905
- end = -1;
906
- step = -1;
907
- }
908
-
909
- // for each line in the array
910
- calculated_number total = 1;
911
- for(i = start; i != end ;i += step) {
912
- calculated_number *cn = &r->v[ i * r->d ];
913
- uint8_t *co = &r->o[ i * r->d ];
914
-
915
- buffer_strcat(wb, betweenlines);
916
- buffer_strcat(wb, startline);
917
-
918
- time_t now = r->t[i];
919
-
920
- if((options & RRDR_OPTION_SECONDS) || (options & RRDR_OPTION_MILLISECONDS)) {
921
- // print the timestamp of the line
922
- buffer_rrd_value(wb, (calculated_number)now);
923
- // in ms
924
- if(options & RRDR_OPTION_MILLISECONDS) buffer_strcat(wb, "000");
925
- }
926
- else {
927
- // generate the local date time
928
- struct tm tmbuf, *tm = localtime_r(&now, &tmbuf);
929
- if(!tm) { error("localtime() failed."); continue; }
930
- buffer_date(wb, tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
931
- }
932
-
933
- if(unlikely(options & RRDR_OPTION_PERCENTAGE)) {
934
- total = 0;
935
- for(c = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) {
936
- calculated_number n = cn[c];
937
-
938
- if(likely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
939
- n = -n;
940
-
941
- total += n;
942
- }
943
- // prevent a division by zero
944
- if(total == 0) total = 1;
945
- }
946
-
947
- // for each dimension
948
- for(c = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) {
949
- if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
950
- if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
951
-
952
- buffer_strcat(wb, separator);
953
-
954
- calculated_number n = cn[c];
955
-
956
- if(co[c] & RRDR_EMPTY) {
957
- if(options & RRDR_OPTION_NULL2ZERO)
958
- buffer_strcat(wb, "0");
959
- else
960
- buffer_strcat(wb, "null");
961
- }
962
- else {
963
- if(unlikely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
964
- n = -n;
965
-
966
- if(unlikely(options & RRDR_OPTION_PERCENTAGE))
967
- n = n * 100 / total;
968
-
969
- buffer_rrd_value(wb, n);
970
- }
971
- }
972
-
973
- buffer_strcat(wb, endline);
974
- }
975
- //info("RRD2CSV(): %s: END", r->st->id);
874
+ //info("RRD2CSV(): %s: BEGIN", r->st->id);
875
+ long c, i;
876
+ RRDDIM *d;
877
+
878
+ // print the csv header
879
+ for(c = 0, i = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) {
880
+ if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
881
+ if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
882
+
883
+ if(!i) {
884
+ buffer_strcat(wb, startline);
885
+ if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\"");
886
+ buffer_strcat(wb, "time");
887
+ if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\"");
888
+ }
889
+ buffer_strcat(wb, separator);
890
+ if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\"");
891
+ buffer_strcat(wb, d->name);
892
+ if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\"");
893
+ i++;
894
+ }
895
+ buffer_strcat(wb, endline);
896
+
897
+ if(!i) {
898
+ // no dimensions present
899
+ return;
900
+ }
901
+
902
+ long start = 0, end = rrdr_rows(r), step = 1;
903
+ if((options & RRDR_OPTION_REVERSED)) {
904
+ start = rrdr_rows(r) - 1;
905
+ end = -1;
906
+ step = -1;
907
+ }
908
+
909
+ // for each line in the array
910
+ calculated_number total = 1;
911
+ for(i = start; i != end ;i += step) {
912
+ calculated_number *cn = &r->v[ i * r->d ];
913
+ uint8_t *co = &r->o[ i * r->d ];
914
+
915
+ buffer_strcat(wb, betweenlines);
916
+ buffer_strcat(wb, startline);
917
+
918
+ time_t now = r->t[i];
919
+
920
+ if((options & RRDR_OPTION_SECONDS) || (options & RRDR_OPTION_MILLISECONDS)) {
921
+ // print the timestamp of the line
922
+ buffer_rrd_value(wb, (calculated_number)now);
923
+ // in ms
924
+ if(options & RRDR_OPTION_MILLISECONDS) buffer_strcat(wb, "000");
925
+ }
926
+ else {
927
+ // generate the local date time
928
+ struct tm tmbuf, *tm = localtime_r(&now, &tmbuf);
929
+ if(!tm) { error("localtime() failed."); continue; }
930
+ buffer_date(wb, tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
931
+ }
932
+
933
+ if(unlikely(options & RRDR_OPTION_PERCENTAGE)) {
934
+ total = 0;
935
+ for(c = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) {
936
+ calculated_number n = cn[c];
937
+
938
+ if(likely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
939
+ n = -n;
940
+
941
+ total += n;
942
+ }
943
+ // prevent a division by zero
944
+ if(total == 0) total = 1;
945
+ }
946
+
947
+ // for each dimension
948
+ for(c = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) {
949
+ if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
950
+ if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
951
+
952
+ buffer_strcat(wb, separator);
953
+
954
+ calculated_number n = cn[c];
955
+
956
+ if(co[c] & RRDR_EMPTY) {
957
+ if(options & RRDR_OPTION_NULL2ZERO)
958
+ buffer_strcat(wb, "0");
959
+ else
960
+ buffer_strcat(wb, "null");
961
+ }
962
+ else {
963
+ if(unlikely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
964
+ n = -n;
965
+
966
+ if(unlikely(options & RRDR_OPTION_PERCENTAGE))
967
+ n = n * 100 / total;
968
+
969
+ buffer_rrd_value(wb, n);
970
+ }
971
+ }
972
+
973
+ buffer_strcat(wb, endline);
974
+ }
975
+ //info("RRD2CSV(): %s: END", r->st->id);
976
}
977
978
inline static calculated_number rrdr2value(RRDR *r, long i, uint32_t options, int *all_values_are_null) {
979
- long c;
980
- RRDDIM *d;
981
-
982
- calculated_number *cn = &r->v[ i * r->d ];
983
- uint8_t *co = &r->o[ i * r->d ];
984
-
985
- calculated_number sum = 0, min = 0, max = 0, v;
986
- int all_null = 1, init = 1;
987
-
988
- calculated_number total = 1;
989
- if(unlikely(options & RRDR_OPTION_PERCENTAGE)) {
990
- total = 0;
991
- for(c = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) {
992
- calculated_number n = cn[c];
993
-
994
- if(likely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
995
- n = -n;
996
-
997
- total += n;
998
- }
999
- // prevent a division by zero
1000
- if(total == 0) total = 1;
1001
- }
1002
-
1003
- // for each dimension
1004
- for(c = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) {
1005
- if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
1006
- if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
1007
-
1008
- calculated_number n = cn[c];
1009
-
1010
- if(likely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
1011
- n = -n;
1012
-
1013
- if(unlikely(options & RRDR_OPTION_PERCENTAGE))
1014
- n = n * 100 / total;
1015
-
1016
- if(unlikely(init)) {
1017
- if(n > 0) {
1018
- min = 0;
1019
- max = n;
1020
- }
1021
- else {
1022
- min = n;
1023
- max = 0;
1024
- }
1025
- init = 0;
1026
- }
1027
-
1028
- if(likely(!(co[c] & RRDR_EMPTY))) {
1029
- all_null = 0;
1030
- sum += n;
1031
- }
1032
-
1033
- if(n < min) min = n;
1034
- if(n > max) max = n;
1035
- }
1036
-
1037
- if(unlikely(all_null)) {
1038
- if(likely(*all_values_are_null))
1039
- *all_values_are_null = 1;
1040
- return 0;
1041
- }
1042
- else {
1043
- if(likely(*all_values_are_null))
1044
- *all_values_are_null = 0;
1045
- }
1046
-
1047
- if(options & RRDR_OPTION_MIN2MAX)
1048
- v = max - min;
1049
- else
1050
- v = sum;
1051
-
1052
- return v;
979
+ long c;
980
+ RRDDIM *d;
981
+
982
+ calculated_number *cn = &r->v[ i * r->d ];
983
+ uint8_t *co = &r->o[ i * r->d ];
984
+
985
+ calculated_number sum = 0, min = 0, max = 0, v;
986
+ int all_null = 1, init = 1;
987
+
988
+ calculated_number total = 1;
989
+ if(unlikely(options & RRDR_OPTION_PERCENTAGE)) {
990
+ total = 0;
991
+ for(c = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) {
992
+ calculated_number n = cn[c];
993
+
994
+ if(likely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
995
+ n = -n;
996
+
997
+ total += n;
998
+ }
999
+ // prevent a division by zero
1000
+ if(total == 0) total = 1;
1001
+ }
1002
+
1003
+ // for each dimension
1004
+ for(c = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) {
1005
+ if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
1006
+ if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
1007
+
1008
+ calculated_number n = cn[c];
1009
+
1010
+ if(likely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
1011
+ n = -n;
1012
+
1013
+ if(unlikely(options & RRDR_OPTION_PERCENTAGE))
1014
+ n = n * 100 / total;
1015
+
1016
+ if(unlikely(init)) {
1017
+ if(n > 0) {
1018
+ min = 0;
1019
+ max = n;
1020
+ }
1021
+ else {
1022
+ min = n;
1023
+ max = 0;
1024
+ }
1025
+ init = 0;
1026
+ }
1027
+
1028
+ if(likely(!(co[c] & RRDR_EMPTY))) {
1029
+ all_null = 0;
1030
+ sum += n;
1031
+ }
1032
+
1033
+ if(n < min) min = n;
1034
+ if(n > max) max = n;
1035
+ }
1036
+
1037
+ if(unlikely(all_null)) {
1038
+ if(likely(*all_values_are_null))
1039
+ *all_values_are_null = 1;
1040
+ return 0;
1041
+ }
1042
+ else {
1043
+ if(likely(*all_values_are_null))
1044
+ *all_values_are_null = 0;
1045
+ }
1046
+
1047
+ if(options & RRDR_OPTION_MIN2MAX)
1048
+ v = max - min;
1049
+ else
1050
+ v = sum;
1051
+
1052
+ return v;
1053
}
1054
1055
static void rrdr2ssv(RRDR *r, BUFFER *wb, uint32_t options, const char *prefix, const char *separator, const char *suffix)
1056
{
1057
- //info("RRD2SSV(): %s: BEGIN", r->st->id);
1058
- long i;
1059
-
1060
- buffer_strcat(wb, prefix);
1061
- long start = 0, end = rrdr_rows(r), step = 1;
1062
- if((options & RRDR_OPTION_REVERSED)) {
1063
- start = rrdr_rows(r) - 1;
1064
- end = -1;
1065
- step = -1;
1066
- }
1067
-
1068
- // for each line in the array
1069
- for(i = start; i != end ;i += step) {
1070
- int all_values_are_null = 0;
1071
- calculated_number v = rrdr2value(r, i, options, &all_values_are_null);
1072
-
1073
- if(likely(i != start)) {
1074
- if(r->min > v) r->min = v;
1075
- if(r->max < v) r->max = v;
1076
- }
1077
- else {
1078
- r->min = v;
1079
- r->max = v;
1080
- }
1081
-
1082
- if(likely(i != start))
1083
- buffer_strcat(wb, separator);
1084
-
1085
- if(all_values_are_null) {
1086
- if(options & RRDR_OPTION_NULL2ZERO)
1087
- buffer_strcat(wb, "0");
1088
- else
1089
- buffer_strcat(wb, "null");
1090
- }
1091
- else
1092
- buffer_rrd_value(wb, v);
1093
- }
1094
- buffer_strcat(wb, suffix);
1095
- //info("RRD2SSV(): %s: END", r->st->id);
1057
+ //info("RRD2SSV(): %s: BEGIN", r->st->id);
1058
+ long i;
1059
+
1060
+ buffer_strcat(wb, prefix);
1061
+ long start = 0, end = rrdr_rows(r), step = 1;
1062
+ if((options & RRDR_OPTION_REVERSED)) {
1063
+ start = rrdr_rows(r) - 1;
1064
+ end = -1;
1065
+ step = -1;
1066
+ }
1067
+
1068
+ // for each line in the array
1069
+ for(i = start; i != end ;i += step) {
1070
+ int all_values_are_null = 0;
1071
+ calculated_number v = rrdr2value(r, i, options, &all_values_are_null);
1072
+
1073
+ if(likely(i != start)) {
1074
+ if(r->min > v) r->min = v;
1075
+ if(r->max < v) r->max = v;
1076
+ }
1077
+ else {
1078
+ r->min = v;
1079
+ r->max = v;
1080
+ }
1081
+
1082
+ if(likely(i != start))
1083
+ buffer_strcat(wb, separator);
1084
+
1085
+ if(all_values_are_null) {
1086
+ if(options & RRDR_OPTION_NULL2ZERO)
1087
+ buffer_strcat(wb, "0");
1088
+ else
1089
+ buffer_strcat(wb, "null");
1090
+ }
1091
+ else
1092
+ buffer_rrd_value(wb, v);
1093
+ }
1094
+ buffer_strcat(wb, suffix);
1095
+ //info("RRD2SSV(): %s: END", r->st->id);
1096
}
1097
1098
inline static calculated_number *rrdr_line_values(RRDR *r)
1099
{
1100
- return &r->v[ r->c * r->d ];
1100
+ return &r->v[ r->c * r->d ];
1101
}
1102
1103
inline static uint8_t *rrdr_line_options(RRDR *r)
1104
{
1105
- return &r->o[ r->c * r->d ];
1105
+ return &r->o[ r->c * r->d ];
1106
}
1107
1108
inline static int rrdr_line_init(RRDR *r, time_t t)
1109
{
1110
- r->c++;
1110
+ r->c++;
1111
1112
- if(unlikely(r->c >= r->n)) {
1113
- error("requested to step above RRDR size for chart %s", r->st->name);
1114
- r->c = r->n - 1;
1115
- }
1112
+ if(unlikely(r->c >= r->n)) {
1113
+ error("requested to step above RRDR size for chart %s", r->st->name);
1114
+ r->c = r->n - 1;
1115
+ }
1116
1117
- // save the time
1118
- r->t[r->c] = t;
1117
+ // save the time
1118
+ r->t[r->c] = t;
1119
1120
- return 1;
1120
+ return 1;
1121
}
1122
1123
inline static void rrdr_lock_rrdset(RRDR *r) {
1124
- if(unlikely(!r)) {
1125
- error("NULL value given!");
1126
- return;
1127
- }
1124
+ if(unlikely(!r)) {
1125
+ error("NULL value given!");
1126
+ return;
1127
+ }
1128
1129
- pthread_rwlock_rdlock(&r->st->rwlock);
1130
- r->has_st_lock = 1;
1129
+ pthread_rwlock_rdlock(&r->st->rwlock);
1130
+ r->has_st_lock = 1;
1131
}
1132
1133
inline static void rrdr_unlock_rrdset(RRDR *r) {
1134
- if(unlikely(!r)) {
1135
- error("NULL value given!");
1136
- return;
1137
- }
1138
-
1139
- if(likely(r->has_st_lock)) {
1140
- pthread_rwlock_unlock(&r->st->rwlock);
1141
- r->has_st_lock = 0;
1142
- }
1134
+ if(unlikely(!r)) {
1135
+ error("NULL value given!");
1136
+ return;
1137
+ }
1138
+
1139
+ if(likely(r->has_st_lock)) {
1140
+ pthread_rwlock_unlock(&r->st->rwlock);
1141
+ r->has_st_lock = 0;
1142
+ }
1143
}
1144
1145
inline static void rrdr_free(RRDR *r)
1146
{
1147
- if(unlikely(!r)) {
1148
- error("NULL value given!");
1149
- return;
1150
- }
1151
-
1152
- rrdr_unlock_rrdset(r);
1153
- freez(r->t);
1154
- freez(r->v);
1155
- freez(r->o);
1156
- freez(r->od);
1157
- freez(r);
1147
+ if(unlikely(!r)) {
1148
+ error("NULL value given!");
1149
+ return;
1150
+ }
1151
+
1152
+ rrdr_unlock_rrdset(r);
1153
+ freez(r->t);
1154
+ freez(r->v);
1155
+ freez(r->o);
1156
+ freez(r->od);
1157
+ freez(r);
1158
}
1159
1160
inline void rrdr_done(RRDR *r)
1161
{
1162
- r->rows = r->c + 1;
1163
- r->c = 0;
1162
+ r->rows = r->c + 1;
1163
+ r->c = 0;
1164
}
1165
1166
static RRDR *rrdr_create(RRDSET *st, long n)
1167
{
1168
- if(unlikely(!st)) {
1169
- error("NULL value given!");
1170
- return NULL;
1171
- }
1168
+ if(unlikely(!st)) {
1169
+ error("NULL value given!");
1170
+ return NULL;
1171
+ }
1172
1173
- RRDR *r = callocz(1, sizeof(RRDR));
1174
- r->st = st;
1173
+ RRDR *r = callocz(1, sizeof(RRDR));
1174
+ r->st = st;
1175
1176
- rrdr_lock_rrdset(r);
1176
+ rrdr_lock_rrdset(r);
1177
1178
- RRDDIM *rd;
1179
- for(rd = st->dimensions ; rd ; rd = rd->next) r->d++;
1178
+ RRDDIM *rd;
1179
+ for(rd = st->dimensions ; rd ; rd = rd->next) r->d++;
1180
1181
- r->n = n;
1181
+ r->n = n;
1182
1183
- r->t = mallocz(n * sizeof(time_t));
1184
- r->v = mallocz(n * r->d * sizeof(calculated_number));
1185
- r->o = mallocz(n * r->d * sizeof(uint8_t));
1186
- r->od = mallocz(r->d * sizeof(uint8_t));
1183
+ r->t = mallocz(n * sizeof(time_t));
1184
+ r->v = mallocz(n * r->d * sizeof(calculated_number));
1185
+ r->o = mallocz(n * r->d * sizeof(uint8_t));
1186
+ r->od = mallocz(r->d * sizeof(uint8_t));
1187
1188
- // set the hidden flag on hidden dimensions
1189
- int c;
1190
- for(c = 0, rd = st->dimensions ; rd ; c++, rd = rd->next) {
1191
- if(unlikely(rd->flags & RRDDIM_FLAG_HIDDEN)) r->od[c] = RRDR_HIDDEN;
1192
- else r->od[c] = 0;
1193
- }
1188
+ // set the hidden flag on hidden dimensions
1189
+ int c;
1190
+ for(c = 0, rd = st->dimensions ; rd ; c++, rd = rd->next) {
1191
+ if(unlikely(rd->flags & RRDDIM_FLAG_HIDDEN)) r->od[c] = RRDR_HIDDEN;
1192
+ else r->od[c] = 0;
1193
+ }
1194
1195
- r->c = -1;
1196
- r->group = 1;
1197
- r->update_every = 1;
1195
+ r->c = -1;
1196
+ r->group = 1;
1197
+ r->update_every = 1;
1198
1199
- return r;
1199
+ return r;
1200
}
1201
1202
RRDR *rrd2rrdr(RRDSET *st, long points, long long after, long long before, int group_method, int aligned)
1203
{
1204
- int debug = st->debug;
1205
- int absolute_period_requested = -1;
1206
-
1207
- time_t first_entry_t = rrdset_first_entry_t(st);
1208
- time_t last_entry_t = rrdset_last_entry_t(st);
1209
-
1210
- if(before == 0 && after == 0) {
1211
- before = last_entry_t;
1212
- after = first_entry_t;
1213
- absolute_period_requested = 0;
1214
- }
1215
-
1216
- // allow relative for before and after
1217
- if(((before < 0)?-before:before) <= (st->update_every * st->entries)) {
1218
- before = last_entry_t + before;
1219
- absolute_period_requested = 0;
1220
- }
1221
-
1222
- if(((after < 0)?-after:after) <= (st->update_every * st->entries)) {
1223
- if(after == 0) after = -st->update_every;
1224
- after = before + after;
1225
- absolute_period_requested = 0;
1226
- }
1227
-
1228
- if(absolute_period_requested == -1)
1229
- absolute_period_requested = 1;
1230
-
1231
- // make sure they are within our timeframe
1232
- if(before > last_entry_t) before = last_entry_t;
1233
- if(before < first_entry_t) before = first_entry_t;
1234
-
1235
- if(after > last_entry_t) after = last_entry_t;
1236
- if(after < first_entry_t) after = first_entry_t;
1237
-
1238
- // check if they are upside down
1239
- if(after > before) {
1240
- time_t tmp = before;
1241
- before = after;
1242
- after = tmp;
1243
- }
1244
-
1245
- // the duration of the chart
1246
- time_t duration = before - after;
1247
- long available_points = duration / st->update_every;
1248
-
1249
- if(duration <= 0 || available_points <= 0)
1250
- return rrdr_create(st, 1);
1251
-
1252
- // check the wanted points
1253
- if(points < 0) points = -points;
1254
- if(points > available_points) points = available_points;
1255
- if(points == 0) points = available_points;
1256
-
1257
- // calculate proper grouping of source data
1258
- long group = available_points / points;
1259
- if(group <= 0) group = 1;
1260
-
1261
- // round group to the closest integer
1262
- if(available_points % points > points / 2) group++;
1263
-
1264
- time_t after_new = (aligned) ? (after - (after % (group * st->update_every))) : after;
1265
- time_t before_new = (aligned) ? (before - (before % (group * st->update_every))) : before;
1266
- long points_new = (before_new - after_new) / st->update_every / group;
1267
-
1268
- // find the starting and ending slots in our round robin db
1269
- long start_at_slot = rrdset_time2slot(st, before_new),
1270
- stop_at_slot = rrdset_time2slot(st, after_new);
1204
+ int debug = st->debug;
1205
+ int absolute_period_requested = -1;
1206
+
1207
+ time_t first_entry_t = rrdset_first_entry_t(st);
1208
+ time_t last_entry_t = rrdset_last_entry_t(st);
1209
+
1210
+ if(before == 0 && after == 0) {
1211
+ before = last_entry_t;
1212
+ after = first_entry_t;
1213
+ absolute_period_requested = 0;
1214
+ }
1215
+
1216
+ // allow relative for before and after
1217
+ if(((before < 0)?-before:before) <= (st->update_every * st->entries)) {
1218
+ before = last_entry_t + before;
1219
+ absolute_period_requested = 0;
1220
+ }
1221
+
1222
+ if(((after < 0)?-after:after) <= (st->update_every * st->entries)) {
1223
+ if(after == 0) after = -st->update_every;
1224
+ after = before + after;
1225
+ absolute_period_requested = 0;
1226
+ }
1227
+
1228
+ if(absolute_period_requested == -1)
1229
+ absolute_period_requested = 1;
1230
+
1231
+ // make sure they are within our timeframe
1232
+ if(before > last_entry_t) before = last_entry_t;
1233
+ if(before < first_entry_t) before = first_entry_t;
1234
+
1235
+ if(after > last_entry_t) after = last_entry_t;
1236
+ if(after < first_entry_t) after = first_entry_t;
1237
+
1238
+ // check if they are upside down
1239
+ if(after > before) {
1240
+ time_t tmp = before;
1241
+ before = after;
1242
+ after = tmp;
1243
+ }
1244
+
1245
+ // the duration of the chart
1246
+ time_t duration = before - after;
1247
+ long available_points = duration / st->update_every;
1248
+
1249
+ if(duration <= 0 || available_points <= 0)
1250
+ return rrdr_create(st, 1);
1251
+
1252
+ // check the wanted points
1253
+ if(points < 0) points = -points;
1254
+ if(points > available_points) points = available_points;
1255
+ if(points == 0) points = available_points;
1256
+
1257
+ // calculate proper grouping of source data
1258
+ long group = available_points / points;
1259
+ if(group <= 0) group = 1;
1260
+
1261
+ // round group to the closest integer
1262
+ if(available_points % points > points / 2) group++;
1263
+
1264
+ time_t after_new = (aligned) ? (after - (after % (group * st->update_every))) : after;
1265
+ time_t before_new = (aligned) ? (before - (before % (group * st->update_every))) : before;
1266
+ long points_new = (before_new - after_new) / st->update_every / group;
1267
+
1268
+ // find the starting and ending slots in our round robin db
1269
+ long start_at_slot = rrdset_time2slot(st, before_new),
1270
+ stop_at_slot = rrdset_time2slot(st, after_new);
1271
1272
#ifdef NETDATA_INTERNAL_CHECKS
1273
- if(after_new < first_entry_t) {
1274
- error("after_new %u is too small, minimum %u", (uint32_t)after_new, (uint32_t)first_entry_t);
1275
- }
1276
- if(after_new > last_entry_t) {
1277
- error("after_new %u is too big, maximum %u", (uint32_t)after_new, (uint32_t)last_entry_t);
1278
- }
1279
- if(before_new < first_entry_t) {
1280
- error("before_new %u is too small, minimum %u", (uint32_t)before_new, (uint32_t)first_entry_t);
1281
- }
1282
- if(before_new > last_entry_t) {
1283
- error("before_new %u is too big, maximum %u", (uint32_t)before_new, (uint32_t)last_entry_t);
1284
- }
1285
- if(start_at_slot < 0 || start_at_slot >= st->entries) {
1286
- error("start_at_slot is invalid %ld, expected 0 to %ld", start_at_slot, st->entries - 1);
1287
- }
1288
- if(stop_at_slot < 0 || stop_at_slot >= st->entries) {
1289
- error("stop_at_slot is invalid %ld, expected 0 to %ld", stop_at_slot, st->entries - 1);
1290
- }
1291
- if(points_new > (before_new - after_new) / group / st->update_every + 1) {
1292
- error("points_new %ld is more than points %ld", points_new, (before_new - after_new) / group / st->update_every + 1);
1293
- }
1273
+ if(after_new < first_entry_t) {
1274
+ error("after_new %u is too small, minimum %u", (uint32_t)after_new, (uint32_t)first_entry_t);
1275
+ }
1276
+ if(after_new > last_entry_t) {
1277
+ error("after_new %u is too big, maximum %u", (uint32_t)after_new, (uint32_t)last_entry_t);
1278
+ }
1279
+ if(before_new < first_entry_t) {
1280
+ error("before_new %u is too small, minimum %u", (uint32_t)before_new, (uint32_t)first_entry_t);
1281
+ }
1282
+ if(before_new > last_entry_t) {
1283
+ error("before_new %u is too big, maximum %u", (uint32_t)before_new, (uint32_t)last_entry_t);
1284
+ }
1285
+ if(start_at_slot < 0 || start_at_slot >= st->entries) {
1286
+ error("start_at_slot is invalid %ld, expected 0 to %ld", start_at_slot, st->entries - 1);
1287
+ }
1288
+ if(stop_at_slot < 0 || stop_at_slot >= st->entries) {
1289
+ error("stop_at_slot is invalid %ld, expected 0 to %ld", stop_at_slot, st->entries - 1);
1290
+ }
1291
+ if(points_new > (before_new - after_new) / group / st->update_every + 1) {
1292
+ error("points_new %ld is more than points %ld", points_new, (before_new - after_new) / group / st->update_every + 1);
1293
+ }
1294
#endif
1295
1296
- //info("RRD2RRDR(): %s: wanted %ld points, got %ld - group=%ld, wanted duration=%u, got %u - wanted %ld - %ld, got %ld - %ld", st->id, points, points_new, group, before - after, before_new - after_new, after, before, after_new, before_new);
1296
+ //info("RRD2RRDR(): %s: wanted %ld points, got %ld - group=%ld, wanted duration=%u, got %u - wanted %ld - %ld, got %ld - %ld", st->id, points, points_new, group, before - after, before_new - after_new, after, before, after_new, before_new);
1297
1298
- after = after_new;
1299
- before = before_new;
1300
- duration = before - after;
1301
- points = points_new;
1298
+ after = after_new;
1299
+ before = before_new;
1300
+ duration = before - after;
1301
+ points = points_new;
1302
1303
- // Now we have:
1304
- // before = the end time of the calculation
1305
- // after = the start time of the calculation
1306
- // duration = the duration of the calculation
1307
- // group = the number of source points to aggregate / group together
1308
- // method = the method of grouping source points
1309
- // points = the number of points to generate
1303
+ // Now we have:
1304
+ // before = the end time of the calculation
1305
+ // after = the start time of the calculation
1306
+ // duration = the duration of the calculation
1307
+ // group = the number of source points to aggregate / group together
1308
+ // method = the method of grouping source points
1309
+ // points = the number of points to generate
1310
1311
1312
- // -------------------------------------------------------------------------
1313
- // initialize our result set
1312
+ // -------------------------------------------------------------------------
1313
+ // initialize our result set
1314
1315
- RRDR *r = rrdr_create(st, points);
1316
- if(!r) {
1315
+ RRDR *r = rrdr_create(st, points);
1316
+ if(!r) {
1317
#ifdef NETDATA_INTERNAL_CHECKS
1318
- error("Cannot create RRDR for %s, after=%u, before=%u, duration=%u, points=%ld", st->id, (uint32_t)after, (uint32_t)before, (uint32_t)duration, points);
1318
+ error("Cannot create RRDR for %s, after=%u, before=%u, duration=%u, points=%ld", st->id, (uint32_t)after, (uint32_t)before, (uint32_t)duration, points);
1319
#endif
1320
- return NULL;
1321
- }
1322
- if(!r->d) {
1320
+ return NULL;
1321
+ }
1322
+ if(!r->d) {
1323
#ifdef NETDATA_INTERNAL_CHECKS
1324
- error("Returning empty RRDR (no dimensions in RRDSET) for %s, after=%u, before=%u, duration=%u, points=%ld", st->id, (uint32_t)after, (uint32_t)before, (uint32_t)duration, points);
1324
+ error("Returning empty RRDR (no dimensions in RRDSET) for %s, after=%u, before=%u, duration=%u, points=%ld", st->id, (uint32_t)after, (uint32_t)before, (uint32_t)duration, points);
1325
#endif
1326
- return r;
1327
- }
1328
-
1329
- if(absolute_period_requested == 1)
1330
- r->result_options |= RRDR_RESULT_OPTION_ABSOLUTE;
1331
- else
1332
- r->result_options |= RRDR_RESULT_OPTION_RELATIVE;
1333
-
1334
- // find how many dimensions we have
1335
- long dimensions = r->d;
1336
-
1337
-
1338
- // -------------------------------------------------------------------------
1339
- // checks for debugging
1340
-
1341
- if(debug) debug(D_RRD_STATS, "INFO %s first_t: %u, last_t: %u, all_duration: %u, after: %u, before: %u, duration: %u, points: %ld, group: %ld"
1342
- , st->id
1343
- , (uint32_t)first_entry_t
1344
- , (uint32_t)last_entry_t
1345
- , (uint32_t)(last_entry_t - first_entry_t)
1346
- , (uint32_t)after
1347
- , (uint32_t)before
1348
- , (uint32_t)duration
1349
- , points
1350
- , group
1351
- );
1352
-
1353
-
1354
- // -------------------------------------------------------------------------
1355
- // temp arrays for keeping values per dimension
1356
-
1357
- calculated_number last_values[dimensions]; // keep the last value of each dimension
1358
- calculated_number group_values[dimensions]; // keep sums when grouping
1359
- long group_counts[dimensions]; // keep the number of values added to group_values
1360
- uint8_t group_options[dimensions];
1361
- uint8_t found_non_zero[dimensions];
1362
-
1363
-
1364
- // initialize them
1365
- RRDDIM *rd;
1366
- long c;
1367
- for( rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
1368
- last_values[c] = 0;
1369
- group_values[c] = 0;
1370
- group_counts[c] = 0;
1371
- group_options[c] = 0;
1372
- found_non_zero[c] = 0;
1373
- }
1374
-
1375
-
1376
- // -------------------------------------------------------------------------
1377
- // the main loop
1378
-
1379
- time_t now = rrdset_slot2time(st, start_at_slot),
1380
- dt = st->update_every,
1381
- group_start_t = 0;
1382
-
1383
- if(unlikely(debug)) debug(D_RRD_STATS, "BEGIN %s after_t: %u (stop_at_t: %ld), before_t: %u (start_at_t: %ld), start_t(now): %u, current_entry: %ld, entries: %ld"
1384
- , st->id
1385
- , (uint32_t)after
1386
- , stop_at_slot
1387
- , (uint32_t)before
1388
- , start_at_slot
1389
- , (uint32_t)now
1390
- , st->current_entry
1391
- , st->entries
1392
- );
1393
-
1394
- r->group = group;
1395
- r->update_every = group * st->update_every;
1396
- r->before = now;
1397
- r->after = now;
1398
-
1399
- //info("RRD2RRDR(): %s: STARTING", st->id);
1400
-
1401
- long slot = start_at_slot, counter = 0, stop_now = 0, added = 0, group_count = 0, add_this = 0;
1402
- for(; !stop_now ; now -= dt, slot--, counter++) {
1403
- if(unlikely(slot < 0)) slot = st->entries - 1;
1404
- if(unlikely(slot == stop_at_slot)) stop_now = counter;
1405
-
1406
- if(unlikely(debug)) debug(D_RRD_STATS, "ROW %s slot: %ld, entries_counter: %ld, group_count: %ld, added: %ld, now: %ld, %s %s"
1407
- , st->id
1408
- , slot
1409
- , counter
1410
- , group_count + 1
1411
- , added
1412
- , now
1413
- , (group_count + 1 == group)?"PRINT":" - "
1414
- , (now >= after && now <= before)?"RANGE":" - "
1415
- );
1416
-
1417
- // make sure we return data in the proper time range
1418
- if(unlikely(now > before)) continue;
1419
- if(unlikely(now < after)) break;
1420
-
1421
- if(unlikely(group_count == 0)) {
1422
- group_start_t = now;
1423
- }
1424
- group_count++;
1425
-
1426
- if(unlikely(group_count == group)) {
1427
- if(unlikely(added >= points)) break;
1428
- add_this = 1;
1429
- }
1430
-
1431
- // do the calculations
1432
- for(rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
1433
- storage_number n = rd->values[slot];
1434
- if(unlikely(!does_storage_number_exist(n))) continue;
1435
-
1436
- group_counts[c]++;
1437
-
1438
- calculated_number value = unpack_storage_number(n);
1439
- if(likely(value != 0.0)) {
1440
- group_options[c] |= RRDR_NONZERO;
1441
- found_non_zero[c] = 1;
1442
- }
1443
-
1444
- if(unlikely(did_storage_number_reset(n)))
1445
- group_options[c] |= RRDR_RESET;
1446
-
1447
- switch(group_method) {
1448
- case GROUP_MAX:
1449
- if(unlikely(fabsl(value) > fabsl(group_values[c])))
1450
- group_values[c] = value;
1451
- break;
1452
-
1453
- default:
1454
- case GROUP_SUM:
1455
- case GROUP_AVERAGE:
1456
- group_values[c] += value;
1457
- break;
1458
-
1459
- case GROUP_INCREMENTAL_SUM:
1460
- if(unlikely(slot == start_at_slot))
1461
- last_values[c] = value;
1462
-
1463
- group_values[c] += last_values[c] - value;
1464
- last_values[c] = value;
1465
- break;
1466
- }
1467
- }
1468
-
1469
- // added it
1470
- if(unlikely(add_this)) {
1471
- if(unlikely(!rrdr_line_init(r, group_start_t))) break;
1472
-
1473
- r->after = now;
1474
-
1475
- calculated_number *cn = rrdr_line_values(r);
1476
- uint8_t *co = rrdr_line_options(r);
1477
-
1478
- for(rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
1479
-
1480
- // update the dimension options
1481
- if(likely(found_non_zero[c])) r->od[c] |= RRDR_NONZERO;
1482
-
1483
- // store the specific point options
1484
- co[c] = group_options[c];
1485
-
1486
- // store the value
1487
- if(unlikely(group_counts[c] == 0)) {
1488
- cn[c] = 0.0;
1489
- co[c] |= RRDR_EMPTY;
1490
- }
1491
- else if(unlikely(group_method == GROUP_AVERAGE)) {
1492
- // GROUP_AVERAGE
1493
- cn[c] = group_values[c] / group_counts[c];
1494
- }
1495
- else {
1496
- // GROUP_SUM
1497
- // GROUP_MAX
1498
- // GROUP_INCREMENTAL_SUM
1499
- cn[c] = group_values[c];
1500
- }
1501
-
1502
- if(cn[c] < r->min) r->min = cn[c];
1503
- if(cn[c] > r->max) r->max = cn[c];
1504
-
1505
- // reset them for the next loop
1506
- group_values[c] = 0;
1507
- group_counts[c] = 0;
1508
- group_options[c] = 0;
1509
- }
1510
-
1511
- added++;
1512
- group_count = 0;
1513
- add_this = 0;
1514
- }
1515
- }
1516
-
1517
- rrdr_done(r);
1518
- //info("RRD2RRDR(): %s: END %ld loops made, %ld points generated", st->id, counter, rrdr_rows(r));
1519
- //error("SHIFT: %s: wanted %ld points, got %ld", st->id, points, rrdr_rows(r));
1520
- return r;
1326
+ return r;
1327
+ }
1328
+
1329
+ if(absolute_period_requested == 1)
1330
+ r->result_options |= RRDR_RESULT_OPTION_ABSOLUTE;
1331
+ else
1332
+ r->result_options |= RRDR_RESULT_OPTION_RELATIVE;
1333
+
1334
+ // find how many dimensions we have
1335
+ long dimensions = r->d;
1336
+
1337
+
1338
+ // -------------------------------------------------------------------------
1339
+ // checks for debugging
1340
+
1341
+ if(debug) debug(D_RRD_STATS, "INFO %s first_t: %u, last_t: %u, all_duration: %u, after: %u, before: %u, duration: %u, points: %ld, group: %ld"
1342
+ , st->id
1343
+ , (uint32_t)first_entry_t
1344
+ , (uint32_t)last_entry_t
1345
+ , (uint32_t)(last_entry_t - first_entry_t)
1346
+ , (uint32_t)after
1347
+ , (uint32_t)before
1348
+ , (uint32_t)duration
1349
+ , points
1350
+ , group
1351
+ );
1352
+
1353
+
1354
+ // -------------------------------------------------------------------------
1355
+ // temp arrays for keeping values per dimension
1356
+
1357
+ calculated_number last_values[dimensions]; // keep the last value of each dimension
1358
+ calculated_number group_values[dimensions]; // keep sums when grouping
1359
+ long group_counts[dimensions]; // keep the number of values added to group_values
1360
+ uint8_t group_options[dimensions];
1361
+ uint8_t found_non_zero[dimensions];
1362
+
1363
+
1364
+ // initialize them
1365
+ RRDDIM *rd;
1366
+ long c;
1367
+ for( rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
1368
+ last_values[c] = 0;
1369
+ group_values[c] = 0;
1370
+ group_counts[c] = 0;
1371
+ group_options[c] = 0;
1372
+ found_non_zero[c] = 0;
1373
+ }
1374
+
1375
+
1376
+ // -------------------------------------------------------------------------
1377
+ // the main loop
1378
+
1379
+ time_t now = rrdset_slot2time(st, start_at_slot),
1380
+ dt = st->update_every,
1381
+ group_start_t = 0;
1382
+
1383
+ if(unlikely(debug)) debug(D_RRD_STATS, "BEGIN %s after_t: %u (stop_at_t: %ld), before_t: %u (start_at_t: %ld), start_t(now): %u, current_entry: %ld, entries: %ld"
1384
+ , st->id
1385
+ , (uint32_t)after
1386
+ , stop_at_slot
1387
+ , (uint32_t)before
1388
+ , start_at_slot
1389
+ , (uint32_t)now
1390
+ , st->current_entry
1391
+ , st->entries
1392
+ );
1393
+
1394
+ r->group = group;
1395
+ r->update_every = group * st->update_every;
1396
+ r->before = now;
1397
+ r->after = now;
1398
+
1399
+ //info("RRD2RRDR(): %s: STARTING", st->id);
1400
+
1401
+ long slot = start_at_slot, counter = 0, stop_now = 0, added = 0, group_count = 0, add_this = 0;
1402
+ for(; !stop_now ; now -= dt, slot--, counter++) {
1403
+ if(unlikely(slot < 0)) slot = st->entries - 1;
1404
+ if(unlikely(slot == stop_at_slot)) stop_now = counter;
1405
+
1406
+ if(unlikely(debug)) debug(D_RRD_STATS, "ROW %s slot: %ld, entries_counter: %ld, group_count: %ld, added: %ld, now: %ld, %s %s"
1407
+ , st->id
1408
+ , slot
1409
+ , counter
1410
+ , group_count + 1
1411
+ , added
1412
+ , now
1413
+ , (group_count + 1 == group)?"PRINT":" - "
1414
+ , (now >= after && now <= before)?"RANGE":" - "
1415
+ );
1416
+
1417
+ // make sure we return data in the proper time range
1418
+ if(unlikely(now > before)) continue;
1419
+ if(unlikely(now < after)) break;
1420
+
1421
+ if(unlikely(group_count == 0)) {
1422
+ group_start_t = now;
1423
+ }
1424
+ group_count++;
1425
+
1426
+ if(unlikely(group_count == group)) {
1427
+ if(unlikely(added >= points)) break;
1428
+ add_this = 1;
1429
+ }
1430
+
1431
+ // do the calculations
1432
+ for(rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
1433
+ storage_number n = rd->values[slot];
1434
+ if(unlikely(!does_storage_number_exist(n))) continue;
1435
+
1436
+ group_counts[c]++;
1437
+
1438
+ calculated_number value = unpack_storage_number(n);
1439
+ if(likely(value != 0.0)) {
1440
+ group_options[c] |= RRDR_NONZERO;
1441
+ found_non_zero[c] = 1;
1442
+ }
1443
+
1444
+ if(unlikely(did_storage_number_reset(n)))
1445
+ group_options[c] |= RRDR_RESET;
1446
+
1447
+ switch(group_method) {
1448
+ case GROUP_MAX:
1449
+ if(unlikely(fabsl(value) > fabsl(group_values[c])))
1450
+ group_values[c] = value;
1451
+ break;
1452
+
1453
+ default:
1454
+ case GROUP_SUM:
1455
+ case GROUP_AVERAGE:
1456
+ group_values[c] += value;
1457
+ break;
1458
+
1459
+ case GROUP_INCREMENTAL_SUM:
1460
+ if(unlikely(slot == start_at_slot))
1461
+ last_values[c] = value;
1462
+
1463
+ group_values[c] += last_values[c] - value;
1464
+ last_values[c] = value;
1465
+ break;
1466
+ }
1467
+ }
1468
+
1469
+ // added it
1470
+ if(unlikely(add_this)) {
1471
+ if(unlikely(!rrdr_line_init(r, group_start_t))) break;
1472
+
1473
+ r->after = now;
1474
+
1475
+ calculated_number *cn = rrdr_line_values(r);
1476
+ uint8_t *co = rrdr_line_options(r);
1477
+
1478
+ for(rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
1479
+
1480
+ // update the dimension options
1481
+ if(likely(found_non_zero[c])) r->od[c] |= RRDR_NONZERO;
1482
+
1483
+ // store the specific point options
1484
+ co[c] = group_options[c];
1485
+
1486
+ // store the value
1487
+ if(unlikely(group_counts[c] == 0)) {
1488
+ cn[c] = 0.0;
1489
+ co[c] |= RRDR_EMPTY;
1490
+ }
1491
+ else if(unlikely(group_method == GROUP_AVERAGE)) {
1492
+ // GROUP_AVERAGE
1493
+ cn[c] = group_values[c] / group_counts[c];
1494
+ }
1495
+ else {
1496
+ // GROUP_SUM
1497
+ // GROUP_MAX
1498
+ // GROUP_INCREMENTAL_SUM
1499
+ cn[c] = group_values[c];
1500
+ }
1501
+
1502
+ if(cn[c] < r->min) r->min = cn[c];
1503
+ if(cn[c] > r->max) r->max = cn[c];
1504
+
1505
+ // reset them for the next loop
1506
+ group_values[c] = 0;
1507
+ group_counts[c] = 0;
1508
+ group_options[c] = 0;
1509
+ }
1510
+
1511
+ added++;
1512
+ group_count = 0;
1513
+ add_this = 0;
1514
+ }
1515
+ }
1516
+
1517
+ rrdr_done(r);
1518
+ //info("RRD2RRDR(): %s: END %ld loops made, %ld points generated", st->id, counter, rrdr_rows(r));
1519
+ //error("SHIFT: %s: wanted %ld points, got %ld", st->id, points, rrdr_rows(r));
1520
+ return r;
1521
}
1522
1523
int rrd2value(RRDSET *st, BUFFER *wb, calculated_number *n, BUFFER *dimensions, long points, long long after, long long before, int group_method, uint32_t options, time_t *latest_timestamp, int *value_is_null)
1524
{
1525
- RRDR *r = rrd2rrdr(st, points, after, before, group_method, !(options & RRDR_OPTION_NOT_ALIGNED));
1526
- if(!r) {
1527
- if(value_is_null) *value_is_null = 1;
1528
- return 500;
1529
- }
1525
+ RRDR *r = rrd2rrdr(st, points, after, before, group_method, !(options & RRDR_OPTION_NOT_ALIGNED));
1526
+ if(!r) {
1527
+ if(value_is_null) *value_is_null = 1;
1528
+ return 500;
1529
+ }
1530
1531
- if(rrdr_rows(r) == 0) {
1532
- rrdr_free(r);
1533
- if(value_is_null) *value_is_null = 1;
1534
- return 400;
1535
- }
1531
+ if(rrdr_rows(r) == 0) {
1532
+ rrdr_free(r);
1533
+ if(value_is_null) *value_is_null = 1;
1534
+ return 400;
1535
+ }
1536
1537
- if(r->result_options & RRDR_RESULT_OPTION_RELATIVE)
1538
- wb->options |= WB_CONTENT_NO_CACHEABLE;
1539
- else if(r->result_options & RRDR_RESULT_OPTION_ABSOLUTE)
1540
- wb->options |= WB_CONTENT_CACHEABLE;
1537
+ if(r->result_options & RRDR_RESULT_OPTION_RELATIVE)
1538
+ wb->options |= WB_CONTENT_NO_CACHEABLE;
1539
+ else if(r->result_options & RRDR_RESULT_OPTION_ABSOLUTE)
1540
+ wb->options |= WB_CONTENT_CACHEABLE;
1541
1542
- options = rrdr_check_options(r, options, (dimensions)?buffer_tostring(dimensions):NULL);
1542
+ options = rrdr_check_options(r, options, (dimensions)?buffer_tostring(dimensions):NULL);
1543
1544
- if(dimensions)
1545
- rrdr_disable_not_selected_dimensions(r, buffer_tostring(dimensions));
1544
+ if(dimensions)
1545
+ rrdr_disable_not_selected_dimensions(r, buffer_tostring(dimensions));
1546
1547
- if(latest_timestamp)
1548
- *latest_timestamp = r->before;
1547
+ if(latest_timestamp)
1548
+ *latest_timestamp = r->before;
1549
1550
- long i = (options & RRDR_OPTION_REVERSED)?rrdr_rows(r) - 1:0;
1551
- *n = rrdr2value(r, i, options, value_is_null);
1550
+ long i = (options & RRDR_OPTION_REVERSED)?rrdr_rows(r) - 1:0;
1551
+ *n = rrdr2value(r, i, options, value_is_null);
1552
1553
- rrdr_free(r);
1554
- return 200;
1553
+ rrdr_free(r);
1554
+ return 200;
1555
}
1556
1557
int rrd2format(RRDSET *st, BUFFER *wb, BUFFER *dimensions, uint32_t format, long points, long long after, long long before, int group_method, uint32_t options, time_t *latest_timestamp)
1558
{
1559
- RRDR *r = rrd2rrdr(st, points, after, before, group_method, !(options & RRDR_OPTION_NOT_ALIGNED));
1560
- if(!r) {
1561
- buffer_strcat(wb, "Cannot generate output with these parameters on this chart.");
1562
- return 500;
1563
- }
1564
-
1565
- if(r->result_options & RRDR_RESULT_OPTION_RELATIVE)
1566
- wb->options |= WB_CONTENT_NO_CACHEABLE;
1567
- else if(r->result_options & RRDR_RESULT_OPTION_ABSOLUTE)
1568
- wb->options |= WB_CONTENT_CACHEABLE;
1569
-
1570
- options = rrdr_check_options(r, options, (dimensions)?buffer_tostring(dimensions):NULL);
1571
-
1572
- if(dimensions)
1573
- rrdr_disable_not_selected_dimensions(r, buffer_tostring(dimensions));
1574
-
1575
- if(latest_timestamp && rrdr_rows(r) > 0)
1576
- *latest_timestamp = r->before;
1577
-
1578
- switch(format) {
1579
- case DATASOURCE_SSV:
1580
- if(options & RRDR_OPTION_JSON_WRAP) {
1581
- wb->contenttype = CT_APPLICATION_JSON;
1582
- rrdr_json_wrapper_begin(r, wb, format, options, 1);
1583
- rrdr2ssv(r, wb, options, "", " ", "");
1584
- rrdr_json_wrapper_end(r, wb, format, options, 1);
1585
- }
1586
- else {
1587
- wb->contenttype = CT_TEXT_PLAIN;
1588
- rrdr2ssv(r, wb, options, "", " ", "");
1589
- }
1590
- break;
1591
-
1592
- case DATASOURCE_SSV_COMMA:
1593
- if(options & RRDR_OPTION_JSON_WRAP) {
1594
- wb->contenttype = CT_APPLICATION_JSON;
1595
- rrdr_json_wrapper_begin(r, wb, format, options, 1);
1596
- rrdr2ssv(r, wb, options, "", ",", "");
1597
- rrdr_json_wrapper_end(r, wb, format, options, 1);
1598
- }
1599
- else {
1600
- wb->contenttype = CT_TEXT_PLAIN;
1601
- rrdr2ssv(r, wb, options, "", ",", "");
1602
- }
1603
- break;
1604
-
1605
- case DATASOURCE_JS_ARRAY:
1606
- if(options & RRDR_OPTION_JSON_WRAP) {
1607
- wb->contenttype = CT_APPLICATION_JSON;
1608
- rrdr_json_wrapper_begin(r, wb, format, options, 0);
1609
- rrdr2ssv(r, wb, options, "[", ",", "]");
1610
- rrdr_json_wrapper_end(r, wb, format, options, 0);
1611
- }
1612
- else {
1613
- wb->contenttype = CT_APPLICATION_JSON;
1614
- rrdr2ssv(r, wb, options, "[", ",", "]");
1615
- }
1616
- break;
1617
-
1618
- case DATASOURCE_CSV:
1619
- if(options & RRDR_OPTION_JSON_WRAP) {
1620
- wb->contenttype = CT_APPLICATION_JSON;
1621
- rrdr_json_wrapper_begin(r, wb, format, options, 1);
1622
- rrdr2csv(r, wb, options, "", ",", "\\n", "");
1623
- rrdr_json_wrapper_end(r, wb, format, options, 1);
1624
- }
1625
- else {
1626
- wb->contenttype = CT_TEXT_PLAIN;
1627
- rrdr2csv(r, wb, options, "", ",", "\r\n", "");
1628
- }
1629
- break;
1630
-
1631
- case DATASOURCE_CSV_JSON_ARRAY:
1632
- wb->contenttype = CT_APPLICATION_JSON;
1633
- if(options & RRDR_OPTION_JSON_WRAP) {
1634
- rrdr_json_wrapper_begin(r, wb, format, options, 0);
1635
- buffer_strcat(wb, "[\n");
1636
- rrdr2csv(r, wb, options + RRDR_OPTION_LABEL_QUOTES, "[", ",", "]", ",\n");
1637
- buffer_strcat(wb, "\n]");
1638
- rrdr_json_wrapper_end(r, wb, format, options, 0);
1639
- }
1640
- else {
1641
- wb->contenttype = CT_TEXT_PLAIN;
1642
- buffer_strcat(wb, "[\n");
1643
- rrdr2csv(r, wb, options + RRDR_OPTION_LABEL_QUOTES, "[", ",", "]", ",\n");
1644
- buffer_strcat(wb, "\n]");
1645
- }
1646
- break;
1647
-
1648
- case DATASOURCE_TSV:
1649
- if(options & RRDR_OPTION_JSON_WRAP) {
1650
- wb->contenttype = CT_APPLICATION_JSON;
1651
- rrdr_json_wrapper_begin(r, wb, format, options, 1);
1652
- rrdr2csv(r, wb, options, "", "\t", "\\n", "");
1653
- rrdr_json_wrapper_end(r, wb, format, options, 1);
1654
- }
1655
- else {
1656
- wb->contenttype = CT_TEXT_PLAIN;
1657
- rrdr2csv(r, wb, options, "", "\t", "\r\n", "");
1658
- }
1659
- break;
1660
-
1661
- case DATASOURCE_HTML:
1662
- if(options & RRDR_OPTION_JSON_WRAP) {
1663
- wb->contenttype = CT_APPLICATION_JSON;
1664
- rrdr_json_wrapper_begin(r, wb, format, options, 1);
1665
- buffer_strcat(wb, "<html>\\n<center>\\n<table border=\\\"0\\\" cellpadding=\\\"5\\\" cellspacing=\\\"5\\\">\\n");
1666
- rrdr2csv(r, wb, options, "<tr><td>", "</td><td>", "</td></tr>\\n", "");
1667
- buffer_strcat(wb, "</table>\\n</center>\\n</html>\\n");
1668
- rrdr_json_wrapper_end(r, wb, format, options, 1);
1669
- }
1670
- else {
1671
- wb->contenttype = CT_TEXT_HTML;
1672
- buffer_strcat(wb, "<html>\n<center>\n<table border=\"0\" cellpadding=\"5\" cellspacing=\"5\">\n");
1673
- rrdr2csv(r, wb, options, "<tr><td>", "</td><td>", "</td></tr>\n", "");
1674
- buffer_strcat(wb, "</table>\n</center>\n</html>\n");
1675
- }
1676
- break;
1677
-
1678
- case DATASOURCE_DATATABLE_JSONP:
1679
- wb->contenttype = CT_APPLICATION_X_JAVASCRIPT;
1680
-
1681
- if(options & RRDR_OPTION_JSON_WRAP)
1682
- rrdr_json_wrapper_begin(r, wb, format, options, 0);
1683
-
1684
- rrdr2json(r, wb, options, 1);
1685
-
1686
- if(options & RRDR_OPTION_JSON_WRAP)
1687
- rrdr_json_wrapper_end(r, wb, format, options, 0);
1688
- break;
1689
-
1690
- case DATASOURCE_DATATABLE_JSON:
1691
- wb->contenttype = CT_APPLICATION_JSON;
1692
-
1693
- if(options & RRDR_OPTION_JSON_WRAP)
1694
- rrdr_json_wrapper_begin(r, wb, format, options, 0);
1695
-
1696
- rrdr2json(r, wb, options, 1);
1697
-
1698
- if(options & RRDR_OPTION_JSON_WRAP)
1699
- rrdr_json_wrapper_end(r, wb, format, options, 0);
1700
- break;
1701
-
1702
- case DATASOURCE_JSONP:
1703
- wb->contenttype = CT_APPLICATION_X_JAVASCRIPT;
1704
- if(options & RRDR_OPTION_JSON_WRAP)
1705
- rrdr_json_wrapper_begin(r, wb, format, options, 0);
1706
-
1707
- rrdr2json(r, wb, options, 0);
1708
-
1709
- if(options & RRDR_OPTION_JSON_WRAP)
1710
- rrdr_json_wrapper_end(r, wb, format, options, 0);
1711
- break;
1712
-
1713
- case DATASOURCE_JSON:
1714
- default:
1715
- wb->contenttype = CT_APPLICATION_JSON;
1716
-
1717
- if(options & RRDR_OPTION_JSON_WRAP)
1718
- rrdr_json_wrapper_begin(r, wb, format, options, 0);
1719
-
1720
- rrdr2json(r, wb, options, 0);
1721
-
1722
- if(options & RRDR_OPTION_JSON_WRAP)
1723
- rrdr_json_wrapper_end(r, wb, format, options, 0);
1724
- break;
1725
- }
1726
-
1727
- rrdr_free(r);
1728
- return 200;
1559
+ RRDR *r = rrd2rrdr(st, points, after, before, group_method, !(options & RRDR_OPTION_NOT_ALIGNED));
1560
+ if(!r) {
1561
+ buffer_strcat(wb, "Cannot generate output with these parameters on this chart.");
1562
+ return 500;
1563
+ }
1564
+
1565
+ if(r->result_options & RRDR_RESULT_OPTION_RELATIVE)
1566
+ wb->options |= WB_CONTENT_NO_CACHEABLE;
1567
+ else if(r->result_options & RRDR_RESULT_OPTION_ABSOLUTE)
1568
+ wb->options |= WB_CONTENT_CACHEABLE;
1569
+
1570
+ options = rrdr_check_options(r, options, (dimensions)?buffer_tostring(dimensions):NULL);
1571
+
1572
+ if(dimensions)
1573
+ rrdr_disable_not_selected_dimensions(r, buffer_tostring(dimensions));
1574
+
1575
+ if(latest_timestamp && rrdr_rows(r) > 0)
1576
+ *latest_timestamp = r->before;
1577
+
1578
+ switch(format) {
1579
+ case DATASOURCE_SSV:
1580
+ if(options & RRDR_OPTION_JSON_WRAP) {
1581
+ wb->contenttype = CT_APPLICATION_JSON;
1582
+ rrdr_json_wrapper_begin(r, wb, format, options, 1);
1583
+ rrdr2ssv(r, wb, options, "", " ", "");
1584
+ rrdr_json_wrapper_end(r, wb, format, options, 1);
1585
+ }
1586
+ else {
1587
+ wb->contenttype = CT_TEXT_PLAIN;
1588
+ rrdr2ssv(r, wb, options, "", " ", "");
1589
+ }
1590
+ break;
1591
+
1592
+ case DATASOURCE_SSV_COMMA:
1593
+ if(options & RRDR_OPTION_JSON_WRAP) {
1594
+ wb->contenttype = CT_APPLICATION_JSON;
1595
+ rrdr_json_wrapper_begin(r, wb, format, options, 1);
1596
+ rrdr2ssv(r, wb, options, "", ",", "");
1597
+ rrdr_json_wrapper_end(r, wb, format, options, 1);
1598
+ }
1599
+ else {
1600
+ wb->contenttype = CT_TEXT_PLAIN;
1601
+ rrdr2ssv(r, wb, options, "", ",", "");
1602
+ }
1603
+ break;
1604
+
1605
+ case DATASOURCE_JS_ARRAY:
1606
+ if(options & RRDR_OPTION_JSON_WRAP) {
1607
+ wb->contenttype = CT_APPLICATION_JSON;
1608
+ rrdr_json_wrapper_begin(r, wb, format, options, 0);
1609
+ rrdr2ssv(r, wb, options, "[", ",", "]");
1610
+ rrdr_json_wrapper_end(r, wb, format, options, 0);
1611
+ }
1612
+ else {
1613
+ wb->contenttype = CT_APPLICATION_JSON;
1614
+ rrdr2ssv(r, wb, options, "[", ",", "]");
1615
+ }
1616
+ break;
1617
+
1618
+ case DATASOURCE_CSV:
1619
+ if(options & RRDR_OPTION_JSON_WRAP) {
1620
+ wb->contenttype = CT_APPLICATION_JSON;
1621
+ rrdr_json_wrapper_begin(r, wb, format, options, 1);
1622
+ rrdr2csv(r, wb, options, "", ",", "\\n", "");
1623
+ rrdr_json_wrapper_end(r, wb, format, options, 1);
1624
+ }
1625
+ else {
1626
+ wb->contenttype = CT_TEXT_PLAIN;
1627
+ rrdr2csv(r, wb, options, "", ",", "\r\n", "");
1628
+ }
1629
+ break;
1630
+
1631
+ case DATASOURCE_CSV_JSON_ARRAY:
1632
+ wb->contenttype = CT_APPLICATION_JSON;
1633
+ if(options & RRDR_OPTION_JSON_WRAP) {
1634
+ rrdr_json_wrapper_begin(r, wb, format, options, 0);
1635
+ buffer_strcat(wb, "[\n");
1636
+ rrdr2csv(r, wb, options + RRDR_OPTION_LABEL_QUOTES, "[", ",", "]", ",\n");
1637
+ buffer_strcat(wb, "\n]");
1638
+ rrdr_json_wrapper_end(r, wb, format, options, 0);
1639
+ }
1640
+ else {
1641
+ wb->contenttype = CT_TEXT_PLAIN;
1642
+ buffer_strcat(wb, "[\n");
1643
+ rrdr2csv(r, wb, options + RRDR_OPTION_LABEL_QUOTES, "[", ",", "]", ",\n");
1644
+ buffer_strcat(wb, "\n]");
1645
+ }
1646
+ break;
1647
+
1648
+ case DATASOURCE_TSV:
1649
+ if(options & RRDR_OPTION_JSON_WRAP) {
1650
+ wb->contenttype = CT_APPLICATION_JSON;
1651
+ rrdr_json_wrapper_begin(r, wb, format, options, 1);
1652
+ rrdr2csv(r, wb, options, "", "\t", "\\n", "");
1653
+ rrdr_json_wrapper_end(r, wb, format, options, 1);
1654
+ }
1655
+ else {
1656
+ wb->contenttype = CT_TEXT_PLAIN;
1657
+ rrdr2csv(r, wb, options, "", "\t", "\r\n", "");
1658
+ }
1659
+ break;
1660
+
1661
+ case DATASOURCE_HTML:
1662
+ if(options & RRDR_OPTION_JSON_WRAP) {
1663
+ wb->contenttype = CT_APPLICATION_JSON;
1664
+ rrdr_json_wrapper_begin(r, wb, format, options, 1);
1665
+ buffer_strcat(wb, "<html>\\n<center>\\n<table border=\\\"0\\\" cellpadding=\\\"5\\\" cellspacing=\\\"5\\\">\\n");
1666
+ rrdr2csv(r, wb, options, "<tr><td>", "</td><td>", "</td></tr>\\n", "");
1667
+ buffer_strcat(wb, "</table>\\n</center>\\n</html>\\n");
1668
+ rrdr_json_wrapper_end(r, wb, format, options, 1);
1669
+ }
1670
+ else {
1671
+ wb->contenttype = CT_TEXT_HTML;
1672
+ buffer_strcat(wb, "<html>\n<center>\n<table border=\"0\" cellpadding=\"5\" cellspacing=\"5\">\n");
1673
+ rrdr2csv(r, wb, options, "<tr><td>", "</td><td>", "</td></tr>\n", "");
1674
+ buffer_strcat(wb, "</table>\n</center>\n</html>\n");
1675
+ }
1676
+ break;
1677
+
1678
+ case DATASOURCE_DATATABLE_JSONP:
1679
+ wb->contenttype = CT_APPLICATION_X_JAVASCRIPT;
1680
+
1681
+ if(options & RRDR_OPTION_JSON_WRAP)
1682
+ rrdr_json_wrapper_begin(r, wb, format, options, 0);
1683
+
1684
+ rrdr2json(r, wb, options, 1);
1685
+
1686
+ if(options & RRDR_OPTION_JSON_WRAP)
1687
+ rrdr_json_wrapper_end(r, wb, format, options, 0);
1688
+ break;
1689
+
1690
+ case DATASOURCE_DATATABLE_JSON:
1691
+ wb->contenttype = CT_APPLICATION_JSON;
1692
+
1693
+ if(options & RRDR_OPTION_JSON_WRAP)
1694
+ rrdr_json_wrapper_begin(r, wb, format, options, 0);
1695
+
1696
+ rrdr2json(r, wb, options, 1);
1697
+
1698
+ if(options & RRDR_OPTION_JSON_WRAP)
1699
+ rrdr_json_wrapper_end(r, wb, format, options, 0);
1700
+ break;
1701
+
1702
+ case DATASOURCE_JSONP:
1703
+ wb->contenttype = CT_APPLICATION_X_JAVASCRIPT;
1704
+ if(options & RRDR_OPTION_JSON_WRAP)
1705
+ rrdr_json_wrapper_begin(r, wb, format, options, 0);
1706
+
1707
+ rrdr2json(r, wb, options, 0);
1708
+
1709
+ if(options & RRDR_OPTION_JSON_WRAP)
1710
+ rrdr_json_wrapper_end(r, wb, format, options, 0);
1711
+ break;
1712
+
1713
+ case DATASOURCE_JSON:
1714
+ default:
1715
+ wb->contenttype = CT_APPLICATION_JSON;
1716
+
1717
+ if(options & RRDR_OPTION_JSON_WRAP)
1718
+ rrdr_json_wrapper_begin(r, wb, format, options, 0);
1719
+
1720
+ rrdr2json(r, wb, options, 0);
1721
+
1722
+ if(options & RRDR_OPTION_JSON_WRAP)
1723
+ rrdr_json_wrapper_end(r, wb, format, options, 0);
1724
+ break;
1725
+ }
1726
+
1727
+ rrdr_free(r);
1728
+ return 200;
1729
}
1730
1731
time_t rrd_stats_json(int type, RRDSET *st, BUFFER *wb, long points, long group, int group_method, time_t after, time_t before, int only_non_zero)
1732
{
1733
- int c;
1734
- pthread_rwlock_rdlock(&st->rwlock);
1733
+ int c;
1734
+ pthread_rwlock_rdlock(&st->rwlock);
1735
1736
1737
- // -------------------------------------------------------------------------
1738
- // switch from JSON to google JSON
1737
+ // -------------------------------------------------------------------------
1738
+ // switch from JSON to google JSON
1739
1740
- char kq[2] = "\"";
1741
- char sq[2] = "\"";
1742
- switch(type) {
1743
- case DATASOURCE_DATATABLE_JSON:
1744
- case DATASOURCE_DATATABLE_JSONP:
1745
- kq[0] = '\0';
1746
- sq[0] = '\'';
1747
- break;
1740
+ char kq[2] = "\"";
1741
+ char sq[2] = "\"";
1742
+ switch(type) {
1743
+ case DATASOURCE_DATATABLE_JSON:
1744
+ case DATASOURCE_DATATABLE_JSONP:
1745
+ kq[0] = '\0';
1746
+ sq[0] = '\'';
1747
+ break;
1748
1749
- case DATASOURCE_JSON:
1750
- default:
1751
- break;
1752
- }
1749
+ case DATASOURCE_JSON:
1750
+ default:
1751
+ break;
1752
+ }
1753
1754
1755
- // -------------------------------------------------------------------------
1756
- // validate the parameters
1755
+ // -------------------------------------------------------------------------
1756
+ // validate the parameters
1757
1758
- if(points < 1) points = 1;
1759
- if(group < 1) group = 1;
1758
+ if(points < 1) points = 1;
1759
+ if(group < 1) group = 1;
1760
1761
- if(before == 0 || before > rrdset_last_entry_t(st)) before = rrdset_last_entry_t(st);
1762
- if(after == 0 || after < rrdset_first_entry_t(st)) after = rrdset_first_entry_t(st);
1761
+ if(before == 0 || before > rrdset_last_entry_t(st)) before = rrdset_last_entry_t(st);
1762
+ if(after == 0 || after < rrdset_first_entry_t(st)) after = rrdset_first_entry_t(st);
1763
1764
- // ---
1764
+ // ---
1765
1766
- // our return value (the last timestamp printed)
1767
- // this is required to detect re-transmit in google JSONP
1768
- time_t last_timestamp = 0;
1766
+ // our return value (the last timestamp printed)
1767
+ // this is required to detect re-transmit in google JSONP
1768
+ time_t last_timestamp = 0;
1769
1770
1771
- // -------------------------------------------------------------------------
1772
- // find how many dimensions we have
1771
+ // -------------------------------------------------------------------------
1772
+ // find how many dimensions we have
1773
1774
- int dimensions = 0;
1775
- RRDDIM *rd;
1776
- for( rd = st->dimensions ; rd ; rd = rd->next) dimensions++;
1777
- if(!dimensions) {
1778
- pthread_rwlock_unlock(&st->rwlock);
1779
- buffer_strcat(wb, "No dimensions yet.");
1780
- return 0;
1781
- }
1774
+ int dimensions = 0;
1775
+ RRDDIM *rd;
1776
+ for( rd = st->dimensions ; rd ; rd = rd->next) dimensions++;
1777
+ if(!dimensions) {
1778
+ pthread_rwlock_unlock(&st->rwlock);
1779
+ buffer_strcat(wb, "No dimensions yet.");
1780
+ return 0;
1781
+ }
1782
1783
1784
- // -------------------------------------------------------------------------
1785
- // prepare various strings, to speed up the loop
1784
+ // -------------------------------------------------------------------------
1785
+ // prepare various strings, to speed up the loop
1786
1787
- char overflow_annotation[201]; snprintfz(overflow_annotation, 200, ",{%sv%s:%sRESET OR OVERFLOW%s},{%sv%s:%sThe counters have been wrapped.%s}", kq, kq, sq, sq, kq, kq, sq, sq);
1788
- char normal_annotation[201]; snprintfz(normal_annotation, 200, ",{%sv%s:null},{%sv%s:null}", kq, kq, kq, kq);
1789
- char pre_date[51]; snprintfz(pre_date, 50, " {%sc%s:[{%sv%s:%s", kq, kq, kq, kq, sq);
1790
- char post_date[21]; snprintfz(post_date, 20, "%s}", sq);
1791
- char pre_value[21]; snprintfz(pre_value, 20, ",{%sv%s:", kq, kq);
1792
- char post_value[21]; strcpy(post_value, "}");
1787
+ char overflow_annotation[201]; snprintfz(overflow_annotation, 200, ",{%sv%s:%sRESET OR OVERFLOW%s},{%sv%s:%sThe counters have been wrapped.%s}", kq, kq, sq, sq, kq, kq, sq, sq);
1788
+ char normal_annotation[201]; snprintfz(normal_annotation, 200, ",{%sv%s:null},{%sv%s:null}", kq, kq, kq, kq);
1789
+ char pre_date[51]; snprintfz(pre_date, 50, " {%sc%s:[{%sv%s:%s", kq, kq, kq, kq, sq);
1790
+ char post_date[21]; snprintfz(post_date, 20, "%s}", sq);
1791
+ char pre_value[21]; snprintfz(pre_value, 20, ",{%sv%s:", kq, kq);
1792
+ char post_value[21]; strcpy(post_value, "}");
1793
1794
1795
- // -------------------------------------------------------------------------
1796
- // checks for debugging
1795
+ // -------------------------------------------------------------------------
1796
+ // checks for debugging
1797
1798
- if(st->debug) {
1799
- debug(D_RRD_STATS, "%s first_entry_t = %ld, last_entry_t = %ld, duration = %ld, after = %ld, before = %ld, duration = %ld, entries_to_show = %ld, group = %ld"
1800
- , st->id
1801
- , rrdset_first_entry_t(st)
1802
- , rrdset_last_entry_t(st)
1803
- , rrdset_last_entry_t(st) - rrdset_first_entry_t(st)
1804
- , after
1805
- , before
1806
- , before - after
1807
- , points
1808
- , group
1809
- );
1798
+ if(st->debug) {
1799
+ debug(D_RRD_STATS, "%s first_entry_t = %ld, last_entry_t = %ld, duration = %ld, after = %ld, before = %ld, duration = %ld, entries_to_show = %ld, group = %ld"
1800
+ , st->id
1801
+ , rrdset_first_entry_t(st)
1802
+ , rrdset_last_entry_t(st)
1803
+ , rrdset_last_entry_t(st) - rrdset_first_entry_t(st)
1804
+ , after
1805
+ , before
1806
+ , before - after
1807
+ , points
1808
+ , group
1809
+ );
1810
1811
- if(before < after)
1812
- debug(D_RRD_STATS, "WARNING: %s The newest value in the database (%ld) is earlier than the oldest (%ld)", st->name, before, after);
1811
+ if(before < after)
1812
+ debug(D_RRD_STATS, "WARNING: %s The newest value in the database (%ld) is earlier than the oldest (%ld)", st->name, before, after);
1813
1814
- if((before - after) > st->entries * st->update_every)
1815
- debug(D_RRD_STATS, "WARNING: %s The time difference between the oldest and the newest entries (%ld) is higher than the capacity of the database (%ld)", st->name, before - after, st->entries * st->update_every);
1816
- }
1817
-
1818
-
1819
- // -------------------------------------------------------------------------
1820
- // temp arrays for keeping values per dimension
1821
-
1822
- calculated_number group_values[dimensions]; // keep sums when grouping
1823
- int print_hidden[dimensions]; // keep hidden flags
1824
- int found_non_zero[dimensions];
1825
- int found_non_existing[dimensions];
1814
+ if((before - after) > st->entries * st->update_every)
1815
+ debug(D_RRD_STATS, "WARNING: %s The time difference between the oldest and the newest entries (%ld) is higher than the capacity of the database (%ld)", st->name, before - after, st->entries * st->update_every);
1816
+ }
1817
+
1818
+
1819
+ // -------------------------------------------------------------------------
1820
+ // temp arrays for keeping values per dimension
1821
+
1822
+ calculated_number group_values[dimensions]; // keep sums when grouping
1823
+ int print_hidden[dimensions]; // keep hidden flags
1824
+ int found_non_zero[dimensions];
1825
+ int found_non_existing[dimensions];
1826
1827
- // initialize them
1828
- for( rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
1829
- group_values[c] = 0;
1830
- print_hidden[c] = (rd->flags & RRDDIM_FLAG_HIDDEN)?1:0;
1831
- found_non_zero[c] = 0;
1832
- found_non_existing[c] = 0;
1833
- }
1827
+ // initialize them
1828
+ for( rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
1829
+ group_values[c] = 0;
1830
+ print_hidden[c] = (rd->flags & RRDDIM_FLAG_HIDDEN)?1:0;
1831
+ found_non_zero[c] = 0;
1832
+ found_non_existing[c] = 0;
1833
+ }
1834
1835
1836
- // error("OLD: points=%d after=%d before=%d group=%d, duration=%d", entries_to_show, before - (st->update_every * group * entries_to_show), before, group, before - after + 1);
1837
- // rrd2array(st, entries_to_show, before - (st->update_every * group * entries_to_show), before, group_method, only_non_zero);
1838
- // rrd2rrdr(st, entries_to_show, before - (st->update_every * group * entries_to_show), before, group_method);
1839
-
1840
- // -------------------------------------------------------------------------
1841
- // remove dimensions that contain only zeros
1842
-
1843
- int max_loop = 1;
1844
- if(only_non_zero) max_loop = 2;
1845
-
1846
- for(; max_loop ; max_loop--) {
1847
-
1848
- // -------------------------------------------------------------------------
1849
- // print the JSON header
1850
-
1851
- buffer_sprintf(wb, "{\n %scols%s:\n [\n", kq, kq);
1852
- buffer_sprintf(wb, " {%sid%s:%s%s,%slabel%s:%stime%s,%spattern%s:%s%s,%stype%s:%sdatetime%s},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq);
1853
- buffer_sprintf(wb, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotation%s}},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
1854
- buffer_sprintf(wb, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotationText%s}}", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
1855
-
1856
- // print the header for each dimension
1857
- // and update the print_hidden array for the dimensions that should be hidden
1858
- int pc = 0;
1859
- for( rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
1860
- if(!print_hidden[c]) {
1861
- pc++;
1862
- buffer_sprintf(wb, ",\n {%sid%s:%s%s,%slabel%s:%s%s%s,%spattern%s:%s%s,%stype%s:%snumber%s}", kq, kq, sq, sq, kq, kq, sq, rd->name, sq, kq, kq, sq, sq, kq, kq, sq, sq);
1863
- }
1864
- }
1865
- if(!pc) {
1866
- buffer_sprintf(wb, ",\n {%sid%s:%s%s,%slabel%s:%s%s%s,%spattern%s:%s%s,%stype%s:%snumber%s}", kq, kq, sq, sq, kq, kq, sq, "no data", sq, kq, kq, sq, sq, kq, kq, sq, sq);
1867
- }
1868
-
1869
- // print the begin of row data
1870
- buffer_sprintf(wb, "\n ],\n %srows%s:\n [\n", kq, kq);
1871
-
1872
-
1873
- // -------------------------------------------------------------------------
1874
- // the main loop
1875
-
1876
- int annotate_reset = 0;
1877
- int annotation_count = 0;
1878
-
1879
- long t = rrdset_time2slot(st, before),
1880
- stop_at_t = rrdset_time2slot(st, after),
1881
- stop_now = 0;
1882
-
1883
- t -= t % group;
1884
-
1885
- time_t now = rrdset_slot2time(st, t),
1886
- dt = st->update_every;
1887
-
1888
- long count = 0, printed = 0, group_count = 0;
1889
- last_timestamp = 0;
1890
-
1891
- if(st->debug) debug(D_RRD_STATS, "%s: REQUEST after:%u before:%u, points:%ld, group:%ld, CHART cur:%ld first: %u last:%u, CALC start_t:%ld, stop_t:%ld"
1892
- , st->id
1893
- , (uint32_t)after
1894
- , (uint32_t)before
1895
- , points
1896
- , group
1897
- , st->current_entry
1898
- , (uint32_t)rrdset_first_entry_t(st)
1899
- , (uint32_t)rrdset_last_entry_t(st)
1900
- , t
1901
- , stop_at_t
1902
- );
1903
-
1904
- long counter = 0;
1905
- for(; !stop_now ; now -= dt, t--, counter++) {
1906
- if(t < 0) t = st->entries - 1;
1907
- if(t == stop_at_t) stop_now = counter;
1908
-
1909
- int print_this = 0;
1910
-
1911
- if(st->debug) debug(D_RRD_STATS, "%s t = %ld, count = %ld, group_count = %ld, printed = %ld, now = %ld, %s %s"
1912
- , st->id
1913
- , t
1914
- , count + 1
1915
- , group_count + 1
1916
- , printed
1917
- , now
1918
- , (group_count + 1 == group)?"PRINT":" - "
1919
- , (now >= after && now <= before)?"RANGE":" - "
1920
- );
1921
-
1922
-
1923
- // make sure we return data in the proper time range
1924
- if(now > before) continue;
1925
- if(now < after) break;
1926
-
1927
- //if(rrdset_slot2time(st, t) != now)
1928
- // error("%s: slot=%ld, now=%ld, slot2time=%ld, diff=%ld, last_entry_t=%ld, rrdset_last_slot=%ld", st->id, t, now, rrdset_slot2time(st,t), now - rrdset_slot2time(st,t), rrdset_last_entry_t(st), rrdset_last_slot(st));
1929
-
1930
- count++;
1931
- group_count++;
1932
-
1933
- // check if we have to print this now
1934
- if(group_count == group) {
1935
- if(printed >= points) {
1936
- // debug(D_RRD_STATS, "Already printed all rows. Stopping.");
1937
- break;
1938
- }
1939
-
1940
- // generate the local date time
1941
- struct tm tmbuf, *tm = localtime_r(&now, &tmbuf);
1942
- if(!tm) { error("localtime() failed."); continue; }
1943
- if(now > last_timestamp) last_timestamp = now;
1944
-
1945
- if(printed) buffer_strcat(wb, "]},\n");
1946
- buffer_strcat(wb, pre_date);
1947
- buffer_jsdate(wb, tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
1948
- buffer_strcat(wb, post_date);
1949
-
1950
- print_this = 1;
1951
- }
1952
-
1953
- // do the calculations
1954
- for(rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
1955
- storage_number n = rd->values[t];
1956
- calculated_number value = unpack_storage_number(n);
1957
-
1958
- if(!does_storage_number_exist(n)) {
1959
- value = 0.0;
1960
- found_non_existing[c]++;
1961
- }
1962
- if(did_storage_number_reset(n)) annotate_reset = 1;
1963
-
1964
- switch(group_method) {
1965
- case GROUP_MAX:
1966
- if(abs(value) > abs(group_values[c])) group_values[c] = value;
1967
- break;
1968
-
1969
- case GROUP_SUM:
1970
- group_values[c] += value;
1971
- break;
1972
-
1973
- default:
1974
- case GROUP_AVERAGE:
1975
- group_values[c] += value;
1976
- if(print_this) group_values[c] /= ( group_count - found_non_existing[c] );
1977
- break;
1978
- }
1979
- }
1980
-
1981
- if(print_this) {
1982
- if(annotate_reset) {
1983
- annotation_count++;
1984
- buffer_strcat(wb, overflow_annotation);
1985
- annotate_reset = 0;
1986
- }
1987
- else
1988
- buffer_strcat(wb, normal_annotation);
1989
-
1990
- pc = 0;
1991
- for(c = 0 ; c < dimensions ; c++) {
1992
- if(found_non_existing[c] == group_count) {
1993
- // all entries are non-existing
1994
- pc++;
1995
- buffer_strcat(wb, pre_value);
1996
- buffer_strcat(wb, "null");
1997
- buffer_strcat(wb, post_value);
1998
- }
1999
- else if(!print_hidden[c]) {
2000
- pc++;
2001
- buffer_strcat(wb, pre_value);
2002
- buffer_rrd_value(wb, group_values[c]);
2003
- buffer_strcat(wb, post_value);
2004
-
2005
- if(group_values[c]) found_non_zero[c]++;
2006
- }
2007
-
2008
- // reset them for the next loop
2009
- group_values[c] = 0;
2010
- found_non_existing[c] = 0;
2011
- }
2012
-
2013
- // if all dimensions are hidden, print a null
2014
- if(!pc) {
2015
- buffer_strcat(wb, pre_value);
2016
- buffer_strcat(wb, "null");
2017
- buffer_strcat(wb, post_value);
2018
- }
2019
-
2020
- printed++;
2021
- group_count = 0;
2022
- }
2023
- }
2024
-
2025
- if(printed) buffer_strcat(wb, "]}");
2026
- buffer_strcat(wb, "\n ]\n}\n");
2027
-
2028
- if(only_non_zero && max_loop > 1) {
2029
- int changed = 0;
2030
- for(rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
2031
- group_values[c] = 0;
2032
- found_non_existing[c] = 0;
2033
-
2034
- if(!print_hidden[c] && !found_non_zero[c]) {
2035
- changed = 1;
2036
- print_hidden[c] = 1;
2037
- }
2038
- }
2039
-
2040
- if(changed) buffer_flush(wb);
2041
- else break;
2042
- }
2043
- else break;
2044
-
2045
- } // max_loop
2046
-
2047
- debug(D_RRD_STATS, "RRD_STATS_JSON: %s total %lu bytes", st->name, wb->len);
2048
-
2049
- pthread_rwlock_unlock(&st->rwlock);
2050
- return last_timestamp;
1836
+ // error("OLD: points=%d after=%d before=%d group=%d, duration=%d", entries_to_show, before - (st->update_every * group * entries_to_show), before, group, before - after + 1);
1837
+ // rrd2array(st, entries_to_show, before - (st->update_every * group * entries_to_show), before, group_method, only_non_zero);
1838
+ // rrd2rrdr(st, entries_to_show, before - (st->update_every * group * entries_to_show), before, group_method);
1839
+
1840
+ // -------------------------------------------------------------------------
1841
+ // remove dimensions that contain only zeros
1842
+
1843
+ int max_loop = 1;
1844
+ if(only_non_zero) max_loop = 2;
1845
+
1846
+ for(; max_loop ; max_loop--) {
1847
+
1848
+ // -------------------------------------------------------------------------
1849
+ // print the JSON header
1850
+
1851
+ buffer_sprintf(wb, "{\n %scols%s:\n [\n", kq, kq);
1852
+ buffer_sprintf(wb, " {%sid%s:%s%s,%slabel%s:%stime%s,%spattern%s:%s%s,%stype%s:%sdatetime%s},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq);
1853
+ buffer_sprintf(wb, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotation%s}},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
1854
+ buffer_sprintf(wb, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotationText%s}}", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
1855
+
1856
+ // print the header for each dimension
1857
+ // and update the print_hidden array for the dimensions that should be hidden
1858
+ int pc = 0;
1859
+ for( rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
1860
+ if(!print_hidden[c]) {
1861
+ pc++;
1862
+ buffer_sprintf(wb, ",\n {%sid%s:%s%s,%slabel%s:%s%s%s,%spattern%s:%s%s,%stype%s:%snumber%s}", kq, kq, sq, sq, kq, kq, sq, rd->name, sq, kq, kq, sq, sq, kq, kq, sq, sq);
1863
+ }
1864
+ }
1865
+ if(!pc) {
1866
+ buffer_sprintf(wb, ",\n {%sid%s:%s%s,%slabel%s:%s%s%s,%spattern%s:%s%s,%stype%s:%snumber%s}", kq, kq, sq, sq, kq, kq, sq, "no data", sq, kq, kq, sq, sq, kq, kq, sq, sq);
1867
+ }
1868
+
1869
+ // print the begin of row data
1870
+ buffer_sprintf(wb, "\n ],\n %srows%s:\n [\n", kq, kq);
1871
+
1872
+
1873
+ // -------------------------------------------------------------------------
1874
+ // the main loop
1875
+
1876
+ int annotate_reset = 0;
1877
+ int annotation_count = 0;
1878
+
1879
+ long t = rrdset_time2slot(st, before),
1880
+ stop_at_t = rrdset_time2slot(st, after),
1881
+ stop_now = 0;
1882
+
1883
+ t -= t % group;
1884
+
1885
+ time_t now = rrdset_slot2time(st, t),
1886
+ dt = st->update_every;
1887
+
1888
+ long count = 0, printed = 0, group_count = 0;
1889
+ last_timestamp = 0;
1890
+
1891
+ if(st->debug) debug(D_RRD_STATS, "%s: REQUEST after:%u before:%u, points:%ld, group:%ld, CHART cur:%ld first: %u last:%u, CALC start_t:%ld, stop_t:%ld"
1892
+ , st->id
1893
+ , (uint32_t)after
1894
+ , (uint32_t)before
1895
+ , points
1896
+ , group
1897
+ , st->current_entry
1898
+ , (uint32_t)rrdset_first_entry_t(st)
1899
+ , (uint32_t)rrdset_last_entry_t(st)
1900
+ , t
1901
+ , stop_at_t
1902
+ );
1903
+
1904
+ long counter = 0;
1905
+ for(; !stop_now ; now -= dt, t--, counter++) {
1906
+ if(t < 0) t = st->entries - 1;
1907
+ if(t == stop_at_t) stop_now = counter;
1908
+
1909
+ int print_this = 0;
1910
+
1911
+ if(st->debug) debug(D_RRD_STATS, "%s t = %ld, count = %ld, group_count = %ld, printed = %ld, now = %ld, %s %s"
1912
+ , st->id
1913
+ , t
1914
+ , count + 1
1915
+ , group_count + 1
1916
+ , printed
1917
+ , now
1918
+ , (group_count + 1 == group)?"PRINT":" - "
1919
+ , (now >= after && now <= before)?"RANGE":" - "
1920
+ );
1921
+
1922
+
1923
+ // make sure we return data in the proper time range
1924
+ if(now > before) continue;
1925
+ if(now < after) break;
1926
+
1927
+ //if(rrdset_slot2time(st, t) != now)
1928
+ // error("%s: slot=%ld, now=%ld, slot2time=%ld, diff=%ld, last_entry_t=%ld, rrdset_last_slot=%ld", st->id, t, now, rrdset_slot2time(st,t), now - rrdset_slot2time(st,t), rrdset_last_entry_t(st), rrdset_last_slot(st));
1929
+
1930
+ count++;
1931
+ group_count++;
1932
+
1933
+ // check if we have to print this now
1934
+ if(group_count == group) {
1935
+ if(printed >= points) {
1936
+ // debug(D_RRD_STATS, "Already printed all rows. Stopping.");
1937
+ break;
1938
+ }
1939
+
1940
+ // generate the local date time
1941
+ struct tm tmbuf, *tm = localtime_r(&now, &tmbuf);
1942
+ if(!tm) { error("localtime() failed."); continue; }
1943
+ if(now > last_timestamp) last_timestamp = now;
1944
+
1945
+ if(printed) buffer_strcat(wb, "]},\n");
1946
+ buffer_strcat(wb, pre_date);
1947
+ buffer_jsdate(wb, tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
1948
+ buffer_strcat(wb, post_date);
1949
+
1950
+ print_this = 1;
1951
+ }
1952
+
1953
+ // do the calculations
1954
+ for(rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
1955
+ storage_number n = rd->values[t];
1956
+ calculated_number value = unpack_storage_number(n);
1957
+
1958
+ if(!does_storage_number_exist(n)) {
1959
+ value = 0.0;
1960
+ found_non_existing[c]++;
1961
+ }
1962
+ if(did_storage_number_reset(n)) annotate_reset = 1;
1963
+
1964
+ switch(group_method) {
1965
+ case GROUP_MAX:
1966
+ if(abs(value) > abs(group_values[c])) group_values[c] = value;
1967
+ break;
1968
+
1969
+ case GROUP_SUM:
1970
+ group_values[c] += value;
1971
+ break;
1972
+
1973
+ default:
1974
+ case GROUP_AVERAGE:
1975
+ group_values[c] += value;
1976
+ if(print_this) group_values[c] /= ( group_count - found_non_existing[c] );
1977
+ break;
1978
+ }
1979
+ }
1980
+
1981
+ if(print_this) {
1982
+ if(annotate_reset) {
1983
+ annotation_count++;
1984
+ buffer_strcat(wb, overflow_annotation);
1985
+ annotate_reset = 0;
1986
+ }
1987
+ else
1988
+ buffer_strcat(wb, normal_annotation);
1989
+
1990
+ pc = 0;
1991
+ for(c = 0 ; c < dimensions ; c++) {
1992
+ if(found_non_existing[c] == group_count) {
1993
+ // all entries are non-existing
1994
+ pc++;
1995
+ buffer_strcat(wb, pre_value);
1996
+ buffer_strcat(wb, "null");
1997
+ buffer_strcat(wb, post_value);
1998
+ }
1999
+ else if(!print_hidden[c]) {
2000
+ pc++;
2001
+ buffer_strcat(wb, pre_value);
2002
+ buffer_rrd_value(wb, group_values[c]);
2003
+ buffer_strcat(wb, post_value);
2004
+
2005
+ if(group_values[c]) found_non_zero[c]++;
2006
+ }
2007
+
2008
+ // reset them for the next loop
2009
+ group_values[c] = 0;
2010
+ found_non_existing[c] = 0;
2011
+ }
2012
+
2013
+ // if all dimensions are hidden, print a null
2014
+ if(!pc) {
2015
+ buffer_strcat(wb, pre_value);
2016
+ buffer_strcat(wb, "null");
2017
+ buffer_strcat(wb, post_value);
2018
+ }
2019
+
2020
+ printed++;
2021
+ group_count = 0;
2022
+ }
2023
+ }
2024
+
2025
+ if(printed) buffer_strcat(wb, "]}");
2026
+ buffer_strcat(wb, "\n ]\n}\n");
2027
+
2028
+ if(only_non_zero && max_loop > 1) {
2029
+ int changed = 0;
2030
+ for(rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
2031
+ group_values[c] = 0;
2032
+ found_non_existing[c] = 0;
2033
+
2034
+ if(!print_hidden[c] && !found_non_zero[c]) {
2035
+ changed = 1;
2036
+ print_hidden[c] = 1;
2037
+ }
2038
+ }
2039
+
2040
+ if(changed) buffer_flush(wb);
2041
+ else break;
2042
+ }
2043
+ else break;
2044
+
2045
+ } // max_loop
2046
+
2047
+ debug(D_RRD_STATS, "RRD_STATS_JSON: %s total %lu bytes", st->name, wb->len);
2048
+
2049
+ pthread_rwlock_unlock(&st->rwlock);
2050
+ return last_timestamp;
2051
}
src/rrd2json.h
+17
-17
@@ -30,24 +30,24 @@ extern char *hostname;
30
#define DATASOURCE_FORMAT_SSV_COMMA "ssvcomma"
31
#define DATASOURCE_FORMAT_CSV_JSON_ARRAY "csvjsonarray"
32
33
-#define GROUP_AVERAGE 0
34
-#define GROUP_MAX 1
35
-#define GROUP_SUM 2
36
-#define GROUP_INCREMENTAL_SUM 3
33
+#define GROUP_AVERAGE 0
34
+#define GROUP_MAX 1
35
+#define GROUP_SUM 2
36
+#define GROUP_INCREMENTAL_SUM 3
37
38
-#define RRDR_OPTION_NONZERO 0x00000001 // don't output dimensions will just zero values
39
-#define RRDR_OPTION_REVERSED 0x00000002 // output the rows in reverse order (oldest to newest)
40
-#define RRDR_OPTION_ABSOLUTE 0x00000004 // values positive, for DATASOURCE_SSV before summing
41
-#define RRDR_OPTION_MIN2MAX 0x00000008 // when adding dimensions, use max - min, instead of sum
42
-#define RRDR_OPTION_SECONDS 0x00000010 // output seconds, instead of dates
43
-#define RRDR_OPTION_MILLISECONDS 0x00000020 // output milliseconds, instead of dates
44
-#define RRDR_OPTION_NULL2ZERO 0x00000040 // do not show nulls, convert them to zeros
45
-#define RRDR_OPTION_OBJECTSROWS 0x00000080 // each row of values should be an object, not an array
46
-#define RRDR_OPTION_GOOGLE_JSON 0x00000100 // comply with google JSON/JSONP specs
47
-#define RRDR_OPTION_JSON_WRAP 0x00000200 // wrap the response in a JSON header with info about the result
48
-#define RRDR_OPTION_LABEL_QUOTES 0x00000400 // in CSV output, wrap header labels in double quotes
49
-#define RRDR_OPTION_PERCENTAGE 0x00000800 // give values as percentage of total
50
-#define RRDR_OPTION_NOT_ALIGNED 0x00001000 // do not align charts for persistant timeframes
38
+#define RRDR_OPTION_NONZERO 0x00000001 // don't output dimensions will just zero values
39
+#define RRDR_OPTION_REVERSED 0x00000002 // output the rows in reverse order (oldest to newest)
40
+#define RRDR_OPTION_ABSOLUTE 0x00000004 // values positive, for DATASOURCE_SSV before summing
41
+#define RRDR_OPTION_MIN2MAX 0x00000008 // when adding dimensions, use max - min, instead of sum
42
+#define RRDR_OPTION_SECONDS 0x00000010 // output seconds, instead of dates
43
+#define RRDR_OPTION_MILLISECONDS 0x00000020 // output milliseconds, instead of dates
44
+#define RRDR_OPTION_NULL2ZERO 0x00000040 // do not show nulls, convert them to zeros
45
+#define RRDR_OPTION_OBJECTSROWS 0x00000080 // each row of values should be an object, not an array
46
+#define RRDR_OPTION_GOOGLE_JSON 0x00000100 // comply with google JSON/JSONP specs
47
+#define RRDR_OPTION_JSON_WRAP 0x00000200 // wrap the response in a JSON header with info about the result
48
+#define RRDR_OPTION_LABEL_QUOTES 0x00000400 // in CSV output, wrap header labels in double quotes
49
+#define RRDR_OPTION_PERCENTAGE 0x00000800 // give values as percentage of total
50
+#define RRDR_OPTION_NOT_ALIGNED 0x00001000 // do not align charts for persistant timeframes
51
52
extern void rrd_stats_api_v1_chart(RRDSET *st, BUFFER *wb);
53
extern void rrd_stats_api_v1_charts(BUFFER *wb);
src/storage_number.c
+124
-124
@@ -5,164 +5,164 @@ extern char *print_number_llu_r(char *str, unsigned long long uvalue);
5
6
storage_number pack_storage_number(calculated_number value, uint32_t flags)
7
{
8
- // bit 32 = sign 0:positive, 1:negative
9
- // bit 31 = 0:divide, 1:multiply
10
- // bit 30, 29, 28 = (multiplier or divider) 0-6 (7 total)
11
- // bit 27, 26, 25 flags
12
- // bit 24 to bit 1 = the value
13
-
14
- storage_number r = get_storage_number_flags(flags);
15
- if(!value) return r;
16
-
17
- int m = 0;
18
- calculated_number n = value;
19
-
20
- // if the value is negative
21
- // add the sign bit and make it positive
22
- if(n < 0) {
23
- r += (1 << 31); // the sign bit 32
24
- n = -n;
25
- }
26
-
27
- // make its integer part fit in 0x00ffffff
28
- // by dividing it by 10 up to 7 times
29
- // and increasing the multiplier
30
- while(m < 7 && n > (calculated_number)0x00ffffff) {
31
- n /= 10;
32
- m++;
33
- }
34
-
35
- if(m) {
36
- // the value was too big and we divided it
37
- // so we add a multiplier to unpack it
38
- r += (1 << 30) + (m << 27); // the multiplier m
39
-
40
- if(n > (calculated_number)0x00ffffff) {
41
- error("Number " CALCULATED_NUMBER_FORMAT " is too big.", value);
42
- r += 0x00ffffff;
43
- return r;
44
- }
45
- }
46
- else {
47
- // 0x0019999e is the number that can be multiplied
48
- // by 10 to give 0x00ffffff
49
- // while the value is below 0x0019999e we can
50
- // multiply it by 10, up to 7 times, increasing
51
- // the multiplier
52
- while(m < 7 && n < (calculated_number)0x0019999e) {
53
- n *= 10;
54
- m++;
55
- }
56
-
57
- // the value was small enough and we multiplied it
58
- // so we add a divider to unpack it
59
- r += (0 << 30) + (m << 27); // the divider m
60
- }
8
+ // bit 32 = sign 0:positive, 1:negative
9
+ // bit 31 = 0:divide, 1:multiply
10
+ // bit 30, 29, 28 = (multiplier or divider) 0-6 (7 total)
11
+ // bit 27, 26, 25 flags
12
+ // bit 24 to bit 1 = the value
13
+
14
+ storage_number r = get_storage_number_flags(flags);
15
+ if(!value) return r;
16
+
17
+ int m = 0;
18
+ calculated_number n = value;
19
+
20
+ // if the value is negative
21
+ // add the sign bit and make it positive
22
+ if(n < 0) {
23
+ r += (1 << 31); // the sign bit 32
24
+ n = -n;
25
+ }
26
+
27
+ // make its integer part fit in 0x00ffffff
28
+ // by dividing it by 10 up to 7 times
29
+ // and increasing the multiplier
30
+ while(m < 7 && n > (calculated_number)0x00ffffff) {
31
+ n /= 10;
32
+ m++;
33
+ }
34
+
35
+ if(m) {
36
+ // the value was too big and we divided it
37
+ // so we add a multiplier to unpack it
38
+ r += (1 << 30) + (m << 27); // the multiplier m
39
+
40
+ if(n > (calculated_number)0x00ffffff) {
41
+ error("Number " CALCULATED_NUMBER_FORMAT " is too big.", value);
42
+ r += 0x00ffffff;
43
+ return r;
44
+ }
45
+ }
46
+ else {
47
+ // 0x0019999e is the number that can be multiplied
48
+ // by 10 to give 0x00ffffff
49
+ // while the value is below 0x0019999e we can
50
+ // multiply it by 10, up to 7 times, increasing
51
+ // the multiplier
52
+ while(m < 7 && n < (calculated_number)0x0019999e) {
53
+ n *= 10;
54
+ m++;
55
+ }
56
+
57
+ // the value was small enough and we multiplied it
58
+ // so we add a divider to unpack it
59
+ r += (0 << 30) + (m << 27); // the divider m
60
+ }
61
62
#ifdef STORAGE_WITH_MATH
63
- // without this there are rounding problems
64
- // example: 0.9 becomes 0.89
65
- r += lrint((double) n);
63
+ // without this there are rounding problems
64
+ // example: 0.9 becomes 0.89
65
+ r += lrint((double) n);
66
#else
67
- r += (storage_number)n;
67
+ r += (storage_number)n;
68
#endif
69
70
- return r;
70
+ return r;
71
}
72
73
calculated_number unpack_storage_number(storage_number value)
74
{
75
- if(!value) return 0;
75
+ if(!value) return 0;
76
77
- int sign = 0, exp = 0;
77
+ int sign = 0, exp = 0;
78
79
- value ^= get_storage_number_flags(value);
79
+ value ^= get_storage_number_flags(value);
80
81
- if(value & (1 << 31)) {
82
- sign = 1;
83
- value ^= 1 << 31;
84
- }
81
+ if(value & (1 << 31)) {
82
+ sign = 1;
83
+ value ^= 1 << 31;
84
+ }
85
86
- if(value & (1 << 30)) {
87
- exp = 1;
88
- value ^= 1 << 30;
89
- }
86
+ if(value & (1 << 30)) {
87
+ exp = 1;
88
+ value ^= 1 << 30;
89
+ }
90
91
- int mul = value >> 27;
92
- value ^= mul << 27;
91
+ int mul = value >> 27;
92
+ value ^= mul << 27;
93
94
- calculated_number n = value;
94
+ calculated_number n = value;
95
96
- // fprintf(stderr, "UNPACK: %08X, sign = %d, exp = %d, mul = %d, n = " CALCULATED_NUMBER_FORMAT "\n", value, sign, exp, mul, n);
96
+ // fprintf(stderr, "UNPACK: %08X, sign = %d, exp = %d, mul = %d, n = " CALCULATED_NUMBER_FORMAT "\n", value, sign, exp, mul, n);
97
98
- while(mul > 0) {
99
- if(exp) n *= 10;
100
- else n /= 10;
101
- mul--;
102
- }
98
+ while(mul > 0) {
99
+ if(exp) n *= 10;
100
+ else n /= 10;
101
+ mul--;
102
+ }
103
104
- if(sign) n = -n;
105
- return n;
104
+ if(sign) n = -n;
105
+ return n;
106
}
107
108
int print_calculated_number(char *str, calculated_number value)
109
{
110
- char *wstr = str;
110
+ char *wstr = str;
111
112
- int sign = (value < 0) ? 1 : 0;
113
- if(sign) value = -value;
112
+ int sign = (value < 0) ? 1 : 0;
113
+ if(sign) value = -value;
114
115
#ifdef STORAGE_WITH_MATH
116
- // without llrint() there are rounding problems
117
- // for example 0.9 becomes 0.89
118
- unsigned long long uvalue = (unsigned long long int) llrint(value * (calculated_number)100000);
116
+ // without llrint() there are rounding problems
117
+ // for example 0.9 becomes 0.89
118
+ unsigned long long uvalue = (unsigned long long int) llrint(value * (calculated_number)100000);
119
#else
120
- unsigned long long uvalue = value * (calculated_number)100000;
120
+ unsigned long long uvalue = value * (calculated_number)100000;
121
#endif
122
123
#ifdef ENVIRONMENT32
124
- if(uvalue > (unsigned long long)0xffffffff)
125
- wstr = print_number_llu_r(str, uvalue);
126
- else
127
- wstr = print_number_lu_r(str, uvalue);
124
+ if(uvalue > (unsigned long long)0xffffffff)
125
+ wstr = print_number_llu_r(str, uvalue);
126
+ else
127
+ wstr = print_number_lu_r(str, uvalue);
128
#else
129
- do *wstr++ = (char)('0' + (uvalue % 10)); while(uvalue /= 10);
129
+ do *wstr++ = (char)('0' + (uvalue % 10)); while(uvalue /= 10);
130
#endif
131
132
- // make sure we have 6 bytes at least
133
- while((wstr - str) < 6) *wstr++ = '0';
132
+ // make sure we have 6 bytes at least
133
+ while((wstr - str) < 6) *wstr++ = '0';
134
135
- // put the sign back
136
- if(sign) *wstr++ = '-';
135
+ // put the sign back
136
+ if(sign) *wstr++ = '-';
137
138
- // reverse it
138
+ // reverse it
139
char *begin = str, *end = --wstr, aux;
140
while (end > begin) aux = *end, *end-- = *begin, *begin++ = aux;
141
- // wstr--;
142
- // strreverse(str, wstr);
143
-
144
- // remove trailing zeros
145
- int decimal = 5;
146
- while(decimal > 0 && *wstr == '0') {
147
- *wstr-- = '\0';
148
- decimal--;
149
- }
150
-
151
- // terminate it, one position to the right
152
- // to let space for a dot
153
- wstr[2] = '\0';
154
-
155
- // make space for the dot
156
- int i;
157
- for(i = 0; i < decimal ;i++) {
158
- wstr[1] = wstr[0];
159
- wstr--;
160
- }
161
-
162
- // put the dot
163
- if(wstr[2] == '\0') { wstr[1] = '\0'; decimal--; }
164
- else wstr[1] = '.';
165
-
166
- // return the buffer length
167
- return (int) ((wstr - str) + 2 + decimal );
141
+ // wstr--;
142
+ // strreverse(str, wstr);
143
+
144
+ // remove trailing zeros
145
+ int decimal = 5;
146
+ while(decimal > 0 && *wstr == '0') {
147
+ *wstr-- = '\0';
148
+ decimal--;
149
+ }
150
+
151
+ // terminate it, one position to the right
152
+ // to let space for a dot
153
+ wstr[2] = '\0';
154
+
155
+ // make space for the dot
156
+ int i;
157
+ for(i = 0; i < decimal ;i++) {
158
+ wstr[1] = wstr[0];
159
+ wstr--;
160
+ }
161
+
162
+ // put the dot
163
+ if(wstr[2] == '\0') { wstr[1] = '\0'; decimal--; }
164
+ else wstr[1] = '.';
165
+
166
+ // return the buffer length
167
+ return (int) ((wstr - str) + 2 + decimal );
168
}
src/storage_number.h
+9
-9
@@ -17,15 +17,15 @@ typedef long double collected_number;
17
typedef uint32_t storage_number;
18
#define STORAGE_NUMBER_FORMAT "%u"
19
20
-#define SN_NOT_EXISTS (0x0 << 24)
21
-#define SN_EXISTS (0x1 << 24)
22
-#define SN_EXISTS_RESET (0x2 << 24)
23
-#define SN_EXISTS_UNDEF1 (0x3 << 24)
24
-#define SN_EXISTS_UNDEF2 (0x4 << 24)
25
-#define SN_EXISTS_UNDEF3 (0x5 << 24)
26
-#define SN_EXISTS_UNDEF4 (0x6 << 24)
27
-
28
-#define SN_FLAGS_MASK (~(0x6 << 24))
20
+#define SN_NOT_EXISTS (0x0 << 24)
21
+#define SN_EXISTS (0x1 << 24)
22
+#define SN_EXISTS_RESET (0x2 << 24)
23
+#define SN_EXISTS_UNDEF1 (0x3 << 24)
24
+#define SN_EXISTS_UNDEF2 (0x4 << 24)
25
+#define SN_EXISTS_UNDEF3 (0x5 << 24)
26
+#define SN_EXISTS_UNDEF4 (0x6 << 24)
27
+
28
+#define SN_FLAGS_MASK (~(0x6 << 24))
29
30
// extract the flags
31
#define get_storage_number_flags(value) ((((storage_number)value) & (1 << 24)) | (((storage_number)value) & (2 << 24)) | (((storage_number)value) & (4 << 24)))
src/sys_fs_cgroup.c
+1067
-1067
@@ -20,171 +20,171 @@ static int cgroup_root_max = 500;
20
static int cgroup_max_depth = 0;
21
22
void read_cgroup_plugin_configuration() {
23
- cgroup_check_for_new_every = config_get_number("plugin:cgroups", "check for new cgroups every", cgroup_check_for_new_every);
24
-
25
- cgroup_enable_cpuacct_stat = config_get_boolean_ondemand("plugin:cgroups", "enable cpuacct stat", cgroup_enable_cpuacct_stat);
26
- cgroup_enable_cpuacct_usage = config_get_boolean_ondemand("plugin:cgroups", "enable cpuacct usage", cgroup_enable_cpuacct_usage);
27
- cgroup_enable_memory = config_get_boolean_ondemand("plugin:cgroups", "enable memory", cgroup_enable_memory);
28
- cgroup_enable_blkio = config_get_boolean_ondemand("plugin:cgroups", "enable blkio", cgroup_enable_blkio);
29
-
30
- char filename[FILENAME_MAX + 1], *s;
31
- struct mountinfo *mi, *root = mountinfo_read();
32
-
33
- mi = mountinfo_find_by_filesystem_super_option(root, "cgroup", "cpuacct");
34
- if(!mi) mi = mountinfo_find_by_filesystem_mount_source(root, "cgroup", "cpuacct");
35
- if(!mi) {
36
- error("Cannot find cgroup cpuacct mountinfo. Assuming default: /sys/fs/cgroup/cpuacct");
37
- s = "/sys/fs/cgroup/cpuacct";
38
- }
39
- else s = mi->mount_point;
40
- snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, s);
41
- cgroup_cpuacct_base = config_get("plugin:cgroups", "path to /sys/fs/cgroup/cpuacct", filename);
42
-
43
- mi = mountinfo_find_by_filesystem_super_option(root, "cgroup", "blkio");
44
- if(!mi) mi = mountinfo_find_by_filesystem_mount_source(root, "cgroup", "blkio");
45
- if(!mi) {
46
- error("Cannot find cgroup blkio mountinfo. Assuming default: /sys/fs/cgroup/blkio");
47
- s = "/sys/fs/cgroup/blkio";
48
- }
49
- else s = mi->mount_point;
50
- snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, s);
51
- cgroup_blkio_base = config_get("plugin:cgroups", "path to /sys/fs/cgroup/blkio", filename);
52
-
53
- mi = mountinfo_find_by_filesystem_super_option(root, "cgroup", "memory");
54
- if(!mi) mi = mountinfo_find_by_filesystem_mount_source(root, "cgroup", "memory");
55
- if(!mi) {
56
- error("Cannot find cgroup memory mountinfo. Assuming default: /sys/fs/cgroup/memory");
57
- s = "/sys/fs/cgroup/memory";
58
- }
59
- else s = mi->mount_point;
60
- snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, s);
61
- cgroup_memory_base = config_get("plugin:cgroups", "path to /sys/fs/cgroup/memory", filename);
62
-
63
- mi = mountinfo_find_by_filesystem_super_option(root, "cgroup", "devices");
64
- if(!mi) mi = mountinfo_find_by_filesystem_mount_source(root, "cgroup", "devices");
65
- if(!mi) {
66
- error("Cannot find cgroup devices mountinfo. Assuming default: /sys/fs/cgroup/devices");
67
- s = "/sys/fs/cgroup/devices";
68
- }
69
- else s = mi->mount_point;
70
- snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, s);
71
- cgroup_devices_base = config_get("plugin:cgroups", "path to /sys/fs/cgroup/devices", filename);
72
-
73
- cgroup_root_max = config_get_number("plugin:cgroups", "max cgroups to allow", cgroup_root_max);
74
- cgroup_max_depth = config_get_number("plugin:cgroups", "max cgroups depth to monitor", cgroup_max_depth);
75
-
76
- cgroup_enable_new_cgroups_detected_at_runtime = config_get_boolean("plugin:cgroups", "enable new cgroups detected at run time", cgroup_enable_new_cgroups_detected_at_runtime);
77
-
78
- mountinfo_free(root);
23
+ cgroup_check_for_new_every = config_get_number("plugin:cgroups", "check for new cgroups every", cgroup_check_for_new_every);
24
+
25
+ cgroup_enable_cpuacct_stat = config_get_boolean_ondemand("plugin:cgroups", "enable cpuacct stat", cgroup_enable_cpuacct_stat);
26
+ cgroup_enable_cpuacct_usage = config_get_boolean_ondemand("plugin:cgroups", "enable cpuacct usage", cgroup_enable_cpuacct_usage);
27
+ cgroup_enable_memory = config_get_boolean_ondemand("plugin:cgroups", "enable memory", cgroup_enable_memory);
28
+ cgroup_enable_blkio = config_get_boolean_ondemand("plugin:cgroups", "enable blkio", cgroup_enable_blkio);
29
+
30
+ char filename[FILENAME_MAX + 1], *s;
31
+ struct mountinfo *mi, *root = mountinfo_read();
32
+
33
+ mi = mountinfo_find_by_filesystem_super_option(root, "cgroup", "cpuacct");
34
+ if(!mi) mi = mountinfo_find_by_filesystem_mount_source(root, "cgroup", "cpuacct");
35
+ if(!mi) {
36
+ error("Cannot find cgroup cpuacct mountinfo. Assuming default: /sys/fs/cgroup/cpuacct");
37
+ s = "/sys/fs/cgroup/cpuacct";
38
+ }
39
+ else s = mi->mount_point;
40
+ snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, s);
41
+ cgroup_cpuacct_base = config_get("plugin:cgroups", "path to /sys/fs/cgroup/cpuacct", filename);
42
+
43
+ mi = mountinfo_find_by_filesystem_super_option(root, "cgroup", "blkio");
44
+ if(!mi) mi = mountinfo_find_by_filesystem_mount_source(root, "cgroup", "blkio");
45
+ if(!mi) {
46
+ error("Cannot find cgroup blkio mountinfo. Assuming default: /sys/fs/cgroup/blkio");
47
+ s = "/sys/fs/cgroup/blkio";
48
+ }
49
+ else s = mi->mount_point;
50
+ snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, s);
51
+ cgroup_blkio_base = config_get("plugin:cgroups", "path to /sys/fs/cgroup/blkio", filename);
52
+
53
+ mi = mountinfo_find_by_filesystem_super_option(root, "cgroup", "memory");
54
+ if(!mi) mi = mountinfo_find_by_filesystem_mount_source(root, "cgroup", "memory");
55
+ if(!mi) {
56
+ error("Cannot find cgroup memory mountinfo. Assuming default: /sys/fs/cgroup/memory");
57
+ s = "/sys/fs/cgroup/memory";
58
+ }
59
+ else s = mi->mount_point;
60
+ snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, s);
61
+ cgroup_memory_base = config_get("plugin:cgroups", "path to /sys/fs/cgroup/memory", filename);
62
+
63
+ mi = mountinfo_find_by_filesystem_super_option(root, "cgroup", "devices");
64
+ if(!mi) mi = mountinfo_find_by_filesystem_mount_source(root, "cgroup", "devices");
65
+ if(!mi) {
66
+ error("Cannot find cgroup devices mountinfo. Assuming default: /sys/fs/cgroup/devices");
67
+ s = "/sys/fs/cgroup/devices";
68
+ }
69
+ else s = mi->mount_point;
70
+ snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, s);
71
+ cgroup_devices_base = config_get("plugin:cgroups", "path to /sys/fs/cgroup/devices", filename);
72
+
73
+ cgroup_root_max = config_get_number("plugin:cgroups", "max cgroups to allow", cgroup_root_max);
74
+ cgroup_max_depth = config_get_number("plugin:cgroups", "max cgroups depth to monitor", cgroup_max_depth);
75
+
76
+ cgroup_enable_new_cgroups_detected_at_runtime = config_get_boolean("plugin:cgroups", "enable new cgroups detected at run time", cgroup_enable_new_cgroups_detected_at_runtime);
77
+
78
+ mountinfo_free(root);
79
}
80
81
// ----------------------------------------------------------------------------
82
// cgroup objects
83
84
struct blkio {
85
- int updated;
85
+ int updated;
86
87
- char *filename;
87
+ char *filename;
88
89
- unsigned long long Read;
90
- unsigned long long Write;
89
+ unsigned long long Read;
90
+ unsigned long long Write;
91
/*
92
- unsigned long long Sync;
93
- unsigned long long Async;
94
- unsigned long long Total;
92
+ unsigned long long Sync;
93
+ unsigned long long Async;
94
+ unsigned long long Total;
95
*/
96
};
97
98
// https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt
99
struct memory {
100
- int updated;
101
-
102
- char *filename;
103
-
104
- int has_dirty_swap;
105
-
106
- unsigned long long cache;
107
- unsigned long long rss;
108
- unsigned long long rss_huge;
109
- unsigned long long mapped_file;
110
- unsigned long long writeback;
111
- unsigned long long dirty;
112
- unsigned long long swap;
113
- unsigned long long pgpgin;
114
- unsigned long long pgpgout;
115
- unsigned long long pgfault;
116
- unsigned long long pgmajfault;
100
+ int updated;
101
+
102
+ char *filename;
103
+
104
+ int has_dirty_swap;
105
+
106
+ unsigned long long cache;
107
+ unsigned long long rss;
108
+ unsigned long long rss_huge;
109
+ unsigned long long mapped_file;
110
+ unsigned long long writeback;
111
+ unsigned long long dirty;
112
+ unsigned long long swap;
113
+ unsigned long long pgpgin;
114
+ unsigned long long pgpgout;
115
+ unsigned long long pgfault;
116
+ unsigned long long pgmajfault;
117
/*
118
- unsigned long long inactive_anon;
119
- unsigned long long active_anon;
120
- unsigned long long inactive_file;
121
- unsigned long long active_file;
122
- unsigned long long unevictable;
123
- unsigned long long hierarchical_memory_limit;
124
- unsigned long long total_cache;
125
- unsigned long long total_rss;
126
- unsigned long long total_rss_huge;
127
- unsigned long long total_mapped_file;
128
- unsigned long long total_writeback;
129
- unsigned long long total_dirty;
130
- unsigned long long total_swap;
131
- unsigned long long total_pgpgin;
132
- unsigned long long total_pgpgout;
133
- unsigned long long total_pgfault;
134
- unsigned long long total_pgmajfault;
135
- unsigned long long total_inactive_anon;
136
- unsigned long long total_active_anon;
137
- unsigned long long total_inactive_file;
138
- unsigned long long total_active_file;
139
- unsigned long long total_unevictable;
118
+ unsigned long long inactive_anon;
119
+ unsigned long long active_anon;
120
+ unsigned long long inactive_file;
121
+ unsigned long long active_file;
122
+ unsigned long long unevictable;
123
+ unsigned long long hierarchical_memory_limit;
124
+ unsigned long long total_cache;
125
+ unsigned long long total_rss;
126
+ unsigned long long total_rss_huge;
127
+ unsigned long long total_mapped_file;
128
+ unsigned long long total_writeback;
129
+ unsigned long long total_dirty;
130
+ unsigned long long total_swap;
131
+ unsigned long long total_pgpgin;
132
+ unsigned long long total_pgpgout;
133
+ unsigned long long total_pgfault;
134
+ unsigned long long total_pgmajfault;
135
+ unsigned long long total_inactive_anon;
136
+ unsigned long long total_active_anon;
137
+ unsigned long long total_inactive_file;
138
+ unsigned long long total_active_file;
139
+ unsigned long long total_unevictable;
140
*/
141
};
142
143
// https://www.kernel.org/doc/Documentation/cgroup-v1/cpuacct.txt
144
struct cpuacct_stat {
145
- int updated;
145
+ int updated;
146
147
- char *filename;
147
+ char *filename;
148
149
- unsigned long long user;
150
- unsigned long long system;
149
+ unsigned long long user;
150
+ unsigned long long system;
151
};
152
153
// https://www.kernel.org/doc/Documentation/cgroup-v1/cpuacct.txt
154
struct cpuacct_usage {
155
- int updated;
155
+ int updated;
156
157
- char *filename;
157
+ char *filename;
158
159
- unsigned int cpus;
160
- unsigned long long *cpu_percpu;
159
+ unsigned int cpus;
160
+ unsigned long long *cpu_percpu;
161
};
162
163
struct cgroup {
164
- int available; // found in the filesystem
165
- int enabled; // enabled in the config
164
+ int available; // found in the filesystem
165
+ int enabled; // enabled in the config
166
167
- char *id;
168
- uint32_t hash;
167
+ char *id;
168
+ uint32_t hash;
169
170
- char *chart_id;
171
- char *chart_title;
170
+ char *chart_id;
171
+ char *chart_title;
172
173
- struct cpuacct_stat cpuacct_stat;
174
- struct cpuacct_usage cpuacct_usage;
173
+ struct cpuacct_stat cpuacct_stat;
174
+ struct cpuacct_usage cpuacct_usage;
175
176
- struct memory memory;
176
+ struct memory memory;
177
178
- struct blkio io_service_bytes; // bytes
179
- struct blkio io_serviced; // operations
178
+ struct blkio io_service_bytes; // bytes
179
+ struct blkio io_serviced; // operations
180
181
- struct blkio throttle_io_service_bytes; // bytes
182
- struct blkio throttle_io_serviced; // operations
181
+ struct blkio throttle_io_service_bytes; // bytes
182
+ struct blkio throttle_io_serviced; // operations
183
184
- struct blkio io_merged; // operations
185
- struct blkio io_queued; // operations
184
+ struct blkio io_merged; // operations
185
+ struct blkio io_queued; // operations
186
187
- struct cgroup *next;
187
+ struct cgroup *next;
188
189
} *cgroup_root = NULL;
190
@@ -192,389 +192,389 @@ struct cgroup {
192
// read values from /sys
193
194
void cgroup_read_cpuacct_stat(struct cpuacct_stat *cp) {
195
- static procfile *ff = NULL;
195
+ static procfile *ff = NULL;
196
197
- static uint32_t user_hash = 0;
198
- static uint32_t system_hash = 0;
197
+ static uint32_t user_hash = 0;
198
+ static uint32_t system_hash = 0;
199
200
- if(unlikely(user_hash == 0)) {
201
- user_hash = simple_hash("user");
202
- system_hash = simple_hash("system");
203
- }
200
+ if(unlikely(user_hash == 0)) {
201
+ user_hash = simple_hash("user");
202
+ system_hash = simple_hash("system");
203
+ }
204
205
- cp->updated = 0;
206
- if(cp->filename) {
207
- ff = procfile_reopen(ff, cp->filename, NULL, PROCFILE_FLAG_DEFAULT);
208
- if(!ff) return;
205
+ cp->updated = 0;
206
+ if(cp->filename) {
207
+ ff = procfile_reopen(ff, cp->filename, NULL, PROCFILE_FLAG_DEFAULT);
208
+ if(!ff) return;
209
210
- ff = procfile_readall(ff);
211
- if(!ff) return;
210
+ ff = procfile_readall(ff);
211
+ if(!ff) return;
212
213
- unsigned long i, lines = procfile_lines(ff);
213
+ unsigned long i, lines = procfile_lines(ff);
214
215
- if(lines < 1) {
216
- error("File '%s' should have 1+ lines.", cp->filename);
217
- return;
218
- }
215
+ if(lines < 1) {
216
+ error("File '%s' should have 1+ lines.", cp->filename);
217
+ return;
218
+ }
219
220
- for(i = 0; i < lines ; i++) {
221
- char *s = procfile_lineword(ff, i, 0);
222
- uint32_t hash = simple_hash(s);
220
+ for(i = 0; i < lines ; i++) {
221
+ char *s = procfile_lineword(ff, i, 0);
222
+ uint32_t hash = simple_hash(s);
223
224
- if(hash == user_hash && !strcmp(s, "user"))
225
- cp->user = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
224
+ if(hash == user_hash && !strcmp(s, "user"))
225
+ cp->user = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
226
227
- else if(hash == system_hash && !strcmp(s, "system"))
228
- cp->system = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
229
- }
227
+ else if(hash == system_hash && !strcmp(s, "system"))
228
+ cp->system = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
229
+ }
230
231
- cp->updated = 1;
231
+ cp->updated = 1;
232
233
- // fprintf(stderr, "READ '%s': user: %llu, system: %llu\n", cp->filename, cp->user, cp->system);
234
- }
233
+ // fprintf(stderr, "READ '%s': user: %llu, system: %llu\n", cp->filename, cp->user, cp->system);
234
+ }
235
}
236
237
void cgroup_read_cpuacct_usage(struct cpuacct_usage *ca) {
238
- static procfile *ff = NULL;
239
-
240
- ca->updated = 0;
241
- if(ca->filename) {
242
- ff = procfile_reopen(ff, ca->filename, NULL, PROCFILE_FLAG_DEFAULT);
243
- if(!ff) return;
244
-
245
- ff = procfile_readall(ff);
246
- if(!ff) return;
247
-
248
- if(procfile_lines(ff) < 1) {
249
- error("File '%s' should have 1+ lines but has %u.", ca->filename, procfile_lines(ff));
250
- return;
251
- }
252
-
253
- unsigned long i = procfile_linewords(ff, 0);
254
- if(i <= 0) return;
255
-
256
- // we may have 1 more CPU reported
257
- while(i > 0) {
258
- char *s = procfile_lineword(ff, 0, i - 1);
259
- if(!*s) i--;
260
- else break;
261
- }
262
-
263
- if(i != ca->cpus) {
264
- freez(ca->cpu_percpu);
265
- ca->cpu_percpu = mallocz(sizeof(unsigned long long) * i);
266
- ca->cpus = (unsigned int)i;
267
- }
268
-
269
- for(i = 0; i < ca->cpus ;i++) {
270
- ca->cpu_percpu[i] = strtoull(procfile_lineword(ff, 0, i), NULL, 10);
271
- // fprintf(stderr, "READ '%s': cpu%d/%d: %llu ('%s')\n", ca->filename, i, ca->cpus, ca->cpu_percpu[i], procfile_lineword(ff, 0, i));
272
- }
273
-
274
- ca->updated = 1;
275
- }
238
+ static procfile *ff = NULL;
239
+
240
+ ca->updated = 0;
241
+ if(ca->filename) {
242
+ ff = procfile_reopen(ff, ca->filename, NULL, PROCFILE_FLAG_DEFAULT);
243
+ if(!ff) return;
244
+
245
+ ff = procfile_readall(ff);
246
+ if(!ff) return;
247
+
248
+ if(procfile_lines(ff) < 1) {
249
+ error("File '%s' should have 1+ lines but has %u.", ca->filename, procfile_lines(ff));
250
+ return;
251
+ }
252
+
253
+ unsigned long i = procfile_linewords(ff, 0);
254
+ if(i <= 0) return;
255
+
256
+ // we may have 1 more CPU reported
257
+ while(i > 0) {
258
+ char *s = procfile_lineword(ff, 0, i - 1);
259
+ if(!*s) i--;
260
+ else break;
261
+ }
262
+
263
+ if(i != ca->cpus) {
264
+ freez(ca->cpu_percpu);
265
+ ca->cpu_percpu = mallocz(sizeof(unsigned long long) * i);
266
+ ca->cpus = (unsigned int)i;
267
+ }
268
+
269
+ for(i = 0; i < ca->cpus ;i++) {
270
+ ca->cpu_percpu[i] = strtoull(procfile_lineword(ff, 0, i), NULL, 10);
271
+ // fprintf(stderr, "READ '%s': cpu%d/%d: %llu ('%s')\n", ca->filename, i, ca->cpus, ca->cpu_percpu[i], procfile_lineword(ff, 0, i));
272
+ }
273
+
274
+ ca->updated = 1;
275
+ }
276
}
277
278
void cgroup_read_blkio(struct blkio *io) {
279
- static procfile *ff = NULL;
279
+ static procfile *ff = NULL;
280
281
- static uint32_t Read_hash = 0;
282
- static uint32_t Write_hash = 0;
281
+ static uint32_t Read_hash = 0;
282
+ static uint32_t Write_hash = 0;
283
/*
284
- static uint32_t Sync_hash = 0;
285
- static uint32_t Async_hash = 0;
286
- static uint32_t Total_hash = 0;
284
+ static uint32_t Sync_hash = 0;
285
+ static uint32_t Async_hash = 0;
286
+ static uint32_t Total_hash = 0;
287
*/
288
289
- if(unlikely(Read_hash == 0)) {
290
- Read_hash = simple_hash("Read");
291
- Write_hash = simple_hash("Write");
289
+ if(unlikely(Read_hash == 0)) {
290
+ Read_hash = simple_hash("Read");
291
+ Write_hash = simple_hash("Write");
292
/*
293
- Sync_hash = simple_hash("Sync");
294
- Async_hash = simple_hash("Async");
295
- Total_hash = simple_hash("Total");
293
+ Sync_hash = simple_hash("Sync");
294
+ Async_hash = simple_hash("Async");
295
+ Total_hash = simple_hash("Total");
296
*/
297
- }
297
+ }
298
299
- io->updated = 0;
300
- if(io->filename) {
301
- ff = procfile_reopen(ff, io->filename, NULL, PROCFILE_FLAG_DEFAULT);
302
- if(!ff) return;
299
+ io->updated = 0;
300
+ if(io->filename) {
301
+ ff = procfile_reopen(ff, io->filename, NULL, PROCFILE_FLAG_DEFAULT);
302
+ if(!ff) return;
303
304
- ff = procfile_readall(ff);
305
- if(!ff) return;
304
+ ff = procfile_readall(ff);
305
+ if(!ff) return;
306
307
- unsigned long i, lines = procfile_lines(ff);
307
+ unsigned long i, lines = procfile_lines(ff);
308
309
- if(lines < 1) {
310
- error("File '%s' should have 1+ lines.", io->filename);
311
- return;
312
- }
309
+ if(lines < 1) {
310
+ error("File '%s' should have 1+ lines.", io->filename);
311
+ return;
312
+ }
313
314
- io->Read = 0;
315
- io->Write = 0;
314
+ io->Read = 0;
315
+ io->Write = 0;
316
/*
317
- io->Sync = 0;
318
- io->Async = 0;
319
- io->Total = 0;
317
+ io->Sync = 0;
318
+ io->Async = 0;
319
+ io->Total = 0;
320
*/
321
322
- for(i = 0; i < lines ; i++) {
323
- char *s = procfile_lineword(ff, i, 1);
324
- uint32_t hash = simple_hash(s);
322
+ for(i = 0; i < lines ; i++) {
323
+ char *s = procfile_lineword(ff, i, 1);
324
+ uint32_t hash = simple_hash(s);
325
326
- if(hash == Read_hash && !strcmp(s, "Read"))
327
- io->Read += strtoull(procfile_lineword(ff, i, 2), NULL, 10);
326
+ if(hash == Read_hash && !strcmp(s, "Read"))
327
+ io->Read += strtoull(procfile_lineword(ff, i, 2), NULL, 10);
328
329
- else if(hash == Write_hash && !strcmp(s, "Write"))
330
- io->Write += strtoull(procfile_lineword(ff, i, 2), NULL, 10);
329
+ else if(hash == Write_hash && !strcmp(s, "Write"))
330
+ io->Write += strtoull(procfile_lineword(ff, i, 2), NULL, 10);
331
332
/*
333
- else if(hash == Sync_hash && !strcmp(s, "Sync"))
334
- io->Sync += strtoull(procfile_lineword(ff, i, 2), NULL, 10);
333
+ else if(hash == Sync_hash && !strcmp(s, "Sync"))
334
+ io->Sync += strtoull(procfile_lineword(ff, i, 2), NULL, 10);
335
336
- else if(hash == Async_hash && !strcmp(s, "Async"))
337
- io->Async += strtoull(procfile_lineword(ff, i, 2), NULL, 10);
336
+ else if(hash == Async_hash && !strcmp(s, "Async"))
337
+ io->Async += strtoull(procfile_lineword(ff, i, 2), NULL, 10);
338
339
- else if(hash == Total_hash && !strcmp(s, "Total"))
340
- io->Total += strtoull(procfile_lineword(ff, i, 2), NULL, 10);
339
+ else if(hash == Total_hash && !strcmp(s, "Total"))
340
+ io->Total += strtoull(procfile_lineword(ff, i, 2), NULL, 10);
341
*/
342
- }
342
+ }
343
344
- io->updated = 1;
345
- // fprintf(stderr, "READ '%s': Read: %llu, Write: %llu, Sync: %llu, Async: %llu, Total: %llu\n", io->filename, io->Read, io->Write, io->Sync, io->Async, io->Total);
346
- }
344
+ io->updated = 1;
345
+ // fprintf(stderr, "READ '%s': Read: %llu, Write: %llu, Sync: %llu, Async: %llu, Total: %llu\n", io->filename, io->Read, io->Write, io->Sync, io->Async, io->Total);
346
+ }
347
}
348
349
void cgroup_read_memory(struct memory *mem) {
350
- static procfile *ff = NULL;
351
-
352
- static uint32_t cache_hash = 0;
353
- static uint32_t rss_hash = 0;
354
- static uint32_t rss_huge_hash = 0;
355
- static uint32_t mapped_file_hash = 0;
356
- static uint32_t writeback_hash = 0;
357
- static uint32_t dirty_hash = 0;
358
- static uint32_t swap_hash = 0;
359
- static uint32_t pgpgin_hash = 0;
360
- static uint32_t pgpgout_hash = 0;
361
- static uint32_t pgfault_hash = 0;
362
- static uint32_t pgmajfault_hash = 0;
350
+ static procfile *ff = NULL;
351
+
352
+ static uint32_t cache_hash = 0;
353
+ static uint32_t rss_hash = 0;
354
+ static uint32_t rss_huge_hash = 0;
355
+ static uint32_t mapped_file_hash = 0;
356
+ static uint32_t writeback_hash = 0;
357
+ static uint32_t dirty_hash = 0;
358
+ static uint32_t swap_hash = 0;
359
+ static uint32_t pgpgin_hash = 0;
360
+ static uint32_t pgpgout_hash = 0;
361
+ static uint32_t pgfault_hash = 0;
362
+ static uint32_t pgmajfault_hash = 0;
363
/*
364
- static uint32_t inactive_anon_hash = 0;
365
- static uint32_t active_anon_hash = 0;
366
- static uint32_t inactive_file_hash = 0;
367
- static uint32_t active_file_hash = 0;
368
- static uint32_t unevictable_hash = 0;
369
- static uint32_t hierarchical_memory_limit_hash = 0;
370
- static uint32_t total_cache_hash = 0;
371
- static uint32_t total_rss_hash = 0;
372
- static uint32_t total_rss_huge_hash = 0;
373
- static uint32_t total_mapped_file_hash = 0;
374
- static uint32_t total_writeback_hash = 0;
375
- static uint32_t total_dirty_hash = 0;
376
- static uint32_t total_swap_hash = 0;
377
- static uint32_t total_pgpgin_hash = 0;
378
- static uint32_t total_pgpgout_hash = 0;
379
- static uint32_t total_pgfault_hash = 0;
380
- static uint32_t total_pgmajfault_hash = 0;
381
- static uint32_t total_inactive_anon_hash = 0;
382
- static uint32_t total_active_anon_hash = 0;
383
- static uint32_t total_inactive_file_hash = 0;
384
- static uint32_t total_active_file_hash = 0;
385
- static uint32_t total_unevictable_hash = 0;
364
+ static uint32_t inactive_anon_hash = 0;
365
+ static uint32_t active_anon_hash = 0;
366
+ static uint32_t inactive_file_hash = 0;
367
+ static uint32_t active_file_hash = 0;
368
+ static uint32_t unevictable_hash = 0;
369
+ static uint32_t hierarchical_memory_limit_hash = 0;
370
+ static uint32_t total_cache_hash = 0;
371
+ static uint32_t total_rss_hash = 0;
372
+ static uint32_t total_rss_huge_hash = 0;
373
+ static uint32_t total_mapped_file_hash = 0;
374
+ static uint32_t total_writeback_hash = 0;
375
+ static uint32_t total_dirty_hash = 0;
376
+ static uint32_t total_swap_hash = 0;
377
+ static uint32_t total_pgpgin_hash = 0;
378
+ static uint32_t total_pgpgout_hash = 0;
379
+ static uint32_t total_pgfault_hash = 0;
380
+ static uint32_t total_pgmajfault_hash = 0;
381
+ static uint32_t total_inactive_anon_hash = 0;
382
+ static uint32_t total_active_anon_hash = 0;
383
+ static uint32_t total_inactive_file_hash = 0;
384
+ static uint32_t total_active_file_hash = 0;
385
+ static uint32_t total_unevictable_hash = 0;
386
*/
387
- if(unlikely(cache_hash == 0)) {
388
- cache_hash = simple_hash("cache");
389
- rss_hash = simple_hash("rss");
390
- rss_huge_hash = simple_hash("rss_huge");
391
- mapped_file_hash = simple_hash("mapped_file");
392
- writeback_hash = simple_hash("writeback");
393
- dirty_hash = simple_hash("dirty");
394
- swap_hash = simple_hash("swap");
395
- pgpgin_hash = simple_hash("pgpgin");
396
- pgpgout_hash = simple_hash("pgpgout");
397
- pgfault_hash = simple_hash("pgfault");
398
- pgmajfault_hash = simple_hash("pgmajfault");
387
+ if(unlikely(cache_hash == 0)) {
388
+ cache_hash = simple_hash("cache");
389
+ rss_hash = simple_hash("rss");
390
+ rss_huge_hash = simple_hash("rss_huge");
391
+ mapped_file_hash = simple_hash("mapped_file");
392
+ writeback_hash = simple_hash("writeback");
393
+ dirty_hash = simple_hash("dirty");
394
+ swap_hash = simple_hash("swap");
395
+ pgpgin_hash = simple_hash("pgpgin");
396
+ pgpgout_hash = simple_hash("pgpgout");
397
+ pgfault_hash = simple_hash("pgfault");
398
+ pgmajfault_hash = simple_hash("pgmajfault");
399
/*
400
- inactive_anon_hash = simple_hash("inactive_anon");
401
- active_anon_hash = simple_hash("active_anon");
402
- inactive_file_hash = simple_hash("inactive_file");
403
- active_file_hash = simple_hash("active_file");
404
- unevictable_hash = simple_hash("unevictable");
405
- hierarchical_memory_limit_hash = simple_hash("hierarchical_memory_limit");
406
- total_cache_hash = simple_hash("total_cache");
407
- total_rss_hash = simple_hash("total_rss");
408
- total_rss_huge_hash = simple_hash("total_rss_huge");
409
- total_mapped_file_hash = simple_hash("total_mapped_file");
410
- total_writeback_hash = simple_hash("total_writeback");
411
- total_dirty_hash = simple_hash("total_dirty");
412
- total_swap_hash = simple_hash("total_swap");
413
- total_pgpgin_hash = simple_hash("total_pgpgin");
414
- total_pgpgout_hash = simple_hash("total_pgpgout");
415
- total_pgfault_hash = simple_hash("total_pgfault");
416
- total_pgmajfault_hash = simple_hash("total_pgmajfault");
417
- total_inactive_anon_hash = simple_hash("total_inactive_anon");
418
- total_active_anon_hash = simple_hash("total_active_anon");
419
- total_inactive_file_hash = simple_hash("total_inactive_file");
420
- total_active_file_hash = simple_hash("total_active_file");
421
- total_unevictable_hash = simple_hash("total_unevictable");
400
+ inactive_anon_hash = simple_hash("inactive_anon");
401
+ active_anon_hash = simple_hash("active_anon");
402
+ inactive_file_hash = simple_hash("inactive_file");
403
+ active_file_hash = simple_hash("active_file");
404
+ unevictable_hash = simple_hash("unevictable");
405
+ hierarchical_memory_limit_hash = simple_hash("hierarchical_memory_limit");
406
+ total_cache_hash = simple_hash("total_cache");
407
+ total_rss_hash = simple_hash("total_rss");
408
+ total_rss_huge_hash = simple_hash("total_rss_huge");
409
+ total_mapped_file_hash = simple_hash("total_mapped_file");
410
+ total_writeback_hash = simple_hash("total_writeback");
411
+ total_dirty_hash = simple_hash("total_dirty");
412
+ total_swap_hash = simple_hash("total_swap");
413
+ total_pgpgin_hash = simple_hash("total_pgpgin");
414
+ total_pgpgout_hash = simple_hash("total_pgpgout");
415
+ total_pgfault_hash = simple_hash("total_pgfault");
416
+ total_pgmajfault_hash = simple_hash("total_pgmajfault");
417
+ total_inactive_anon_hash = simple_hash("total_inactive_anon");
418
+ total_active_anon_hash = simple_hash("total_active_anon");
419
+ total_inactive_file_hash = simple_hash("total_inactive_file");
420
+ total_active_file_hash = simple_hash("total_active_file");
421
+ total_unevictable_hash = simple_hash("total_unevictable");
422
*/
423
- }
423
+ }
424
425
- mem->updated = 0;
426
- if(mem->filename) {
427
- ff = procfile_reopen(ff, mem->filename, NULL, PROCFILE_FLAG_DEFAULT);
428
- if(!ff) return;
425
+ mem->updated = 0;
426
+ if(mem->filename) {
427
+ ff = procfile_reopen(ff, mem->filename, NULL, PROCFILE_FLAG_DEFAULT);
428
+ if(!ff) return;
429
430
- ff = procfile_readall(ff);
431
- if(!ff) return;
430
+ ff = procfile_readall(ff);
431
+ if(!ff) return;
432
433
- unsigned long i, lines = procfile_lines(ff);
433
+ unsigned long i, lines = procfile_lines(ff);
434
435
- if(lines < 1) {
436
- error("File '%s' should have 1+ lines.", mem->filename);
437
- return;
438
- }
435
+ if(lines < 1) {
436
+ error("File '%s' should have 1+ lines.", mem->filename);
437
+ return;
438
+ }
439
440
- for(i = 0; i < lines ; i++) {
441
- char *s = procfile_lineword(ff, i, 0);
442
- uint32_t hash = simple_hash(s);
440
+ for(i = 0; i < lines ; i++) {
441
+ char *s = procfile_lineword(ff, i, 0);
442
+ uint32_t hash = simple_hash(s);
443
444
- if(hash == cache_hash && !strcmp(s, "cache"))
445
- mem->cache = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
444
+ if(hash == cache_hash && !strcmp(s, "cache"))
445
+ mem->cache = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
446
447
- else if(hash == rss_hash && !strcmp(s, "rss"))
448
- mem->rss = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
447
+ else if(hash == rss_hash && !strcmp(s, "rss"))
448
+ mem->rss = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
449
450
- else if(hash == rss_huge_hash && !strcmp(s, "rss_huge"))
451
- mem->rss_huge = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
450
+ else if(hash == rss_huge_hash && !strcmp(s, "rss_huge"))
451
+ mem->rss_huge = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
452
453
- else if(hash == mapped_file_hash && !strcmp(s, "mapped_file"))
454
- mem->mapped_file = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
453
+ else if(hash == mapped_file_hash && !strcmp(s, "mapped_file"))
454
+ mem->mapped_file = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
455
456
- else if(hash == writeback_hash && !strcmp(s, "writeback"))
457
- mem->writeback = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
456
+ else if(hash == writeback_hash && !strcmp(s, "writeback"))
457
+ mem->writeback = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
458
459
- else if(hash == dirty_hash && !strcmp(s, "dirty")) {
460
- mem->dirty = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
461
- mem->has_dirty_swap = 1;
462
- }
459
+ else if(hash == dirty_hash && !strcmp(s, "dirty")) {
460
+ mem->dirty = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
461
+ mem->has_dirty_swap = 1;
462
+ }
463
464
- else if(hash == swap_hash && !strcmp(s, "swap")) {
465
- mem->swap = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
466
- mem->has_dirty_swap = 1;
467
- }
464
+ else if(hash == swap_hash && !strcmp(s, "swap")) {
465
+ mem->swap = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
466
+ mem->has_dirty_swap = 1;
467
+ }
468
469
- else if(hash == pgpgin_hash && !strcmp(s, "pgpgin"))
470
- mem->pgpgin = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
469
+ else if(hash == pgpgin_hash && !strcmp(s, "pgpgin"))
470
+ mem->pgpgin = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
471
472
- else if(hash == pgpgout_hash && !strcmp(s, "pgpgout"))
473
- mem->pgpgout = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
472
+ else if(hash == pgpgout_hash && !strcmp(s, "pgpgout"))
473
+ mem->pgpgout = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
474
475
- else if(hash == pgfault_hash && !strcmp(s, "pgfault"))
476
- mem->pgfault = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
475
+ else if(hash == pgfault_hash && !strcmp(s, "pgfault"))
476
+ mem->pgfault = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
477
478
- else if(hash == pgmajfault_hash && !strcmp(s, "pgmajfault"))
479
- mem->pgmajfault = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
478
+ else if(hash == pgmajfault_hash && !strcmp(s, "pgmajfault"))
479
+ mem->pgmajfault = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
480
481
/*
482
- else if(hash == inactive_anon_hash && !strcmp(s, "inactive_anon"))
483
- mem->inactive_anon = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
482
+ else if(hash == inactive_anon_hash && !strcmp(s, "inactive_anon"))
483
+ mem->inactive_anon = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
484
485
- else if(hash == active_anon_hash && !strcmp(s, "active_anon"))
486
- mem->active_anon = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
485
+ else if(hash == active_anon_hash && !strcmp(s, "active_anon"))
486
+ mem->active_anon = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
487
488
- else if(hash == inactive_file_hash && !strcmp(s, "inactive_file"))
489
- mem->inactive_file = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
488
+ else if(hash == inactive_file_hash && !strcmp(s, "inactive_file"))
489
+ mem->inactive_file = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
490
491
- else if(hash == active_file_hash && !strcmp(s, "active_file"))
492
- mem->active_file = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
491
+ else if(hash == active_file_hash && !strcmp(s, "active_file"))
492
+ mem->active_file = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
493
494
- else if(hash == unevictable_hash && !strcmp(s, "unevictable"))
495
- mem->unevictable = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
494
+ else if(hash == unevictable_hash && !strcmp(s, "unevictable"))
495
+ mem->unevictable = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
496
497
- else if(hash == hierarchical_memory_limit_hash && !strcmp(s, "hierarchical_memory_limit"))
498
- mem->hierarchical_memory_limit = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
497
+ else if(hash == hierarchical_memory_limit_hash && !strcmp(s, "hierarchical_memory_limit"))
498
+ mem->hierarchical_memory_limit = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
499
500
- else if(hash == total_cache_hash && !strcmp(s, "total_cache"))
501
- mem->total_cache = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
500
+ else if(hash == total_cache_hash && !strcmp(s, "total_cache"))
501
+ mem->total_cache = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
502
503
- else if(hash == total_rss_hash && !strcmp(s, "total_rss"))
504
- mem->total_rss = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
503
+ else if(hash == total_rss_hash && !strcmp(s, "total_rss"))
504
+ mem->total_rss = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
505
506
- else if(hash == total_rss_huge_hash && !strcmp(s, "total_rss_huge"))
507
- mem->total_rss_huge = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
506
+ else if(hash == total_rss_huge_hash && !strcmp(s, "total_rss_huge"))
507
+ mem->total_rss_huge = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
508
509
- else if(hash == total_mapped_file_hash && !strcmp(s, "total_mapped_file"))
510
- mem->total_mapped_file = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
509
+ else if(hash == total_mapped_file_hash && !strcmp(s, "total_mapped_file"))
510
+ mem->total_mapped_file = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
511
512
- else if(hash == total_writeback_hash && !strcmp(s, "total_writeback"))
513
- mem->total_writeback = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
512
+ else if(hash == total_writeback_hash && !strcmp(s, "total_writeback"))
513
+ mem->total_writeback = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
514
515
- else if(hash == total_dirty_hash && !strcmp(s, "total_dirty"))
516
- mem->total_dirty = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
515
+ else if(hash == total_dirty_hash && !strcmp(s, "total_dirty"))
516
+ mem->total_dirty = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
517
518
- else if(hash == total_swap_hash && !strcmp(s, "total_swap"))
519
- mem->total_swap = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
518
+ else if(hash == total_swap_hash && !strcmp(s, "total_swap"))
519
+ mem->total_swap = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
520
521
- else if(hash == total_pgpgin_hash && !strcmp(s, "total_pgpgin"))
522
- mem->total_pgpgin = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
521
+ else if(hash == total_pgpgin_hash && !strcmp(s, "total_pgpgin"))
522
+ mem->total_pgpgin = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
523
524
- else if(hash == total_pgpgout_hash && !strcmp(s, "total_pgpgout"))
525
- mem->total_pgpgout = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
524
+ else if(hash == total_pgpgout_hash && !strcmp(s, "total_pgpgout"))
525
+ mem->total_pgpgout = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
526
527
- else if(hash == total_pgfault_hash && !strcmp(s, "total_pgfault"))
528
- mem->total_pgfault = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
527
+ else if(hash == total_pgfault_hash && !strcmp(s, "total_pgfault"))
528
+ mem->total_pgfault = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
529
530
- else if(hash == total_pgmajfault_hash && !strcmp(s, "total_pgmajfault"))
531
- mem->total_pgmajfault = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
530
+ else if(hash == total_pgmajfault_hash && !strcmp(s, "total_pgmajfault"))
531
+ mem->total_pgmajfault = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
532
533
- else if(hash == total_inactive_anon_hash && !strcmp(s, "total_inactive_anon"))
534
- mem->total_inactive_anon = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
533
+ else if(hash == total_inactive_anon_hash && !strcmp(s, "total_inactive_anon"))
534
+ mem->total_inactive_anon = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
535
536
- else if(hash == total_active_anon_hash && !strcmp(s, "total_active_anon"))
537
- mem->total_active_anon = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
536
+ else if(hash == total_active_anon_hash && !strcmp(s, "total_active_anon"))
537
+ mem->total_active_anon = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
538
539
- else if(hash == total_inactive_file_hash && !strcmp(s, "total_inactive_file"))
540
- mem->total_inactive_file = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
539
+ else if(hash == total_inactive_file_hash && !strcmp(s, "total_inactive_file"))
540
+ mem->total_inactive_file = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
541
542
- else if(hash == total_active_file_hash && !strcmp(s, "total_active_file"))
543
- mem->total_active_file = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
542
+ else if(hash == total_active_file_hash && !strcmp(s, "total_active_file"))
543
+ mem->total_active_file = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
544
545
- else if(hash == total_unevictable_hash && !strcmp(s, "total_unevictable"))
546
- mem->total_unevictable = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
545
+ else if(hash == total_unevictable_hash && !strcmp(s, "total_unevictable"))
546
+ mem->total_unevictable = strtoull(procfile_lineword(ff, i, 1), NULL, 10);
547
*/
548
- }
548
+ }
549
550
- // fprintf(stderr, "READ: '%s', cache: %llu, rss: %llu, rss_huge: %llu, mapped_file: %llu, writeback: %llu, dirty: %llu, swap: %llu, pgpgin: %llu, pgpgout: %llu, pgfault: %llu, pgmajfault: %llu, inactive_anon: %llu, active_anon: %llu, inactive_file: %llu, active_file: %llu, unevictable: %llu, hierarchical_memory_limit: %llu, total_cache: %llu, total_rss: %llu, total_rss_huge: %llu, total_mapped_file: %llu, total_writeback: %llu, total_dirty: %llu, total_swap: %llu, total_pgpgin: %llu, total_pgpgout: %llu, total_pgfault: %llu, total_pgmajfault: %llu, total_inactive_anon: %llu, total_active_anon: %llu, total_inactive_file: %llu, total_active_file: %llu, total_unevictable: %llu\n", mem->filename, mem->cache, mem->rss, mem->rss_huge, mem->mapped_file, mem->writeback, mem->dirty, mem->swap, mem->pgpgin, mem->pgpgout, mem->pgfault, mem->pgmajfault, mem->inactive_anon, mem->active_anon, mem->inactive_file, mem->active_file, mem->unevictable, mem->hierarchical_memory_limit, mem->total_cache, mem->total_rss, mem->total_rss_huge, mem->total_mapped_file, mem->total_writeback, mem->total_dirty, mem->total_swap, mem->total_pgpgin, mem->total_pgpgout, mem->total_pgfault, mem->total_pgmajfault, mem->total_inactive_anon, mem->total_active_anon, mem->total_inactive_file, mem->total_active_file, mem->total_unevictable);
550
+ // fprintf(stderr, "READ: '%s', cache: %llu, rss: %llu, rss_huge: %llu, mapped_file: %llu, writeback: %llu, dirty: %llu, swap: %llu, pgpgin: %llu, pgpgout: %llu, pgfault: %llu, pgmajfault: %llu, inactive_anon: %llu, active_anon: %llu, inactive_file: %llu, active_file: %llu, unevictable: %llu, hierarchical_memory_limit: %llu, total_cache: %llu, total_rss: %llu, total_rss_huge: %llu, total_mapped_file: %llu, total_writeback: %llu, total_dirty: %llu, total_swap: %llu, total_pgpgin: %llu, total_pgpgout: %llu, total_pgfault: %llu, total_pgmajfault: %llu, total_inactive_anon: %llu, total_active_anon: %llu, total_inactive_file: %llu, total_active_file: %llu, total_unevictable: %llu\n", mem->filename, mem->cache, mem->rss, mem->rss_huge, mem->mapped_file, mem->writeback, mem->dirty, mem->swap, mem->pgpgin, mem->pgpgout, mem->pgfault, mem->pgmajfault, mem->inactive_anon, mem->active_anon, mem->inactive_file, mem->active_file, mem->unevictable, mem->hierarchical_memory_limit, mem->total_cache, mem->total_rss, mem->total_rss_huge, mem->total_mapped_file, mem->total_writeback, mem->total_dirty, mem->total_swap, mem->total_pgpgin, mem->total_pgpgout, mem->total_pgfault, mem->total_pgmajfault, mem->total_inactive_anon, mem->total_active_anon, mem->total_inactive_file, mem->total_active_file, mem->total_unevictable);
551
552
- mem->updated = 1;
553
- }
552
+ mem->updated = 1;
553
+ }
554
}
555
556
void cgroup_read(struct cgroup *cg) {
557
- debug(D_CGROUP, "reading metrics for cgroups '%s'", cg->id);
558
-
559
- cgroup_read_cpuacct_stat(&cg->cpuacct_stat);
560
- cgroup_read_cpuacct_usage(&cg->cpuacct_usage);
561
- cgroup_read_memory(&cg->memory);
562
- cgroup_read_blkio(&cg->io_service_bytes);
563
- cgroup_read_blkio(&cg->io_serviced);
564
- cgroup_read_blkio(&cg->throttle_io_service_bytes);
565
- cgroup_read_blkio(&cg->throttle_io_serviced);
566
- cgroup_read_blkio(&cg->io_merged);
567
- cgroup_read_blkio(&cg->io_queued);
557
+ debug(D_CGROUP, "reading metrics for cgroups '%s'", cg->id);
558
+
559
+ cgroup_read_cpuacct_stat(&cg->cpuacct_stat);
560
+ cgroup_read_cpuacct_usage(&cg->cpuacct_usage);
561
+ cgroup_read_memory(&cg->memory);
562
+ cgroup_read_blkio(&cg->io_service_bytes);
563
+ cgroup_read_blkio(&cg->io_serviced);
564
+ cgroup_read_blkio(&cg->throttle_io_service_bytes);
565
+ cgroup_read_blkio(&cg->throttle_io_serviced);
566
+ cgroup_read_blkio(&cg->io_merged);
567
+ cgroup_read_blkio(&cg->io_queued);
568
}
569
570
void read_all_cgroups(struct cgroup *root) {
571
- debug(D_CGROUP, "reading metrics for all cgroups");
571
+ debug(D_CGROUP, "reading metrics for all cgroups");
572
573
- struct cgroup *cg;
573
+ struct cgroup *cg;
574
575
- for(cg = root; cg ; cg = cg->next)
576
- if(cg->enabled && cg->available)
577
- cgroup_read(cg);
575
+ for(cg = root; cg ; cg = cg->next)
576
+ if(cg->enabled && cg->available)
577
+ cgroup_read(cg);
578
}
579
580
// ----------------------------------------------------------------------------
@@ -583,167 +583,167 @@ void read_all_cgroups(struct cgroup *root) {
583
#define CGROUP_CHARTID_LINE_MAX 1024
584
585
void cgroup_get_chart_id(struct cgroup *cg) {
586
- debug(D_CGROUP, "getting the name of cgroup '%s'", cg->id);
586
+ debug(D_CGROUP, "getting the name of cgroup '%s'", cg->id);
587
588
- pid_t cgroup_pid;
589
- char buffer[CGROUP_CHARTID_LINE_MAX + 1];
588
+ pid_t cgroup_pid;
589
+ char buffer[CGROUP_CHARTID_LINE_MAX + 1];
590
591
- snprintfz(buffer, CGROUP_CHARTID_LINE_MAX, "exec %s '%s'",
592
- config_get("plugin:cgroups", "script to get cgroup names", PLUGINS_DIR "/cgroup-name.sh"), cg->chart_id);
591
+ snprintfz(buffer, CGROUP_CHARTID_LINE_MAX, "exec %s '%s'",
592
+ config_get("plugin:cgroups", "script to get cgroup names", PLUGINS_DIR "/cgroup-name.sh"), cg->chart_id);
593
594
- debug(D_CGROUP, "executing command '%s' for cgroup '%s'", buffer, cg->id);
595
- FILE *fp = mypopen(buffer, &cgroup_pid);
596
- if(!fp) {
597
- error("CGROUP: Cannot popen(\"%s\", \"r\").", buffer);
598
- return;
599
- }
600
- debug(D_CGROUP, "reading from command '%s' for cgroup '%s'", buffer, cg->id);
601
- char *s = fgets(buffer, CGROUP_CHARTID_LINE_MAX, fp);
602
- debug(D_CGROUP, "closing command for cgroup '%s'", cg->id);
603
- mypclose(fp, cgroup_pid);
604
- debug(D_CGROUP, "closed command for cgroup '%s'", cg->id);
594
+ debug(D_CGROUP, "executing command '%s' for cgroup '%s'", buffer, cg->id);
595
+ FILE *fp = mypopen(buffer, &cgroup_pid);
596
+ if(!fp) {
597
+ error("CGROUP: Cannot popen(\"%s\", \"r\").", buffer);
598
+ return;
599
+ }
600
+ debug(D_CGROUP, "reading from command '%s' for cgroup '%s'", buffer, cg->id);
601
+ char *s = fgets(buffer, CGROUP_CHARTID_LINE_MAX, fp);
602
+ debug(D_CGROUP, "closing command for cgroup '%s'", cg->id);
603
+ mypclose(fp, cgroup_pid);
604
+ debug(D_CGROUP, "closed command for cgroup '%s'", cg->id);
605
606
- if(s && *s && *s != '\n') {
607
- debug(D_CGROUP, "cgroup '%s' should be renamed to '%s'", cg->id, s);
606
+ if(s && *s && *s != '\n') {
607
+ debug(D_CGROUP, "cgroup '%s' should be renamed to '%s'", cg->id, s);
608
609
- trim(s);
609
+ trim(s);
610
611
- freez(cg->chart_title);
612
- cg->chart_title = strdupz(s);
613
- netdata_fix_chart_name(cg->chart_title);
611
+ freez(cg->chart_title);
612
+ cg->chart_title = strdupz(s);
613
+ netdata_fix_chart_name(cg->chart_title);
614
615
- freez(cg->chart_id);
616
- cg->chart_id = strdupz(s);
615
+ freez(cg->chart_id);
616
+ cg->chart_id = strdupz(s);
617
618
- netdata_fix_chart_id(cg->chart_id);
618
+ netdata_fix_chart_id(cg->chart_id);
619
620
- debug(D_CGROUP, "cgroup '%s' renamed to '%s' (title: '%s')", cg->id, cg->chart_id, cg->chart_title);
621
- }
622
- else debug(D_CGROUP, "cgroup '%s' is not to be renamed (will be shown as '%s')", cg->id, cg->chart_id);
620
+ debug(D_CGROUP, "cgroup '%s' renamed to '%s' (title: '%s')", cg->id, cg->chart_id, cg->chart_title);
621
+ }
622
+ else debug(D_CGROUP, "cgroup '%s' is not to be renamed (will be shown as '%s')", cg->id, cg->chart_id);
623
}
624
625
struct cgroup *cgroup_add(const char *id) {
626
- debug(D_CGROUP, "adding cgroup '%s'", id);
627
-
628
- if(cgroup_root_count >= cgroup_root_max) {
629
- info("Maximum number of cgroups reached (%d). Not adding cgroup '%s'", cgroup_root_count, id);
630
- return NULL;
631
- }
632
-
633
- int def = cgroup_enable_new_cgroups_detected_at_runtime;
634
- const char *chart_id = id;
635
- if(!*chart_id) {
636
- chart_id = "/";
637
-
638
- // disable by default the root cgroup
639
- def = 0;
640
- debug(D_CGROUP, "cgroup '%s' is the root container (by default %s)", id, (def)?"enabled":"disabled");
641
- }
642
- else {
643
- if(*chart_id == '/') chart_id++;
644
-
645
- size_t len = strlen(chart_id);
646
-
647
- // disable by default the parent cgroup
648
- // for known cgroup managers
649
- if(!strcmp(chart_id, "lxc") ||
650
- !strcmp(chart_id, "docker") ||
651
- !strcmp(chart_id, "libvirt") ||
652
- !strcmp(chart_id, "qemu") ||
653
- !strcmp(chart_id, "systemd") ||
654
- !strcmp(chart_id, "system.slice") ||
655
- !strcmp(chart_id, "machine.slice") ||
656
- !strcmp(chart_id, "init.scope") ||
657
- !strcmp(chart_id, "user") ||
658
- !strcmp(chart_id, "system") ||
659
- !strcmp(chart_id, "machine") ||
660
- // starts with them
661
- (len > 6 && !strncmp(chart_id, "user/", 6)) ||
662
- (len > 11 && !strncmp(chart_id, "user.slice/", 11)) ||
663
- // ends with them
664
- (len > 5 && !strncmp(&chart_id[len - 5], ".user", 5)) ||
665
- (len > 5 && !strncmp(&chart_id[len - 5], ".swap", 5)) ||
666
- (len > 6 && !strncmp(&chart_id[len - 6], ".slice", 6)) ||
667
- (len > 6 && !strncmp(&chart_id[len - 6], ".mount", 6)) ||
668
- (len > 8 && !strncmp(&chart_id[len - 8], ".session", 8)) ||
669
- (len > 8 && !strncmp(&chart_id[len - 8], ".service", 8)) ||
670
- (len > 10 && !strncmp(&chart_id[len - 10], ".partition", 10))
671
- ) {
672
- def = 0;
673
- debug(D_CGROUP, "cgroup '%s' is %s (by default)", id, (def)?"enabled":"disabled");
674
- }
675
- }
676
-
677
- struct cgroup *cg = callocz(1, sizeof(struct cgroup));
678
-
679
- debug(D_CGROUP, "adding cgroup '%s'", id);
680
-
681
- cg->id = strdupz(id);
682
- cg->hash = simple_hash(cg->id);
683
-
684
- cg->chart_id = strdupz(chart_id);
685
- cg->chart_title = strdupz(chart_id);
686
-
687
- if(!cgroup_root)
688
- cgroup_root = cg;
689
- else {
690
- // append it
691
- struct cgroup *e;
692
- for(e = cgroup_root; e->next ;e = e->next) ;
693
- e->next = cg;
694
- }
695
-
696
- cgroup_root_count++;
697
-
698
- // fix the name by calling the external script
699
- cgroup_get_chart_id(cg);
700
-
701
- char option[FILENAME_MAX + 1];
702
- snprintfz(option, FILENAME_MAX, "enable cgroup %s", cg->chart_title);
703
- cg->enabled = config_get_boolean("plugin:cgroups", option, def);
704
-
705
- debug(D_CGROUP, "Added cgroup '%s' with chart id '%s' and title '%s' as %s (default was %s)", cg->id, cg->chart_id, cg->chart_title, (cg->enabled)?"enabled":"disabled", (def)?"enabled":"disabled");
706
-
707
- return cg;
626
+ debug(D_CGROUP, "adding cgroup '%s'", id);
627
+
628
+ if(cgroup_root_count >= cgroup_root_max) {
629
+ info("Maximum number of cgroups reached (%d). Not adding cgroup '%s'", cgroup_root_count, id);
630
+ return NULL;
631
+ }
632
+
633
+ int def = cgroup_enable_new_cgroups_detected_at_runtime;
634
+ const char *chart_id = id;
635
+ if(!*chart_id) {
636
+ chart_id = "/";
637
+
638
+ // disable by default the root cgroup
639
+ def = 0;
640
+ debug(D_CGROUP, "cgroup '%s' is the root container (by default %s)", id, (def)?"enabled":"disabled");
641
+ }
642
+ else {
643
+ if(*chart_id == '/') chart_id++;
644
+
645
+ size_t len = strlen(chart_id);
646
+
647
+ // disable by default the parent cgroup
648
+ // for known cgroup managers
649
+ if(!strcmp(chart_id, "lxc") ||
650
+ !strcmp(chart_id, "docker") ||
651
+ !strcmp(chart_id, "libvirt") ||
652
+ !strcmp(chart_id, "qemu") ||
653
+ !strcmp(chart_id, "systemd") ||
654
+ !strcmp(chart_id, "system.slice") ||
655
+ !strcmp(chart_id, "machine.slice") ||
656
+ !strcmp(chart_id, "init.scope") ||
657
+ !strcmp(chart_id, "user") ||
658
+ !strcmp(chart_id, "system") ||
659
+ !strcmp(chart_id, "machine") ||
660
+ // starts with them
661
+ (len > 6 && !strncmp(chart_id, "user/", 6)) ||
662
+ (len > 11 && !strncmp(chart_id, "user.slice/", 11)) ||
663
+ // ends with them
664
+ (len > 5 && !strncmp(&chart_id[len - 5], ".user", 5)) ||
665
+ (len > 5 && !strncmp(&chart_id[len - 5], ".swap", 5)) ||
666
+ (len > 6 && !strncmp(&chart_id[len - 6], ".slice", 6)) ||
667
+ (len > 6 && !strncmp(&chart_id[len - 6], ".mount", 6)) ||
668
+ (len > 8 && !strncmp(&chart_id[len - 8], ".session", 8)) ||
669
+ (len > 8 && !strncmp(&chart_id[len - 8], ".service", 8)) ||
670
+ (len > 10 && !strncmp(&chart_id[len - 10], ".partition", 10))
671
+ ) {
672
+ def = 0;
673
+ debug(D_CGROUP, "cgroup '%s' is %s (by default)", id, (def)?"enabled":"disabled");
674
+ }
675
+ }
676
+
677
+ struct cgroup *cg = callocz(1, sizeof(struct cgroup));
678
+
679
+ debug(D_CGROUP, "adding cgroup '%s'", id);
680
+
681
+ cg->id = strdupz(id);
682
+ cg->hash = simple_hash(cg->id);
683
+
684
+ cg->chart_id = strdupz(chart_id);
685
+ cg->chart_title = strdupz(chart_id);
686
+
687
+ if(!cgroup_root)
688
+ cgroup_root = cg;
689
+ else {
690
+ // append it
691
+ struct cgroup *e;
692
+ for(e = cgroup_root; e->next ;e = e->next) ;
693
+ e->next = cg;
694
+ }
695
+
696
+ cgroup_root_count++;
697
+
698
+ // fix the name by calling the external script
699
+ cgroup_get_chart_id(cg);
700
+
701
+ char option[FILENAME_MAX + 1];
702
+ snprintfz(option, FILENAME_MAX, "enable cgroup %s", cg->chart_title);
703
+ cg->enabled = config_get_boolean("plugin:cgroups", option, def);
704
+
705
+ debug(D_CGROUP, "Added cgroup '%s' with chart id '%s' and title '%s' as %s (default was %s)", cg->id, cg->chart_id, cg->chart_title, (cg->enabled)?"enabled":"disabled", (def)?"enabled":"disabled");
706
+
707
+ return cg;
708
}
709
710
void cgroup_free(struct cgroup *cg) {
711
- debug(D_CGROUP, "Removing cgroup '%s' with chart id '%s' (was %s and %s)", cg->id, cg->chart_id, (cg->enabled)?"enabled":"disabled", (cg->available)?"available":"not available");
712
-
713
- freez(cg->cpuacct_usage.cpu_percpu);
714
-
715
- freez(cg->cpuacct_stat.filename);
716
- freez(cg->cpuacct_usage.filename);
717
- freez(cg->memory.filename);
718
- freez(cg->io_service_bytes.filename);
719
- freez(cg->io_serviced.filename);
720
- freez(cg->throttle_io_service_bytes.filename);
721
- freez(cg->throttle_io_serviced.filename);
722
- freez(cg->io_merged.filename);
723
- freez(cg->io_queued.filename);
724
-
725
- freez(cg->id);
726
- freez(cg->chart_id);
727
- freez(cg->chart_title);
728
- freez(cg);
729
-
730
- cgroup_root_count--;
711
+ debug(D_CGROUP, "Removing cgroup '%s' with chart id '%s' (was %s and %s)", cg->id, cg->chart_id, (cg->enabled)?"enabled":"disabled", (cg->available)?"available":"not available");
712
+
713
+ freez(cg->cpuacct_usage.cpu_percpu);
714
+
715
+ freez(cg->cpuacct_stat.filename);
716
+ freez(cg->cpuacct_usage.filename);
717
+ freez(cg->memory.filename);
718
+ freez(cg->io_service_bytes.filename);
719
+ freez(cg->io_serviced.filename);
720
+ freez(cg->throttle_io_service_bytes.filename);
721
+ freez(cg->throttle_io_serviced.filename);
722
+ freez(cg->io_merged.filename);
723
+ freez(cg->io_queued.filename);
724
+
725
+ freez(cg->id);
726
+ freez(cg->chart_id);
727
+ freez(cg->chart_title);
728
+ freez(cg);
729
+
730
+ cgroup_root_count--;
731
}
732
733
// find if a given cgroup exists
734
struct cgroup *cgroup_find(const char *id) {
735
- debug(D_CGROUP, "searching for cgroup '%s'", id);
735
+ debug(D_CGROUP, "searching for cgroup '%s'", id);
736
737
- uint32_t hash = simple_hash(id);
737
+ uint32_t hash = simple_hash(id);
738
739
- struct cgroup *cg;
740
- for(cg = cgroup_root; cg ; cg = cg->next) {
741
- if(hash == cg->hash && strcmp(id, cg->id) == 0)
742
- break;
743
- }
739
+ struct cgroup *cg;
740
+ for(cg = cgroup_root; cg ; cg = cg->next) {
741
+ if(hash == cg->hash && strcmp(id, cg->id) == 0)
742
+ break;
743
+ }
744
745
- debug(D_CGROUP, "cgroup_find('%s') %s", id, (cg)?"found":"not found");
746
- return cg;
745
+ debug(D_CGROUP, "cgroup_find('%s') %s", id, (cg)?"found":"not found");
746
+ return cg;
747
}
748
749
// ----------------------------------------------------------------------------
@@ -751,232 +751,232 @@ struct cgroup *cgroup_find(const char *id) {
751
752
// callback for find_file_in_subdirs()
753
void found_subdir_in_dir(const char *dir) {
754
- debug(D_CGROUP, "examining cgroup dir '%s'", dir);
755
-
756
- struct cgroup *cg = cgroup_find(dir);
757
- if(!cg) {
758
- if(*dir && cgroup_max_depth > 0) {
759
- int depth = 0;
760
- const char *s;
761
-
762
- for(s = dir; *s ;s++)
763
- if(unlikely(*s == '/'))
764
- depth++;
765
-
766
- if(depth > cgroup_max_depth) {
767
- info("cgroup '%s' is too deep (%d, while max is %d)", dir, depth, cgroup_max_depth);
768
- return;
769
- }
770
- }
771
- debug(D_CGROUP, "will add dir '%s' as cgroup", dir);
772
- cg = cgroup_add(dir);
773
- }
774
-
775
- if(cg) cg->available = 1;
754
+ debug(D_CGROUP, "examining cgroup dir '%s'", dir);
755
+
756
+ struct cgroup *cg = cgroup_find(dir);
757
+ if(!cg) {
758
+ if(*dir && cgroup_max_depth > 0) {
759
+ int depth = 0;
760
+ const char *s;
761
+
762
+ for(s = dir; *s ;s++)
763
+ if(unlikely(*s == '/'))
764
+ depth++;
765
+
766
+ if(depth > cgroup_max_depth) {
767
+ info("cgroup '%s' is too deep (%d, while max is %d)", dir, depth, cgroup_max_depth);
768
+ return;
769
+ }
770
+ }
771
+ debug(D_CGROUP, "will add dir '%s' as cgroup", dir);
772
+ cg = cgroup_add(dir);
773
+ }
774
+
775
+ if(cg) cg->available = 1;
776
}
777
778
void find_dir_in_subdirs(const char *base, const char *this, void (*callback)(const char *)) {
779
- debug(D_CGROUP, "searching for directories in '%s'", base);
780
-
781
- int enabled = -1;
782
- if(!this) this = base;
783
- size_t dirlen = strlen(this), baselen = strlen(base);
784
- const char *relative_path = &this[baselen];
785
-
786
- DIR *dir = opendir(this);
787
- if(!dir) {
788
- error("Cannot read cgroups directory '%s'", base);
789
- return;
790
- }
791
-
792
- callback(relative_path);
793
-
794
- struct dirent *de = NULL;
795
- while((de = readdir(dir))) {
796
- if(de->d_type == DT_DIR
797
- && (
798
- (de->d_name[0] == '.' && de->d_name[1] == '\0')
799
- || (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')
800
- ))
801
- continue;
802
-
803
- debug(D_CGROUP, "examining '%s/%s'", this, de->d_name);
804
-
805
- if(de->d_type == DT_DIR) {
806
- if(enabled == -1) {
807
- const char *r = relative_path;
808
- if(*r == '\0') r = "/";
809
- else if (*r == '/') r++;
810
-
811
- // we check for this option here
812
- // so that the config will not have settings
813
- // for leaf directories
814
- char option[FILENAME_MAX + 1];
815
- snprintfz(option, FILENAME_MAX, "search for cgroups under %s", r);
816
- option[FILENAME_MAX] = '\0';
817
- enabled = config_get_boolean("plugin:cgroups", option, 1);
818
- }
819
-
820
- if(enabled) {
821
- char *s = mallocz(dirlen + strlen(de->d_name) + 2);
779
+ debug(D_CGROUP, "searching for directories in '%s'", base);
780
+
781
+ int enabled = -1;
782
+ if(!this) this = base;
783
+ size_t dirlen = strlen(this), baselen = strlen(base);
784
+ const char *relative_path = &this[baselen];
785
+
786
+ DIR *dir = opendir(this);
787
+ if(!dir) {
788
+ error("Cannot read cgroups directory '%s'", base);
789
+ return;
790
+ }
791
+
792
+ callback(relative_path);
793
+
794
+ struct dirent *de = NULL;
795
+ while((de = readdir(dir))) {
796
+ if(de->d_type == DT_DIR
797
+ && (
798
+ (de->d_name[0] == '.' && de->d_name[1] == '\0')
799
+ || (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')
800
+ ))
801
+ continue;
802
+
803
+ debug(D_CGROUP, "examining '%s/%s'", this, de->d_name);
804
+
805
+ if(de->d_type == DT_DIR) {
806
+ if(enabled == -1) {
807
+ const char *r = relative_path;
808
+ if(*r == '\0') r = "/";
809
+ else if (*r == '/') r++;
810
+
811
+ // we check for this option here
812
+ // so that the config will not have settings
813
+ // for leaf directories
814
+ char option[FILENAME_MAX + 1];
815
+ snprintfz(option, FILENAME_MAX, "search for cgroups under %s", r);
816
+ option[FILENAME_MAX] = '\0';
817
+ enabled = config_get_boolean("plugin:cgroups", option, 1);
818
+ }
819
+
820
+ if(enabled) {
821
+ char *s = mallocz(dirlen + strlen(de->d_name) + 2);
822
strcpy(s, this);
823
strcat(s, "/");
824
strcat(s, de->d_name);
825
find_dir_in_subdirs(base, s, callback);
826
freez(s);
827
- }
828
- }
829
- }
827
+ }
828
+ }
829
+ }
830
831
- closedir(dir);
831
+ closedir(dir);
832
}
833
834
void mark_all_cgroups_as_not_available() {
835
- debug(D_CGROUP, "marking all cgroups as not available");
835
+ debug(D_CGROUP, "marking all cgroups as not available");
836
837
- struct cgroup *cg;
837
+ struct cgroup *cg;
838
839
- // mark all as not available
840
- for(cg = cgroup_root; cg ; cg = cg->next)
841
- cg->available = 0;
839
+ // mark all as not available
840
+ for(cg = cgroup_root; cg ; cg = cg->next)
841
+ cg->available = 0;
842
}
843
844
void cleanup_all_cgroups() {
845
- struct cgroup *cg = cgroup_root, *last = NULL;
846
-
847
- for(; cg ;) {
848
- if(!cg->available) {
849
-
850
- if(!last)
851
- cgroup_root = cg->next;
852
- else
853
- last->next = cg->next;
854
-
855
- cgroup_free(cg);
856
-
857
- if(!last)
858
- cg = cgroup_root;
859
- else
860
- cg = last->next;
861
- }
862
- else {
863
- last = cg;
864
- cg = cg->next;
865
- }
866
- }
845
+ struct cgroup *cg = cgroup_root, *last = NULL;
846
+
847
+ for(; cg ;) {
848
+ if(!cg->available) {
849
+
850
+ if(!last)
851
+ cgroup_root = cg->next;
852
+ else
853
+ last->next = cg->next;
854
+
855
+ cgroup_free(cg);
856
+
857
+ if(!last)
858
+ cg = cgroup_root;
859
+ else
860
+ cg = last->next;
861
+ }
862
+ else {
863
+ last = cg;
864
+ cg = cg->next;
865
+ }
866
+ }
867
}
868
869
void find_all_cgroups() {
870
- debug(D_CGROUP, "searching for cgroups");
871
-
872
- mark_all_cgroups_as_not_available();
873
-
874
- if(cgroup_enable_cpuacct_stat || cgroup_enable_cpuacct_usage)
875
- find_dir_in_subdirs(cgroup_cpuacct_base, NULL, found_subdir_in_dir);
876
-
877
- if(cgroup_enable_blkio)
878
- find_dir_in_subdirs(cgroup_blkio_base, NULL, found_subdir_in_dir);
879
-
880
- if(cgroup_enable_memory)
881
- find_dir_in_subdirs(cgroup_memory_base, NULL, found_subdir_in_dir);
882
-
883
- if(cgroup_enable_devices)
884
- find_dir_in_subdirs(cgroup_devices_base, NULL, found_subdir_in_dir);
885
-
886
- // remove any non-existing cgroups
887
- cleanup_all_cgroups();
888
-
889
- struct cgroup *cg;
890
- struct stat buf;
891
- for(cg = cgroup_root; cg ; cg = cg->next) {
892
- // fprintf(stderr, " >>> CGROUP '%s' (%u - %s) with name '%s'\n", cg->id, cg->hash, cg->available?"available":"stopped", cg->name);
893
-
894
- if(unlikely(!cg->available))
895
- continue;
896
-
897
- debug(D_CGROUP, "checking paths for cgroup '%s'", cg->id);
898
-
899
- // check for newly added cgroups
900
- // and update the filenames they read
901
- char filename[FILENAME_MAX + 1];
902
- if(cgroup_enable_cpuacct_stat && !cg->cpuacct_stat.filename) {
903
- snprintfz(filename, FILENAME_MAX, "%s%s/cpuacct.stat", cgroup_cpuacct_base, cg->id);
904
- if(stat(filename, &buf) != -1) {
905
- cg->cpuacct_stat.filename = strdupz(filename);
906
- debug(D_CGROUP, "cpuacct.stat filename for cgroup '%s': '%s'", cg->id, cg->cpuacct_stat.filename);
907
- }
908
- else debug(D_CGROUP, "cpuacct.stat file for cgroup '%s': '%s' does not exist.", cg->id, filename);
909
- }
910
- if(cgroup_enable_cpuacct_usage && !cg->cpuacct_usage.filename) {
911
- snprintfz(filename, FILENAME_MAX, "%s%s/cpuacct.usage_percpu", cgroup_cpuacct_base, cg->id);
912
- if(stat(filename, &buf) != -1) {
913
- cg->cpuacct_usage.filename = strdupz(filename);
914
- debug(D_CGROUP, "cpuacct.usage_percpu filename for cgroup '%s': '%s'", cg->id, cg->cpuacct_usage.filename);
915
- }
916
- else debug(D_CGROUP, "cpuacct.usage_percpu file for cgroup '%s': '%s' does not exist.", cg->id, filename);
917
- }
918
- if(cgroup_enable_memory && !cg->memory.filename) {
919
- snprintfz(filename, FILENAME_MAX, "%s%s/memory.stat", cgroup_memory_base, cg->id);
920
- if(stat(filename, &buf) != -1) {
921
- cg->memory.filename = strdupz(filename);
922
- debug(D_CGROUP, "memory.stat filename for cgroup '%s': '%s'", cg->id, cg->memory.filename);
923
- }
924
- else debug(D_CGROUP, "memory.stat file for cgroup '%s': '%s' does not exist.", cg->id, filename);
925
- }
926
- if(cgroup_enable_blkio) {
927
- if(!cg->io_service_bytes.filename) {
928
- snprintfz(filename, FILENAME_MAX, "%s%s/blkio.io_service_bytes", cgroup_blkio_base, cg->id);
929
- if(stat(filename, &buf) != -1) {
930
- cg->io_service_bytes.filename = strdupz(filename);
931
- debug(D_CGROUP, "io_service_bytes filename for cgroup '%s': '%s'", cg->id, cg->io_service_bytes.filename);
932
- }
933
- else debug(D_CGROUP, "io_service_bytes file for cgroup '%s': '%s' does not exist.", cg->id, filename);
934
- }
935
- if(!cg->io_serviced.filename) {
936
- snprintfz(filename, FILENAME_MAX, "%s%s/blkio.io_serviced", cgroup_blkio_base, cg->id);
937
- if(stat(filename, &buf) != -1) {
938
- cg->io_serviced.filename = strdupz(filename);
939
- debug(D_CGROUP, "io_serviced filename for cgroup '%s': '%s'", cg->id, cg->io_serviced.filename);
940
- }
941
- else debug(D_CGROUP, "io_serviced file for cgroup '%s': '%s' does not exist.", cg->id, filename);
942
- }
943
- if(!cg->throttle_io_service_bytes.filename) {
944
- snprintfz(filename, FILENAME_MAX, "%s%s/blkio.throttle.io_service_bytes", cgroup_blkio_base, cg->id);
945
- if(stat(filename, &buf) != -1) {
946
- cg->throttle_io_service_bytes.filename = strdupz(filename);
947
- debug(D_CGROUP, "throttle_io_service_bytes filename for cgroup '%s': '%s'", cg->id, cg->throttle_io_service_bytes.filename);
948
- }
949
- else debug(D_CGROUP, "throttle_io_service_bytes file for cgroup '%s': '%s' does not exist.", cg->id, filename);
950
- }
951
- if(!cg->throttle_io_serviced.filename) {
952
- snprintfz(filename, FILENAME_MAX, "%s%s/blkio.throttle.io_serviced", cgroup_blkio_base, cg->id);
953
- if(stat(filename, &buf) != -1) {
954
- cg->throttle_io_serviced.filename = strdupz(filename);
955
- debug(D_CGROUP, "throttle_io_serviced filename for cgroup '%s': '%s'", cg->id, cg->throttle_io_serviced.filename);
956
- }
957
- else debug(D_CGROUP, "throttle_io_serviced file for cgroup '%s': '%s' does not exist.", cg->id, filename);
958
- }
959
- if(!cg->io_merged.filename) {
960
- snprintfz(filename, FILENAME_MAX, "%s%s/blkio.io_merged", cgroup_blkio_base, cg->id);
961
- if(stat(filename, &buf) != -1) {
962
- cg->io_merged.filename = strdupz(filename);
963
- debug(D_CGROUP, "io_merged filename for cgroup '%s': '%s'", cg->id, cg->io_merged.filename);
964
- }
965
- else debug(D_CGROUP, "io_merged file for cgroup '%s': '%s' does not exist.", cg->id, filename);
966
- }
967
- if(!cg->io_queued.filename) {
968
- snprintfz(filename, FILENAME_MAX, "%s%s/blkio.io_queued", cgroup_blkio_base, cg->id);
969
- if(stat(filename, &buf) != -1) {
970
- cg->io_queued.filename = strdupz(filename);
971
- debug(D_CGROUP, "io_queued filename for cgroup '%s': '%s'", cg->id, cg->io_queued.filename);
972
- }
973
- else debug(D_CGROUP, "io_queued file for cgroup '%s': '%s' does not exist.", cg->id, filename);
974
- }
975
- }
976
- }
977
-
978
- debug(D_CGROUP, "done searching for cgroups");
979
- return;
870
+ debug(D_CGROUP, "searching for cgroups");
871
+
872
+ mark_all_cgroups_as_not_available();
873
+
874
+ if(cgroup_enable_cpuacct_stat || cgroup_enable_cpuacct_usage)
875
+ find_dir_in_subdirs(cgroup_cpuacct_base, NULL, found_subdir_in_dir);
876
+
877
+ if(cgroup_enable_blkio)
878
+ find_dir_in_subdirs(cgroup_blkio_base, NULL, found_subdir_in_dir);
879
+
880
+ if(cgroup_enable_memory)
881
+ find_dir_in_subdirs(cgroup_memory_base, NULL, found_subdir_in_dir);
882
+
883
+ if(cgroup_enable_devices)
884
+ find_dir_in_subdirs(cgroup_devices_base, NULL, found_subdir_in_dir);
885
+
886
+ // remove any non-existing cgroups
887
+ cleanup_all_cgroups();
888
+
889
+ struct cgroup *cg;
890
+ struct stat buf;
891
+ for(cg = cgroup_root; cg ; cg = cg->next) {
892
+ // fprintf(stderr, " >>> CGROUP '%s' (%u - %s) with name '%s'\n", cg->id, cg->hash, cg->available?"available":"stopped", cg->name);
893
+
894
+ if(unlikely(!cg->available))
895
+ continue;
896
+
897
+ debug(D_CGROUP, "checking paths for cgroup '%s'", cg->id);
898
+
899
+ // check for newly added cgroups
900
+ // and update the filenames they read
901
+ char filename[FILENAME_MAX + 1];
902
+ if(cgroup_enable_cpuacct_stat && !cg->cpuacct_stat.filename) {
903
+ snprintfz(filename, FILENAME_MAX, "%s%s/cpuacct.stat", cgroup_cpuacct_base, cg->id);
904
+ if(stat(filename, &buf) != -1) {
905
+ cg->cpuacct_stat.filename = strdupz(filename);
906
+ debug(D_CGROUP, "cpuacct.stat filename for cgroup '%s': '%s'", cg->id, cg->cpuacct_stat.filename);
907
+ }
908
+ else debug(D_CGROUP, "cpuacct.stat file for cgroup '%s': '%s' does not exist.", cg->id, filename);
909
+ }
910
+ if(cgroup_enable_cpuacct_usage && !cg->cpuacct_usage.filename) {
911
+ snprintfz(filename, FILENAME_MAX, "%s%s/cpuacct.usage_percpu", cgroup_cpuacct_base, cg->id);
912
+ if(stat(filename, &buf) != -1) {
913
+ cg->cpuacct_usage.filename = strdupz(filename);
914
+ debug(D_CGROUP, "cpuacct.usage_percpu filename for cgroup '%s': '%s'", cg->id, cg->cpuacct_usage.filename);
915
+ }
916
+ else debug(D_CGROUP, "cpuacct.usage_percpu file for cgroup '%s': '%s' does not exist.", cg->id, filename);
917
+ }
918
+ if(cgroup_enable_memory && !cg->memory.filename) {
919
+ snprintfz(filename, FILENAME_MAX, "%s%s/memory.stat", cgroup_memory_base, cg->id);
920
+ if(stat(filename, &buf) != -1) {
921
+ cg->memory.filename = strdupz(filename);
922
+ debug(D_CGROUP, "memory.stat filename for cgroup '%s': '%s'", cg->id, cg->memory.filename);
923
+ }
924
+ else debug(D_CGROUP, "memory.stat file for cgroup '%s': '%s' does not exist.", cg->id, filename);
925
+ }
926
+ if(cgroup_enable_blkio) {
927
+ if(!cg->io_service_bytes.filename) {
928
+ snprintfz(filename, FILENAME_MAX, "%s%s/blkio.io_service_bytes", cgroup_blkio_base, cg->id);
929
+ if(stat(filename, &buf) != -1) {
930
+ cg->io_service_bytes.filename = strdupz(filename);
931
+ debug(D_CGROUP, "io_service_bytes filename for cgroup '%s': '%s'", cg->id, cg->io_service_bytes.filename);
932
+ }
933
+ else debug(D_CGROUP, "io_service_bytes file for cgroup '%s': '%s' does not exist.", cg->id, filename);
934
+ }
935
+ if(!cg->io_serviced.filename) {
936
+ snprintfz(filename, FILENAME_MAX, "%s%s/blkio.io_serviced", cgroup_blkio_base, cg->id);
937
+ if(stat(filename, &buf) != -1) {
938
+ cg->io_serviced.filename = strdupz(filename);
939
+ debug(D_CGROUP, "io_serviced filename for cgroup '%s': '%s'", cg->id, cg->io_serviced.filename);
940
+ }
941
+ else debug(D_CGROUP, "io_serviced file for cgroup '%s': '%s' does not exist.", cg->id, filename);
942
+ }
943
+ if(!cg->throttle_io_service_bytes.filename) {
944
+ snprintfz(filename, FILENAME_MAX, "%s%s/blkio.throttle.io_service_bytes", cgroup_blkio_base, cg->id);
945
+ if(stat(filename, &buf) != -1) {
946
+ cg->throttle_io_service_bytes.filename = strdupz(filename);
947
+ debug(D_CGROUP, "throttle_io_service_bytes filename for cgroup '%s': '%s'", cg->id, cg->throttle_io_service_bytes.filename);
948
+ }
949
+ else debug(D_CGROUP, "throttle_io_service_bytes file for cgroup '%s': '%s' does not exist.", cg->id, filename);
950
+ }
951
+ if(!cg->throttle_io_serviced.filename) {
952
+ snprintfz(filename, FILENAME_MAX, "%s%s/blkio.throttle.io_serviced", cgroup_blkio_base, cg->id);
953
+ if(stat(filename, &buf) != -1) {
954
+ cg->throttle_io_serviced.filename = strdupz(filename);
955
+ debug(D_CGROUP, "throttle_io_serviced filename for cgroup '%s': '%s'", cg->id, cg->throttle_io_serviced.filename);
956
+ }
957
+ else debug(D_CGROUP, "throttle_io_serviced file for cgroup '%s': '%s' does not exist.", cg->id, filename);
958
+ }
959
+ if(!cg->io_merged.filename) {
960
+ snprintfz(filename, FILENAME_MAX, "%s%s/blkio.io_merged", cgroup_blkio_base, cg->id);
961
+ if(stat(filename, &buf) != -1) {
962
+ cg->io_merged.filename = strdupz(filename);
963
+ debug(D_CGROUP, "io_merged filename for cgroup '%s': '%s'", cg->id, cg->io_merged.filename);
964
+ }
965
+ else debug(D_CGROUP, "io_merged file for cgroup '%s': '%s' does not exist.", cg->id, filename);
966
+ }
967
+ if(!cg->io_queued.filename) {
968
+ snprintfz(filename, FILENAME_MAX, "%s%s/blkio.io_queued", cgroup_blkio_base, cg->id);
969
+ if(stat(filename, &buf) != -1) {
970
+ cg->io_queued.filename = strdupz(filename);
971
+ debug(D_CGROUP, "io_queued filename for cgroup '%s': '%s'", cg->id, cg->io_queued.filename);
972
+ }
973
+ else debug(D_CGROUP, "io_queued file for cgroup '%s': '%s' does not exist.", cg->id, filename);
974
+ }
975
+ }
976
+ }
977
+
978
+ debug(D_CGROUP, "done searching for cgroups");
979
+ return;
980
}
981
982
// ----------------------------------------------------------------------------
@@ -985,349 +985,349 @@ void find_all_cgroups() {
985
#define CHART_TITLE_MAX 300
986
987
void update_cgroup_charts(int update_every) {
988
- debug(D_CGROUP, "updating cgroups charts");
989
-
990
- char type[RRD_ID_LENGTH_MAX + 1];
991
- char title[CHART_TITLE_MAX + 1];
992
-
993
- struct cgroup *cg;
994
- RRDSET *st;
995
-
996
- for(cg = cgroup_root; cg ; cg = cg->next) {
997
- if(!cg->available || !cg->enabled)
998
- continue;
999
-
1000
- if(cg->id[0] == '\0')
1001
- strcpy(type, "cgroup_root");
1002
- else if(cg->id[0] == '/')
1003
- snprintfz(type, RRD_ID_LENGTH_MAX, "cgroup_%s", cg->chart_id);
1004
- else
1005
- snprintfz(type, RRD_ID_LENGTH_MAX, "cgroup_%s", cg->chart_id);
1006
-
1007
- netdata_fix_chart_id(type);
1008
-
1009
- if(cg->cpuacct_stat.updated) {
1010
- st = rrdset_find_bytype(type, "cpu");
1011
- if(!st) {
1012
- snprintfz(title, CHART_TITLE_MAX, "CPU Usage for cgroup %s", cg->chart_title);
1013
- st = rrdset_create(type, "cpu", NULL, "cpu", "cgroup.cpu", title, "%", 40000, update_every, RRDSET_TYPE_STACKED);
1014
-
1015
- rrddim_add(st, "user", NULL, 100, hz, RRDDIM_INCREMENTAL);
1016
- rrddim_add(st, "system", NULL, 100, hz, RRDDIM_INCREMENTAL);
1017
- }
1018
- else rrdset_next(st);
1019
-
1020
- rrddim_set(st, "user", cg->cpuacct_stat.user);
1021
- rrddim_set(st, "system", cg->cpuacct_stat.system);
1022
- rrdset_done(st);
1023
- }
1024
-
1025
- if(cg->cpuacct_usage.updated) {
1026
- char id[RRD_ID_LENGTH_MAX + 1];
1027
- unsigned int i;
1028
-
1029
- st = rrdset_find_bytype(type, "cpu_per_core");
1030
- if(!st) {
1031
- snprintfz(title, CHART_TITLE_MAX, "CPU Usage Per Core for cgroup %s", cg->chart_title);
1032
- st = rrdset_create(type, "cpu_per_core", NULL, "cpu", "cgroup.cpu_per_core", title, "%", 40100, update_every, RRDSET_TYPE_STACKED);
1033
-
1034
- for(i = 0; i < cg->cpuacct_usage.cpus ;i++) {
1035
- snprintfz(id, CHART_TITLE_MAX, "cpu%u", i);
1036
- rrddim_add(st, id, NULL, 100, 1000000000, RRDDIM_INCREMENTAL);
1037
- }
1038
- }
1039
- else rrdset_next(st);
1040
-
1041
- for(i = 0; i < cg->cpuacct_usage.cpus ;i++) {
1042
- snprintfz(id, CHART_TITLE_MAX, "cpu%u", i);
1043
- rrddim_set(st, id, cg->cpuacct_usage.cpu_percpu[i]);
1044
- }
1045
- rrdset_done(st);
1046
- }
1047
-
1048
- if(cg->memory.updated) {
1049
- if(cg->memory.cache + cg->memory.rss + cg->memory.rss_huge + cg->memory.mapped_file > 0) {
1050
- st = rrdset_find_bytype(type, "mem");
1051
- if(!st) {
1052
- snprintfz(title, CHART_TITLE_MAX, "Memory Usage for cgroup %s", cg->chart_title);
1053
- st = rrdset_create(type, "mem", NULL, "mem", "cgroup.mem", title, "MB", 40200, update_every,
1054
- RRDSET_TYPE_STACKED);
1055
-
1056
- rrddim_add(st, "cache", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
1057
- rrddim_add(st, "rss", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
1058
- if(cg->memory.has_dirty_swap)
1059
- rrddim_add(st, "swap", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
1060
- rrddim_add(st, "rss_huge", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
1061
- rrddim_add(st, "mapped_file", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
1062
- }
1063
- else rrdset_next(st);
1064
-
1065
- rrddim_set(st, "cache", cg->memory.cache);
1066
- rrddim_set(st, "rss", cg->memory.rss);
1067
- if(cg->memory.has_dirty_swap)
1068
- rrddim_set(st, "swap", cg->memory.swap);
1069
- rrddim_set(st, "rss_huge", cg->memory.rss_huge);
1070
- rrddim_set(st, "mapped_file", cg->memory.mapped_file);
1071
- rrdset_done(st);
1072
- }
1073
-
1074
- st = rrdset_find_bytype(type, "writeback");
1075
- if(!st) {
1076
- snprintfz(title, CHART_TITLE_MAX, "Writeback Memory for cgroup %s", cg->chart_title);
1077
- st = rrdset_create(type, "writeback", NULL, "mem", "cgroup.writeback", title, "MB", 40300,
1078
- update_every, RRDSET_TYPE_AREA);
1079
-
1080
- if(cg->memory.has_dirty_swap)
1081
- rrddim_add(st, "dirty", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
1082
- rrddim_add(st, "writeback", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
1083
- }
1084
- else rrdset_next(st);
1085
-
1086
- if(cg->memory.has_dirty_swap)
1087
- rrddim_set(st, "dirty", cg->memory.dirty);
1088
- rrddim_set(st, "writeback", cg->memory.writeback);
1089
- rrdset_done(st);
1090
-
1091
- if(cg->memory.pgpgin + cg->memory.pgpgout > 0) {
1092
- st = rrdset_find_bytype(type, "mem_activity");
1093
- if(!st) {
1094
- snprintfz(title, CHART_TITLE_MAX, "Memory Activity for cgroup %s", cg->chart_title);
1095
- st = rrdset_create(type, "mem_activity", NULL, "mem", "cgroup.mem_activity", title, "MB/s",
1096
- 40400, update_every, RRDSET_TYPE_LINE);
1097
-
1098
- rrddim_add(st, "pgpgin", "in", sysconf(_SC_PAGESIZE), 1024 * 1024, RRDDIM_INCREMENTAL);
1099
- rrddim_add(st, "pgpgout", "out", -sysconf(_SC_PAGESIZE), 1024 * 1024, RRDDIM_INCREMENTAL);
1100
- }
1101
- else rrdset_next(st);
1102
-
1103
- rrddim_set(st, "pgpgin", cg->memory.pgpgin);
1104
- rrddim_set(st, "pgpgout", cg->memory.pgpgout);
1105
- rrdset_done(st);
1106
- }
1107
-
1108
- if(cg->memory.pgfault + cg->memory.pgmajfault > 0) {
1109
- st = rrdset_find_bytype(type, "pgfaults");
1110
- if(!st) {
1111
- snprintfz(title, CHART_TITLE_MAX, "Memory Page Faults for cgroup %s", cg->chart_title);
1112
- st = rrdset_create(type, "pgfaults", NULL, "mem", "cgroup.pgfaults", title, "MB/s", 40500,
1113
- update_every, RRDSET_TYPE_LINE);
1114
-
1115
- rrddim_add(st, "pgfault", NULL, sysconf(_SC_PAGESIZE), 1024 * 1024, RRDDIM_INCREMENTAL);
1116
- rrddim_add(st, "pgmajfault", "swap", -sysconf(_SC_PAGESIZE), 1024 * 1024, RRDDIM_INCREMENTAL);
1117
- }
1118
- else rrdset_next(st);
1119
-
1120
- rrddim_set(st, "pgfault", cg->memory.pgfault);
1121
- rrddim_set(st, "pgmajfault", cg->memory.pgmajfault);
1122
- rrdset_done(st);
1123
- }
1124
- }
1125
-
1126
- if(cg->io_service_bytes.updated && cg->io_service_bytes.Read + cg->io_service_bytes.Write > 0) {
1127
- st = rrdset_find_bytype(type, "io");
1128
- if(!st) {
1129
- snprintfz(title, CHART_TITLE_MAX, "I/O Bandwidth (all disks) for cgroup %s", cg->chart_title);
1130
- st = rrdset_create(type, "io", NULL, "disk", "cgroup.io", title, "KB/s", 41200,
1131
- update_every, RRDSET_TYPE_LINE);
1132
-
1133
- rrddim_add(st, "read", NULL, 1, 1024, RRDDIM_INCREMENTAL);
1134
- rrddim_add(st, "write", NULL, -1, 1024, RRDDIM_INCREMENTAL);
1135
- }
1136
- else rrdset_next(st);
1137
-
1138
- rrddim_set(st, "read", cg->io_service_bytes.Read);
1139
- rrddim_set(st, "write", cg->io_service_bytes.Write);
1140
- rrdset_done(st);
1141
- }
1142
-
1143
- if(cg->io_serviced.updated && cg->io_serviced.Read + cg->io_serviced.Write > 0) {
1144
- st = rrdset_find_bytype(type, "serviced_ops");
1145
- if(!st) {
1146
- snprintfz(title, CHART_TITLE_MAX, "Serviced I/O Operations (all disks) for cgroup %s", cg->chart_title);
1147
- st = rrdset_create(type, "serviced_ops", NULL, "disk", "cgroup.serviced_ops", title, "operations/s", 41200,
1148
- update_every, RRDSET_TYPE_LINE);
1149
-
1150
- rrddim_add(st, "read", NULL, 1, 1, RRDDIM_INCREMENTAL);
1151
- rrddim_add(st, "write", NULL, -1, 1, RRDDIM_INCREMENTAL);
1152
- }
1153
- else rrdset_next(st);
1154
-
1155
- rrddim_set(st, "read", cg->io_serviced.Read);
1156
- rrddim_set(st, "write", cg->io_serviced.Write);
1157
- rrdset_done(st);
1158
- }
1159
-
1160
- if(cg->throttle_io_service_bytes.updated && cg->throttle_io_service_bytes.Read + cg->throttle_io_service_bytes.Write > 0) {
1161
- st = rrdset_find_bytype(type, "io");
1162
- if(!st) {
1163
- snprintfz(title, CHART_TITLE_MAX, "Throttle I/O Bandwidth (all disks) for cgroup %s", cg->chart_title);
1164
- st = rrdset_create(type, "io", NULL, "disk", "cgroup.io", title, "KB/s", 41200,
1165
- update_every, RRDSET_TYPE_LINE);
1166
-
1167
- rrddim_add(st, "read", NULL, 1, 1024, RRDDIM_INCREMENTAL);
1168
- rrddim_add(st, "write", NULL, -1, 1024, RRDDIM_INCREMENTAL);
1169
- }
1170
- else rrdset_next(st);
1171
-
1172
- rrddim_set(st, "read", cg->throttle_io_service_bytes.Read);
1173
- rrddim_set(st, "write", cg->throttle_io_service_bytes.Write);
1174
- rrdset_done(st);
1175
- }
1176
-
1177
-
1178
- if(cg->throttle_io_serviced.updated && cg->throttle_io_serviced.Read + cg->throttle_io_serviced.Write > 0) {
1179
- st = rrdset_find_bytype(type, "throttle_serviced_ops");
1180
- if(!st) {
1181
- snprintfz(title, CHART_TITLE_MAX, "Throttle Serviced I/O Operations (all disks) for cgroup %s", cg->chart_title);
1182
- st = rrdset_create(type, "throttle_serviced_ops", NULL, "disk", "cgroup.throttle_serviced_ops", title, "operations/s", 41200,
1183
- update_every, RRDSET_TYPE_LINE);
1184
-
1185
- rrddim_add(st, "read", NULL, 1, 1, RRDDIM_INCREMENTAL);
1186
- rrddim_add(st, "write", NULL, -1, 1, RRDDIM_INCREMENTAL);
1187
- }
1188
- else rrdset_next(st);
1189
-
1190
- rrddim_set(st, "read", cg->throttle_io_serviced.Read);
1191
- rrddim_set(st, "write", cg->throttle_io_serviced.Write);
1192
- rrdset_done(st);
1193
- }
1194
-
1195
- if(cg->io_queued.updated) {
1196
- st = rrdset_find_bytype(type, "queued_ops");
1197
- if(!st) {
1198
- snprintfz(title, CHART_TITLE_MAX, "Queued I/O Operations (all disks) for cgroup %s", cg->chart_title);
1199
- st = rrdset_create(type, "queued_ops", NULL, "disk", "cgroup.queued_ops", title, "operations", 42000,
1200
- update_every, RRDSET_TYPE_LINE);
1201
-
1202
- rrddim_add(st, "read", NULL, 1, 1, RRDDIM_ABSOLUTE);
1203
- rrddim_add(st, "write", NULL, -1, 1, RRDDIM_ABSOLUTE);
1204
- }
1205
- else rrdset_next(st);
1206
-
1207
- rrddim_set(st, "read", cg->io_queued.Read);
1208
- rrddim_set(st, "write", cg->io_queued.Write);
1209
- rrdset_done(st);
1210
- }
1211
-
1212
- if(cg->io_merged.updated && cg->io_merged.Read + cg->io_merged.Write > 0) {
1213
- st = rrdset_find_bytype(type, "merged_ops");
1214
- if(!st) {
1215
- snprintfz(title, CHART_TITLE_MAX, "Merged I/O Operations (all disks) for cgroup %s", cg->chart_title);
1216
- st = rrdset_create(type, "merged_ops", NULL, "disk", "cgroup.merged_ops", title, "operations/s", 42100,
1217
- update_every, RRDSET_TYPE_LINE);
1218
-
1219
- rrddim_add(st, "read", NULL, 1, 1024, RRDDIM_INCREMENTAL);
1220
- rrddim_add(st, "write", NULL, -1, 1024, RRDDIM_INCREMENTAL);
1221
- }
1222
- else rrdset_next(st);
1223
-
1224
- rrddim_set(st, "read", cg->io_merged.Read);
1225
- rrddim_set(st, "write", cg->io_merged.Write);
1226
- rrdset_done(st);
1227
- }
1228
- }
1229
-
1230
- debug(D_CGROUP, "done updating cgroups charts");
988
+ debug(D_CGROUP, "updating cgroups charts");
989
+
990
+ char type[RRD_ID_LENGTH_MAX + 1];
991
+ char title[CHART_TITLE_MAX + 1];
992
+
993
+ struct cgroup *cg;
994
+ RRDSET *st;
995
+
996
+ for(cg = cgroup_root; cg ; cg = cg->next) {
997
+ if(!cg->available || !cg->enabled)
998
+ continue;
999
+
1000
+ if(cg->id[0] == '\0')
1001
+ strcpy(type, "cgroup_root");
1002
+ else if(cg->id[0] == '/')
1003
+ snprintfz(type, RRD_ID_LENGTH_MAX, "cgroup_%s", cg->chart_id);
1004
+ else
1005
+ snprintfz(type, RRD_ID_LENGTH_MAX, "cgroup_%s", cg->chart_id);
1006
+
1007
+ netdata_fix_chart_id(type);
1008
+
1009
+ if(cg->cpuacct_stat.updated) {
1010
+ st = rrdset_find_bytype(type, "cpu");
1011
+ if(!st) {
1012
+ snprintfz(title, CHART_TITLE_MAX, "CPU Usage for cgroup %s", cg->chart_title);
1013
+ st = rrdset_create(type, "cpu", NULL, "cpu", "cgroup.cpu", title, "%", 40000, update_every, RRDSET_TYPE_STACKED);
1014
+
1015
+ rrddim_add(st, "user", NULL, 100, hz, RRDDIM_INCREMENTAL);
1016
+ rrddim_add(st, "system", NULL, 100, hz, RRDDIM_INCREMENTAL);
1017
+ }
1018
+ else rrdset_next(st);
1019
+
1020
+ rrddim_set(st, "user", cg->cpuacct_stat.user);
1021
+ rrddim_set(st, "system", cg->cpuacct_stat.system);
1022
+ rrdset_done(st);
1023
+ }
1024
+
1025
+ if(cg->cpuacct_usage.updated) {
1026
+ char id[RRD_ID_LENGTH_MAX + 1];
1027
+ unsigned int i;
1028
+
1029
+ st = rrdset_find_bytype(type, "cpu_per_core");
1030
+ if(!st) {
1031
+ snprintfz(title, CHART_TITLE_MAX, "CPU Usage Per Core for cgroup %s", cg->chart_title);
1032
+ st = rrdset_create(type, "cpu_per_core", NULL, "cpu", "cgroup.cpu_per_core", title, "%", 40100, update_every, RRDSET_TYPE_STACKED);
1033
+
1034
+ for(i = 0; i < cg->cpuacct_usage.cpus ;i++) {
1035
+ snprintfz(id, CHART_TITLE_MAX, "cpu%u", i);
1036
+ rrddim_add(st, id, NULL, 100, 1000000000, RRDDIM_INCREMENTAL);
1037
+ }
1038
+ }
1039
+ else rrdset_next(st);
1040
+
1041
+ for(i = 0; i < cg->cpuacct_usage.cpus ;i++) {
1042
+ snprintfz(id, CHART_TITLE_MAX, "cpu%u", i);
1043
+ rrddim_set(st, id, cg->cpuacct_usage.cpu_percpu[i]);
1044
+ }
1045
+ rrdset_done(st);
1046
+ }
1047
+
1048
+ if(cg->memory.updated) {
1049
+ if(cg->memory.cache + cg->memory.rss + cg->memory.rss_huge + cg->memory.mapped_file > 0) {
1050
+ st = rrdset_find_bytype(type, "mem");
1051
+ if(!st) {
1052
+ snprintfz(title, CHART_TITLE_MAX, "Memory Usage for cgroup %s", cg->chart_title);
1053
+ st = rrdset_create(type, "mem", NULL, "mem", "cgroup.mem", title, "MB", 40200, update_every,
1054
+ RRDSET_TYPE_STACKED);
1055
+
1056
+ rrddim_add(st, "cache", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
1057
+ rrddim_add(st, "rss", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
1058
+ if(cg->memory.has_dirty_swap)
1059
+ rrddim_add(st, "swap", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
1060
+ rrddim_add(st, "rss_huge", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
1061
+ rrddim_add(st, "mapped_file", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
1062
+ }
1063
+ else rrdset_next(st);
1064
+
1065
+ rrddim_set(st, "cache", cg->memory.cache);
1066
+ rrddim_set(st, "rss", cg->memory.rss);
1067
+ if(cg->memory.has_dirty_swap)
1068
+ rrddim_set(st, "swap", cg->memory.swap);
1069
+ rrddim_set(st, "rss_huge", cg->memory.rss_huge);
1070
+ rrddim_set(st, "mapped_file", cg->memory.mapped_file);
1071
+ rrdset_done(st);
1072
+ }
1073
+
1074
+ st = rrdset_find_bytype(type, "writeback");
1075
+ if(!st) {
1076
+ snprintfz(title, CHART_TITLE_MAX, "Writeback Memory for cgroup %s", cg->chart_title);
1077
+ st = rrdset_create(type, "writeback", NULL, "mem", "cgroup.writeback", title, "MB", 40300,
1078
+ update_every, RRDSET_TYPE_AREA);
1079
+
1080
+ if(cg->memory.has_dirty_swap)
1081
+ rrddim_add(st, "dirty", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
1082
+ rrddim_add(st, "writeback", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
1083
+ }
1084
+ else rrdset_next(st);
1085
+
1086
+ if(cg->memory.has_dirty_swap)
1087
+ rrddim_set(st, "dirty", cg->memory.dirty);
1088
+ rrddim_set(st, "writeback", cg->memory.writeback);
1089
+ rrdset_done(st);
1090
+
1091
+ if(cg->memory.pgpgin + cg->memory.pgpgout > 0) {
1092
+ st = rrdset_find_bytype(type, "mem_activity");
1093
+ if(!st) {
1094
+ snprintfz(title, CHART_TITLE_MAX, "Memory Activity for cgroup %s", cg->chart_title);
1095
+ st = rrdset_create(type, "mem_activity", NULL, "mem", "cgroup.mem_activity", title, "MB/s",
1096
+ 40400, update_every, RRDSET_TYPE_LINE);
1097
+
1098
+ rrddim_add(st, "pgpgin", "in", sysconf(_SC_PAGESIZE), 1024 * 1024, RRDDIM_INCREMENTAL);
1099
+ rrddim_add(st, "pgpgout", "out", -sysconf(_SC_PAGESIZE), 1024 * 1024, RRDDIM_INCREMENTAL);
1100
+ }
1101
+ else rrdset_next(st);
1102
+
1103
+ rrddim_set(st, "pgpgin", cg->memory.pgpgin);
1104
+ rrddim_set(st, "pgpgout", cg->memory.pgpgout);
1105
+ rrdset_done(st);
1106
+ }
1107
+
1108
+ if(cg->memory.pgfault + cg->memory.pgmajfault > 0) {
1109
+ st = rrdset_find_bytype(type, "pgfaults");
1110
+ if(!st) {
1111
+ snprintfz(title, CHART_TITLE_MAX, "Memory Page Faults for cgroup %s", cg->chart_title);
1112
+ st = rrdset_create(type, "pgfaults", NULL, "mem", "cgroup.pgfaults", title, "MB/s", 40500,
1113
+ update_every, RRDSET_TYPE_LINE);
1114
+
1115
+ rrddim_add(st, "pgfault", NULL, sysconf(_SC_PAGESIZE), 1024 * 1024, RRDDIM_INCREMENTAL);
1116
+ rrddim_add(st, "pgmajfault", "swap", -sysconf(_SC_PAGESIZE), 1024 * 1024, RRDDIM_INCREMENTAL);
1117
+ }
1118
+ else rrdset_next(st);
1119
+
1120
+ rrddim_set(st, "pgfault", cg->memory.pgfault);
1121
+ rrddim_set(st, "pgmajfault", cg->memory.pgmajfault);
1122
+ rrdset_done(st);
1123
+ }
1124
+ }
1125
+
1126
+ if(cg->io_service_bytes.updated && cg->io_service_bytes.Read + cg->io_service_bytes.Write > 0) {
1127
+ st = rrdset_find_bytype(type, "io");
1128
+ if(!st) {
1129
+ snprintfz(title, CHART_TITLE_MAX, "I/O Bandwidth (all disks) for cgroup %s", cg->chart_title);
1130
+ st = rrdset_create(type, "io", NULL, "disk", "cgroup.io", title, "KB/s", 41200,
1131
+ update_every, RRDSET_TYPE_LINE);
1132
+
1133
+ rrddim_add(st, "read", NULL, 1, 1024, RRDDIM_INCREMENTAL);
1134
+ rrddim_add(st, "write", NULL, -1, 1024, RRDDIM_INCREMENTAL);
1135
+ }
1136
+ else rrdset_next(st);
1137
+
1138
+ rrddim_set(st, "read", cg->io_service_bytes.Read);
1139
+ rrddim_set(st, "write", cg->io_service_bytes.Write);
1140
+ rrdset_done(st);
1141
+ }
1142
+
1143
+ if(cg->io_serviced.updated && cg->io_serviced.Read + cg->io_serviced.Write > 0) {
1144
+ st = rrdset_find_bytype(type, "serviced_ops");
1145
+ if(!st) {
1146
+ snprintfz(title, CHART_TITLE_MAX, "Serviced I/O Operations (all disks) for cgroup %s", cg->chart_title);
1147
+ st = rrdset_create(type, "serviced_ops", NULL, "disk", "cgroup.serviced_ops", title, "operations/s", 41200,
1148
+ update_every, RRDSET_TYPE_LINE);
1149
+
1150
+ rrddim_add(st, "read", NULL, 1, 1, RRDDIM_INCREMENTAL);
1151
+ rrddim_add(st, "write", NULL, -1, 1, RRDDIM_INCREMENTAL);
1152
+ }
1153
+ else rrdset_next(st);
1154
+
1155
+ rrddim_set(st, "read", cg->io_serviced.Read);
1156
+ rrddim_set(st, "write", cg->io_serviced.Write);
1157
+ rrdset_done(st);
1158
+ }
1159
+
1160
+ if(cg->throttle_io_service_bytes.updated && cg->throttle_io_service_bytes.Read + cg->throttle_io_service_bytes.Write > 0) {
1161
+ st = rrdset_find_bytype(type, "io");
1162
+ if(!st) {
1163
+ snprintfz(title, CHART_TITLE_MAX, "Throttle I/O Bandwidth (all disks) for cgroup %s", cg->chart_title);
1164
+ st = rrdset_create(type, "io", NULL, "disk", "cgroup.io", title, "KB/s", 41200,
1165
+ update_every, RRDSET_TYPE_LINE);
1166
+
1167
+ rrddim_add(st, "read", NULL, 1, 1024, RRDDIM_INCREMENTAL);
1168
+ rrddim_add(st, "write", NULL, -1, 1024, RRDDIM_INCREMENTAL);
1169
+ }
1170
+ else rrdset_next(st);
1171
+
1172
+ rrddim_set(st, "read", cg->throttle_io_service_bytes.Read);
1173
+ rrddim_set(st, "write", cg->throttle_io_service_bytes.Write);
1174
+ rrdset_done(st);
1175
+ }
1176
+
1177
+
1178
+ if(cg->throttle_io_serviced.updated && cg->throttle_io_serviced.Read + cg->throttle_io_serviced.Write > 0) {
1179
+ st = rrdset_find_bytype(type, "throttle_serviced_ops");
1180
+ if(!st) {
1181
+ snprintfz(title, CHART_TITLE_MAX, "Throttle Serviced I/O Operations (all disks) for cgroup %s", cg->chart_title);
1182
+ st = rrdset_create(type, "throttle_serviced_ops", NULL, "disk", "cgroup.throttle_serviced_ops", title, "operations/s", 41200,
1183
+ update_every, RRDSET_TYPE_LINE);
1184
+
1185
+ rrddim_add(st, "read", NULL, 1, 1, RRDDIM_INCREMENTAL);
1186
+ rrddim_add(st, "write", NULL, -1, 1, RRDDIM_INCREMENTAL);
1187
+ }
1188
+ else rrdset_next(st);
1189
+
1190
+ rrddim_set(st, "read", cg->throttle_io_serviced.Read);
1191
+ rrddim_set(st, "write", cg->throttle_io_serviced.Write);
1192
+ rrdset_done(st);
1193
+ }
1194
+
1195
+ if(cg->io_queued.updated) {
1196
+ st = rrdset_find_bytype(type, "queued_ops");
1197
+ if(!st) {
1198
+ snprintfz(title, CHART_TITLE_MAX, "Queued I/O Operations (all disks) for cgroup %s", cg->chart_title);
1199
+ st = rrdset_create(type, "queued_ops", NULL, "disk", "cgroup.queued_ops", title, "operations", 42000,
1200
+ update_every, RRDSET_TYPE_LINE);
1201
+
1202
+ rrddim_add(st, "read", NULL, 1, 1, RRDDIM_ABSOLUTE);
1203
+ rrddim_add(st, "write", NULL, -1, 1, RRDDIM_ABSOLUTE);
1204
+ }
1205
+ else rrdset_next(st);
1206
+
1207
+ rrddim_set(st, "read", cg->io_queued.Read);
1208
+ rrddim_set(st, "write", cg->io_queued.Write);
1209
+ rrdset_done(st);
1210
+ }
1211
+
1212
+ if(cg->io_merged.updated && cg->io_merged.Read + cg->io_merged.Write > 0) {
1213
+ st = rrdset_find_bytype(type, "merged_ops");
1214
+ if(!st) {
1215
+ snprintfz(title, CHART_TITLE_MAX, "Merged I/O Operations (all disks) for cgroup %s", cg->chart_title);
1216
+ st = rrdset_create(type, "merged_ops", NULL, "disk", "cgroup.merged_ops", title, "operations/s", 42100,
1217
+ update_every, RRDSET_TYPE_LINE);
1218
+
1219
+ rrddim_add(st, "read", NULL, 1, 1024, RRDDIM_INCREMENTAL);
1220
+ rrddim_add(st, "write", NULL, -1, 1024, RRDDIM_INCREMENTAL);
1221
+ }
1222
+ else rrdset_next(st);
1223
+
1224
+ rrddim_set(st, "read", cg->io_merged.Read);
1225
+ rrddim_set(st, "write", cg->io_merged.Write);
1226
+ rrdset_done(st);
1227
+ }
1228
+ }
1229
+
1230
+ debug(D_CGROUP, "done updating cgroups charts");
1231
}
1232
1233
// ----------------------------------------------------------------------------
1234
// cgroups main
1235
1236
int do_sys_fs_cgroup(int update_every, unsigned long long dt) {
1237
- (void)dt;
1237
+ (void)dt;
1238
1239
- static int cgroup_global_config_read = 0;
1240
- static time_t last_run = 0;
1241
- time_t now = time(NULL);
1239
+ static int cgroup_global_config_read = 0;
1240
+ static time_t last_run = 0;
1241
+ time_t now = time(NULL);
1242
1243
- if(unlikely(!cgroup_global_config_read)) {
1244
- read_cgroup_plugin_configuration();
1245
- cgroup_global_config_read = 1;
1246
- }
1243
+ if(unlikely(!cgroup_global_config_read)) {
1244
+ read_cgroup_plugin_configuration();
1245
+ cgroup_global_config_read = 1;
1246
+ }
1247
1248
- if(unlikely(cgroup_enable_new_cgroups_detected_at_runtime && now - last_run > cgroup_check_for_new_every)) {
1249
- find_all_cgroups();
1250
- last_run = now;
1251
- }
1248
+ if(unlikely(cgroup_enable_new_cgroups_detected_at_runtime && now - last_run > cgroup_check_for_new_every)) {
1249
+ find_all_cgroups();
1250
+ last_run = now;
1251
+ }
1252
1253
- read_all_cgroups(cgroup_root);
1254
- update_cgroup_charts(update_every);
1253
+ read_all_cgroups(cgroup_root);
1254
+ update_cgroup_charts(update_every);
1255
1256
- return 0;
1256
+ return 0;
1257
}
1258
1259
void *cgroups_main(void *ptr)
1260
{
1261
- if(ptr) { ; }
1261
+ if(ptr) { ; }
1262
1263
- info("CGROUP Plugin thread created with task id %d", gettid());
1263
+ info("CGROUP Plugin thread created with task id %d", gettid());
1264
1265
- if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
1266
- error("Cannot set pthread cancel type to DEFERRED.");
1265
+ if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
1266
+ error("Cannot set pthread cancel type to DEFERRED.");
1267
1268
- if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
1269
- error("Cannot set pthread cancel state to ENABLE.");
1268
+ if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
1269
+ error("Cannot set pthread cancel state to ENABLE.");
1270
1271
- struct rusage thread;
1271
+ struct rusage thread;
1272
1273
- // when ZERO, attempt to do it
1274
- int vdo_sys_fs_cgroup = 0;
1275
- int vdo_cpu_netdata = !config_get_boolean("plugin:cgroups", "cgroups plugin resources", 1);
1273
+ // when ZERO, attempt to do it
1274
+ int vdo_sys_fs_cgroup = 0;
1275
+ int vdo_cpu_netdata = !config_get_boolean("plugin:cgroups", "cgroups plugin resources", 1);
1276
1277
- // keep track of the time each module was called
1278
- unsigned long long sutime_sys_fs_cgroup = 0ULL;
1277
+ // keep track of the time each module was called
1278
+ unsigned long long sutime_sys_fs_cgroup = 0ULL;
1279
1280
- // the next time we will run - aligned properly
1281
- unsigned long long sunext = (time(NULL) - (time(NULL) % rrd_update_every) + rrd_update_every) * 1000000ULL;
1282
- unsigned long long sunow;
1280
+ // the next time we will run - aligned properly
1281
+ unsigned long long sunext = (time(NULL) - (time(NULL) % rrd_update_every) + rrd_update_every) * 1000000ULL;
1282
+ unsigned long long sunow;
1283
1284
- RRDSET *stcpu_thread = NULL;
1284
+ RRDSET *stcpu_thread = NULL;
1285
1286
- for(;1;) {
1287
- if(unlikely(netdata_exit)) break;
1286
+ for(;1;) {
1287
+ if(unlikely(netdata_exit)) break;
1288
1289
- // delay until it is our time to run
1290
- while((sunow = time_usec()) < sunext)
1291
- sleep_usec(sunext - sunow);
1289
+ // delay until it is our time to run
1290
+ while((sunow = time_usec()) < sunext)
1291
+ sleep_usec(sunext - sunow);
1292
1293
- // find the next time we need to run
1294
- while(time_usec() > sunext)
1295
- sunext += rrd_update_every * 1000000ULL;
1293
+ // find the next time we need to run
1294
+ while(time_usec() > sunext)
1295
+ sunext += rrd_update_every * 1000000ULL;
1296
1297
- if(unlikely(netdata_exit)) break;
1297
+ if(unlikely(netdata_exit)) break;
1298
1299
- // BEGIN -- the job to be done
1299
+ // BEGIN -- the job to be done
1300
1301
- if(!vdo_sys_fs_cgroup) {
1302
- debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_sys_fs_cgroup().");
1303
- sunow = time_usec();
1304
- vdo_sys_fs_cgroup = do_sys_fs_cgroup(rrd_update_every, (sutime_sys_fs_cgroup > 0)?sunow - sutime_sys_fs_cgroup:0ULL);
1305
- sutime_sys_fs_cgroup = sunow;
1306
- }
1307
- if(unlikely(netdata_exit)) break;
1301
+ if(!vdo_sys_fs_cgroup) {
1302
+ debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_sys_fs_cgroup().");
1303
+ sunow = time_usec();
1304
+ vdo_sys_fs_cgroup = do_sys_fs_cgroup(rrd_update_every, (sutime_sys_fs_cgroup > 0)?sunow - sutime_sys_fs_cgroup:0ULL);
1305
+ sutime_sys_fs_cgroup = sunow;
1306
+ }
1307
+ if(unlikely(netdata_exit)) break;
1308
1309
- // END -- the job is done
1309
+ // END -- the job is done
1310
1311
- // --------------------------------------------------------------------
1311
+ // --------------------------------------------------------------------
1312
1313
- if(!vdo_cpu_netdata) {
1314
- getrusage(RUSAGE_THREAD, &thread);
1313
+ if(!vdo_cpu_netdata) {
1314
+ getrusage(RUSAGE_THREAD, &thread);
1315
1316
- if(!stcpu_thread) stcpu_thread = rrdset_find("netdata.plugin_cgroups_cpu");
1317
- if(!stcpu_thread) {
1318
- stcpu_thread = rrdset_create("netdata", "plugin_cgroups_cpu", NULL, "proc.internal", NULL, "NetData CGroups Plugin CPU usage", "milliseconds/s", 132000, rrd_update_every, RRDSET_TYPE_STACKED);
1316
+ if(!stcpu_thread) stcpu_thread = rrdset_find("netdata.plugin_cgroups_cpu");
1317
+ if(!stcpu_thread) {
1318
+ stcpu_thread = rrdset_create("netdata", "plugin_cgroups_cpu", NULL, "proc.internal", NULL, "NetData CGroups Plugin CPU usage", "milliseconds/s", 132000, rrd_update_every, RRDSET_TYPE_STACKED);
1319
1320
- rrddim_add(stcpu_thread, "user", NULL, 1, 1000, RRDDIM_INCREMENTAL);
1321
- rrddim_add(stcpu_thread, "system", NULL, 1, 1000, RRDDIM_INCREMENTAL);
1322
- }
1323
- else rrdset_next(stcpu_thread);
1320
+ rrddim_add(stcpu_thread, "user", NULL, 1, 1000, RRDDIM_INCREMENTAL);
1321
+ rrddim_add(stcpu_thread, "system", NULL, 1, 1000, RRDDIM_INCREMENTAL);
1322
+ }
1323
+ else rrdset_next(stcpu_thread);
1324
1325
- rrddim_set(stcpu_thread, "user" , thread.ru_utime.tv_sec * 1000000ULL + thread.ru_utime.tv_usec);
1326
- rrddim_set(stcpu_thread, "system", thread.ru_stime.tv_sec * 1000000ULL + thread.ru_stime.tv_usec);
1327
- rrdset_done(stcpu_thread);
1328
- }
1329
- }
1325
+ rrddim_set(stcpu_thread, "user" , thread.ru_utime.tv_sec * 1000000ULL + thread.ru_utime.tv_usec);
1326
+ rrddim_set(stcpu_thread, "system", thread.ru_stime.tv_sec * 1000000ULL + thread.ru_stime.tv_usec);
1327
+ rrdset_done(stcpu_thread);
1328
+ }
1329
+ }
1330
1331
- pthread_exit(NULL);
1332
- return NULL;
1331
+ pthread_exit(NULL);
1332
+ return NULL;
1333
}
src/sys_kernel_mm_ksm.c
+98
-98
@@ -1,8 +1,8 @@
1
#include "common.h"
2
3
typedef struct ksm_name_value {
4
- char filename[FILENAME_MAX + 1];
5
- unsigned long long value;
4
+ char filename[FILENAME_MAX + 1];
5
+ unsigned long long value;
6
} KSM_NAME_VALUE;
7
8
#define PAGES_SHARED 0
@@ -12,127 +12,127 @@ typedef struct ksm_name_value {
12
#define PAGES_TO_SCAN 4
13
14
KSM_NAME_VALUE values[] = {
15
- [PAGES_SHARED] = { "/sys/kernel/mm/ksm/pages_shared", 0ULL },
16
- [PAGES_SHARING] = { "/sys/kernel/mm/ksm/pages_sharing", 0ULL },
17
- [PAGES_UNSHARED] = { "/sys/kernel/mm/ksm/pages_unshared", 0ULL },
18
- [PAGES_VOLATILE] = { "/sys/kernel/mm/ksm/pages_volatile", 0ULL },
19
- [PAGES_TO_SCAN] = { "/sys/kernel/mm/ksm/pages_to_scan", 0ULL },
15
+ [PAGES_SHARED] = { "/sys/kernel/mm/ksm/pages_shared", 0ULL },
16
+ [PAGES_SHARING] = { "/sys/kernel/mm/ksm/pages_sharing", 0ULL },
17
+ [PAGES_UNSHARED] = { "/sys/kernel/mm/ksm/pages_unshared", 0ULL },
18
+ [PAGES_VOLATILE] = { "/sys/kernel/mm/ksm/pages_volatile", 0ULL },
19
+ [PAGES_TO_SCAN] = { "/sys/kernel/mm/ksm/pages_to_scan", 0ULL },
20
};
21
22
int do_sys_kernel_mm_ksm(int update_every, unsigned long long dt) {
23
- static procfile *ff_pages_shared = NULL, *ff_pages_sharing = NULL, *ff_pages_unshared = NULL, *ff_pages_volatile = NULL, *ff_pages_to_scan = NULL;
24
- static long page_size = -1;
23
+ static procfile *ff_pages_shared = NULL, *ff_pages_sharing = NULL, *ff_pages_unshared = NULL, *ff_pages_volatile = NULL, *ff_pages_to_scan = NULL;
24
+ static long page_size = -1;
25
26
- if(dt) {};
27
-
28
- if(page_size == -1)
29
- page_size = sysconf(_SC_PAGESIZE);
30
-
31
- if(!ff_pages_shared) {
32
- snprintfz(values[PAGES_SHARED].filename, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/kernel/mm/ksm/pages_shared");
33
- snprintfz(values[PAGES_SHARED].filename, FILENAME_MAX, "%s", config_get("plugin:proc:/sys/kernel/mm/ksm", "/sys/kernel/mm/ksm/pages_shared", values[PAGES_SHARED].filename));
34
- ff_pages_shared = procfile_open(values[PAGES_SHARED].filename, " \t:", PROCFILE_FLAG_DEFAULT);
35
- }
26
+ if(dt) {};
27
+
28
+ if(page_size == -1)
29
+ page_size = sysconf(_SC_PAGESIZE);
30
+
31
+ if(!ff_pages_shared) {
32
+ snprintfz(values[PAGES_SHARED].filename, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/kernel/mm/ksm/pages_shared");
33
+ snprintfz(values[PAGES_SHARED].filename, FILENAME_MAX, "%s", config_get("plugin:proc:/sys/kernel/mm/ksm", "/sys/kernel/mm/ksm/pages_shared", values[PAGES_SHARED].filename));
34
+ ff_pages_shared = procfile_open(values[PAGES_SHARED].filename, " \t:", PROCFILE_FLAG_DEFAULT);
35
+ }
36
37
- if(!ff_pages_sharing) {
38
- snprintfz(values[PAGES_SHARING].filename, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/kernel/mm/ksm/pages_sharing");
39
- snprintfz(values[PAGES_SHARING].filename, FILENAME_MAX, "%s", config_get("plugin:proc:/sys/kernel/mm/ksm", "/sys/kernel/mm/ksm/pages_sharing", values[PAGES_SHARING].filename));
40
- ff_pages_sharing = procfile_open(values[PAGES_SHARING].filename, " \t:", PROCFILE_FLAG_DEFAULT);
41
- }
37
+ if(!ff_pages_sharing) {
38
+ snprintfz(values[PAGES_SHARING].filename, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/kernel/mm/ksm/pages_sharing");
39
+ snprintfz(values[PAGES_SHARING].filename, FILENAME_MAX, "%s", config_get("plugin:proc:/sys/kernel/mm/ksm", "/sys/kernel/mm/ksm/pages_sharing", values[PAGES_SHARING].filename));
40
+ ff_pages_sharing = procfile_open(values[PAGES_SHARING].filename, " \t:", PROCFILE_FLAG_DEFAULT);
41
+ }
42
43
- if(!ff_pages_unshared) {
44
- snprintfz(values[PAGES_UNSHARED].filename, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/kernel/mm/ksm/pages_unshared");
45
- snprintfz(values[PAGES_UNSHARED].filename, FILENAME_MAX, "%s", config_get("plugin:proc:/sys/kernel/mm/ksm", "/sys/kernel/mm/ksm/pages_unshared", values[PAGES_UNSHARED].filename));
46
- ff_pages_unshared = procfile_open(values[PAGES_UNSHARED].filename, " \t:", PROCFILE_FLAG_DEFAULT);
47
- }
43
+ if(!ff_pages_unshared) {
44
+ snprintfz(values[PAGES_UNSHARED].filename, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/kernel/mm/ksm/pages_unshared");
45
+ snprintfz(values[PAGES_UNSHARED].filename, FILENAME_MAX, "%s", config_get("plugin:proc:/sys/kernel/mm/ksm", "/sys/kernel/mm/ksm/pages_unshared", values[PAGES_UNSHARED].filename));
46
+ ff_pages_unshared = procfile_open(values[PAGES_UNSHARED].filename, " \t:", PROCFILE_FLAG_DEFAULT);
47
+ }
48
49
- if(!ff_pages_volatile) {
50
- snprintfz(values[PAGES_VOLATILE].filename, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/kernel/mm/ksm/pages_volatile");
51
- snprintfz(values[PAGES_VOLATILE].filename, FILENAME_MAX, "%s", config_get("plugin:proc:/sys/kernel/mm/ksm", "/sys/kernel/mm/ksm/pages_volatile", values[PAGES_VOLATILE].filename));
52
- ff_pages_volatile = procfile_open(values[PAGES_VOLATILE].filename, " \t:", PROCFILE_FLAG_DEFAULT);
53
- }
49
+ if(!ff_pages_volatile) {
50
+ snprintfz(values[PAGES_VOLATILE].filename, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/kernel/mm/ksm/pages_volatile");
51
+ snprintfz(values[PAGES_VOLATILE].filename, FILENAME_MAX, "%s", config_get("plugin:proc:/sys/kernel/mm/ksm", "/sys/kernel/mm/ksm/pages_volatile", values[PAGES_VOLATILE].filename));
52
+ ff_pages_volatile = procfile_open(values[PAGES_VOLATILE].filename, " \t:", PROCFILE_FLAG_DEFAULT);
53
+ }
54
55
- if(!ff_pages_to_scan) {
56
- snprintfz(values[PAGES_TO_SCAN].filename, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/kernel/mm/ksm/pages_to_scan");
57
- snprintfz(values[PAGES_TO_SCAN].filename, FILENAME_MAX, "%s", config_get("plugin:proc:/sys/kernel/mm/ksm", "/sys/kernel/mm/ksm/pages_to_scan", values[PAGES_TO_SCAN].filename));
58
- ff_pages_to_scan = procfile_open(values[PAGES_TO_SCAN].filename, " \t:", PROCFILE_FLAG_DEFAULT);
59
- }
55
+ if(!ff_pages_to_scan) {
56
+ snprintfz(values[PAGES_TO_SCAN].filename, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/kernel/mm/ksm/pages_to_scan");
57
+ snprintfz(values[PAGES_TO_SCAN].filename, FILENAME_MAX, "%s", config_get("plugin:proc:/sys/kernel/mm/ksm", "/sys/kernel/mm/ksm/pages_to_scan", values[PAGES_TO_SCAN].filename));
58
+ ff_pages_to_scan = procfile_open(values[PAGES_TO_SCAN].filename, " \t:", PROCFILE_FLAG_DEFAULT);
59
+ }
60
61
- if(!ff_pages_shared || !ff_pages_sharing || !ff_pages_unshared || !ff_pages_volatile || !ff_pages_to_scan) return 1;
61
+ if(!ff_pages_shared || !ff_pages_sharing || !ff_pages_unshared || !ff_pages_volatile || !ff_pages_to_scan) return 1;
62
63
- unsigned long long pages_shared = 0, pages_sharing = 0, pages_unshared = 0, pages_volatile = 0, pages_to_scan = 0, offered = 0, saved = 0;
63
+ unsigned long long pages_shared = 0, pages_sharing = 0, pages_unshared = 0, pages_volatile = 0, pages_to_scan = 0, offered = 0, saved = 0;
64
65
- ff_pages_shared = procfile_readall(ff_pages_shared);
66
- if(!ff_pages_shared) return 0; // we return 0, so that we will retry to open it next time
67
- pages_shared = strtoull(procfile_lineword(ff_pages_shared, 0, 0), NULL, 10);
65
+ ff_pages_shared = procfile_readall(ff_pages_shared);
66
+ if(!ff_pages_shared) return 0; // we return 0, so that we will retry to open it next time
67
+ pages_shared = strtoull(procfile_lineword(ff_pages_shared, 0, 0), NULL, 10);
68
69
- ff_pages_sharing = procfile_readall(ff_pages_sharing);
70
- if(!ff_pages_sharing) return 0; // we return 0, so that we will retry to open it next time
71
- pages_sharing = strtoull(procfile_lineword(ff_pages_sharing, 0, 0), NULL, 10);
69
+ ff_pages_sharing = procfile_readall(ff_pages_sharing);
70
+ if(!ff_pages_sharing) return 0; // we return 0, so that we will retry to open it next time
71
+ pages_sharing = strtoull(procfile_lineword(ff_pages_sharing, 0, 0), NULL, 10);
72
73
- ff_pages_unshared = procfile_readall(ff_pages_unshared);
74
- if(!ff_pages_unshared) return 0; // we return 0, so that we will retry to open it next time
75
- pages_unshared = strtoull(procfile_lineword(ff_pages_unshared, 0, 0), NULL, 10);
73
+ ff_pages_unshared = procfile_readall(ff_pages_unshared);
74
+ if(!ff_pages_unshared) return 0; // we return 0, so that we will retry to open it next time
75
+ pages_unshared = strtoull(procfile_lineword(ff_pages_unshared, 0, 0), NULL, 10);
76
77
- ff_pages_volatile = procfile_readall(ff_pages_volatile);
78
- if(!ff_pages_volatile) return 0; // we return 0, so that we will retry to open it next time
79
- pages_volatile = strtoull(procfile_lineword(ff_pages_volatile, 0, 0), NULL, 10);
77
+ ff_pages_volatile = procfile_readall(ff_pages_volatile);
78
+ if(!ff_pages_volatile) return 0; // we return 0, so that we will retry to open it next time
79
+ pages_volatile = strtoull(procfile_lineword(ff_pages_volatile, 0, 0), NULL, 10);
80
81
- ff_pages_to_scan = procfile_readall(ff_pages_to_scan);
82
- if(!ff_pages_to_scan) return 0; // we return 0, so that we will retry to open it next time
83
- pages_to_scan = strtoull(procfile_lineword(ff_pages_to_scan, 0, 0), NULL, 10);
81
+ ff_pages_to_scan = procfile_readall(ff_pages_to_scan);
82
+ if(!ff_pages_to_scan) return 0; // we return 0, so that we will retry to open it next time
83
+ pages_to_scan = strtoull(procfile_lineword(ff_pages_to_scan, 0, 0), NULL, 10);
84
85
- offered = pages_sharing + pages_shared + pages_unshared + pages_volatile;
86
- saved = pages_sharing - pages_shared;
85
+ offered = pages_sharing + pages_shared + pages_unshared + pages_volatile;
86
+ saved = pages_sharing - pages_shared;
87
88
- if(!offered || !pages_to_scan) return 0;
88
+ if(!offered || !pages_to_scan) return 0;
89
90
- RRDSET *st;
90
+ RRDSET *st;
91
92
- // --------------------------------------------------------------------
92
+ // --------------------------------------------------------------------
93
94
- st = rrdset_find("mem.ksm");
95
- if(!st) {
96
- st = rrdset_create("mem", "ksm", NULL, "ksm", NULL, "Kernel Same Page Merging", "MB", 5000, update_every, RRDSET_TYPE_AREA);
94
+ st = rrdset_find("mem.ksm");
95
+ if(!st) {
96
+ st = rrdset_create("mem", "ksm", NULL, "ksm", NULL, "Kernel Same Page Merging", "MB", 5000, update_every, RRDSET_TYPE_AREA);
97
98
- rrddim_add(st, "shared", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
99
- rrddim_add(st, "unshared", NULL, -1, 1024 * 1024, RRDDIM_ABSOLUTE);
100
- rrddim_add(st, "sharing", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
101
- rrddim_add(st, "volatile", NULL, -1, 1024 * 1024, RRDDIM_ABSOLUTE);
102
- rrddim_add(st, "to_scan", "to scan", -1, 1024 * 1024, RRDDIM_ABSOLUTE);
103
- }
104
- else rrdset_next(st);
98
+ rrddim_add(st, "shared", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
99
+ rrddim_add(st, "unshared", NULL, -1, 1024 * 1024, RRDDIM_ABSOLUTE);
100
+ rrddim_add(st, "sharing", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
101
+ rrddim_add(st, "volatile", NULL, -1, 1024 * 1024, RRDDIM_ABSOLUTE);
102
+ rrddim_add(st, "to_scan", "to scan", -1, 1024 * 1024, RRDDIM_ABSOLUTE);
103
+ }
104
+ else rrdset_next(st);
105
106
- rrddim_set(st, "shared", pages_shared * page_size);
107
- rrddim_set(st, "unshared", pages_unshared * page_size);
108
- rrddim_set(st, "sharing", pages_sharing * page_size);
109
- rrddim_set(st, "volatile", pages_volatile * page_size);
110
- rrddim_set(st, "to_scan", pages_to_scan * page_size);
111
- rrdset_done(st);
106
+ rrddim_set(st, "shared", pages_shared * page_size);
107
+ rrddim_set(st, "unshared", pages_unshared * page_size);
108
+ rrddim_set(st, "sharing", pages_sharing * page_size);
109
+ rrddim_set(st, "volatile", pages_volatile * page_size);
110
+ rrddim_set(st, "to_scan", pages_to_scan * page_size);
111
+ rrdset_done(st);
112
113
- st = rrdset_find("mem.ksm_savings");
114
- if(!st) {
115
- st = rrdset_create("mem", "ksm_savings", NULL, "ksm", NULL, "Kernel Same Page Merging Savings", "MB", 5001, update_every, RRDSET_TYPE_AREA);
113
+ st = rrdset_find("mem.ksm_savings");
114
+ if(!st) {
115
+ st = rrdset_create("mem", "ksm_savings", NULL, "ksm", NULL, "Kernel Same Page Merging Savings", "MB", 5001, update_every, RRDSET_TYPE_AREA);
116
117
- rrddim_add(st, "savings", NULL, -1, 1024 * 1024, RRDDIM_ABSOLUTE);
118
- rrddim_add(st, "offered", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
119
- }
120
- else rrdset_next(st);
117
+ rrddim_add(st, "savings", NULL, -1, 1024 * 1024, RRDDIM_ABSOLUTE);
118
+ rrddim_add(st, "offered", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
119
+ }
120
+ else rrdset_next(st);
121
122
- rrddim_set(st, "savings", saved * page_size);
123
- rrddim_set(st, "offered", offered * page_size);
124
- rrdset_done(st);
122
+ rrddim_set(st, "savings", saved * page_size);
123
+ rrddim_set(st, "offered", offered * page_size);
124
+ rrdset_done(st);
125
126
- st = rrdset_find("mem.ksm_ratios");
127
- if(!st) {
128
- st = rrdset_create("mem", "ksm_ratios", NULL, "ksm", NULL, "Kernel Same Page Merging Effectiveness", "percentage", 5002, update_every, RRDSET_TYPE_LINE);
129
-
130
- rrddim_add(st, "savings", NULL, 1, 10000, RRDDIM_ABSOLUTE);
131
- }
132
- else rrdset_next(st);
133
-
134
- rrddim_set(st, "savings", (saved * 1000000) / offered);
135
- rrdset_done(st);
126
+ st = rrdset_find("mem.ksm_ratios");
127
+ if(!st) {
128
+ st = rrdset_create("mem", "ksm_ratios", NULL, "ksm", NULL, "Kernel Same Page Merging Effectiveness", "percentage", 5002, update_every, RRDSET_TYPE_LINE);
129
+
130
+ rrddim_add(st, "savings", NULL, 1, 10000, RRDDIM_ABSOLUTE);
131
+ }
132
+ else rrdset_next(st);
133
+
134
+ rrddim_set(st, "savings", (saved * 1000000) / offered);
135
+ rrdset_done(st);
136
137
- return 0;
137
+ return 0;
138
}
src/unit_test.c
+702
-702
@@ -1,258 +1,258 @@
1
#include "common.h"
2
3
int check_storage_number(calculated_number n, int debug) {
4
- char buffer[100];
5
- uint32_t flags = SN_EXISTS;
6
-
7
- storage_number s = pack_storage_number(n, flags);
8
- calculated_number d = unpack_storage_number(s);
9
-
10
- if(!does_storage_number_exist(s)) {
11
- fprintf(stderr, "Exists flags missing for number " CALCULATED_NUMBER_FORMAT "!\n", n);
12
- return 5;
13
- }
14
-
15
- calculated_number ddiff = d - n;
16
- calculated_number dcdiff = ddiff * 100.0 / n;
17
-
18
- if(dcdiff < 0) dcdiff = -dcdiff;
19
-
20
- size_t len = print_calculated_number(buffer, d);
21
- calculated_number p = strtold(buffer, NULL);
22
- calculated_number pdiff = n - p;
23
- calculated_number pcdiff = pdiff * 100.0 / n;
24
- if(pcdiff < 0) pcdiff = -pcdiff;
25
-
26
- if(debug) {
27
- fprintf(stderr,
28
- CALCULATED_NUMBER_FORMAT " original\n"
29
- CALCULATED_NUMBER_FORMAT " packed and unpacked, (stored as 0x%08X, diff " CALCULATED_NUMBER_FORMAT ", " CALCULATED_NUMBER_FORMAT "%%)\n"
30
- "%s printed after unpacked (%zu bytes)\n"
31
- CALCULATED_NUMBER_FORMAT " re-parsed from printed (diff " CALCULATED_NUMBER_FORMAT ", " CALCULATED_NUMBER_FORMAT "%%)\n\n",
32
- n,
33
- d, s, ddiff, dcdiff,
34
- buffer,
35
- len, p, pdiff, pcdiff
36
- );
37
- if(len != strlen(buffer)) fprintf(stderr, "ERROR: printed number %s is reported to have length %zu but it has %zu\n", buffer, len, strlen(buffer));
38
- if(dcdiff > ACCURACY_LOSS) fprintf(stderr, "WARNING: packing number " CALCULATED_NUMBER_FORMAT " has accuracy loss %0.7Lf %%\n", n, dcdiff);
39
- if(pcdiff > ACCURACY_LOSS) fprintf(stderr, "WARNING: re-parsing the packed, unpacked and printed number " CALCULATED_NUMBER_FORMAT " has accuracy loss %0.7Lf %%\n", n, pcdiff);
40
- }
41
-
42
- if(len != strlen(buffer)) return 1;
43
- if(dcdiff > ACCURACY_LOSS) return 3;
44
- if(pcdiff > ACCURACY_LOSS) return 4;
45
- return 0;
4
+ char buffer[100];
5
+ uint32_t flags = SN_EXISTS;
6
+
7
+ storage_number s = pack_storage_number(n, flags);
8
+ calculated_number d = unpack_storage_number(s);
9
+
10
+ if(!does_storage_number_exist(s)) {
11
+ fprintf(stderr, "Exists flags missing for number " CALCULATED_NUMBER_FORMAT "!\n", n);
12
+ return 5;
13
+ }
14
+
15
+ calculated_number ddiff = d - n;
16
+ calculated_number dcdiff = ddiff * 100.0 / n;
17
+
18
+ if(dcdiff < 0) dcdiff = -dcdiff;
19
+
20
+ size_t len = print_calculated_number(buffer, d);
21
+ calculated_number p = strtold(buffer, NULL);
22
+ calculated_number pdiff = n - p;
23
+ calculated_number pcdiff = pdiff * 100.0 / n;
24
+ if(pcdiff < 0) pcdiff = -pcdiff;
25
+
26
+ if(debug) {
27
+ fprintf(stderr,
28
+ CALCULATED_NUMBER_FORMAT " original\n"
29
+ CALCULATED_NUMBER_FORMAT " packed and unpacked, (stored as 0x%08X, diff " CALCULATED_NUMBER_FORMAT ", " CALCULATED_NUMBER_FORMAT "%%)\n"
30
+ "%s printed after unpacked (%zu bytes)\n"
31
+ CALCULATED_NUMBER_FORMAT " re-parsed from printed (diff " CALCULATED_NUMBER_FORMAT ", " CALCULATED_NUMBER_FORMAT "%%)\n\n",
32
+ n,
33
+ d, s, ddiff, dcdiff,
34
+ buffer,
35
+ len, p, pdiff, pcdiff
36
+ );
37
+ if(len != strlen(buffer)) fprintf(stderr, "ERROR: printed number %s is reported to have length %zu but it has %zu\n", buffer, len, strlen(buffer));
38
+ if(dcdiff > ACCURACY_LOSS) fprintf(stderr, "WARNING: packing number " CALCULATED_NUMBER_FORMAT " has accuracy loss %0.7Lf %%\n", n, dcdiff);
39
+ if(pcdiff > ACCURACY_LOSS) fprintf(stderr, "WARNING: re-parsing the packed, unpacked and printed number " CALCULATED_NUMBER_FORMAT " has accuracy loss %0.7Lf %%\n", n, pcdiff);
40
+ }
41
+
42
+ if(len != strlen(buffer)) return 1;
43
+ if(dcdiff > ACCURACY_LOSS) return 3;
44
+ if(pcdiff > ACCURACY_LOSS) return 4;
45
+ return 0;
46
}
47
48
void benchmark_storage_number(int loop, int multiplier) {
49
- int i, j;
50
- calculated_number n, d;
51
- storage_number s;
52
- unsigned long long user, system, total, mine, their;
49
+ int i, j;
50
+ calculated_number n, d;
51
+ storage_number s;
52
+ unsigned long long user, system, total, mine, their;
53
54
- char buffer[100];
54
+ char buffer[100];
55
56
- struct rusage now, last;
56
+ struct rusage now, last;
57
58
- fprintf(stderr, "\n\nBenchmarking %d numbers, please wait...\n\n", loop);
58
+ fprintf(stderr, "\n\nBenchmarking %d numbers, please wait...\n\n", loop);
59
60
- // ------------------------------------------------------------------------
60
+ // ------------------------------------------------------------------------
61
62
- fprintf(stderr, "SYSTEM LONG DOUBLE SIZE: %zu bytes\n", sizeof(calculated_number));
63
- fprintf(stderr, "NETDATA FLOATING POINT SIZE: %zu bytes\n", sizeof(storage_number));
62
+ fprintf(stderr, "SYSTEM LONG DOUBLE SIZE: %zu bytes\n", sizeof(calculated_number));
63
+ fprintf(stderr, "NETDATA FLOATING POINT SIZE: %zu bytes\n", sizeof(storage_number));
64
65
- mine = (calculated_number)sizeof(storage_number) * (calculated_number)loop;
66
- their = (calculated_number)sizeof(calculated_number) * (calculated_number)loop;
65
+ mine = (calculated_number)sizeof(storage_number) * (calculated_number)loop;
66
+ their = (calculated_number)sizeof(calculated_number) * (calculated_number)loop;
67
68
- if(mine > their) {
69
- fprintf(stderr, "\nNETDATA NEEDS %0.2Lf TIMES MORE MEMORY. Sorry!\n", (long double)(mine / their));
70
- }
71
- else {
72
- fprintf(stderr, "\nNETDATA INTERNAL FLOATING POINT ARITHMETICS NEEDS %0.2Lf TIMES LESS MEMORY.\n", (long double)(their / mine));
73
- }
68
+ if(mine > their) {
69
+ fprintf(stderr, "\nNETDATA NEEDS %0.2Lf TIMES MORE MEMORY. Sorry!\n", (long double)(mine / their));
70
+ }
71
+ else {
72
+ fprintf(stderr, "\nNETDATA INTERNAL FLOATING POINT ARITHMETICS NEEDS %0.2Lf TIMES LESS MEMORY.\n", (long double)(their / mine));
73
+ }
74
75
- fprintf(stderr, "\nNETDATA FLOATING POINT\n");
76
- fprintf(stderr, "MIN POSITIVE VALUE " CALCULATED_NUMBER_FORMAT "\n", (calculated_number)STORAGE_NUMBER_POSITIVE_MIN);
77
- fprintf(stderr, "MAX POSITIVE VALUE " CALCULATED_NUMBER_FORMAT "\n", (calculated_number)STORAGE_NUMBER_POSITIVE_MAX);
78
- fprintf(stderr, "MIN NEGATIVE VALUE " CALCULATED_NUMBER_FORMAT "\n", (calculated_number)STORAGE_NUMBER_NEGATIVE_MIN);
79
- fprintf(stderr, "MAX NEGATIVE VALUE " CALCULATED_NUMBER_FORMAT "\n", (calculated_number)STORAGE_NUMBER_NEGATIVE_MAX);
80
- fprintf(stderr, "Maximum accuracy loss: " CALCULATED_NUMBER_FORMAT "%%\n\n\n", (calculated_number)ACCURACY_LOSS);
75
+ fprintf(stderr, "\nNETDATA FLOATING POINT\n");
76
+ fprintf(stderr, "MIN POSITIVE VALUE " CALCULATED_NUMBER_FORMAT "\n", (calculated_number)STORAGE_NUMBER_POSITIVE_MIN);
77
+ fprintf(stderr, "MAX POSITIVE VALUE " CALCULATED_NUMBER_FORMAT "\n", (calculated_number)STORAGE_NUMBER_POSITIVE_MAX);
78
+ fprintf(stderr, "MIN NEGATIVE VALUE " CALCULATED_NUMBER_FORMAT "\n", (calculated_number)STORAGE_NUMBER_NEGATIVE_MIN);
79
+ fprintf(stderr, "MAX NEGATIVE VALUE " CALCULATED_NUMBER_FORMAT "\n", (calculated_number)STORAGE_NUMBER_NEGATIVE_MAX);
80
+ fprintf(stderr, "Maximum accuracy loss: " CALCULATED_NUMBER_FORMAT "%%\n\n\n", (calculated_number)ACCURACY_LOSS);
81
82
- // ------------------------------------------------------------------------
82
+ // ------------------------------------------------------------------------
83
84
- fprintf(stderr, "INTERNAL LONG DOUBLE PRINTING: ");
85
- getrusage(RUSAGE_SELF, &last);
84
+ fprintf(stderr, "INTERNAL LONG DOUBLE PRINTING: ");
85
+ getrusage(RUSAGE_SELF, &last);
86
87
- // do the job
88
- for(j = 1; j < 11 ;j++) {
89
- n = STORAGE_NUMBER_POSITIVE_MIN * j;
87
+ // do the job
88
+ for(j = 1; j < 11 ;j++) {
89
+ n = STORAGE_NUMBER_POSITIVE_MIN * j;
90
91
- for(i = 0; i < loop ;i++) {
92
- n *= multiplier;
93
- if(n > STORAGE_NUMBER_POSITIVE_MAX) n = STORAGE_NUMBER_POSITIVE_MIN;
91
+ for(i = 0; i < loop ;i++) {
92
+ n *= multiplier;
93
+ if(n > STORAGE_NUMBER_POSITIVE_MAX) n = STORAGE_NUMBER_POSITIVE_MIN;
94
95
- print_calculated_number(buffer, n);
96
- }
97
- }
95
+ print_calculated_number(buffer, n);
96
+ }
97
+ }
98
99
- getrusage(RUSAGE_SELF, &now);
100
- user = now.ru_utime.tv_sec * 1000000ULL + now.ru_utime.tv_usec - last.ru_utime.tv_sec * 1000000ULL + last.ru_utime.tv_usec;
101
- system = now.ru_stime.tv_sec * 1000000ULL + now.ru_stime.tv_usec - last.ru_stime.tv_sec * 1000000ULL + last.ru_stime.tv_usec;
102
- total = user + system;
103
- mine = total;
99
+ getrusage(RUSAGE_SELF, &now);
100
+ user = now.ru_utime.tv_sec * 1000000ULL + now.ru_utime.tv_usec - last.ru_utime.tv_sec * 1000000ULL + last.ru_utime.tv_usec;
101
+ system = now.ru_stime.tv_sec * 1000000ULL + now.ru_stime.tv_usec - last.ru_stime.tv_sec * 1000000ULL + last.ru_stime.tv_usec;
102
+ total = user + system;
103
+ mine = total;
104
105
- fprintf(stderr, "user %0.5Lf, system %0.5Lf, total %0.5Lf\n", (long double)(user / 1000000.0), (long double)(system / 1000000.0), (long double)(total / 1000000.0));
105
+ fprintf(stderr, "user %0.5Lf, system %0.5Lf, total %0.5Lf\n", (long double)(user / 1000000.0), (long double)(system / 1000000.0), (long double)(total / 1000000.0));
106
107
- // ------------------------------------------------------------------------
107
+ // ------------------------------------------------------------------------
108
109
- fprintf(stderr, "SYSTEM LONG DOUBLE PRINTING: ");
110
- getrusage(RUSAGE_SELF, &last);
109
+ fprintf(stderr, "SYSTEM LONG DOUBLE PRINTING: ");
110
+ getrusage(RUSAGE_SELF, &last);
111
112
- // do the job
113
- for(j = 1; j < 11 ;j++) {
114
- n = STORAGE_NUMBER_POSITIVE_MIN * j;
112
+ // do the job
113
+ for(j = 1; j < 11 ;j++) {
114
+ n = STORAGE_NUMBER_POSITIVE_MIN * j;
115
116
- for(i = 0; i < loop ;i++) {
117
- n *= multiplier;
118
- if(n > STORAGE_NUMBER_POSITIVE_MAX) n = STORAGE_NUMBER_POSITIVE_MIN;
119
- snprintfz(buffer, 100, CALCULATED_NUMBER_FORMAT, n);
120
- }
121
- }
116
+ for(i = 0; i < loop ;i++) {
117
+ n *= multiplier;
118
+ if(n > STORAGE_NUMBER_POSITIVE_MAX) n = STORAGE_NUMBER_POSITIVE_MIN;
119
+ snprintfz(buffer, 100, CALCULATED_NUMBER_FORMAT, n);
120
+ }
121
+ }
122
123
- getrusage(RUSAGE_SELF, &now);
124
- user = now.ru_utime.tv_sec * 1000000ULL + now.ru_utime.tv_usec - last.ru_utime.tv_sec * 1000000ULL + last.ru_utime.tv_usec;
125
- system = now.ru_stime.tv_sec * 1000000ULL + now.ru_stime.tv_usec - last.ru_stime.tv_sec * 1000000ULL + last.ru_stime.tv_usec;
126
- total = user + system;
127
- their = total;
123
+ getrusage(RUSAGE_SELF, &now);
124
+ user = now.ru_utime.tv_sec * 1000000ULL + now.ru_utime.tv_usec - last.ru_utime.tv_sec * 1000000ULL + last.ru_utime.tv_usec;
125
+ system = now.ru_stime.tv_sec * 1000000ULL + now.ru_stime.tv_usec - last.ru_stime.tv_sec * 1000000ULL + last.ru_stime.tv_usec;
126
+ total = user + system;
127
+ their = total;
128
129
- fprintf(stderr, "user %0.5Lf, system %0.5Lf, total %0.5Lf\n", (long double)(user / 1000000.0), (long double)(system / 1000000.0), (long double)(total / 1000000.0));
129
+ fprintf(stderr, "user %0.5Lf, system %0.5Lf, total %0.5Lf\n", (long double)(user / 1000000.0), (long double)(system / 1000000.0), (long double)(total / 1000000.0));
130
131
- if(mine > total) {
132
- fprintf(stderr, "NETDATA CODE IS SLOWER %0.2Lf %%\n", (long double)(mine * 100.0 / their - 100.0));
133
- }
134
- else {
135
- fprintf(stderr, "NETDATA CODE IS F A S T E R %0.2Lf %%\n", (long double)(their * 100.0 / mine - 100.0));
136
- }
131
+ if(mine > total) {
132
+ fprintf(stderr, "NETDATA CODE IS SLOWER %0.2Lf %%\n", (long double)(mine * 100.0 / their - 100.0));
133
+ }
134
+ else {
135
+ fprintf(stderr, "NETDATA CODE IS F A S T E R %0.2Lf %%\n", (long double)(their * 100.0 / mine - 100.0));
136
+ }
137
138
- // ------------------------------------------------------------------------
138
+ // ------------------------------------------------------------------------
139
140
- fprintf(stderr, "\nINTERNAL LONG DOUBLE PRINTING WITH PACK / UNPACK: ");
141
- getrusage(RUSAGE_SELF, &last);
140
+ fprintf(stderr, "\nINTERNAL LONG DOUBLE PRINTING WITH PACK / UNPACK: ");
141
+ getrusage(RUSAGE_SELF, &last);
142
143
- // do the job
144
- for(j = 1; j < 11 ;j++) {
145
- n = STORAGE_NUMBER_POSITIVE_MIN * j;
143
+ // do the job
144
+ for(j = 1; j < 11 ;j++) {
145
+ n = STORAGE_NUMBER_POSITIVE_MIN * j;
146
147
- for(i = 0; i < loop ;i++) {
148
- n *= multiplier;
149
- if(n > STORAGE_NUMBER_POSITIVE_MAX) n = STORAGE_NUMBER_POSITIVE_MIN;
147
+ for(i = 0; i < loop ;i++) {
148
+ n *= multiplier;
149
+ if(n > STORAGE_NUMBER_POSITIVE_MAX) n = STORAGE_NUMBER_POSITIVE_MIN;
150
151
- s = pack_storage_number(n, 1);
152
- d = unpack_storage_number(s);
153
- print_calculated_number(buffer, d);
154
- }
155
- }
151
+ s = pack_storage_number(n, 1);
152
+ d = unpack_storage_number(s);
153
+ print_calculated_number(buffer, d);
154
+ }
155
+ }
156
157
- getrusage(RUSAGE_SELF, &now);
158
- user = now.ru_utime.tv_sec * 1000000ULL + now.ru_utime.tv_usec - last.ru_utime.tv_sec * 1000000ULL + last.ru_utime.tv_usec;
159
- system = now.ru_stime.tv_sec * 1000000ULL + now.ru_stime.tv_usec - last.ru_stime.tv_sec * 1000000ULL + last.ru_stime.tv_usec;
160
- total = user + system;
161
- mine = total;
162
-
163
- fprintf(stderr, "user %0.5Lf, system %0.5Lf, total %0.5Lf\n", (long double)(user / 1000000.0), (long double)(system / 1000000.0), (long double)(total / 1000000.0));
157
+ getrusage(RUSAGE_SELF, &now);
158
+ user = now.ru_utime.tv_sec * 1000000ULL + now.ru_utime.tv_usec - last.ru_utime.tv_sec * 1000000ULL + last.ru_utime.tv_usec;
159
+ system = now.ru_stime.tv_sec * 1000000ULL + now.ru_stime.tv_usec - last.ru_stime.tv_sec * 1000000ULL + last.ru_stime.tv_usec;
160
+ total = user + system;
161
+ mine = total;
162
+
163
+ fprintf(stderr, "user %0.5Lf, system %0.5Lf, total %0.5Lf\n", (long double)(user / 1000000.0), (long double)(system / 1000000.0), (long double)(total / 1000000.0));
164
165
- if(mine > their) {
166
- fprintf(stderr, "WITH PACKING UNPACKING NETDATA CODE IS SLOWER %0.2Lf %%\n", (long double)(mine * 100.0 / their - 100.0));
167
- }
168
- else {
169
- fprintf(stderr, "EVEN WITH PACKING AND UNPACKING, NETDATA CODE IS F A S T E R %0.2Lf %%\n", (long double)(their * 100.0 / mine - 100.0));
170
- }
165
+ if(mine > their) {
166
+ fprintf(stderr, "WITH PACKING UNPACKING NETDATA CODE IS SLOWER %0.2Lf %%\n", (long double)(mine * 100.0 / their - 100.0));
167
+ }
168
+ else {
169
+ fprintf(stderr, "EVEN WITH PACKING AND UNPACKING, NETDATA CODE IS F A S T E R %0.2Lf %%\n", (long double)(their * 100.0 / mine - 100.0));
170
+ }
171
172
- // ------------------------------------------------------------------------
172
+ // ------------------------------------------------------------------------
173
174
}
175
176
static int check_storage_number_exists() {
177
- uint32_t flags = SN_EXISTS;
178
-
179
-
180
- for(flags = 0; flags < 7 ; flags++) {
181
- if(get_storage_number_flags(flags << 24) != flags << 24) {
182
- fprintf(stderr, "Flag 0x%08x is not checked correctly. It became 0x%08x\n", flags << 24, get_storage_number_flags(flags << 24));
183
- return 1;
184
- }
185
- }
186
-
187
- flags = SN_EXISTS;
188
- calculated_number n = 0.0;
189
-
190
- storage_number s = pack_storage_number(n, flags);
191
- calculated_number d = unpack_storage_number(s);
192
- if(get_storage_number_flags(s) != flags) {
193
- fprintf(stderr, "Wrong flags. Given %08x, Got %08x!\n", flags, get_storage_number_flags(s));
194
- return 1;
195
- }
196
- if(n != d) {
197
- fprintf(stderr, "Wrong number returned. Expected " CALCULATED_NUMBER_FORMAT ", returned " CALCULATED_NUMBER_FORMAT "!\n", n, d);
198
- return 1;
199
- }
200
-
201
- return 0;
177
+ uint32_t flags = SN_EXISTS;
178
+
179
+
180
+ for(flags = 0; flags < 7 ; flags++) {
181
+ if(get_storage_number_flags(flags << 24) != flags << 24) {
182
+ fprintf(stderr, "Flag 0x%08x is not checked correctly. It became 0x%08x\n", flags << 24, get_storage_number_flags(flags << 24));
183
+ return 1;
184
+ }
185
+ }
186
+
187
+ flags = SN_EXISTS;
188
+ calculated_number n = 0.0;
189
+
190
+ storage_number s = pack_storage_number(n, flags);
191
+ calculated_number d = unpack_storage_number(s);
192
+ if(get_storage_number_flags(s) != flags) {
193
+ fprintf(stderr, "Wrong flags. Given %08x, Got %08x!\n", flags, get_storage_number_flags(s));
194
+ return 1;
195
+ }
196
+ if(n != d) {
197
+ fprintf(stderr, "Wrong number returned. Expected " CALCULATED_NUMBER_FORMAT ", returned " CALCULATED_NUMBER_FORMAT "!\n", n, d);
198
+ return 1;
199
+ }
200
+
201
+ return 0;
202
}
203
204
int unit_test_storage()
205
{
206
- if(check_storage_number_exists()) return 0;
206
+ if(check_storage_number_exists()) return 0;
207
208
- calculated_number c, a = 0;
209
- int i, j, g, r = 0;
208
+ calculated_number c, a = 0;
209
+ int i, j, g, r = 0;
210
211
- for(g = -1; g <= 1 ; g++) {
212
- a = 0;
211
+ for(g = -1; g <= 1 ; g++) {
212
+ a = 0;
213
214
- if(!g) continue;
214
+ if(!g) continue;
215
216
- for(j = 0; j < 9 ;j++) {
217
- a += 0.0000001;
218
- c = a * g;
219
- for(i = 0; i < 21 ;i++, c *= 10) {
220
- if(c > 0 && c < STORAGE_NUMBER_POSITIVE_MIN) continue;
221
- if(c < 0 && c > STORAGE_NUMBER_NEGATIVE_MAX) continue;
216
+ for(j = 0; j < 9 ;j++) {
217
+ a += 0.0000001;
218
+ c = a * g;
219
+ for(i = 0; i < 21 ;i++, c *= 10) {
220
+ if(c > 0 && c < STORAGE_NUMBER_POSITIVE_MIN) continue;
221
+ if(c < 0 && c > STORAGE_NUMBER_NEGATIVE_MAX) continue;
222
223
- if(check_storage_number(c, 1)) return 1;
224
- }
225
- }
226
- }
223
+ if(check_storage_number(c, 1)) return 1;
224
+ }
225
+ }
226
+ }
227
228
- benchmark_storage_number(1000000, 2);
229
- return r;
228
+ benchmark_storage_number(1000000, 2);
229
+ return r;
230
}
231
232
233
// --------------------------------------------------------------------------------------------------------------------
234
235
struct feed_values {
236
- unsigned long long microseconds;
237
- collected_number value;
236
+ unsigned long long microseconds;
237
+ collected_number value;
238
};
239
240
struct test {
241
- char name[100];
242
- char description[1024];
241
+ char name[100];
242
+ char description[1024];
243
244
- int update_every;
245
- unsigned long long multiplier;
246
- unsigned long long divisor;
247
- int algorithm;
244
+ int update_every;
245
+ unsigned long long multiplier;
246
+ unsigned long long divisor;
247
+ int algorithm;
248
249
- unsigned long feed_entries;
250
- unsigned long result_entries;
251
- struct feed_values *feed;
252
- calculated_number *results;
249
+ unsigned long feed_entries;
250
+ unsigned long result_entries;
251
+ struct feed_values *feed;
252
+ calculated_number *results;
253
254
- collected_number *feed2;
255
- calculated_number *results2;
254
+ collected_number *feed2;
255
+ calculated_number *results2;
256
};
257
258
// --------------------------------------------------------------------------------------------------------------------
@@ -260,35 +260,35 @@ struct test {
260
// test absolute values stored
261
262
struct feed_values test1_feed[] = {
263
- { 0, 10 },
264
- { 1000000, 20 },
265
- { 1000000, 30 },
266
- { 1000000, 40 },
267
- { 1000000, 50 },
268
- { 1000000, 60 },
269
- { 1000000, 70 },
270
- { 1000000, 80 },
271
- { 1000000, 90 },
272
- { 1000000, 100 },
263
+ { 0, 10 },
264
+ { 1000000, 20 },
265
+ { 1000000, 30 },
266
+ { 1000000, 40 },
267
+ { 1000000, 50 },
268
+ { 1000000, 60 },
269
+ { 1000000, 70 },
270
+ { 1000000, 80 },
271
+ { 1000000, 90 },
272
+ { 1000000, 100 },
273
};
274
275
calculated_number test1_results[] = {
276
- 20, 30, 40, 50, 60, 70, 80, 90, 100
276
+ 20, 30, 40, 50, 60, 70, 80, 90, 100
277
};
278
279
struct test test1 = {
280
- "test1", // name
281
- "test absolute values stored at exactly second boundaries",
282
- 1, // update_every
283
- 1, // multiplier
284
- 1, // divisor
285
- RRDDIM_ABSOLUTE, // algorithm
286
- 10, // feed entries
287
- 9, // result entries
288
- test1_feed, // feed
289
- test1_results, // results
290
- NULL, // feed2
291
- NULL // results2
280
+ "test1", // name
281
+ "test absolute values stored at exactly second boundaries",
282
+ 1, // update_every
283
+ 1, // multiplier
284
+ 1, // divisor
285
+ RRDDIM_ABSOLUTE, // algorithm
286
+ 10, // feed entries
287
+ 9, // result entries
288
+ test1_feed, // feed
289
+ test1_results, // results
290
+ NULL, // feed2
291
+ NULL // results2
292
};
293
294
// --------------------------------------------------------------------------------------------------------------------
@@ -296,667 +296,667 @@ struct test test1 = {
296
// test absolute values stored in the middle of second boundaries
297
298
struct feed_values test2_feed[] = {
299
- { 500000, 10 },
300
- { 1000000, 20 },
301
- { 1000000, 30 },
302
- { 1000000, 40 },
303
- { 1000000, 50 },
304
- { 1000000, 60 },
305
- { 1000000, 70 },
306
- { 1000000, 80 },
307
- { 1000000, 90 },
308
- { 1000000, 100 },
299
+ { 500000, 10 },
300
+ { 1000000, 20 },
301
+ { 1000000, 30 },
302
+ { 1000000, 40 },
303
+ { 1000000, 50 },
304
+ { 1000000, 60 },
305
+ { 1000000, 70 },
306
+ { 1000000, 80 },
307
+ { 1000000, 90 },
308
+ { 1000000, 100 },
309
};
310
311
calculated_number test2_results[] = {
312
- 20, 30, 40, 50, 60, 70, 80, 90, 100
312
+ 20, 30, 40, 50, 60, 70, 80, 90, 100
313
};
314
315
struct test test2 = {
316
- "test2", // name
317
- "test absolute values stored in the middle of second boundaries",
318
- 1, // update_every
319
- 1, // multiplier
320
- 1, // divisor
321
- RRDDIM_ABSOLUTE, // algorithm
322
- 10, // feed entries
323
- 9, // result entries
324
- test2_feed, // feed
325
- test2_results, // results
326
- NULL, // feed2
327
- NULL // results2
316
+ "test2", // name
317
+ "test absolute values stored in the middle of second boundaries",
318
+ 1, // update_every
319
+ 1, // multiplier
320
+ 1, // divisor
321
+ RRDDIM_ABSOLUTE, // algorithm
322
+ 10, // feed entries
323
+ 9, // result entries
324
+ test2_feed, // feed
325
+ test2_results, // results
326
+ NULL, // feed2
327
+ NULL // results2
328
};
329
330
// --------------------------------------------------------------------------------------------------------------------
331
// test3
332
333
struct feed_values test3_feed[] = {
334
- { 0, 10 },
335
- { 1000000, 20 },
336
- { 1000000, 30 },
337
- { 1000000, 40 },
338
- { 1000000, 50 },
339
- { 1000000, 60 },
340
- { 1000000, 70 },
341
- { 1000000, 80 },
342
- { 1000000, 90 },
343
- { 1000000, 100 },
334
+ { 0, 10 },
335
+ { 1000000, 20 },
336
+ { 1000000, 30 },
337
+ { 1000000, 40 },
338
+ { 1000000, 50 },
339
+ { 1000000, 60 },
340
+ { 1000000, 70 },
341
+ { 1000000, 80 },
342
+ { 1000000, 90 },
343
+ { 1000000, 100 },
344
};
345
346
calculated_number test3_results[] = {
347
- 10, 10, 10, 10, 10, 10, 10, 10, 10
347
+ 10, 10, 10, 10, 10, 10, 10, 10, 10
348
};
349
350
struct test test3 = {
351
- "test3", // name
352
- "test incremental values stored at exactly second boundaries",
353
- 1, // update_every
354
- 1, // multiplier
355
- 1, // divisor
356
- RRDDIM_INCREMENTAL, // algorithm
357
- 10, // feed entries
358
- 9, // result entries
359
- test3_feed, // feed
360
- test3_results, // results
361
- NULL, // feed2
362
- NULL // results2
351
+ "test3", // name
352
+ "test incremental values stored at exactly second boundaries",
353
+ 1, // update_every
354
+ 1, // multiplier
355
+ 1, // divisor
356
+ RRDDIM_INCREMENTAL, // algorithm
357
+ 10, // feed entries
358
+ 9, // result entries
359
+ test3_feed, // feed
360
+ test3_results, // results
361
+ NULL, // feed2
362
+ NULL // results2
363
};
364
365
// --------------------------------------------------------------------------------------------------------------------
366
// test4
367
368
struct feed_values test4_feed[] = {
369
- { 500000, 10 },
370
- { 1000000, 20 },
371
- { 1000000, 30 },
372
- { 1000000, 40 },
373
- { 1000000, 50 },
374
- { 1000000, 60 },
375
- { 1000000, 70 },
376
- { 1000000, 80 },
377
- { 1000000, 90 },
378
- { 1000000, 100 },
369
+ { 500000, 10 },
370
+ { 1000000, 20 },
371
+ { 1000000, 30 },
372
+ { 1000000, 40 },
373
+ { 1000000, 50 },
374
+ { 1000000, 60 },
375
+ { 1000000, 70 },
376
+ { 1000000, 80 },
377
+ { 1000000, 90 },
378
+ { 1000000, 100 },
379
};
380
381
calculated_number test4_results[] = {
382
- 5, 10, 10, 10, 10, 10, 10, 10, 10
382
+ 5, 10, 10, 10, 10, 10, 10, 10, 10
383
};
384
385
struct test test4 = {
386
- "test4", // name
387
- "test incremental values stored in the middle of second boundaries",
388
- 1, // update_every
389
- 1, // multiplier
390
- 1, // divisor
391
- RRDDIM_INCREMENTAL, // algorithm
392
- 10, // feed entries
393
- 9, // result entries
394
- test4_feed, // feed
395
- test4_results, // results
396
- NULL, // feed2
397
- NULL // results2
386
+ "test4", // name
387
+ "test incremental values stored in the middle of second boundaries",
388
+ 1, // update_every
389
+ 1, // multiplier
390
+ 1, // divisor
391
+ RRDDIM_INCREMENTAL, // algorithm
392
+ 10, // feed entries
393
+ 9, // result entries
394
+ test4_feed, // feed
395
+ test4_results, // results
396
+ NULL, // feed2
397
+ NULL // results2
398
};
399
400
// --------------------------------------------------------------------------------------------------------------------
401
// test5
402
403
struct feed_values test5_feed[] = {
404
- { 500000, 1000 },
405
- { 1000000, 2000 },
406
- { 1000000, 2000 },
407
- { 1000000, 2000 },
408
- { 1000000, 3000 },
409
- { 1000000, 2000 },
410
- { 1000000, 2000 },
411
- { 1000000, 2000 },
412
- { 1000000, 2000 },
413
- { 1000000, 2000 },
404
+ { 500000, 1000 },
405
+ { 1000000, 2000 },
406
+ { 1000000, 2000 },
407
+ { 1000000, 2000 },
408
+ { 1000000, 3000 },
409
+ { 1000000, 2000 },
410
+ { 1000000, 2000 },
411
+ { 1000000, 2000 },
412
+ { 1000000, 2000 },
413
+ { 1000000, 2000 },
414
};
415
416
calculated_number test5_results[] = {
417
- 500, 500, 0, 500, 500, 0, 0, 0, 0
417
+ 500, 500, 0, 500, 500, 0, 0, 0, 0
418
};
419
420
struct test test5 = {
421
- "test5", // name
422
- "test incremental values ups and downs",
423
- 1, // update_every
424
- 1, // multiplier
425
- 1, // divisor
426
- RRDDIM_INCREMENTAL, // algorithm
427
- 10, // feed entries
428
- 9, // result entries
429
- test5_feed, // feed
430
- test5_results, // results
431
- NULL, // feed2
432
- NULL // results2
421
+ "test5", // name
422
+ "test incremental values ups and downs",
423
+ 1, // update_every
424
+ 1, // multiplier
425
+ 1, // divisor
426
+ RRDDIM_INCREMENTAL, // algorithm
427
+ 10, // feed entries
428
+ 9, // result entries
429
+ test5_feed, // feed
430
+ test5_results, // results
431
+ NULL, // feed2
432
+ NULL // results2
433
};
434
435
// --------------------------------------------------------------------------------------------------------------------
436
// test6
437
438
struct feed_values test6_feed[] = {
439
- { 250000, 1000 },
440
- { 250000, 2000 },
441
- { 250000, 3000 },
442
- { 250000, 4000 },
443
- { 250000, 5000 },
444
- { 250000, 6000 },
445
- { 250000, 7000 },
446
- { 250000, 8000 },
447
- { 250000, 9000 },
448
- { 250000, 10000 },
449
- { 250000, 11000 },
450
- { 250000, 12000 },
451
- { 250000, 13000 },
452
- { 250000, 14000 },
453
- { 250000, 15000 },
454
- { 250000, 16000 },
439
+ { 250000, 1000 },
440
+ { 250000, 2000 },
441
+ { 250000, 3000 },
442
+ { 250000, 4000 },
443
+ { 250000, 5000 },
444
+ { 250000, 6000 },
445
+ { 250000, 7000 },
446
+ { 250000, 8000 },
447
+ { 250000, 9000 },
448
+ { 250000, 10000 },
449
+ { 250000, 11000 },
450
+ { 250000, 12000 },
451
+ { 250000, 13000 },
452
+ { 250000, 14000 },
453
+ { 250000, 15000 },
454
+ { 250000, 16000 },
455
};
456
457
calculated_number test6_results[] = {
458
- 3000, 4000, 4000, 4000
458
+ 3000, 4000, 4000, 4000
459
};
460
461
struct test test6 = {
462
- "test6", // name
463
- "test incremental values updated within the same second",
464
- 1, // update_every
465
- 1, // multiplier
466
- 1, // divisor
467
- RRDDIM_INCREMENTAL, // algorithm
468
- 16, // feed entries
469
- 4, // result entries
470
- test6_feed, // feed
471
- test6_results, // results
472
- NULL, // feed2
473
- NULL // results2
462
+ "test6", // name
463
+ "test incremental values updated within the same second",
464
+ 1, // update_every
465
+ 1, // multiplier
466
+ 1, // divisor
467
+ RRDDIM_INCREMENTAL, // algorithm
468
+ 16, // feed entries
469
+ 4, // result entries
470
+ test6_feed, // feed
471
+ test6_results, // results
472
+ NULL, // feed2
473
+ NULL // results2
474
};
475
476
// --------------------------------------------------------------------------------------------------------------------
477
// test7
478
479
struct feed_values test7_feed[] = {
480
- { 500000, 1000 },
481
- { 2000000, 2000 },
482
- { 2000000, 3000 },
483
- { 2000000, 4000 },
484
- { 2000000, 5000 },
485
- { 2000000, 6000 },
486
- { 2000000, 7000 },
487
- { 2000000, 8000 },
488
- { 2000000, 9000 },
489
- { 2000000, 10000 },
480
+ { 500000, 1000 },
481
+ { 2000000, 2000 },
482
+ { 2000000, 3000 },
483
+ { 2000000, 4000 },
484
+ { 2000000, 5000 },
485
+ { 2000000, 6000 },
486
+ { 2000000, 7000 },
487
+ { 2000000, 8000 },
488
+ { 2000000, 9000 },
489
+ { 2000000, 10000 },
490
};
491
492
calculated_number test7_results[] = {
493
- 250, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500
493
+ 250, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500
494
};
495
496
struct test test7 = {
497
- "test7", // name
498
- "test incremental values updated in long durations",
499
- 1, // update_every
500
- 1, // multiplier
501
- 1, // divisor
502
- RRDDIM_INCREMENTAL, // algorithm
503
- 10, // feed entries
504
- 18, // result entries
505
- test7_feed, // feed
506
- test7_results, // results
507
- NULL, // feed2
508
- NULL // results2
497
+ "test7", // name
498
+ "test incremental values updated in long durations",
499
+ 1, // update_every
500
+ 1, // multiplier
501
+ 1, // divisor
502
+ RRDDIM_INCREMENTAL, // algorithm
503
+ 10, // feed entries
504
+ 18, // result entries
505
+ test7_feed, // feed
506
+ test7_results, // results
507
+ NULL, // feed2
508
+ NULL // results2
509
};
510
511
// --------------------------------------------------------------------------------------------------------------------
512
// test8
513
514
struct feed_values test8_feed[] = {
515
- { 500000, 1000 },
516
- { 2000000, 2000 },
517
- { 2000000, 3000 },
518
- { 2000000, 4000 },
519
- { 2000000, 5000 },
520
- { 2000000, 6000 },
515
+ { 500000, 1000 },
516
+ { 2000000, 2000 },
517
+ { 2000000, 3000 },
518
+ { 2000000, 4000 },
519
+ { 2000000, 5000 },
520
+ { 2000000, 6000 },
521
};
522
523
calculated_number test8_results[] = {
524
- 1250, 2000, 2250, 3000, 3250, 4000, 4250, 5000, 5250, 6000
524
+ 1250, 2000, 2250, 3000, 3250, 4000, 4250, 5000, 5250, 6000
525
};
526
527
struct test test8 = {
528
- "test8", // name
529
- "test absolute values updated in long durations",
530
- 1, // update_every
531
- 1, // multiplier
532
- 1, // divisor
533
- RRDDIM_ABSOLUTE, // algorithm
534
- 6, // feed entries
535
- 10, // result entries
536
- test8_feed, // feed
537
- test8_results, // results
538
- NULL, // feed2
539
- NULL // results2
528
+ "test8", // name
529
+ "test absolute values updated in long durations",
530
+ 1, // update_every
531
+ 1, // multiplier
532
+ 1, // divisor
533
+ RRDDIM_ABSOLUTE, // algorithm
534
+ 6, // feed entries
535
+ 10, // result entries
536
+ test8_feed, // feed
537
+ test8_results, // results
538
+ NULL, // feed2
539
+ NULL // results2
540
};
541
542
// --------------------------------------------------------------------------------------------------------------------
543
// test9
544
545
struct feed_values test9_feed[] = {
546
- { 250000, 1000 },
547
- { 250000, 2000 },
548
- { 250000, 3000 },
549
- { 250000, 4000 },
550
- { 250000, 5000 },
551
- { 250000, 6000 },
552
- { 250000, 7000 },
553
- { 250000, 8000 },
554
- { 250000, 9000 },
555
- { 250000, 10000 },
556
- { 250000, 11000 },
557
- { 250000, 12000 },
558
- { 250000, 13000 },
559
- { 250000, 14000 },
560
- { 250000, 15000 },
561
- { 250000, 16000 },
546
+ { 250000, 1000 },
547
+ { 250000, 2000 },
548
+ { 250000, 3000 },
549
+ { 250000, 4000 },
550
+ { 250000, 5000 },
551
+ { 250000, 6000 },
552
+ { 250000, 7000 },
553
+ { 250000, 8000 },
554
+ { 250000, 9000 },
555
+ { 250000, 10000 },
556
+ { 250000, 11000 },
557
+ { 250000, 12000 },
558
+ { 250000, 13000 },
559
+ { 250000, 14000 },
560
+ { 250000, 15000 },
561
+ { 250000, 16000 },
562
};
563
564
calculated_number test9_results[] = {
565
- 4000, 8000, 12000, 16000
565
+ 4000, 8000, 12000, 16000
566
};
567
568
struct test test9 = {
569
- "test9", // name
570
- "test absolute values updated within the same second",
571
- 1, // update_every
572
- 1, // multiplier
573
- 1, // divisor
574
- RRDDIM_ABSOLUTE, // algorithm
575
- 16, // feed entries
576
- 4, // result entries
577
- test9_feed, // feed
578
- test9_results, // results
579
- NULL, // feed2
580
- NULL // results2
569
+ "test9", // name
570
+ "test absolute values updated within the same second",
571
+ 1, // update_every
572
+ 1, // multiplier
573
+ 1, // divisor
574
+ RRDDIM_ABSOLUTE, // algorithm
575
+ 16, // feed entries
576
+ 4, // result entries
577
+ test9_feed, // feed
578
+ test9_results, // results
579
+ NULL, // feed2
580
+ NULL // results2
581
};
582
583
// --------------------------------------------------------------------------------------------------------------------
584
// test10
585
586
struct feed_values test10_feed[] = {
587
- { 500000, 1000 },
588
- { 600000, 1000 + 600 },
589
- { 200000, 1600 + 200 },
590
- { 1000000, 1800 + 1000 },
591
- { 200000, 2800 + 200 },
592
- { 2000000, 3000 + 2000 },
593
- { 600000, 5000 + 600 },
594
- { 400000, 5600 + 400 },
595
- { 900000, 6000 + 900 },
596
- { 1000000, 6900 + 1000 },
587
+ { 500000, 1000 },
588
+ { 600000, 1000 + 600 },
589
+ { 200000, 1600 + 200 },
590
+ { 1000000, 1800 + 1000 },
591
+ { 200000, 2800 + 200 },
592
+ { 2000000, 3000 + 2000 },
593
+ { 600000, 5000 + 600 },
594
+ { 400000, 5600 + 400 },
595
+ { 900000, 6000 + 900 },
596
+ { 1000000, 6900 + 1000 },
597
};
598
599
calculated_number test10_results[] = {
600
- 500, 1000, 1000, 1000, 1000, 1000, 1000
600
+ 500, 1000, 1000, 1000, 1000, 1000, 1000
601
};
602
603
struct test test10 = {
604
- "test10", // name
605
- "test incremental values updated in short and long durations",
606
- 1, // update_every
607
- 1, // multiplier
608
- 1, // divisor
609
- RRDDIM_INCREMENTAL, // algorithm
610
- 10, // feed entries
611
- 7, // result entries
612
- test10_feed, // feed
613
- test10_results, // results
614
- NULL, // feed2
615
- NULL // results2
604
+ "test10", // name
605
+ "test incremental values updated in short and long durations",
606
+ 1, // update_every
607
+ 1, // multiplier
608
+ 1, // divisor
609
+ RRDDIM_INCREMENTAL, // algorithm
610
+ 10, // feed entries
611
+ 7, // result entries
612
+ test10_feed, // feed
613
+ test10_results, // results
614
+ NULL, // feed2
615
+ NULL // results2
616
};
617
618
// --------------------------------------------------------------------------------------------------------------------
619
// test11
620
621
struct feed_values test11_feed[] = {
622
- { 0, 10 },
623
- { 1000000, 20 },
624
- { 1000000, 30 },
625
- { 1000000, 40 },
626
- { 1000000, 50 },
627
- { 1000000, 60 },
628
- { 1000000, 70 },
629
- { 1000000, 80 },
630
- { 1000000, 90 },
631
- { 1000000, 100 },
622
+ { 0, 10 },
623
+ { 1000000, 20 },
624
+ { 1000000, 30 },
625
+ { 1000000, 40 },
626
+ { 1000000, 50 },
627
+ { 1000000, 60 },
628
+ { 1000000, 70 },
629
+ { 1000000, 80 },
630
+ { 1000000, 90 },
631
+ { 1000000, 100 },
632
};
633
634
collected_number test11_feed2[] = {
635
- 10, 20, 30, 40, 50, 60, 70, 80, 90, 100
635
+ 10, 20, 30, 40, 50, 60, 70, 80, 90, 100
636
};
637
638
calculated_number test11_results[] = {
639
- 50, 50, 50, 50, 50, 50, 50, 50, 50
639
+ 50, 50, 50, 50, 50, 50, 50, 50, 50
640
};
641
642
calculated_number test11_results2[] = {
643
- 50, 50, 50, 50, 50, 50, 50, 50, 50
643
+ 50, 50, 50, 50, 50, 50, 50, 50, 50
644
};
645
646
struct test test11 = {
647
- "test11", // name
648
- "test percentage-of-incremental-row with equal values",
649
- 1, // update_every
650
- 1, // multiplier
651
- 1, // divisor
652
- RRDDIM_PCENT_OVER_DIFF_TOTAL, // algorithm
653
- 10, // feed entries
654
- 9, // result entries
655
- test11_feed, // feed
656
- test11_results, // results
657
- test11_feed2, // feed2
658
- test11_results2 // results2
647
+ "test11", // name
648
+ "test percentage-of-incremental-row with equal values",
649
+ 1, // update_every
650
+ 1, // multiplier
651
+ 1, // divisor
652
+ RRDDIM_PCENT_OVER_DIFF_TOTAL, // algorithm
653
+ 10, // feed entries
654
+ 9, // result entries
655
+ test11_feed, // feed
656
+ test11_results, // results
657
+ test11_feed2, // feed2
658
+ test11_results2 // results2
659
};
660
661
// --------------------------------------------------------------------------------------------------------------------
662
// test12
663
664
struct feed_values test12_feed[] = {
665
- { 0, 10 },
666
- { 1000000, 20 },
667
- { 1000000, 30 },
668
- { 1000000, 40 },
669
- { 1000000, 50 },
670
- { 1000000, 60 },
671
- { 1000000, 70 },
672
- { 1000000, 80 },
673
- { 1000000, 90 },
674
- { 1000000, 100 },
665
+ { 0, 10 },
666
+ { 1000000, 20 },
667
+ { 1000000, 30 },
668
+ { 1000000, 40 },
669
+ { 1000000, 50 },
670
+ { 1000000, 60 },
671
+ { 1000000, 70 },
672
+ { 1000000, 80 },
673
+ { 1000000, 90 },
674
+ { 1000000, 100 },
675
};
676
677
collected_number test12_feed2[] = {
678
- 10*3, 20*3, 30*3, 40*3, 50*3, 60*3, 70*3, 80*3, 90*3, 100*3
678
+ 10*3, 20*3, 30*3, 40*3, 50*3, 60*3, 70*3, 80*3, 90*3, 100*3
679
};
680
681
calculated_number test12_results[] = {
682
- 25, 25, 25, 25, 25, 25, 25, 25, 25
682
+ 25, 25, 25, 25, 25, 25, 25, 25, 25
683
};
684
685
calculated_number test12_results2[] = {
686
- 75, 75, 75, 75, 75, 75, 75, 75, 75
686
+ 75, 75, 75, 75, 75, 75, 75, 75, 75
687
};
688
689
struct test test12 = {
690
- "test12", // name
691
- "test percentage-of-incremental-row with equal values",
692
- 1, // update_every
693
- 1, // multiplier
694
- 1, // divisor
695
- RRDDIM_PCENT_OVER_DIFF_TOTAL, // algorithm
696
- 10, // feed entries
697
- 9, // result entries
698
- test12_feed, // feed
699
- test12_results, // results
700
- test12_feed2, // feed2
701
- test12_results2 // results2
690
+ "test12", // name
691
+ "test percentage-of-incremental-row with equal values",
692
+ 1, // update_every
693
+ 1, // multiplier
694
+ 1, // divisor
695
+ RRDDIM_PCENT_OVER_DIFF_TOTAL, // algorithm
696
+ 10, // feed entries
697
+ 9, // result entries
698
+ test12_feed, // feed
699
+ test12_results, // results
700
+ test12_feed2, // feed2
701
+ test12_results2 // results2
702
};
703
704
// --------------------------------------------------------------------------------------------------------------------
705
// test13
706
707
struct feed_values test13_feed[] = {
708
- { 500000, 1000 },
709
- { 600000, 1000 + 600 },
710
- { 200000, 1600 + 200 },
711
- { 1000000, 1800 + 1000 },
712
- { 200000, 2800 + 200 },
713
- { 2000000, 3000 + 2000 },
714
- { 600000, 5000 + 600 },
715
- { 400000, 5600 + 400 },
716
- { 900000, 6000 + 900 },
717
- { 1000000, 6900 + 1000 },
708
+ { 500000, 1000 },
709
+ { 600000, 1000 + 600 },
710
+ { 200000, 1600 + 200 },
711
+ { 1000000, 1800 + 1000 },
712
+ { 200000, 2800 + 200 },
713
+ { 2000000, 3000 + 2000 },
714
+ { 600000, 5000 + 600 },
715
+ { 400000, 5600 + 400 },
716
+ { 900000, 6000 + 900 },
717
+ { 1000000, 6900 + 1000 },
718
};
719
720
calculated_number test13_results[] = {
721
- 83.3333300, 100, 100, 100, 100, 100, 100
721
+ 83.3333300, 100, 100, 100, 100, 100, 100
722
};
723
724
struct test test13 = {
725
- "test13", // name
726
- "test incremental values updated in short and long durations",
727
- 1, // update_every
728
- 1, // multiplier
729
- 1, // divisor
730
- RRDDIM_PCENT_OVER_DIFF_TOTAL, // algorithm
731
- 10, // feed entries
732
- 7, // result entries
733
- test13_feed, // feed
734
- test13_results, // results
735
- NULL, // feed2
736
- NULL // results2
725
+ "test13", // name
726
+ "test incremental values updated in short and long durations",
727
+ 1, // update_every
728
+ 1, // multiplier
729
+ 1, // divisor
730
+ RRDDIM_PCENT_OVER_DIFF_TOTAL, // algorithm
731
+ 10, // feed entries
732
+ 7, // result entries
733
+ test13_feed, // feed
734
+ test13_results, // results
735
+ NULL, // feed2
736
+ NULL // results2
737
};
738
739
// --------------------------------------------------------------------------------------------------------------------
740
741
int run_test(struct test *test)
742
{
743
- fprintf(stderr, "\nRunning test '%s':\n%s\n", test->name, test->description);
744
-
745
- rrd_memory_mode = RRD_MEMORY_MODE_RAM;
746
- rrd_update_every = test->update_every;
747
-
748
- char name[101];
749
- snprintfz(name, 100, "unittest-%s", test->name);
750
-
751
- // create the chart
752
- RRDSET *st = rrdset_create("netdata", name, name, "netdata", NULL, "Unit Testing", "a value", 1, 1, RRDSET_TYPE_LINE);
753
- RRDDIM *rd = rrddim_add(st, "dim1", NULL, test->multiplier, test->divisor, test->algorithm);
754
-
755
- RRDDIM *rd2 = NULL;
756
- if(test->feed2)
757
- rd2 = rrddim_add(st, "dim2", NULL, test->multiplier, test->divisor, test->algorithm);
758
-
759
- st->debug = 1;
760
-
761
- // feed it with the test data
762
- unsigned long c;
763
- for(c = 0; c < test->feed_entries; c++) {
764
- if(debug_flags) fprintf(stderr, "\n\n");
765
-
766
- if(c) {
767
- fprintf(stderr, " > %s: feeding position %lu, after %llu microseconds\n", test->name, c+1, test->feed[c].microseconds);
768
- rrdset_next_usec(st, test->feed[c].microseconds);
769
- }
770
- else {
771
- fprintf(stderr, " > %s: feeding position %lu\n", test->name, c+1);
772
- }
773
-
774
- fprintf(stderr, " >> %s with value " COLLECTED_NUMBER_FORMAT "\n", rd->name, test->feed[c].value);
775
- rrddim_set(st, "dim1", test->feed[c].value);
776
-
777
- if(rd2) {
778
- fprintf(stderr, " >> %s with value " COLLECTED_NUMBER_FORMAT "\n", rd2->name, test->feed2[c]);
779
- rrddim_set(st, "dim2", test->feed2[c]);
780
- }
781
-
782
- rrdset_done(st);
783
-
784
- // align the first entry to second boundary
785
- if(!c) {
786
- fprintf(stderr, " > %s: fixing first collection time to be %llu microseconds to second boundary\n", test->name, test->feed[c].microseconds);
787
- rd->last_collected_time.tv_usec = st->last_collected_time.tv_usec = st->last_updated.tv_usec = test->feed[c].microseconds;
788
- }
789
- }
790
-
791
- // check the result
792
- int errors = 0;
793
-
794
- if(st->counter != test->result_entries) {
795
- fprintf(stderr, " %s stored %lu entries, but we were expecting %lu, ### E R R O R ###\n", test->name, st->counter, test->result_entries);
796
- errors++;
797
- }
798
-
799
- unsigned long max = (st->counter < test->result_entries)?st->counter:test->result_entries;
800
- for(c = 0 ; c < max ; c++) {
801
- calculated_number v = unpack_storage_number(rd->values[c]);
802
- calculated_number n = test->results[c];
803
- int same = (roundl(v * 10000000.0) == roundl(n * 10000000.0))?1:0;
804
- fprintf(stderr, " %s/%s: checking position %lu, expecting value " CALCULATED_NUMBER_FORMAT ", found " CALCULATED_NUMBER_FORMAT ", %s\n", test->name, rd->name, c+1, n, v, (same)?"OK":"### E R R O R ###");
805
- if(!same) errors++;
806
-
807
- if(rd2) {
808
- v = unpack_storage_number(rd2->values[c]);
809
- n = test->results2[c];
810
- same = (roundl(v * 10000000.0) == roundl(n * 10000000.0))?1:0;
811
- fprintf(stderr, " %s/%s: checking position %lu, expecting value " CALCULATED_NUMBER_FORMAT ", found " CALCULATED_NUMBER_FORMAT ", %s\n", test->name, rd2->name, c+1, n, v, (same)?"OK":"### E R R O R ###");
812
- if(!same) errors++;
813
- }
814
- }
815
-
816
- return errors;
743
+ fprintf(stderr, "\nRunning test '%s':\n%s\n", test->name, test->description);
744
+
745
+ rrd_memory_mode = RRD_MEMORY_MODE_RAM;
746
+ rrd_update_every = test->update_every;
747
+
748
+ char name[101];
749
+ snprintfz(name, 100, "unittest-%s", test->name);
750
+
751
+ // create the chart
752
+ RRDSET *st = rrdset_create("netdata", name, name, "netdata", NULL, "Unit Testing", "a value", 1, 1, RRDSET_TYPE_LINE);
753
+ RRDDIM *rd = rrddim_add(st, "dim1", NULL, test->multiplier, test->divisor, test->algorithm);
754
+
755
+ RRDDIM *rd2 = NULL;
756
+ if(test->feed2)
757
+ rd2 = rrddim_add(st, "dim2", NULL, test->multiplier, test->divisor, test->algorithm);
758
+
759
+ st->debug = 1;
760
+
761
+ // feed it with the test data
762
+ unsigned long c;
763
+ for(c = 0; c < test->feed_entries; c++) {
764
+ if(debug_flags) fprintf(stderr, "\n\n");
765
+
766
+ if(c) {
767
+ fprintf(stderr, " > %s: feeding position %lu, after %llu microseconds\n", test->name, c+1, test->feed[c].microseconds);
768
+ rrdset_next_usec(st, test->feed[c].microseconds);
769
+ }
770
+ else {
771
+ fprintf(stderr, " > %s: feeding position %lu\n", test->name, c+1);
772
+ }
773
+
774
+ fprintf(stderr, " >> %s with value " COLLECTED_NUMBER_FORMAT "\n", rd->name, test->feed[c].value);
775
+ rrddim_set(st, "dim1", test->feed[c].value);
776
+
777
+ if(rd2) {
778
+ fprintf(stderr, " >> %s with value " COLLECTED_NUMBER_FORMAT "\n", rd2->name, test->feed2[c]);
779
+ rrddim_set(st, "dim2", test->feed2[c]);
780
+ }
781
+
782
+ rrdset_done(st);
783
+
784
+ // align the first entry to second boundary
785
+ if(!c) {
786
+ fprintf(stderr, " > %s: fixing first collection time to be %llu microseconds to second boundary\n", test->name, test->feed[c].microseconds);
787
+ rd->last_collected_time.tv_usec = st->last_collected_time.tv_usec = st->last_updated.tv_usec = test->feed[c].microseconds;
788
+ }
789
+ }
790
+
791
+ // check the result
792
+ int errors = 0;
793
+
794
+ if(st->counter != test->result_entries) {
795
+ fprintf(stderr, " %s stored %lu entries, but we were expecting %lu, ### E R R O R ###\n", test->name, st->counter, test->result_entries);
796
+ errors++;
797
+ }
798
+
799
+ unsigned long max = (st->counter < test->result_entries)?st->counter:test->result_entries;
800
+ for(c = 0 ; c < max ; c++) {
801
+ calculated_number v = unpack_storage_number(rd->values[c]);
802
+ calculated_number n = test->results[c];
803
+ int same = (roundl(v * 10000000.0) == roundl(n * 10000000.0))?1:0;
804
+ fprintf(stderr, " %s/%s: checking position %lu, expecting value " CALCULATED_NUMBER_FORMAT ", found " CALCULATED_NUMBER_FORMAT ", %s\n", test->name, rd->name, c+1, n, v, (same)?"OK":"### E R R O R ###");
805
+ if(!same) errors++;
806
+
807
+ if(rd2) {
808
+ v = unpack_storage_number(rd2->values[c]);
809
+ n = test->results2[c];
810
+ same = (roundl(v * 10000000.0) == roundl(n * 10000000.0))?1:0;
811
+ fprintf(stderr, " %s/%s: checking position %lu, expecting value " CALCULATED_NUMBER_FORMAT ", found " CALCULATED_NUMBER_FORMAT ", %s\n", test->name, rd2->name, c+1, n, v, (same)?"OK":"### E R R O R ###");
812
+ if(!same) errors++;
813
+ }
814
+ }
815
+
816
+ return errors;
817
}
818
819
int run_all_mockup_tests(void)
820
{
821
- if(run_test(&test1))
822
- return 1;
821
+ if(run_test(&test1))
822
+ return 1;
823
824
- if(run_test(&test2))
825
- return 1;
824
+ if(run_test(&test2))
825
+ return 1;
826
827
- if(run_test(&test3))
828
- return 1;
827
+ if(run_test(&test3))
828
+ return 1;
829
830
- if(run_test(&test4))
831
- return 1;
830
+ if(run_test(&test4))
831
+ return 1;
832
833
- if(run_test(&test5))
834
- return 1;
833
+ if(run_test(&test5))
834
+ return 1;
835
836
- if(run_test(&test6))
837
- return 1;
836
+ if(run_test(&test6))
837
+ return 1;
838
839
- if(run_test(&test7))
840
- return 1;
839
+ if(run_test(&test7))
840
+ return 1;
841
842
- if(run_test(&test8))
843
- return 1;
842
+ if(run_test(&test8))
843
+ return 1;
844
845
- if(run_test(&test9))
846
- return 1;
845
+ if(run_test(&test9))
846
+ return 1;
847
848
- if(run_test(&test10))
849
- return 1;
848
+ if(run_test(&test10))
849
+ return 1;
850
851
- if(run_test(&test11))
852
- return 1;
851
+ if(run_test(&test11))
852
+ return 1;
853
854
- if(run_test(&test12))
855
- return 1;
854
+ if(run_test(&test12))
855
+ return 1;
856
857
- if(run_test(&test13))
858
- return 1;
857
+ if(run_test(&test13))
858
+ return 1;
859
860
- return 0;
860
+ return 0;
861
}
862
863
int unit_test(long delay, long shift)
864
{
865
- static int repeat = 0;
866
- repeat++;
867
-
868
- char name[101];
869
- snprintfz(name, 100, "unittest-%d-%ld-%ld", repeat, delay, shift);
870
-
871
- //debug_flags = 0xffffffff;
872
- rrd_memory_mode = RRD_MEMORY_MODE_RAM;
873
- rrd_update_every = 1;
874
-
875
- int do_abs = 1;
876
- int do_inc = 1;
877
- int do_abst = 0;
878
- int do_absi = 0;
879
-
880
- RRDSET *st = rrdset_create("netdata", name, name, "netdata", NULL, "Unit Testing", "a value", 1, 1, RRDSET_TYPE_LINE);
881
- st->debug = 1;
882
-
883
- RRDDIM *rdabs = NULL;
884
- RRDDIM *rdinc = NULL;
885
- RRDDIM *rdabst = NULL;
886
- RRDDIM *rdabsi = NULL;
887
-
888
- if(do_abs) rdabs = rrddim_add(st, "absolute", "absolute", 1, 1, RRDDIM_ABSOLUTE);
889
- if(do_inc) rdinc = rrddim_add(st, "incremental", "incremental", 1, 1, RRDDIM_INCREMENTAL);
890
- if(do_abst) rdabst = rrddim_add(st, "percentage-of-absolute-row", "percentage-of-absolute-row", 1, 1, RRDDIM_PCENT_OVER_ROW_TOTAL);
891
- if(do_absi) rdabsi = rrddim_add(st, "percentage-of-incremental-row", "percentage-of-incremental-row", 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
892
-
893
- long increment = 1000;
894
- collected_number i = 0;
895
-
896
- unsigned long c, dimensions = 0;
897
- RRDDIM *rd;
898
- for(rd = st->dimensions ; rd ; rd = rd->next) dimensions++;
899
-
900
- for(c = 0; c < 20 ;c++) {
901
- i += increment;
902
-
903
- fprintf(stderr, "\n\nLOOP = %lu, DELAY = %ld, VALUE = " COLLECTED_NUMBER_FORMAT "\n", c, delay, i);
904
- if(c) {
905
- rrdset_next_usec(st, delay);
906
- }
907
- if(do_abs) rrddim_set(st, "absolute", i);
908
- if(do_inc) rrddim_set(st, "incremental", i);
909
- if(do_abst) rrddim_set(st, "percentage-of-absolute-row", i);
910
- if(do_absi) rrddim_set(st, "percentage-of-incremental-row", i);
911
-
912
- if(!c) {
913
- gettimeofday(&st->last_collected_time, NULL);
914
- st->last_collected_time.tv_usec = shift;
915
- }
916
-
917
- // prevent it from deleting the dimensions
918
- for(rd = st->dimensions ; rd ; rd = rd->next)
919
- rd->last_collected_time.tv_sec = st->last_collected_time.tv_sec;
920
-
921
- rrdset_done(st);
922
- }
923
-
924
- unsigned long oincrement = increment;
925
- increment = increment * st->update_every * 1000000 / delay;
926
- fprintf(stderr, "\n\nORIGINAL INCREMENT: %lu, INCREMENT %ld, DELAY %ld, SHIFT %ld\n", oincrement * 10, increment * 10, delay, shift);
927
-
928
- int ret = 0;
929
- storage_number sn;
930
- calculated_number cn, v;
931
- for(c = 0 ; c < st->counter ; c++) {
932
- fprintf(stderr, "\nPOSITION: c = %lu, EXPECTED VALUE %lu\n", c, (oincrement + c * increment + increment * (1000000 - shift) / 1000000 )* 10);
933
-
934
- for(rd = st->dimensions ; rd ; rd = rd->next) {
935
- sn = rd->values[c];
936
- cn = unpack_storage_number(sn);
937
- fprintf(stderr, "\t %s " CALCULATED_NUMBER_FORMAT " (PACKED AS " STORAGE_NUMBER_FORMAT ") -> ", rd->id, cn, sn);
938
-
939
- if(rd == rdabs) v =
940
- ( oincrement
941
- // + (increment * (1000000 - shift) / 1000000)
942
- + (c + 1) * increment
943
- );
944
-
945
- else if(rd == rdinc) v = (c?(increment):(increment * (1000000 - shift) / 1000000));
946
- else if(rd == rdabst) v = oincrement / dimensions / 10;
947
- else if(rd == rdabsi) v = oincrement / dimensions / 10;
948
- else v = 0;
949
-
950
- if(v == cn) fprintf(stderr, "passed.\n");
951
- else {
952
- fprintf(stderr, "ERROR! (expected " CALCULATED_NUMBER_FORMAT ")\n", v);
953
- ret = 1;
954
- }
955
- }
956
- }
957
-
958
- if(ret)
959
- fprintf(stderr, "\n\nUNIT TEST(%ld, %ld) FAILED\n\n", delay, shift);
960
-
961
- return ret;
865
+ static int repeat = 0;
866
+ repeat++;
867
+
868
+ char name[101];
869
+ snprintfz(name, 100, "unittest-%d-%ld-%ld", repeat, delay, shift);
870
+
871
+ //debug_flags = 0xffffffff;
872
+ rrd_memory_mode = RRD_MEMORY_MODE_RAM;
873
+ rrd_update_every = 1;
874
+
875
+ int do_abs = 1;
876
+ int do_inc = 1;
877
+ int do_abst = 0;
878
+ int do_absi = 0;
879
+
880
+ RRDSET *st = rrdset_create("netdata", name, name, "netdata", NULL, "Unit Testing", "a value", 1, 1, RRDSET_TYPE_LINE);
881
+ st->debug = 1;
882
+
883
+ RRDDIM *rdabs = NULL;
884
+ RRDDIM *rdinc = NULL;
885
+ RRDDIM *rdabst = NULL;
886
+ RRDDIM *rdabsi = NULL;
887
+
888
+ if(do_abs) rdabs = rrddim_add(st, "absolute", "absolute", 1, 1, RRDDIM_ABSOLUTE);
889
+ if(do_inc) rdinc = rrddim_add(st, "incremental", "incremental", 1, 1, RRDDIM_INCREMENTAL);
890
+ if(do_abst) rdabst = rrddim_add(st, "percentage-of-absolute-row", "percentage-of-absolute-row", 1, 1, RRDDIM_PCENT_OVER_ROW_TOTAL);
891
+ if(do_absi) rdabsi = rrddim_add(st, "percentage-of-incremental-row", "percentage-of-incremental-row", 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
892
+
893
+ long increment = 1000;
894
+ collected_number i = 0;
895
+
896
+ unsigned long c, dimensions = 0;
897
+ RRDDIM *rd;
898
+ for(rd = st->dimensions ; rd ; rd = rd->next) dimensions++;
899
+
900
+ for(c = 0; c < 20 ;c++) {
901
+ i += increment;
902
+
903
+ fprintf(stderr, "\n\nLOOP = %lu, DELAY = %ld, VALUE = " COLLECTED_NUMBER_FORMAT "\n", c, delay, i);
904
+ if(c) {
905
+ rrdset_next_usec(st, delay);
906
+ }
907
+ if(do_abs) rrddim_set(st, "absolute", i);
908
+ if(do_inc) rrddim_set(st, "incremental", i);
909
+ if(do_abst) rrddim_set(st, "percentage-of-absolute-row", i);
910
+ if(do_absi) rrddim_set(st, "percentage-of-incremental-row", i);
911
+
912
+ if(!c) {
913
+ gettimeofday(&st->last_collected_time, NULL);
914
+ st->last_collected_time.tv_usec = shift;
915
+ }
916
+
917
+ // prevent it from deleting the dimensions
918
+ for(rd = st->dimensions ; rd ; rd = rd->next)
919
+ rd->last_collected_time.tv_sec = st->last_collected_time.tv_sec;
920
+
921
+ rrdset_done(st);
922
+ }
923
+
924
+ unsigned long oincrement = increment;
925
+ increment = increment * st->update_every * 1000000 / delay;
926
+ fprintf(stderr, "\n\nORIGINAL INCREMENT: %lu, INCREMENT %ld, DELAY %ld, SHIFT %ld\n", oincrement * 10, increment * 10, delay, shift);
927
+
928
+ int ret = 0;
929
+ storage_number sn;
930
+ calculated_number cn, v;
931
+ for(c = 0 ; c < st->counter ; c++) {
932
+ fprintf(stderr, "\nPOSITION: c = %lu, EXPECTED VALUE %lu\n", c, (oincrement + c * increment + increment * (1000000 - shift) / 1000000 )* 10);
933
+
934
+ for(rd = st->dimensions ; rd ; rd = rd->next) {
935
+ sn = rd->values[c];
936
+ cn = unpack_storage_number(sn);
937
+ fprintf(stderr, "\t %s " CALCULATED_NUMBER_FORMAT " (PACKED AS " STORAGE_NUMBER_FORMAT ") -> ", rd->id, cn, sn);
938
+
939
+ if(rd == rdabs) v =
940
+ ( oincrement
941
+ // + (increment * (1000000 - shift) / 1000000)
942
+ + (c + 1) * increment
943
+ );
944
+
945
+ else if(rd == rdinc) v = (c?(increment):(increment * (1000000 - shift) / 1000000));
946
+ else if(rd == rdabst) v = oincrement / dimensions / 10;
947
+ else if(rd == rdabsi) v = oincrement / dimensions / 10;
948
+ else v = 0;
949
+
950
+ if(v == cn) fprintf(stderr, "passed.\n");
951
+ else {
952
+ fprintf(stderr, "ERROR! (expected " CALCULATED_NUMBER_FORMAT ")\n", v);
953
+ ret = 1;
954
+ }
955
+ }
956
+ }
957
+
958
+ if(ret)
959
+ fprintf(stderr, "\n\nUNIT TEST(%ld, %ld) FAILED\n\n", delay, shift);
960
+
961
+ return ret;
962
}
src/url.c
+39
-39
@@ -6,72 +6,72 @@
6
7
/* Converts a hex character to its integer value */
8
char from_hex(char ch) {
9
- return (char)(isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10);
9
+ return (char)(isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10);
10
}
11
12
/* Converts an integer value to its hex character*/
13
char to_hex(char code) {
14
- static char hex[] = "0123456789abcdef";
15
- return hex[code & 15];
14
+ static char hex[] = "0123456789abcdef";
15
+ return hex[code & 15];
16
}
17
18
/* Returns a url-encoded version of str */
19
/* IMPORTANT: be sure to free() the returned string after use */
20
char *url_encode(char *str) {
21
- char *buf, *pbuf;
21
+ char *buf, *pbuf;
22
23
- pbuf = buf = mallocz(strlen(str) * 3 + 1);
23
+ pbuf = buf = mallocz(strlen(str) * 3 + 1);
24
25
- while (*str) {
26
- if (isalnum(*str) || *str == '-' || *str == '_' || *str == '.' || *str == '~')
27
- *pbuf++ = *str;
25
+ while (*str) {
26
+ if (isalnum(*str) || *str == '-' || *str == '_' || *str == '.' || *str == '~')
27
+ *pbuf++ = *str;
28
29
- else if (*str == ' ')
30
- *pbuf++ = '+';
29
+ else if (*str == ' ')
30
+ *pbuf++ = '+';
31
32
- else
33
- *pbuf++ = '%', *pbuf++ = to_hex(*str >> 4), *pbuf++ = to_hex(*str & 15);
32
+ else
33
+ *pbuf++ = '%', *pbuf++ = to_hex(*str >> 4), *pbuf++ = to_hex(*str & 15);
34
35
- str++;
36
- }
37
- *pbuf = '\0';
35
+ str++;
36
+ }
37
+ *pbuf = '\0';
38
39
- pbuf = strdupz(buf);
40
- freez(buf);
41
- return pbuf;
39
+ pbuf = strdupz(buf);
40
+ freez(buf);
41
+ return pbuf;
42
}
43
44
/* Returns a url-decoded version of str */
45
/* IMPORTANT: be sure to free() the returned string after use */
46
char *url_decode(char *str) {
47
- size_t size = strlen(str) + 1;
47
+ size_t size = strlen(str) + 1;
48
49
- char *buf = mallocz(size);
50
- return url_decode_r(buf, str, size);
49
+ char *buf = mallocz(size);
50
+ return url_decode_r(buf, str, size);
51
}
52
53
char *url_decode_r(char *to, char *url, size_t size) {
54
- char *s = url, // source
55
- *d = to, // destination
56
- *e = &to[size - 1]; // destination end
54
+ char *s = url, // source
55
+ *d = to, // destination
56
+ *e = &to[size - 1]; // destination end
57
58
- while(*s && d < e) {
59
- if(unlikely(*s == '%')) {
60
- if(likely(s[1] && s[2])) {
61
- *d++ = from_hex(s[1]) << 4 | from_hex(s[2]);
62
- s += 2;
63
- }
64
- }
65
- else if(unlikely(*s == '+'))
66
- *d++ = ' ';
58
+ while(*s && d < e) {
59
+ if(unlikely(*s == '%')) {
60
+ if(likely(s[1] && s[2])) {
61
+ *d++ = from_hex(s[1]) << 4 | from_hex(s[2]);
62
+ s += 2;
63
+ }
64
+ }
65
+ else if(unlikely(*s == '+'))
66
+ *d++ = ' ';
67
68
- else
69
- *d++ = *s;
68
+ else
69
+ *d++ = *s;
70
71
- s++;
72
- }
71
+ s++;
72
+ }
73
74
- *d = '\0';
74
+ *d = '\0';
75
76
- return to;
76
+ return to;
77
}
src/web_buffer.c
+163
-163
@@ -4,8 +4,8 @@
4
5
static inline void buffer_overflow_init(BUFFER *b)
6
{
7
- b->buffer[b->size] = '\0';
8
- strcpy(&b->buffer[b->size + 1], BUFFER_OVERFLOW_EOF);
7
+ b->buffer[b->size] = '\0';
8
+ strcpy(&b->buffer[b->size + 1], BUFFER_OVERFLOW_EOF);
9
}
10
11
#ifdef NETDATA_INTERNAL_CHECKS
@@ -16,49 +16,49 @@ static inline void buffer_overflow_init(BUFFER *b)
16
17
static inline void _buffer_overflow_check(BUFFER *b, const char *file, const char *function, const unsigned long line)
18
{
19
- if(b->len > b->size) {
20
- error("BUFFER: length %zu is above size %zu, at line %lu, at function %s() of file '%s'.", b->len, b->size, line, function, file);
21
- b->len = b->size;
22
- }
23
-
24
- if(b->buffer[b->size] != '\0' || strcmp(&b->buffer[b->size + 1], BUFFER_OVERFLOW_EOF)) {
25
- error("BUFFER: detected overflow at line %lu, at function %s() of file '%s'.", line, function, file);
26
- buffer_overflow_init(b);
27
- }
19
+ if(b->len > b->size) {
20
+ error("BUFFER: length %zu is above size %zu, at line %lu, at function %s() of file '%s'.", b->len, b->size, line, function, file);
21
+ b->len = b->size;
22
+ }
23
+
24
+ if(b->buffer[b->size] != '\0' || strcmp(&b->buffer[b->size + 1], BUFFER_OVERFLOW_EOF)) {
25
+ error("BUFFER: detected overflow at line %lu, at function %s() of file '%s'.", line, function, file);
26
+ buffer_overflow_init(b);
27
+ }
28
}
29
30
31
void buffer_reset(BUFFER *wb)
32
{
33
- buffer_flush(wb);
33
+ buffer_flush(wb);
34
35
- wb->contenttype = CT_TEXT_PLAIN;
36
- wb->options = 0;
37
- wb->date = 0;
35
+ wb->contenttype = CT_TEXT_PLAIN;
36
+ wb->options = 0;
37
+ wb->date = 0;
38
39
- buffer_overflow_check(wb);
39
+ buffer_overflow_check(wb);
40
}
41
42
const char *buffer_tostring(BUFFER *wb)
43
{
44
- buffer_need_bytes(wb, 1);
45
- wb->buffer[wb->len] = '\0';
44
+ buffer_need_bytes(wb, 1);
45
+ wb->buffer[wb->len] = '\0';
46
47
- buffer_overflow_check(wb);
47
+ buffer_overflow_check(wb);
48
49
- return(wb->buffer);
49
+ return(wb->buffer);
50
}
51
52
void buffer_char_replace(BUFFER *wb, char from, char to)
53
{
54
- char *s = wb->buffer, *end = &wb->buffer[wb->len];
54
+ char *s = wb->buffer, *end = &wb->buffer[wb->len];
55
56
- while(s != end) {
57
- if(*s == from) *s = to;
58
- s++;
59
- }
56
+ while(s != end) {
57
+ if(*s == from) *s = to;
58
+ s++;
59
+ }
60
61
- buffer_overflow_check(wb);
61
+ buffer_overflow_check(wb);
62
}
63
64
// This trick seems to give an 80% speed increase in 32bit systems
@@ -67,171 +67,171 @@ void buffer_char_replace(BUFFER *wb, char from, char to)
67
// print_calculated_number_lu_r() to print the rest with 32 bit arithmetic.
68
69
inline char *print_number_lu_r(char *str, unsigned long uvalue) {
70
- char *wstr = str;
70
+ char *wstr = str;
71
72
- // print each digit
73
- do *wstr++ = (char)('0' + (uvalue % 10)); while(uvalue /= 10);
74
- return wstr;
72
+ // print each digit
73
+ do *wstr++ = (char)('0' + (uvalue % 10)); while(uvalue /= 10);
74
+ return wstr;
75
}
76
77
inline char *print_number_llu_r(char *str, unsigned long long uvalue) {
78
- char *wstr = str;
78
+ char *wstr = str;
79
80
- // print each digit
81
- do *wstr++ = (char)('0' + (uvalue % 10)); while((uvalue /= 10) && uvalue > (unsigned long long)0xffffffff);
82
- if(uvalue) return print_number_lu_r(wstr, uvalue);
83
- return wstr;
80
+ // print each digit
81
+ do *wstr++ = (char)('0' + (uvalue % 10)); while((uvalue /= 10) && uvalue > (unsigned long long)0xffffffff);
82
+ if(uvalue) return print_number_lu_r(wstr, uvalue);
83
+ return wstr;
84
}
85
86
void buffer_print_llu(BUFFER *wb, unsigned long long uvalue)
87
{
88
- buffer_need_bytes(wb, 50);
88
+ buffer_need_bytes(wb, 50);
89
90
- char *str = &wb->buffer[wb->len];
91
- char *wstr = str;
90
+ char *str = &wb->buffer[wb->len];
91
+ char *wstr = str;
92
93
#ifdef ENVIRONMENT32
94
- if(uvalue > (unsigned long long)0xffffffff)
95
- wstr = print_number_llu_r(wstr, uvalue);
96
- else
97
- wstr = print_number_lu_r(wstr, uvalue);
94
+ if(uvalue > (unsigned long long)0xffffffff)
95
+ wstr = print_number_llu_r(wstr, uvalue);
96
+ else
97
+ wstr = print_number_lu_r(wstr, uvalue);
98
#else
99
- do *wstr++ = (char)('0' + (uvalue % 10)); while(uvalue /= 10);
99
+ do *wstr++ = (char)('0' + (uvalue % 10)); while(uvalue /= 10);
100
#endif
101
102
- // terminate it
103
- *wstr = '\0';
102
+ // terminate it
103
+ *wstr = '\0';
104
105
- // reverse it
106
- char *begin = str, *end = wstr - 1, aux;
107
- while (end > begin) aux = *end, *end-- = *begin, *begin++ = aux;
105
+ // reverse it
106
+ char *begin = str, *end = wstr - 1, aux;
107
+ while (end > begin) aux = *end, *end-- = *begin, *begin++ = aux;
108
109
- // return the buffer length
110
- wb->len += wstr - str;
109
+ // return the buffer length
110
+ wb->len += wstr - str;
111
}
112
113
void buffer_strcat(BUFFER *wb, const char *txt)
114
{
115
- if(unlikely(!txt || !*txt)) return;
116
-
117
- buffer_need_bytes(wb, 1);
118
-
119
- char *s = &wb->buffer[wb->len], *start, *end = &wb->buffer[wb->size];
120
- long len = wb->len;
121
-
122
- start = s;
123
- while(*txt && s != end)
124
- *s++ = *txt++;
125
-
126
- len += s - start;
127
-
128
- wb->len = len;
129
- buffer_overflow_check(wb);
130
-
131
- if(*txt) {
132
- debug(D_WEB_BUFFER, "strcat(): increasing web_buffer at position %zu, size = %zu\n", wb->len, wb->size);
133
- len = strlen(txt);
134
- buffer_increase(wb, len);
135
- buffer_strcat(wb, txt);
136
- }
137
- else {
138
- // terminate the string
139
- // without increasing the length
140
- buffer_need_bytes(wb, (size_t)1);
141
- wb->buffer[wb->len] = '\0';
142
- }
115
+ if(unlikely(!txt || !*txt)) return;
116
+
117
+ buffer_need_bytes(wb, 1);
118
+
119
+ char *s = &wb->buffer[wb->len], *start, *end = &wb->buffer[wb->size];
120
+ long len = wb->len;
121
+
122
+ start = s;
123
+ while(*txt && s != end)
124
+ *s++ = *txt++;
125
+
126
+ len += s - start;
127
+
128
+ wb->len = len;
129
+ buffer_overflow_check(wb);
130
+
131
+ if(*txt) {
132
+ debug(D_WEB_BUFFER, "strcat(): increasing web_buffer at position %zu, size = %zu\n", wb->len, wb->size);
133
+ len = strlen(txt);
134
+ buffer_increase(wb, len);
135
+ buffer_strcat(wb, txt);
136
+ }
137
+ else {
138
+ // terminate the string
139
+ // without increasing the length
140
+ buffer_need_bytes(wb, (size_t)1);
141
+ wb->buffer[wb->len] = '\0';
142
+ }
143
}
144
145
146
void buffer_snprintf(BUFFER *wb, size_t len, const char *fmt, ...)
147
{
148
- if(unlikely(!fmt || !*fmt)) return;
148
+ if(unlikely(!fmt || !*fmt)) return;
149
150
- buffer_need_bytes(wb, len + 1);
150
+ buffer_need_bytes(wb, len + 1);
151
152
- va_list args;
153
- va_start(args, fmt);
154
- wb->len += vsnprintfz(&wb->buffer[wb->len], len, fmt, args);
155
- va_end(args);
152
+ va_list args;
153
+ va_start(args, fmt);
154
+ wb->len += vsnprintfz(&wb->buffer[wb->len], len, fmt, args);
155
+ va_end(args);
156
157
- buffer_overflow_check(wb);
157
+ buffer_overflow_check(wb);
158
159
- // the buffer is \0 terminated by vsnprintfz
159
+ // the buffer is \0 terminated by vsnprintfz
160
}
161
162
void buffer_vsprintf(BUFFER *wb, const char *fmt, va_list args)
163
{
164
- if(unlikely(!fmt || !*fmt)) return;
164
+ if(unlikely(!fmt || !*fmt)) return;
165
166
- buffer_need_bytes(wb, 2);
166
+ buffer_need_bytes(wb, 2);
167
168
- size_t len = wb->size - wb->len - 1;
168
+ size_t len = wb->size - wb->len - 1;
169
170
- wb->len += vsnprintfz(&wb->buffer[wb->len], len, fmt, args);
170
+ wb->len += vsnprintfz(&wb->buffer[wb->len], len, fmt, args);
171
172
- buffer_overflow_check(wb);
172
+ buffer_overflow_check(wb);
173
174
- // the buffer is \0 terminated by vsnprintfz
174
+ // the buffer is \0 terminated by vsnprintfz
175
}
176
177
void buffer_sprintf(BUFFER *wb, const char *fmt, ...)
178
{
179
- if(unlikely(!fmt || !*fmt)) return;
179
+ if(unlikely(!fmt || !*fmt)) return;
180
181
- buffer_need_bytes(wb, 2);
181
+ buffer_need_bytes(wb, 2);
182
183
- size_t len = wb->size - wb->len - 1;
184
- size_t wrote;
183
+ size_t len = wb->size - wb->len - 1;
184
+ size_t wrote;
185
186
- va_list args;
187
- va_start(args, fmt);
188
- wrote = (size_t) vsnprintfz(&wb->buffer[wb->len], len, fmt, args);
189
- va_end(args);
186
+ va_list args;
187
+ va_start(args, fmt);
188
+ wrote = (size_t) vsnprintfz(&wb->buffer[wb->len], len, fmt, args);
189
+ va_end(args);
190
191
- if(unlikely(wrote >= len)) {
192
- // there is bug in vsnprintf() and it returns
193
- // a number higher to len, but it does not
194
- // overflow the buffer.
195
- // our buffer overflow detector will log it
196
- // if it does.
197
- buffer_overflow_check(wb);
191
+ if(unlikely(wrote >= len)) {
192
+ // there is bug in vsnprintf() and it returns
193
+ // a number higher to len, but it does not
194
+ // overflow the buffer.
195
+ // our buffer overflow detector will log it
196
+ // if it does.
197
+ buffer_overflow_check(wb);
198
199
- debug(D_WEB_BUFFER, "web_buffer_sprintf(): increasing web_buffer at position %zu, size = %zu\n", wb->len, wb->size);
200
- buffer_need_bytes(wb, len + WEB_DATA_LENGTH_INCREASE_STEP);
199
+ debug(D_WEB_BUFFER, "web_buffer_sprintf(): increasing web_buffer at position %zu, size = %zu\n", wb->len, wb->size);
200
+ buffer_need_bytes(wb, len + WEB_DATA_LENGTH_INCREASE_STEP);
201
202
- va_start(args, fmt);
203
- buffer_vsprintf(wb, fmt, args);
204
- va_end(args);
205
- }
206
- else
207
- wb->len += wrote;
202
+ va_start(args, fmt);
203
+ buffer_vsprintf(wb, fmt, args);
204
+ va_end(args);
205
+ }
206
+ else
207
+ wb->len += wrote;
208
209
- // the buffer is \0 terminated by vsnprintf
209
+ // the buffer is \0 terminated by vsnprintf
210
}
211
212
213
void buffer_rrd_value(BUFFER *wb, calculated_number value)
214
{
215
- buffer_need_bytes(wb, 50);
216
- wb->len += print_calculated_number(&wb->buffer[wb->len], value);
215
+ buffer_need_bytes(wb, 50);
216
+ wb->len += print_calculated_number(&wb->buffer[wb->len], value);
217
218
- // terminate it
219
- buffer_need_bytes(wb, 1);
220
- wb->buffer[wb->len] = '\0';
218
+ // terminate it
219
+ buffer_need_bytes(wb, 1);
220
+ wb->buffer[wb->len] = '\0';
221
222
- buffer_overflow_check(wb);
222
+ buffer_overflow_check(wb);
223
}
224
225
// generate a javascript date, the fastest possible way...
226
void buffer_jsdate(BUFFER *wb, int year, int month, int day, int hours, int minutes, int seconds)
227
{
228
// 10 20 30 = 35
229
- // 01234567890123456789012345678901234
230
- // Date(2014,04,01,03,28,20)
229
+ // 01234567890123456789012345678901234
230
+ // Date(2014,04,01,03,28,20)
231
232
- buffer_need_bytes(wb, 30);
232
+ buffer_need_bytes(wb, 30);
233
234
- char *b = &wb->buffer[wb->len], *p;
234
+ char *b = &wb->buffer[wb->len], *p;
235
unsigned int *q = (unsigned int *)b;
236
237
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
@@ -270,23 +270,23 @@ void buffer_jsdate(BUFFER *wb, int year, int month, int day, int hours, int minu
270
*r++ = 0x2900; // ")\0"
271
#endif
272
273
- wb->len += (size_t)((char *)r - b - 1);
273
+ wb->len += (size_t)((char *)r - b - 1);
274
275
- // terminate it
276
- wb->buffer[wb->len] = '\0';
277
- buffer_overflow_check(wb);
275
+ // terminate it
276
+ wb->buffer[wb->len] = '\0';
277
+ buffer_overflow_check(wb);
278
}
279
280
// generate a date, the fastest possible way...
281
void buffer_date(BUFFER *wb, int year, int month, int day, int hours, int minutes, int seconds)
282
{
283
- // 10 20 30 = 35
284
- // 01234567890123456789012345678901234
285
- // 2014-04-01 03:28:20
283
+ // 10 20 30 = 35
284
+ // 01234567890123456789012345678901234
285
+ // 2014-04-01 03:28:20
286
287
- buffer_need_bytes(wb, 36);
287
+ buffer_need_bytes(wb, 36);
288
289
- char *b = &wb->buffer[wb->len];
289
+ char *b = &wb->buffer[wb->len];
290
char *p = b;
291
292
*p++ = '0' + year / 1000; year %= 1000;
@@ -310,56 +310,56 @@ void buffer_date(BUFFER *wb, int year, int month, int day, int hours, int minute
310
*p++ = '0' + seconds % 10;
311
*p = '\0';
312
313
- wb->len += (size_t)(p - b);
313
+ wb->len += (size_t)(p - b);
314
315
- // terminate it
316
- wb->buffer[wb->len] = '\0';
317
- buffer_overflow_check(wb);
315
+ // terminate it
316
+ wb->buffer[wb->len] = '\0';
317
+ buffer_overflow_check(wb);
318
}
319
320
BUFFER *buffer_create(size_t size)
321
{
322
- BUFFER *b;
322
+ BUFFER *b;
323
324
- debug(D_WEB_BUFFER, "Creating new web buffer of size %zu.", size);
324
+ debug(D_WEB_BUFFER, "Creating new web buffer of size %zu.", size);
325
326
- b = callocz(1, sizeof(BUFFER));
327
- b->buffer = mallocz(size + sizeof(BUFFER_OVERFLOW_EOF) + 2);
328
- b->buffer[0] = '\0';
329
- b->size = size;
330
- b->contenttype = CT_TEXT_PLAIN;
331
- buffer_overflow_init(b);
332
- buffer_overflow_check(b);
326
+ b = callocz(1, sizeof(BUFFER));
327
+ b->buffer = mallocz(size + sizeof(BUFFER_OVERFLOW_EOF) + 2);
328
+ b->buffer[0] = '\0';
329
+ b->size = size;
330
+ b->contenttype = CT_TEXT_PLAIN;
331
+ buffer_overflow_init(b);
332
+ buffer_overflow_check(b);
333
334
- return(b);
334
+ return(b);
335
}
336
337
void buffer_free(BUFFER *b)
338
{
339
- buffer_overflow_check(b);
339
+ buffer_overflow_check(b);
340
341
- debug(D_WEB_BUFFER, "Freeing web buffer of size %zu.", b->size);
341
+ debug(D_WEB_BUFFER, "Freeing web buffer of size %zu.", b->size);
342
343
- freez(b->buffer);
344
- freez(b);
343
+ freez(b->buffer);
344
+ freez(b);
345
}
346
347
void buffer_increase(BUFFER *b, size_t free_size_required)
348
{
349
- buffer_overflow_check(b);
349
+ buffer_overflow_check(b);
350
351
- size_t left = b->size - b->len;
351
+ size_t left = b->size - b->len;
352
353
- if(left >= free_size_required) return;
353
+ if(left >= free_size_required) return;
354
355
- size_t increase = free_size_required - left;
356
- if(increase < WEB_DATA_LENGTH_INCREASE_STEP) increase = WEB_DATA_LENGTH_INCREASE_STEP;
355
+ size_t increase = free_size_required - left;
356
+ if(increase < WEB_DATA_LENGTH_INCREASE_STEP) increase = WEB_DATA_LENGTH_INCREASE_STEP;
357
358
- debug(D_WEB_BUFFER, "Increasing data buffer from size %zu to %zu.", b->size, b->size + increase);
358
+ debug(D_WEB_BUFFER, "Increasing data buffer from size %zu to %zu.", b->size, b->size + increase);
359
360
- b->buffer = reallocz(b->buffer, b->size + increase + sizeof(BUFFER_OVERFLOW_EOF) + 2);
361
- b->size += increase;
360
+ b->buffer = reallocz(b->buffer, b->size + increase + sizeof(BUFFER_OVERFLOW_EOF) + 2);
361
+ b->size += increase;
362
363
- buffer_overflow_init(b);
364
- buffer_overflow_check(b);
363
+ buffer_overflow_init(b);
364
+ buffer_overflow_check(b);
365
}
src/web_buffer.h
+29
-29
@@ -4,40 +4,40 @@
4
#define WEB_DATA_LENGTH_INCREASE_STEP 1024
5
6
typedef struct web_buffer {
7
- size_t size; // allocation size of buffer
8
- size_t len; // current data length in buffer
9
- char *buffer; // the buffer
10
- uint8_t contenttype;
11
- uint8_t options;
12
- time_t date; // the date this content has been generated
7
+ size_t size; // allocation size of buffer
8
+ size_t len; // current data length in buffer
9
+ char *buffer; // the buffer
10
+ uint8_t contenttype;
11
+ uint8_t options;
12
+ time_t date; // the date this content has been generated
13
} BUFFER;
14
15
// options
16
-#define WB_CONTENT_CACHEABLE 1
17
-#define WB_CONTENT_NO_CACHEABLE 2
16
+#define WB_CONTENT_CACHEABLE 1
17
+#define WB_CONTENT_NO_CACHEABLE 2
18
19
// content-types
20
-#define CT_APPLICATION_JSON 1
21
-#define CT_TEXT_PLAIN 2
22
-#define CT_TEXT_HTML 3
23
-#define CT_APPLICATION_X_JAVASCRIPT 4
24
-#define CT_TEXT_CSS 5
25
-#define CT_TEXT_XML 6
26
-#define CT_APPLICATION_XML 7
27
-#define CT_TEXT_XSL 8
28
-#define CT_APPLICATION_OCTET_STREAM 9
29
-#define CT_APPLICATION_X_FONT_TRUETYPE 10
30
-#define CT_APPLICATION_X_FONT_OPENTYPE 11
31
-#define CT_APPLICATION_FONT_WOFF 12
32
-#define CT_APPLICATION_FONT_WOFF2 13
33
-#define CT_APPLICATION_VND_MS_FONTOBJ 14
34
-#define CT_IMAGE_SVG_XML 15
35
-#define CT_IMAGE_PNG 16
36
-#define CT_IMAGE_JPG 17
37
-#define CT_IMAGE_GIF 18
38
-#define CT_IMAGE_XICON 19
39
-#define CT_IMAGE_ICNS 20
40
-#define CT_IMAGE_BMP 21
20
+#define CT_APPLICATION_JSON 1
21
+#define CT_TEXT_PLAIN 2
22
+#define CT_TEXT_HTML 3
23
+#define CT_APPLICATION_X_JAVASCRIPT 4
24
+#define CT_TEXT_CSS 5
25
+#define CT_TEXT_XML 6
26
+#define CT_APPLICATION_XML 7
27
+#define CT_TEXT_XSL 8
28
+#define CT_APPLICATION_OCTET_STREAM 9
29
+#define CT_APPLICATION_X_FONT_TRUETYPE 10
30
+#define CT_APPLICATION_X_FONT_OPENTYPE 11
31
+#define CT_APPLICATION_FONT_WOFF 12
32
+#define CT_APPLICATION_FONT_WOFF2 13
33
+#define CT_APPLICATION_VND_MS_FONTOBJ 14
34
+#define CT_IMAGE_SVG_XML 15
35
+#define CT_IMAGE_PNG 16
36
+#define CT_IMAGE_JPG 17
37
+#define CT_IMAGE_GIF 18
38
+#define CT_IMAGE_XICON 19
39
+#define CT_IMAGE_ICNS 20
40
+#define CT_IMAGE_BMP 21
41
42
#define buffer_strlen(wb) ((wb)->len)
43
extern const char *buffer_tostring(BUFFER *wb);
src/web_buffer_svg.c
+533
-533
@@ -9,559 +9,559 @@
9
*/
10
11
double verdana11_widths[256] = {
12
- [0] = 0.0,
13
- [1] = 0.0,
14
- [2] = 0.0,
15
- [3] = 0.0,
16
- [4] = 0.0,
17
- [5] = 0.0,
18
- [6] = 0.0,
19
- [7] = 0.0,
20
- [8] = 0.0,
21
- [9] = 0.0,
22
- [10] = 0.0,
23
- [11] = 0.0,
24
- [12] = 0.0,
25
- [13] = 0.0,
26
- [14] = 0.0,
27
- [15] = 0.0,
28
- [16] = 0.0,
29
- [17] = 0.0,
30
- [18] = 0.0,
31
- [19] = 0.0,
32
- [20] = 0.0,
33
- [21] = 0.0,
34
- [22] = 0.0,
35
- [23] = 0.0,
36
- [24] = 0.0,
37
- [25] = 0.0,
38
- [26] = 0.0,
39
- [27] = 0.0,
40
- [28] = 0.0,
41
- [29] = 0.0,
42
- [30] = 0.0,
43
- [31] = 0.0,
44
- [32] = 3.8671874999999996, //
45
- [33] = 4.3291015625, // !
46
- [34] = 5.048828125, // "
47
- [35] = 9.001953125, // #
48
- [36] = 6.9931640625, // $
49
- [37] = 11.837890625, // %
50
- [38] = 7.992187499999999, // &
51
- [39] = 2.9541015625, // '
52
- [40] = 4.9951171875, // (
53
- [41] = 4.9951171875, // )
54
- [42] = 6.9931640625, // *
55
- [43] = 9.001953125, // +
56
- [44] = 4.00146484375, // ,
57
- [45] = 4.9951171875, // -
58
- [46] = 4.00146484375, // .
59
- [47] = 4.9951171875, // /
60
- [48] = 6.9931640625, // 0
61
- [49] = 6.9931640625, // 1
62
- [50] = 6.9931640625, // 2
63
- [51] = 6.9931640625, // 3
64
- [52] = 6.9931640625, // 4
65
- [53] = 6.9931640625, // 5
66
- [54] = 6.9931640625, // 6
67
- [55] = 6.9931640625, // 7
68
- [56] = 6.9931640625, // 8
69
- [57] = 6.9931640625, // 9
70
- [58] = 4.9951171875, // :
71
- [59] = 4.9951171875, // ;
72
- [60] = 9.001953125, // <
73
- [61] = 9.001953125, // =
74
- [62] = 9.001953125, // >
75
- [63] = 5.99951171875, // ?
76
- [64] = 11.0, // @
77
- [65] = 7.51953125, // A
78
- [66] = 7.541015625, // B
79
- [67] = 7.680664062499999, // C
80
- [68] = 8.4755859375, // D
81
- [69] = 6.95556640625, // E
82
- [70] = 6.32177734375, // F
83
- [71] = 8.529296875, // G
84
- [72] = 8.26611328125, // H
85
- [73] = 4.6298828125, // I
86
- [74] = 5.00048828125, // J
87
- [75] = 7.62158203125, // K
88
- [76] = 6.123046875, // L
89
- [77] = 9.2705078125, // M
90
- [78] = 8.228515625, // N
91
- [79] = 8.658203125, // O
92
- [80] = 6.63330078125, // P
93
- [81] = 8.658203125, // Q
94
- [82] = 7.6484375, // R
95
- [83] = 7.51953125, // S
96
- [84] = 6.7783203125, // T
97
- [85] = 8.05126953125, // U
98
- [86] = 7.51953125, // V
99
- [87] = 10.87646484375, // W
100
- [88] = 7.53564453125, // X
101
- [89] = 6.767578125, // Y
102
- [90] = 7.53564453125, // Z
103
- [91] = 4.9951171875, // [
104
- [92] = 4.9951171875, // backslash
105
- [93] = 4.9951171875, // ]
106
- [94] = 9.001953125, // ^
107
- [95] = 6.9931640625, // _
108
- [96] = 6.9931640625, // `
109
- [97] = 6.6064453125, // a
110
- [98] = 6.853515625, // b
111
- [99] = 5.73095703125, // c
112
- [100] = 6.853515625, // d
113
- [101] = 6.552734375, // e
114
- [102] = 3.8671874999999996, // f
115
- [103] = 6.853515625, // g
116
- [104] = 6.9609375, // h
117
- [105] = 3.0185546875, // i
118
- [106] = 3.78662109375, // j
119
- [107] = 6.509765625, // k
120
- [108] = 3.0185546875, // l
121
- [109] = 10.69921875, // m
122
- [110] = 6.9609375, // n
123
- [111] = 6.67626953125, // o
124
- [112] = 6.853515625, // p
125
- [113] = 6.853515625, // q
126
- [114] = 4.6943359375, // r
127
- [115] = 5.73095703125, // s
128
- [116] = 4.33447265625, // t
129
- [117] = 6.9609375, // u
130
- [118] = 6.509765625, // v
131
- [119] = 9.001953125, // w
132
- [120] = 6.509765625, // x
133
- [121] = 6.509765625, // y
134
- [122] = 5.779296875, // z
135
- [123] = 6.982421875, // {
136
- [124] = 4.9951171875, // |
137
- [125] = 6.982421875, // }
138
- [126] = 9.001953125, // ~
139
- [127] = 0.0,
140
- [128] = 0.0,
141
- [129] = 0.0,
142
- [130] = 0.0,
143
- [131] = 0.0,
144
- [132] = 0.0,
145
- [133] = 0.0,
146
- [134] = 0.0,
147
- [135] = 0.0,
148
- [136] = 0.0,
149
- [137] = 0.0,
150
- [138] = 0.0,
151
- [139] = 0.0,
152
- [140] = 0.0,
153
- [141] = 0.0,
154
- [142] = 0.0,
155
- [143] = 0.0,
156
- [144] = 0.0,
157
- [145] = 0.0,
158
- [146] = 0.0,
159
- [147] = 0.0,
160
- [148] = 0.0,
161
- [149] = 0.0,
162
- [150] = 0.0,
163
- [151] = 0.0,
164
- [152] = 0.0,
165
- [153] = 0.0,
166
- [154] = 0.0,
167
- [155] = 0.0,
168
- [156] = 0.0,
169
- [157] = 0.0,
170
- [158] = 0.0,
171
- [159] = 0.0,
172
- [160] = 0.0,
173
- [161] = 0.0,
174
- [162] = 0.0,
175
- [163] = 0.0,
176
- [164] = 0.0,
177
- [165] = 0.0,
178
- [166] = 0.0,
179
- [167] = 0.0,
180
- [168] = 0.0,
181
- [169] = 0.0,
182
- [170] = 0.0,
183
- [171] = 0.0,
184
- [172] = 0.0,
185
- [173] = 0.0,
186
- [174] = 0.0,
187
- [175] = 0.0,
188
- [176] = 0.0,
189
- [177] = 0.0,
190
- [178] = 0.0,
191
- [179] = 0.0,
192
- [180] = 0.0,
193
- [181] = 0.0,
194
- [182] = 0.0,
195
- [183] = 0.0,
196
- [184] = 0.0,
197
- [185] = 0.0,
198
- [186] = 0.0,
199
- [187] = 0.0,
200
- [188] = 0.0,
201
- [189] = 0.0,
202
- [190] = 0.0,
203
- [191] = 0.0,
204
- [192] = 0.0,
205
- [193] = 0.0,
206
- [194] = 0.0,
207
- [195] = 0.0,
208
- [196] = 0.0,
209
- [197] = 0.0,
210
- [198] = 0.0,
211
- [199] = 0.0,
212
- [200] = 0.0,
213
- [201] = 0.0,
214
- [202] = 0.0,
215
- [203] = 0.0,
216
- [204] = 0.0,
217
- [205] = 0.0,
218
- [206] = 0.0,
219
- [207] = 0.0,
220
- [208] = 0.0,
221
- [209] = 0.0,
222
- [210] = 0.0,
223
- [211] = 0.0,
224
- [212] = 0.0,
225
- [213] = 0.0,
226
- [214] = 0.0,
227
- [215] = 0.0,
228
- [216] = 0.0,
229
- [217] = 0.0,
230
- [218] = 0.0,
231
- [219] = 0.0,
232
- [220] = 0.0,
233
- [221] = 0.0,
234
- [222] = 0.0,
235
- [223] = 0.0,
236
- [224] = 0.0,
237
- [225] = 0.0,
238
- [226] = 0.0,
239
- [227] = 0.0,
240
- [228] = 0.0,
241
- [229] = 0.0,
242
- [230] = 0.0,
243
- [231] = 0.0,
244
- [232] = 0.0,
245
- [233] = 0.0,
246
- [234] = 0.0,
247
- [235] = 0.0,
248
- [236] = 0.0,
249
- [237] = 0.0,
250
- [238] = 0.0,
251
- [239] = 0.0,
252
- [240] = 0.0,
253
- [241] = 0.0,
254
- [242] = 0.0,
255
- [243] = 0.0,
256
- [244] = 0.0,
257
- [245] = 0.0,
258
- [246] = 0.0,
259
- [247] = 0.0,
260
- [248] = 0.0,
261
- [249] = 0.0,
262
- [250] = 0.0,
263
- [251] = 0.0,
264
- [252] = 0.0,
265
- [253] = 0.0,
266
- [254] = 0.0,
267
- [255] = 0.0
12
+ [0] = 0.0,
13
+ [1] = 0.0,
14
+ [2] = 0.0,
15
+ [3] = 0.0,
16
+ [4] = 0.0,
17
+ [5] = 0.0,
18
+ [6] = 0.0,
19
+ [7] = 0.0,
20
+ [8] = 0.0,
21
+ [9] = 0.0,
22
+ [10] = 0.0,
23
+ [11] = 0.0,
24
+ [12] = 0.0,
25
+ [13] = 0.0,
26
+ [14] = 0.0,
27
+ [15] = 0.0,
28
+ [16] = 0.0,
29
+ [17] = 0.0,
30
+ [18] = 0.0,
31
+ [19] = 0.0,
32
+ [20] = 0.0,
33
+ [21] = 0.0,
34
+ [22] = 0.0,
35
+ [23] = 0.0,
36
+ [24] = 0.0,
37
+ [25] = 0.0,
38
+ [26] = 0.0,
39
+ [27] = 0.0,
40
+ [28] = 0.0,
41
+ [29] = 0.0,
42
+ [30] = 0.0,
43
+ [31] = 0.0,
44
+ [32] = 3.8671874999999996, //
45
+ [33] = 4.3291015625, // !
46
+ [34] = 5.048828125, // "
47
+ [35] = 9.001953125, // #
48
+ [36] = 6.9931640625, // $
49
+ [37] = 11.837890625, // %
50
+ [38] = 7.992187499999999, // &
51
+ [39] = 2.9541015625, // '
52
+ [40] = 4.9951171875, // (
53
+ [41] = 4.9951171875, // )
54
+ [42] = 6.9931640625, // *
55
+ [43] = 9.001953125, // +
56
+ [44] = 4.00146484375, // ,
57
+ [45] = 4.9951171875, // -
58
+ [46] = 4.00146484375, // .
59
+ [47] = 4.9951171875, // /
60
+ [48] = 6.9931640625, // 0
61
+ [49] = 6.9931640625, // 1
62
+ [50] = 6.9931640625, // 2
63
+ [51] = 6.9931640625, // 3
64
+ [52] = 6.9931640625, // 4
65
+ [53] = 6.9931640625, // 5
66
+ [54] = 6.9931640625, // 6
67
+ [55] = 6.9931640625, // 7
68
+ [56] = 6.9931640625, // 8
69
+ [57] = 6.9931640625, // 9
70
+ [58] = 4.9951171875, // :
71
+ [59] = 4.9951171875, // ;
72
+ [60] = 9.001953125, // <
73
+ [61] = 9.001953125, // =
74
+ [62] = 9.001953125, // >
75
+ [63] = 5.99951171875, // ?
76
+ [64] = 11.0, // @
77
+ [65] = 7.51953125, // A
78
+ [66] = 7.541015625, // B
79
+ [67] = 7.680664062499999, // C
80
+ [68] = 8.4755859375, // D
81
+ [69] = 6.95556640625, // E
82
+ [70] = 6.32177734375, // F
83
+ [71] = 8.529296875, // G
84
+ [72] = 8.26611328125, // H
85
+ [73] = 4.6298828125, // I
86
+ [74] = 5.00048828125, // J
87
+ [75] = 7.62158203125, // K
88
+ [76] = 6.123046875, // L
89
+ [77] = 9.2705078125, // M
90
+ [78] = 8.228515625, // N
91
+ [79] = 8.658203125, // O
92
+ [80] = 6.63330078125, // P
93
+ [81] = 8.658203125, // Q
94
+ [82] = 7.6484375, // R
95
+ [83] = 7.51953125, // S
96
+ [84] = 6.7783203125, // T
97
+ [85] = 8.05126953125, // U
98
+ [86] = 7.51953125, // V
99
+ [87] = 10.87646484375, // W
100
+ [88] = 7.53564453125, // X
101
+ [89] = 6.767578125, // Y
102
+ [90] = 7.53564453125, // Z
103
+ [91] = 4.9951171875, // [
104
+ [92] = 4.9951171875, // backslash
105
+ [93] = 4.9951171875, // ]
106
+ [94] = 9.001953125, // ^
107
+ [95] = 6.9931640625, // _
108
+ [96] = 6.9931640625, // `
109
+ [97] = 6.6064453125, // a
110
+ [98] = 6.853515625, // b
111
+ [99] = 5.73095703125, // c
112
+ [100] = 6.853515625, // d
113
+ [101] = 6.552734375, // e
114
+ [102] = 3.8671874999999996, // f
115
+ [103] = 6.853515625, // g
116
+ [104] = 6.9609375, // h
117
+ [105] = 3.0185546875, // i
118
+ [106] = 3.78662109375, // j
119
+ [107] = 6.509765625, // k
120
+ [108] = 3.0185546875, // l
121
+ [109] = 10.69921875, // m
122
+ [110] = 6.9609375, // n
123
+ [111] = 6.67626953125, // o
124
+ [112] = 6.853515625, // p
125
+ [113] = 6.853515625, // q
126
+ [114] = 4.6943359375, // r
127
+ [115] = 5.73095703125, // s
128
+ [116] = 4.33447265625, // t
129
+ [117] = 6.9609375, // u
130
+ [118] = 6.509765625, // v
131
+ [119] = 9.001953125, // w
132
+ [120] = 6.509765625, // x
133
+ [121] = 6.509765625, // y
134
+ [122] = 5.779296875, // z
135
+ [123] = 6.982421875, // {
136
+ [124] = 4.9951171875, // |
137
+ [125] = 6.982421875, // }
138
+ [126] = 9.001953125, // ~
139
+ [127] = 0.0,
140
+ [128] = 0.0,
141
+ [129] = 0.0,
142
+ [130] = 0.0,
143
+ [131] = 0.0,
144
+ [132] = 0.0,
145
+ [133] = 0.0,
146
+ [134] = 0.0,
147
+ [135] = 0.0,
148
+ [136] = 0.0,
149
+ [137] = 0.0,
150
+ [138] = 0.0,
151
+ [139] = 0.0,
152
+ [140] = 0.0,
153
+ [141] = 0.0,
154
+ [142] = 0.0,
155
+ [143] = 0.0,
156
+ [144] = 0.0,
157
+ [145] = 0.0,
158
+ [146] = 0.0,
159
+ [147] = 0.0,
160
+ [148] = 0.0,
161
+ [149] = 0.0,
162
+ [150] = 0.0,
163
+ [151] = 0.0,
164
+ [152] = 0.0,
165
+ [153] = 0.0,
166
+ [154] = 0.0,
167
+ [155] = 0.0,
168
+ [156] = 0.0,
169
+ [157] = 0.0,
170
+ [158] = 0.0,
171
+ [159] = 0.0,
172
+ [160] = 0.0,
173
+ [161] = 0.0,
174
+ [162] = 0.0,
175
+ [163] = 0.0,
176
+ [164] = 0.0,
177
+ [165] = 0.0,
178
+ [166] = 0.0,
179
+ [167] = 0.0,
180
+ [168] = 0.0,
181
+ [169] = 0.0,
182
+ [170] = 0.0,
183
+ [171] = 0.0,
184
+ [172] = 0.0,
185
+ [173] = 0.0,
186
+ [174] = 0.0,
187
+ [175] = 0.0,
188
+ [176] = 0.0,
189
+ [177] = 0.0,
190
+ [178] = 0.0,
191
+ [179] = 0.0,
192
+ [180] = 0.0,
193
+ [181] = 0.0,
194
+ [182] = 0.0,
195
+ [183] = 0.0,
196
+ [184] = 0.0,
197
+ [185] = 0.0,
198
+ [186] = 0.0,
199
+ [187] = 0.0,
200
+ [188] = 0.0,
201
+ [189] = 0.0,
202
+ [190] = 0.0,
203
+ [191] = 0.0,
204
+ [192] = 0.0,
205
+ [193] = 0.0,
206
+ [194] = 0.0,
207
+ [195] = 0.0,
208
+ [196] = 0.0,
209
+ [197] = 0.0,
210
+ [198] = 0.0,
211
+ [199] = 0.0,
212
+ [200] = 0.0,
213
+ [201] = 0.0,
214
+ [202] = 0.0,
215
+ [203] = 0.0,
216
+ [204] = 0.0,
217
+ [205] = 0.0,
218
+ [206] = 0.0,
219
+ [207] = 0.0,
220
+ [208] = 0.0,
221
+ [209] = 0.0,
222
+ [210] = 0.0,
223
+ [211] = 0.0,
224
+ [212] = 0.0,
225
+ [213] = 0.0,
226
+ [214] = 0.0,
227
+ [215] = 0.0,
228
+ [216] = 0.0,
229
+ [217] = 0.0,
230
+ [218] = 0.0,
231
+ [219] = 0.0,
232
+ [220] = 0.0,
233
+ [221] = 0.0,
234
+ [222] = 0.0,
235
+ [223] = 0.0,
236
+ [224] = 0.0,
237
+ [225] = 0.0,
238
+ [226] = 0.0,
239
+ [227] = 0.0,
240
+ [228] = 0.0,
241
+ [229] = 0.0,
242
+ [230] = 0.0,
243
+ [231] = 0.0,
244
+ [232] = 0.0,
245
+ [233] = 0.0,
246
+ [234] = 0.0,
247
+ [235] = 0.0,
248
+ [236] = 0.0,
249
+ [237] = 0.0,
250
+ [238] = 0.0,
251
+ [239] = 0.0,
252
+ [240] = 0.0,
253
+ [241] = 0.0,
254
+ [242] = 0.0,
255
+ [243] = 0.0,
256
+ [244] = 0.0,
257
+ [245] = 0.0,
258
+ [246] = 0.0,
259
+ [247] = 0.0,
260
+ [248] = 0.0,
261
+ [249] = 0.0,
262
+ [250] = 0.0,
263
+ [251] = 0.0,
264
+ [252] = 0.0,
265
+ [253] = 0.0,
266
+ [254] = 0.0,
267
+ [255] = 0.0
268
};
269
270
// find the width of the string using the verdana 11points font
271
// re-write the string in place, skiping zero-length characters
272
static inline int verdana11_width(char *s) {
273
- double w = 0.0;
274
- char *d = s;
275
-
276
- while(*s) {
277
- double t = verdana11_widths[(unsigned char)*s];
278
- if(t == 0.0)
279
- s++;
280
- else {
281
- w += t + VERDANA_KERNING;
282
- if(d != s)
283
- *d++ = *s++;
284
- else
285
- d = ++s;
286
- }
287
- }
288
-
289
- *d = '\0';
290
- w -= VERDANA_KERNING;
291
- return ceil(w);
273
+ double w = 0.0;
274
+ char *d = s;
275
+
276
+ while(*s) {
277
+ double t = verdana11_widths[(unsigned char)*s];
278
+ if(t == 0.0)
279
+ s++;
280
+ else {
281
+ w += t + VERDANA_KERNING;
282
+ if(d != s)
283
+ *d++ = *s++;
284
+ else
285
+ d = ++s;
286
+ }
287
+ }
288
+
289
+ *d = '\0';
290
+ w -= VERDANA_KERNING;
291
+ return ceil(w);
292
}
293
294
static inline size_t escape_xmlz(char *dst, const char *src, size_t len) {
295
- size_t i = len;
296
-
297
- // required escapes from
298
- // https://github.com/badges/shields/blob/master/badge.js
299
- while(*src && i) {
300
- switch(*src) {
301
- case '\\':
302
- *dst++ = '/';
303
- src++;
304
- i--;
305
- break;
306
-
307
- case '&':
308
- if(i > 5) {
309
- strcpy(dst, "&");
310
- i -= 5;
311
- dst += 5;
312
- src++;
313
- }
314
- else goto cleanup;
315
- break;
316
-
317
- case '<':
318
- if(i > 4) {
319
- strcpy(dst, "<");
320
- i -= 4;
321
- dst += 4;
322
- src++;
323
- }
324
- else goto cleanup;
325
- break;
326
-
327
- case '>':
328
- if(i > 4) {
329
- strcpy(dst, ">");
330
- i -= 4;
331
- dst += 4;
332
- src++;
333
- }
334
- else goto cleanup;
335
- break;
336
-
337
- case '"':
338
- if(i > 6) {
339
- strcpy(dst, """);
340
- i -= 6;
341
- dst += 6;
342
- src++;
343
- }
344
- else goto cleanup;
345
- break;
346
-
347
- case '\'':
348
- if(i > 6) {
349
- strcpy(dst, "'");
350
- i -= 6;
351
- dst += 6;
352
- src++;
353
- }
354
- else goto cleanup;
355
- break;
356
-
357
- default:
358
- i--;
359
- *dst++ = *src++;
360
- break;
361
- }
362
- }
295
+ size_t i = len;
296
+
297
+ // required escapes from
298
+ // https://github.com/badges/shields/blob/master/badge.js
299
+ while(*src && i) {
300
+ switch(*src) {
301
+ case '\\':
302
+ *dst++ = '/';
303
+ src++;
304
+ i--;
305
+ break;
306
+
307
+ case '&':
308
+ if(i > 5) {
309
+ strcpy(dst, "&");
310
+ i -= 5;
311
+ dst += 5;
312
+ src++;
313
+ }
314
+ else goto cleanup;
315
+ break;
316
+
317
+ case '<':
318
+ if(i > 4) {
319
+ strcpy(dst, "<");
320
+ i -= 4;
321
+ dst += 4;
322
+ src++;
323
+ }
324
+ else goto cleanup;
325
+ break;
326
+
327
+ case '>':
328
+ if(i > 4) {
329
+ strcpy(dst, ">");
330
+ i -= 4;
331
+ dst += 4;
332
+ src++;
333
+ }
334
+ else goto cleanup;
335
+ break;
336
+
337
+ case '"':
338
+ if(i > 6) {
339
+ strcpy(dst, """);
340
+ i -= 6;
341
+ dst += 6;
342
+ src++;
343
+ }
344
+ else goto cleanup;
345
+ break;
346
+
347
+ case '\'':
348
+ if(i > 6) {
349
+ strcpy(dst, "'");
350
+ i -= 6;
351
+ dst += 6;
352
+ src++;
353
+ }
354
+ else goto cleanup;
355
+ break;
356
+
357
+ default:
358
+ i--;
359
+ *dst++ = *src++;
360
+ break;
361
+ }
362
+ }
363
364
cleanup:
365
- *dst = '\0';
366
- return len - i;
365
+ *dst = '\0';
366
+ return len - i;
367
}
368
369
static inline const char *fix_units(const char *units) {
370
- if(!units || !*units || !strcmp(units, "empty") || !strcmp(units, "null")) return "";
371
- if(!strcmp(units, "percentage") || !strcmp(units, "percent") || !strcmp(units, "pcent")) return "%";
372
- return units;
370
+ if(!units || !*units || !strcmp(units, "empty") || !strcmp(units, "null")) return "";
371
+ if(!strcmp(units, "percentage") || !strcmp(units, "percent") || !strcmp(units, "pcent")) return "%";
372
+ return units;
373
}
374
375
static inline const char *color_map(const char *color) {
376
- // colors from:
377
- // https://github.com/badges/shields/blob/master/colorscheme.json
378
- if(!strcmp(color, "brightgreen")) return "#4c1";
379
- else if(!strcmp(color, "green")) return "#97CA00";
380
- else if(!strcmp(color, "yellow")) return "#dfb317";
381
- else if(!strcmp(color, "yellowgreen")) return "#a4a61d";
382
- else if(!strcmp(color, "orange")) return "#fe7d37";
383
- else if(!strcmp(color, "red")) return "#e05d44";
384
- else if(!strcmp(color, "blue")) return "#007ec6";
385
- else if(!strcmp(color, "grey")) return "#555";
386
- else if(!strcmp(color, "gray")) return "#555";
387
- else if(!strcmp(color, "lightgrey")) return "#9f9f9f";
388
- else if(!strcmp(color, "lightgray")) return "#9f9f9f";
389
- return color;
376
+ // colors from:
377
+ // https://github.com/badges/shields/blob/master/colorscheme.json
378
+ if(!strcmp(color, "brightgreen")) return "#4c1";
379
+ else if(!strcmp(color, "green")) return "#97CA00";
380
+ else if(!strcmp(color, "yellow")) return "#dfb317";
381
+ else if(!strcmp(color, "yellowgreen")) return "#a4a61d";
382
+ else if(!strcmp(color, "orange")) return "#fe7d37";
383
+ else if(!strcmp(color, "red")) return "#e05d44";
384
+ else if(!strcmp(color, "blue")) return "#007ec6";
385
+ else if(!strcmp(color, "grey")) return "#555";
386
+ else if(!strcmp(color, "gray")) return "#555";
387
+ else if(!strcmp(color, "lightgrey")) return "#9f9f9f";
388
+ else if(!strcmp(color, "lightgray")) return "#9f9f9f";
389
+ return color;
390
}
391
392
static inline void calc_colorz(const char *color, char *final, size_t len, calculated_number value, int value_is_null) {
393
- char color_buffer[256 + 1] = "";
394
- char value_buffer[256 + 1] = "";
395
- char comparison = '>';
396
-
397
- // example input:
398
- // color<max|color>min|color:null...
399
-
400
- const char *c = color;
401
- while(*c) {
402
- char *dc = color_buffer, *dv = NULL;
403
- size_t ci = 0, vi = 0;
404
-
405
- const char *t = c;
406
-
407
- while(*t && *t != '|') {
408
- switch(*t) {
409
- case ':':
410
- comparison = '=';
411
- dv = value_buffer;
412
- break;
413
-
414
- case '}':
415
- case ')':
416
- case '>':
417
- if(t[1] == '=') {
418
- comparison = ')';
419
- t++;
420
- }
421
- else
422
- comparison = '>';
423
- dv = value_buffer;
424
- break;
425
-
426
- case '{':
427
- case '(':
428
- case '<':
429
- if(t[1] == '=') {
430
- comparison = '(';
431
- t++;
432
- }
433
- else
434
- comparison = '<';
435
- dv = value_buffer;
436
- break;
437
-
438
- default:
439
- if(dv) {
440
- if(vi < 256) {
441
- vi++;
442
- *dv++ = *t;
443
- }
444
- }
445
- else {
446
- if(ci < 256) {
447
- ci++;
448
- *dc++ = *t;
449
- }
450
- }
451
- break;
452
- }
453
-
454
- t++;
455
- }
456
-
457
- // prepare for next iteration
458
- if(*t == '|') t++;
459
- c = t;
460
-
461
- // do the math
462
- *dc = '\0';
463
- if(dv) {
464
- *dv = '\0';
465
-
466
- if(value_is_null) {
467
- if(!*value_buffer || !strcmp(value_buffer, "null"))
468
- break;
469
- }
470
- else {
471
- calculated_number v = strtold(value_buffer, NULL);
472
-
473
- if(comparison == '<' && value < v) break;
474
- else if(comparison == '(' && value <= v) break;
475
- else if(comparison == '>' && value > v) break;
476
- else if(comparison == ')' && value >= v) break;
477
- else if(comparison == '=' && value == v) break;
478
- }
479
- }
480
- else
481
- break;
482
- }
483
-
484
- const char *b;
485
- if(color_buffer[0])
486
- b = color_buffer;
487
- else
488
- b = color;
489
-
490
- strncpyz(final, b, len);
393
+ char color_buffer[256 + 1] = "";
394
+ char value_buffer[256 + 1] = "";
395
+ char comparison = '>';
396
+
397
+ // example input:
398
+ // color<max|color>min|color:null...
399
+
400
+ const char *c = color;
401
+ while(*c) {
402
+ char *dc = color_buffer, *dv = NULL;
403
+ size_t ci = 0, vi = 0;
404
+
405
+ const char *t = c;
406
+
407
+ while(*t && *t != '|') {
408
+ switch(*t) {
409
+ case ':':
410
+ comparison = '=';
411
+ dv = value_buffer;
412
+ break;
413
+
414
+ case '}':
415
+ case ')':
416
+ case '>':
417
+ if(t[1] == '=') {
418
+ comparison = ')';
419
+ t++;
420
+ }
421
+ else
422
+ comparison = '>';
423
+ dv = value_buffer;
424
+ break;
425
+
426
+ case '{':
427
+ case '(':
428
+ case '<':
429
+ if(t[1] == '=') {
430
+ comparison = '(';
431
+ t++;
432
+ }
433
+ else
434
+ comparison = '<';
435
+ dv = value_buffer;
436
+ break;
437
+
438
+ default:
439
+ if(dv) {
440
+ if(vi < 256) {
441
+ vi++;
442
+ *dv++ = *t;
443
+ }
444
+ }
445
+ else {
446
+ if(ci < 256) {
447
+ ci++;
448
+ *dc++ = *t;
449
+ }
450
+ }
451
+ break;
452
+ }
453
+
454
+ t++;
455
+ }
456
+
457
+ // prepare for next iteration
458
+ if(*t == '|') t++;
459
+ c = t;
460
+
461
+ // do the math
462
+ *dc = '\0';
463
+ if(dv) {
464
+ *dv = '\0';
465
+
466
+ if(value_is_null) {
467
+ if(!*value_buffer || !strcmp(value_buffer, "null"))
468
+ break;
469
+ }
470
+ else {
471
+ calculated_number v = strtold(value_buffer, NULL);
472
+
473
+ if(comparison == '<' && value < v) break;
474
+ else if(comparison == '(' && value <= v) break;
475
+ else if(comparison == '>' && value > v) break;
476
+ else if(comparison == ')' && value >= v) break;
477
+ else if(comparison == '=' && value == v) break;
478
+ }
479
+ }
480
+ else
481
+ break;
482
+ }
483
+
484
+ const char *b;
485
+ if(color_buffer[0])
486
+ b = color_buffer;
487
+ else
488
+ b = color;
489
+
490
+ strncpyz(final, b, len);
491
}
492
493
void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const char *units, const char *label_color, const char *value_color, int value_is_null, int precision) {
494
- char label_buffer[256 + 1], value_string[512 + 1], value_color_buffer[256 + 1];
495
- char label_escaped[256 + 1], value_escaped[512 + 1], label_color_escaped[256 + 1], value_color_escaped[256 + 1];
496
- int label_width, value_width, total_width;
497
-
498
- if(!label_color || !*label_color) label_color = "#555";
499
- if(!value_color || !*value_color) value_color = (value_is_null)?"#999":"#4c1";
500
-
501
- units = fix_units(units);
502
- calc_colorz(value_color, value_color_buffer, 256, value, value_is_null);
503
-
504
- char *separator = "";
505
- if(isalnum(*units)) separator = " ";
506
-
507
- if(value_is_null)
508
- strcpy(value_string, "-");
509
- else if(precision < 0) {
510
- calculated_number abs = (value < (calculated_number)0)?-value:value;
511
- if(abs > (calculated_number)1000.0) snprintfz(value_string, 512, "%0.0Lf%s%s", (long double)value, separator, units);
512
- else if(abs > (calculated_number)100.0) snprintfz(value_string, 512, "%0.1Lf%s%s", (long double)value, separator, units);
513
- else if(abs > (calculated_number)1.0) snprintfz(value_string, 512, "%0.2Lf%s%s", (long double)value, separator, units);
514
- else if(abs > (calculated_number)0.1) snprintfz(value_string, 512, "%0.3Lf%s%s", (long double)value, separator, units);
515
- else snprintfz(value_string, 512, "%0.4Lf%s%s", (long double)value, separator, units);
516
- }
517
- else {
518
- if(precision > 50) precision = 50;
519
- snprintfz(value_string, 512, "%0.*Lf%s%s", precision, (long double)value, separator, units);
520
- }
521
-
522
- // we need to copy the label, since verdana11_width may write to it
523
- strncpyz(label_buffer, label, 256);
524
-
525
- label_width = verdana11_width(label_buffer) + (BADGE_HORIZONTAL_PADDING * 2);
526
- value_width = verdana11_width(value_string) + (BADGE_HORIZONTAL_PADDING * 2);
527
- total_width = label_width + value_width;
528
-
529
- escape_xmlz(label_escaped, label_buffer, 256);
530
- escape_xmlz(value_escaped, value_string, 256);
531
- escape_xmlz(label_color_escaped, color_map(label_color), 256);
532
- escape_xmlz(value_color_escaped, color_map(value_color_buffer), 256);
533
-
534
- wb->contenttype = CT_IMAGE_SVG_XML;
535
-
536
- // svg template from:
537
- // https://raw.githubusercontent.com/badges/shields/master/templates/flat-template.svg
538
- buffer_sprintf(wb,
539
- "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"%d\" height=\"20\">"
540
- "<linearGradient id=\"smooth\" x2=\"0\" y2=\"100%%\">"
541
- "<stop offset=\"0\" stop-color=\"#bbb\" stop-opacity=\".1\"/>"
542
- "<stop offset=\"1\" stop-opacity=\".1\"/>"
543
- "</linearGradient>"
544
- "<mask id=\"round\">"
545
- "<rect width=\"%d\" height=\"20\" rx=\"3\" fill=\"#fff\"/>"
546
- "</mask>"
547
- "<g mask=\"url(#round)\">"
548
- "<rect width=\"%d\" height=\"20\" fill=\"%s\"/>"
549
- "<rect x=\"%d\" width=\"%d\" height=\"20\" fill=\"%s\"/>"
550
- "<rect width=\"%d\" height=\"20\" fill=\"url(#smooth)\"/>"
551
- "</g>"
552
- "<g fill=\"#fff\" text-anchor=\"middle\" font-family=\"DejaVu Sans,Verdana,Geneva,sans-serif\" font-size=\"11\">"
553
- "<text x=\"%d\" y=\"15\" fill=\"#010101\" fill-opacity=\".3\">%s</text>"
554
- "<text x=\"%d\" y=\"14\">%s</text>"
555
- "<text x=\"%d\" y=\"15\" fill=\"#010101\" fill-opacity=\".3\">%s</text>"
556
- "<text x=\"%d\" y=\"14\">%s</text>"
557
- "</g>"
558
- "</svg>",
559
- total_width, total_width,
560
- label_width, label_color_escaped,
561
- label_width, value_width, value_color_escaped,
562
- total_width,
563
- label_width / 2, label_escaped,
564
- label_width / 2, label_escaped,
565
- label_width + value_width / 2 -1, value_escaped,
566
- label_width + value_width / 2 -1, value_escaped);
494
+ char label_buffer[256 + 1], value_string[512 + 1], value_color_buffer[256 + 1];
495
+ char label_escaped[256 + 1], value_escaped[512 + 1], label_color_escaped[256 + 1], value_color_escaped[256 + 1];
496
+ int label_width, value_width, total_width;
497
+
498
+ if(!label_color || !*label_color) label_color = "#555";
499
+ if(!value_color || !*value_color) value_color = (value_is_null)?"#999":"#4c1";
500
+
501
+ units = fix_units(units);
502
+ calc_colorz(value_color, value_color_buffer, 256, value, value_is_null);
503
+
504
+ char *separator = "";
505
+ if(isalnum(*units)) separator = " ";
506
+
507
+ if(value_is_null)
508
+ strcpy(value_string, "-");
509
+ else if(precision < 0) {
510
+ calculated_number abs = (value < (calculated_number)0)?-value:value;
511
+ if(abs > (calculated_number)1000.0) snprintfz(value_string, 512, "%0.0Lf%s%s", (long double)value, separator, units);
512
+ else if(abs > (calculated_number)100.0) snprintfz(value_string, 512, "%0.1Lf%s%s", (long double)value, separator, units);
513
+ else if(abs > (calculated_number)1.0) snprintfz(value_string, 512, "%0.2Lf%s%s", (long double)value, separator, units);
514
+ else if(abs > (calculated_number)0.1) snprintfz(value_string, 512, "%0.3Lf%s%s", (long double)value, separator, units);
515
+ else snprintfz(value_string, 512, "%0.4Lf%s%s", (long double)value, separator, units);
516
+ }
517
+ else {
518
+ if(precision > 50) precision = 50;
519
+ snprintfz(value_string, 512, "%0.*Lf%s%s", precision, (long double)value, separator, units);
520
+ }
521
+
522
+ // we need to copy the label, since verdana11_width may write to it
523
+ strncpyz(label_buffer, label, 256);
524
+
525
+ label_width = verdana11_width(label_buffer) + (BADGE_HORIZONTAL_PADDING * 2);
526
+ value_width = verdana11_width(value_string) + (BADGE_HORIZONTAL_PADDING * 2);
527
+ total_width = label_width + value_width;
528
+
529
+ escape_xmlz(label_escaped, label_buffer, 256);
530
+ escape_xmlz(value_escaped, value_string, 256);
531
+ escape_xmlz(label_color_escaped, color_map(label_color), 256);
532
+ escape_xmlz(value_color_escaped, color_map(value_color_buffer), 256);
533
+
534
+ wb->contenttype = CT_IMAGE_SVG_XML;
535
+
536
+ // svg template from:
537
+ // https://raw.githubusercontent.com/badges/shields/master/templates/flat-template.svg
538
+ buffer_sprintf(wb,
539
+ "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"%d\" height=\"20\">"
540
+ "<linearGradient id=\"smooth\" x2=\"0\" y2=\"100%%\">"
541
+ "<stop offset=\"0\" stop-color=\"#bbb\" stop-opacity=\".1\"/>"
542
+ "<stop offset=\"1\" stop-opacity=\".1\"/>"
543
+ "</linearGradient>"
544
+ "<mask id=\"round\">"
545
+ "<rect width=\"%d\" height=\"20\" rx=\"3\" fill=\"#fff\"/>"
546
+ "</mask>"
547
+ "<g mask=\"url(#round)\">"
548
+ "<rect width=\"%d\" height=\"20\" fill=\"%s\"/>"
549
+ "<rect x=\"%d\" width=\"%d\" height=\"20\" fill=\"%s\"/>"
550
+ "<rect width=\"%d\" height=\"20\" fill=\"url(#smooth)\"/>"
551
+ "</g>"
552
+ "<g fill=\"#fff\" text-anchor=\"middle\" font-family=\"DejaVu Sans,Verdana,Geneva,sans-serif\" font-size=\"11\">"
553
+ "<text x=\"%d\" y=\"15\" fill=\"#010101\" fill-opacity=\".3\">%s</text>"
554
+ "<text x=\"%d\" y=\"14\">%s</text>"
555
+ "<text x=\"%d\" y=\"15\" fill=\"#010101\" fill-opacity=\".3\">%s</text>"
556
+ "<text x=\"%d\" y=\"14\">%s</text>"
557
+ "</g>"
558
+ "</svg>",
559
+ total_width, total_width,
560
+ label_width, label_color_escaped,
561
+ label_width, value_width, value_color_escaped,
562
+ total_width,
563
+ label_width / 2, label_escaped,
564
+ label_width / 2, label_escaped,
565
+ label_width + value_width / 2 -1, value_escaped,
566
+ label_width + value_width / 2 -1, value_escaped);
567
}
src/web_client.c
+2182
-2182
@@ -16,125 +16,125 @@ unsigned long long web_clients_count = 0;
16
17
inline int web_client_crock_socket(struct web_client *w) {
18
#ifdef TCP_CORK
19
- if(likely(!w->tcp_cork && w->ofd != -1)) {
20
- w->tcp_cork = 1;
21
- if(unlikely(setsockopt(w->ofd, IPPROTO_TCP, TCP_CORK, (char *) &w->tcp_cork, sizeof(int)) != 0)) {
22
- error("%llu: failed to enable TCP_CORK on socket.", w->id);
23
- w->tcp_cork = 0;
24
- return -1;
25
- }
26
- }
19
+ if(likely(!w->tcp_cork && w->ofd != -1)) {
20
+ w->tcp_cork = 1;
21
+ if(unlikely(setsockopt(w->ofd, IPPROTO_TCP, TCP_CORK, (char *) &w->tcp_cork, sizeof(int)) != 0)) {
22
+ error("%llu: failed to enable TCP_CORK on socket.", w->id);
23
+ w->tcp_cork = 0;
24
+ return -1;
25
+ }
26
+ }
27
#endif /* TCP_CORK */
28
29
- return 0;
29
+ return 0;
30
}
31
32
inline int web_client_uncrock_socket(struct web_client *w) {
33
#ifdef TCP_CORK
34
- if(likely(w->tcp_cork && w->ofd != -1)) {
35
- w->tcp_cork = 0;
36
- if(unlikely(setsockopt(w->ofd, IPPROTO_TCP, TCP_CORK, (char *) &w->tcp_cork, sizeof(int)) != 0)) {
37
- error("%llu: failed to disable TCP_CORK on socket.", w->id);
38
- w->tcp_cork = 1;
39
- return -1;
40
- }
41
- }
34
+ if(likely(w->tcp_cork && w->ofd != -1)) {
35
+ w->tcp_cork = 0;
36
+ if(unlikely(setsockopt(w->ofd, IPPROTO_TCP, TCP_CORK, (char *) &w->tcp_cork, sizeof(int)) != 0)) {
37
+ error("%llu: failed to disable TCP_CORK on socket.", w->id);
38
+ w->tcp_cork = 1;
39
+ return -1;
40
+ }
41
+ }
42
#endif /* TCP_CORK */
43
44
- return 0;
44
+ return 0;
45
}
46
47
struct web_client *web_client_create(int listener)
48
{
49
- struct web_client *w;
50
-
51
- w = callocz(1, sizeof(struct web_client));
52
- w->id = ++web_clients_count;
53
- w->mode = WEB_CLIENT_MODE_NORMAL;
54
-
55
- {
56
- struct sockaddr *sadr;
57
- socklen_t addrlen;
58
-
59
- sadr = (struct sockaddr*) &w->clientaddr;
60
- addrlen = sizeof(w->clientaddr);
61
-
62
- w->ifd = accept4(listener, sadr, &addrlen, SOCK_NONBLOCK);
63
- if (w->ifd == -1) {
64
- error("%llu: Cannot accept new incoming connection.", w->id);
65
- freez(w);
66
- return NULL;
67
- }
68
- w->ofd = w->ifd;
69
-
70
- if(getnameinfo(sadr, addrlen, w->client_ip, NI_MAXHOST, w->client_port, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
71
- error("Cannot getnameinfo() on received client connection.");
72
- strncpyz(w->client_ip, "UNKNOWN", NI_MAXHOST);
73
- strncpyz(w->client_port, "UNKNOWN", NI_MAXSERV);
74
- }
75
- w->client_ip[NI_MAXHOST] = '\0';
76
- w->client_port[NI_MAXSERV] = '\0';
77
-
78
- switch(sadr->sa_family) {
79
- case AF_INET:
80
- debug(D_WEB_CLIENT_ACCESS, "%llu: New IPv4 web client from %s port %s on socket %d.", w->id, w->client_ip, w->client_port, w->ifd);
81
- break;
82
-
83
- case AF_INET6:
84
- if(strncmp(w->client_ip, "::ffff:", 7) == 0) {
85
- memmove(w->client_ip, &w->client_ip[7], strlen(&w->client_ip[7]) + 1);
86
- debug(D_WEB_CLIENT_ACCESS, "%llu: New IPv4 web client from %s port %s on socket %d.", w->id, w->client_ip, w->client_port, w->ifd);
87
- }
88
- else
89
- debug(D_WEB_CLIENT_ACCESS, "%llu: New IPv6 web client from %s port %s on socket %d.", w->id, w->client_ip, w->client_port, w->ifd);
90
- break;
91
-
92
- default:
93
- debug(D_WEB_CLIENT_ACCESS, "%llu: New UNKNOWN web client from %s port %s on socket %d.", w->id, w->client_ip, w->client_port, w->ifd);
94
- break;
95
- }
96
-
97
- int flag = 1;
98
- if(setsockopt(w->ofd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int)) != 0)
99
- error("%llu: failed to enable TCP_NODELAY on socket.", w->id);
100
-
101
- flag = 1;
102
- if(setsockopt(w->ifd, SOL_SOCKET, SO_KEEPALIVE, (char *) &flag, sizeof(int)) != 0)
103
- error("%llu: Cannot set SO_KEEPALIVE on socket.", w->id);
104
- }
105
-
106
- w->response.data = buffer_create(INITIAL_WEB_DATA_LENGTH);
107
- w->response.header = buffer_create(HTTP_RESPONSE_HEADER_SIZE);
108
- w->response.header_output = buffer_create(HTTP_RESPONSE_HEADER_SIZE);
109
- w->origin[0] = '*';
110
- w->wait_receive = 1;
111
-
112
- if(web_clients) web_clients->prev = w;
113
- w->next = web_clients;
114
- web_clients = w;
49
+ struct web_client *w;
50
+
51
+ w = callocz(1, sizeof(struct web_client));
52
+ w->id = ++web_clients_count;
53
+ w->mode = WEB_CLIENT_MODE_NORMAL;
54
+
55
+ {
56
+ struct sockaddr *sadr;
57
+ socklen_t addrlen;
58
+
59
+ sadr = (struct sockaddr*) &w->clientaddr;
60
+ addrlen = sizeof(w->clientaddr);
61
+
62
+ w->ifd = accept4(listener, sadr, &addrlen, SOCK_NONBLOCK);
63
+ if (w->ifd == -1) {
64
+ error("%llu: Cannot accept new incoming connection.", w->id);
65
+ freez(w);
66
+ return NULL;
67
+ }
68
+ w->ofd = w->ifd;
69
+
70
+ if(getnameinfo(sadr, addrlen, w->client_ip, NI_MAXHOST, w->client_port, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
71
+ error("Cannot getnameinfo() on received client connection.");
72
+ strncpyz(w->client_ip, "UNKNOWN", NI_MAXHOST);
73
+ strncpyz(w->client_port, "UNKNOWN", NI_MAXSERV);
74
+ }
75
+ w->client_ip[NI_MAXHOST] = '\0';
76
+ w->client_port[NI_MAXSERV] = '\0';
77
+
78
+ switch(sadr->sa_family) {
79
+ case AF_INET:
80
+ debug(D_WEB_CLIENT_ACCESS, "%llu: New IPv4 web client from %s port %s on socket %d.", w->id, w->client_ip, w->client_port, w->ifd);
81
+ break;
82
+
83
+ case AF_INET6:
84
+ if(strncmp(w->client_ip, "::ffff:", 7) == 0) {
85
+ memmove(w->client_ip, &w->client_ip[7], strlen(&w->client_ip[7]) + 1);
86
+ debug(D_WEB_CLIENT_ACCESS, "%llu: New IPv4 web client from %s port %s on socket %d.", w->id, w->client_ip, w->client_port, w->ifd);
87
+ }
88
+ else
89
+ debug(D_WEB_CLIENT_ACCESS, "%llu: New IPv6 web client from %s port %s on socket %d.", w->id, w->client_ip, w->client_port, w->ifd);
90
+ break;
91
+
92
+ default:
93
+ debug(D_WEB_CLIENT_ACCESS, "%llu: New UNKNOWN web client from %s port %s on socket %d.", w->id, w->client_ip, w->client_port, w->ifd);
94
+ break;
95
+ }
96
+
97
+ int flag = 1;
98
+ if(setsockopt(w->ofd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int)) != 0)
99
+ error("%llu: failed to enable TCP_NODELAY on socket.", w->id);
100
+
101
+ flag = 1;
102
+ if(setsockopt(w->ifd, SOL_SOCKET, SO_KEEPALIVE, (char *) &flag, sizeof(int)) != 0)
103
+ error("%llu: Cannot set SO_KEEPALIVE on socket.", w->id);
104
+ }
105
+
106
+ w->response.data = buffer_create(INITIAL_WEB_DATA_LENGTH);
107
+ w->response.header = buffer_create(HTTP_RESPONSE_HEADER_SIZE);
108
+ w->response.header_output = buffer_create(HTTP_RESPONSE_HEADER_SIZE);
109
+ w->origin[0] = '*';
110
+ w->wait_receive = 1;
111
+
112
+ if(web_clients) web_clients->prev = w;
113
+ w->next = web_clients;
114
+ web_clients = w;
115
116
web_client_connected();
117
118
- return(w);
118
+ return(w);
119
}
120
121
void web_client_reset(struct web_client *w) {
122
- web_client_uncrock_socket(w);
122
+ web_client_uncrock_socket(w);
123
124
- debug(D_WEB_CLIENT, "%llu: Reseting client.", w->id);
124
+ debug(D_WEB_CLIENT, "%llu: Reseting client.", w->id);
125
126
- if(likely(w->last_url[0])) {
127
- struct timeval tv;
128
- gettimeofday(&tv, NULL);
126
+ if(likely(w->last_url[0])) {
127
+ struct timeval tv;
128
+ gettimeofday(&tv, NULL);
129
130
- size_t size = (w->mode == WEB_CLIENT_MODE_FILECOPY)?w->response.rlen:w->response.data->len;
131
- size_t sent = size;
130
+ size_t size = (w->mode == WEB_CLIENT_MODE_FILECOPY)?w->response.rlen:w->response.data->len;
131
+ size_t sent = size;
132
#ifdef NETDATA_WITH_ZLIB
133
- if(likely(w->response.zoutput)) sent = (size_t)w->response.zstream.total_out;
133
+ if(likely(w->response.zoutput)) sent = (size_t)w->response.zstream.total_out;
134
#endif
135
136
- // --------------------------------------------------------------------
137
- // global statistics
136
+ // --------------------------------------------------------------------
137
+ // global statistics
138
139
finished_web_request_statistics(usec_dt(&tv, &w->tv_in),
140
w->stats_received_bytes,
@@ -142,1439 +142,1439 @@ void web_client_reset(struct web_client *w) {
142
size,
143
sent);
144
145
- w->stats_received_bytes = 0;
146
- w->stats_sent_bytes = 0;
147
-
148
-
149
- // --------------------------------------------------------------------
150
- // access log
151
-
152
- log_access("%llu: (sent/all = %zu/%zu bytes %0.0f%%, prep/sent/total = %0.2f/%0.2f/%0.2f ms) %s: %d '%s'",
153
- w->id,
154
- sent, size, -((size > 0) ? ((size - sent) / (double) size * 100.0) : 0.0),
155
- usec_dt(&w->tv_ready, &w->tv_in) / 1000.0,
156
- usec_dt(&tv, &w->tv_ready) / 1000.0,
157
- usec_dt(&tv, &w->tv_in) / 1000.0,
158
- (w->mode == WEB_CLIENT_MODE_FILECOPY) ? "filecopy" : ((w->mode == WEB_CLIENT_MODE_OPTIONS)
159
- ? "options" : "data"),
160
- w->response.code,
161
- w->last_url
162
- );
163
- }
164
-
165
- if(unlikely(w->mode == WEB_CLIENT_MODE_FILECOPY)) {
166
- if(w->ifd != w->ofd) {
167
- debug(D_WEB_CLIENT, "%llu: Closing filecopy input file descriptor %d.", w->id, w->ifd);
168
- if(w->ifd != -1) close(w->ifd);
169
- w->ifd = w->ofd;
170
- }
171
- }
172
-
173
- w->last_url[0] = '\0';
174
- w->cookie1[0] = '\0';
175
- w->cookie2[0] = '\0';
176
- w->origin[0] = '*';
177
- w->origin[1] = '\0';
178
-
179
- w->mode = WEB_CLIENT_MODE_NORMAL;
180
-
181
- w->tcp_cork = 0;
182
- w->donottrack = 0;
183
- w->tracking_required = 0;
184
- w->keepalive = 0;
185
- w->decoded_url[0] = '\0';
186
-
187
- buffer_reset(w->response.header_output);
188
- buffer_reset(w->response.header);
189
- buffer_reset(w->response.data);
190
- w->response.rlen = 0;
191
- w->response.sent = 0;
192
- w->response.code = 0;
193
-
194
- w->wait_receive = 1;
195
- w->wait_send = 0;
196
-
197
- w->response.zoutput = 0;
198
-
199
- // if we had enabled compression, release it
145
+ w->stats_received_bytes = 0;
146
+ w->stats_sent_bytes = 0;
147
+
148
+
149
+ // --------------------------------------------------------------------
150
+ // access log
151
+
152
+ log_access("%llu: (sent/all = %zu/%zu bytes %0.0f%%, prep/sent/total = %0.2f/%0.2f/%0.2f ms) %s: %d '%s'",
153
+ w->id,
154
+ sent, size, -((size > 0) ? ((size - sent) / (double) size * 100.0) : 0.0),
155
+ usec_dt(&w->tv_ready, &w->tv_in) / 1000.0,
156
+ usec_dt(&tv, &w->tv_ready) / 1000.0,
157
+ usec_dt(&tv, &w->tv_in) / 1000.0,
158
+ (w->mode == WEB_CLIENT_MODE_FILECOPY) ? "filecopy" : ((w->mode == WEB_CLIENT_MODE_OPTIONS)
159
+ ? "options" : "data"),
160
+ w->response.code,
161
+ w->last_url
162
+ );
163
+ }
164
+
165
+ if(unlikely(w->mode == WEB_CLIENT_MODE_FILECOPY)) {
166
+ if(w->ifd != w->ofd) {
167
+ debug(D_WEB_CLIENT, "%llu: Closing filecopy input file descriptor %d.", w->id, w->ifd);
168
+ if(w->ifd != -1) close(w->ifd);
169
+ w->ifd = w->ofd;
170
+ }
171
+ }
172
+
173
+ w->last_url[0] = '\0';
174
+ w->cookie1[0] = '\0';
175
+ w->cookie2[0] = '\0';
176
+ w->origin[0] = '*';
177
+ w->origin[1] = '\0';
178
+
179
+ w->mode = WEB_CLIENT_MODE_NORMAL;
180
+
181
+ w->tcp_cork = 0;
182
+ w->donottrack = 0;
183
+ w->tracking_required = 0;
184
+ w->keepalive = 0;
185
+ w->decoded_url[0] = '\0';
186
+
187
+ buffer_reset(w->response.header_output);
188
+ buffer_reset(w->response.header);
189
+ buffer_reset(w->response.data);
190
+ w->response.rlen = 0;
191
+ w->response.sent = 0;
192
+ w->response.code = 0;
193
+
194
+ w->wait_receive = 1;
195
+ w->wait_send = 0;
196
+
197
+ w->response.zoutput = 0;
198
+
199
+ // if we had enabled compression, release it
200
#ifdef NETDATA_WITH_ZLIB
201
- if(w->response.zinitialized) {
202
- debug(D_DEFLATE, "%llu: Freeing compression resources.", w->id);
203
- deflateEnd(&w->response.zstream);
204
- w->response.zsent = 0;
205
- w->response.zhave = 0;
206
- w->response.zstream.avail_in = 0;
207
- w->response.zstream.avail_out = 0;
208
- w->response.zstream.total_in = 0;
209
- w->response.zstream.total_out = 0;
210
- w->response.zinitialized = 0;
211
- }
201
+ if(w->response.zinitialized) {
202
+ debug(D_DEFLATE, "%llu: Freeing compression resources.", w->id);
203
+ deflateEnd(&w->response.zstream);
204
+ w->response.zsent = 0;
205
+ w->response.zhave = 0;
206
+ w->response.zstream.avail_in = 0;
207
+ w->response.zstream.avail_out = 0;
208
+ w->response.zstream.total_in = 0;
209
+ w->response.zstream.total_out = 0;
210
+ w->response.zinitialized = 0;
211
+ }
212
#endif // NETDATA_WITH_ZLIB
213
}
214
215
struct web_client *web_client_free(struct web_client *w) {
216
- web_client_reset(w);
216
+ web_client_reset(w);
217
218
- struct web_client *n = w->next;
219
- if(w == web_clients) web_clients = n;
218
+ struct web_client *n = w->next;
219
+ if(w == web_clients) web_clients = n;
220
221
- debug(D_WEB_CLIENT_ACCESS, "%llu: Closing web client from %s port %s.", w->id, w->client_ip, w->client_port);
221
+ debug(D_WEB_CLIENT_ACCESS, "%llu: Closing web client from %s port %s.", w->id, w->client_ip, w->client_port);
222
223
- if(w->prev) w->prev->next = w->next;
224
- if(w->next) w->next->prev = w->prev;
225
- if(w->response.header_output) buffer_free(w->response.header_output);
226
- if(w->response.header) buffer_free(w->response.header);
227
- if(w->response.data) buffer_free(w->response.data);
228
- if(w->ifd != -1) close(w->ifd);
229
- if(w->ofd != -1 && w->ofd != w->ifd) close(w->ofd);
230
- freez(w);
223
+ if(w->prev) w->prev->next = w->next;
224
+ if(w->next) w->next->prev = w->prev;
225
+ if(w->response.header_output) buffer_free(w->response.header_output);
226
+ if(w->response.header) buffer_free(w->response.header);
227
+ if(w->response.data) buffer_free(w->response.data);
228
+ if(w->ifd != -1) close(w->ifd);
229
+ if(w->ofd != -1 && w->ofd != w->ifd) close(w->ofd);
230
+ freez(w);
231
232
web_client_disconnected();
233
234
- return(n);
234
+ return(n);
235
}
236
237
uid_t web_files_uid(void) {
238
- static char *web_owner = NULL;
239
- static uid_t owner_uid = 0;
240
-
241
- if(unlikely(!web_owner)) {
242
- web_owner = config_get("global", "web files owner", config_get("global", "run as user", ""));
243
- if(!web_owner || !*web_owner)
244
- owner_uid = geteuid();
245
- else {
246
- // getpwnam() is not thread safe,
247
- // but we have called this function once
248
- // while single threaded
249
- struct passwd *pw = getpwnam(web_owner);
250
- if(!pw) {
251
- error("User '%s' is not present. Ignoring option.", web_owner);
252
- owner_uid = geteuid();
253
- }
254
- else {
255
- debug(D_WEB_CLIENT, "Web files owner set to %s.", web_owner);
256
- owner_uid = pw->pw_uid;
257
- }
258
- }
259
- }
260
-
261
- return(owner_uid);
238
+ static char *web_owner = NULL;
239
+ static uid_t owner_uid = 0;
240
+
241
+ if(unlikely(!web_owner)) {
242
+ web_owner = config_get("global", "web files owner", config_get("global", "run as user", ""));
243
+ if(!web_owner || !*web_owner)
244
+ owner_uid = geteuid();
245
+ else {
246
+ // getpwnam() is not thread safe,
247
+ // but we have called this function once
248
+ // while single threaded
249
+ struct passwd *pw = getpwnam(web_owner);
250
+ if(!pw) {
251
+ error("User '%s' is not present. Ignoring option.", web_owner);
252
+ owner_uid = geteuid();
253
+ }
254
+ else {
255
+ debug(D_WEB_CLIENT, "Web files owner set to %s.", web_owner);
256
+ owner_uid = pw->pw_uid;
257
+ }
258
+ }
259
+ }
260
+
261
+ return(owner_uid);
262
}
263
264
gid_t web_files_gid(void) {
265
- static char *web_group = NULL;
266
- static gid_t owner_gid = 0;
267
-
268
- if(unlikely(!web_group)) {
269
- web_group = config_get("global", "web files group", config_get("global", "web files owner", ""));
270
- if(!web_group || !*web_group)
271
- owner_gid = getegid();
272
- else {
273
- // getgrnam() is not thread safe,
274
- // but we have called this function once
275
- // while single threaded
276
- struct group *gr = getgrnam(web_group);
277
- if(!gr) {
278
- error("Group '%s' is not present. Ignoring option.", web_group);
279
- owner_gid = getegid();
280
- }
281
- else {
282
- debug(D_WEB_CLIENT, "Web files group set to %s.", web_group);
283
- owner_gid = gr->gr_gid;
284
- }
285
- }
286
- }
287
-
288
- return(owner_gid);
265
+ static char *web_group = NULL;
266
+ static gid_t owner_gid = 0;
267
+
268
+ if(unlikely(!web_group)) {
269
+ web_group = config_get("global", "web files group", config_get("global", "web files owner", ""));
270
+ if(!web_group || !*web_group)
271
+ owner_gid = getegid();
272
+ else {
273
+ // getgrnam() is not thread safe,
274
+ // but we have called this function once
275
+ // while single threaded
276
+ struct group *gr = getgrnam(web_group);
277
+ if(!gr) {
278
+ error("Group '%s' is not present. Ignoring option.", web_group);
279
+ owner_gid = getegid();
280
+ }
281
+ else {
282
+ debug(D_WEB_CLIENT, "Web files group set to %s.", web_group);
283
+ owner_gid = gr->gr_gid;
284
+ }
285
+ }
286
+ }
287
+
288
+ return(owner_gid);
289
}
290
291
int mysendfile(struct web_client *w, char *filename)
292
{
293
- static char *web_dir = NULL;
294
-
295
- // initialize our static data
296
- if(unlikely(!web_dir)) web_dir = config_get("global", "web files directory", WEB_DIR);
297
-
298
- debug(D_WEB_CLIENT, "%llu: Looking for file '%s/%s'", w->id, web_dir, filename);
299
-
300
- // skip leading slashes
301
- while (*filename == '/') filename++;
302
-
303
- // if the filename contain known paths, skip them
304
- if(strncmp(filename, WEB_PATH_FILE "/", strlen(WEB_PATH_FILE) + 1) == 0)
305
- filename = &filename[strlen(WEB_PATH_FILE) + 1];
306
-
307
- char *s;
308
- for(s = filename; *s ;s++) {
309
- if( !isalnum(*s) && *s != '/' && *s != '.' && *s != '-' && *s != '_') {
310
- debug(D_WEB_CLIENT_ACCESS, "%llu: File '%s' is not acceptable.", w->id, filename);
311
- buffer_sprintf(w->response.data, "File '%s' cannot be served. Filename contains invalid character '%c'", filename, *s);
312
- return 400;
313
- }
314
- }
315
-
316
- // if the filename contains a .. refuse to serve it
317
- if(strstr(filename, "..") != 0) {
318
- debug(D_WEB_CLIENT_ACCESS, "%llu: File '%s' is not acceptable.", w->id, filename);
319
- buffer_sprintf(w->response.data, "File '%s' cannot be served. Relative filenames with '..' in them are not supported.", filename);
320
- return 400;
321
- }
322
-
323
- // access the file
324
- char webfilename[FILENAME_MAX + 1];
325
- snprintfz(webfilename, FILENAME_MAX, "%s/%s", web_dir, filename);
326
-
327
- // check if the file exists
328
- struct stat stat;
329
- if(lstat(webfilename, &stat) != 0) {
330
- debug(D_WEB_CLIENT_ACCESS, "%llu: File '%s' is not found.", w->id, webfilename);
331
- buffer_sprintf(w->response.data, "File '%s' does not exist, or is not accessible.", webfilename);
332
- return 404;
333
- }
334
-
335
- // check if the file is owned by expected user
336
- if(stat.st_uid != web_files_uid()) {
337
- error("%llu: File '%s' is owned by user %u (expected user %u). Access Denied.", w->id, webfilename, stat.st_uid, web_files_uid());
338
- buffer_sprintf(w->response.data, "Access to file '%s' is not permitted.", webfilename);
339
- return 403;
340
- }
341
-
342
- // check if the file is owned by expected group
343
- if(stat.st_gid != web_files_gid()) {
344
- error("%llu: File '%s' is owned by group %u (expected group %u). Access Denied.", w->id, webfilename, stat.st_gid, web_files_gid());
345
- buffer_sprintf(w->response.data, "Access to file '%s' is not permitted.", webfilename);
346
- return 403;
347
- }
348
-
349
- if((stat.st_mode & S_IFMT) == S_IFDIR) {
350
- snprintfz(webfilename, FILENAME_MAX, "%s/index.html", filename);
351
- return mysendfile(w, webfilename);
352
- }
353
-
354
- if((stat.st_mode & S_IFMT) != S_IFREG) {
355
- error("%llu: File '%s' is not a regular file. Access Denied.", w->id, webfilename);
356
- buffer_sprintf(w->response.data, "Access to file '%s' is not permitted.", webfilename);
357
- return 403;
358
- }
359
-
360
- // open the file
361
- w->ifd = open(webfilename, O_NONBLOCK, O_RDONLY);
362
- if(w->ifd == -1) {
363
- w->ifd = w->ofd;
364
-
365
- if(errno == EBUSY || errno == EAGAIN) {
366
- error("%llu: File '%s' is busy, sending 307 Moved Temporarily to force retry.", w->id, webfilename);
367
- buffer_sprintf(w->response.header, "Location: /" WEB_PATH_FILE "/%s\r\n", filename);
368
- buffer_sprintf(w->response.data, "The file '%s' is currently busy. Please try again later.", webfilename);
369
- return 307;
370
- }
371
- else {
372
- error("%llu: Cannot open file '%s'.", w->id, webfilename);
373
- buffer_sprintf(w->response.data, "Cannot open file '%s'.", webfilename);
374
- return 404;
375
- }
376
- }
377
- if(fcntl(w->ifd, F_SETFL, O_NONBLOCK) < 0)
378
- error("%llu: Cannot set O_NONBLOCK on file '%s'.", w->id, webfilename);
379
-
380
- // pick a Content-Type for the file
381
- if(strstr(filename, ".html") != NULL) w->response.data->contenttype = CT_TEXT_HTML;
382
- else if(strstr(filename, ".js") != NULL) w->response.data->contenttype = CT_APPLICATION_X_JAVASCRIPT;
383
- else if(strstr(filename, ".css") != NULL) w->response.data->contenttype = CT_TEXT_CSS;
384
- else if(strstr(filename, ".xml") != NULL) w->response.data->contenttype = CT_TEXT_XML;
385
- else if(strstr(filename, ".xsl") != NULL) w->response.data->contenttype = CT_TEXT_XSL;
386
- else if(strstr(filename, ".txt") != NULL) w->response.data->contenttype = CT_TEXT_PLAIN;
387
- else if(strstr(filename, ".svg") != NULL) w->response.data->contenttype = CT_IMAGE_SVG_XML;
388
- else if(strstr(filename, ".ttf") != NULL) w->response.data->contenttype = CT_APPLICATION_X_FONT_TRUETYPE;
389
- else if(strstr(filename, ".otf") != NULL) w->response.data->contenttype = CT_APPLICATION_X_FONT_OPENTYPE;
390
- else if(strstr(filename, ".woff2")!= NULL) w->response.data->contenttype = CT_APPLICATION_FONT_WOFF2;
391
- else if(strstr(filename, ".woff") != NULL) w->response.data->contenttype = CT_APPLICATION_FONT_WOFF;
392
- else if(strstr(filename, ".eot") != NULL) w->response.data->contenttype = CT_APPLICATION_VND_MS_FONTOBJ;
393
- else if(strstr(filename, ".png") != NULL) w->response.data->contenttype = CT_IMAGE_PNG;
394
- else if(strstr(filename, ".jpg") != NULL) w->response.data->contenttype = CT_IMAGE_JPG;
395
- else if(strstr(filename, ".jpeg") != NULL) w->response.data->contenttype = CT_IMAGE_JPG;
396
- else if(strstr(filename, ".gif") != NULL) w->response.data->contenttype = CT_IMAGE_GIF;
397
- else if(strstr(filename, ".bmp") != NULL) w->response.data->contenttype = CT_IMAGE_BMP;
398
- else if(strstr(filename, ".ico") != NULL) w->response.data->contenttype = CT_IMAGE_XICON;
399
- else if(strstr(filename, ".icns") != NULL) w->response.data->contenttype = CT_IMAGE_ICNS;
400
- else w->response.data->contenttype = CT_APPLICATION_OCTET_STREAM;
401
-
402
- debug(D_WEB_CLIENT_ACCESS, "%llu: Sending file '%s' (%ld bytes, ifd %d, ofd %d).", w->id, webfilename, stat.st_size, w->ifd, w->ofd);
403
-
404
- w->mode = WEB_CLIENT_MODE_FILECOPY;
405
- w->wait_receive = 1;
406
- w->wait_send = 0;
407
- buffer_flush(w->response.data);
408
- w->response.rlen = stat.st_size;
409
- w->response.data->date = stat.st_mtim.tv_sec;
410
-
411
- return 200;
293
+ static char *web_dir = NULL;
294
+
295
+ // initialize our static data
296
+ if(unlikely(!web_dir)) web_dir = config_get("global", "web files directory", WEB_DIR);
297
+
298
+ debug(D_WEB_CLIENT, "%llu: Looking for file '%s/%s'", w->id, web_dir, filename);
299
+
300
+ // skip leading slashes
301
+ while (*filename == '/') filename++;
302
+
303
+ // if the filename contain known paths, skip them
304
+ if(strncmp(filename, WEB_PATH_FILE "/", strlen(WEB_PATH_FILE) + 1) == 0)
305
+ filename = &filename[strlen(WEB_PATH_FILE) + 1];
306
+
307
+ char *s;
308
+ for(s = filename; *s ;s++) {
309
+ if( !isalnum(*s) && *s != '/' && *s != '.' && *s != '-' && *s != '_') {
310
+ debug(D_WEB_CLIENT_ACCESS, "%llu: File '%s' is not acceptable.", w->id, filename);
311
+ buffer_sprintf(w->response.data, "File '%s' cannot be served. Filename contains invalid character '%c'", filename, *s);
312
+ return 400;
313
+ }
314
+ }
315
+
316
+ // if the filename contains a .. refuse to serve it
317
+ if(strstr(filename, "..") != 0) {
318
+ debug(D_WEB_CLIENT_ACCESS, "%llu: File '%s' is not acceptable.", w->id, filename);
319
+ buffer_sprintf(w->response.data, "File '%s' cannot be served. Relative filenames with '..' in them are not supported.", filename);
320
+ return 400;
321
+ }
322
+
323
+ // access the file
324
+ char webfilename[FILENAME_MAX + 1];
325
+ snprintfz(webfilename, FILENAME_MAX, "%s/%s", web_dir, filename);
326
+
327
+ // check if the file exists
328
+ struct stat stat;
329
+ if(lstat(webfilename, &stat) != 0) {
330
+ debug(D_WEB_CLIENT_ACCESS, "%llu: File '%s' is not found.", w->id, webfilename);
331
+ buffer_sprintf(w->response.data, "File '%s' does not exist, or is not accessible.", webfilename);
332
+ return 404;
333
+ }
334
+
335
+ // check if the file is owned by expected user
336
+ if(stat.st_uid != web_files_uid()) {
337
+ error("%llu: File '%s' is owned by user %u (expected user %u). Access Denied.", w->id, webfilename, stat.st_uid, web_files_uid());
338
+ buffer_sprintf(w->response.data, "Access to file '%s' is not permitted.", webfilename);
339
+ return 403;
340
+ }
341
+
342
+ // check if the file is owned by expected group
343
+ if(stat.st_gid != web_files_gid()) {
344
+ error("%llu: File '%s' is owned by group %u (expected group %u). Access Denied.", w->id, webfilename, stat.st_gid, web_files_gid());
345
+ buffer_sprintf(w->response.data, "Access to file '%s' is not permitted.", webfilename);
346
+ return 403;
347
+ }
348
+
349
+ if((stat.st_mode & S_IFMT) == S_IFDIR) {
350
+ snprintfz(webfilename, FILENAME_MAX, "%s/index.html", filename);
351
+ return mysendfile(w, webfilename);
352
+ }
353
+
354
+ if((stat.st_mode & S_IFMT) != S_IFREG) {
355
+ error("%llu: File '%s' is not a regular file. Access Denied.", w->id, webfilename);
356
+ buffer_sprintf(w->response.data, "Access to file '%s' is not permitted.", webfilename);
357
+ return 403;
358
+ }
359
+
360
+ // open the file
361
+ w->ifd = open(webfilename, O_NONBLOCK, O_RDONLY);
362
+ if(w->ifd == -1) {
363
+ w->ifd = w->ofd;
364
+
365
+ if(errno == EBUSY || errno == EAGAIN) {
366
+ error("%llu: File '%s' is busy, sending 307 Moved Temporarily to force retry.", w->id, webfilename);
367
+ buffer_sprintf(w->response.header, "Location: /" WEB_PATH_FILE "/%s\r\n", filename);
368
+ buffer_sprintf(w->response.data, "The file '%s' is currently busy. Please try again later.", webfilename);
369
+ return 307;
370
+ }
371
+ else {
372
+ error("%llu: Cannot open file '%s'.", w->id, webfilename);
373
+ buffer_sprintf(w->response.data, "Cannot open file '%s'.", webfilename);
374
+ return 404;
375
+ }
376
+ }
377
+ if(fcntl(w->ifd, F_SETFL, O_NONBLOCK) < 0)
378
+ error("%llu: Cannot set O_NONBLOCK on file '%s'.", w->id, webfilename);
379
+
380
+ // pick a Content-Type for the file
381
+ if(strstr(filename, ".html") != NULL) w->response.data->contenttype = CT_TEXT_HTML;
382
+ else if(strstr(filename, ".js") != NULL) w->response.data->contenttype = CT_APPLICATION_X_JAVASCRIPT;
383
+ else if(strstr(filename, ".css") != NULL) w->response.data->contenttype = CT_TEXT_CSS;
384
+ else if(strstr(filename, ".xml") != NULL) w->response.data->contenttype = CT_TEXT_XML;
385
+ else if(strstr(filename, ".xsl") != NULL) w->response.data->contenttype = CT_TEXT_XSL;
386
+ else if(strstr(filename, ".txt") != NULL) w->response.data->contenttype = CT_TEXT_PLAIN;
387
+ else if(strstr(filename, ".svg") != NULL) w->response.data->contenttype = CT_IMAGE_SVG_XML;
388
+ else if(strstr(filename, ".ttf") != NULL) w->response.data->contenttype = CT_APPLICATION_X_FONT_TRUETYPE;
389
+ else if(strstr(filename, ".otf") != NULL) w->response.data->contenttype = CT_APPLICATION_X_FONT_OPENTYPE;
390
+ else if(strstr(filename, ".woff2")!= NULL) w->response.data->contenttype = CT_APPLICATION_FONT_WOFF2;
391
+ else if(strstr(filename, ".woff") != NULL) w->response.data->contenttype = CT_APPLICATION_FONT_WOFF;
392
+ else if(strstr(filename, ".eot") != NULL) w->response.data->contenttype = CT_APPLICATION_VND_MS_FONTOBJ;
393
+ else if(strstr(filename, ".png") != NULL) w->response.data->contenttype = CT_IMAGE_PNG;
394
+ else if(strstr(filename, ".jpg") != NULL) w->response.data->contenttype = CT_IMAGE_JPG;
395
+ else if(strstr(filename, ".jpeg") != NULL) w->response.data->contenttype = CT_IMAGE_JPG;
396
+ else if(strstr(filename, ".gif") != NULL) w->response.data->contenttype = CT_IMAGE_GIF;
397
+ else if(strstr(filename, ".bmp") != NULL) w->response.data->contenttype = CT_IMAGE_BMP;
398
+ else if(strstr(filename, ".ico") != NULL) w->response.data->contenttype = CT_IMAGE_XICON;
399
+ else if(strstr(filename, ".icns") != NULL) w->response.data->contenttype = CT_IMAGE_ICNS;
400
+ else w->response.data->contenttype = CT_APPLICATION_OCTET_STREAM;
401
+
402
+ debug(D_WEB_CLIENT_ACCESS, "%llu: Sending file '%s' (%ld bytes, ifd %d, ofd %d).", w->id, webfilename, stat.st_size, w->ifd, w->ofd);
403
+
404
+ w->mode = WEB_CLIENT_MODE_FILECOPY;
405
+ w->wait_receive = 1;
406
+ w->wait_send = 0;
407
+ buffer_flush(w->response.data);
408
+ w->response.rlen = stat.st_size;
409
+ w->response.data->date = stat.st_mtim.tv_sec;
410
+
411
+ return 200;
412
}
413
414
415
#ifdef NETDATA_WITH_ZLIB
416
void web_client_enable_deflate(struct web_client *w, int gzip) {
417
- if(unlikely(w->response.zinitialized)) {
418
- error("%llu: Compression has already be initialized for this client.", w->id);
419
- return;
420
- }
421
-
422
- if(unlikely(w->response.sent)) {
423
- error("%llu: Cannot enable compression in the middle of a conversation.", w->id);
424
- return;
425
- }
426
-
427
- w->response.zstream.zalloc = Z_NULL;
428
- w->response.zstream.zfree = Z_NULL;
429
- w->response.zstream.opaque = Z_NULL;
430
-
431
- w->response.zstream.next_in = (Bytef *)w->response.data->buffer;
432
- w->response.zstream.avail_in = 0;
433
- w->response.zstream.total_in = 0;
434
-
435
- w->response.zstream.next_out = w->response.zbuffer;
436
- w->response.zstream.avail_out = 0;
437
- w->response.zstream.total_out = 0;
438
-
439
- w->response.zstream.zalloc = Z_NULL;
440
- w->response.zstream.zfree = Z_NULL;
441
- w->response.zstream.opaque = Z_NULL;
442
-
443
-// if(deflateInit(&w->response.zstream, Z_DEFAULT_COMPRESSION) != Z_OK) {
444
-// error("%llu: Failed to initialize zlib. Proceeding without compression.", w->id);
445
-// return;
446
-// }
447
-
448
- // Select GZIP compression: windowbits = 15 + 16 = 31
449
- if(deflateInit2(&w->response.zstream, web_gzip_level, Z_DEFLATED, 15 + ((gzip)?16:0), 8, web_gzip_strategy) != Z_OK) {
450
- error("%llu: Failed to initialize zlib. Proceeding without compression.", w->id);
451
- return;
452
- }
453
-
454
- w->response.zsent = 0;
455
- w->response.zoutput = 1;
456
- w->response.zinitialized = 1;
457
-
458
- debug(D_DEFLATE, "%llu: Initialized compression.", w->id);
417
+ if(unlikely(w->response.zinitialized)) {
418
+ error("%llu: Compression has already be initialized for this client.", w->id);
419
+ return;
420
+ }
421
+
422
+ if(unlikely(w->response.sent)) {
423
+ error("%llu: Cannot enable compression in the middle of a conversation.", w->id);
424
+ return;
425
+ }
426
+
427
+ w->response.zstream.zalloc = Z_NULL;
428
+ w->response.zstream.zfree = Z_NULL;
429
+ w->response.zstream.opaque = Z_NULL;
430
+
431
+ w->response.zstream.next_in = (Bytef *)w->response.data->buffer;
432
+ w->response.zstream.avail_in = 0;
433
+ w->response.zstream.total_in = 0;
434
+
435
+ w->response.zstream.next_out = w->response.zbuffer;
436
+ w->response.zstream.avail_out = 0;
437
+ w->response.zstream.total_out = 0;
438
+
439
+ w->response.zstream.zalloc = Z_NULL;
440
+ w->response.zstream.zfree = Z_NULL;
441
+ w->response.zstream.opaque = Z_NULL;
442
+
443
+// if(deflateInit(&w->response.zstream, Z_DEFAULT_COMPRESSION) != Z_OK) {
444
+// error("%llu: Failed to initialize zlib. Proceeding without compression.", w->id);
445
+// return;
446
+// }
447
+
448
+ // Select GZIP compression: windowbits = 15 + 16 = 31
449
+ if(deflateInit2(&w->response.zstream, web_gzip_level, Z_DEFLATED, 15 + ((gzip)?16:0), 8, web_gzip_strategy) != Z_OK) {
450
+ error("%llu: Failed to initialize zlib. Proceeding without compression.", w->id);
451
+ return;
452
+ }
453
+
454
+ w->response.zsent = 0;
455
+ w->response.zoutput = 1;
456
+ w->response.zinitialized = 1;
457
+
458
+ debug(D_DEFLATE, "%llu: Initialized compression.", w->id);
459
}
460
#endif // NETDATA_WITH_ZLIB
461
462
uint32_t web_client_api_request_v1_data_options(char *o)
463
{
464
- uint32_t ret = 0x00000000;
465
- char *tok;
466
-
467
- while(o && *o && (tok = mystrsep(&o, ", |"))) {
468
- if(!*tok) continue;
469
-
470
- if(!strcmp(tok, "nonzero"))
471
- ret |= RRDR_OPTION_NONZERO;
472
- else if(!strcmp(tok, "flip") || !strcmp(tok, "reversed") || !strcmp(tok, "reverse"))
473
- ret |= RRDR_OPTION_REVERSED;
474
- else if(!strcmp(tok, "jsonwrap"))
475
- ret |= RRDR_OPTION_JSON_WRAP;
476
- else if(!strcmp(tok, "min2max"))
477
- ret |= RRDR_OPTION_MIN2MAX;
478
- else if(!strcmp(tok, "ms") || !strcmp(tok, "milliseconds"))
479
- ret |= RRDR_OPTION_MILLISECONDS;
480
- else if(!strcmp(tok, "abs") || !strcmp(tok, "absolute") || !strcmp(tok, "absolute_sum") || !strcmp(tok, "absolute-sum"))
481
- ret |= RRDR_OPTION_ABSOLUTE;
482
- else if(!strcmp(tok, "seconds"))
483
- ret |= RRDR_OPTION_SECONDS;
484
- else if(!strcmp(tok, "null2zero"))
485
- ret |= RRDR_OPTION_NULL2ZERO;
486
- else if(!strcmp(tok, "objectrows"))
487
- ret |= RRDR_OPTION_OBJECTSROWS;
488
- else if(!strcmp(tok, "google_json"))
489
- ret |= RRDR_OPTION_GOOGLE_JSON;
490
- else if(!strcmp(tok, "percentage"))
491
- ret |= RRDR_OPTION_PERCENTAGE;
492
- else if(!strcmp(tok, "unaligned"))
493
- ret |= RRDR_OPTION_NOT_ALIGNED;
494
- }
495
-
496
- return ret;
464
+ uint32_t ret = 0x00000000;
465
+ char *tok;
466
+
467
+ while(o && *o && (tok = mystrsep(&o, ", |"))) {
468
+ if(!*tok) continue;
469
+
470
+ if(!strcmp(tok, "nonzero"))
471
+ ret |= RRDR_OPTION_NONZERO;
472
+ else if(!strcmp(tok, "flip") || !strcmp(tok, "reversed") || !strcmp(tok, "reverse"))
473
+ ret |= RRDR_OPTION_REVERSED;
474
+ else if(!strcmp(tok, "jsonwrap"))
475
+ ret |= RRDR_OPTION_JSON_WRAP;
476
+ else if(!strcmp(tok, "min2max"))
477
+ ret |= RRDR_OPTION_MIN2MAX;
478
+ else if(!strcmp(tok, "ms") || !strcmp(tok, "milliseconds"))
479
+ ret |= RRDR_OPTION_MILLISECONDS;
480
+ else if(!strcmp(tok, "abs") || !strcmp(tok, "absolute") || !strcmp(tok, "absolute_sum") || !strcmp(tok, "absolute-sum"))
481
+ ret |= RRDR_OPTION_ABSOLUTE;
482
+ else if(!strcmp(tok, "seconds"))
483
+ ret |= RRDR_OPTION_SECONDS;
484
+ else if(!strcmp(tok, "null2zero"))
485
+ ret |= RRDR_OPTION_NULL2ZERO;
486
+ else if(!strcmp(tok, "objectrows"))
487
+ ret |= RRDR_OPTION_OBJECTSROWS;
488
+ else if(!strcmp(tok, "google_json"))
489
+ ret |= RRDR_OPTION_GOOGLE_JSON;
490
+ else if(!strcmp(tok, "percentage"))
491
+ ret |= RRDR_OPTION_PERCENTAGE;
492
+ else if(!strcmp(tok, "unaligned"))
493
+ ret |= RRDR_OPTION_NOT_ALIGNED;
494
+ }
495
+
496
+ return ret;
497
}
498
499
uint32_t web_client_api_request_v1_data_format(char *name)
500
{
501
- if(!strcmp(name, DATASOURCE_FORMAT_DATATABLE_JSON)) // datatable
502
- return DATASOURCE_DATATABLE_JSON;
501
+ if(!strcmp(name, DATASOURCE_FORMAT_DATATABLE_JSON)) // datatable
502
+ return DATASOURCE_DATATABLE_JSON;
503
504
- else if(!strcmp(name, DATASOURCE_FORMAT_DATATABLE_JSONP)) // datasource
505
- return DATASOURCE_DATATABLE_JSONP;
504
+ else if(!strcmp(name, DATASOURCE_FORMAT_DATATABLE_JSONP)) // datasource
505
+ return DATASOURCE_DATATABLE_JSONP;
506
507
- else if(!strcmp(name, DATASOURCE_FORMAT_JSON)) // json
508
- return DATASOURCE_JSON;
507
+ else if(!strcmp(name, DATASOURCE_FORMAT_JSON)) // json
508
+ return DATASOURCE_JSON;
509
510
- else if(!strcmp(name, DATASOURCE_FORMAT_JSONP)) // jsonp
511
- return DATASOURCE_JSONP;
510
+ else if(!strcmp(name, DATASOURCE_FORMAT_JSONP)) // jsonp
511
+ return DATASOURCE_JSONP;
512
513
- else if(!strcmp(name, DATASOURCE_FORMAT_SSV)) // ssv
514
- return DATASOURCE_SSV;
513
+ else if(!strcmp(name, DATASOURCE_FORMAT_SSV)) // ssv
514
+ return DATASOURCE_SSV;
515
516
- else if(!strcmp(name, DATASOURCE_FORMAT_CSV)) // csv
517
- return DATASOURCE_CSV;
516
+ else if(!strcmp(name, DATASOURCE_FORMAT_CSV)) // csv
517
+ return DATASOURCE_CSV;
518
519
- else if(!strcmp(name, DATASOURCE_FORMAT_TSV) || !strcmp(name, "tsv-excel")) // tsv
520
- return DATASOURCE_TSV;
519
+ else if(!strcmp(name, DATASOURCE_FORMAT_TSV) || !strcmp(name, "tsv-excel")) // tsv
520
+ return DATASOURCE_TSV;
521
522
- else if(!strcmp(name, DATASOURCE_FORMAT_HTML)) // html
523
- return DATASOURCE_HTML;
522
+ else if(!strcmp(name, DATASOURCE_FORMAT_HTML)) // html
523
+ return DATASOURCE_HTML;
524
525
- else if(!strcmp(name, DATASOURCE_FORMAT_JS_ARRAY)) // array
526
- return DATASOURCE_JS_ARRAY;
525
+ else if(!strcmp(name, DATASOURCE_FORMAT_JS_ARRAY)) // array
526
+ return DATASOURCE_JS_ARRAY;
527
528
- else if(!strcmp(name, DATASOURCE_FORMAT_SSV_COMMA)) // ssvcomma
529
- return DATASOURCE_SSV_COMMA;
528
+ else if(!strcmp(name, DATASOURCE_FORMAT_SSV_COMMA)) // ssvcomma
529
+ return DATASOURCE_SSV_COMMA;
530
531
- else if(!strcmp(name, DATASOURCE_FORMAT_CSV_JSON_ARRAY)) // csvjsonarray
532
- return DATASOURCE_CSV_JSON_ARRAY;
531
+ else if(!strcmp(name, DATASOURCE_FORMAT_CSV_JSON_ARRAY)) // csvjsonarray
532
+ return DATASOURCE_CSV_JSON_ARRAY;
533
534
- return DATASOURCE_JSON;
534
+ return DATASOURCE_JSON;
535
}
536
537
uint32_t web_client_api_request_v1_data_google_format(char *name)
538
{
539
- if(!strcmp(name, "json"))
540
- return DATASOURCE_DATATABLE_JSONP;
539
+ if(!strcmp(name, "json"))
540
+ return DATASOURCE_DATATABLE_JSONP;
541
542
- else if(!strcmp(name, "html"))
543
- return DATASOURCE_HTML;
542
+ else if(!strcmp(name, "html"))
543
+ return DATASOURCE_HTML;
544
545
- else if(!strcmp(name, "csv"))
546
- return DATASOURCE_CSV;
545
+ else if(!strcmp(name, "csv"))
546
+ return DATASOURCE_CSV;
547
548
- else if(!strcmp(name, "tsv-excel"))
549
- return DATASOURCE_TSV;
548
+ else if(!strcmp(name, "tsv-excel"))
549
+ return DATASOURCE_TSV;
550
551
- return DATASOURCE_JSON;
551
+ return DATASOURCE_JSON;
552
}
553
554
int web_client_api_request_v1_data_group(char *name, int def)
555
{
556
- if(!strcmp(name, "max"))
557
- return GROUP_MAX;
556
+ if(!strcmp(name, "max"))
557
+ return GROUP_MAX;
558
559
- else if(!strcmp(name, "average"))
560
- return GROUP_AVERAGE;
559
+ else if(!strcmp(name, "average"))
560
+ return GROUP_AVERAGE;
561
562
- else if(!strcmp(name, "sum"))
563
- return GROUP_SUM;
562
+ else if(!strcmp(name, "sum"))
563
+ return GROUP_SUM;
564
565
- else if(!strcmp(name, "incremental-sum"))
566
- return GROUP_INCREMENTAL_SUM;
565
+ else if(!strcmp(name, "incremental-sum"))
566
+ return GROUP_INCREMENTAL_SUM;
567
568
- return def;
568
+ return def;
569
}
570
571
int web_client_api_request_v1_charts(struct web_client *w, char *url)
572
{
573
- if(url) { ; }
573
+ if(url) { ; }
574
575
- buffer_flush(w->response.data);
576
- w->response.data->contenttype = CT_APPLICATION_JSON;
577
- rrd_stats_api_v1_charts(w->response.data);
578
- return 200;
575
+ buffer_flush(w->response.data);
576
+ w->response.data->contenttype = CT_APPLICATION_JSON;
577
+ rrd_stats_api_v1_charts(w->response.data);
578
+ return 200;
579
}
580
581
int web_client_api_request_v1_chart(struct web_client *w, char *url)
582
{
583
- int ret = 400;
584
- char *chart = NULL;
585
-
586
- buffer_flush(w->response.data);
587
-
588
- while(url) {
589
- char *value = mystrsep(&url, "?&[]");
590
- if(!value || !*value) continue;
591
-
592
- char *name = mystrsep(&value, "=");
593
- if(!name || !*name) continue;
594
- if(!value || !*value) continue;
595
-
596
- // name and value are now the parameters
597
- // they are not null and not empty
598
-
599
- if(!strcmp(name, "chart")) chart = value;
600
- //else {
601
- /// buffer_sprintf(w->response.data, "Unknown parameter '%s' in request.", name);
602
- // goto cleanup;
603
- //}
604
- }
605
-
606
- if(!chart || !*chart) {
607
- buffer_sprintf(w->response.data, "No chart id is given at the request.");
608
- goto cleanup;
609
- }
610
-
611
- RRDSET *st = rrdset_find(chart);
612
- if(!st) st = rrdset_find_byname(chart);
613
- if(!st) {
614
- buffer_sprintf(w->response.data, "Chart '%s' is not found.", chart);
615
- ret = 404;
616
- goto cleanup;
617
- }
618
-
619
- w->response.data->contenttype = CT_APPLICATION_JSON;
620
- rrd_stats_api_v1_chart(st, w->response.data);
621
- return 200;
583
+ int ret = 400;
584
+ char *chart = NULL;
585
+
586
+ buffer_flush(w->response.data);
587
+
588
+ while(url) {
589
+ char *value = mystrsep(&url, "?&[]");
590
+ if(!value || !*value) continue;
591
+
592
+ char *name = mystrsep(&value, "=");
593
+ if(!name || !*name) continue;
594
+ if(!value || !*value) continue;
595
+
596
+ // name and value are now the parameters
597
+ // they are not null and not empty
598
+
599
+ if(!strcmp(name, "chart")) chart = value;
600
+ //else {
601
+ /// buffer_sprintf(w->response.data, "Unknown parameter '%s' in request.", name);
602
+ // goto cleanup;
603
+ //}
604
+ }
605
+
606
+ if(!chart || !*chart) {
607
+ buffer_sprintf(w->response.data, "No chart id is given at the request.");
608
+ goto cleanup;
609
+ }
610
+
611
+ RRDSET *st = rrdset_find(chart);
612
+ if(!st) st = rrdset_find_byname(chart);
613
+ if(!st) {
614
+ buffer_sprintf(w->response.data, "Chart '%s' is not found.", chart);
615
+ ret = 404;
616
+ goto cleanup;
617
+ }
618
+
619
+ w->response.data->contenttype = CT_APPLICATION_JSON;
620
+ rrd_stats_api_v1_chart(st, w->response.data);
621
+ return 200;
622
623
cleanup:
624
- return ret;
624
+ return ret;
625
}
626
627
int web_client_api_v1_badge(struct web_client *w, char *url) {
628
- int ret = 400;
629
- buffer_flush(w->response.data);
630
-
631
- BUFFER *dimensions = NULL;
632
-
633
- const char *chart = NULL
634
- , *before_str = NULL
635
- , *after_str = NULL
636
- , *points_str = NULL
637
- , *multiply_str = NULL
638
- , *divide_str = NULL
639
- , *label = NULL
640
- , *units = NULL
641
- , *label_color = NULL
642
- , *value_color = NULL
643
- , *refresh_str = NULL
644
- , *precision_str = NULL;
645
-
646
- int group = GROUP_AVERAGE;
647
- uint32_t options = 0x00000000;
648
-
649
- while(url) {
650
- char *value = mystrsep(&url, "/?&[]");
651
- if(!value || !*value) continue;
652
-
653
- char *name = mystrsep(&value, "=");
654
- if(!name || !*name) continue;
655
- if(!value || !*value) continue;
656
-
657
- debug(D_WEB_CLIENT, "%llu: API v1 badge.svg query param '%s' with value '%s'", w->id, name, value);
658
-
659
- // name and value are now the parameters
660
- // they are not null and not empty
661
-
662
- if(!strcmp(name, "chart")) chart = value;
663
- else if(!strcmp(name, "dimension") || !strcmp(name, "dim") || !strcmp(name, "dimensions") || !strcmp(name, "dims")) {
664
- if(!dimensions)
665
- dimensions = buffer_create(100);
628
+ int ret = 400;
629
+ buffer_flush(w->response.data);
630
+
631
+ BUFFER *dimensions = NULL;
632
+
633
+ const char *chart = NULL
634
+ , *before_str = NULL
635
+ , *after_str = NULL
636
+ , *points_str = NULL
637
+ , *multiply_str = NULL
638
+ , *divide_str = NULL
639
+ , *label = NULL
640
+ , *units = NULL
641
+ , *label_color = NULL
642
+ , *value_color = NULL
643
+ , *refresh_str = NULL
644
+ , *precision_str = NULL;
645
+
646
+ int group = GROUP_AVERAGE;
647
+ uint32_t options = 0x00000000;
648
+
649
+ while(url) {
650
+ char *value = mystrsep(&url, "/?&[]");
651
+ if(!value || !*value) continue;
652
+
653
+ char *name = mystrsep(&value, "=");
654
+ if(!name || !*name) continue;
655
+ if(!value || !*value) continue;
656
+
657
+ debug(D_WEB_CLIENT, "%llu: API v1 badge.svg query param '%s' with value '%s'", w->id, name, value);
658
+
659
+ // name and value are now the parameters
660
+ // they are not null and not empty
661
+
662
+ if(!strcmp(name, "chart")) chart = value;
663
+ else if(!strcmp(name, "dimension") || !strcmp(name, "dim") || !strcmp(name, "dimensions") || !strcmp(name, "dims")) {
664
+ if(!dimensions)
665
+ dimensions = buffer_create(100);
666
667
buffer_strcat(dimensions, "|");
668
buffer_strcat(dimensions, value);
669
- }
670
- else if(!strcmp(name, "after")) after_str = value;
671
- else if(!strcmp(name, "before")) before_str = value;
672
- else if(!strcmp(name, "points")) points_str = value;
673
- else if(!strcmp(name, "group")) {
674
- group = web_client_api_request_v1_data_group(value, GROUP_AVERAGE);
675
- }
676
- else if(!strcmp(name, "options")) {
677
- options |= web_client_api_request_v1_data_options(value);
678
- }
679
- else if(!strcmp(name, "label")) label = value;
680
- else if(!strcmp(name, "units")) units = value;
681
- else if(!strcmp(name, "label_color")) label_color = value;
682
- else if(!strcmp(name, "value_color")) value_color = value;
683
- else if(!strcmp(name, "multiply")) multiply_str = value;
684
- else if(!strcmp(name, "divide")) divide_str = value;
685
- else if(!strcmp(name, "refresh")) refresh_str = value;
686
- else if(!strcmp(name, "precision")) precision_str = value;
687
- }
688
-
689
- if(!chart || !*chart) {
690
- buffer_sprintf(w->response.data, "No chart id is given at the request.");
691
- goto cleanup;
692
- }
693
-
694
- RRDSET *st = rrdset_find(chart);
695
- if(!st) st = rrdset_find_byname(chart);
696
- if(!st) {
697
- buffer_svg(w->response.data, "chart not found", 0, "", NULL, NULL, 1, -1);
698
- ret = 200;
699
- goto cleanup;
700
- }
701
-
702
- long long multiply = (multiply_str && *multiply_str )?atol(multiply_str):1;
703
- long long divide = (divide_str && *divide_str )?atol(divide_str):1;
704
- long long before = (before_str && *before_str )?atol(before_str):0;
705
- long long after = (after_str && *after_str )?atol(after_str):-st->update_every;
706
- int points = (points_str && *points_str )?atoi(points_str):1;
707
- int precision = (precision_str && *precision_str)?atoi(precision_str):-1;
708
-
709
- if(!multiply) multiply = 1;
710
- if(!divide) divide = 1;
711
-
712
- int refresh = 0;
713
- if(refresh_str && *refresh_str) {
714
- if(!strcmp(refresh_str, "auto")) {
715
- if(options & RRDR_OPTION_NOT_ALIGNED)
716
- refresh = st->update_every;
717
- else {
718
- refresh = (before - after);
719
- if(refresh < 0) refresh = -refresh;
720
- }
721
- }
722
- else {
723
- refresh = atoi(refresh_str);
724
- if(refresh < 0) refresh = -refresh;
725
- }
726
- }
727
-
728
- if(!label) {
729
- if(dimensions) {
730
- const char *dim = buffer_tostring(dimensions);
731
- if(*dim == '|') dim++;
732
- label = dim;
733
- }
734
- else
735
- label = st->name;
736
- }
737
- if(!units) {
738
- if(options & RRDR_OPTION_PERCENTAGE)
739
- units="%";
740
- else
741
- units = st->units;
742
- }
743
-
744
- debug(D_WEB_CLIENT, "%llu: API command 'badge.svg' for chart '%s', dimensions '%s', after '%lld', before '%lld', points '%d', group '%d', options '0x%08x'"
745
- , w->id
746
- , chart
747
- , (dimensions)?buffer_tostring(dimensions):""
748
- , after
749
- , before
750
- , points
751
- , group
752
- , options
753
- );
754
-
755
- time_t latest_timestamp = 0;
756
- int value_is_null = 1;
757
- calculated_number n = 0;
758
- ret = 500;
759
-
760
- // if the collected value is too old, don't calculate its value
761
- if(rrdset_last_entry_t(st) >= (time(NULL) - (st->update_every * st->gap_when_lost_iterations_above)))
762
- ret = rrd2value(st, w->response.data, &n, dimensions, points, after, before, group, options, &latest_timestamp, &value_is_null);
763
-
764
- // if the value cannot be calculated, show empty badge
765
- if(ret != 200) {
766
- value_is_null = 1;
767
- n = 0;
768
- ret = 200;
769
- }
770
- else if(refresh > 0)
771
- buffer_sprintf(w->response.header, "Refresh: %d\r\n", refresh);
772
-
773
- // render the badge
774
- buffer_svg(w->response.data, label, n * multiply / divide, units, label_color, value_color, value_is_null, precision);
669
+ }
670
+ else if(!strcmp(name, "after")) after_str = value;
671
+ else if(!strcmp(name, "before")) before_str = value;
672
+ else if(!strcmp(name, "points")) points_str = value;
673
+ else if(!strcmp(name, "group")) {
674
+ group = web_client_api_request_v1_data_group(value, GROUP_AVERAGE);
675
+ }
676
+ else if(!strcmp(name, "options")) {
677
+ options |= web_client_api_request_v1_data_options(value);
678
+ }
679
+ else if(!strcmp(name, "label")) label = value;
680
+ else if(!strcmp(name, "units")) units = value;
681
+ else if(!strcmp(name, "label_color")) label_color = value;
682
+ else if(!strcmp(name, "value_color")) value_color = value;
683
+ else if(!strcmp(name, "multiply")) multiply_str = value;
684
+ else if(!strcmp(name, "divide")) divide_str = value;
685
+ else if(!strcmp(name, "refresh")) refresh_str = value;
686
+ else if(!strcmp(name, "precision")) precision_str = value;
687
+ }
688
+
689
+ if(!chart || !*chart) {
690
+ buffer_sprintf(w->response.data, "No chart id is given at the request.");
691
+ goto cleanup;
692
+ }
693
+
694
+ RRDSET *st = rrdset_find(chart);
695
+ if(!st) st = rrdset_find_byname(chart);
696
+ if(!st) {
697
+ buffer_svg(w->response.data, "chart not found", 0, "", NULL, NULL, 1, -1);
698
+ ret = 200;
699
+ goto cleanup;
700
+ }
701
+
702
+ long long multiply = (multiply_str && *multiply_str )?atol(multiply_str):1;
703
+ long long divide = (divide_str && *divide_str )?atol(divide_str):1;
704
+ long long before = (before_str && *before_str )?atol(before_str):0;
705
+ long long after = (after_str && *after_str )?atol(after_str):-st->update_every;
706
+ int points = (points_str && *points_str )?atoi(points_str):1;
707
+ int precision = (precision_str && *precision_str)?atoi(precision_str):-1;
708
+
709
+ if(!multiply) multiply = 1;
710
+ if(!divide) divide = 1;
711
+
712
+ int refresh = 0;
713
+ if(refresh_str && *refresh_str) {
714
+ if(!strcmp(refresh_str, "auto")) {
715
+ if(options & RRDR_OPTION_NOT_ALIGNED)
716
+ refresh = st->update_every;
717
+ else {
718
+ refresh = (before - after);
719
+ if(refresh < 0) refresh = -refresh;
720
+ }
721
+ }
722
+ else {
723
+ refresh = atoi(refresh_str);
724
+ if(refresh < 0) refresh = -refresh;
725
+ }
726
+ }
727
+
728
+ if(!label) {
729
+ if(dimensions) {
730
+ const char *dim = buffer_tostring(dimensions);
731
+ if(*dim == '|') dim++;
732
+ label = dim;
733
+ }
734
+ else
735
+ label = st->name;
736
+ }
737
+ if(!units) {
738
+ if(options & RRDR_OPTION_PERCENTAGE)
739
+ units="%";
740
+ else
741
+ units = st->units;
742
+ }
743
+
744
+ debug(D_WEB_CLIENT, "%llu: API command 'badge.svg' for chart '%s', dimensions '%s', after '%lld', before '%lld', points '%d', group '%d', options '0x%08x'"
745
+ , w->id
746
+ , chart
747
+ , (dimensions)?buffer_tostring(dimensions):""
748
+ , after
749
+ , before
750
+ , points
751
+ , group
752
+ , options
753
+ );
754
+
755
+ time_t latest_timestamp = 0;
756
+ int value_is_null = 1;
757
+ calculated_number n = 0;
758
+ ret = 500;
759
+
760
+ // if the collected value is too old, don't calculate its value
761
+ if(rrdset_last_entry_t(st) >= (time(NULL) - (st->update_every * st->gap_when_lost_iterations_above)))
762
+ ret = rrd2value(st, w->response.data, &n, dimensions, points, after, before, group, options, &latest_timestamp, &value_is_null);
763
+
764
+ // if the value cannot be calculated, show empty badge
765
+ if(ret != 200) {
766
+ value_is_null = 1;
767
+ n = 0;
768
+ ret = 200;
769
+ }
770
+ else if(refresh > 0)
771
+ buffer_sprintf(w->response.header, "Refresh: %d\r\n", refresh);
772
+
773
+ // render the badge
774
+ buffer_svg(w->response.data, label, n * multiply / divide, units, label_color, value_color, value_is_null, precision);
775
776
cleanup:
777
- if(dimensions)
778
- buffer_free(dimensions);
779
- return ret;
777
+ if(dimensions)
778
+ buffer_free(dimensions);
779
+ return ret;
780
}
781
782
// returns the HTTP code
783
int web_client_api_request_v1_data(struct web_client *w, char *url)
784
{
785
- debug(D_WEB_CLIENT, "%llu: API v1 data with URL '%s'", w->id, url);
785
+ debug(D_WEB_CLIENT, "%llu: API v1 data with URL '%s'", w->id, url);
786
787
- int ret = 400;
788
- BUFFER *dimensions = NULL;
787
+ int ret = 400;
788
+ BUFFER *dimensions = NULL;
789
790
- buffer_flush(w->response.data);
790
+ buffer_flush(w->response.data);
791
792
- char *google_version = "0.6",
793
- *google_reqId = "0",
794
- *google_sig = "0",
795
- *google_out = "json",
796
- *responseHandler = NULL,
797
- *outFileName = NULL;
792
+ char *google_version = "0.6",
793
+ *google_reqId = "0",
794
+ *google_sig = "0",
795
+ *google_out = "json",
796
+ *responseHandler = NULL,
797
+ *outFileName = NULL;
798
799
- time_t last_timestamp_in_data = 0, google_timestamp = 0;
799
+ time_t last_timestamp_in_data = 0, google_timestamp = 0;
800
801
- char *chart = NULL
802
- , *before_str = NULL
803
- , *after_str = NULL
804
- , *points_str = NULL;
801
+ char *chart = NULL
802
+ , *before_str = NULL
803
+ , *after_str = NULL
804
+ , *points_str = NULL;
805
806
- int group = GROUP_AVERAGE;
807
- uint32_t format = DATASOURCE_JSON;
808
- uint32_t options = 0x00000000;
806
+ int group = GROUP_AVERAGE;
807
+ uint32_t format = DATASOURCE_JSON;
808
+ uint32_t options = 0x00000000;
809
810
- while(url) {
811
- char *value = mystrsep(&url, "?&[]");
812
- if(!value || !*value) continue;
810
+ while(url) {
811
+ char *value = mystrsep(&url, "?&[]");
812
+ if(!value || !*value) continue;
813
814
- char *name = mystrsep(&value, "=");
815
- if(!name || !*name) continue;
816
- if(!value || !*value) continue;
814
+ char *name = mystrsep(&value, "=");
815
+ if(!name || !*name) continue;
816
+ if(!value || !*value) continue;
817
818
- debug(D_WEB_CLIENT, "%llu: API v1 data query param '%s' with value '%s'", w->id, name, value);
818
+ debug(D_WEB_CLIENT, "%llu: API v1 data query param '%s' with value '%s'", w->id, name, value);
819
820
- // name and value are now the parameters
821
- // they are not null and not empty
820
+ // name and value are now the parameters
821
+ // they are not null and not empty
822
823
- if(!strcmp(name, "chart")) chart = value;
824
- else if(!strcmp(name, "dimension") || !strcmp(name, "dim") || !strcmp(name, "dimensions") || !strcmp(name, "dims")) {
825
- if(!dimensions) dimensions = buffer_create(100);
823
+ if(!strcmp(name, "chart")) chart = value;
824
+ else if(!strcmp(name, "dimension") || !strcmp(name, "dim") || !strcmp(name, "dimensions") || !strcmp(name, "dims")) {
825
+ if(!dimensions) dimensions = buffer_create(100);
826
buffer_strcat(dimensions, "|");
827
buffer_strcat(dimensions, value);
828
- }
829
- else if(!strcmp(name, "after")) after_str = value;
830
- else if(!strcmp(name, "before")) before_str = value;
831
- else if(!strcmp(name, "points")) points_str = value;
832
- else if(!strcmp(name, "group")) {
833
- group = web_client_api_request_v1_data_group(value, GROUP_AVERAGE);
834
- }
835
- else if(!strcmp(name, "format")) {
836
- format = web_client_api_request_v1_data_format(value);
837
- }
838
- else if(!strcmp(name, "options")) {
839
- options |= web_client_api_request_v1_data_options(value);
840
- }
841
- else if(!strcmp(name, "callback")) {
842
- responseHandler = value;
843
- }
844
- else if(!strcmp(name, "filename")) {
845
- outFileName = value;
846
- }
847
- else if(!strcmp(name, "tqx")) {
848
- // parse Google Visualization API options
849
- // https://developers.google.com/chart/interactive/docs/dev/implementing_data_source
850
- char *tqx_name, *tqx_value;
851
-
852
- while(value) {
853
- tqx_value = mystrsep(&value, ";");
854
- if(!tqx_value || !*tqx_value) continue;
855
-
856
- tqx_name = mystrsep(&tqx_value, ":");
857
- if(!tqx_name || !*tqx_name) continue;
858
- if(!tqx_value || !*tqx_value) continue;
859
-
860
- if(!strcmp(tqx_name, "version"))
861
- google_version = tqx_value;
862
- else if(!strcmp(tqx_name, "reqId"))
863
- google_reqId = tqx_value;
864
- else if(!strcmp(tqx_name, "sig")) {
865
- google_sig = tqx_value;
866
- google_timestamp = strtoul(google_sig, NULL, 0);
867
- }
868
- else if(!strcmp(tqx_name, "out")) {
869
- google_out = tqx_value;
870
- format = web_client_api_request_v1_data_google_format(google_out);
871
- }
872
- else if(!strcmp(tqx_name, "responseHandler"))
873
- responseHandler = tqx_value;
874
- else if(!strcmp(tqx_name, "outFileName"))
875
- outFileName = tqx_value;
876
- }
877
- }
878
- }
879
-
880
- if(!chart || !*chart) {
881
- buffer_sprintf(w->response.data, "No chart id is given at the request.");
882
- goto cleanup;
883
- }
884
-
885
- RRDSET *st = rrdset_find(chart);
886
- if(!st) st = rrdset_find_byname(chart);
887
- if(!st) {
888
- buffer_sprintf(w->response.data, "Chart '%s' is not found.", chart);
889
- ret = 404;
890
- goto cleanup;
891
- }
892
-
893
- long long before = (before_str && *before_str)?atol(before_str):0;
894
- long long after = (after_str && *after_str) ?atol(after_str):0;
895
- int points = (points_str && *points_str)?atoi(points_str):0;
896
-
897
- debug(D_WEB_CLIENT, "%llu: API command 'data' for chart '%s', dimensions '%s', after '%lld', before '%lld', points '%d', group '%d', format '%u', options '0x%08x'"
898
- , w->id
899
- , chart
900
- , (dimensions)?buffer_tostring(dimensions):""
901
- , after
902
- , before
903
- , points
904
- , group
905
- , format
906
- , options
907
- );
908
-
909
- if(outFileName && *outFileName) {
910
- buffer_sprintf(w->response.header, "Content-Disposition: attachment; filename=\"%s\"\r\n", outFileName);
911
- debug(D_WEB_CLIENT, "%llu: generating outfilename header: '%s'", w->id, outFileName);
912
- }
913
-
914
- if(format == DATASOURCE_DATATABLE_JSONP) {
915
- if(responseHandler == NULL)
916
- responseHandler = "google.visualization.Query.setResponse";
917
-
918
- debug(D_WEB_CLIENT_ACCESS, "%llu: GOOGLE JSON/JSONP: version = '%s', reqId = '%s', sig = '%s', out = '%s', responseHandler = '%s', outFileName = '%s'",
919
- w->id, google_version, google_reqId, google_sig, google_out, responseHandler, outFileName
920
- );
921
-
922
- buffer_sprintf(w->response.data,
923
- "%s({version:'%s',reqId:'%s',status:'ok',sig:'%ld',table:",
924
- responseHandler, google_version, google_reqId, st->last_updated.tv_sec);
925
- }
926
- else if(format == DATASOURCE_JSONP) {
927
- if(responseHandler == NULL)
928
- responseHandler = "callback";
929
-
930
- buffer_strcat(w->response.data, responseHandler);
931
- buffer_strcat(w->response.data, "(");
932
- }
933
-
934
- ret = rrd2format(st, w->response.data, dimensions, format, points, after, before, group, options, &last_timestamp_in_data);
935
-
936
- if(format == DATASOURCE_DATATABLE_JSONP) {
937
- if(google_timestamp < last_timestamp_in_data)
938
- buffer_strcat(w->response.data, "});");
939
-
940
- else {
941
- // the client already has the latest data
942
- buffer_flush(w->response.data);
943
- buffer_sprintf(w->response.data,
944
- "%s({version:'%s',reqId:'%s',status:'error',errors:[{reason:'not_modified',message:'Data not modified'}]});",
945
- responseHandler, google_version, google_reqId);
946
- }
947
- }
948
- else if(format == DATASOURCE_JSONP)
949
- buffer_strcat(w->response.data, ");");
828
+ }
829
+ else if(!strcmp(name, "after")) after_str = value;
830
+ else if(!strcmp(name, "before")) before_str = value;
831
+ else if(!strcmp(name, "points")) points_str = value;
832
+ else if(!strcmp(name, "group")) {
833
+ group = web_client_api_request_v1_data_group(value, GROUP_AVERAGE);
834
+ }
835
+ else if(!strcmp(name, "format")) {
836
+ format = web_client_api_request_v1_data_format(value);
837
+ }
838
+ else if(!strcmp(name, "options")) {
839
+ options |= web_client_api_request_v1_data_options(value);
840
+ }
841
+ else if(!strcmp(name, "callback")) {
842
+ responseHandler = value;
843
+ }
844
+ else if(!strcmp(name, "filename")) {
845
+ outFileName = value;
846
+ }
847
+ else if(!strcmp(name, "tqx")) {
848
+ // parse Google Visualization API options
849
+ // https://developers.google.com/chart/interactive/docs/dev/implementing_data_source
850
+ char *tqx_name, *tqx_value;
851
+
852
+ while(value) {
853
+ tqx_value = mystrsep(&value, ";");
854
+ if(!tqx_value || !*tqx_value) continue;
855
+
856
+ tqx_name = mystrsep(&tqx_value, ":");
857
+ if(!tqx_name || !*tqx_name) continue;
858
+ if(!tqx_value || !*tqx_value) continue;
859
+
860
+ if(!strcmp(tqx_name, "version"))
861
+ google_version = tqx_value;
862
+ else if(!strcmp(tqx_name, "reqId"))
863
+ google_reqId = tqx_value;
864
+ else if(!strcmp(tqx_name, "sig")) {
865
+ google_sig = tqx_value;
866
+ google_timestamp = strtoul(google_sig, NULL, 0);
867
+ }
868
+ else if(!strcmp(tqx_name, "out")) {
869
+ google_out = tqx_value;
870
+ format = web_client_api_request_v1_data_google_format(google_out);
871
+ }
872
+ else if(!strcmp(tqx_name, "responseHandler"))
873
+ responseHandler = tqx_value;
874
+ else if(!strcmp(tqx_name, "outFileName"))
875
+ outFileName = tqx_value;
876
+ }
877
+ }
878
+ }
879
+
880
+ if(!chart || !*chart) {
881
+ buffer_sprintf(w->response.data, "No chart id is given at the request.");
882
+ goto cleanup;
883
+ }
884
+
885
+ RRDSET *st = rrdset_find(chart);
886
+ if(!st) st = rrdset_find_byname(chart);
887
+ if(!st) {
888
+ buffer_sprintf(w->response.data, "Chart '%s' is not found.", chart);
889
+ ret = 404;
890
+ goto cleanup;
891
+ }
892
+
893
+ long long before = (before_str && *before_str)?atol(before_str):0;
894
+ long long after = (after_str && *after_str) ?atol(after_str):0;
895
+ int points = (points_str && *points_str)?atoi(points_str):0;
896
+
897
+ debug(D_WEB_CLIENT, "%llu: API command 'data' for chart '%s', dimensions '%s', after '%lld', before '%lld', points '%d', group '%d', format '%u', options '0x%08x'"
898
+ , w->id
899
+ , chart
900
+ , (dimensions)?buffer_tostring(dimensions):""
901
+ , after
902
+ , before
903
+ , points
904
+ , group
905
+ , format
906
+ , options
907
+ );
908
+
909
+ if(outFileName && *outFileName) {
910
+ buffer_sprintf(w->response.header, "Content-Disposition: attachment; filename=\"%s\"\r\n", outFileName);
911
+ debug(D_WEB_CLIENT, "%llu: generating outfilename header: '%s'", w->id, outFileName);
912
+ }
913
+
914
+ if(format == DATASOURCE_DATATABLE_JSONP) {
915
+ if(responseHandler == NULL)
916
+ responseHandler = "google.visualization.Query.setResponse";
917
+
918
+ debug(D_WEB_CLIENT_ACCESS, "%llu: GOOGLE JSON/JSONP: version = '%s', reqId = '%s', sig = '%s', out = '%s', responseHandler = '%s', outFileName = '%s'",
919
+ w->id, google_version, google_reqId, google_sig, google_out, responseHandler, outFileName
920
+ );
921
+
922
+ buffer_sprintf(w->response.data,
923
+ "%s({version:'%s',reqId:'%s',status:'ok',sig:'%ld',table:",
924
+ responseHandler, google_version, google_reqId, st->last_updated.tv_sec);
925
+ }
926
+ else if(format == DATASOURCE_JSONP) {
927
+ if(responseHandler == NULL)
928
+ responseHandler = "callback";
929
+
930
+ buffer_strcat(w->response.data, responseHandler);
931
+ buffer_strcat(w->response.data, "(");
932
+ }
933
+
934
+ ret = rrd2format(st, w->response.data, dimensions, format, points, after, before, group, options, &last_timestamp_in_data);
935
+
936
+ if(format == DATASOURCE_DATATABLE_JSONP) {
937
+ if(google_timestamp < last_timestamp_in_data)
938
+ buffer_strcat(w->response.data, "});");
939
+
940
+ else {
941
+ // the client already has the latest data
942
+ buffer_flush(w->response.data);
943
+ buffer_sprintf(w->response.data,
944
+ "%s({version:'%s',reqId:'%s',status:'error',errors:[{reason:'not_modified',message:'Data not modified'}]});",
945
+ responseHandler, google_version, google_reqId);
946
+ }
947
+ }
948
+ else if(format == DATASOURCE_JSONP)
949
+ buffer_strcat(w->response.data, ");");
950
951
cleanup:
952
- if(dimensions) buffer_free(dimensions);
953
- return ret;
952
+ if(dimensions) buffer_free(dimensions);
953
+ return ret;
954
}
955
956
int web_client_api_request_v1_registry(struct web_client *w, char *url)
957
{
958
- static uint32_t hash_action = 0, hash_access = 0, hash_hello = 0, hash_delete = 0, hash_search = 0,
959
- hash_switch = 0, hash_machine = 0, hash_url = 0, hash_name = 0, hash_delete_url = 0, hash_for = 0,
960
- hash_to = 0 /*, hash_redirects = 0 */;
961
-
962
- if(unlikely(!hash_action)) {
963
- hash_action = simple_hash("action");
964
- hash_access = simple_hash("access");
965
- hash_hello = simple_hash("hello");
966
- hash_delete = simple_hash("delete");
967
- hash_search = simple_hash("search");
968
- hash_switch = simple_hash("switch");
969
- hash_machine = simple_hash("machine");
970
- hash_url = simple_hash("url");
971
- hash_name = simple_hash("name");
972
- hash_delete_url = simple_hash("delete_url");
973
- hash_for = simple_hash("for");
974
- hash_to = simple_hash("to");
958
+ static uint32_t hash_action = 0, hash_access = 0, hash_hello = 0, hash_delete = 0, hash_search = 0,
959
+ hash_switch = 0, hash_machine = 0, hash_url = 0, hash_name = 0, hash_delete_url = 0, hash_for = 0,
960
+ hash_to = 0 /*, hash_redirects = 0 */;
961
+
962
+ if(unlikely(!hash_action)) {
963
+ hash_action = simple_hash("action");
964
+ hash_access = simple_hash("access");
965
+ hash_hello = simple_hash("hello");
966
+ hash_delete = simple_hash("delete");
967
+ hash_search = simple_hash("search");
968
+ hash_switch = simple_hash("switch");
969
+ hash_machine = simple_hash("machine");
970
+ hash_url = simple_hash("url");
971
+ hash_name = simple_hash("name");
972
+ hash_delete_url = simple_hash("delete_url");
973
+ hash_for = simple_hash("for");
974
+ hash_to = simple_hash("to");
975
/*
976
- hash_redirects = simple_hash("redirects");
976
+ hash_redirects = simple_hash("redirects");
977
*/
978
- }
979
-
980
- char person_guid[36 + 1] = "";
981
-
982
- debug(D_WEB_CLIENT, "%llu: API v1 registry with URL '%s'", w->id, url);
983
-
984
- // FIXME
985
- // The browser may send multiple cookies with our id
986
-
987
- char *cookie = strstr(w->response.data->buffer, NETDATA_REGISTRY_COOKIE_NAME "=");
988
- if(cookie)
989
- strncpyz(person_guid, &cookie[sizeof(NETDATA_REGISTRY_COOKIE_NAME)], 36);
990
-
991
- char action = '\0';
992
- char *machine_guid = NULL,
993
- *machine_url = NULL,
994
- *url_name = NULL,
995
- *search_machine_guid = NULL,
996
- *delete_url = NULL,
997
- *to_person_guid = NULL;
978
+ }
979
+
980
+ char person_guid[36 + 1] = "";
981
+
982
+ debug(D_WEB_CLIENT, "%llu: API v1 registry with URL '%s'", w->id, url);
983
+
984
+ // FIXME
985
+ // The browser may send multiple cookies with our id
986
+
987
+ char *cookie = strstr(w->response.data->buffer, NETDATA_REGISTRY_COOKIE_NAME "=");
988
+ if(cookie)
989
+ strncpyz(person_guid, &cookie[sizeof(NETDATA_REGISTRY_COOKIE_NAME)], 36);
990
+
991
+ char action = '\0';
992
+ char *machine_guid = NULL,
993
+ *machine_url = NULL,
994
+ *url_name = NULL,
995
+ *search_machine_guid = NULL,
996
+ *delete_url = NULL,
997
+ *to_person_guid = NULL;
998
/*
999
- int redirects = 0;
999
+ int redirects = 0;
1000
*/
1001
1002
- while(url) {
1003
- char *value = mystrsep(&url, "?&[]");
1004
- if (!value || !*value) continue;
1002
+ while(url) {
1003
+ char *value = mystrsep(&url, "?&[]");
1004
+ if (!value || !*value) continue;
1005
1006
- char *name = mystrsep(&value, "=");
1007
- if (!name || !*name) continue;
1008
- if (!value || !*value) continue;
1006
+ char *name = mystrsep(&value, "=");
1007
+ if (!name || !*name) continue;
1008
+ if (!value || !*value) continue;
1009
1010
- debug(D_WEB_CLIENT, "%llu: API v1 registry query param '%s' with value '%s'", w->id, name, value);
1010
+ debug(D_WEB_CLIENT, "%llu: API v1 registry query param '%s' with value '%s'", w->id, name, value);
1011
1012
- uint32_t hash = simple_hash(name);
1012
+ uint32_t hash = simple_hash(name);
1013
1014
- if(hash == hash_action && !strcmp(name, "action")) {
1015
- uint32_t vhash = simple_hash(value);
1014
+ if(hash == hash_action && !strcmp(name, "action")) {
1015
+ uint32_t vhash = simple_hash(value);
1016
1017
- if(vhash == hash_access && !strcmp(value, "access")) action = 'A';
1018
- else if(vhash == hash_hello && !strcmp(value, "hello")) action = 'H';
1019
- else if(vhash == hash_delete && !strcmp(value, "delete")) action = 'D';
1020
- else if(vhash == hash_search && !strcmp(value, "search")) action = 'S';
1021
- else if(vhash == hash_switch && !strcmp(value, "switch")) action = 'W';
1017
+ if(vhash == hash_access && !strcmp(value, "access")) action = 'A';
1018
+ else if(vhash == hash_hello && !strcmp(value, "hello")) action = 'H';
1019
+ else if(vhash == hash_delete && !strcmp(value, "delete")) action = 'D';
1020
+ else if(vhash == hash_search && !strcmp(value, "search")) action = 'S';
1021
+ else if(vhash == hash_switch && !strcmp(value, "switch")) action = 'W';
1022
#ifdef NETDATA_INTERNAL_CHECKS
1023
else error("unknown registry action '%s'", value);
1024
#endif /* NETDATA_INTERNAL_CHECKS */
1025
- }
1025
+ }
1026
/*
1027
- else if(hash == hash_redirects && !strcmp(name, "redirects"))
1028
- redirects = atoi(value);
1027
+ else if(hash == hash_redirects && !strcmp(name, "redirects"))
1028
+ redirects = atoi(value);
1029
*/
1030
- else if(hash == hash_machine && !strcmp(name, "machine"))
1031
- machine_guid = value;
1032
-
1033
- else if(hash == hash_url && !strcmp(name, "url"))
1034
- machine_url = value;
1035
-
1036
- else if(action == 'A') {
1037
- if(hash == hash_name && !strcmp(name, "name"))
1038
- url_name = value;
1039
- }
1040
- else if(action == 'D') {
1041
- if(hash == hash_delete_url && !strcmp(name, "delete_url"))
1042
- delete_url = value;
1043
- }
1044
- else if(action == 'S') {
1045
- if(hash == hash_for && !strcmp(name, "for"))
1046
- search_machine_guid = value;
1047
- }
1048
- else if(action == 'W') {
1049
- if(hash == hash_to && !strcmp(name, "to"))
1050
- to_person_guid = value;
1051
- }
1030
+ else if(hash == hash_machine && !strcmp(name, "machine"))
1031
+ machine_guid = value;
1032
+
1033
+ else if(hash == hash_url && !strcmp(name, "url"))
1034
+ machine_url = value;
1035
+
1036
+ else if(action == 'A') {
1037
+ if(hash == hash_name && !strcmp(name, "name"))
1038
+ url_name = value;
1039
+ }
1040
+ else if(action == 'D') {
1041
+ if(hash == hash_delete_url && !strcmp(name, "delete_url"))
1042
+ delete_url = value;
1043
+ }
1044
+ else if(action == 'S') {
1045
+ if(hash == hash_for && !strcmp(name, "for"))
1046
+ search_machine_guid = value;
1047
+ }
1048
+ else if(action == 'W') {
1049
+ if(hash == hash_to && !strcmp(name, "to"))
1050
+ to_person_guid = value;
1051
+ }
1052
#ifdef NETDATA_INTERNAL_CHECKS
1053
- else error("unused registry URL parameter '%s' with value '%s'", name, value);
1053
+ else error("unused registry URL parameter '%s' with value '%s'", name, value);
1054
#endif /* NETDATA_INTERNAL_CHECKS */
1055
- }
1056
-
1057
- if(web_donotrack_comply && w->donottrack) {
1058
- buffer_flush(w->response.data);
1059
- buffer_sprintf(w->response.data, "Your web browser is sending 'DNT: 1' (Do Not Track). The registry requires persistent cookies on your browser to work.");
1060
- return 400;
1061
- }
1062
-
1063
- if(action == 'A' && (!machine_guid || !machine_url || !url_name)) {
1064
- buffer_flush(w->response.data);
1065
- buffer_sprintf(w->response.data, "Invalid registry request - access requires these parameters: machine ('%s'), url ('%s'), name ('%s')",
1066
- machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", url_name?url_name:"UNSET");
1067
- return 400;
1068
- }
1069
- else if(action == 'D' && (!machine_guid || !machine_url || !delete_url)) {
1070
- buffer_flush(w->response.data);
1071
- buffer_sprintf(w->response.data, "Invalid registry request - delete requires these parameters: machine ('%s'), url ('%s'), delete_url ('%s')",
1072
- machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", delete_url?delete_url:"UNSET");
1073
- return 400;
1074
- }
1075
- else if(action == 'S' && (!machine_guid || !machine_url || !search_machine_guid)) {
1076
- buffer_flush(w->response.data);
1077
- buffer_sprintf(w->response.data, "Invalid registry request - search requires these parameters: machine ('%s'), url ('%s'), for ('%s')",
1078
- machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", search_machine_guid?search_machine_guid:"UNSET");
1079
- return 400;
1080
- }
1081
- else if(action == 'W' && (!machine_guid || !machine_url || !to_person_guid)) {
1082
- buffer_flush(w->response.data);
1083
- buffer_sprintf(w->response.data, "Invalid registry request - switching identity requires these parameters: machine ('%s'), url ('%s'), to ('%s')",
1084
- machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", to_person_guid?to_person_guid:"UNSET");
1085
- return 400;
1086
- }
1087
-
1088
- switch(action) {
1089
- case 'A':
1090
- w->tracking_required = 1;
1091
- if(registry_verify_cookies_redirects() > 0 && (!cookie || !person_guid[0])) {
1092
- buffer_flush(w->response.data);
1093
-
1094
- registry_set_cookie(w, "give-me-back-this-cookie-please");
1095
- w->response.data->contenttype = CT_APPLICATION_JSON;
1096
- buffer_sprintf(w->response.data, "{ \"status\": \"redirect\", \"registry\": \"%s\" }", registry_to_announce());
1097
- return 200;
1055
+ }
1056
+
1057
+ if(web_donotrack_comply && w->donottrack) {
1058
+ buffer_flush(w->response.data);
1059
+ buffer_sprintf(w->response.data, "Your web browser is sending 'DNT: 1' (Do Not Track). The registry requires persistent cookies on your browser to work.");
1060
+ return 400;
1061
+ }
1062
+
1063
+ if(action == 'A' && (!machine_guid || !machine_url || !url_name)) {
1064
+ buffer_flush(w->response.data);
1065
+ buffer_sprintf(w->response.data, "Invalid registry request - access requires these parameters: machine ('%s'), url ('%s'), name ('%s')",
1066
+ machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", url_name?url_name:"UNSET");
1067
+ return 400;
1068
+ }
1069
+ else if(action == 'D' && (!machine_guid || !machine_url || !delete_url)) {
1070
+ buffer_flush(w->response.data);
1071
+ buffer_sprintf(w->response.data, "Invalid registry request - delete requires these parameters: machine ('%s'), url ('%s'), delete_url ('%s')",
1072
+ machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", delete_url?delete_url:"UNSET");
1073
+ return 400;
1074
+ }
1075
+ else if(action == 'S' && (!machine_guid || !machine_url || !search_machine_guid)) {
1076
+ buffer_flush(w->response.data);
1077
+ buffer_sprintf(w->response.data, "Invalid registry request - search requires these parameters: machine ('%s'), url ('%s'), for ('%s')",
1078
+ machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", search_machine_guid?search_machine_guid:"UNSET");
1079
+ return 400;
1080
+ }
1081
+ else if(action == 'W' && (!machine_guid || !machine_url || !to_person_guid)) {
1082
+ buffer_flush(w->response.data);
1083
+ buffer_sprintf(w->response.data, "Invalid registry request - switching identity requires these parameters: machine ('%s'), url ('%s'), to ('%s')",
1084
+ machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", to_person_guid?to_person_guid:"UNSET");
1085
+ return 400;
1086
+ }
1087
+
1088
+ switch(action) {
1089
+ case 'A':
1090
+ w->tracking_required = 1;
1091
+ if(registry_verify_cookies_redirects() > 0 && (!cookie || !person_guid[0])) {
1092
+ buffer_flush(w->response.data);
1093
+
1094
+ registry_set_cookie(w, "give-me-back-this-cookie-please");
1095
+ w->response.data->contenttype = CT_APPLICATION_JSON;
1096
+ buffer_sprintf(w->response.data, "{ \"status\": \"redirect\", \"registry\": \"%s\" }", registry_to_announce());
1097
+ return 200;
1098
1099
/*
1100
* it seems that web browsers are ignoring 307 (Moved Temporarily)
1101
* under certain conditions, when using CORS
1102
* so this is commented and we use application level redirects instead
1103
*
1104
- redirects++;
1105
-
1106
- if(redirects > registry_verify_cookies_redirects()) {
1107
- buffer_flush(w->response.data);
1108
- buffer_sprintf(w->response.data, "Your browser does not support cookies");
1109
- return 400;
1110
- }
1111
-
1112
- char *encoded_url = url_encode(machine_url);
1113
- if(!encoded_url) {
1114
- error("%llu: Cannot URL encode string '%s'", w->id, machine_url);
1115
- return 500;
1116
- }
1117
-
1118
- char *encoded_name = url_encode(url_name);
1119
- if(!encoded_name) {
1120
- free(encoded_url);
1121
- error("%llu: Cannot URL encode string '%s'", w->id, url_name);
1122
- return 500;
1123
- }
1124
-
1125
- char *encoded_guid = url_encode(machine_guid);
1126
- if(!encoded_guid) {
1127
- free(encoded_url);
1128
- free(encoded_name);
1129
- error("%llu: Cannot URL encode string '%s'", w->id, machine_guid);
1130
- return 500;
1131
- }
1132
-
1133
- buffer_sprintf(w->response.header, "Location: %s/api/v1/registry?action=access&machine=%s&name=%s&url=%s&redirects=%d\r\n",
1134
- registry_to_announce(), encoded_guid, encoded_name, encoded_url, redirects);
1135
-
1136
- free(encoded_guid);
1137
- free(encoded_name);
1138
- free(encoded_url);
1139
- return 307
1104
+ redirects++;
1105
+
1106
+ if(redirects > registry_verify_cookies_redirects()) {
1107
+ buffer_flush(w->response.data);
1108
+ buffer_sprintf(w->response.data, "Your browser does not support cookies");
1109
+ return 400;
1110
+ }
1111
+
1112
+ char *encoded_url = url_encode(machine_url);
1113
+ if(!encoded_url) {
1114
+ error("%llu: Cannot URL encode string '%s'", w->id, machine_url);
1115
+ return 500;
1116
+ }
1117
+
1118
+ char *encoded_name = url_encode(url_name);
1119
+ if(!encoded_name) {
1120
+ free(encoded_url);
1121
+ error("%llu: Cannot URL encode string '%s'", w->id, url_name);
1122
+ return 500;
1123
+ }
1124
+
1125
+ char *encoded_guid = url_encode(machine_guid);
1126
+ if(!encoded_guid) {
1127
+ free(encoded_url);
1128
+ free(encoded_name);
1129
+ error("%llu: Cannot URL encode string '%s'", w->id, machine_guid);
1130
+ return 500;
1131
+ }
1132
+
1133
+ buffer_sprintf(w->response.header, "Location: %s/api/v1/registry?action=access&machine=%s&name=%s&url=%s&redirects=%d\r\n",
1134
+ registry_to_announce(), encoded_guid, encoded_name, encoded_url, redirects);
1135
+
1136
+ free(encoded_guid);
1137
+ free(encoded_name);
1138
+ free(encoded_url);
1139
+ return 307
1140
*/
1141
- }
1142
- return registry_request_access_json(w, person_guid, machine_guid, machine_url, url_name, time(NULL));
1141
+ }
1142
+ return registry_request_access_json(w, person_guid, machine_guid, machine_url, url_name, time(NULL));
1143
1144
- case 'D':
1145
- w->tracking_required = 1;
1146
- return registry_request_delete_json(w, person_guid, machine_guid, machine_url, delete_url, time(NULL));
1144
+ case 'D':
1145
+ w->tracking_required = 1;
1146
+ return registry_request_delete_json(w, person_guid, machine_guid, machine_url, delete_url, time(NULL));
1147
1148
- case 'S':
1149
- w->tracking_required = 1;
1150
- return registry_request_search_json(w, person_guid, machine_guid, machine_url, search_machine_guid, time(NULL));
1148
+ case 'S':
1149
+ w->tracking_required = 1;
1150
+ return registry_request_search_json(w, person_guid, machine_guid, machine_url, search_machine_guid, time(NULL));
1151
1152
- case 'W':
1153
- w->tracking_required = 1;
1154
- return registry_request_switch_json(w, person_guid, machine_guid, machine_url, to_person_guid, time(NULL));
1152
+ case 'W':
1153
+ w->tracking_required = 1;
1154
+ return registry_request_switch_json(w, person_guid, machine_guid, machine_url, to_person_guid, time(NULL));
1155
1156
- case 'H':
1157
- return registry_request_hello_json(w);
1156
+ case 'H':
1157
+ return registry_request_hello_json(w);
1158
1159
- default:
1160
- buffer_flush(w->response.data);
1161
- buffer_sprintf(w->response.data, "Invalid registry request - you need to set an action: hello, access, delete, search");
1162
- return 400;
1163
- }
1159
+ default:
1160
+ buffer_flush(w->response.data);
1161
+ buffer_sprintf(w->response.data, "Invalid registry request - you need to set an action: hello, access, delete, search");
1162
+ return 400;
1163
+ }
1164
1165
- buffer_flush(w->response.data);
1166
- buffer_sprintf(w->response.data, "Invalid or no registry action.");
1167
- return 400;
1165
+ buffer_flush(w->response.data);
1166
+ buffer_sprintf(w->response.data, "Invalid or no registry action.");
1167
+ return 400;
1168
}
1169
1170
int web_client_api_request_v1(struct web_client *w, char *url) {
1171
- static uint32_t hash_data = 0, hash_chart = 0, hash_charts = 0, hash_registry = 0, hash_badge = 0;
1172
-
1173
- if(unlikely(hash_data == 0)) {
1174
- hash_data = simple_hash("data");
1175
- hash_chart = simple_hash("chart");
1176
- hash_charts = simple_hash("charts");
1177
- hash_registry = simple_hash("registry");
1178
- hash_badge = simple_hash("badge.svg");
1179
- }
1180
-
1181
- // get the command
1182
- char *tok = mystrsep(&url, "/?&");
1183
- if(tok && *tok) {
1184
- debug(D_WEB_CLIENT, "%llu: Searching for API v1 command '%s'.", w->id, tok);
1185
- uint32_t hash = simple_hash(tok);
1186
-
1187
- if(hash == hash_data && !strcmp(tok, "data"))
1188
- return web_client_api_request_v1_data(w, url);
1189
-
1190
- else if(hash == hash_chart && !strcmp(tok, "chart"))
1191
- return web_client_api_request_v1_chart(w, url);
1192
-
1193
- else if(hash == hash_charts && !strcmp(tok, "charts"))
1194
- return web_client_api_request_v1_charts(w, url);
1195
-
1196
- else if(hash == hash_registry && !strcmp(tok, "registry"))
1197
- return web_client_api_request_v1_registry(w, url);
1198
-
1199
- else if(hash == hash_badge && !strcmp(tok, "badge.svg"))
1200
- return web_client_api_v1_badge(w, url);
1201
-
1202
- else {
1203
- buffer_flush(w->response.data);
1204
- buffer_sprintf(w->response.data, "Unsupported v1 API command: %s", tok);
1205
- return 404;
1206
- }
1207
- }
1208
- else {
1209
- buffer_flush(w->response.data);
1210
- buffer_sprintf(w->response.data, "API v1 command?");
1211
- return 400;
1212
- }
1171
+ static uint32_t hash_data = 0, hash_chart = 0, hash_charts = 0, hash_registry = 0, hash_badge = 0;
1172
+
1173
+ if(unlikely(hash_data == 0)) {
1174
+ hash_data = simple_hash("data");
1175
+ hash_chart = simple_hash("chart");
1176
+ hash_charts = simple_hash("charts");
1177
+ hash_registry = simple_hash("registry");
1178
+ hash_badge = simple_hash("badge.svg");
1179
+ }
1180
+
1181
+ // get the command
1182
+ char *tok = mystrsep(&url, "/?&");
1183
+ if(tok && *tok) {
1184
+ debug(D_WEB_CLIENT, "%llu: Searching for API v1 command '%s'.", w->id, tok);
1185
+ uint32_t hash = simple_hash(tok);
1186
+
1187
+ if(hash == hash_data && !strcmp(tok, "data"))
1188
+ return web_client_api_request_v1_data(w, url);
1189
+
1190
+ else if(hash == hash_chart && !strcmp(tok, "chart"))
1191
+ return web_client_api_request_v1_chart(w, url);
1192
+
1193
+ else if(hash == hash_charts && !strcmp(tok, "charts"))
1194
+ return web_client_api_request_v1_charts(w, url);
1195
+
1196
+ else if(hash == hash_registry && !strcmp(tok, "registry"))
1197
+ return web_client_api_request_v1_registry(w, url);
1198
+
1199
+ else if(hash == hash_badge && !strcmp(tok, "badge.svg"))
1200
+ return web_client_api_v1_badge(w, url);
1201
+
1202
+ else {
1203
+ buffer_flush(w->response.data);
1204
+ buffer_sprintf(w->response.data, "Unsupported v1 API command: %s", tok);
1205
+ return 404;
1206
+ }
1207
+ }
1208
+ else {
1209
+ buffer_flush(w->response.data);
1210
+ buffer_sprintf(w->response.data, "API v1 command?");
1211
+ return 400;
1212
+ }
1213
}
1214
1215
int web_client_api_request(struct web_client *w, char *url)
1216
{
1217
- // get the api version
1218
- char *tok = mystrsep(&url, "/?&");
1219
- if(tok && *tok) {
1220
- debug(D_WEB_CLIENT, "%llu: Searching for API version '%s'.", w->id, tok);
1221
- if(strcmp(tok, "v1") == 0)
1222
- return web_client_api_request_v1(w, url);
1223
- else {
1224
- buffer_flush(w->response.data);
1225
- buffer_sprintf(w->response.data, "Unsupported API version: %s", tok);
1226
- return 404;
1227
- }
1228
- }
1229
- else {
1230
- buffer_flush(w->response.data);
1231
- buffer_sprintf(w->response.data, "Which API version?");
1232
- return 400;
1233
- }
1217
+ // get the api version
1218
+ char *tok = mystrsep(&url, "/?&");
1219
+ if(tok && *tok) {
1220
+ debug(D_WEB_CLIENT, "%llu: Searching for API version '%s'.", w->id, tok);
1221
+ if(strcmp(tok, "v1") == 0)
1222
+ return web_client_api_request_v1(w, url);
1223
+ else {
1224
+ buffer_flush(w->response.data);
1225
+ buffer_sprintf(w->response.data, "Unsupported API version: %s", tok);
1226
+ return 404;
1227
+ }
1228
+ }
1229
+ else {
1230
+ buffer_flush(w->response.data);
1231
+ buffer_sprintf(w->response.data, "Which API version?");
1232
+ return 400;
1233
+ }
1234
}
1235
1236
int web_client_api_old_data_request(struct web_client *w, char *url, int datasource_type)
1237
{
1238
- RRDSET *st = NULL;
1239
-
1240
- char *args = strchr(url, '?');
1241
- if(args) {
1242
- *args='\0';
1243
- args = &args[1];
1244
- }
1245
-
1246
- // get the name of the data to show
1247
- char *tok = mystrsep(&url, "/");
1248
- if(!tok) tok = "";
1249
-
1250
- // do we have such a data set?
1251
- if(*tok) {
1252
- debug(D_WEB_CLIENT, "%llu: Searching for RRD data with name '%s'.", w->id, tok);
1253
- st = rrdset_find_byname(tok);
1254
- if(!st) st = rrdset_find(tok);
1255
- }
1256
-
1257
- if(!st) {
1258
- // we don't have it
1259
- // try to send a file with that name
1260
- buffer_flush(w->response.data);
1261
- return(mysendfile(w, tok));
1262
- }
1263
-
1264
- // we have it
1265
- debug(D_WEB_CLIENT, "%llu: Found RRD data with name '%s'.", w->id, tok);
1266
-
1267
- // how many entries does the client want?
1268
- int lines = rrd_default_history_entries;
1269
- int group_count = 1;
1270
- time_t after = 0, before = 0;
1271
- int group_method = GROUP_AVERAGE;
1272
- int nonzero = 0;
1273
-
1274
- if(url) {
1275
- // parse the lines required
1276
- tok = mystrsep(&url, "/");
1277
- if(tok) lines = atoi(tok);
1278
- if(lines < 1) lines = 1;
1279
- }
1280
- if(url) {
1281
- // parse the group count required
1282
- tok = mystrsep(&url, "/");
1283
- if(tok && *tok) group_count = atoi(tok);
1284
- if(group_count < 1) group_count = 1;
1285
- //if(group_count > save_history / 20) group_count = save_history / 20;
1286
- }
1287
- if(url) {
1288
- // parse the grouping method required
1289
- tok = mystrsep(&url, "/");
1290
- if(tok && *tok) {
1291
- if(strcmp(tok, "max") == 0) group_method = GROUP_MAX;
1292
- else if(strcmp(tok, "average") == 0) group_method = GROUP_AVERAGE;
1293
- else if(strcmp(tok, "sum") == 0) group_method = GROUP_SUM;
1294
- else debug(D_WEB_CLIENT, "%llu: Unknown group method '%s'", w->id, tok);
1295
- }
1296
- }
1297
- if(url) {
1298
- // parse after time
1299
- tok = mystrsep(&url, "/");
1300
- if(tok && *tok) after = strtoul(tok, NULL, 10);
1301
- if(after < 0) after = 0;
1302
- }
1303
- if(url) {
1304
- // parse before time
1305
- tok = mystrsep(&url, "/");
1306
- if(tok && *tok) before = strtoul(tok, NULL, 10);
1307
- if(before < 0) before = 0;
1308
- }
1309
- if(url) {
1310
- // parse nonzero
1311
- tok = mystrsep(&url, "/");
1312
- if(tok && *tok && strcmp(tok, "nonzero") == 0) nonzero = 1;
1313
- }
1314
-
1315
- w->response.data->contenttype = CT_APPLICATION_JSON;
1316
- buffer_flush(w->response.data);
1317
-
1318
- char *google_version = "0.6";
1319
- char *google_reqId = "0";
1320
- char *google_sig = "0";
1321
- char *google_out = "json";
1322
- char *google_responseHandler = "google.visualization.Query.setResponse";
1323
- char *google_outFileName = NULL;
1324
- time_t last_timestamp_in_data = 0;
1325
- if(datasource_type == DATASOURCE_DATATABLE_JSON || datasource_type == DATASOURCE_DATATABLE_JSONP) {
1326
-
1327
- w->response.data->contenttype = CT_APPLICATION_X_JAVASCRIPT;
1328
-
1329
- while(args) {
1330
- tok = mystrsep(&args, "&");
1331
- if(tok && *tok) {
1332
- char *name = mystrsep(&tok, "=");
1333
- if(name && *name && strcmp(name, "tqx") == 0) {
1334
- char *key = mystrsep(&tok, ":");
1335
- char *value = mystrsep(&tok, ";");
1336
- if(key && value && *key && *value) {
1337
- if(strcmp(key, "version") == 0)
1338
- google_version = value;
1339
-
1340
- else if(strcmp(key, "reqId") == 0)
1341
- google_reqId = value;
1342
-
1343
- else if(strcmp(key, "sig") == 0)
1344
- google_sig = value;
1345
-
1346
- else if(strcmp(key, "out") == 0)
1347
- google_out = value;
1348
-
1349
- else if(strcmp(key, "responseHandler") == 0)
1350
- google_responseHandler = value;
1351
-
1352
- else if(strcmp(key, "outFileName") == 0)
1353
- google_outFileName = value;
1354
- }
1355
- }
1356
- }
1357
- }
1358
-
1359
- debug(D_WEB_CLIENT_ACCESS, "%llu: GOOGLE JSONP: version = '%s', reqId = '%s', sig = '%s', out = '%s', responseHandler = '%s', outFileName = '%s'",
1360
- w->id, google_version, google_reqId, google_sig, google_out, google_responseHandler, google_outFileName
1361
- );
1362
-
1363
- if(datasource_type == DATASOURCE_DATATABLE_JSONP) {
1364
- last_timestamp_in_data = strtoul(google_sig, NULL, 0);
1365
-
1366
- // check the client wants json
1367
- if(strcmp(google_out, "json") != 0) {
1368
- buffer_sprintf(w->response.data,
1369
- "%s({version:'%s',reqId:'%s',status:'error',errors:[{reason:'invalid_query',message:'output format is not supported',detailed_message:'the format %s requested is not supported by netdata.'}]});",
1370
- google_responseHandler, google_version, google_reqId, google_out);
1371
- return 200;
1372
- }
1373
- }
1374
- }
1375
-
1376
- if(datasource_type == DATASOURCE_DATATABLE_JSONP) {
1377
- buffer_sprintf(w->response.data,
1378
- "%s({version:'%s',reqId:'%s',status:'ok',sig:'%ld',table:",
1379
- google_responseHandler, google_version, google_reqId, st->last_updated.tv_sec);
1380
- }
1381
-
1382
- debug(D_WEB_CLIENT_ACCESS, "%llu: Sending RRD data '%s' (id %s, %d lines, %d group, %d group_method, %ld after, %ld before).",
1383
- w->id, st->name, st->id, lines, group_count, group_method, after, before);
1384
-
1385
- time_t timestamp_in_data = rrd_stats_json(datasource_type, st, w->response.data, lines, group_count, group_method, (unsigned long)after, (unsigned long)before, nonzero);
1386
-
1387
- if(datasource_type == DATASOURCE_DATATABLE_JSONP) {
1388
- if(timestamp_in_data > last_timestamp_in_data)
1389
- buffer_strcat(w->response.data, "});");
1390
-
1391
- else {
1392
- // the client already has the latest data
1393
- buffer_flush(w->response.data);
1394
- buffer_sprintf(w->response.data,
1395
- "%s({version:'%s',reqId:'%s',status:'error',errors:[{reason:'not_modified',message:'Data not modified'}]});",
1396
- google_responseHandler, google_version, google_reqId);
1397
- }
1398
- }
1399
-
1400
- return 200;
1238
+ RRDSET *st = NULL;
1239
+
1240
+ char *args = strchr(url, '?');
1241
+ if(args) {
1242
+ *args='\0';
1243
+ args = &args[1];
1244
+ }
1245
+
1246
+ // get the name of the data to show
1247
+ char *tok = mystrsep(&url, "/");
1248
+ if(!tok) tok = "";
1249
+
1250
+ // do we have such a data set?
1251
+ if(*tok) {
1252
+ debug(D_WEB_CLIENT, "%llu: Searching for RRD data with name '%s'.", w->id, tok);
1253
+ st = rrdset_find_byname(tok);
1254
+ if(!st) st = rrdset_find(tok);
1255
+ }
1256
+
1257
+ if(!st) {
1258
+ // we don't have it
1259
+ // try to send a file with that name
1260
+ buffer_flush(w->response.data);
1261
+ return(mysendfile(w, tok));
1262
+ }
1263
+
1264
+ // we have it
1265
+ debug(D_WEB_CLIENT, "%llu: Found RRD data with name '%s'.", w->id, tok);
1266
+
1267
+ // how many entries does the client want?
1268
+ int lines = rrd_default_history_entries;
1269
+ int group_count = 1;
1270
+ time_t after = 0, before = 0;
1271
+ int group_method = GROUP_AVERAGE;
1272
+ int nonzero = 0;
1273
+
1274
+ if(url) {
1275
+ // parse the lines required
1276
+ tok = mystrsep(&url, "/");
1277
+ if(tok) lines = atoi(tok);
1278
+ if(lines < 1) lines = 1;
1279
+ }
1280
+ if(url) {
1281
+ // parse the group count required
1282
+ tok = mystrsep(&url, "/");
1283
+ if(tok && *tok) group_count = atoi(tok);
1284
+ if(group_count < 1) group_count = 1;
1285
+ //if(group_count > save_history / 20) group_count = save_history / 20;
1286
+ }
1287
+ if(url) {
1288
+ // parse the grouping method required
1289
+ tok = mystrsep(&url, "/");
1290
+ if(tok && *tok) {
1291
+ if(strcmp(tok, "max") == 0) group_method = GROUP_MAX;
1292
+ else if(strcmp(tok, "average") == 0) group_method = GROUP_AVERAGE;
1293
+ else if(strcmp(tok, "sum") == 0) group_method = GROUP_SUM;
1294
+ else debug(D_WEB_CLIENT, "%llu: Unknown group method '%s'", w->id, tok);
1295
+ }
1296
+ }
1297
+ if(url) {
1298
+ // parse after time
1299
+ tok = mystrsep(&url, "/");
1300
+ if(tok && *tok) after = strtoul(tok, NULL, 10);
1301
+ if(after < 0) after = 0;
1302
+ }
1303
+ if(url) {
1304
+ // parse before time
1305
+ tok = mystrsep(&url, "/");
1306
+ if(tok && *tok) before = strtoul(tok, NULL, 10);
1307
+ if(before < 0) before = 0;
1308
+ }
1309
+ if(url) {
1310
+ // parse nonzero
1311
+ tok = mystrsep(&url, "/");
1312
+ if(tok && *tok && strcmp(tok, "nonzero") == 0) nonzero = 1;
1313
+ }
1314
+
1315
+ w->response.data->contenttype = CT_APPLICATION_JSON;
1316
+ buffer_flush(w->response.data);
1317
+
1318
+ char *google_version = "0.6";
1319
+ char *google_reqId = "0";
1320
+ char *google_sig = "0";
1321
+ char *google_out = "json";
1322
+ char *google_responseHandler = "google.visualization.Query.setResponse";
1323
+ char *google_outFileName = NULL;
1324
+ time_t last_timestamp_in_data = 0;
1325
+ if(datasource_type == DATASOURCE_DATATABLE_JSON || datasource_type == DATASOURCE_DATATABLE_JSONP) {
1326
+
1327
+ w->response.data->contenttype = CT_APPLICATION_X_JAVASCRIPT;
1328
+
1329
+ while(args) {
1330
+ tok = mystrsep(&args, "&");
1331
+ if(tok && *tok) {
1332
+ char *name = mystrsep(&tok, "=");
1333
+ if(name && *name && strcmp(name, "tqx") == 0) {
1334
+ char *key = mystrsep(&tok, ":");
1335
+ char *value = mystrsep(&tok, ";");
1336
+ if(key && value && *key && *value) {
1337
+ if(strcmp(key, "version") == 0)
1338
+ google_version = value;
1339
+
1340
+ else if(strcmp(key, "reqId") == 0)
1341
+ google_reqId = value;
1342
+
1343
+ else if(strcmp(key, "sig") == 0)
1344
+ google_sig = value;
1345
+
1346
+ else if(strcmp(key, "out") == 0)
1347
+ google_out = value;
1348
+
1349
+ else if(strcmp(key, "responseHandler") == 0)
1350
+ google_responseHandler = value;
1351
+
1352
+ else if(strcmp(key, "outFileName") == 0)
1353
+ google_outFileName = value;
1354
+ }
1355
+ }
1356
+ }
1357
+ }
1358
+
1359
+ debug(D_WEB_CLIENT_ACCESS, "%llu: GOOGLE JSONP: version = '%s', reqId = '%s', sig = '%s', out = '%s', responseHandler = '%s', outFileName = '%s'",
1360
+ w->id, google_version, google_reqId, google_sig, google_out, google_responseHandler, google_outFileName
1361
+ );
1362
+
1363
+ if(datasource_type == DATASOURCE_DATATABLE_JSONP) {
1364
+ last_timestamp_in_data = strtoul(google_sig, NULL, 0);
1365
+
1366
+ // check the client wants json
1367
+ if(strcmp(google_out, "json") != 0) {
1368
+ buffer_sprintf(w->response.data,
1369
+ "%s({version:'%s',reqId:'%s',status:'error',errors:[{reason:'invalid_query',message:'output format is not supported',detailed_message:'the format %s requested is not supported by netdata.'}]});",
1370
+ google_responseHandler, google_version, google_reqId, google_out);
1371
+ return 200;
1372
+ }
1373
+ }
1374
+ }
1375
+
1376
+ if(datasource_type == DATASOURCE_DATATABLE_JSONP) {
1377
+ buffer_sprintf(w->response.data,
1378
+ "%s({version:'%s',reqId:'%s',status:'ok',sig:'%ld',table:",
1379
+ google_responseHandler, google_version, google_reqId, st->last_updated.tv_sec);
1380
+ }
1381
+
1382
+ debug(D_WEB_CLIENT_ACCESS, "%llu: Sending RRD data '%s' (id %s, %d lines, %d group, %d group_method, %ld after, %ld before).",
1383
+ w->id, st->name, st->id, lines, group_count, group_method, after, before);
1384
+
1385
+ time_t timestamp_in_data = rrd_stats_json(datasource_type, st, w->response.data, lines, group_count, group_method, (unsigned long)after, (unsigned long)before, nonzero);
1386
+
1387
+ if(datasource_type == DATASOURCE_DATATABLE_JSONP) {
1388
+ if(timestamp_in_data > last_timestamp_in_data)
1389
+ buffer_strcat(w->response.data, "});");
1390
+
1391
+ else {
1392
+ // the client already has the latest data
1393
+ buffer_flush(w->response.data);
1394
+ buffer_sprintf(w->response.data,
1395
+ "%s({version:'%s',reqId:'%s',status:'error',errors:[{reason:'not_modified',message:'Data not modified'}]});",
1396
+ google_responseHandler, google_version, google_reqId);
1397
+ }
1398
+ }
1399
+
1400
+ return 200;
1401
}
1402
1403
const char *web_content_type_to_string(uint8_t contenttype) {
1404
- switch(contenttype) {
1405
- case CT_TEXT_HTML:
1406
- return "text/html; charset=utf-8";
1404
+ switch(contenttype) {
1405
+ case CT_TEXT_HTML:
1406
+ return "text/html; charset=utf-8";
1407
1408
- case CT_APPLICATION_XML:
1409
- return "application/xml; charset=utf-8";
1408
+ case CT_APPLICATION_XML:
1409
+ return "application/xml; charset=utf-8";
1410
1411
- case CT_APPLICATION_JSON:
1412
- return "application/json; charset=utf-8";
1411
+ case CT_APPLICATION_JSON:
1412
+ return "application/json; charset=utf-8";
1413
1414
- case CT_APPLICATION_X_JAVASCRIPT:
1415
- return "application/x-javascript; charset=utf-8";
1414
+ case CT_APPLICATION_X_JAVASCRIPT:
1415
+ return "application/x-javascript; charset=utf-8";
1416
1417
- case CT_TEXT_CSS:
1418
- return "text/css; charset=utf-8";
1417
+ case CT_TEXT_CSS:
1418
+ return "text/css; charset=utf-8";
1419
1420
- case CT_TEXT_XML:
1421
- return "text/xml; charset=utf-8";
1420
+ case CT_TEXT_XML:
1421
+ return "text/xml; charset=utf-8";
1422
1423
- case CT_TEXT_XSL:
1424
- return "text/xsl; charset=utf-8";
1423
+ case CT_TEXT_XSL:
1424
+ return "text/xsl; charset=utf-8";
1425
1426
- case CT_APPLICATION_OCTET_STREAM:
1427
- return "application/octet-stream";
1426
+ case CT_APPLICATION_OCTET_STREAM:
1427
+ return "application/octet-stream";
1428
1429
- case CT_IMAGE_SVG_XML:
1430
- return "image/svg+xml";
1429
+ case CT_IMAGE_SVG_XML:
1430
+ return "image/svg+xml";
1431
1432
- case CT_APPLICATION_X_FONT_TRUETYPE:
1433
- return "application/x-font-truetype";
1432
+ case CT_APPLICATION_X_FONT_TRUETYPE:
1433
+ return "application/x-font-truetype";
1434
1435
- case CT_APPLICATION_X_FONT_OPENTYPE:
1436
- return "application/x-font-opentype";
1435
+ case CT_APPLICATION_X_FONT_OPENTYPE:
1436
+ return "application/x-font-opentype";
1437
1438
- case CT_APPLICATION_FONT_WOFF:
1439
- return "application/font-woff";
1438
+ case CT_APPLICATION_FONT_WOFF:
1439
+ return "application/font-woff";
1440
1441
- case CT_APPLICATION_FONT_WOFF2:
1442
- return "application/font-woff2";
1441
+ case CT_APPLICATION_FONT_WOFF2:
1442
+ return "application/font-woff2";
1443
1444
- case CT_APPLICATION_VND_MS_FONTOBJ:
1445
- return "application/vnd.ms-fontobject";
1444
+ case CT_APPLICATION_VND_MS_FONTOBJ:
1445
+ return "application/vnd.ms-fontobject";
1446
1447
- case CT_IMAGE_PNG:
1448
- return "image/png";
1447
+ case CT_IMAGE_PNG:
1448
+ return "image/png";
1449
1450
- case CT_IMAGE_JPG:
1451
- return "image/jpeg";
1450
+ case CT_IMAGE_JPG:
1451
+ return "image/jpeg";
1452
1453
- case CT_IMAGE_GIF:
1454
- return "image/gif";
1453
+ case CT_IMAGE_GIF:
1454
+ return "image/gif";
1455
1456
- case CT_IMAGE_XICON:
1457
- return "image/x-icon";
1456
+ case CT_IMAGE_XICON:
1457
+ return "image/x-icon";
1458
1459
- case CT_IMAGE_BMP:
1460
- return "image/bmp";
1459
+ case CT_IMAGE_BMP:
1460
+ return "image/bmp";
1461
1462
- case CT_IMAGE_ICNS:
1463
- return "image/icns";
1462
+ case CT_IMAGE_ICNS:
1463
+ return "image/icns";
1464
1465
- default:
1466
- case CT_TEXT_PLAIN:
1467
- return "text/plain; charset=utf-8";
1468
- }
1465
+ default:
1466
+ case CT_TEXT_PLAIN:
1467
+ return "text/plain; charset=utf-8";
1468
+ }
1469
}
1470
1471
1472
const char *web_response_code_to_string(int code) {
1473
- switch(code) {
1474
- case 200:
1475
- return "OK";
1473
+ switch(code) {
1474
+ case 200:
1475
+ return "OK";
1476
1477
- case 307:
1478
- return "Temporary Redirect";
1477
+ case 307:
1478
+ return "Temporary Redirect";
1479
1480
- case 400:
1481
- return "Bad Request";
1480
+ case 400:
1481
+ return "Bad Request";
1482
1483
- case 403:
1484
- return "Forbidden";
1483
+ case 403:
1484
+ return "Forbidden";
1485
1486
- case 404:
1487
- return "Not Found";
1486
+ case 404:
1487
+ return "Not Found";
1488
1489
- case 412:
1490
- return "Preconditions Failed";
1489
+ case 412:
1490
+ return "Preconditions Failed";
1491
1492
- default:
1493
- if(code >= 100 && code < 200)
1494
- return "Informational";
1492
+ default:
1493
+ if(code >= 100 && code < 200)
1494
+ return "Informational";
1495
1496
- if(code >= 200 && code < 300)
1497
- return "Successful";
1496
+ if(code >= 200 && code < 300)
1497
+ return "Successful";
1498
1499
- if(code >= 300 && code < 400)
1500
- return "Redirection";
1499
+ if(code >= 300 && code < 400)
1500
+ return "Redirection";
1501
1502
- if(code >= 400 && code < 500)
1503
- return "Bad Request";
1502
+ if(code >= 400 && code < 500)
1503
+ return "Bad Request";
1504
1505
- if(code >= 500 && code < 600)
1506
- return "Server Error";
1505
+ if(code >= 500 && code < 600)
1506
+ return "Server Error";
1507
1508
- return "Undefined Error";
1509
- }
1508
+ return "Undefined Error";
1509
+ }
1510
}
1511
1512
static inline char *http_header_parse(struct web_client *w, char *s) {
1513
- static uint32_t hash_origin = 0, hash_connection = 0, hash_accept_encoding = 0, hash_donottrack = 0;
1514
-
1515
- if(unlikely(!hash_origin)) {
1516
- hash_origin = simple_uhash("Origin");
1517
- hash_connection = simple_uhash("Connection");
1518
- hash_accept_encoding = simple_uhash("Accept-Encoding");
1519
- hash_donottrack = simple_uhash("DNT");
1520
- }
1521
-
1522
- char *e = s;
1523
-
1524
- // find the :
1525
- while(*e && *e != ':') e++;
1526
- if(!*e) return e;
1527
-
1528
- // get the name
1529
- *e = '\0';
1530
-
1531
- // find the value
1532
- char *v = e + 1, *ve;
1533
-
1534
- // skip leading spaces from value
1535
- while(*v == ' ') v++;
1536
- ve = v;
1537
-
1538
- // find the \r
1539
- while(*ve && *ve != '\r') ve++;
1540
- if(!*ve || ve[1] != '\n') {
1541
- *e = ':';
1542
- return ve;
1543
- }
1544
-
1545
- // terminate the value
1546
- *ve = '\0';
1547
-
1548
- // fprintf(stderr, "HEADER: '%s' = '%s'\n", s, v);
1549
- uint32_t hash = simple_uhash(s);
1550
-
1551
- if(hash == hash_origin && !strcasecmp(s, "Origin"))
1552
- strncpyz(w->origin, v, ORIGIN_MAX);
1553
-
1554
- else if(hash == hash_connection && !strcasecmp(s, "Connection")) {
1555
- if(strcasestr(v, "keep-alive"))
1556
- w->keepalive = 1;
1557
- }
1558
- else if(web_donotrack_comply && hash == hash_donottrack && !strcasecmp(s, "DNT")) {
1559
- if(*v == '0') w->donottrack = 0;
1560
- else if(*v == '1') w->donottrack = 1;
1561
- }
1513
+ static uint32_t hash_origin = 0, hash_connection = 0, hash_accept_encoding = 0, hash_donottrack = 0;
1514
+
1515
+ if(unlikely(!hash_origin)) {
1516
+ hash_origin = simple_uhash("Origin");
1517
+ hash_connection = simple_uhash("Connection");
1518
+ hash_accept_encoding = simple_uhash("Accept-Encoding");
1519
+ hash_donottrack = simple_uhash("DNT");
1520
+ }
1521
+
1522
+ char *e = s;
1523
+
1524
+ // find the :
1525
+ while(*e && *e != ':') e++;
1526
+ if(!*e) return e;
1527
+
1528
+ // get the name
1529
+ *e = '\0';
1530
+
1531
+ // find the value
1532
+ char *v = e + 1, *ve;
1533
+
1534
+ // skip leading spaces from value
1535
+ while(*v == ' ') v++;
1536
+ ve = v;
1537
+
1538
+ // find the \r
1539
+ while(*ve && *ve != '\r') ve++;
1540
+ if(!*ve || ve[1] != '\n') {
1541
+ *e = ':';
1542
+ return ve;
1543
+ }
1544
+
1545
+ // terminate the value
1546
+ *ve = '\0';
1547
+
1548
+ // fprintf(stderr, "HEADER: '%s' = '%s'\n", s, v);
1549
+ uint32_t hash = simple_uhash(s);
1550
+
1551
+ if(hash == hash_origin && !strcasecmp(s, "Origin"))
1552
+ strncpyz(w->origin, v, ORIGIN_MAX);
1553
+
1554
+ else if(hash == hash_connection && !strcasecmp(s, "Connection")) {
1555
+ if(strcasestr(v, "keep-alive"))
1556
+ w->keepalive = 1;
1557
+ }
1558
+ else if(web_donotrack_comply && hash == hash_donottrack && !strcasecmp(s, "DNT")) {
1559
+ if(*v == '0') w->donottrack = 0;
1560
+ else if(*v == '1') w->donottrack = 1;
1561
+ }
1562
#ifdef NETDATA_WITH_ZLIB
1563
- else if(hash == hash_accept_encoding && !strcasecmp(s, "Accept-Encoding")) {
1564
- if(web_enable_gzip) {
1565
- if(strcasestr(v, "gzip"))
1566
- web_client_enable_deflate(w, 1);
1567
- //
1568
- // does not seem to work
1569
- // else if(strcasestr(v, "deflate"))
1570
- // web_client_enable_deflate(w, 0);
1571
- }
1572
- }
1563
+ else if(hash == hash_accept_encoding && !strcasecmp(s, "Accept-Encoding")) {
1564
+ if(web_enable_gzip) {
1565
+ if(strcasestr(v, "gzip"))
1566
+ web_client_enable_deflate(w, 1);
1567
+ //
1568
+ // does not seem to work
1569
+ // else if(strcasestr(v, "deflate"))
1570
+ // web_client_enable_deflate(w, 0);
1571
+ }
1572
+ }
1573
#endif /* NETDATA_WITH_ZLIB */
1574
1575
- *e = ':';
1576
- *ve = '\r';
1577
- return ve;
1575
+ *e = ':';
1576
+ *ve = '\r';
1577
+ return ve;
1578
}
1579
1580
// http_request_validate()
@@ -1584,760 +1584,760 @@ static inline char *http_header_parse(struct web_client *w, char *s) {
1584
// < 0 : request is incomplete - wait for more data
1585
1586
static inline int http_request_validate(struct web_client *w) {
1587
- char *s = w->response.data->buffer, *encoded_url = NULL;
1588
-
1589
- // is is a valid request?
1590
- if(!strncmp(s, "GET ", 4)) {
1591
- encoded_url = s = &s[4];
1592
- w->mode = WEB_CLIENT_MODE_NORMAL;
1593
- }
1594
- else if(!strncmp(s, "OPTIONS ", 8)) {
1595
- encoded_url = s = &s[8];
1596
- w->mode = WEB_CLIENT_MODE_OPTIONS;
1597
- }
1598
- else {
1599
- w->wait_receive = 0;
1600
- return 1;
1601
- }
1602
-
1603
- // find the SPACE + "HTTP/"
1604
- while(*s) {
1605
- // find the next space
1606
- while (*s && *s != ' ') s++;
1607
-
1608
- // is it SPACE + "HTTP/" ?
1609
- if(*s && !strncmp(s, " HTTP/", 6)) break;
1610
- else s++;
1611
- }
1612
-
1613
- // incomplete requests
1614
- if(unlikely(!*s)) {
1615
- w->wait_receive = 1;
1616
- return -2;
1617
- }
1618
-
1619
- // we have the end of encoded_url - remember it
1620
- char *ue = s;
1621
-
1622
- // make sure we have complete request
1623
- // complete requests contain: \r\n\r\n
1624
- while(*s) {
1625
- // find a line feed
1626
- while(*s && *s++ != '\r');
1627
-
1628
- // did we reach the end?
1629
- if(unlikely(!*s)) break;
1630
-
1631
- // is it \r\n ?
1632
- if(likely(*s++ == '\n')) {
1633
-
1634
- // is it again \r\n ? (header end)
1635
- if(unlikely(*s == '\r' && s[1] == '\n')) {
1636
- // a valid complete HTTP request found
1637
-
1638
- *ue = '\0';
1639
- url_decode_r(w->decoded_url, encoded_url, URL_MAX + 1);
1640
- *ue = ' ';
1641
-
1642
- // copy the URL - we are going to overwrite parts of it
1643
- // FIXME -- we should avoid it
1644
- strncpyz(w->last_url, w->decoded_url, URL_MAX);
1645
-
1646
- w->wait_receive = 0;
1647
- return 0;
1648
- }
1649
-
1650
- // another header line
1651
- s = http_header_parse(w, s);
1652
- }
1653
- }
1654
-
1655
- // incomplete request
1656
- w->wait_receive = 1;
1657
- return -3;
1587
+ char *s = w->response.data->buffer, *encoded_url = NULL;
1588
+
1589
+ // is is a valid request?
1590
+ if(!strncmp(s, "GET ", 4)) {
1591
+ encoded_url = s = &s[4];
1592
+ w->mode = WEB_CLIENT_MODE_NORMAL;
1593
+ }
1594
+ else if(!strncmp(s, "OPTIONS ", 8)) {
1595
+ encoded_url = s = &s[8];
1596
+ w->mode = WEB_CLIENT_MODE_OPTIONS;
1597
+ }
1598
+ else {
1599
+ w->wait_receive = 0;
1600
+ return 1;
1601
+ }
1602
+
1603
+ // find the SPACE + "HTTP/"
1604
+ while(*s) {
1605
+ // find the next space
1606
+ while (*s && *s != ' ') s++;
1607
+
1608
+ // is it SPACE + "HTTP/" ?
1609
+ if(*s && !strncmp(s, " HTTP/", 6)) break;
1610
+ else s++;
1611
+ }
1612
+
1613
+ // incomplete requests
1614
+ if(unlikely(!*s)) {
1615
+ w->wait_receive = 1;
1616
+ return -2;
1617
+ }
1618
+
1619
+ // we have the end of encoded_url - remember it
1620
+ char *ue = s;
1621
+
1622
+ // make sure we have complete request
1623
+ // complete requests contain: \r\n\r\n
1624
+ while(*s) {
1625
+ // find a line feed
1626
+ while(*s && *s++ != '\r');
1627
+
1628
+ // did we reach the end?
1629
+ if(unlikely(!*s)) break;
1630
+
1631
+ // is it \r\n ?
1632
+ if(likely(*s++ == '\n')) {
1633
+
1634
+ // is it again \r\n ? (header end)
1635
+ if(unlikely(*s == '\r' && s[1] == '\n')) {
1636
+ // a valid complete HTTP request found
1637
+
1638
+ *ue = '\0';
1639
+ url_decode_r(w->decoded_url, encoded_url, URL_MAX + 1);
1640
+ *ue = ' ';
1641
+
1642
+ // copy the URL - we are going to overwrite parts of it
1643
+ // FIXME -- we should avoid it
1644
+ strncpyz(w->last_url, w->decoded_url, URL_MAX);
1645
+
1646
+ w->wait_receive = 0;
1647
+ return 0;
1648
+ }
1649
+
1650
+ // another header line
1651
+ s = http_header_parse(w, s);
1652
+ }
1653
+ }
1654
+
1655
+ // incomplete request
1656
+ w->wait_receive = 1;
1657
+ return -3;
1658
}
1659
1660
void web_client_process(struct web_client *w) {
1661
- static uint32_t hash_api = 0, hash_netdata_conf = 0, hash_data = 0, hash_datasource = 0, hash_graph = 0,
1662
- hash_list = 0, hash_all_json = 0, hash_exit = 0, hash_debug = 0, hash_mirror = 0;
1661
+ static uint32_t hash_api = 0, hash_netdata_conf = 0, hash_data = 0, hash_datasource = 0, hash_graph = 0,
1662
+ hash_list = 0, hash_all_json = 0, hash_exit = 0, hash_debug = 0, hash_mirror = 0;
1663
1664
// start timing us
1665
gettimeofday(&w->tv_in, NULL);
1666
1667
if(unlikely(!hash_api)) {
1668
- hash_api = simple_hash("api");
1669
- hash_netdata_conf = simple_hash("netdata.conf");
1670
- hash_data = simple_hash(WEB_PATH_DATA);
1671
- hash_datasource = simple_hash(WEB_PATH_DATASOURCE);
1672
- hash_graph = simple_hash(WEB_PATH_GRAPH);
1673
- hash_list = simple_hash("list");
1674
- hash_all_json = simple_hash("all.json");
1675
- hash_exit = simple_hash("exit");
1676
- hash_debug = simple_hash("debug");
1677
- hash_mirror = simple_hash("mirror");
1678
- }
1679
-
1680
- int code = 500;
1681
- ssize_t bytes;
1682
-
1683
- int what_to_do = http_request_validate(w);
1684
-
1685
- // wait for more data
1686
- if(what_to_do < 0) {
1687
- if(w->response.data->len > TOO_BIG_REQUEST) {
1688
- strcpy(w->last_url, "too big request");
1689
-
1690
- debug(D_WEB_CLIENT_ACCESS, "%llu: Received request is too big (%zu bytes).", w->id, w->response.data->len);
1691
-
1692
- code = 400;
1693
- buffer_flush(w->response.data);
1694
- buffer_sprintf(w->response.data, "Received request is too big (%zu bytes).\r\n", w->response.data->len);
1695
- }
1696
- else {
1697
- // wait for more data
1698
- return;
1699
- }
1700
- }
1701
- else if(what_to_do > 0) {
1702
- // strcpy(w->last_url, "not a valid request");
1703
-
1704
- debug(D_WEB_CLIENT_ACCESS, "%llu: Cannot understand '%s'.", w->id, w->response.data->buffer);
1705
-
1706
- code = 500;
1707
- buffer_flush(w->response.data);
1708
- buffer_strcat(w->response.data, "I don't understand you...\r\n");
1709
- }
1710
- else { // what_to_do == 0
1711
- if(w->mode == WEB_CLIENT_MODE_OPTIONS) {
1712
- code = 200;
1713
- w->response.data->contenttype = CT_TEXT_PLAIN;
1714
- buffer_flush(w->response.data);
1715
- buffer_strcat(w->response.data, "OK");
1716
- }
1717
- else {
1718
- char *url = w->decoded_url;
1719
- char *tok = mystrsep(&url, "/?");
1720
- if(tok && *tok) {
1721
- uint32_t hash = simple_hash(tok);
1722
- debug(D_WEB_CLIENT, "%llu: Processing command '%s'.", w->id, tok);
1723
-
1724
- if(hash == hash_api && strcmp(tok, "api") == 0) {
1725
- // the client is requesting api access
1726
- code = web_client_api_request(w, url);
1727
- }
1728
- else if(hash == hash_netdata_conf && strcmp(tok, "netdata.conf") == 0) {
1729
- code = 200;
1730
- debug(D_WEB_CLIENT_ACCESS, "%llu: Sending netdata.conf ...", w->id);
1731
-
1732
- w->response.data->contenttype = CT_TEXT_PLAIN;
1733
- buffer_flush(w->response.data);
1734
- generate_config(w->response.data, 0);
1735
- }
1736
- else if(hash == hash_data && strcmp(tok, WEB_PATH_DATA) == 0) { // "data"
1737
- // the client is requesting rrd data -- OLD API
1738
- code = web_client_api_old_data_request(w, url, DATASOURCE_JSON);
1739
- }
1740
- else if(hash == hash_datasource && strcmp(tok, WEB_PATH_DATASOURCE) == 0) { // "datasource"
1741
- // the client is requesting google datasource -- OLD API
1742
- code = web_client_api_old_data_request(w, url, DATASOURCE_DATATABLE_JSONP);
1743
- }
1744
- else if(hash == hash_graph && strcmp(tok, WEB_PATH_GRAPH) == 0) { // "graph"
1745
- // the client is requesting an rrd graph -- OLD API
1746
-
1747
- // get the name of the data to show
1748
- tok = mystrsep(&url, "/?&");
1749
- if(tok && *tok) {
1750
- debug(D_WEB_CLIENT, "%llu: Searching for RRD data with name '%s'.", w->id, tok);
1751
-
1752
- // do we have such a data set?
1753
- RRDSET *st = rrdset_find_byname(tok);
1754
- if(!st) st = rrdset_find(tok);
1755
- if(!st) {
1756
- // we don't have it
1757
- // try to send a file with that name
1758
- buffer_flush(w->response.data);
1759
- code = mysendfile(w, tok);
1760
- }
1761
- else {
1762
- code = 200;
1763
- debug(D_WEB_CLIENT_ACCESS, "%llu: Sending %s.json of RRD_STATS...", w->id, st->name);
1764
- w->response.data->contenttype = CT_APPLICATION_JSON;
1765
- buffer_flush(w->response.data);
1766
- rrd_stats_graph_json(st, url, w->response.data);
1767
- }
1768
- }
1769
- else {
1770
- code = 400;
1771
- buffer_flush(w->response.data);
1772
- buffer_strcat(w->response.data, "Graph name?\r\n");
1773
- }
1774
- }
1775
- else if(hash == hash_list && strcmp(tok, "list") == 0) {
1776
- // OLD API
1777
- code = 200;
1778
-
1779
- debug(D_WEB_CLIENT_ACCESS, "%llu: Sending list of RRD_STATS...", w->id);
1780
-
1781
- buffer_flush(w->response.data);
1782
- RRDSET *st = localhost.rrdset_root;
1783
-
1784
- for ( ; st ; st = st->next )
1785
- buffer_sprintf(w->response.data, "%s\n", st->name);
1786
- }
1787
- else if(hash == hash_all_json && strcmp(tok, "all.json") == 0) {
1788
- // OLD API
1789
- code = 200;
1790
- debug(D_WEB_CLIENT_ACCESS, "%llu: Sending JSON list of all monitors of RRD_STATS...", w->id);
1791
-
1792
- w->response.data->contenttype = CT_APPLICATION_JSON;
1793
- buffer_flush(w->response.data);
1794
- rrd_stats_all_json(w->response.data);
1795
- }
1668
+ hash_api = simple_hash("api");
1669
+ hash_netdata_conf = simple_hash("netdata.conf");
1670
+ hash_data = simple_hash(WEB_PATH_DATA);
1671
+ hash_datasource = simple_hash(WEB_PATH_DATASOURCE);
1672
+ hash_graph = simple_hash(WEB_PATH_GRAPH);
1673
+ hash_list = simple_hash("list");
1674
+ hash_all_json = simple_hash("all.json");
1675
+ hash_exit = simple_hash("exit");
1676
+ hash_debug = simple_hash("debug");
1677
+ hash_mirror = simple_hash("mirror");
1678
+ }
1679
+
1680
+ int code = 500;
1681
+ ssize_t bytes;
1682
+
1683
+ int what_to_do = http_request_validate(w);
1684
+
1685
+ // wait for more data
1686
+ if(what_to_do < 0) {
1687
+ if(w->response.data->len > TOO_BIG_REQUEST) {
1688
+ strcpy(w->last_url, "too big request");
1689
+
1690
+ debug(D_WEB_CLIENT_ACCESS, "%llu: Received request is too big (%zu bytes).", w->id, w->response.data->len);
1691
+
1692
+ code = 400;
1693
+ buffer_flush(w->response.data);
1694
+ buffer_sprintf(w->response.data, "Received request is too big (%zu bytes).\r\n", w->response.data->len);
1695
+ }
1696
+ else {
1697
+ // wait for more data
1698
+ return;
1699
+ }
1700
+ }
1701
+ else if(what_to_do > 0) {
1702
+ // strcpy(w->last_url, "not a valid request");
1703
+
1704
+ debug(D_WEB_CLIENT_ACCESS, "%llu: Cannot understand '%s'.", w->id, w->response.data->buffer);
1705
+
1706
+ code = 500;
1707
+ buffer_flush(w->response.data);
1708
+ buffer_strcat(w->response.data, "I don't understand you...\r\n");
1709
+ }
1710
+ else { // what_to_do == 0
1711
+ if(w->mode == WEB_CLIENT_MODE_OPTIONS) {
1712
+ code = 200;
1713
+ w->response.data->contenttype = CT_TEXT_PLAIN;
1714
+ buffer_flush(w->response.data);
1715
+ buffer_strcat(w->response.data, "OK");
1716
+ }
1717
+ else {
1718
+ char *url = w->decoded_url;
1719
+ char *tok = mystrsep(&url, "/?");
1720
+ if(tok && *tok) {
1721
+ uint32_t hash = simple_hash(tok);
1722
+ debug(D_WEB_CLIENT, "%llu: Processing command '%s'.", w->id, tok);
1723
+
1724
+ if(hash == hash_api && strcmp(tok, "api") == 0) {
1725
+ // the client is requesting api access
1726
+ code = web_client_api_request(w, url);
1727
+ }
1728
+ else if(hash == hash_netdata_conf && strcmp(tok, "netdata.conf") == 0) {
1729
+ code = 200;
1730
+ debug(D_WEB_CLIENT_ACCESS, "%llu: Sending netdata.conf ...", w->id);
1731
+
1732
+ w->response.data->contenttype = CT_TEXT_PLAIN;
1733
+ buffer_flush(w->response.data);
1734
+ generate_config(w->response.data, 0);
1735
+ }
1736
+ else if(hash == hash_data && strcmp(tok, WEB_PATH_DATA) == 0) { // "data"
1737
+ // the client is requesting rrd data -- OLD API
1738
+ code = web_client_api_old_data_request(w, url, DATASOURCE_JSON);
1739
+ }
1740
+ else if(hash == hash_datasource && strcmp(tok, WEB_PATH_DATASOURCE) == 0) { // "datasource"
1741
+ // the client is requesting google datasource -- OLD API
1742
+ code = web_client_api_old_data_request(w, url, DATASOURCE_DATATABLE_JSONP);
1743
+ }
1744
+ else if(hash == hash_graph && strcmp(tok, WEB_PATH_GRAPH) == 0) { // "graph"
1745
+ // the client is requesting an rrd graph -- OLD API
1746
+
1747
+ // get the name of the data to show
1748
+ tok = mystrsep(&url, "/?&");
1749
+ if(tok && *tok) {
1750
+ debug(D_WEB_CLIENT, "%llu: Searching for RRD data with name '%s'.", w->id, tok);
1751
+
1752
+ // do we have such a data set?
1753
+ RRDSET *st = rrdset_find_byname(tok);
1754
+ if(!st) st = rrdset_find(tok);
1755
+ if(!st) {
1756
+ // we don't have it
1757
+ // try to send a file with that name
1758
+ buffer_flush(w->response.data);
1759
+ code = mysendfile(w, tok);
1760
+ }
1761
+ else {
1762
+ code = 200;
1763
+ debug(D_WEB_CLIENT_ACCESS, "%llu: Sending %s.json of RRD_STATS...", w->id, st->name);
1764
+ w->response.data->contenttype = CT_APPLICATION_JSON;
1765
+ buffer_flush(w->response.data);
1766
+ rrd_stats_graph_json(st, url, w->response.data);
1767
+ }
1768
+ }
1769
+ else {
1770
+ code = 400;
1771
+ buffer_flush(w->response.data);
1772
+ buffer_strcat(w->response.data, "Graph name?\r\n");
1773
+ }
1774
+ }
1775
+ else if(hash == hash_list && strcmp(tok, "list") == 0) {
1776
+ // OLD API
1777
+ code = 200;
1778
+
1779
+ debug(D_WEB_CLIENT_ACCESS, "%llu: Sending list of RRD_STATS...", w->id);
1780
+
1781
+ buffer_flush(w->response.data);
1782
+ RRDSET *st = localhost.rrdset_root;
1783
+
1784
+ for ( ; st ; st = st->next )
1785
+ buffer_sprintf(w->response.data, "%s\n", st->name);
1786
+ }
1787
+ else if(hash == hash_all_json && strcmp(tok, "all.json") == 0) {
1788
+ // OLD API
1789
+ code = 200;
1790
+ debug(D_WEB_CLIENT_ACCESS, "%llu: Sending JSON list of all monitors of RRD_STATS...", w->id);
1791
+
1792
+ w->response.data->contenttype = CT_APPLICATION_JSON;
1793
+ buffer_flush(w->response.data);
1794
+ rrd_stats_all_json(w->response.data);
1795
+ }
1796
#ifdef NETDATA_INTERNAL_CHECKS
1797
- else if(hash == hash_exit && strcmp(tok, "exit") == 0) {
1798
- code = 200;
1799
- w->response.data->contenttype = CT_TEXT_PLAIN;
1800
- buffer_flush(w->response.data);
1801
-
1802
- if(!netdata_exit)
1803
- buffer_strcat(w->response.data, "ok, will do...");
1804
- else
1805
- buffer_strcat(w->response.data, "I am doing it already");
1806
-
1807
- error("web request to exit received.");
1808
- netdata_cleanup_and_exit(0);
1809
- netdata_exit = 1;
1810
- }
1811
- else if(hash == hash_debug && strcmp(tok, "debug") == 0) {
1812
- buffer_flush(w->response.data);
1813
-
1814
- // get the name of the data to show
1815
- tok = mystrsep(&url, "/?&");
1816
- if(tok && *tok) {
1817
- debug(D_WEB_CLIENT, "%llu: Searching for RRD data with name '%s'.", w->id, tok);
1818
-
1819
- // do we have such a data set?
1820
- RRDSET *st = rrdset_find_byname(tok);
1821
- if(!st) st = rrdset_find(tok);
1822
- if(!st) {
1823
- code = 404;
1824
- buffer_sprintf(w->response.data, "Chart %s is not found.\r\n", tok);
1825
- debug(D_WEB_CLIENT_ACCESS, "%llu: %s is not found.", w->id, tok);
1826
- }
1827
- else {
1828
- code = 200;
1829
- debug_flags |= D_RRD_STATS;
1830
- st->debug = !st->debug;
1831
- buffer_sprintf(w->response.data, "Chart %s has now debug %s.\r\n", tok, st->debug?"enabled":"disabled");
1832
- debug(D_WEB_CLIENT_ACCESS, "%llu: debug for %s is %s.", w->id, tok, st->debug?"enabled":"disabled");
1833
- }
1834
- }
1835
- else {
1836
- code = 500;
1837
- buffer_flush(w->response.data);
1838
- buffer_strcat(w->response.data, "debug which chart?\r\n");
1839
- }
1840
- }
1841
- else if(hash == hash_mirror && strcmp(tok, "mirror") == 0) {
1842
- code = 200;
1843
-
1844
- debug(D_WEB_CLIENT_ACCESS, "%llu: Mirroring...", w->id);
1845
-
1846
- // replace the zero bytes with spaces
1847
- buffer_char_replace(w->response.data, '\0', ' ');
1848
-
1849
- // just leave the buffer as is
1850
- // it will be copied back to the client
1851
- }
1852
-#endif /* NETDATA_INTERNAL_CHECKS */
1853
- else {
1854
- char filename[FILENAME_MAX+1];
1855
- url = filename;
1856
- strncpyz(filename, w->last_url, FILENAME_MAX);
1857
- tok = mystrsep(&url, "?");
1858
- buffer_flush(w->response.data);
1859
- code = mysendfile(w, (tok && *tok)?tok:"/");
1860
- }
1861
- }
1862
- else {
1863
- char filename[FILENAME_MAX+1];
1864
- url = filename;
1865
- strncpyz(filename, w->last_url, FILENAME_MAX);
1866
- tok = mystrsep(&url, "?");
1867
- buffer_flush(w->response.data);
1868
- code = mysendfile(w, (tok && *tok)?tok:"/");
1869
- }
1870
- }
1871
- }
1872
-
1873
- gettimeofday(&w->tv_ready, NULL);
1874
- w->response.data->date = time(NULL);
1875
- w->response.sent = 0;
1876
- w->response.code = code;
1877
-
1878
- // prepare the HTTP response header
1879
- debug(D_WEB_CLIENT, "%llu: Generating HTTP header with response %d.", w->id, code);
1880
-
1881
- const char *content_type_string = web_content_type_to_string(w->response.data->contenttype);
1882
- const char *code_msg = web_response_code_to_string(code);
1883
-
1884
- char date[32];
1885
- struct tm tmbuf, *tm = gmtime_r(&w->response.data->date, &tmbuf);
1886
- strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %Z", tm);
1887
-
1888
- buffer_sprintf(w->response.header_output,
1889
- "HTTP/1.1 %d %s\r\n"
1890
- "Connection: %s\r\n"
1891
- "Server: NetData Embedded HTTP Server\r\n"
1892
- "Access-Control-Allow-Origin: %s\r\n"
1893
- "Access-Control-Allow-Credentials: true\r\n"
1894
- "Content-Type: %s\r\n"
1895
- "Date: %s\r\n"
1896
- , code, code_msg
1897
- , w->keepalive?"keep-alive":"close"
1898
- , w->origin
1899
- , content_type_string
1900
- , date
1901
- );
1902
-
1903
- if(w->cookie1[0] || w->cookie2[0]) {
1904
- if(w->cookie1[0]) {
1905
- buffer_sprintf(w->response.header_output,
1906
- "Set-Cookie: %s\r\n",
1907
- w->cookie1);
1908
- }
1909
-
1910
- if(w->cookie2[0]) {
1911
- buffer_sprintf(w->response.header_output,
1912
- "Set-Cookie: %s\r\n",
1913
- w->cookie2);
1914
- }
1915
-
1916
- if(web_donotrack_comply)
1917
- buffer_sprintf(w->response.header_output,
1918
- "Tk: T;cookies\r\n");
1919
- }
1920
- else {
1921
- if(web_donotrack_comply) {
1922
- if(w->tracking_required)
1923
- buffer_sprintf(w->response.header_output,
1924
- "Tk: T;cookies\r\n");
1925
- else
1926
- buffer_sprintf(w->response.header_output,
1927
- "Tk: N\r\n");
1928
- }
1929
- }
1930
-
1931
- if(w->mode == WEB_CLIENT_MODE_OPTIONS) {
1932
- buffer_strcat(w->response.header_output,
1933
- "Access-Control-Allow-Methods: GET, OPTIONS\r\n"
1934
- "Access-Control-Allow-Headers: accept, x-requested-with, origin, content-type, cookie\r\n"
1935
- "Access-Control-Max-Age: 1209600\r\n" // 86400 * 14
1936
- );
1937
- }
1938
-
1939
- if(buffer_strlen(w->response.header))
1940
- buffer_strcat(w->response.header_output, buffer_tostring(w->response.header));
1941
-
1942
- if(w->mode == WEB_CLIENT_MODE_NORMAL && (w->response.data->options & WB_CONTENT_NO_CACHEABLE)) {
1943
- buffer_sprintf(w->response.header_output,
1944
- "Expires: %s\r\n"
1945
- "Cache-Control: no-cache\r\n"
1946
- , date);
1947
- }
1948
- else if(w->mode != WEB_CLIENT_MODE_OPTIONS) {
1949
- char edate[32];
1950
- time_t et = w->response.data->date + (86400 * 14);
1951
- struct tm etmbuf, *etm = gmtime_r(&et, &etmbuf);
1952
- strftime(edate, sizeof(edate), "%a, %d %b %Y %H:%M:%S %Z", etm);
1953
-
1954
- buffer_sprintf(w->response.header_output,
1955
- "Expires: %s\r\n"
1956
- "Cache-Control: public\r\n"
1957
- , edate);
1958
- }
1959
-
1960
- // if we know the content length, put it
1961
- if(!w->response.zoutput && (w->response.data->len || w->response.rlen))
1962
- buffer_sprintf(w->response.header_output,
1963
- "Content-Length: %zu\r\n"
1964
- , w->response.data->len? w->response.data->len: w->response.rlen
1965
- );
1966
- else if(!w->response.zoutput)
1967
- w->keepalive = 0; // content-length is required for keep-alive
1968
-
1969
- if(w->response.zoutput) {
1970
- buffer_strcat(w->response.header_output,
1971
- "Content-Encoding: gzip\r\n"
1972
- "Transfer-Encoding: chunked\r\n"
1973
- );
1974
- }
1975
-
1976
- buffer_strcat(w->response.header_output, "\r\n");
1977
-
1978
- // sent the HTTP header
1979
- debug(D_WEB_DATA, "%llu: Sending response HTTP header of size %zu: '%s'"
1980
- , w->id
1981
- , buffer_strlen(w->response.header_output)
1982
- , buffer_tostring(w->response.header_output)
1983
- );
1984
-
1985
- web_client_crock_socket(w);
1986
-
1987
- bytes = send(w->ofd, buffer_tostring(w->response.header_output), buffer_strlen(w->response.header_output), 0);
1988
- if(bytes != (ssize_t) buffer_strlen(w->response.header_output)) {
1989
- if(bytes > 0)
1990
- w->stats_sent_bytes += bytes;
1991
-
1992
- debug(D_WEB_CLIENT, "%llu: HTTP Header failed to be sent (I sent %zu bytes but the system sent %zd bytes). Closing web client."
1993
- , w->id
1994
- , buffer_strlen(w->response.header_output)
1995
- , bytes);
1996
-
1997
- WEB_CLIENT_IS_DEAD(w);
1998
- return;
1999
- }
2000
- else
2001
- w->stats_sent_bytes += bytes;
2002
-
2003
- // enable sending immediately if we have data
2004
- if(w->response.data->len) w->wait_send = 1;
2005
- else w->wait_send = 0;
2006
-
2007
- // pretty logging
2008
- switch(w->mode) {
2009
- case WEB_CLIENT_MODE_OPTIONS:
2010
- debug(D_WEB_CLIENT, "%llu: Done preparing the OPTIONS response. Sending data (%zu bytes) to client.", w->id, w->response.data->len);
2011
- break;
2012
-
2013
- case WEB_CLIENT_MODE_NORMAL:
2014
- debug(D_WEB_CLIENT, "%llu: Done preparing the response. Sending data (%zu bytes) to client.", w->id, w->response.data->len);
2015
- break;
2016
-
2017
- case WEB_CLIENT_MODE_FILECOPY:
2018
- if(w->response.rlen) {
2019
- debug(D_WEB_CLIENT, "%llu: Done preparing the response. Will be sending data file of %zu bytes to client.", w->id, w->response.rlen);
2020
- w->wait_receive = 1;
2021
-
2022
- /*
2023
- // utilize the kernel sendfile() for copying the file to the socket.
2024
- // this block of code can be commented, without anything missing.
2025
- // when it is commented, the program will copy the data using async I/O.
2026
- {
2027
- long len = sendfile(w->ofd, w->ifd, NULL, w->response.data->rbytes);
2028
- if(len != w->response.data->rbytes)
2029
- error("%llu: sendfile() should copy %ld bytes, but copied %ld. Falling back to manual copy.", w->id, w->response.data->rbytes, len);
2030
- else
2031
- web_client_reset(w);
2032
- }
2033
- */
2034
- }
2035
- else
2036
- debug(D_WEB_CLIENT, "%llu: Done preparing the response. Will be sending an unknown amount of bytes to client.", w->id);
2037
- break;
2038
-
2039
- default:
2040
- fatal("%llu: Unknown client mode %d.", w->id, w->mode);
2041
- break;
2042
- }
1797
+ else if(hash == hash_exit && strcmp(tok, "exit") == 0) {
1798
+ code = 200;
1799
+ w->response.data->contenttype = CT_TEXT_PLAIN;
1800
+ buffer_flush(w->response.data);
1801
+
1802
+ if(!netdata_exit)
1803
+ buffer_strcat(w->response.data, "ok, will do...");
1804
+ else
1805
+ buffer_strcat(w->response.data, "I am doing it already");
1806
+
1807
+ error("web request to exit received.");
1808
+ netdata_cleanup_and_exit(0);
1809
+ netdata_exit = 1;
1810
+ }
1811
+ else if(hash == hash_debug && strcmp(tok, "debug") == 0) {
1812
+ buffer_flush(w->response.data);
1813
+
1814
+ // get the name of the data to show
1815
+ tok = mystrsep(&url, "/?&");
1816
+ if(tok && *tok) {
1817
+ debug(D_WEB_CLIENT, "%llu: Searching for RRD data with name '%s'.", w->id, tok);
1818
+
1819
+ // do we have such a data set?
1820
+ RRDSET *st = rrdset_find_byname(tok);
1821
+ if(!st) st = rrdset_find(tok);
1822
+ if(!st) {
1823
+ code = 404;
1824
+ buffer_sprintf(w->response.data, "Chart %s is not found.\r\n", tok);
1825
+ debug(D_WEB_CLIENT_ACCESS, "%llu: %s is not found.", w->id, tok);
1826
+ }
1827
+ else {
1828
+ code = 200;
1829
+ debug_flags |= D_RRD_STATS;
1830
+ st->debug = !st->debug;
1831
+ buffer_sprintf(w->response.data, "Chart %s has now debug %s.\r\n", tok, st->debug?"enabled":"disabled");
1832
+ debug(D_WEB_CLIENT_ACCESS, "%llu: debug for %s is %s.", w->id, tok, st->debug?"enabled":"disabled");
1833
+ }
1834
+ }
1835
+ else {
1836
+ code = 500;
1837
+ buffer_flush(w->response.data);
1838
+ buffer_strcat(w->response.data, "debug which chart?\r\n");
1839
+ }
1840
+ }
1841
+ else if(hash == hash_mirror && strcmp(tok, "mirror") == 0) {
1842
+ code = 200;
1843
+
1844
+ debug(D_WEB_CLIENT_ACCESS, "%llu: Mirroring...", w->id);
1845
+
1846
+ // replace the zero bytes with spaces
1847
+ buffer_char_replace(w->response.data, '\0', ' ');
1848
+
1849
+ // just leave the buffer as is
1850
+ // it will be copied back to the client
1851
+ }
1852
+#endif /* NETDATA_INTERNAL_CHECKS */
1853
+ else {
1854
+ char filename[FILENAME_MAX+1];
1855
+ url = filename;
1856
+ strncpyz(filename, w->last_url, FILENAME_MAX);
1857
+ tok = mystrsep(&url, "?");
1858
+ buffer_flush(w->response.data);
1859
+ code = mysendfile(w, (tok && *tok)?tok:"/");
1860
+ }
1861
+ }
1862
+ else {
1863
+ char filename[FILENAME_MAX+1];
1864
+ url = filename;
1865
+ strncpyz(filename, w->last_url, FILENAME_MAX);
1866
+ tok = mystrsep(&url, "?");
1867
+ buffer_flush(w->response.data);
1868
+ code = mysendfile(w, (tok && *tok)?tok:"/");
1869
+ }
1870
+ }
1871
+ }
1872
+
1873
+ gettimeofday(&w->tv_ready, NULL);
1874
+ w->response.data->date = time(NULL);
1875
+ w->response.sent = 0;
1876
+ w->response.code = code;
1877
+
1878
+ // prepare the HTTP response header
1879
+ debug(D_WEB_CLIENT, "%llu: Generating HTTP header with response %d.", w->id, code);
1880
+
1881
+ const char *content_type_string = web_content_type_to_string(w->response.data->contenttype);
1882
+ const char *code_msg = web_response_code_to_string(code);
1883
+
1884
+ char date[32];
1885
+ struct tm tmbuf, *tm = gmtime_r(&w->response.data->date, &tmbuf);
1886
+ strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %Z", tm);
1887
+
1888
+ buffer_sprintf(w->response.header_output,
1889
+ "HTTP/1.1 %d %s\r\n"
1890
+ "Connection: %s\r\n"
1891
+ "Server: NetData Embedded HTTP Server\r\n"
1892
+ "Access-Control-Allow-Origin: %s\r\n"
1893
+ "Access-Control-Allow-Credentials: true\r\n"
1894
+ "Content-Type: %s\r\n"
1895
+ "Date: %s\r\n"
1896
+ , code, code_msg
1897
+ , w->keepalive?"keep-alive":"close"
1898
+ , w->origin
1899
+ , content_type_string
1900
+ , date
1901
+ );
1902
+
1903
+ if(w->cookie1[0] || w->cookie2[0]) {
1904
+ if(w->cookie1[0]) {
1905
+ buffer_sprintf(w->response.header_output,
1906
+ "Set-Cookie: %s\r\n",
1907
+ w->cookie1);
1908
+ }
1909
+
1910
+ if(w->cookie2[0]) {
1911
+ buffer_sprintf(w->response.header_output,
1912
+ "Set-Cookie: %s\r\n",
1913
+ w->cookie2);
1914
+ }
1915
+
1916
+ if(web_donotrack_comply)
1917
+ buffer_sprintf(w->response.header_output,
1918
+ "Tk: T;cookies\r\n");
1919
+ }
1920
+ else {
1921
+ if(web_donotrack_comply) {
1922
+ if(w->tracking_required)
1923
+ buffer_sprintf(w->response.header_output,
1924
+ "Tk: T;cookies\r\n");
1925
+ else
1926
+ buffer_sprintf(w->response.header_output,
1927
+ "Tk: N\r\n");
1928
+ }
1929
+ }
1930
+
1931
+ if(w->mode == WEB_CLIENT_MODE_OPTIONS) {
1932
+ buffer_strcat(w->response.header_output,
1933
+ "Access-Control-Allow-Methods: GET, OPTIONS\r\n"
1934
+ "Access-Control-Allow-Headers: accept, x-requested-with, origin, content-type, cookie\r\n"
1935
+ "Access-Control-Max-Age: 1209600\r\n" // 86400 * 14
1936
+ );
1937
+ }
1938
+
1939
+ if(buffer_strlen(w->response.header))
1940
+ buffer_strcat(w->response.header_output, buffer_tostring(w->response.header));
1941
+
1942
+ if(w->mode == WEB_CLIENT_MODE_NORMAL && (w->response.data->options & WB_CONTENT_NO_CACHEABLE)) {
1943
+ buffer_sprintf(w->response.header_output,
1944
+ "Expires: %s\r\n"
1945
+ "Cache-Control: no-cache\r\n"
1946
+ , date);
1947
+ }
1948
+ else if(w->mode != WEB_CLIENT_MODE_OPTIONS) {
1949
+ char edate[32];
1950
+ time_t et = w->response.data->date + (86400 * 14);
1951
+ struct tm etmbuf, *etm = gmtime_r(&et, &etmbuf);
1952
+ strftime(edate, sizeof(edate), "%a, %d %b %Y %H:%M:%S %Z", etm);
1953
+
1954
+ buffer_sprintf(w->response.header_output,
1955
+ "Expires: %s\r\n"
1956
+ "Cache-Control: public\r\n"
1957
+ , edate);
1958
+ }
1959
+
1960
+ // if we know the content length, put it
1961
+ if(!w->response.zoutput && (w->response.data->len || w->response.rlen))
1962
+ buffer_sprintf(w->response.header_output,
1963
+ "Content-Length: %zu\r\n"
1964
+ , w->response.data->len? w->response.data->len: w->response.rlen
1965
+ );
1966
+ else if(!w->response.zoutput)
1967
+ w->keepalive = 0; // content-length is required for keep-alive
1968
+
1969
+ if(w->response.zoutput) {
1970
+ buffer_strcat(w->response.header_output,
1971
+ "Content-Encoding: gzip\r\n"
1972
+ "Transfer-Encoding: chunked\r\n"
1973
+ );
1974
+ }
1975
+
1976
+ buffer_strcat(w->response.header_output, "\r\n");
1977
+
1978
+ // sent the HTTP header
1979
+ debug(D_WEB_DATA, "%llu: Sending response HTTP header of size %zu: '%s'"
1980
+ , w->id
1981
+ , buffer_strlen(w->response.header_output)
1982
+ , buffer_tostring(w->response.header_output)
1983
+ );
1984
+
1985
+ web_client_crock_socket(w);
1986
+
1987
+ bytes = send(w->ofd, buffer_tostring(w->response.header_output), buffer_strlen(w->response.header_output), 0);
1988
+ if(bytes != (ssize_t) buffer_strlen(w->response.header_output)) {
1989
+ if(bytes > 0)
1990
+ w->stats_sent_bytes += bytes;
1991
+
1992
+ debug(D_WEB_CLIENT, "%llu: HTTP Header failed to be sent (I sent %zu bytes but the system sent %zd bytes). Closing web client."
1993
+ , w->id
1994
+ , buffer_strlen(w->response.header_output)
1995
+ , bytes);
1996
+
1997
+ WEB_CLIENT_IS_DEAD(w);
1998
+ return;
1999
+ }
2000
+ else
2001
+ w->stats_sent_bytes += bytes;
2002
+
2003
+ // enable sending immediately if we have data
2004
+ if(w->response.data->len) w->wait_send = 1;
2005
+ else w->wait_send = 0;
2006
+
2007
+ // pretty logging
2008
+ switch(w->mode) {
2009
+ case WEB_CLIENT_MODE_OPTIONS:
2010
+ debug(D_WEB_CLIENT, "%llu: Done preparing the OPTIONS response. Sending data (%zu bytes) to client.", w->id, w->response.data->len);
2011
+ break;
2012
+
2013
+ case WEB_CLIENT_MODE_NORMAL:
2014
+ debug(D_WEB_CLIENT, "%llu: Done preparing the response. Sending data (%zu bytes) to client.", w->id, w->response.data->len);
2015
+ break;
2016
+
2017
+ case WEB_CLIENT_MODE_FILECOPY:
2018
+ if(w->response.rlen) {
2019
+ debug(D_WEB_CLIENT, "%llu: Done preparing the response. Will be sending data file of %zu bytes to client.", w->id, w->response.rlen);
2020
+ w->wait_receive = 1;
2021
+
2022
+ /*
2023
+ // utilize the kernel sendfile() for copying the file to the socket.
2024
+ // this block of code can be commented, without anything missing.
2025
+ // when it is commented, the program will copy the data using async I/O.
2026
+ {
2027
+ long len = sendfile(w->ofd, w->ifd, NULL, w->response.data->rbytes);
2028
+ if(len != w->response.data->rbytes)
2029
+ error("%llu: sendfile() should copy %ld bytes, but copied %ld. Falling back to manual copy.", w->id, w->response.data->rbytes, len);
2030
+ else
2031
+ web_client_reset(w);
2032
+ }
2033
+ */
2034
+ }
2035
+ else
2036
+ debug(D_WEB_CLIENT, "%llu: Done preparing the response. Will be sending an unknown amount of bytes to client.", w->id);
2037
+ break;
2038
+
2039
+ default:
2040
+ fatal("%llu: Unknown client mode %d.", w->id, w->mode);
2041
+ break;
2042
+ }
2043
}
2044
2045
ssize_t web_client_send_chunk_header(struct web_client *w, size_t len)
2046
{
2047
- debug(D_DEFLATE, "%llu: OPEN CHUNK of %zu bytes (hex: %zx).", w->id, len, len);
2048
- char buf[24];
2049
- sprintf(buf, "%zX\r\n", len);
2050
-
2051
- ssize_t bytes = send(w->ofd, buf, strlen(buf), 0);
2052
- if(bytes > 0) {
2053
- debug(D_DEFLATE, "%llu: Sent chunk header %zd bytes.", w->id, bytes);
2054
- w->stats_sent_bytes += bytes;
2055
- }
2056
-
2057
- else if(bytes == 0) {
2058
- debug(D_WEB_CLIENT, "%llu: Did not send chunk header to the client.", w->id);
2059
- WEB_CLIENT_IS_DEAD(w);
2060
- }
2061
- else {
2062
- debug(D_WEB_CLIENT, "%llu: Failed to send chunk header to client.", w->id);
2063
- WEB_CLIENT_IS_DEAD(w);
2064
- }
2065
-
2066
- return bytes;
2047
+ debug(D_DEFLATE, "%llu: OPEN CHUNK of %zu bytes (hex: %zx).", w->id, len, len);
2048
+ char buf[24];
2049
+ sprintf(buf, "%zX\r\n", len);
2050
+
2051
+ ssize_t bytes = send(w->ofd, buf, strlen(buf), 0);
2052
+ if(bytes > 0) {
2053
+ debug(D_DEFLATE, "%llu: Sent chunk header %zd bytes.", w->id, bytes);
2054
+ w->stats_sent_bytes += bytes;
2055
+ }
2056
+
2057
+ else if(bytes == 0) {
2058
+ debug(D_WEB_CLIENT, "%llu: Did not send chunk header to the client.", w->id);
2059
+ WEB_CLIENT_IS_DEAD(w);
2060
+ }
2061
+ else {
2062
+ debug(D_WEB_CLIENT, "%llu: Failed to send chunk header to client.", w->id);
2063
+ WEB_CLIENT_IS_DEAD(w);
2064
+ }
2065
+
2066
+ return bytes;
2067
}
2068
2069
ssize_t web_client_send_chunk_close(struct web_client *w)
2070
{
2071
- //debug(D_DEFLATE, "%llu: CLOSE CHUNK.", w->id);
2072
-
2073
- ssize_t bytes = send(w->ofd, "\r\n", 2, 0);
2074
- if(bytes > 0) {
2075
- debug(D_DEFLATE, "%llu: Sent chunk suffix %zd bytes.", w->id, bytes);
2076
- w->stats_sent_bytes += bytes;
2077
- }
2078
-
2079
- else if(bytes == 0) {
2080
- debug(D_WEB_CLIENT, "%llu: Did not send chunk suffix to the client.", w->id);
2081
- WEB_CLIENT_IS_DEAD(w);
2082
- }
2083
- else {
2084
- debug(D_WEB_CLIENT, "%llu: Failed to send chunk suffix to client.", w->id);
2085
- WEB_CLIENT_IS_DEAD(w);
2086
- }
2087
-
2088
- return bytes;
2071
+ //debug(D_DEFLATE, "%llu: CLOSE CHUNK.", w->id);
2072
+
2073
+ ssize_t bytes = send(w->ofd, "\r\n", 2, 0);
2074
+ if(bytes > 0) {
2075
+ debug(D_DEFLATE, "%llu: Sent chunk suffix %zd bytes.", w->id, bytes);
2076
+ w->stats_sent_bytes += bytes;
2077
+ }
2078
+
2079
+ else if(bytes == 0) {
2080
+ debug(D_WEB_CLIENT, "%llu: Did not send chunk suffix to the client.", w->id);
2081
+ WEB_CLIENT_IS_DEAD(w);
2082
+ }
2083
+ else {
2084
+ debug(D_WEB_CLIENT, "%llu: Failed to send chunk suffix to client.", w->id);
2085
+ WEB_CLIENT_IS_DEAD(w);
2086
+ }
2087
+
2088
+ return bytes;
2089
}
2090
2091
ssize_t web_client_send_chunk_finalize(struct web_client *w)
2092
{
2093
- //debug(D_DEFLATE, "%llu: FINALIZE CHUNK.", w->id);
2094
-
2095
- ssize_t bytes = send(w->ofd, "\r\n0\r\n\r\n", 7, 0);
2096
- if(bytes > 0) {
2097
- debug(D_DEFLATE, "%llu: Sent chunk suffix %zd bytes.", w->id, bytes);
2098
- w->stats_sent_bytes += bytes;
2099
- }
2100
-
2101
- else if(bytes == 0) {
2102
- debug(D_WEB_CLIENT, "%llu: Did not send chunk finalize suffix to the client.", w->id);
2103
- WEB_CLIENT_IS_DEAD(w);
2104
- }
2105
- else {
2106
- debug(D_WEB_CLIENT, "%llu: Failed to send chunk finalize suffix to client.", w->id);
2107
- WEB_CLIENT_IS_DEAD(w);
2108
- }
2109
-
2110
- return bytes;
2093
+ //debug(D_DEFLATE, "%llu: FINALIZE CHUNK.", w->id);
2094
+
2095
+ ssize_t bytes = send(w->ofd, "\r\n0\r\n\r\n", 7, 0);
2096
+ if(bytes > 0) {
2097
+ debug(D_DEFLATE, "%llu: Sent chunk suffix %zd bytes.", w->id, bytes);
2098
+ w->stats_sent_bytes += bytes;
2099
+ }
2100
+
2101
+ else if(bytes == 0) {
2102
+ debug(D_WEB_CLIENT, "%llu: Did not send chunk finalize suffix to the client.", w->id);
2103
+ WEB_CLIENT_IS_DEAD(w);
2104
+ }
2105
+ else {
2106
+ debug(D_WEB_CLIENT, "%llu: Failed to send chunk finalize suffix to client.", w->id);
2107
+ WEB_CLIENT_IS_DEAD(w);
2108
+ }
2109
+
2110
+ return bytes;
2111
}
2112
2113
#ifdef NETDATA_WITH_ZLIB
2114
ssize_t web_client_send_deflate(struct web_client *w)
2115
{
2116
- ssize_t len = 0, t = 0;
2117
-
2118
- // when using compression,
2119
- // w->response.sent is the amount of bytes passed through compression
2120
-
2121
- debug(D_DEFLATE, "%llu: web_client_send_deflate(): w->response.data->len = %zu, w->response.sent = %zu, w->response.zhave = %zu, w->response.zsent = %zu, w->response.zstream.avail_in = %u, w->response.zstream.avail_out = %u, w->response.zstream.total_in = %lu, w->response.zstream.total_out = %lu.",
2122
- w->id, w->response.data->len, w->response.sent, w->response.zhave, w->response.zsent, w->response.zstream.avail_in, w->response.zstream.avail_out, w->response.zstream.total_in, w->response.zstream.total_out);
2123
-
2124
- if(w->response.data->len - w->response.sent == 0 && w->response.zstream.avail_in == 0 && w->response.zhave == w->response.zsent && w->response.zstream.avail_out != 0) {
2125
- // there is nothing to send
2126
-
2127
- debug(D_WEB_CLIENT, "%llu: Out of output data.", w->id);
2128
-
2129
- // finalize the chunk
2130
- if(w->response.sent != 0) {
2131
- t = web_client_send_chunk_finalize(w);
2132
- if(t < 0) return t;
2133
- }
2134
-
2135
- if(w->mode == WEB_CLIENT_MODE_FILECOPY && w->wait_receive && w->response.rlen && w->response.rlen > w->response.data->len) {
2136
- // we have to wait, more data will come
2137
- debug(D_WEB_CLIENT, "%llu: Waiting for more data to become available.", w->id);
2138
- w->wait_send = 0;
2139
- return t;
2140
- }
2141
-
2142
- if(unlikely(!w->keepalive)) {
2143
- debug(D_WEB_CLIENT, "%llu: Closing (keep-alive is not enabled). %zu bytes sent.", w->id, w->response.sent);
2144
- WEB_CLIENT_IS_DEAD(w);
2145
- return t;
2146
- }
2147
-
2148
- // reset the client
2149
- web_client_reset(w);
2150
- debug(D_WEB_CLIENT, "%llu: Done sending all data on socket.", w->id);
2151
- return t;
2152
- }
2153
-
2154
- if(w->response.zhave == w->response.zsent) {
2155
- // compress more input data
2156
-
2157
- // close the previous open chunk
2158
- if(w->response.sent != 0) {
2159
- t = web_client_send_chunk_close(w);
2160
- if(t < 0) return t;
2161
- }
2162
-
2163
- debug(D_DEFLATE, "%llu: Compressing %zu new bytes starting from %zu (and %u left behind).", w->id, (w->response.data->len - w->response.sent), w->response.sent, w->response.zstream.avail_in);
2164
-
2165
- // give the compressor all the data not passed through the compressor yet
2166
- if(w->response.data->len > w->response.sent) {
2167
- w->response.zstream.next_in = (Bytef *)&w->response.data->buffer[w->response.sent - w->response.zstream.avail_in];
2168
- w->response.zstream.avail_in += (uInt) (w->response.data->len - w->response.sent);
2169
- }
2170
-
2171
- // reset the compressor output buffer
2172
- w->response.zstream.next_out = w->response.zbuffer;
2173
- w->response.zstream.avail_out = ZLIB_CHUNK;
2174
-
2175
- // ask for FINISH if we have all the input
2176
- int flush = Z_SYNC_FLUSH;
2177
- if(w->mode == WEB_CLIENT_MODE_NORMAL
2178
- || (w->mode == WEB_CLIENT_MODE_FILECOPY && !w->wait_receive && w->response.data->len == w->response.rlen)) {
2179
- flush = Z_FINISH;
2180
- debug(D_DEFLATE, "%llu: Requesting Z_FINISH, if possible.", w->id);
2181
- }
2182
- else {
2183
- debug(D_DEFLATE, "%llu: Requesting Z_SYNC_FLUSH.", w->id);
2184
- }
2185
-
2186
- // compress
2187
- if(deflate(&w->response.zstream, flush) == Z_STREAM_ERROR) {
2188
- error("%llu: Compression failed. Closing down client.", w->id);
2189
- web_client_reset(w);
2190
- return(-1);
2191
- }
2192
-
2193
- w->response.zhave = ZLIB_CHUNK - w->response.zstream.avail_out;
2194
- w->response.zsent = 0;
2195
-
2196
- // keep track of the bytes passed through the compressor
2197
- w->response.sent = w->response.data->len;
2198
-
2199
- debug(D_DEFLATE, "%llu: Compression produced %zu bytes.", w->id, w->response.zhave);
2200
-
2201
- // open a new chunk
2202
- ssize_t t2 = web_client_send_chunk_header(w, w->response.zhave);
2203
- if(t2 < 0) return t2;
2204
- t += t2;
2205
- }
2206
-
2207
- debug(D_WEB_CLIENT, "%llu: Sending %zu bytes of data (+%zd of chunk header).", w->id, w->response.zhave - w->response.zsent, t);
2208
-
2209
- len = send(w->ofd, &w->response.zbuffer[w->response.zsent], (size_t) (w->response.zhave - w->response.zsent), MSG_DONTWAIT);
2210
- if(len > 0) {
2211
- w->stats_sent_bytes += len;
2212
- w->response.zsent += len;
2213
- len += t;
2214
- debug(D_WEB_CLIENT, "%llu: Sent %zd bytes.", w->id, len);
2215
- }
2216
- else if(len == 0) {
2217
- debug(D_WEB_CLIENT, "%llu: Did not send any bytes to the client (zhave = %zu, zsent = %zu, need to send = %zu).",
2218
- w->id, w->response.zhave, w->response.zsent, w->response.zhave - w->response.zsent);
2219
-
2220
- WEB_CLIENT_IS_DEAD(w);
2221
- }
2222
- else {
2223
- debug(D_WEB_CLIENT, "%llu: Failed to send data to client.", w->id);
2224
- WEB_CLIENT_IS_DEAD(w);
2225
- }
2226
-
2227
- return(len);
2116
+ ssize_t len = 0, t = 0;
2117
+
2118
+ // when using compression,
2119
+ // w->response.sent is the amount of bytes passed through compression
2120
+
2121
+ debug(D_DEFLATE, "%llu: web_client_send_deflate(): w->response.data->len = %zu, w->response.sent = %zu, w->response.zhave = %zu, w->response.zsent = %zu, w->response.zstream.avail_in = %u, w->response.zstream.avail_out = %u, w->response.zstream.total_in = %lu, w->response.zstream.total_out = %lu.",
2122
+ w->id, w->response.data->len, w->response.sent, w->response.zhave, w->response.zsent, w->response.zstream.avail_in, w->response.zstream.avail_out, w->response.zstream.total_in, w->response.zstream.total_out);
2123
+
2124
+ if(w->response.data->len - w->response.sent == 0 && w->response.zstream.avail_in == 0 && w->response.zhave == w->response.zsent && w->response.zstream.avail_out != 0) {
2125
+ // there is nothing to send
2126
+
2127
+ debug(D_WEB_CLIENT, "%llu: Out of output data.", w->id);
2128
+
2129
+ // finalize the chunk
2130
+ if(w->response.sent != 0) {
2131
+ t = web_client_send_chunk_finalize(w);
2132
+ if(t < 0) return t;
2133
+ }
2134
+
2135
+ if(w->mode == WEB_CLIENT_MODE_FILECOPY && w->wait_receive && w->response.rlen && w->response.rlen > w->response.data->len) {
2136
+ // we have to wait, more data will come
2137
+ debug(D_WEB_CLIENT, "%llu: Waiting for more data to become available.", w->id);
2138
+ w->wait_send = 0;
2139
+ return t;
2140
+ }
2141
+
2142
+ if(unlikely(!w->keepalive)) {
2143
+ debug(D_WEB_CLIENT, "%llu: Closing (keep-alive is not enabled). %zu bytes sent.", w->id, w->response.sent);
2144
+ WEB_CLIENT_IS_DEAD(w);
2145
+ return t;
2146
+ }
2147
+
2148
+ // reset the client
2149
+ web_client_reset(w);
2150
+ debug(D_WEB_CLIENT, "%llu: Done sending all data on socket.", w->id);
2151
+ return t;
2152
+ }
2153
+
2154
+ if(w->response.zhave == w->response.zsent) {
2155
+ // compress more input data
2156
+
2157
+ // close the previous open chunk
2158
+ if(w->response.sent != 0) {
2159
+ t = web_client_send_chunk_close(w);
2160
+ if(t < 0) return t;
2161
+ }
2162
+
2163
+ debug(D_DEFLATE, "%llu: Compressing %zu new bytes starting from %zu (and %u left behind).", w->id, (w->response.data->len - w->response.sent), w->response.sent, w->response.zstream.avail_in);
2164
+
2165
+ // give the compressor all the data not passed through the compressor yet
2166
+ if(w->response.data->len > w->response.sent) {
2167
+ w->response.zstream.next_in = (Bytef *)&w->response.data->buffer[w->response.sent - w->response.zstream.avail_in];
2168
+ w->response.zstream.avail_in += (uInt) (w->response.data->len - w->response.sent);
2169
+ }
2170
+
2171
+ // reset the compressor output buffer
2172
+ w->response.zstream.next_out = w->response.zbuffer;
2173
+ w->response.zstream.avail_out = ZLIB_CHUNK;
2174
+
2175
+ // ask for FINISH if we have all the input
2176
+ int flush = Z_SYNC_FLUSH;
2177
+ if(w->mode == WEB_CLIENT_MODE_NORMAL
2178
+ || (w->mode == WEB_CLIENT_MODE_FILECOPY && !w->wait_receive && w->response.data->len == w->response.rlen)) {
2179
+ flush = Z_FINISH;
2180
+ debug(D_DEFLATE, "%llu: Requesting Z_FINISH, if possible.", w->id);
2181
+ }
2182
+ else {
2183
+ debug(D_DEFLATE, "%llu: Requesting Z_SYNC_FLUSH.", w->id);
2184
+ }
2185
+
2186
+ // compress
2187
+ if(deflate(&w->response.zstream, flush) == Z_STREAM_ERROR) {
2188
+ error("%llu: Compression failed. Closing down client.", w->id);
2189
+ web_client_reset(w);
2190
+ return(-1);
2191
+ }
2192
+
2193
+ w->response.zhave = ZLIB_CHUNK - w->response.zstream.avail_out;
2194
+ w->response.zsent = 0;
2195
+
2196
+ // keep track of the bytes passed through the compressor
2197
+ w->response.sent = w->response.data->len;
2198
+
2199
+ debug(D_DEFLATE, "%llu: Compression produced %zu bytes.", w->id, w->response.zhave);
2200
+
2201
+ // open a new chunk
2202
+ ssize_t t2 = web_client_send_chunk_header(w, w->response.zhave);
2203
+ if(t2 < 0) return t2;
2204
+ t += t2;
2205
+ }
2206
+
2207
+ debug(D_WEB_CLIENT, "%llu: Sending %zu bytes of data (+%zd of chunk header).", w->id, w->response.zhave - w->response.zsent, t);
2208
+
2209
+ len = send(w->ofd, &w->response.zbuffer[w->response.zsent], (size_t) (w->response.zhave - w->response.zsent), MSG_DONTWAIT);
2210
+ if(len > 0) {
2211
+ w->stats_sent_bytes += len;
2212
+ w->response.zsent += len;
2213
+ len += t;
2214
+ debug(D_WEB_CLIENT, "%llu: Sent %zd bytes.", w->id, len);
2215
+ }
2216
+ else if(len == 0) {
2217
+ debug(D_WEB_CLIENT, "%llu: Did not send any bytes to the client (zhave = %zu, zsent = %zu, need to send = %zu).",
2218
+ w->id, w->response.zhave, w->response.zsent, w->response.zhave - w->response.zsent);
2219
+
2220
+ WEB_CLIENT_IS_DEAD(w);
2221
+ }
2222
+ else {
2223
+ debug(D_WEB_CLIENT, "%llu: Failed to send data to client.", w->id);
2224
+ WEB_CLIENT_IS_DEAD(w);
2225
+ }
2226
+
2227
+ return(len);
2228
}
2229
#endif // NETDATA_WITH_ZLIB
2230
2231
ssize_t web_client_send(struct web_client *w) {
2232
#ifdef NETDATA_WITH_ZLIB
2233
- if(likely(w->response.zoutput)) return web_client_send_deflate(w);
2233
+ if(likely(w->response.zoutput)) return web_client_send_deflate(w);
2234
#endif // NETDATA_WITH_ZLIB
2235
2236
- ssize_t bytes;
2237
-
2238
- if(unlikely(w->response.data->len - w->response.sent == 0)) {
2239
- // there is nothing to send
2240
-
2241
- debug(D_WEB_CLIENT, "%llu: Out of output data.", w->id);
2242
-
2243
- // there can be two cases for this
2244
- // A. we have done everything
2245
- // B. we temporarily have nothing to send, waiting for the buffer to be filled by ifd
2246
-
2247
- if(w->mode == WEB_CLIENT_MODE_FILECOPY && w->wait_receive && w->response.rlen && w->response.rlen > w->response.data->len) {
2248
- // we have to wait, more data will come
2249
- debug(D_WEB_CLIENT, "%llu: Waiting for more data to become available.", w->id);
2250
- w->wait_send = 0;
2251
- return 0;
2252
- }
2253
-
2254
- if(unlikely(!w->keepalive)) {
2255
- debug(D_WEB_CLIENT, "%llu: Closing (keep-alive is not enabled). %zu bytes sent.", w->id, w->response.sent);
2256
- WEB_CLIENT_IS_DEAD(w);
2257
- return 0;
2258
- }
2259
-
2260
- web_client_reset(w);
2261
- debug(D_WEB_CLIENT, "%llu: Done sending all data on socket. Waiting for next request on the same socket.", w->id);
2262
- return 0;
2263
- }
2264
-
2265
- bytes = send(w->ofd, &w->response.data->buffer[w->response.sent], w->response.data->len - w->response.sent, MSG_DONTWAIT);
2266
- if(likely(bytes > 0)) {
2267
- w->stats_sent_bytes += bytes;
2268
- w->response.sent += bytes;
2269
- debug(D_WEB_CLIENT, "%llu: Sent %zd bytes.", w->id, bytes);
2270
- }
2271
- else if(likely(bytes == 0)) {
2272
- debug(D_WEB_CLIENT, "%llu: Did not send any bytes to the client.", w->id);
2273
- WEB_CLIENT_IS_DEAD(w);
2274
- }
2275
- else {
2276
- debug(D_WEB_CLIENT, "%llu: Failed to send data to client.", w->id);
2277
- WEB_CLIENT_IS_DEAD(w);
2278
- }
2279
-
2280
- return(bytes);
2236
+ ssize_t bytes;
2237
+
2238
+ if(unlikely(w->response.data->len - w->response.sent == 0)) {
2239
+ // there is nothing to send
2240
+
2241
+ debug(D_WEB_CLIENT, "%llu: Out of output data.", w->id);
2242
+
2243
+ // there can be two cases for this
2244
+ // A. we have done everything
2245
+ // B. we temporarily have nothing to send, waiting for the buffer to be filled by ifd
2246
+
2247
+ if(w->mode == WEB_CLIENT_MODE_FILECOPY && w->wait_receive && w->response.rlen && w->response.rlen > w->response.data->len) {
2248
+ // we have to wait, more data will come
2249
+ debug(D_WEB_CLIENT, "%llu: Waiting for more data to become available.", w->id);
2250
+ w->wait_send = 0;
2251
+ return 0;
2252
+ }
2253
+
2254
+ if(unlikely(!w->keepalive)) {
2255
+ debug(D_WEB_CLIENT, "%llu: Closing (keep-alive is not enabled). %zu bytes sent.", w->id, w->response.sent);
2256
+ WEB_CLIENT_IS_DEAD(w);
2257
+ return 0;
2258
+ }
2259
+
2260
+ web_client_reset(w);
2261
+ debug(D_WEB_CLIENT, "%llu: Done sending all data on socket. Waiting for next request on the same socket.", w->id);
2262
+ return 0;
2263
+ }
2264
+
2265
+ bytes = send(w->ofd, &w->response.data->buffer[w->response.sent], w->response.data->len - w->response.sent, MSG_DONTWAIT);
2266
+ if(likely(bytes > 0)) {
2267
+ w->stats_sent_bytes += bytes;
2268
+ w->response.sent += bytes;
2269
+ debug(D_WEB_CLIENT, "%llu: Sent %zd bytes.", w->id, bytes);
2270
+ }
2271
+ else if(likely(bytes == 0)) {
2272
+ debug(D_WEB_CLIENT, "%llu: Did not send any bytes to the client.", w->id);
2273
+ WEB_CLIENT_IS_DEAD(w);
2274
+ }
2275
+ else {
2276
+ debug(D_WEB_CLIENT, "%llu: Failed to send data to client.", w->id);
2277
+ WEB_CLIENT_IS_DEAD(w);
2278
+ }
2279
+
2280
+ return(bytes);
2281
}
2282
2283
ssize_t web_client_receive(struct web_client *w)
2284
{
2285
- // do we have any space for more data?
2286
- buffer_need_bytes(w->response.data, WEB_REQUEST_LENGTH);
2287
-
2288
- ssize_t left = w->response.data->size - w->response.data->len;
2289
- ssize_t bytes;
2290
-
2291
- if(unlikely(w->mode == WEB_CLIENT_MODE_FILECOPY))
2292
- bytes = read(w->ifd, &w->response.data->buffer[w->response.data->len], (size_t) (left - 1));
2293
- else
2294
- bytes = recv(w->ifd, &w->response.data->buffer[w->response.data->len], (size_t) (left - 1), MSG_DONTWAIT);
2295
-
2296
- if(likely(bytes > 0)) {
2297
- if(w->mode != WEB_CLIENT_MODE_FILECOPY)
2298
- w->stats_received_bytes += bytes;
2299
-
2300
- size_t old = w->response.data->len;
2301
- w->response.data->len += bytes;
2302
- w->response.data->buffer[w->response.data->len] = '\0';
2303
-
2304
- debug(D_WEB_CLIENT, "%llu: Received %zd bytes.", w->id, bytes);
2305
- debug(D_WEB_DATA, "%llu: Received data: '%s'.", w->id, &w->response.data->buffer[old]);
2306
-
2307
- if(w->mode == WEB_CLIENT_MODE_FILECOPY) {
2308
- w->wait_send = 1;
2309
-
2310
- if(w->response.rlen && w->response.data->len >= w->response.rlen)
2311
- w->wait_receive = 0;
2312
- }
2313
- }
2314
- else if(likely(bytes == 0)) {
2315
- debug(D_WEB_CLIENT, "%llu: Out of input data.", w->id);
2316
-
2317
- // if we cannot read, it means we have an error on input.
2318
- // if however, we are copying a file from ifd to ofd, we should not return an error.
2319
- // in this case, the error should be generated when the file has been sent to the client.
2320
-
2321
- if(w->mode == WEB_CLIENT_MODE_FILECOPY) {
2322
- // we are copying data from ifd to ofd
2323
- // let it finish copying...
2324
- w->wait_receive = 0;
2325
-
2326
- debug(D_WEB_CLIENT, "%llu: Read the whole file.", w->id);
2327
- if(w->ifd != w->ofd) close(w->ifd);
2328
- w->ifd = w->ofd;
2329
- }
2330
- else {
2331
- debug(D_WEB_CLIENT, "%llu: failed to receive data.", w->id);
2332
- WEB_CLIENT_IS_DEAD(w);
2333
- }
2334
- }
2335
- else {
2336
- debug(D_WEB_CLIENT, "%llu: receive data failed.", w->id);
2337
- WEB_CLIENT_IS_DEAD(w);
2338
- }
2339
-
2340
- return(bytes);
2285
+ // do we have any space for more data?
2286
+ buffer_need_bytes(w->response.data, WEB_REQUEST_LENGTH);
2287
+
2288
+ ssize_t left = w->response.data->size - w->response.data->len;
2289
+ ssize_t bytes;
2290
+
2291
+ if(unlikely(w->mode == WEB_CLIENT_MODE_FILECOPY))
2292
+ bytes = read(w->ifd, &w->response.data->buffer[w->response.data->len], (size_t) (left - 1));
2293
+ else
2294
+ bytes = recv(w->ifd, &w->response.data->buffer[w->response.data->len], (size_t) (left - 1), MSG_DONTWAIT);
2295
+
2296
+ if(likely(bytes > 0)) {
2297
+ if(w->mode != WEB_CLIENT_MODE_FILECOPY)
2298
+ w->stats_received_bytes += bytes;
2299
+
2300
+ size_t old = w->response.data->len;
2301
+ w->response.data->len += bytes;
2302
+ w->response.data->buffer[w->response.data->len] = '\0';
2303
+
2304
+ debug(D_WEB_CLIENT, "%llu: Received %zd bytes.", w->id, bytes);
2305
+ debug(D_WEB_DATA, "%llu: Received data: '%s'.", w->id, &w->response.data->buffer[old]);
2306
+
2307
+ if(w->mode == WEB_CLIENT_MODE_FILECOPY) {
2308
+ w->wait_send = 1;
2309
+
2310
+ if(w->response.rlen && w->response.data->len >= w->response.rlen)
2311
+ w->wait_receive = 0;
2312
+ }
2313
+ }
2314
+ else if(likely(bytes == 0)) {
2315
+ debug(D_WEB_CLIENT, "%llu: Out of input data.", w->id);
2316
+
2317
+ // if we cannot read, it means we have an error on input.
2318
+ // if however, we are copying a file from ifd to ofd, we should not return an error.
2319
+ // in this case, the error should be generated when the file has been sent to the client.
2320
+
2321
+ if(w->mode == WEB_CLIENT_MODE_FILECOPY) {
2322
+ // we are copying data from ifd to ofd
2323
+ // let it finish copying...
2324
+ w->wait_receive = 0;
2325
+
2326
+ debug(D_WEB_CLIENT, "%llu: Read the whole file.", w->id);
2327
+ if(w->ifd != w->ofd) close(w->ifd);
2328
+ w->ifd = w->ofd;
2329
+ }
2330
+ else {
2331
+ debug(D_WEB_CLIENT, "%llu: failed to receive data.", w->id);
2332
+ WEB_CLIENT_IS_DEAD(w);
2333
+ }
2334
+ }
2335
+ else {
2336
+ debug(D_WEB_CLIENT, "%llu: receive data failed.", w->id);
2337
+ WEB_CLIENT_IS_DEAD(w);
2338
+ }
2339
+
2340
+ return(bytes);
2341
}
2342
2343
@@ -2351,131 +2351,131 @@ ssize_t web_client_receive(struct web_client *w)
2351
2352
void *web_client_main(void *ptr)
2353
{
2354
- if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
2355
- error("Cannot set pthread cancel type to DEFERRED.");
2356
-
2357
- if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
2358
- error("Cannot set pthread cancel state to ENABLE.");
2359
-
2360
- struct web_client *w = ptr;
2361
- struct pollfd fds[2], *ifd, *ofd;
2362
- int retval, fdmax = 0, timeout;
2363
-
2364
- log_access("%llu: %s port %s connected on thread task id %d", w->id, w->client_ip, w->client_port, gettid());
2365
-
2366
- for(;;) {
2367
- if(unlikely(w->dead)) {
2368
- debug(D_WEB_CLIENT, "%llu: client is dead.", w->id);
2369
- break;
2370
- }
2371
- else if(unlikely(!w->wait_receive && !w->wait_send)) {
2372
- debug(D_WEB_CLIENT, "%llu: client is not set for neither receiving nor sending data.", w->id);
2373
- break;
2374
- }
2375
-
2376
- if(unlikely(w->ifd < 0 || w->ofd < 0)) {
2377
- error("%llu: invalid file descriptor, ifd = %d, ofd = %d (required 0 <= fd", w->id, w->ifd, w->ofd);
2378
- break;
2379
- }
2380
-
2381
- if(w->ifd == w->ofd) {
2382
- fds[0].fd = w->ifd;
2383
- fds[0].events = 0;
2384
- fds[0].revents = 0;
2385
-
2386
- if(w->wait_receive) fds[0].events |= POLLIN;
2387
- if(w->wait_send) fds[0].events |= POLLOUT;
2388
-
2389
- fds[1].fd = -1;
2390
- fds[1].events = 0;
2391
- fds[1].revents = 0;
2392
-
2393
- ifd = ofd = &fds[0];
2394
-
2395
- fdmax = 1;
2396
- }
2397
- else {
2398
- fds[0].fd = w->ifd;
2399
- fds[0].events = 0;
2400
- fds[0].revents = 0;
2401
- if(w->wait_receive) fds[0].events |= POLLIN;
2402
- ifd = &fds[0];
2403
-
2404
- fds[1].fd = w->ofd;
2405
- fds[1].events = 0;
2406
- fds[1].revents = 0;
2407
- if(w->wait_send) fds[1].events |= POLLOUT;
2408
- ofd = &fds[1];
2409
-
2410
- fdmax = 2;
2411
- }
2412
-
2413
- debug(D_WEB_CLIENT, "%llu: Waiting socket async I/O for %s %s", w->id, w->wait_receive?"INPUT":"", w->wait_send?"OUTPUT":"");
2414
- errno = 0;
2415
- timeout = web_client_timeout * 1000;
2416
- retval = poll(fds, fdmax, timeout);
2417
-
2418
- if(unlikely(retval == -1)) {
2419
- if(errno == EAGAIN || errno == EINTR) {
2420
- debug(D_WEB_CLIENT, "%llu: EAGAIN received.", w->id);
2421
- continue;
2422
- }
2423
-
2424
- debug(D_WEB_CLIENT, "%llu: LISTENER: poll() failed (input fd = %d, output fd = %d). Closing client.", w->id, w->ifd, w->ofd);
2425
- break;
2426
- }
2427
- else if(unlikely(!retval)) {
2428
- debug(D_WEB_CLIENT, "%llu: Timeout while waiting socket async I/O for %s %s", w->id, w->wait_receive?"INPUT":"", w->wait_send?"OUTPUT":"");
2429
- break;
2430
- }
2431
-
2432
- int used = 0;
2433
- if(w->wait_send && ofd->revents & POLLOUT) {
2434
- used++;
2435
- if(web_client_send(w) < 0) {
2436
- debug(D_WEB_CLIENT, "%llu: Cannot send data to client. Closing client.", w->id);
2437
- break;
2438
- }
2439
- }
2440
-
2441
- if(w->wait_receive && (ifd->revents & POLLIN || ifd->revents & POLLPRI)) {
2442
- used++;
2443
- if(web_client_receive(w) < 0) {
2444
- debug(D_WEB_CLIENT, "%llu: Cannot receive data from client. Closing client.", w->id);
2445
- break;
2446
- }
2447
-
2448
- if(w->mode == WEB_CLIENT_MODE_NORMAL) {
2449
- debug(D_WEB_CLIENT, "%llu: Attempting to process received data.", w->id);
2450
- web_client_process(w);
2451
- }
2452
- }
2453
-
2454
- if(unlikely(!used)) {
2455
- debug(D_WEB_CLIENT_ACCESS, "%llu: Received error on socket.", w->id);
2456
- break;
2457
- }
2458
- }
2459
-
2460
- web_client_reset(w);
2461
-
2462
- log_access("%llu: %s port %s disconnected from thread task id %d", w->id, w->client_ip, w->client_port, gettid());
2463
- debug(D_WEB_CLIENT, "%llu: done...", w->id);
2464
-
2465
- // close the sockets/files now
2466
- // to free file descriptors
2467
- if(w->ifd == w->ofd) {
2468
- if(w->ifd != -1) close(w->ifd);
2469
- }
2470
- else {
2471
- if(w->ifd != -1) close(w->ifd);
2472
- if(w->ofd != -1) close(w->ofd);
2473
- }
2474
- w->ifd = -1;
2475
- w->ofd = -1;
2476
-
2477
- w->obsolete = 1;
2478
-
2479
- pthread_exit(NULL);
2480
- return NULL;
2354
+ if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
2355
+ error("Cannot set pthread cancel type to DEFERRED.");
2356
+
2357
+ if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
2358
+ error("Cannot set pthread cancel state to ENABLE.");
2359
+
2360
+ struct web_client *w = ptr;
2361
+ struct pollfd fds[2], *ifd, *ofd;
2362
+ int retval, fdmax = 0, timeout;
2363
+
2364
+ log_access("%llu: %s port %s connected on thread task id %d", w->id, w->client_ip, w->client_port, gettid());
2365
+
2366
+ for(;;) {
2367
+ if(unlikely(w->dead)) {
2368
+ debug(D_WEB_CLIENT, "%llu: client is dead.", w->id);
2369
+ break;
2370
+ }
2371
+ else if(unlikely(!w->wait_receive && !w->wait_send)) {
2372
+ debug(D_WEB_CLIENT, "%llu: client is not set for neither receiving nor sending data.", w->id);
2373
+ break;
2374
+ }
2375
+
2376
+ if(unlikely(w->ifd < 0 || w->ofd < 0)) {
2377
+ error("%llu: invalid file descriptor, ifd = %d, ofd = %d (required 0 <= fd", w->id, w->ifd, w->ofd);
2378
+ break;
2379
+ }
2380
+
2381
+ if(w->ifd == w->ofd) {
2382
+ fds[0].fd = w->ifd;
2383
+ fds[0].events = 0;
2384
+ fds[0].revents = 0;
2385
+
2386
+ if(w->wait_receive) fds[0].events |= POLLIN;
2387
+ if(w->wait_send) fds[0].events |= POLLOUT;
2388
+
2389
+ fds[1].fd = -1;
2390
+ fds[1].events = 0;
2391
+ fds[1].revents = 0;
2392
+
2393
+ ifd = ofd = &fds[0];
2394
+
2395
+ fdmax = 1;
2396
+ }
2397
+ else {
2398
+ fds[0].fd = w->ifd;
2399
+ fds[0].events = 0;
2400
+ fds[0].revents = 0;
2401
+ if(w->wait_receive) fds[0].events |= POLLIN;
2402
+ ifd = &fds[0];
2403
+
2404
+ fds[1].fd = w->ofd;
2405
+ fds[1].events = 0;
2406
+ fds[1].revents = 0;
2407
+ if(w->wait_send) fds[1].events |= POLLOUT;
2408
+ ofd = &fds[1];
2409
+
2410
+ fdmax = 2;
2411
+ }
2412
+
2413
+ debug(D_WEB_CLIENT, "%llu: Waiting socket async I/O for %s %s", w->id, w->wait_receive?"INPUT":"", w->wait_send?"OUTPUT":"");
2414
+ errno = 0;
2415
+ timeout = web_client_timeout * 1000;
2416
+ retval = poll(fds, fdmax, timeout);
2417
+
2418
+ if(unlikely(retval == -1)) {
2419
+ if(errno == EAGAIN || errno == EINTR) {
2420
+ debug(D_WEB_CLIENT, "%llu: EAGAIN received.", w->id);
2421
+ continue;
2422
+ }
2423
+
2424
+ debug(D_WEB_CLIENT, "%llu: LISTENER: poll() failed (input fd = %d, output fd = %d). Closing client.", w->id, w->ifd, w->ofd);
2425
+ break;
2426
+ }
2427
+ else if(unlikely(!retval)) {
2428
+ debug(D_WEB_CLIENT, "%llu: Timeout while waiting socket async I/O for %s %s", w->id, w->wait_receive?"INPUT":"", w->wait_send?"OUTPUT":"");
2429
+ break;
2430
+ }
2431
+
2432
+ int used = 0;
2433
+ if(w->wait_send && ofd->revents & POLLOUT) {
2434
+ used++;
2435
+ if(web_client_send(w) < 0) {
2436
+ debug(D_WEB_CLIENT, "%llu: Cannot send data to client. Closing client.", w->id);
2437
+ break;
2438
+ }
2439
+ }
2440
+
2441
+ if(w->wait_receive && (ifd->revents & POLLIN || ifd->revents & POLLPRI)) {
2442
+ used++;
2443
+ if(web_client_receive(w) < 0) {
2444
+ debug(D_WEB_CLIENT, "%llu: Cannot receive data from client. Closing client.", w->id);
2445
+ break;
2446
+ }
2447
+
2448
+ if(w->mode == WEB_CLIENT_MODE_NORMAL) {
2449
+ debug(D_WEB_CLIENT, "%llu: Attempting to process received data.", w->id);
2450
+ web_client_process(w);
2451
+ }
2452
+ }
2453
+
2454
+ if(unlikely(!used)) {
2455
+ debug(D_WEB_CLIENT_ACCESS, "%llu: Received error on socket.", w->id);
2456
+ break;
2457
+ }
2458
+ }
2459
+
2460
+ web_client_reset(w);
2461
+
2462
+ log_access("%llu: %s port %s disconnected from thread task id %d", w->id, w->client_ip, w->client_port, gettid());
2463
+ debug(D_WEB_CLIENT, "%llu: done...", w->id);
2464
+
2465
+ // close the sockets/files now
2466
+ // to free file descriptors
2467
+ if(w->ifd == w->ofd) {
2468
+ if(w->ifd != -1) close(w->ifd);
2469
+ }
2470
+ else {
2471
+ if(w->ifd != -1) close(w->ifd);
2472
+ if(w->ofd != -1) close(w->ofd);
2473
+ }
2474
+ w->ifd = -1;
2475
+ w->ofd = -1;
2476
+
2477
+ w->obsolete = 1;
2478
+
2479
+ pthread_exit(NULL);
2480
+ return NULL;
2481
}
src/web_client.h
+45
-45
@@ -8,83 +8,83 @@ extern int web_client_timeout;
8
extern int web_enable_gzip, web_gzip_level, web_gzip_strategy, web_donotrack_comply;
9
#endif /* NETDATA_WITH_ZLIB */
10
11
-#define WEB_CLIENT_MODE_NORMAL 0
12
-#define WEB_CLIENT_MODE_FILECOPY 1
13
-#define WEB_CLIENT_MODE_OPTIONS 2
11
+#define WEB_CLIENT_MODE_NORMAL 0
12
+#define WEB_CLIENT_MODE_FILECOPY 1
13
+#define WEB_CLIENT_MODE_OPTIONS 2
14
15
#define URL_MAX 8192
16
-#define ZLIB_CHUNK 16384
16
+#define ZLIB_CHUNK 16384
17
#define HTTP_RESPONSE_HEADER_SIZE 4096
18
#define COOKIE_MAX 1024
19
#define ORIGIN_MAX 1024
20
21
struct response {
22
- BUFFER *header; // our response header
23
- BUFFER *header_output; // internal use
24
- BUFFER *data; // our response data buffer
22
+ BUFFER *header; // our response header
23
+ BUFFER *header_output; // internal use
24
+ BUFFER *data; // our response data buffer
25
26
- int code; // the HTTP response code
26
+ int code; // the HTTP response code
27
28
- size_t rlen; // if non-zero, the excepted size of ifd (input of firecopy)
29
- size_t sent; // current data length sent to output
28
+ size_t rlen; // if non-zero, the excepted size of ifd (input of firecopy)
29
+ size_t sent; // current data length sent to output
30
31
- int zoutput; // if set to 1, web_client_send() will send compressed data
31
+ int zoutput; // if set to 1, web_client_send() will send compressed data
32
#ifdef NETDATA_WITH_ZLIB
33
- z_stream zstream; // zlib stream for sending compressed output to client
34
- Bytef zbuffer[ZLIB_CHUNK]; // temporary buffer for storing compressed output
35
- size_t zsent; // the compressed bytes we have sent to the client
36
- size_t zhave; // the compressed bytes that we have received from zlib
37
- int zinitialized:1;
33
+ z_stream zstream; // zlib stream for sending compressed output to client
34
+ Bytef zbuffer[ZLIB_CHUNK]; // temporary buffer for storing compressed output
35
+ size_t zsent; // the compressed bytes we have sent to the client
36
+ size_t zhave; // the compressed bytes that we have received from zlib
37
+ int zinitialized:1;
38
#endif /* NETDATA_WITH_ZLIB */
39
40
};
41
42
struct web_client {
43
- unsigned long long id;
43
+ unsigned long long id;
44
45
- uint8_t obsolete:1; // if set to 1, the listener will remove this client
46
- // after setting this to 1, you should not touch
47
- // this web_client
45
+ uint8_t obsolete:1; // if set to 1, the listener will remove this client
46
+ // after setting this to 1, you should not touch
47
+ // this web_client
48
49
- uint8_t dead:1; // if set to 1, this client is dead
49
+ uint8_t dead:1; // if set to 1, this client is dead
50
51
- uint8_t keepalive:1; // if set to 1, the web client will be re-used
51
+ uint8_t keepalive:1; // if set to 1, the web client will be re-used
52
53
- uint8_t mode:3; // the operational mode of the client
53
+ uint8_t mode:3; // the operational mode of the client
54
55
- uint8_t wait_receive:1; // 1 = we are waiting more input data
56
- uint8_t wait_send:1; // 1 = we have data to send to the client
55
+ uint8_t wait_receive:1; // 1 = we are waiting more input data
56
+ uint8_t wait_send:1; // 1 = we have data to send to the client
57
58
- uint8_t donottrack:1; // 1 = we should not set cookies on this client
59
- uint8_t tracking_required:1; // 1 = if the request requires cookies
58
+ uint8_t donottrack:1; // 1 = we should not set cookies on this client
59
+ uint8_t tracking_required:1; // 1 = if the request requires cookies
60
61
- int tcp_cork; // 1 = we have a cork on the socket
61
+ int tcp_cork; // 1 = we have a cork on the socket
62
63
- int ifd;
64
- int ofd;
63
+ int ifd;
64
+ int ofd;
65
66
- char client_ip[NI_MAXHOST+1];
67
- char client_port[NI_MAXSERV+1];
66
+ char client_ip[NI_MAXHOST+1];
67
+ char client_port[NI_MAXSERV+1];
68
69
- char decoded_url[URL_MAX + 1]; // we decode the URL in this buffer
70
- char last_url[URL_MAX+1]; // we keep a copy of the decoded URL here
69
+ char decoded_url[URL_MAX + 1]; // we decode the URL in this buffer
70
+ char last_url[URL_MAX+1]; // we keep a copy of the decoded URL here
71
72
- struct timeval tv_in, tv_ready;
72
+ struct timeval tv_in, tv_ready;
73
74
- char cookie1[COOKIE_MAX+1];
75
- char cookie2[COOKIE_MAX+1];
76
- char origin[ORIGIN_MAX+1];
74
+ char cookie1[COOKIE_MAX+1];
75
+ char cookie2[COOKIE_MAX+1];
76
+ char origin[ORIGIN_MAX+1];
77
78
- struct sockaddr_storage clientaddr;
79
- struct response response;
78
+ struct sockaddr_storage clientaddr;
79
+ struct response response;
80
81
- size_t stats_received_bytes;
82
- size_t stats_sent_bytes;
81
+ size_t stats_received_bytes;
82
+ size_t stats_sent_bytes;
83
84
- pthread_t thread; // the thread servicing this client
84
+ pthread_t thread; // the thread servicing this client
85
86
- struct web_client *prev;
87
- struct web_client *next;
86
+ struct web_client *prev;
87
+ struct web_client *next;
88
};
89
90
#define WEB_CLIENT_IS_DEAD(w) (w)->dead=1
src/web_server.c
+303
-303
@@ -10,75 +10,75 @@ int web_server_mode = WEB_SERVER_MODE_MULTI_THREADED;
10
#ifdef NETDATA_INTERNAL_CHECKS
11
static void log_allocations(void)
12
{
13
- static int mem = 0;
13
+ static int mem = 0;
14
15
- struct mallinfo mi;
15
+ struct mallinfo mi;
16
17
- mi = mallinfo();
18
- if(mi.uordblks > mem) {
19
- int clients = 0;
20
- struct web_client *w;
21
- for(w = web_clients; w ; w = w->next) clients++;
17
+ mi = mallinfo();
18
+ if(mi.uordblks > mem) {
19
+ int clients = 0;
20
+ struct web_client *w;
21
+ for(w = web_clients; w ; w = w->next) clients++;
22
23
- info("Allocated memory increased from %d to %d (increased by %d bytes). There are %d web clients connected.", mem, mi.uordblks, mi.uordblks - mem, clients);
24
- mem = mi.uordblks;
25
- }
23
+ info("Allocated memory increased from %d to %d (increased by %d bytes). There are %d web clients connected.", mem, mi.uordblks, mi.uordblks - mem, clients);
24
+ mem = mi.uordblks;
25
+ }
26
}
27
#endif
28
29
#ifndef HAVE_ACCEPT4
30
int accept4(int sock, struct sockaddr *addr, socklen_t *addrlen, int flags) {
31
- int fd = accept(sock, addr, addrlen);
32
- int newflags = 0;
33
-
34
- if (fd < 0) return fd;
35
-
36
- if (flags & SOCK_NONBLOCK) {
37
- newflags |= O_NONBLOCK;
38
- flags &= ~SOCK_NONBLOCK;
39
- }
40
-
41
- if (flags & SOCK_CLOEXEC) {
42
- newflags |= O_CLOEXEC;
43
- flags &= ~SOCK_CLOEXEC;
44
- }
45
-
46
- if (flags) {
47
- errno = -EINVAL;
48
- return -1;
49
- }
50
-
51
- if (fcntl(fd, F_SETFL, newflags) < 0) {
52
- int saved_errno = errno;
53
- close(fd);
54
- errno = saved_errno;
55
- return -1;
56
- }
57
-
58
- return fd;
31
+ int fd = accept(sock, addr, addrlen);
32
+ int newflags = 0;
33
+
34
+ if (fd < 0) return fd;
35
+
36
+ if (flags & SOCK_NONBLOCK) {
37
+ newflags |= O_NONBLOCK;
38
+ flags &= ~SOCK_NONBLOCK;
39
+ }
40
+
41
+ if (flags & SOCK_CLOEXEC) {
42
+ newflags |= O_CLOEXEC;
43
+ flags &= ~SOCK_CLOEXEC;
44
+ }
45
+
46
+ if (flags) {
47
+ errno = -EINVAL;
48
+ return -1;
49
+ }
50
+
51
+ if (fcntl(fd, F_SETFL, newflags) < 0) {
52
+ int saved_errno = errno;
53
+ close(fd);
54
+ errno = saved_errno;
55
+ return -1;
56
+ }
57
+
58
+ return fd;
59
}
60
#endif
61
62
int create_listen_socket4(const char *ip, int port, int listen_backlog) {
63
- int sock;
64
- int sockopt = 1;
63
+ int sock;
64
+ int sockopt = 1;
65
66
- debug(D_LISTENER, "IPv4 creating new listening socket on ip '%s' port %d", ip, port);
66
+ debug(D_LISTENER, "IPv4 creating new listening socket on ip '%s' port %d", ip, port);
67
68
- sock = socket(AF_INET, SOCK_STREAM, 0);
69
- if(sock < 0) {
70
- error("IPv4 socket() on ip '%s' port %d failed.", ip, port);
71
- return -1;
72
- }
68
+ sock = socket(AF_INET, SOCK_STREAM, 0);
69
+ if(sock < 0) {
70
+ error("IPv4 socket() on ip '%s' port %d failed.", ip, port);
71
+ return -1;
72
+ }
73
74
- /* avoid "address already in use" */
75
- if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*)&sockopt, sizeof(sockopt)) != 0)
76
- error("Cannot set SO_REUSEADDR on ip '%s' port's %d.", ip, port);
74
+ /* avoid "address already in use" */
75
+ if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*)&sockopt, sizeof(sockopt)) != 0)
76
+ error("Cannot set SO_REUSEADDR on ip '%s' port's %d.", ip, port);
77
78
- struct sockaddr_in name;
79
- memset(&name, 0, sizeof(struct sockaddr_in));
80
- name.sin_family = AF_INET;
81
- name.sin_port = htons (port);
78
+ struct sockaddr_in name;
79
+ memset(&name, 0, sizeof(struct sockaddr_in));
80
+ name.sin_family = AF_INET;
81
+ name.sin_port = htons (port);
82
83
int ret = inet_pton(AF_INET, ip, (void *)&name.sin_addr.s_addr);
84
if(ret != 1) {
@@ -87,34 +87,34 @@ int create_listen_socket4(const char *ip, int port, int listen_backlog) {
87
return -1;
88
}
89
90
- if(bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0) {
91
- close(sock);
92
- error("IPv4 bind() on ip '%s' port %d failed.", ip, port);
93
- return -1;
94
- }
90
+ if(bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0) {
91
+ close(sock);
92
+ error("IPv4 bind() on ip '%s' port %d failed.", ip, port);
93
+ return -1;
94
+ }
95
96
- if(listen(sock, listen_backlog) < 0) {
97
- close(sock);
98
- fatal("IPv4 listen() on ip '%s' port %d failed.", ip, port);
99
- return -1;
100
- }
96
+ if(listen(sock, listen_backlog) < 0) {
97
+ close(sock);
98
+ fatal("IPv4 listen() on ip '%s' port %d failed.", ip, port);
99
+ return -1;
100
+ }
101
102
- debug(D_LISTENER, "Listening on IPv4 ip '%s' port %d", ip, port);
103
- return sock;
102
+ debug(D_LISTENER, "Listening on IPv4 ip '%s' port %d", ip, port);
103
+ return sock;
104
}
105
106
int create_listen_socket6(const char *ip, int port, int listen_backlog) {
107
- int sock = -1;
108
- int sockopt = 1;
107
+ int sock = -1;
108
+ int sockopt = 1;
109
int ipv6only = 1;
110
111
- debug(D_LISTENER, "IPv6 creating new listening socket on ip '%s' port %d", ip, port);
111
+ debug(D_LISTENER, "IPv6 creating new listening socket on ip '%s' port %d", ip, port);
112
113
- sock = socket(AF_INET6, SOCK_STREAM, 0);
114
- if (sock < 0) {
115
- error("IPv6 socket() on ip '%s' port %d failed.", ip, port);
116
- return -1;
117
- }
113
+ sock = socket(AF_INET6, SOCK_STREAM, 0);
114
+ if (sock < 0) {
115
+ error("IPv6 socket() on ip '%s' port %d failed.", ip, port);
116
+ return -1;
117
+ }
118
119
/* avoid "address already in use" */
120
if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*)&sockopt, sizeof(sockopt)) != 0)
@@ -125,9 +125,9 @@ int create_listen_socket6(const char *ip, int port, int listen_backlog) {
125
error("Cannot set IPV6_V6ONLY on ip '%s' port's %d.", ip, port);
126
127
struct sockaddr_in6 name;
128
- memset(&name, 0, sizeof(struct sockaddr_in6));
129
- name.sin6_family = AF_INET6;
130
- name.sin6_port = htons ((uint16_t) port);
128
+ memset(&name, 0, sizeof(struct sockaddr_in6));
129
+ name.sin6_family = AF_INET6;
130
+ name.sin6_port = htons ((uint16_t) port);
131
132
int ret = inet_pton(AF_INET6, ip, (void *)&name.sin6_addr.s6_addr);
133
if(ret != 1) {
@@ -136,22 +136,22 @@ int create_listen_socket6(const char *ip, int port, int listen_backlog) {
136
return -1;
137
}
138
139
- name.sin6_scope_id = 0;
139
+ name.sin6_scope_id = 0;
140
141
- if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0) {
142
- close(sock);
143
- error("IPv6 bind() on ip '%s' port %d failed.", ip, port);
144
- return -1;
145
- }
141
+ if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0) {
142
+ close(sock);
143
+ error("IPv6 bind() on ip '%s' port %d failed.", ip, port);
144
+ return -1;
145
+ }
146
147
- if (listen(sock, listen_backlog) < 0) {
148
- close(sock);
149
- error("IPv6 listen() on ip '%s' port %d failed.", ip, port);
150
- return -1;
151
- }
147
+ if (listen(sock, listen_backlog) < 0) {
148
+ close(sock);
149
+ error("IPv6 listen() on ip '%s' port %d failed.", ip, port);
150
+ return -1;
151
+ }
152
153
- debug(D_LISTENER, "Listening on IPv6 ip '%s' port %d", ip, port);
154
- return sock;
153
+ debug(D_LISTENER, "Listening on IPv6 ip '%s' port %d", ip, port);
154
+ return sock;
155
}
156
157
static inline int add_listen_socket(int fd, const char *ip, int port) {
@@ -275,13 +275,13 @@ static inline int bind_to_one(const char *definition, int default_port, int list
275
}
276
}
277
278
- freeaddrinfo(result);
278
+ freeaddrinfo(result);
279
280
return added;
281
}
282
283
int create_listen_sockets(void) {
284
- listen_backlog = (int) config_get_number("global", "http port listen backlog", LISTEN_BACKLOG);
284
+ listen_backlog = (int) config_get_number("global", "http port listen backlog", LISTEN_BACKLOG);
285
286
if(config_exists("global", "bind socket to IP") && !config_exists("global", "bind to"))
287
config_rename("global", "bind socket to IP", "bind to");
@@ -290,11 +290,11 @@ int create_listen_sockets(void) {
290
config_rename("global", "port", "default port");
291
292
listen_port = (int) config_get_number("global", "default port", LISTEN_PORT);
293
- if(listen_port < 1 || listen_port > 65535) {
294
- error("Invalid listen port %d given. Defaulting to %d.", listen_port, LISTEN_PORT);
293
+ if(listen_port < 1 || listen_port > 65535) {
294
+ error("Invalid listen port %d given. Defaulting to %d.", listen_port, LISTEN_PORT);
295
listen_port = (int) config_set_number("global", "default port", LISTEN_PORT);
296
- }
297
- debug(D_OPTIONS, "Default listen port set to %d.", listen_port);
296
+ }
297
+ debug(D_OPTIONS, "Default listen port set to %d.", listen_port);
298
299
char *s = config_get("global", "bind to", "*");
300
while(*s) {
@@ -319,27 +319,27 @@ int create_listen_sockets(void) {
319
if(!listen_fds_count)
320
fatal("Cannot listen on any socket. Exiting...");
321
322
- return (int)listen_fds_count;
322
+ return (int)listen_fds_count;
323
}
324
325
// --------------------------------------------------------------------------------------
326
// the main socket listener
327
328
static inline void cleanup_web_clients(void) {
329
- struct web_client *w;
330
-
331
- for (w = web_clients; w;) {
332
- if (w->obsolete) {
333
- debug(D_WEB_CLIENT, "%llu: Removing client.", w->id);
334
- // pthread_cancel(w->thread);
335
- // pthread_join(w->thread, NULL);
336
- w = web_client_free(w);
329
+ struct web_client *w;
330
+
331
+ for (w = web_clients; w;) {
332
+ if (w->obsolete) {
333
+ debug(D_WEB_CLIENT, "%llu: Removing client.", w->id);
334
+ // pthread_cancel(w->thread);
335
+ // pthread_join(w->thread, NULL);
336
+ w = web_client_free(w);
337
#ifdef NETDATA_INTERNAL_CHECKS
338
- log_allocations();
338
+ log_allocations();
339
#endif
340
- }
341
- else w = w->next;
342
- }
340
+ }
341
+ else w = w->next;
342
+ }
343
}
344
345
// 1. it accepts new incoming requests on our port
@@ -350,252 +350,252 @@ static inline void cleanup_web_clients(void) {
350
#define CLEANUP_EVERY_EVENTS 100
351
352
void *socket_listen_main_multi_threaded(void *ptr) {
353
- (void)ptr;
353
+ (void)ptr;
354
355
- web_server_mode = WEB_SERVER_MODE_MULTI_THREADED;
356
- info("Multi-threaded WEB SERVER thread created with task id %d", gettid());
355
+ web_server_mode = WEB_SERVER_MODE_MULTI_THREADED;
356
+ info("Multi-threaded WEB SERVER thread created with task id %d", gettid());
357
358
- struct web_client *w;
359
- int retval, counter = 0;
358
+ struct web_client *w;
359
+ int retval, counter = 0;
360
361
- if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
362
- error("Cannot set pthread cancel type to DEFERRED.");
361
+ if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
362
+ error("Cannot set pthread cancel type to DEFERRED.");
363
364
- if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
365
- error("Cannot set pthread cancel state to ENABLE.");
364
+ if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
365
+ error("Cannot set pthread cancel state to ENABLE.");
366
367
- if(!listen_fds_count)
368
- fatal("LISTENER: No sockets to listen to.");
367
+ if(!listen_fds_count)
368
+ fatal("LISTENER: No sockets to listen to.");
369
370
- struct pollfd *fds = callocz(sizeof(struct pollfd), listen_fds_count);
370
+ struct pollfd *fds = callocz(sizeof(struct pollfd), listen_fds_count);
371
372
- size_t i;
373
- for(i = 0; i < listen_fds_count ;i++) {
374
- fds[i].fd = listen_fds[i];
375
- fds[i].events = POLLIN;
376
- fds[i].revents = 0;
372
+ size_t i;
373
+ for(i = 0; i < listen_fds_count ;i++) {
374
+ fds[i].fd = listen_fds[i];
375
+ fds[i].events = POLLIN;
376
+ fds[i].revents = 0;
377
378
info("Listening on '%s'", (listen_fds_names[i])?listen_fds_names[i]:"UNKNOWN");
379
}
380
381
- int timeout = 10 * 1000;
382
-
383
- for(;;) {
384
- // debug(D_WEB_CLIENT, "LISTENER: Waiting...");
385
- retval = poll(fds, listen_fds_count, timeout);
386
-
387
- if(unlikely(retval == -1)) {
388
- error("LISTENER: poll() failed.");
389
- continue;
390
- }
391
- else if(unlikely(!retval)) {
392
- debug(D_WEB_CLIENT, "LISTENER: select() timeout.");
393
- counter = 0;
394
- cleanup_web_clients();
395
- continue;
396
- }
397
-
398
- for(i = 0 ; i < listen_fds_count ; i++) {
399
- short int revents = fds[i].revents;
400
-
401
- // check for new incoming connections
402
- if(revents & POLLIN || revents & POLLPRI) {
403
- fds[i].revents = 0;
404
-
405
- w = web_client_create(fds[i].fd);
406
- if(unlikely(!w)) {
407
- // no need for error log - web_client_create already logged the error
408
- continue;
409
- }
410
-
411
- if(pthread_create(&w->thread, NULL, web_client_main, w) != 0) {
412
- error("%llu: failed to create new thread for web client.", w->id);
413
- w->obsolete = 1;
414
- }
415
- else if(pthread_detach(w->thread) != 0) {
416
- error("%llu: Cannot request detach of newly created web client thread.", w->id);
417
- w->obsolete = 1;
418
- }
419
- }
420
- }
421
-
422
- // cleanup unused clients
423
- counter++;
424
- if(counter >= CLEANUP_EVERY_EVENTS) {
425
- counter = 0;
426
- cleanup_web_clients();
427
- }
428
- }
429
-
430
- debug(D_WEB_CLIENT, "LISTENER: exit!");
381
+ int timeout = 10 * 1000;
382
+
383
+ for(;;) {
384
+ // debug(D_WEB_CLIENT, "LISTENER: Waiting...");
385
+ retval = poll(fds, listen_fds_count, timeout);
386
+
387
+ if(unlikely(retval == -1)) {
388
+ error("LISTENER: poll() failed.");
389
+ continue;
390
+ }
391
+ else if(unlikely(!retval)) {
392
+ debug(D_WEB_CLIENT, "LISTENER: select() timeout.");
393
+ counter = 0;
394
+ cleanup_web_clients();
395
+ continue;
396
+ }
397
+
398
+ for(i = 0 ; i < listen_fds_count ; i++) {
399
+ short int revents = fds[i].revents;
400
+
401
+ // check for new incoming connections
402
+ if(revents & POLLIN || revents & POLLPRI) {
403
+ fds[i].revents = 0;
404
+
405
+ w = web_client_create(fds[i].fd);
406
+ if(unlikely(!w)) {
407
+ // no need for error log - web_client_create already logged the error
408
+ continue;
409
+ }
410
+
411
+ if(pthread_create(&w->thread, NULL, web_client_main, w) != 0) {
412
+ error("%llu: failed to create new thread for web client.", w->id);
413
+ w->obsolete = 1;
414
+ }
415
+ else if(pthread_detach(w->thread) != 0) {
416
+ error("%llu: Cannot request detach of newly created web client thread.", w->id);
417
+ w->obsolete = 1;
418
+ }
419
+ }
420
+ }
421
+
422
+ // cleanup unused clients
423
+ counter++;
424
+ if(counter >= CLEANUP_EVERY_EVENTS) {
425
+ counter = 0;
426
+ cleanup_web_clients();
427
+ }
428
+ }
429
+
430
+ debug(D_WEB_CLIENT, "LISTENER: exit!");
431
close_listen_sockets();
432
433
- return NULL;
433
+ return NULL;
434
}
435
436
struct web_client *single_threaded_clients[FD_SETSIZE];
437
438
static inline int single_threaded_link_client(struct web_client *w, fd_set *ifds, fd_set *ofds, fd_set *efds, int *max) {
439
- if(unlikely(w->obsolete || w->dead || (!w->wait_receive && !w->wait_send)))
440
- return 1;
439
+ if(unlikely(w->obsolete || w->dead || (!w->wait_receive && !w->wait_send)))
440
+ return 1;
441
442
- if(unlikely(w->ifd < 0 || w->ifd >= FD_SETSIZE || w->ofd < 0 || w->ofd >= FD_SETSIZE)) {
443
- error("%llu: invalid file descriptor, ifd = %d, ofd = %d (required 0 <= fd < FD_SETSIZE (%d)", w->id, w->ifd, w->ofd, FD_SETSIZE);
444
- return 1;
445
- }
442
+ if(unlikely(w->ifd < 0 || w->ifd >= FD_SETSIZE || w->ofd < 0 || w->ofd >= FD_SETSIZE)) {
443
+ error("%llu: invalid file descriptor, ifd = %d, ofd = %d (required 0 <= fd < FD_SETSIZE (%d)", w->id, w->ifd, w->ofd, FD_SETSIZE);
444
+ return 1;
445
+ }
446
447
- FD_SET(w->ifd, efds);
448
- if(unlikely(*max < w->ifd)) *max = w->ifd;
447
+ FD_SET(w->ifd, efds);
448
+ if(unlikely(*max < w->ifd)) *max = w->ifd;
449
450
- if(unlikely(w->ifd != w->ofd)) {
451
- if(*max < w->ofd) *max = w->ofd;
452
- FD_SET(w->ofd, efds);
453
- }
450
+ if(unlikely(w->ifd != w->ofd)) {
451
+ if(*max < w->ofd) *max = w->ofd;
452
+ FD_SET(w->ofd, efds);
453
+ }
454
455
- if(w->wait_receive) FD_SET(w->ifd, ifds);
456
- if(w->wait_send) FD_SET(w->ofd, ofds);
455
+ if(w->wait_receive) FD_SET(w->ifd, ifds);
456
+ if(w->wait_send) FD_SET(w->ofd, ofds);
457
458
- single_threaded_clients[w->ifd] = w;
459
- single_threaded_clients[w->ofd] = w;
458
+ single_threaded_clients[w->ifd] = w;
459
+ single_threaded_clients[w->ofd] = w;
460
461
- return 0;
461
+ return 0;
462
}
463
464
static inline int single_threaded_unlink_client(struct web_client *w, fd_set *ifds, fd_set *ofds, fd_set *efds) {
465
- FD_CLR(w->ifd, efds);
466
- if(unlikely(w->ifd != w->ofd)) FD_CLR(w->ofd, efds);
465
+ FD_CLR(w->ifd, efds);
466
+ if(unlikely(w->ifd != w->ofd)) FD_CLR(w->ofd, efds);
467
468
- if(w->wait_receive) FD_CLR(w->ifd, ifds);
469
- if(w->wait_send) FD_CLR(w->ofd, ofds);
468
+ if(w->wait_receive) FD_CLR(w->ifd, ifds);
469
+ if(w->wait_send) FD_CLR(w->ofd, ofds);
470
471
- single_threaded_clients[w->ifd] = NULL;
472
- single_threaded_clients[w->ofd] = NULL;
471
+ single_threaded_clients[w->ifd] = NULL;
472
+ single_threaded_clients[w->ofd] = NULL;
473
474
- if(unlikely(w->obsolete || w->dead || (!w->wait_receive && !w->wait_send)))
475
- return 1;
474
+ if(unlikely(w->obsolete || w->dead || (!w->wait_receive && !w->wait_send)))
475
+ return 1;
476
477
- return 0;
477
+ return 0;
478
}
479
480
void *socket_listen_main_single_threaded(void *ptr) {
481
- (void)ptr;
481
+ (void)ptr;
482
483
- web_server_mode = WEB_SERVER_MODE_SINGLE_THREADED;
483
+ web_server_mode = WEB_SERVER_MODE_SINGLE_THREADED;
484
485
- info("Single-threaded WEB SERVER thread created with task id %d", gettid());
485
+ info("Single-threaded WEB SERVER thread created with task id %d", gettid());
486
487
- struct web_client *w;
488
- int retval;
487
+ struct web_client *w;
488
+ int retval;
489
490
- if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
491
- error("Cannot set pthread cancel type to DEFERRED.");
490
+ if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
491
+ error("Cannot set pthread cancel type to DEFERRED.");
492
493
- if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
494
- error("Cannot set pthread cancel state to ENABLE.");
493
+ if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
494
+ error("Cannot set pthread cancel state to ENABLE.");
495
496
- if(!listen_fds_count)
497
- fatal("LISTENER: no listen sockets available.");
496
+ if(!listen_fds_count)
497
+ fatal("LISTENER: no listen sockets available.");
498
499
size_t i;
500
for(i = 0; i < FD_SETSIZE ; i++)
501
- single_threaded_clients[i] = NULL;
501
+ single_threaded_clients[i] = NULL;
502
503
- fd_set ifds, ofds, efds, rifds, rofds, refds;
504
- FD_ZERO (&ifds);
505
- FD_ZERO (&ofds);
506
- FD_ZERO (&efds);
507
- int fdmax = 0;
503
+ fd_set ifds, ofds, efds, rifds, rofds, refds;
504
+ FD_ZERO (&ifds);
505
+ FD_ZERO (&ofds);
506
+ FD_ZERO (&efds);
507
+ int fdmax = 0;
508
509
- for(i = 0; i < listen_fds_count ; i++) {
510
- if (listen_fds[i] < 0 || listen_fds[i] >= FD_SETSIZE)
511
- fatal("LISTENER: Listen socket %d is not ready, or invalid.", listen_fds[i]);
509
+ for(i = 0; i < listen_fds_count ; i++) {
510
+ if (listen_fds[i] < 0 || listen_fds[i] >= FD_SETSIZE)
511
+ fatal("LISTENER: Listen socket %d is not ready, or invalid.", listen_fds[i]);
512
513
info("Listening on '%s'", (listen_fds_names[i])?listen_fds_names[i]:"UNKNOWN");
514
515
- FD_SET(listen_fds[i], &ifds);
516
- FD_SET(listen_fds[i], &efds);
517
- if(fdmax < listen_fds[i])
515
+ FD_SET(listen_fds[i], &ifds);
516
+ FD_SET(listen_fds[i], &efds);
517
+ if(fdmax < listen_fds[i])
518
fdmax = listen_fds[i];
519
- }
520
-
521
- for(;;) {
522
- debug(D_WEB_CLIENT_ACCESS, "LISTENER: single threaded web server waiting (fdmax = %d)...", fdmax);
523
-
524
- struct timeval tv = { .tv_sec = 1, .tv_usec = 0 };
525
- rifds = ifds;
526
- rofds = ofds;
527
- refds = efds;
528
- retval = select(fdmax+1, &rifds, &rofds, &refds, &tv);
529
-
530
- if(unlikely(retval == -1)) {
531
- error("LISTENER: select() failed.");
532
- continue;
533
- }
534
- else if(likely(retval)) {
535
- debug(D_WEB_CLIENT_ACCESS, "LISTENER: got something.");
536
-
537
- for(i = 0; i < listen_fds_count ; i++) {
538
- if (FD_ISSET(listen_fds[i], &rifds)) {
539
- debug(D_WEB_CLIENT_ACCESS, "LISTENER: new connection.");
540
- w = web_client_create(listen_fds[i]);
541
- if (single_threaded_link_client(w, &ifds, &ofds, &ifds, &fdmax) != 0) {
542
- web_client_free(w);
543
- }
544
- }
545
- }
546
-
547
- for(i = 0 ; i <= (size_t)fdmax ; i++) {
548
- if(likely(!FD_ISSET(i, &rifds) && !FD_ISSET(i, &rofds) && !FD_ISSET(i, &refds)))
549
- continue;
550
-
551
- w = single_threaded_clients[i];
552
- if(unlikely(!w))
553
- continue;
554
-
555
- if(unlikely(single_threaded_unlink_client(w, &ifds, &ofds, &efds) != 0)) {
556
- web_client_free(w);
557
- continue;
558
- }
559
-
560
- if (unlikely(FD_ISSET(w->ifd, &refds) || FD_ISSET(w->ofd, &refds))) {
561
- web_client_free(w);
562
- continue;
563
- }
564
-
565
- if (unlikely(w->wait_receive && FD_ISSET(w->ifd, &rifds))) {
566
- if (unlikely(web_client_receive(w) < 0)) {
567
- web_client_free(w);
568
- continue;
569
- }
570
-
571
- if (w->mode != WEB_CLIENT_MODE_FILECOPY) {
572
- debug(D_WEB_CLIENT, "%llu: Processing received data.", w->id);
573
- web_client_process(w);
574
- }
575
- }
576
-
577
- if (unlikely(w->wait_send && FD_ISSET(w->ofd, &rofds))) {
578
- if (unlikely(web_client_send(w) < 0)) {
579
- debug(D_WEB_CLIENT, "%llu: Cannot send data to client. Closing client.", w->id);
580
- web_client_free(w);
581
- continue;
582
- }
583
- }
584
-
585
- if(unlikely(single_threaded_link_client(w, &ifds, &ofds, &efds, &fdmax) != 0)) {
586
- web_client_free(w);
587
- }
588
- }
589
- }
590
- else {
591
- debug(D_WEB_CLIENT_ACCESS, "LISTENER: single threaded web server timeout.");
519
+ }
520
+
521
+ for(;;) {
522
+ debug(D_WEB_CLIENT_ACCESS, "LISTENER: single threaded web server waiting (fdmax = %d)...", fdmax);
523
+
524
+ struct timeval tv = { .tv_sec = 1, .tv_usec = 0 };
525
+ rifds = ifds;
526
+ rofds = ofds;
527
+ refds = efds;
528
+ retval = select(fdmax+1, &rifds, &rofds, &refds, &tv);
529
+
530
+ if(unlikely(retval == -1)) {
531
+ error("LISTENER: select() failed.");
532
+ continue;
533
+ }
534
+ else if(likely(retval)) {
535
+ debug(D_WEB_CLIENT_ACCESS, "LISTENER: got something.");
536
+
537
+ for(i = 0; i < listen_fds_count ; i++) {
538
+ if (FD_ISSET(listen_fds[i], &rifds)) {
539
+ debug(D_WEB_CLIENT_ACCESS, "LISTENER: new connection.");
540
+ w = web_client_create(listen_fds[i]);
541
+ if (single_threaded_link_client(w, &ifds, &ofds, &ifds, &fdmax) != 0) {
542
+ web_client_free(w);
543
+ }
544
+ }
545
+ }
546
+
547
+ for(i = 0 ; i <= (size_t)fdmax ; i++) {
548
+ if(likely(!FD_ISSET(i, &rifds) && !FD_ISSET(i, &rofds) && !FD_ISSET(i, &refds)))
549
+ continue;
550
+
551
+ w = single_threaded_clients[i];
552
+ if(unlikely(!w))
553
+ continue;
554
+
555
+ if(unlikely(single_threaded_unlink_client(w, &ifds, &ofds, &efds) != 0)) {
556
+ web_client_free(w);
557
+ continue;
558
+ }
559
+
560
+ if (unlikely(FD_ISSET(w->ifd, &refds) || FD_ISSET(w->ofd, &refds))) {
561
+ web_client_free(w);
562
+ continue;
563
+ }
564
+
565
+ if (unlikely(w->wait_receive && FD_ISSET(w->ifd, &rifds))) {
566
+ if (unlikely(web_client_receive(w) < 0)) {
567
+ web_client_free(w);
568
+ continue;
569
+ }
570
+
571
+ if (w->mode != WEB_CLIENT_MODE_FILECOPY) {
572
+ debug(D_WEB_CLIENT, "%llu: Processing received data.", w->id);
573
+ web_client_process(w);
574
+ }
575
+ }
576
+
577
+ if (unlikely(w->wait_send && FD_ISSET(w->ofd, &rofds))) {
578
+ if (unlikely(web_client_send(w) < 0)) {
579
+ debug(D_WEB_CLIENT, "%llu: Cannot send data to client. Closing client.", w->id);
580
+ web_client_free(w);
581
+ continue;
582
+ }
583
+ }
584
+
585
+ if(unlikely(single_threaded_link_client(w, &ifds, &ofds, &efds, &fdmax) != 0)) {
586
+ web_client_free(w);
587
+ }
588
+ }
589
+ }
590
+ else {
591
+ debug(D_WEB_CLIENT_ACCESS, "LISTENER: single threaded web server timeout.");
592
#ifdef NETDATA_INTERNAL_CHECKS
593
- log_allocations();
593
+ log_allocations();
594
#endif
595
- }
596
- }
595
+ }
596
+ }
597
598
- debug(D_WEB_CLIENT, "LISTENER: exit!");
598
+ debug(D_WEB_CLIENT, "LISTENER: exit!");
599
close_listen_sockets();
600
- return NULL;
600
+ return NULL;
601
}
src/web_server.h
+4
-4
@@ -1,10 +1,10 @@
1
#ifndef NETDATA_WEB_SERVER_H
2
#define NETDATA_WEB_SERVER_H 1
3
4
-#define WEB_PATH_FILE "file"
5
-#define WEB_PATH_DATA "data"
6
-#define WEB_PATH_DATASOURCE "datasource"
7
-#define WEB_PATH_GRAPH "graph"
4
+#define WEB_PATH_FILE "file"
5
+#define WEB_PATH_DATA "data"
6
+#define WEB_PATH_DATASOURCE "datasource"
7
+#define WEB_PATH_GRAPH "graph"
8
9
#define LISTEN_PORT 19999
10
#define LISTEN_BACKLOG 100