diff options
author | Dmitrijs Goloscapovs <dmitrijs.goloscapovs@zabbix.com> | 2022-11-07 15:02:25 +0300 |
---|---|---|
committer | Dmitrijs Goloscapovs <dmitrijs.goloscapovs@zabbix.com> | 2022-11-07 15:02:25 +0300 |
commit | 0d725d08d1cd8287463c7a1ac9aae94dfd718b93 (patch) | |
tree | 0c497ca03967acb3223f573cec21241e12455dd5 /src | |
parent | 45aa479dacdba3c14093b05fcf97394f967ee118 (diff) | |
parent | a7403cf21480121349e1e56e4ce33e5fc52fe016 (diff) |
........S. [ZBX-21616] resolved conflict
Diffstat (limited to 'src')
233 files changed, 10517 insertions, 5513 deletions
diff --git a/src/go/go.mod b/src/go/go.mod index a49e83baa4d..e1592e57866 100644 --- a/src/go/go.mod +++ b/src/go/go.mod @@ -1,33 +1,60 @@ module zabbix.com -go 1.16 +go 1.18 require ( - git.zabbix.com/ap/plugin-support v0.0.0-20220608100211-35b8bffd7ad0 + git.zabbix.com/ap/plugin-support v1.1.0 github.com/BurntSushi/locker v0.0.0-20171006230638-a6e239ea1c69 github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5 - github.com/chromedp/cdproto v0.0.0-20210104223854-2cc87dae3ee3 - github.com/chromedp/chromedp v0.6.0 + github.com/chromedp/cdproto v0.0.0-20220827030233-358ed4af73cf + github.com/chromedp/chromedp v0.8.5 github.com/dustin/gomemcached v0.0.0-20160817010731-a2284a01c143 - github.com/eclipse/paho.mqtt.golang v1.2.0 - github.com/fsnotify/fsnotify v1.4.9 + github.com/eclipse/paho.mqtt.golang v1.4.1 + github.com/fsnotify/fsnotify v1.5.4 github.com/go-ldap/ldap v3.0.3+incompatible - github.com/go-ole/go-ole v1.2.4 - github.com/go-sql-driver/mysql v1.5.0 + github.com/go-ole/go-ole v1.2.6 + github.com/go-sql-driver/mysql v1.6.0 github.com/goburrow/modbus v0.1.0 - github.com/goburrow/serial v0.1.0 // indirect github.com/godbus/dbus v4.1.0+incompatible - github.com/godror/godror v0.20.1 - github.com/jackc/pgx/v4 v4.8.2-0.20200910143026-040df1ccef85 - github.com/mattn/go-sqlite3 v1.14.8 - github.com/mediocregopher/radix/v3 v3.5.0 - github.com/memcachier/mc/v3 v3.0.1 - github.com/miekg/dns v1.1.43 + github.com/godror/godror v0.34.0 + github.com/jackc/pgx/v4 v4.17.2 + github.com/mattn/go-sqlite3 v1.14.15 + github.com/mediocregopher/radix/v3 v3.8.1 + github.com/memcachier/mc/v3 v3.0.3 + github.com/miekg/dns v1.1.50 github.com/natefinch/npipe v0.0.0-20160621034901-c1b8fa8bdcce github.com/omeid/go-yarn v0.0.1 + golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64 +) + +require ( + github.com/chromedp/sysutil v1.0.0 // indirect + github.com/go-logfmt/logfmt v0.5.1 // indirect + github.com/go-logr/logr v1.2.3 // indirect + github.com/goburrow/serial v0.1.0 // indirect + github.com/gobwas/httphead v0.1.0 // indirect + github.com/gobwas/pool v0.2.1 // indirect + github.com/gobwas/ws v1.1.0 // indirect + github.com/godror/knownpb v0.1.0 // indirect + github.com/gorilla/websocket v1.4.2 // indirect + github.com/jackc/chunkreader/v2 v2.0.1 // indirect + github.com/jackc/pgconn v1.13.0 // indirect + github.com/jackc/pgio v1.0.0 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgproto3/v2 v2.3.1 // indirect + github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect + github.com/jackc/pgtype v1.12.0 // indirect + github.com/jackc/puddle v1.3.0 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/mailru/easyjson v0.7.7 // indirect github.com/pkg/errors v0.9.1 // indirect - golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 + golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect + golang.org/x/mod v0.4.2 // indirect + golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect + golang.org/x/sync v0.0.0-20220513210516-0976fa681c29 // indirect + golang.org/x/text v0.3.7 // indirect + golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + google.golang.org/protobuf v1.27.1 // indirect gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect - gopkg.in/yaml.v2 v2.2.8 // indirect ) diff --git a/src/go/go.sum b/src/go/go.sum index 52f19406c56..e204247a5fe 100644 --- a/src/go/go.sum +++ b/src/go/go.sum @@ -1,26 +1,16 @@ -git.zabbix.com/ap/plugin-support v0.0.0-20220524072909-7233a93fe116 h1:IGbQPDh/U7UHSM0M4h2k/wdRjyO3zG8uq4Dx+gej4y8= -git.zabbix.com/ap/plugin-support v0.0.0-20220524072909-7233a93fe116/go.mod h1:R3QzQWgpxlA+ddJNkOhsPTcGOVtrR69WS0hXIsnBurY= -git.zabbix.com/ap/plugin-support v0.0.0-20220524082638-7fd18350f78d h1:fv+sfiIPe6U8X0T+vrpI4bBpo5kzYnp9qxNwA30Ay/U= -git.zabbix.com/ap/plugin-support v0.0.0-20220524082638-7fd18350f78d/go.mod h1:R3QzQWgpxlA+ddJNkOhsPTcGOVtrR69WS0hXIsnBurY= -git.zabbix.com/ap/plugin-support v0.0.0-20220525103006-9363aae69d10 h1:zRmgkxzcYbFXMmHgLQ0i3FIOUhqLKK6uCTF/Fdlbl00= -git.zabbix.com/ap/plugin-support v0.0.0-20220525103006-9363aae69d10/go.mod h1:R3QzQWgpxlA+ddJNkOhsPTcGOVtrR69WS0hXIsnBurY= -git.zabbix.com/ap/plugin-support v0.0.0-20220530082632-bd6f3ae15c88 h1:a/w3gm8CKYRkw7gRu6+ufdCAadmWjnh4LNHqQRG3Nu4= -git.zabbix.com/ap/plugin-support v0.0.0-20220530082632-bd6f3ae15c88/go.mod h1:R3QzQWgpxlA+ddJNkOhsPTcGOVtrR69WS0hXIsnBurY= -git.zabbix.com/ap/plugin-support v0.0.0-20220601115430-7e21b812be52 h1:dgk5oJtySHzjkkzfELzM4tkAQbjJO9krfj0GJQMXdS4= -git.zabbix.com/ap/plugin-support v0.0.0-20220601115430-7e21b812be52/go.mod h1:R3QzQWgpxlA+ddJNkOhsPTcGOVtrR69WS0hXIsnBurY= -git.zabbix.com/ap/plugin-support v0.0.0-20220608100211-35b8bffd7ad0 h1:VZuQnO95vu+83jsQaY+HGDzx+SoTf8inEZFkZhPvZtM= -git.zabbix.com/ap/plugin-support v0.0.0-20220608100211-35b8bffd7ad0/go.mod h1:R3QzQWgpxlA+ddJNkOhsPTcGOVtrR69WS0hXIsnBurY= -git.zabbix.com/ap/plugin-support v0.0.2 h1:ce5LDuqEK4yYrD0g2BNWrSlnr33AVB3QT4G3wmjhDts= -git.zabbix.com/ap/plugin-support v0.0.2/go.mod h1:R3QzQWgpxlA+ddJNkOhsPTcGOVtrR69WS0hXIsnBurY= +git.zabbix.com/ap/plugin-support v1.1.0 h1:t2a2ijsup3KSm0fXkPr9mnQw9xPskZ0PzWnQwGVjxzw= +git.zabbix.com/ap/plugin-support v1.1.0/go.mod h1:R3QzQWgpxlA+ddJNkOhsPTcGOVtrR69WS0hXIsnBurY= github.com/BurntSushi/locker v0.0.0-20171006230638-a6e239ea1c69 h1:+tu3HOoMXB7RXEINRVIpxJCT+KdYiI7LAEAUrOw3dIU= github.com/BurntSushi/locker v0.0.0-20171006230638-a6e239ea1c69/go.mod h1:L1AbZdiDllfyYH5l5OkAaZtk7VkWe89bPJFmnDBNHxg= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= +github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5 h1:BjkPE3785EwPhhyuFkbINB+2a1xATwk8SNDWnJiD41g= github.com/cakturk/go-netstat v0.0.0-20200220111822-e5b49efee7a5/go.mod h1:jtAfVaU/2cu1+wdSRPWE2c1N2qeAA3K4RH9pYgqwets= -github.com/chromedp/cdproto v0.0.0-20210104223854-2cc87dae3ee3 h1:XeGYLuu3Yu3/2/FLDXyObe6lBYtUFDTJgjjNPcfcU40= -github.com/chromedp/cdproto v0.0.0-20210104223854-2cc87dae3ee3/go.mod h1:55pim6Ht4LJKdVLlyFJV/g++HsEA1hQxPbB5JyNdZC0= -github.com/chromedp/chromedp v0.6.0 h1:jjzHzXW5pNdKt1D9cEDAKZM/yZ2EwL/hLyGbCUFldBI= -github.com/chromedp/chromedp v0.6.0/go.mod h1:Yay7TUDCNOQBK8EJDUon6AUaQI12VEBOuULcGtY4uDY= +github.com/chromedp/cdproto v0.0.0-20220827030233-358ed4af73cf h1:e0oJZmGJidTRZ0FvWXNhdj9OaOMN30Yf+T3K2Tf3L+s= +github.com/chromedp/cdproto v0.0.0-20220827030233-358ed4af73cf/go.mod h1:5Y4sD/eXpwrChIuxhSr/G20n9CdbCmoerOHnuAf0Zr0= +github.com/chromedp/chromedp v0.8.5 h1:HAVg54yQFcn7sg5reVjXtoI1eQaFxhjAjflHACicUFw= +github.com/chromedp/chromedp v0.8.5/go.mod h1:xal2XY5Di7m/bzlGwtoYpmgIOfDqCakOIVg5OfdkPZ4= github.com/chromedp/sysutil v1.0.0 h1:+ZxhTpfpZlmchB58ih/LBHX52ky7w2VhQVKQMucy3Ic= github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= @@ -33,18 +23,22 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dustin/gomemcached v0.0.0-20160817010731-a2284a01c143 h1:K9CFK8HRZWzmoIWbpA7u0XYLggCyfa/N77eVaq/nUiA= github.com/dustin/gomemcached v0.0.0-20160817010731-a2284a01c143/go.mod h1:BLhrehfVmtABJWBZTJV8HyPWCSZoiMzjjcZ3+vHHhPI= -github.com/eclipse/paho.mqtt.golang v1.2.0 h1:1F8mhG9+aO5/xpdtFkW4SxOJB67ukuDC3t2y2qayIX0= -github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/eclipse/paho.mqtt.golang v1.4.1 h1:tUSpviiL5G3P9SZZJPC4ZULZJsxQKXxfENpMvdbAXAI= +github.com/eclipse/paho.mqtt.golang v1.4.1/go.mod h1:JGt0RsEwEX+Xa/agj90YJ9d9DH2b7upDZMK9HRbFvCA= +github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-ldap/ldap v3.0.3+incompatible h1:HTeSZO8hWMS1Rgb2Ziku6b8a7qRIZZMHjsvuZyatzwk= github.com/go-ldap/ldap v3.0.3+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc= -github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI= -github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= -github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= -github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/goburrow/modbus v0.1.0 h1:DejRZY73nEM6+bt5JSP6IsFolJ9dVcqxsYbpLbeW/ro= github.com/goburrow/modbus v0.1.0/go.mod h1:Kx552D5rLIS8E7TyUwQ/UdHEqvX5T8tyiGBTlzMcZBg= @@ -54,18 +48,22 @@ github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gobwas/ws v1.0.4 h1:5eXU1CZhpQdq5kXbKb+sECH5Ia5KiO6CYzIzdlVx6Bs= -github.com/gobwas/ws v1.0.4/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= +github.com/gobwas/ws v1.1.0 h1:7RFti/xnNkMJnrK7D1yQ/iCIB5OrrY/54/H930kIbHA= +github.com/gobwas/ws v1.1.0/go.mod h1:nzvNcVha5eUziGrbxFCo6qFIojQHjJV5cLYIbezhfL0= github.com/godbus/dbus v4.1.0+incompatible h1:WqqLRTsQic3apZUK9qC5sGNfXthmPXzUZ7nQPrNITa4= github.com/godbus/dbus v4.1.0+incompatible/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= -github.com/godror/godror v0.20.1 h1:s/ehD65nfVzWR2MrZGChDkLvVPlIVxbt+Jpzfwkl1c8= -github.com/godror/godror v0.20.1/go.mod h1:YlPoIf962ZZKPM5Xqa8NxmGgck39pi51tqAs+K3IaFM= -github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE= -github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/godror/godror v0.34.0 h1:/D40cxuWY3PtMa1oIcfXqqInlts5anEL3vj6IkTW8Q8= +github.com/godror/godror v0.34.0/go.mod h1:9QtjJWw+r1v9zh93Qx+hSOfYRVgj11a/7TUnU/00Wbc= +github.com/godror/knownpb v0.1.0 h1:dJPK8s/I3PQzGGaGcUStL2zIaaICNzKKAK8BzP1uLio= +github.com/godror/knownpb v0.1.0/go.mod h1:4nRFbQo1dDuwKnblRXDxrfCFYeT4hjg3GjMqef58eRE= +github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= +github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= @@ -73,51 +71,47 @@ github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgO github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= -github.com/jackc/pgconn v1.4.0/go.mod h1:Y2O3ZDF0q4mMacyWV3AstPJpeHXWGEetiFttmq5lahk= -github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= -github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= -github.com/jackc/pgconn v1.6.5-0.20200905181414-0d4f029683fc h1:9ThyBXKdyBFN2Y1NSCPGCA0kdWCNpd9u4SKWwtr6GfU= -github.com/jackc/pgconn v1.6.5-0.20200905181414-0d4f029683fc/go.mod h1:gm9GeeZiC+Ja7JV4fB/MNDeaOqsCrzFiZlLVhAompxk= +github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= +github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= +github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= +github.com/jackc/pgconn v1.13.0 h1:3L1XMNV2Zvca/8BYhzcRFS70Lr0WlDg16Di6SFGAbys= +github.com/jackc/pgconn v1.13.0/go.mod h1:AnowpAqO4CMIIJNZl2VJp+KrkAZciAkhEl0W0JIobpI= github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= -github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2 h1:JVX6jT/XfzNqIjye4717ITLaNwV9mWbJx0dLCpcRzdA= github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= +github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= +github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5Wi/+Zz7xoE5ALHsRQlOctkOiHc= +github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.0.4 h1:RHkX5ZUD9bl/kn0f9dYUWs1N7Nwvo1wwUYvKiR26Zco= -github.com/jackc/pgproto3/v2 v2.0.4/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= +github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.3.1 h1:nwj7qwf0S+Q7ISFfBndqeLwSwxs+4DPsbRFjECT1Y4Y= +github.com/jackc/pgproto3/v2 v2.3.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= -github.com/jackc/pgtype v1.2.0/go.mod h1:5m2OfMh1wTK7x+Fk952IDmI4nw3nPrvtQdM0ZT4WpC0= -github.com/jackc/pgtype v1.3.1-0.20200510190516-8cd94a14c75a/go.mod h1:vaogEUkALtxZMCH411K+tKzNpwzCKU+AnPzBKZ+I+Po= -github.com/jackc/pgtype v1.3.1-0.20200606141011-f6355165a91c/go.mod h1:cvk9Bgu/VzJ9/lxTO5R5sf80p0DiucVtN7ZxvaC4GmQ= -github.com/jackc/pgtype v1.4.3-0.20200905161353-e7d2b057a716 h1:DrP52jA32liWkjCF/g3rYC1QjnRh6kvyXaZSevAtlqE= -github.com/jackc/pgtype v1.4.3-0.20200905161353-e7d2b057a716/go.mod h1:JCULISAZBFGrHaOXIIFiyfzW5VY0GRitRr8NeJsrdig= +github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= +github.com/jackc/pgtype v1.12.0 h1:Dlq8Qvcch7kiehm8wPGIW0W3KsCCHJnRacKW0UM8n5w= +github.com/jackc/pgtype v1.12.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= -github.com/jackc/pgx/v4 v4.5.0/go.mod h1:EpAKPLdnTorwmPUUsqrPxy5fphV18j9q3wrfRXgo+kA= -github.com/jackc/pgx/v4 v4.6.1-0.20200510190926-94ba730bb1e9/go.mod h1:t3/cdRQl6fOLDxqtlyhe9UWgfIi9R8+8v8GKV5TRA/o= -github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904/go.mod h1:ZDaNWkt9sW1JMiNn0kdYBaLelIhw7Pg4qd+Vk6tw7Hg= -github.com/jackc/pgx/v4 v4.8.2-0.20200910143026-040df1ccef85 h1:G5gbS1Q6cq7/Q1Z1CUqU9IKWfar2R1P6CE0zkKClEG0= -github.com/jackc/pgx/v4 v4.8.2-0.20200910143026-040df1ccef85/go.mod h1:OWJpVJk5U9XXEiYHeQ+5NtRt82Y5c8gvIZj96kl27Ow= +github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= +github.com/jackc/pgx/v4 v4.17.2 h1:0Ut0rpeKwvIVbMQ1KbMBU4h6wxehBI535LK6Flheh8E= +github.com/jackc/pgx/v4 v4.17.2/go.mod h1:lcxIZN44yMIrWI78a5CpucdD14hX0SBDbNRvjDBItsw= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.2-0.20200821025810-91d0159cc97a h1:ec2LCBkfN1pOq0PhLRH/QitjSXr9s2dnh0gOFyohxHM= -github.com/jackc/puddle v1.1.2-0.20200821025810-91d0159cc97a/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.3.0 h1:eHK/5clGOatcjX3oWGBO/MpxpbHzSwud5EWTSCI+MX0= +github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= @@ -127,33 +121,33 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kULo2bwGEkFvCePZ3qHDDTC3/J9Swo= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.3.0 h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU= -github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= +github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-sqlite3 v1.14.8 h1:gDp86IdQsN/xWjIEmr9MF6o9mpksUgh0fu+9ByFxzIU= -github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/mediocregopher/radix/v3 v3.5.0 h1:8QHQmNh2ne9aFxTD3z63u/bkPPiOtknHoz80oP8EA/E= -github.com/mediocregopher/radix/v3 v3.5.0/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= -github.com/memcachier/mc/v3 v3.0.1 h1:Os/fUl/8c+hc1qWgjv5hNK0JI6GxKUOuehzB/UmjLP0= -github.com/memcachier/mc/v3 v3.0.1/go.mod h1:GzjocBahcXPxt2cmqzknrgqCOmMxiSzhVKPOe90Tpug= -github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= -github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= +github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI= +github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= +github.com/mediocregopher/radix/v3 v3.8.1 h1:rOkHflVuulFKlwsLY01/M2cM2tWCjDoETcMqKbAWu1M= +github.com/mediocregopher/radix/v3 v3.8.1/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= +github.com/memcachier/mc/v3 v3.0.3 h1:qii+lDiPKi36O4Xg+HVKwHu6Oq+Gt17b+uEiA0Drwv4= +github.com/memcachier/mc/v3 v3.0.3/go.mod h1:GzjocBahcXPxt2cmqzknrgqCOmMxiSzhVKPOe90Tpug= +github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA= +github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= github.com/natefinch/npipe v0.0.0-20160621034901-c1b8fa8bdcce h1:TqjP/BTDrwN7zP9xyXVuLsMBXYMt6LLYi55PlrIcq8U= github.com/natefinch/npipe v0.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:ifHPsLndGGzvgzcaXUvzmt6LxKT4pJ+uzEhtnMt+f7A= +github.com/oklog/ulid/v2 v2.0.2 h1:r4fFzBm+bv0wNKNh5eXTwU7i85y5x+uwkxCUTNVQqLc= github.com/omeid/go-yarn v0.0.1 h1:mUQExNwUrYn7tZRwQdsUuoQWHIujtjjpjb/PAtUj9dk= github.com/omeid/go-yarn v0.0.1/go.mod h1:JYxmAvShSw7YmX/9vFsccpJE4o/KW111eUh3n/TQ5h8= +github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde h1:x0TT0RDC7UhAVbbWWBzr41ElhJx5tXPWkIHA2HWPRuw= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -165,47 +159,65 @@ github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OK github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= -github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc h1:jUIKcSPO9MoMJBbEoyE/RJoE8vz7Mb8AjvifMMwSyvY= -github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= +golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220513210516-0976fa681c29 h1:w8s32wxx3sY+OjLlv9qltkLU5yvJzxjjgiHWLjdIcw4= +golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -213,20 +225,30 @@ golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng= -golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64 h1:UiNENfZ8gDvpiWw7IpOMQ27spWmThO1RwwdQVbJahJM= +golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -234,6 +256,10 @@ golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 h1:BonxutuHCTL0rBDnZlKjpGIQFTjyUVTexFOdWkB6Fg0= +golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -241,6 +267,9 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d h1:TxyelI5cVkbREznMhfzycHdkp5cLA7DpE+GKjSslYhM= gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -248,8 +277,8 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= -gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= diff --git a/src/go/internal/agent/scheduler/manager.go b/src/go/internal/agent/scheduler/manager.go index fa0c32abc0a..14e96f4d012 100644 --- a/src/go/internal/agent/scheduler/manager.go +++ b/src/go/internal/agent/scheduler/manager.go @@ -527,6 +527,7 @@ func (m *Manager) init() { if metric.Plugin.IsExternal() { ext := metric.Plugin.(*external.Plugin) + metric.Plugin.SetCapacity(1) log.Infof("using plugin '%s' (%s) providing following interfaces: %s", metric.Plugin.Name(), ext.Path, interfaces) } else { diff --git a/src/go/pkg/tls/tls.go b/src/go/pkg/tls/tls.go index 4a73e81456c..be240db2e34 100644 --- a/src/go/pkg/tls/tls.go +++ b/src/go/pkg/tls/tls.go @@ -961,6 +961,7 @@ func SupportedErrMsg() string { } func init() { + log.Tracef("Calling C function \"tls_init()\"") supported = C.tls_init() != -1 if !supported { @@ -970,8 +971,10 @@ func init() { func describeCiphersuites(context unsafe.Pointer) (desc string) { var cDesc *C.char + log.Tracef("Calling C function \"tls_describe_ciphersuites()\"") C.tls_describe_ciphersuites(C.SSL_CTX_LP(context), &cDesc) desc = C.GoString(cDesc) + log.Tracef("Calling C function \"free()\"") C.free(unsafe.Pointer(cDesc)) return } @@ -987,8 +990,10 @@ type tlsConn struct { func (c *tlsConn) Error() (err error) { var cBuf *C.char var errmsg string + log.Tracef("Calling C function \"tls_error()\"") if c.tls != nil && 0 != C.tls_error((*C.tls_t)(c.tls), &cBuf) { errmsg = C.GoString(cBuf) + log.Tracef("Calling C function \"free()\"") C.free(unsafe.Pointer(cBuf)) } else { errmsg = "unknown openssl error" @@ -997,12 +1002,14 @@ func (c *tlsConn) Error() (err error) { } func (c *tlsConn) ready() bool { + log.Tracef("Calling C function \"tls_ready()\"") return C.tls_ready((*C.tls_t)(c.tls)) == 1 } // Note, don't use flushTLS() and recvTLS() concurrently func (c *tlsConn) flushTLS() (err error) { for { + log.Tracef("Calling C function \"tls_recv()\"") if cn := C.tls_recv((*C.tls_t)(c.tls), (*C.char)(unsafe.Pointer(&c.buf[0])), C.int(len(c.buf))); cn > 0 { if c.shiftDeadline { if err = c.conn.SetWriteDeadline(time.Now().Add(c.timeout)); err != nil { @@ -1030,6 +1037,7 @@ func (c *tlsConn) recvTLS() (err error) { if n, err = c.conn.Read(c.buf); err != nil { return } + log.Tracef("Calling C function \"tls_send()\"") C.tls_send((*C.tls_t)(c.tls), (*C.char)(unsafe.Pointer(&c.buf[0])), C.int(n)) return } @@ -1055,9 +1063,11 @@ func (c *tlsConn) SetWriteDeadline(t time.Time) error { } func (c *tlsConn) Close() (err error) { + log.Tracef("Calling C function \"tls_close()\"") cr := C.tls_close((*C.tls_t)(c.tls)) c.conn.Close() + log.Tracef("Calling C function \"tls_free()\"") C.tls_free((*C.tls_t)(c.tls)) c.tls = nil @@ -1072,12 +1082,15 @@ func (c *tlsConn) verifyIssuerSubject(cfg *Config) (err error) { var cSubject, cIssuer *C.char if cfg.ServerCertIssuer != "" { cIssuer = C.CString(cfg.ServerCertIssuer) + log.Tracef("Calling C function \"free()\"") defer C.free(unsafe.Pointer(cSubject)) } if cfg.ServerCertSubject != "" { cSubject = C.CString(cfg.ServerCertSubject) + log.Tracef("Calling C function \"free()\"") defer C.free(unsafe.Pointer(cSubject)) } + log.Tracef("Calling C function \"tls_validate_issuer_and_subject()\"") if 0 != C.tls_validate_issuer_and_subject((*C.tls_t)(c.tls), cIssuer, cSubject) { return c.Error() } @@ -1087,8 +1100,10 @@ func (c *tlsConn) verifyIssuerSubject(cfg *Config) (err error) { func (c *tlsConn) String() (desc string) { var cDesc *C.char + log.Tracef("Calling C function \"tls_description()\"") C.tls_description((*C.tls_t)(c.tls), &cDesc) desc = C.GoString(cDesc) + log.Tracef("Calling C function \"free()\"") C.free(unsafe.Pointer(cDesc)) return } @@ -1099,10 +1114,13 @@ type Client struct { } func (c *Client) checkConnection() (err error) { + log.Tracef("Calling C function \"tls_connected()\"") if C.tls_connected((*C.tls_t)(c.tls)) == C.int(1) { return } + log.Tracef("Calling C function \"tls_connected()\"") for C.tls_connected((*C.tls_t)(c.tls)) != C.int(1) { + log.Tracef("Calling C function \"tls_handshake()\"") cRet := C.tls_handshake((*C.tls_t)(c.tls)) if cRet == 0 { break @@ -1125,6 +1143,7 @@ func (c *Client) Write(b []byte) (n int, err error) { if err = c.checkConnection(); err != nil { return } + log.Tracef("Calling C function \"tls_write()\"") cRet := C.tls_write((*C.tls_t)(c.tls), (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b))) if cRet <= 0 { return 0, c.Error() @@ -1140,6 +1159,7 @@ func (c *Client) Read(b []byte) (n int, err error) { if err = c.checkConnection(); err != nil { return } + log.Tracef("Calling C function \"tls_read()\"") cRet := C.tls_read((*C.tls_t)(c.tls), (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b))) if cRet > 0 { return int(cRet), nil @@ -1169,7 +1189,9 @@ func NewClient(nc net.Conn, cfg *Config, timeout time.Duration, shiftDeadline bo cSecret = C.CString(cfg.PSKKey) defer func() { + log.Tracef("Calling C function \"free()\"") C.free(unsafe.Pointer(cUser)) + log.Tracef("Calling C function \"free()\"") C.free(unsafe.Pointer(cSecret)) }() context = pskContext @@ -1179,11 +1201,13 @@ func NewClient(nc net.Conn, cfg *Config, timeout time.Duration, shiftDeadline bo hostname := url.Host() if nil == net.ParseIP(hostname) { cHostname = C.CString(hostname) + log.Tracef("Calling C function \"free()\"") defer C.free(unsafe.Pointer(cHostname)) } } // for TLS we overwrite the timeoutMode and force it to move on every read or write + log.Tracef("Calling C function \"tls_new_client()\"") c := &Client{ tlsConn: tlsConn{ conn: nc, @@ -1193,6 +1217,7 @@ func NewClient(nc net.Conn, cfg *Config, timeout time.Duration, shiftDeadline bo shiftDeadline: shiftDeadline, }, } + log.Tracef("Calling C function \"tls_free()\"") runtime.SetFinalizer(c, func(c *Client) { C.tls_free((*C.tls_t)(c.tls)) }) if !c.ready() { @@ -1218,10 +1243,12 @@ type Server struct { } func (s *Server) checkConnection() (err error) { + log.Tracef("Calling C function \"tls_connected()\"") if C.tls_connected((*C.tls_t)(s.tls)) == C.int(1) { return } for { + log.Tracef("Calling C function \"tls_accept()\"") cRet := C.tls_accept((*C.tls_t)(s.tls)) if cRet == 0 { break @@ -1244,6 +1271,7 @@ func (s *Server) Write(b []byte) (n int, err error) { if err = s.checkConnection(); err != nil { return } + log.Tracef("Calling C function \"tls_write()\"") cRet := C.tls_write((*C.tls_t)(s.tls), (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b))) if cRet <= 0 { return 0, s.Error() @@ -1257,6 +1285,7 @@ func (s *Server) Read(b []byte) (n int, err error) { if err = s.checkConnection(); err != nil { return } + log.Tracef("Calling C function \"tls_read()\"") cRet := C.tls_read((*C.tls_t)(s.tls), (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b))) if cRet > 0 { return int(cRet), nil @@ -1281,7 +1310,9 @@ func NewServer(nc net.Conn, cfg *Config, b []byte, timeout time.Duration, shiftD cSecret = C.CString(cfg.PSKKey) defer func() { + log.Tracef("Calling C function \"free()\"") C.free(unsafe.Pointer(cUser)) + log.Tracef("Calling C function \"free()\"") C.free(unsafe.Pointer(cSecret)) }() } @@ -1292,6 +1323,7 @@ func NewServer(nc net.Conn, cfg *Config, b []byte, timeout time.Duration, shiftD } // for TLS we overwrite the timeoutMode and force it to move on every read or write + log.Tracef("Calling C function \"tls_new_server()\"") s := &Server{ tlsConn: tlsConn{ conn: nc, @@ -1301,12 +1333,14 @@ func NewServer(nc net.Conn, cfg *Config, b []byte, timeout time.Duration, shiftD shiftDeadline: shiftDeadline, }, } + log.Tracef("Calling C function \"tls_free()\"") runtime.SetFinalizer(s, func(s *Server) { C.tls_free((*C.tls_t)(s.tls)) }) if !s.ready() { return nil, s.Error() } + log.Tracef("Calling C function \"tls_send()\"") C.tls_send((*C.tls_t)(s.tls), (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b))) if err = s.checkConnection(); err != nil { @@ -1345,11 +1379,13 @@ type Config struct { } func CopyrightMessage() (message string) { + log.Tracef("Calling C function \"tls_version()\"") version := C.tls_version() if version == nil { return "" } + log.Tracef("Calling C function \"tls_version_static()\"") return fmt.Sprintf("\n\nThis product includes software developed by the OpenSSL Project\n"+ "for use in the OpenSSL Toolkit (http://www.openssl.org/).\n\n"+ "Compiled with %s\nRunning with %s\n", C.GoString(C.tls_version_static()), C.GoString(version)) @@ -1360,9 +1396,11 @@ func Init(config *Config) (err error) { return errors.New(SupportedErrMsg()) } if pskContext != nil { + log.Tracef("Calling C function \"tls_free_context()\"") C.tls_free_context(C.SSL_CTX_LP(pskContext)) } if defaultContext != nil { + log.Tracef("Calling C function \"tls_free_context()\"") C.tls_free_context(C.SSL_CTX_LP(defaultContext)) } @@ -1371,28 +1409,37 @@ func Init(config *Config) (err error) { cCaFile = C.CString(config.CAFile) cCertFile = C.CString(config.CertFile) cKeyFile = C.CString(config.KeyFile) + log.Tracef("Calling C function \"free()\"") defer C.free(unsafe.Pointer(cCaFile)) + log.Tracef("Calling C function \"free()\"") defer C.free(unsafe.Pointer(cCertFile)) + log.Tracef("Calling C function \"free()\"") defer C.free(unsafe.Pointer(cKeyFile)) if config.CRLFile != "" { cCrlFile = C.CString(config.CRLFile) + log.Tracef("Calling C function \"free()\"") defer C.free(unsafe.Pointer(cCrlFile)) } } + log.Tracef("Calling C function \"tls_new_context()\"") if defaultContext = unsafe.Pointer(C.tls_new_context(cCaFile, cCrlFile, cCertFile, cKeyFile, &cErr)); defaultContext == nil { err = fmt.Errorf("cannot initialize default TLS context: %s", C.GoString(cErr)) + log.Tracef("Calling C function \"free()\"") C.free(unsafe.Pointer(cErr)) return } + log.Tracef("Calling C function \"tls_new_context()\"") if pskContext = unsafe.Pointer(C.tls_new_context(cNULL, cNULL, cNULL, cNULL, &cErr)); pskContext == nil { err = fmt.Errorf("cannot initialize PSK TLS context: %s", C.GoString(cErr)) + log.Tracef("Calling C function \"free()\"") C.free(unsafe.Pointer(cErr)) return } + log.Tracef("Calling C function \"tls_version()\"") log.Infof("OpenSSL library (%s) initialized", C.GoString(C.tls_version())) log.Debugf("default context ciphersuites:%s", describeCiphersuites(defaultContext)) log.Debugf("psk context ciphersuites:%s", describeCiphersuites(pskContext)) diff --git a/src/go/pkg/version/version.go b/src/go/pkg/version/version.go index c89f10d27e5..67eb292ae04 100644 --- a/src/go/pkg/version/version.go +++ b/src/go/pkg/version/version.go @@ -26,15 +26,15 @@ import ( ) const ( - ZABBIX_REVDATE = "14 September 2022" + ZABBIX_REVDATE = "29 September 2022" ZABBIX_VERSION_MAJOR = 6 ZABBIX_VERSION_MINOR = 4 ZABBIX_VERSION_PATCH = 0 - ZABBIX_VERSION_RC = "alpha2" + ZABBIX_VERSION_RC = "beta2" ZABBIX_VERSION_RC_NUM = "{ZABBIX_RC_NUM}" ZABBIX_VERSION_REVISION = "{ZABBIX_REVISION}" copyrightMessage = "Copyright (C) 2022 Zabbix SIA\n" + - "License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>.\n" + + "License GPLv2+: GNU GPL version 2 or later <https://www.gnu.org/licenses/>.\n" + "This is free software: you are free to change and redistribute it according to\n" + "the license. There is NO WARRANTY, to the extent permitted by law." ) diff --git a/src/go/pkg/zbxlib/checks.go b/src/go/pkg/zbxlib/checks.go index aceaf810546..d24a96c876e 100644 --- a/src/go/pkg/zbxlib/checks.go +++ b/src/go/pkg/zbxlib/checks.go @@ -36,9 +36,9 @@ static int execute_check(const char *key, zbx_agent_check_t check_func, char **v AGENT_RESULT result; AGENT_REQUEST request; - init_request(&request); - init_result(&result); - if (SUCCEED != parse_item_key(key, &request)) + zbx_init_agent_request(&request); + zbx_init_agent_result(&result); + if (SUCCEED != zbx_parse_item_key(key, &request)) { *value = zbx_strdup(NULL, "Invalid item key format."); goto out; @@ -59,8 +59,8 @@ static int execute_check(const char *key, zbx_agent_check_t check_func, char **v ret = SUCCEED; out: - free_result(&result); - free_request(&request); + zbx_free_agent_result(&result); + zbx_free_agent_request(&request); return ret; } @@ -72,6 +72,7 @@ import ( "unsafe" "zabbix.com/pkg/itemutil" + "git.zabbix.com/ap/plugin-support/log" ) func ExecuteCheck(key string, params []string) (result *string, err error) { @@ -83,17 +84,21 @@ func ExecuteCheck(key string, params []string) (result *string, err error) { var cvalue, cerrmsg *C.char ckey := C.CString(itemutil.MakeKey(key, params)) + log.Tracef("Calling C function \"execute_check()\"") if C.execute_check(ckey, C.zbx_agent_check_t(cfunc), &cvalue, &cerrmsg) == Succeed { if cvalue != nil { value := C.GoString(cvalue) result = &value } + log.Tracef("Calling C function \"free()\"") C.free(unsafe.Pointer(cvalue)) } else { err = errors.New(C.GoString(cerrmsg)) + log.Tracef("Calling C function \"free()\"") C.free(unsafe.Pointer(cerrmsg)) } + log.Tracef("Calling C function \"free()\"") C.free(unsafe.Pointer(ckey)) return } diff --git a/src/go/pkg/zbxlib/eventlog_windows.go b/src/go/pkg/zbxlib/eventlog_windows.go index dadf1a31b6d..bc22fac410f 100644 --- a/src/go/pkg/zbxlib/eventlog_windows.go +++ b/src/go/pkg/zbxlib/eventlog_windows.go @@ -148,6 +148,8 @@ import ( "unsafe" "zabbix.com/internal/agent" "zabbix.com/pkg/tls" + + "git.zabbix.com/ap/plugin-support/log" ) type EventLogItem struct { @@ -169,13 +171,16 @@ type EventLogResult struct { } func ProcessEventLogCheck(data unsafe.Pointer, item *EventLogItem, refresh int, cblob unsafe.Pointer) { + log.Tracef("Calling C function \"metric_set_refresh()\"") C.metric_set_refresh(C.ZBX_ACTIVE_METRIC_LP(data), C.int(refresh)) var clastLogsizeSent, clastLogsizeLast C.zbx_uint64_t var cstate, cmtime C.int + log.Tracef("Calling C function \"metric_get_meta()\"") C.metric_get_meta(C.ZBX_ACTIVE_METRIC_LP(data), &clastLogsizeSent, &cmtime) clastLogsizeLast = clastLogsizeSent + log.Tracef("Calling C function \"new_eventlog_result()\"") result := C.new_eventlog_result(C.int(item.Output.PersistSlotsAvailable())) var tlsConfig *tls.Config @@ -193,6 +198,7 @@ func ProcessEventLogCheck(data unsafe.Pointer, item *EventLogItem, refresh int, return } if (nil != tlsConfig) { + log.Tracef("Calling C function \"zbx_config_tls_init_for_agent2()\"") C.zbx_config_tls_init_for_agent2(&ctlsConfig, (C.uint)(tlsConfig.Accept), (C.uint)(tlsConfig.Connect), (C.CString)(tlsConfig.PSKIdentity), (C.CString)(tlsConfig.PSKKey), (C.CString)(tlsConfig.CAFile), (C.CString)(tlsConfig.CRLFile), (C.CString)(tlsConfig.CertFile), @@ -202,6 +208,7 @@ func ProcessEventLogCheck(data unsafe.Pointer, item *EventLogItem, refresh int, } var cerrmsg *C.char + log.Tracef("Calling C function \"process_eventlog_check()\"") ret := C.process_eventlog_check(nil, C.zbx_vector_ptr_lp_t(unsafe.Pointer(result)), C.zbx_vector_ptr_lp_t(cblob), C.ZBX_ACTIVE_METRIC_LP(data), C.zbx_process_value_func_t(C.process_eventlog_value_cb), &clastLogsizeSent, ctlsConfig_p, &cerrmsg) @@ -214,6 +221,7 @@ func ProcessEventLogCheck(data unsafe.Pointer, item *EventLogItem, refresh int, if logTs.Before(item.LastTs) { logTs = item.LastTs } + log.Tracef("Calling C function \"get_eventlog_value()\"") for i := 0; C.get_eventlog_value(result, C.int(i), &cvalue, &csource, &clogeventid, &cseverity, &ctimestamp, &cstate, &clastlogsize) != C.FAIL; i++ { @@ -249,16 +257,19 @@ func ProcessEventLogCheck(data unsafe.Pointer, item *EventLogItem, refresh int, item.Results = append(item.Results, &r) logTs = logTs.Add(time.Nanosecond) } + log.Tracef("Calling C function \"free_eventlog_result()\"") C.free_eventlog_result(result) item.LastTs = logTs if ret == C.FAIL { + log.Tracef("Calling C function \"metric_set_unsupported()\"") C.metric_set_unsupported(C.ZBX_ACTIVE_METRIC_LP(data)) var err error if cerrmsg != nil { err = errors.New(C.GoString(cerrmsg)) + log.Tracef("Calling C function \"free()\"") C.free(unsafe.Pointer(cerrmsg)) } else { err = errors.New("Unknown error.") @@ -269,9 +280,11 @@ func ProcessEventLogCheck(data unsafe.Pointer, item *EventLogItem, refresh int, } item.Results = append(item.Results, result) } else { + log.Tracef("Calling C function \"metric_set_supported()\"") ret := C.metric_set_supported(C.ZBX_ACTIVE_METRIC_LP(data), clastLogsizeSent, 0, clastLogsizeLast, 0) if ret == Succeed { + log.Tracef("Calling C function \"metric_get_meta()\"") C.metric_get_meta(C.ZBX_ACTIVE_METRIC_LP(data), &clastLogsizeLast, &cmtime) result := EventLogResult{ Ts: time.Now(), diff --git a/src/go/pkg/zbxlib/expressions.go b/src/go/pkg/zbxlib/expressions.go index da079ee6877..d89a5c65e7a 100644 --- a/src/go/pkg/zbxlib/expressions.go +++ b/src/go/pkg/zbxlib/expressions.go @@ -48,21 +48,28 @@ import "C" import ( "errors" "unsafe" + + "git.zabbix.com/ap/plugin-support/log" ) func NewGlobalRegexp() (grxp unsafe.Pointer) { + log.Tracef("Calling C function \"new_global_regexp()\"") return unsafe.Pointer(C.new_global_regexp()) } func DestroyGlobalRegexp(grxp unsafe.Pointer) { + log.Tracef("Calling C function \"free_global_regexp()\"") C.free_global_regexp(C.zbx_vector_ptr_lp_t(grxp)) } func AddGlobalRegexp(grxp unsafe.Pointer, name, body string, expr_type int, delim byte, mode int) { cname := C.CString(name) cbody := C.CString(body) + log.Tracef("Calling C function \"add_regexp_ex()\"") C.add_regexp_ex(C.zbx_vector_ptr_lp_t(grxp), cname, cbody, C.int(expr_type), C.char(delim), C.int(mode)) + log.Tracef("Calling C function \"free()\"") C.free(unsafe.Pointer(cname)) + log.Tracef("Calling C function \"free()\"") C.free(unsafe.Pointer(cbody)) } @@ -77,9 +84,11 @@ func MatchGlobalRegexp( var ctemplate, coutput *C.char if output_template != nil { ctemplate = C.CString(*output_template) + log.Tracef("Calling C function \"free()\"") defer C.free(unsafe.Pointer(ctemplate)) } + log.Tracef("Calling C function \"regexp_sub_ex()\"") ret := C.regexp_sub_ex(C.zbx_vector_ptr_lp_t(grxp), cvalue, cpattern, C.int(mode), ctemplate, &coutput) switch ret { case C.ZBX_REGEXP_MATCH: @@ -93,9 +102,12 @@ func MatchGlobalRegexp( err = errors.New("invalid global regular expression") } + log.Tracef("Calling C function \"free()\"") C.free(unsafe.Pointer(cvalue)) + log.Tracef("Calling C function \"free()\"") C.free(unsafe.Pointer(cpattern)) if coutput != nil { + log.Tracef("Calling C function \"free()\"") C.free(unsafe.Pointer(coutput)) } return diff --git a/src/go/pkg/zbxlib/globals_windows.go b/src/go/pkg/zbxlib/globals_windows.go index fdd88b66736..126123dc817 100644 --- a/src/go/pkg/zbxlib/globals_windows.go +++ b/src/go/pkg/zbxlib/globals_windows.go @@ -37,6 +37,9 @@ package zbxlib #cgo LDFLAGS: ${SRCDIR}/../../../../build/mingw/output/file.o #cgo LDFLAGS: ${SRCDIR}/../../../../build/mingw/output/time.o #cgo LDFLAGS: ${SRCDIR}/../../../../build/mingw/output/expr.o +#cgo LDFLAGS: ${SRCDIR}/../../../../build/mingw/output/function.o +#cgo LDFLAGS: ${SRCDIR}/../../../../build/mingw/output/host.o +#cgo LDFLAGS: ${SRCDIR}/../../../../build/mingw/output/macro.o #cgo LDFLAGS: ${SRCDIR}/../../../../build/mingw/output/token.o #cgo LDFLAGS: ${SRCDIR}/../../../../build/mingw/output/fatal.o #cgo LDFLAGS: ${SRCDIR}/../../../../build/mingw/output/disk.o diff --git a/src/go/pkg/zbxlib/log.go b/src/go/pkg/zbxlib/log.go index 342e33440b6..e07268e7ff0 100644 --- a/src/go/pkg/zbxlib/log.go +++ b/src/go/pkg/zbxlib/log.go @@ -75,10 +75,15 @@ int zbx_redirect_stdio(const char *filename) */ import "C" +import ( + "git.zabbix.com/ap/plugin-support/log" +) + func SetLogLevel(level int) { C.zbx_log_level = C.int(level) } func init() { + log.Tracef("Calling C function \"getpid()\"") C.zbx_agent_pid = C.getpid() } diff --git a/src/go/pkg/zbxlib/logfile.go b/src/go/pkg/zbxlib/logfile.go index 584330b4d6c..ce137831313 100644 --- a/src/go/pkg/zbxlib/logfile.go +++ b/src/go/pkg/zbxlib/logfile.go @@ -252,6 +252,7 @@ import ( "zabbix.com/pkg/itemutil" "zabbix.com/internal/agent" "zabbix.com/pkg/tls" + "git.zabbix.com/ap/plugin-support/log" ) const ( @@ -312,22 +313,27 @@ func NewActiveMetric(key string, params []string, lastLogsize uint64, mtime int3 } ckey := C.CString(itemutil.MakeKey(key, params)) + log.Tracef("Calling C function \"new_metric()\"") return unsafe.Pointer(C.new_metric(ckey, C.zbx_uint64_t(lastLogsize), C.int(mtime), C.int(flags))), nil } func FreeActiveMetric(data unsafe.Pointer) { + log.Tracef("Calling C function \"metric_free()\"") C.metric_free(C.ZBX_ACTIVE_METRIC_LP(data)) } func ProcessLogCheck(data unsafe.Pointer, item *LogItem, refresh int, cblob unsafe.Pointer) { + log.Tracef("Calling C function \"metric_set_refresh()\"") C.metric_set_refresh(C.ZBX_ACTIVE_METRIC_LP(data), C.int(refresh)) var clastLogsizeSent, clastLogsizeLast C.zbx_uint64_t var cmtimeSent, cmtimeLast C.int + log.Tracef("Calling C function \"metric_get_meta()\"") C.metric_get_meta(C.ZBX_ACTIVE_METRIC_LP(data), &clastLogsizeSent, &cmtimeSent) clastLogsizeLast = clastLogsizeSent cmtimeLast = cmtimeSent + log.Tracef("Calling C function \"new_log_result()\"") result := C.new_log_result(C.int(item.Output.PersistSlotsAvailable())) var tlsConfig *tls.Config @@ -345,6 +351,7 @@ func ProcessLogCheck(data unsafe.Pointer, item *LogItem, refresh int, cblob unsa return } if (nil != tlsConfig) { + log.Tracef("Calling C function \"zbx_config_tls_init_for_agent2()\"") C.zbx_config_tls_init_for_agent2(&ctlsConfig, (C.uint)(tlsConfig.Accept), (C.uint)(tlsConfig.Connect), (C.CString)(tlsConfig.PSKIdentity), (C.CString)(tlsConfig.PSKKey), (C.CString)(tlsConfig.CAFile), (C.CString)(tlsConfig.CRLFile), (C.CString)(tlsConfig.CertFile), @@ -354,11 +361,14 @@ func ProcessLogCheck(data unsafe.Pointer, item *LogItem, refresh int, cblob unsa } var cerrmsg *C.char + log.Tracef("Calling C function \"new_prep_vec()\"") cprepVec := C.new_prep_vec() // In Agent2 it is always empty vector. Not used but required for linking. + log.Tracef("Calling C function \"process_log_check()\"") ret := C.process_log_check(nil, C.zbx_vector_ptr_lp_t(unsafe.Pointer(result)), C.zbx_vector_ptr_lp_t(cblob), C.ZBX_ACTIVE_METRIC_LP(data), C.zbx_process_value_func_t(C.process_value_cb), &clastLogsizeSent, &cmtimeSent, &cerrmsg, cprepVec, ctlsConfig_p) + log.Tracef("Calling C function \"free_prep_vec()\"") C.free_prep_vec(cprepVec) // add cached results @@ -369,6 +379,7 @@ func ProcessLogCheck(data unsafe.Pointer, item *LogItem, refresh int, cblob unsa if logTs.Before(item.LastTs) { logTs = item.LastTs } + log.Tracef("Calling C function \"get_log_value()\"") for i := 0; C.get_log_value(result, C.int(i), &cvalue, &cstate, &clastlogsize, &cmtime) != C.FAIL; i++ { var value string var err error @@ -389,16 +400,19 @@ func ProcessLogCheck(data unsafe.Pointer, item *LogItem, refresh int, cblob unsa item.Results = append(item.Results, r) logTs = logTs.Add(time.Nanosecond) } + log.Tracef("Calling C function \"free_log_result()\"") C.free_log_result(result) item.LastTs = logTs if ret == C.FAIL { + log.Tracef("Calling C function \"metric_set_unsupported()\"") C.metric_set_unsupported(C.ZBX_ACTIVE_METRIC_LP(data)) var err error if cerrmsg != nil { err = errors.New(C.GoString(cerrmsg)) + log.Tracef("Calling C function \"free()\"") C.free(unsafe.Pointer(cerrmsg)) } else { err = errors.New("Unknown error.") @@ -409,10 +423,12 @@ func ProcessLogCheck(data unsafe.Pointer, item *LogItem, refresh int, cblob unsa } item.Results = append(item.Results, result) } else { + log.Tracef("Calling C function \"metric_set_supported()\"") ret := C.metric_set_supported(C.ZBX_ACTIVE_METRIC_LP(data), clastLogsizeSent, cmtimeSent, clastLogsizeLast, cmtimeLast) if ret == Succeed { + log.Tracef("Calling C function \"metric_get_meta()\"") C.metric_get_meta(C.ZBX_ACTIVE_METRIC_LP(data), &clastLogsizeLast, &cmtimeLast) result := &LogResult{ Ts: time.Now(), diff --git a/src/go/pkg/zbxlib/nextcheck.go b/src/go/pkg/zbxlib/nextcheck.go index dc02e09ebc0..ca239f940a8 100644 --- a/src/go/pkg/zbxlib/nextcheck.go +++ b/src/go/pkg/zbxlib/nextcheck.go @@ -33,6 +33,8 @@ import ( "errors" "time" "unsafe" + + "git.zabbix.com/ap/plugin-support/log" ) func GetNextcheck(itemid uint64, delay string, from time.Time) (nextcheck time.Time, scheduling bool, err error) { @@ -41,11 +43,13 @@ func GetNextcheck(itemid uint64, delay string, from time.Time) (nextcheck time.T cdelay := C.CString(delay) now := from.Unix() + log.Tracef("Calling C function \"zbx_get_agent_item_nextcheck()\"") ret := C.zbx_get_agent_item_nextcheck(C.zbx_uint64_t(itemid), cdelay, C.int(now), &cnextcheck, &cscheduling, &cerr) if ret != Succeed { err = errors.New(C.GoString(cerr)) + log.Tracef("Calling C function \"free()\"") C.free(unsafe.Pointer(cerr)) } else { nextcheck = time.Unix(int64(cnextcheck), 0) @@ -53,6 +57,7 @@ func GetNextcheck(itemid uint64, delay string, from time.Time) (nextcheck time.T scheduling = true } } + log.Tracef("Calling C function \"free()\"") C.free(unsafe.Pointer(cdelay)) return diff --git a/src/go/plugins/external/broker.go b/src/go/plugins/external/broker.go index df6310968e2..11fb36628db 100644 --- a/src/go/plugins/external/broker.go +++ b/src/go/plugins/external/broker.go @@ -85,7 +85,19 @@ func (b *pluginBroker) handleConnection() { for { t, data, err := comms.Read(b.conn) if err != nil { - return + if errors.Is(err, net.ErrClosed) { + log.Tracef("closed connection to loaded %s plugin", b.pluginName) + + return + } + + log.Errf( + "failed to read response for plugin %s, %s", + b.pluginName, + err.Error(), + ) + + continue } var id uint32 diff --git a/src/go/plugins/net/tcp/tcp_netstat.go b/src/go/plugins/net/tcp/tcp_netstat.go index 0621389666a..aeb4e107b97 100644 --- a/src/go/plugins/net/tcp/tcp_netstat.go +++ b/src/go/plugins/net/tcp/tcp_netstat.go @@ -25,6 +25,7 @@ package tcpudp import ( "errors" "net" + "os" "strconv" "github.com/cakturk/go-netstat/netstat" @@ -178,7 +179,8 @@ func netStatTcpCount(laddres net.IP, lNet *net.IPNet, lport int, raddres net.IP, count++ return false }) - if err != nil { + + if err != nil && !errors.Is(err, os.ErrNotExist) { return 0, err } diff --git a/src/go/plugins/net/udp/udp_netstat.go b/src/go/plugins/net/udp/udp_netstat.go index 558ad767222..43611b92c6b 100644 --- a/src/go/plugins/net/udp/udp_netstat.go +++ b/src/go/plugins/net/udp/udp_netstat.go @@ -24,6 +24,7 @@ package udp import ( "errors" + "os" "net" "strconv" @@ -157,7 +158,7 @@ func netStatUdpCount(laddres net.IP, lNet *net.IPNet, lport int, raddres net.IP, return true }) - if err != nil { + if err != nil && !errors.Is(err, os.ErrNotExist) { return 0, err } diff --git a/src/go/plugins/proc/proc_linux.go b/src/go/plugins/proc/proc_linux.go index 46929372dd4..9692ea47476 100644 --- a/src/go/plugins/proc/proc_linux.go +++ b/src/go/plugins/proc/proc_linux.go @@ -476,6 +476,7 @@ func (p *Plugin) Export(key string, params []string, ctx plugin.ContextProvider) ticks *= 1e12 ticks /= uint64(tail.timestamp.Sub(head.timestamp)) + log.Tracef("Calling C function \"sysconf()\"") return math.Round(float64(ticks)/float64(C.sysconf(C._SC_CLK_TCK))) / 10, nil } stats := &cpuUtilStats{accessed: now, history: make([]cpuUtilData, maxHistory)} diff --git a/src/go/plugins/proc/procfs_linux.go b/src/go/plugins/proc/procfs_linux.go index 021988cd394..6983fb7ed05 100644 --- a/src/go/plugins/proc/procfs_linux.go +++ b/src/go/plugins/proc/procfs_linux.go @@ -38,6 +38,7 @@ import ( "syscall" "zabbix.com/pkg/procfs" + "git.zabbix.com/ap/plugin-support/log" ) type processUserInfo struct { @@ -182,7 +183,9 @@ func getProcessCpuTimes(pid string, proc *procStatus) () { return } + log.Tracef("Calling C function \"sysconf()\"") proc.CpuTimeUser = float64(stat.utime) / float64(C.sysconf(C._SC_CLK_TCK)) + log.Tracef("Calling C function \"sysconf()\"") proc.CpuTimeSystem = float64(stat.stime) / float64(C.sysconf(C._SC_CLK_TCK)) proc.PageFaults = stat.pageFaults } diff --git a/src/go/plugins/system/cpu/cpu_linux.go b/src/go/plugins/system/cpu/cpu_linux.go index 188db3ea6a7..9c96e7d4295 100644 --- a/src/go/plugins/system/cpu/cpu_linux.go +++ b/src/go/plugins/system/cpu/cpu_linux.go @@ -32,6 +32,7 @@ import ( "strings" "git.zabbix.com/ap/plugin-support/plugin" + "git.zabbix.com/ap/plugin-support/log" ) // Plugin - @@ -132,10 +133,12 @@ func (p *Plugin) addCpu(index int) { } func numCPUConf() int { + log.Tracef("Calling C function \"sysconf()\"") return int(C.sysconf(C._SC_NPROCESSORS_CONF)) } func numCPUOnline() int { + log.Tracef("Calling C function \"sysconf()\"") return int(C.sysconf(C._SC_NPROCESSORS_ONLN)) } diff --git a/src/go/plugins/vfs/file/encoding.go b/src/go/plugins/vfs/file/encoding.go index 455765a180c..795d16ce3b9 100644 --- a/src/go/plugins/vfs/file/encoding.go +++ b/src/go/plugins/vfs/file/encoding.go @@ -31,6 +31,8 @@ import "C" import ( "syscall" "unsafe" + + "git.zabbix.com/ap/plugin-support/log" ) func decode(encoder string, inbuf []byte) (outbuf []byte) { @@ -48,10 +50,13 @@ func decode(encoder string, inbuf []byte) (outbuf []byte) { } tocode := C.CString("UTF-8") + log.Tracef("Calling C function \"free()\"") defer C.free(unsafe.Pointer(tocode)) fromcode := C.CString(encoder) + log.Tracef("Calling C function \"free()\"") defer C.free(unsafe.Pointer(fromcode)) + log.Tracef("Calling C function \"iconv_open()\"") cd, err := C.iconv_open(tocode, fromcode) if err != nil { @@ -65,6 +70,7 @@ func decode(encoder string, inbuf []byte) (outbuf []byte) { for { inptr := (*C.char)(unsafe.Pointer(&inbuf[len(inbuf)-int(inbytes)])) outptr := (*C.char)(unsafe.Pointer(&outbuf[len(outbuf)-int(outbytes)])) + log.Tracef("Calling C function \"call_iconv()\"") _, err := C.call_iconv(cd, inptr, &inbytes, outptr, &outbytes) if err == nil || err.(syscall.Errno) != syscall.E2BIG { break @@ -75,6 +81,7 @@ func decode(encoder string, inbuf []byte) (outbuf []byte) { outbuf = tmp } outbuf = outbuf[:len(outbuf)-int(outbytes)] + log.Tracef("Calling C function \"iconv_close()\"") C.iconv_close(cd) if len(outbuf) > 3 && 0xef == outbuf[0] && 0xbb == outbuf[1] && 0xbf == outbuf[2] { outbuf = outbuf[3:] diff --git a/src/libs/zbxalgo/prediction.c b/src/libs/zbxalgo/prediction.c index af6e60bfd91..6b2ab0bfbe6 100644 --- a/src/libs/zbxalgo/prediction.c +++ b/src/libs/zbxalgo/prediction.c @@ -1150,7 +1150,7 @@ out: double zbx_timeleft(double *t, double *x, int n, double now, double threshold, zbx_fit_t fit, unsigned k) { zbx_matrix_t *coefficients = NULL; - double current, result; + double current, result = -1.0; int res; if (1 == n) diff --git a/src/libs/zbxcommon/components_strings_representations.c b/src/libs/zbxcommon/components_strings_representations.c index 7f84c5819f6..dbae20d087f 100644 --- a/src/libs/zbxcommon/components_strings_representations.c +++ b/src/libs/zbxcommon/components_strings_representations.c @@ -67,8 +67,6 @@ const char *get_process_type_string(unsigned char proc_type) return "data sender"; case ZBX_PROCESS_TYPE_CONFSYNCER: return "configuration syncer"; - case ZBX_PROCESS_TYPE_HEARTBEAT: - return "heartbeat sender"; case ZBX_PROCESS_TYPE_SELFMON: return "self-monitoring"; case ZBX_PROCESS_TYPE_VMWARE: diff --git a/src/libs/zbxcommon/misc.c b/src/libs/zbxcommon/misc.c index 0b3d9ac2c90..b4b40971cda 100644 --- a/src/libs/zbxcommon/misc.c +++ b/src/libs/zbxcommon/misc.c @@ -281,7 +281,7 @@ void zbx_usage(void) static const char copyright_message[] = "Copyright (C) 2022 Zabbix SIA\n" - "License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>.\n" + "License GPLv2+: GNU GPL version 2 or later <https://www.gnu.org/licenses/>.\n" "This is free software: you are free to change and redistribute it according to\n" "the license. There is NO WARRANTY, to the extent permitted by law."; @@ -497,340 +497,6 @@ void uint64_array_remove(zbx_uint64_t *values, int *num, const zbx_uint64_t *rm_ /****************************************************************************** * * - * Return value: SUCCEED - the char is allowed in the host name * - * FAIL - otherwise * - * * - * Comments: in host name allowed characters: '0-9a-zA-Z. _-' * - * !!! Don't forget to sync the code with PHP !!! * - * * - ******************************************************************************/ -int is_hostname_char(unsigned char c) -{ - if (0 != isalnum(c)) - return SUCCEED; - - if (c == '.' || c == ' ' || c == '_' || c == '-') - return SUCCEED; - - return FAIL; -} - -/****************************************************************************** - * * - * Return value: SUCCEED - the char is allowed in the item key * - * FAIL - otherwise * - * * - * Comments: in key allowed characters: '0-9a-zA-Z._-' * - * !!! Don't forget to sync the code with PHP !!! * - * * - ******************************************************************************/ -int is_key_char(unsigned char c) -{ - if (0 != isalnum(c)) - return SUCCEED; - - if (c == '.' || c == '_' || c == '-') - return SUCCEED; - - return FAIL; -} - -/****************************************************************************** - * * - * Return value: SUCCEED - the char is allowed in the trigger function * - * FAIL - otherwise * - * * - * Comments: in trigger function allowed characters: 'a-z' * - * !!! Don't forget to sync the code with PHP !!! * - * * - ******************************************************************************/ -int is_function_char(unsigned char c) -{ - if (0 != islower(c)) - return SUCCEED; - - return FAIL; -} - -/****************************************************************************** - * * - * Return value: SUCCEED - the char is allowed in the macro name * - * FAIL - otherwise * - * * - * Comments: allowed characters in macro names: '0-9A-Z._' * - * !!! Don't forget to sync the code with PHP !!! * - * * - ******************************************************************************/ -int is_macro_char(unsigned char c) -{ - if (0 != isupper(c)) - return SUCCEED; - - if ('.' == c || '_' == c) - return SUCCEED; - - if (0 != isdigit(c)) - return SUCCEED; - - return FAIL; -} - -/****************************************************************************** - * * - * Purpose: checks if the name is a valid discovery macro * - * * - * Return value: SUCCEED - the name is a valid discovery macro * - * FAIL - otherwise * - * * - ******************************************************************************/ -int is_discovery_macro(const char *name) -{ - if ('{' != *name++ || '#' != *name++) - return FAIL; - - do - { - if (SUCCEED != is_macro_char(*name++)) - return FAIL; - - } while ('}' != *name); - - if ('\0' != name[1]) - return FAIL; - - return SUCCEED; -} - -/****************************************************************************** - * * - * Purpose: advances pointer to first invalid character in string * - * ensuring that everything before it is a valid key * - * * - * e.g., system.run[cat /etc/passwd | awk -F: '{ print $1 }'] * - * * - * Parameters: exp - [IN/OUT] pointer to the first char of key * - * * - * e.g., {host:system.run[cat /etc/passwd | awk -F: '{ print $1 }'].last(0)} * - * ^ * - * Return value: returns FAIL only if no key is present (length 0), * - * or the whole string is invalid. SUCCEED otherwise. * - * * - * Comments: the pointer is advanced to the first invalid character even if * - * FAIL is returned (meaning there is a syntax error in item key). * - * If necessary, the caller must keep a copy of pointer original * - * value. * - * * - ******************************************************************************/ -int parse_key(const char **exp) -{ - const char *s; - - for (s = *exp; SUCCEED == is_key_char(*s); s++) - ; - - if (*exp == s) /* the key is empty */ - return FAIL; - - if ('[' == *s) /* for instance, net.tcp.port[,80] */ - { - int state = 0; /* 0 - init, 1 - inside quoted param, 2 - inside unquoted param */ - int array = 0; /* array nest level */ - - for (s++; '\0' != *s; s++) - { - switch (state) - { - /* init state */ - case 0: - if (',' == *s) - ; - else if ('"' == *s) - state = 1; - else if ('[' == *s) - { - if (0 == array) - array = 1; - else - goto fail; /* incorrect syntax: multi-level array */ - } - else if (']' == *s && 0 != array) - { - array = 0; - s++; - - while (' ' == *s) /* skip trailing spaces after closing ']' */ - s++; - - if (']' == *s) - goto succeed; - - if (',' != *s) - goto fail; /* incorrect syntax */ - } - else if (']' == *s && 0 == array) - goto succeed; - else if (' ' != *s) - state = 2; - break; - /* quoted */ - case 1: - if ('"' == *s) - { - while (' ' == s[1]) /* skip trailing spaces after closing quotes */ - s++; - - if (0 == array && ']' == s[1]) - { - s++; - goto succeed; - } - - if (',' != s[1] && !(0 != array && ']' == s[1])) - { - s++; - goto fail; /* incorrect syntax */ - } - - state = 0; - } - else if ('\\' == *s && '"' == s[1]) - s++; - break; - /* unquoted */ - case 2: - if (',' == *s || (']' == *s && 0 != array)) - { - s--; - state = 0; - } - else if (']' == *s && 0 == array) - goto succeed; - break; - } - } -fail: - *exp = s; - return FAIL; -succeed: - s++; - } - - *exp = s; - return SUCCEED; -} - -/****************************************************************************** - * * - * Purpose: return hostname and key * - * <hostname:>key * - * * - * Parameters: * - * exp - pointer to the first char of hostname * - * host:key[key params] * - * ^ * - * * - * Return value: return SUCCEED or FAIL * - * * - ******************************************************************************/ -int parse_host_key(char *exp, char **host, char **key) -{ - char *p, *s; - - if (NULL == exp || '\0' == *exp) - return FAIL; - - for (p = exp, s = exp; '\0' != *p; p++) /* check for optional hostname */ - { - if (':' == *p) /* hostname:vfs.fs.size[/,total] - * --------^ - */ - { - *p = '\0'; - *host = zbx_strdup(NULL, s); - *p++ = ':'; - - s = p; - break; - } - - if (SUCCEED != is_hostname_char(*p)) - break; - } - - *key = zbx_strdup(NULL, s); - - return SUCCEED; -} - -/****************************************************************************** - * * - * Purpose: replace all not-allowed hostname characters in the string * - * * - * Parameters: host - the target C-style string * - * * - * Comments: the string must be null-terminated, otherwise not secure! * - * * - ******************************************************************************/ -void make_hostname(char *host) -{ - char *c; - - assert(host); - - for (c = host; '\0' != *c; ++c) - { - if (FAIL == is_hostname_char(*c)) - *c = '_'; - } -} - -/****************************************************************************** - * * - * Purpose: check a byte stream for a valid hostname * - * * - * Parameters: hostname - pointer to the first char of hostname * - * error - pointer to the error message (can be NULL) * - * * - * Return value: return SUCCEED if hostname is valid * - * or FAIL if hostname contains invalid chars, is empty * - * or is longer than ZBX_MAX_HOSTNAME_LEN * - * * - ******************************************************************************/ -int zbx_check_hostname(const char *hostname, char **error) -{ - int len = 0; - - while ('\0' != hostname[len]) - { - if (FAIL == is_hostname_char(hostname[len])) - { - if (NULL != error) - *error = zbx_dsprintf(NULL, "name contains invalid character '%c'", hostname[len]); - return FAIL; - } - - len++; - } - - if (0 == len) - { - if (NULL != error) - *error = zbx_strdup(NULL, "name is empty"); - return FAIL; - } - - if (ZBX_MAX_HOSTNAME_LEN < len) - { - if (NULL != error) - *error = zbx_dsprintf(NULL, "name is too long (max %d characters)", ZBX_MAX_HOSTNAME_LEN); - return FAIL; - } - - return SUCCEED; -} - -/****************************************************************************** - * * * Return value: Interface type * * * * Comments: !!! Don't forget to sync the code with PHP !!! * diff --git a/src/libs/zbxcrypto/crypto.c b/src/libs/zbxcrypto/crypto.c index 79557356458..5b19652bf2b 100644 --- a/src/libs/zbxcrypto/crypto.c +++ b/src/libs/zbxcrypto/crypto.c @@ -19,7 +19,6 @@ #include "zbxcrypto.h" -#include "zbxhash.h" #include "zbxtime.h" /****************************************************************************** @@ -112,7 +111,7 @@ int zbx_bin2hex(const unsigned char *bin, size_t bin_len, char *out, size_t o * Return value: Hexadecimal token string, must be freed by caller * * * * Comments: if you change token creation algorithm do not forget to adjust * - * zbx_get_token_len() function * + * ZBX_SESSION_TOKEN_SIZE macro * * * ******************************************************************************/ char *zbx_create_token(zbx_uint64_t seed) @@ -124,7 +123,7 @@ char *zbx_create_token(zbx_uint64_t seed) int i; char *token, *ptr; - ptr = token = (char *)zbx_malloc(NULL, zbx_get_token_len() + 1); + ptr = token = (char *)zbx_malloc(NULL, ZBX_SESSION_TOKEN_SIZE + 1); zbx_timespec(&ts); @@ -146,21 +145,6 @@ char *zbx_create_token(zbx_uint64_t seed) /****************************************************************************** * * - * Return value: number of characters in a token created by * - * zbx_create_token() * - * * - * Comments: terminating '\0' byte is not included in the result * - * * - ******************************************************************************/ -size_t zbx_get_token_len(void) -{ -#define ZBX_DATA_SESSION_TOKEN_SIZE (ZBX_MD5_DIGEST_SIZE * 2) - return ZBX_DATA_SESSION_TOKEN_SIZE; -#undef ZBX_DATA_SESSION_TOKEN_SIZE -} - -/****************************************************************************** - * * * Purpose: calculate UUID version 4 as string of 32 symbols * * * * Parameters: seed - [IN] string for seed calculation * diff --git a/src/libs/zbxcrypto/hmac.c b/src/libs/zbxcrypto/hmac.c index d3345b49c2d..3efe6af39af 100644 --- a/src/libs/zbxcrypto/hmac.c +++ b/src/libs/zbxcrypto/hmac.c @@ -19,7 +19,6 @@ #include "zbxcrypto.h" -#include "zbxhash.h" #include "zbxcommon.h" static void *hmac_hash_init(zbx_crypto_hash_t type) diff --git a/src/libs/zbxdb/db.c b/src/libs/zbxdb/db.c index 7915e32d6e4..42db53433c2 100644 --- a/src/libs/zbxdb/db.c +++ b/src/libs/zbxdb/db.c @@ -2744,7 +2744,7 @@ void zbx_dbms_version_info_extract(struct zbx_db_version_info_t *version_info) zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); ZBX_PG_SVERSION = (zbx_uint32_t)PQserverVersion(conn); - major = (zbx_uint32_t)RIGHT2(ZBX_PG_SVERSION/10000); + major = ZBX_PG_SVERSION/10000; version_info->database = "PostgreSQL"; @@ -2755,12 +2755,12 @@ void zbx_dbms_version_info_extract(struct zbx_db_version_info_t *version_info) if (10 > major) { - version_info->friendly_current_version = zbx_dsprintf(NULL, "%u.%d.%d", (unsigned int)major, + version_info->friendly_current_version = zbx_dsprintf(NULL, "%" PRIu32 ".%d.%d", major, RIGHT2(ZBX_PG_SVERSION/100), RIGHT2(ZBX_PG_SVERSION)); } else { - version_info->friendly_current_version = zbx_dsprintf(NULL, "%u.%d", (unsigned int)major, + version_info->friendly_current_version = zbx_dsprintf(NULL, "%" PRIu32 ".%d", major, RIGHT2(ZBX_PG_SVERSION)); } diff --git a/src/libs/zbxdbcache/dbconfig.c b/src/libs/zbxdbcache/dbconfig.c index 13f21a4d3b4..4bfdb8a6c65 100644 --- a/src/libs/zbxdbcache/dbconfig.c +++ b/src/libs/zbxdbcache/dbconfig.c @@ -76,8 +76,11 @@ int sync_in_progress = 0; in_maintenance_without_data_collection(dc_host->maintenance_status, \ dc_host->maintenance_type, dc_item->type) -ZBX_PTR_VECTOR_IMPL(cached_proxy, zbx_cached_proxy_t *) +ZBX_PTR_VECTOR_IMPL(cached_proxy_ptr, zbx_cached_proxy_t *) +ZBX_PTR_VECTOR_IMPL(dc_httptest_ptr, zbx_dc_httptest_t *) +ZBX_PTR_VECTOR_IMPL(dc_host_ptr, ZBX_DC_HOST *) ZBX_PTR_VECTOR_IMPL(dc_item_ptr, ZBX_DC_ITEM *) +ZBX_VECTOR_IMPL(host_rev, zbx_host_rev_t) /****************************************************************************** * * @@ -108,8 +111,10 @@ static void dc_item_reset_triggers(ZBX_DC_ITEM *item, ZBX_DC_TRIGGER *trigger_ex static char *dc_expand_user_macros_dyn(const char *text, const zbx_uint64_t *hostids, int hostids_num, int env); static void dc_reschedule_items(const zbx_hashset_t *activated_hosts); +static void dc_reschedule_httptests(zbx_hashset_t *activated_hosts); -static int dc_host_update_revision(ZBX_DC_HOST *host, zbx_uint32_t revision); +static int dc_host_update_revision(ZBX_DC_HOST *host, zbx_uint64_t revision); +static int dc_item_update_revision(ZBX_DC_ITEM *item, zbx_uint64_t revision); extern char *CONFIG_VAULTTOKEN; extern char *CONFIG_VAULT; @@ -156,6 +161,7 @@ static zbx_dc_um_handle_t *dc_um_handle = NULL; * | Zabbix internal | zabbix[host,,items_unsupported] | * * | Zabbix internal | zabbix[host,discovery,interfaces] | * * | Zabbix internal | zabbix[host,,maintenance] | * + * | Zabbix internal | zabbix[proxy,discovery] | * * | Zabbix internal | zabbix[proxy,<proxyname>,lastaccess] | * * | Zabbix internal | zabbix[proxy,<proxyname>,delay] | * * | Zabbix aggregate | * | * @@ -179,13 +185,25 @@ int is_item_processed_by_server(unsigned char type, const char *key) AGENT_REQUEST request; char *arg1, *arg2, *arg3; - init_request(&request); + zbx_init_agent_request(&request); - if (SUCCEED != parse_item_key(key, &request) || 3 != request.nparam) + if (SUCCEED != zbx_parse_item_key(key, &request) || 2 > request.nparam || + 3 < request.nparam) + { goto clean; + } arg1 = get_rparam(&request, 0); arg2 = get_rparam(&request, 1); + + if (2 == request.nparam) + { + if (0 == strcmp(arg1, "proxy") && 0 == strcmp(arg2, "discovery")) + ret = SUCCEED; + + goto clean; + } + arg3 = get_rparam(&request, 2); if (0 == strcmp(arg1, "host")) @@ -201,11 +219,13 @@ int is_item_processed_by_server(unsigned char type, const char *key) else if (0 == strcmp(arg2, "discovery") && 0 == strcmp(arg3, "interfaces")) ret = SUCCEED; } - else if (0 == strcmp(arg1, "proxy") && - (0 == strcmp(arg3, "lastaccess") || 0 == strcmp(arg3, "delay"))) + else if (0 == strcmp(arg1, "proxy") && (0 == strcmp(arg3, "lastaccess") || + 0 == strcmp(arg3, "delay"))) + { ret = SUCCEED; + } clean: - free_request(&request); + zbx_free_agent_request(&request); } break; } @@ -228,9 +248,9 @@ static unsigned char poller_by_item(unsigned char type, const char *key) switch (type) { case ITEM_TYPE_SIMPLE: - if (SUCCEED == cmp_key_id(key, SERVER_ICMPPING_KEY) || - SUCCEED == cmp_key_id(key, SERVER_ICMPPINGSEC_KEY) || - SUCCEED == cmp_key_id(key, SERVER_ICMPPINGLOSS_KEY)) + if (SUCCEED == cmp_key_id(key, ZBX_SERVER_ICMPPING_KEY) || + SUCCEED == cmp_key_id(key, ZBX_SERVER_ICMPPINGSEC_KEY) || + SUCCEED == cmp_key_id(key, ZBX_SERVER_ICMPPINGLOSS_KEY)) { if (0 == CONFIG_PINGER_FORKS) break; @@ -338,9 +358,9 @@ static zbx_uint64_t get_item_nextcheck_seed(zbx_uint64_t itemid, zbx_uint64_t in if (ITEM_TYPE_SIMPLE == type) { - if (SUCCEED == cmp_key_id(key, SERVER_ICMPPING_KEY) || - SUCCEED == cmp_key_id(key, SERVER_ICMPPINGSEC_KEY) || - SUCCEED == cmp_key_id(key, SERVER_ICMPPINGLOSS_KEY)) + if (SUCCEED == cmp_key_id(key, ZBX_SERVER_ICMPPING_KEY) || + SUCCEED == cmp_key_id(key, ZBX_SERVER_ICMPPINGSEC_KEY) || + SUCCEED == cmp_key_id(key, ZBX_SERVER_ICMPPINGLOSS_KEY)) { return interfaceid; } @@ -569,12 +589,12 @@ static ZBX_DC_HOST *DCfind_proxy(const char *host) static zbx_hash_t __config_strpool_hash(const void *data) { - return ZBX_DEFAULT_STRING_HASH_FUNC((char *)data + REFCOUNT_FIELD_SIZE); + return ZBX_DEFAULT_STRING_HASH_FUNC((const char *)data + REFCOUNT_FIELD_SIZE); } static int __config_strpool_compare(const void *d1, const void *d2) { - return strcmp((char *)d1 + REFCOUNT_FIELD_SIZE, (char *)d2 + REFCOUNT_FIELD_SIZE); + return strcmp((const char *)d1 + REFCOUNT_FIELD_SIZE, (const char *)d2 + REFCOUNT_FIELD_SIZE); } const char *dc_strpool_intern(const char *str) @@ -703,21 +723,29 @@ static void DCupdate_proxy_queue(ZBX_DC_PROXY *proxy) * value_raw - [IN] setting value to validate * * * ******************************************************************************/ -static int set_hk_opt(int *value, int non_zero, int value_min, const char *value_raw) +static int set_hk_opt(int *value, int non_zero, int value_min, const char *value_raw, zbx_uint64_t revision) { - if (SUCCEED != zbx_is_time_suffix(value_raw, value, ZBX_LENGTH_UNLIMITED)) + int value_int; + + if (SUCCEED != zbx_is_time_suffix(value_raw, &value_int, ZBX_LENGTH_UNLIMITED)) return FAIL; - if (0 != non_zero && 0 == *value) + if (0 != non_zero && 0 == value_int) return FAIL; - if (0 != *value && (value_min > *value || ZBX_HK_PERIOD_MAX < *value)) + if (0 != *value && (value_min > value_int || ZBX_HK_PERIOD_MAX < value_int)) return FAIL; + if (*value != value_int) + { + *value = value_int; + config->revision.config_table = revision; + } + return SUCCEED; } -static int DCsync_config(zbx_dbsync_t *sync, int *flags) +static int DCsync_config(zbx_dbsync_t *sync, zbx_uint64_t revision, int *flags) { const ZBX_TABLE *config_table; @@ -735,9 +763,10 @@ static int DCsync_config(zbx_dbsync_t *sync, int *flags) const char *row[ARRSIZE(selected_fields)]; size_t i; - int j, found = 1, ret; + int j, found = 1, ret, value_int; + unsigned char value_uchar; char **db_row; - zbx_uint64_t rowid; + zbx_uint64_t rowid, value_uint64; unsigned char tag; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); @@ -748,6 +777,7 @@ static int DCsync_config(zbx_dbsync_t *sync, int *flags) { found = 0; config->config = (ZBX_DC_CONFIG_TABLE *)__config_shmem_malloc_func(NULL, sizeof(ZBX_DC_CONFIG_TABLE)); + memset(config->config, 0, sizeof(ZBX_DC_CONFIG_TABLE)); } if (SUCCEED != (ret = zbx_dbsync_next(sync, &rowid, &db_row, &tag))) @@ -771,24 +801,69 @@ static int DCsync_config(zbx_dbsync_t *sync, int *flags) /* store the config data */ if (NULL != row[0]) - ZBX_STR2UINT64(config->config->discovery_groupid, row[0]); + ZBX_STR2UINT64(value_uint64, row[0]); else - config->config->discovery_groupid = ZBX_DISCOVERY_GROUPID_UNDEFINED; + value_uint64 = ZBX_DISCOVERY_GROUPID_UNDEFINED; - ZBX_STR2UCHAR(config->config->snmptrap_logging, row[1]); - config->config->default_inventory_mode = atoi(row[25]); - dc_strpool_replace(found, (const char **)&config->config->db.extension, row[26]); - ZBX_STR2UCHAR(config->config->autoreg_tls_accept, row[27]); - ZBX_STR2UCHAR(config->config->db.history_compression_status, row[28]); + if (config->config->discovery_groupid != value_uint64) + { + config->config->discovery_groupid = value_uint64; + config->revision.config_table = revision; + } - if (SUCCEED != zbx_is_time_suffix(row[29], &config->config->db.history_compress_older, ZBX_LENGTH_UNLIMITED)) + ZBX_STR2UCHAR(value_uchar, row[1]); + if (config->config->snmptrap_logging != value_uchar) + { + config->config->snmptrap_logging = value_uchar; + config->revision.config_table = revision; + } + + if (config->config->default_inventory_mode != (value_int = atoi(row[25]))) + { + config->config->default_inventory_mode = value_int; + config->revision.config_table = revision; + } + + if (NULL == config->config->db.extension || 0 != strcmp(config->config->db.extension, row[26])) + { + dc_strpool_replace(found, (const char **)&config->config->db.extension, row[26]); + config->revision.config_table = revision; + } + + ZBX_STR2UCHAR(value_uchar, row[27]); + if (config->config->autoreg_tls_accept != value_uchar) + { + config->config->autoreg_tls_accept = value_uchar; + config->revision.config_table = revision; + } + + ZBX_STR2UCHAR(value_uchar, row[28]); + if (config->config->db.history_compression_status != value_uchar) + { + config->config->db.history_compression_status = value_uchar; + config->revision.config_table = revision; + } + + if (SUCCEED != zbx_is_time_suffix(row[29], &value_int, ZBX_LENGTH_UNLIMITED)) { zabbix_log(LOG_LEVEL_WARNING, "invalid history compression age: %s", row[29]); - config->config->db.history_compress_older = 0; + value_int = 0; + } + + if (config->config->db.history_compress_older != value_int) + { + config->config->db.history_compress_older = value_int; + config->revision.config_table = revision; } for (j = 0; TRIGGER_SEVERITY_COUNT > j; j++) - dc_strpool_replace(found, &config->config->severity_name[j], row[2 + j]); + { + if (NULL == config->config->severity_name[j] || 0 != strcmp(config->config->severity_name[j], row[2 + j])) + { + dc_strpool_replace(found, (const char **)&config->config->severity_name[j], row[2 + j]); + config->revision.config_table = revision; + } + } /* instance id cannot be changed - update it only at first sync to avoid read locks later */ if (0 == found) @@ -799,51 +874,89 @@ static int DCsync_config(zbx_dbsync_t *sync, int *flags) #endif /* read housekeeper configuration */ - - if (ZBX_HK_OPTION_ENABLED == (config->config->hk.events_mode = atoi(row[8])) && - (SUCCEED != set_hk_opt(&config->config->hk.events_trigger, 1, SEC_PER_DAY, row[9]) || - SUCCEED != set_hk_opt(&config->config->hk.events_internal, 1, SEC_PER_DAY, row[10]) || - SUCCEED != set_hk_opt(&config->config->hk.events_discovery, 1, SEC_PER_DAY, row[11]) || - SUCCEED != set_hk_opt(&config->config->hk.events_autoreg, 1, SEC_PER_DAY, row[12]) || - SUCCEED != set_hk_opt(&config->config->hk.events_service, 1, SEC_PER_DAY, row[32]))) + if (ZBX_HK_OPTION_ENABLED == (value_int = atoi(row[8])) && + (SUCCEED != set_hk_opt(&config->config->hk.events_trigger, 1, SEC_PER_DAY, row[9], revision) || + SUCCEED != set_hk_opt(&config->config->hk.events_internal, 1, SEC_PER_DAY, row[10], revision) || + SUCCEED != set_hk_opt(&config->config->hk.events_discovery, 1, SEC_PER_DAY, row[11], revision) || + SUCCEED != set_hk_opt(&config->config->hk.events_autoreg, 1, SEC_PER_DAY, row[12], revision) || + SUCCEED != set_hk_opt(&config->config->hk.events_service, 1, SEC_PER_DAY, row[32], revision))) { zabbix_log(LOG_LEVEL_WARNING, "trigger, internal, network discovery and auto-registration data" " housekeeping will be disabled due to invalid settings"); - config->config->hk.events_mode = ZBX_HK_OPTION_DISABLED; + value_int = ZBX_HK_OPTION_DISABLED; + } + if (config->config->hk.events_mode != value_int) + { + config->config->hk.events_mode = value_int; + config->revision.config_table = revision; } - if (ZBX_HK_OPTION_ENABLED == (config->config->hk.services_mode = atoi(row[13])) && - SUCCEED != set_hk_opt(&config->config->hk.services, 1, SEC_PER_DAY, row[14])) + if (ZBX_HK_OPTION_ENABLED == (value_int = atoi(row[13])) && + SUCCEED != set_hk_opt(&config->config->hk.services, 1, SEC_PER_DAY, row[14], revision)) { zabbix_log(LOG_LEVEL_WARNING, "IT services data housekeeping will be disabled due to invalid" " settings"); - config->config->hk.services_mode = ZBX_HK_OPTION_DISABLED; + value_int = ZBX_HK_OPTION_DISABLED; + } + if (config->config->hk.services_mode != value_int) + { + config->config->hk.services_mode = value_int; + config->revision.config_table = revision; } - if (ZBX_HK_OPTION_ENABLED == (config->config->hk.audit_mode = atoi(row[15])) && - SUCCEED != set_hk_opt(&config->config->hk.audit, 1, SEC_PER_DAY, row[16])) + if (ZBX_HK_OPTION_ENABLED == (value_int = atoi(row[15])) && + SUCCEED != set_hk_opt(&config->config->hk.audit, 1, SEC_PER_DAY, row[16], revision)) { zabbix_log(LOG_LEVEL_WARNING, "audit data housekeeping will be disabled due to invalid" " settings"); - config->config->hk.audit_mode = ZBX_HK_OPTION_DISABLED; + value_int = ZBX_HK_OPTION_DISABLED; + } + if (config->config->hk.audit_mode != value_int) + { + config->config->hk.audit_mode = value_int; + config->revision.config_table = revision; } - if (ZBX_HK_OPTION_ENABLED == (config->config->hk.sessions_mode = atoi(row[17])) && - SUCCEED != set_hk_opt(&config->config->hk.sessions, 1, SEC_PER_DAY, row[18])) + if (ZBX_HK_OPTION_ENABLED == (value_int = atoi(row[17])) && + SUCCEED != set_hk_opt(&config->config->hk.sessions, 1, SEC_PER_DAY, row[18], revision)) { zabbix_log(LOG_LEVEL_WARNING, "user sessions data housekeeping will be disabled due to invalid" " settings"); - config->config->hk.sessions_mode = ZBX_HK_OPTION_DISABLED; + value_int = ZBX_HK_OPTION_DISABLED; + } + if (config->config->hk.sessions_mode != value_int) + { + config->config->hk.sessions_mode = value_int; + config->revision.config_table = revision; } - config->config->hk.history_mode = atoi(row[19]); - if (ZBX_HK_OPTION_ENABLED == (config->config->hk.history_global = atoi(row[20])) && - SUCCEED != set_hk_opt(&config->config->hk.history, 0, ZBX_HK_HISTORY_MIN, row[21])) + if (config->config->hk.history_mode != (value_int = atoi(row[19]))) + { + config->config->hk.history_mode = value_int; + config->revision.config_table = revision; + } + + if (ZBX_HK_OPTION_ENABLED == (value_int = atoi(row[20])) && + SUCCEED != set_hk_opt(&config->config->hk.history, 0, ZBX_HK_HISTORY_MIN, row[21], revision)) { zabbix_log(LOG_LEVEL_WARNING, "history data housekeeping will be disabled and all items will" " store their history due to invalid global override settings"); - config->config->hk.history_mode = ZBX_HK_MODE_DISABLED; - config->config->hk.history = 1; /* just enough to make 0 == items[i].history condition fail */ + if (ZBX_HK_MODE_DISABLED != config->config->hk.history_mode) + { + config->config->hk.history_mode = ZBX_HK_MODE_DISABLED; + config->revision.config_table = revision; + } + + if (1 != config->config->hk.history) + { + config->config->hk.history = 1; /* just enough to make 0 == items[i].history condition fail */ + config->revision.config_table = revision; + } + } + if (config->config->hk.history_global != value_int) + { + config->config->hk.history_global = value_int; + config->revision.config_table = revision; } #ifdef HAVE_POSTGRESQL @@ -851,18 +964,40 @@ static int DCsync_config(zbx_dbsync_t *sync, int *flags) ZBX_HK_OPTION_ENABLED == config->config->hk.history_global && 0 == zbx_strcmp_null(config->config->db.extension, ZBX_DB_EXTENSION_TIMESCALEDB)) { - config->config->hk.history_mode = ZBX_HK_MODE_PARTITION; + if (ZBX_HK_MODE_PARTITION != config->config->hk.history_mode) + { + config->config->hk.history_mode = ZBX_HK_MODE_PARTITION; + config->revision.config_table = revision; + } } #endif - config->config->hk.trends_mode = atoi(row[22]); - if (ZBX_HK_OPTION_ENABLED == (config->config->hk.trends_global = atoi(row[23])) && - SUCCEED != set_hk_opt(&config->config->hk.trends, 0, ZBX_HK_TRENDS_MIN, row[24])) + if (config->config->hk.trends_mode != (value_int = atoi(row[22]))) + { + config->config->hk.trends_mode = value_int; + config->revision.config_table = revision; + } + + if (ZBX_HK_OPTION_ENABLED == (value_int = atoi(row[23])) && + SUCCEED != set_hk_opt(&config->config->hk.trends, 0, ZBX_HK_TRENDS_MIN, row[24], revision)) { zabbix_log(LOG_LEVEL_WARNING, "trends data housekeeping will be disabled and all numeric items" " will store their history due to invalid global override settings"); - config->config->hk.trends_mode = ZBX_HK_MODE_DISABLED; - config->config->hk.trends = 1; /* just enough to make 0 == items[i].trends condition fail */ + if (ZBX_HK_MODE_DISABLED != config->config->hk.trends_mode) + { + config->config->hk.trends_mode = ZBX_HK_MODE_DISABLED; + config->revision.config_table = revision; + } + if (1 != config->config->hk.trends) + { + config->config->hk.trends = 1; /* just enough to make 0 == items[i].trends condition fail */ + config->revision.config_table = revision; + } + } + if (config->config->hk.trends_global != value_int) + { + config->config->hk.trends_global = value_int; + config->revision.config_table = revision; } #ifdef HAVE_POSTGRESQL @@ -870,12 +1005,25 @@ static int DCsync_config(zbx_dbsync_t *sync, int *flags) ZBX_HK_OPTION_ENABLED == config->config->hk.trends_global && 0 == zbx_strcmp_null(config->config->db.extension, ZBX_DB_EXTENSION_TIMESCALEDB)) { - config->config->hk.trends_mode = ZBX_HK_MODE_PARTITION; + if (ZBX_HK_MODE_PARTITION != config->config->hk.trends_mode) + { + config->config->hk.trends_mode = ZBX_HK_MODE_PARTITION; + config->revision.config_table = revision; + } } #endif - dc_strpool_replace(found, &config->config->default_timezone, row[31]); - config->config->auditlog_enabled = atoi(row[33]); + if (NULL == config->config->default_timezone || 0 != strcmp(config->config->default_timezone, row[31])) + { + dc_strpool_replace(found, (const char **)&config->config->default_timezone, row[31]); + config->revision.config_table = revision; + } + + if (config->config->auditlog_enabled != (value_int = atoi(row[33]))) + { + config->config->auditlog_enabled = value_int; + config->revision.config_table = revision; + } if (SUCCEED == ret && SUCCEED == zbx_dbsync_next(sync, &rowid, &db_row, &tag)) /* table must have */ zabbix_log(LOG_LEVEL_ERR, "table 'config' has multiple records"); /* only one record */ @@ -908,7 +1056,7 @@ static time_t calculate_proxy_nextcheck(zbx_uint64_t hostid, unsigned int delay, return nextcheck; } -static void DCsync_autoreg_config(zbx_dbsync_t *sync) +static void DCsync_autoreg_config(zbx_dbsync_t *sync, zbx_uint64_t revision) { /* sync this function with zbx_dbsync_compare_autoreg_psk() */ char **db_row; @@ -934,6 +1082,8 @@ static void DCsync_autoreg_config(zbx_dbsync_t *sync) default: THIS_SHOULD_NEVER_HAPPEN; } + + config->revision.autoreg_tls = revision; } zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); @@ -987,38 +1137,78 @@ static void DCsync_proxy_remove(ZBX_DC_PROXY *proxy) } dc_strpool_release(proxy->proxy_address); + dc_strpool_release(proxy->version_str); + + zbx_vector_dc_host_ptr_destroy(&proxy->hosts); + zbx_vector_host_rev_destroy(&proxy->removed_hosts); + zbx_hashset_remove_direct(&config->proxies, proxy); } -static void DCsync_hosts(zbx_dbsync_t *sync, zbx_uint32_t revision, zbx_vector_uint64_t *active_avail_diff, - zbx_hashset_t *activated_hosts) +static void dc_host_deregister_proxy(ZBX_DC_HOST *host, zbx_uint64_t proxy_hostid, zbx_uint64_t revision) { - char **row; - zbx_uint64_t rowid; - unsigned char tag; + ZBX_DC_PROXY *proxy; + int i; + zbx_host_rev_t rev; - ZBX_DC_HOST *host; - ZBX_DC_IPMIHOST *ipmihost; + if (NULL == (proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &proxy_hostid))) + return; + + rev.hostid = host->hostid; + rev.revision = revision; + zbx_vector_host_rev_append(&proxy->removed_hosts, rev); + + if (FAIL == (i = zbx_vector_dc_host_ptr_search(&proxy->hosts, host, ZBX_DEFAULT_PTR_COMPARE_FUNC))) + return; + + zbx_vector_dc_host_ptr_remove_noorder(&proxy->hosts, i); + proxy->revision = revision; +} + +static void dc_host_register_proxy(ZBX_DC_HOST *host, zbx_uint64_t proxy_hostid, zbx_uint64_t revision) +{ ZBX_DC_PROXY *proxy; - ZBX_DC_HOST_H *host_h, host_h_local, *host_p, host_p_local; - int found; - int update_index_h, update_index_p, ret; - zbx_uint64_t hostid, proxy_hostid; - unsigned char status; - time_t now; - signed char ipmi_authtype; - unsigned char ipmi_privilege; + if (NULL == (proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &proxy_hostid))) + return; + + zbx_vector_dc_host_ptr_append(&proxy->hosts, host); + proxy->revision = revision; +} + + +static void DCsync_hosts(zbx_dbsync_t *sync, zbx_uint64_t revision, zbx_vector_uint64_t *active_avail_diff, + zbx_hashset_t *activated_hosts) +{ + char **row; + zbx_uint64_t rowid; + unsigned char tag; + + ZBX_DC_HOST *host; + ZBX_DC_IPMIHOST *ipmihost; + ZBX_DC_PROXY *proxy; + ZBX_DC_HOST_H *host_h, host_h_local, *host_p, host_p_local; + + int i, found; + int update_index_h, update_index_p, ret; + zbx_uint64_t hostid, proxy_hostid; + unsigned char status; + time_t now; + signed char ipmi_authtype; + unsigned char ipmi_privilege; + zbx_vector_dc_host_ptr_t proxy_hosts; #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) - ZBX_DC_PSK *psk_i, psk_i_local; - zbx_ptr_pair_t *psk_owner, psk_owner_local; - zbx_hashset_t psk_owners; + ZBX_DC_PSK *psk_i, psk_i_local; + zbx_ptr_pair_t *psk_owner, psk_owner_local; + zbx_hashset_t psk_owners; #endif zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) zbx_hashset_create(&psk_owners, 0, ZBX_DEFAULT_PTR_HASH_FUNC, ZBX_DEFAULT_PTR_COMPARE_FUNC); #endif + zbx_vector_dc_host_ptr_create(&proxy_hosts); + now = time(NULL); while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag))) @@ -1305,11 +1495,13 @@ done: host->maintenance_type = (unsigned char)atoi(row[8]); host->maintenance_from = atoi(row[9]); host->data_expected_from = now; - host->update_items = 0; zbx_vector_ptr_create_ext(&host->interfaces_v, __config_shmem_malloc_func, __config_shmem_realloc_func, __config_shmem_free_func); - zbx_vector_dc_item_ptr_create_ext(&host->active_items, __config_shmem_malloc_func, + + zbx_vector_dc_httptest_ptr_create_ext(&host->httptests, __config_shmem_malloc_func, + __config_shmem_realloc_func, __config_shmem_free_func); + zbx_vector_dc_item_ptr_create_ext(&host->items, __config_shmem_malloc_func, __config_shmem_realloc_func, __config_shmem_free_func); } else @@ -1337,7 +1529,6 @@ done: if (0 != reset_availability) { - int i; ZBX_DC_INTERFACE *interface; for (i = 0; i < host->interfaces_v.values_num; i++) @@ -1356,6 +1547,30 @@ done: } } + if (HOST_STATUS_MONITORED == status || HOST_STATUS_NOT_MONITORED == status) + { + if (0 != found && 0 != host->proxy_hostid && host->proxy_hostid != proxy_hostid) + { + dc_host_deregister_proxy(host, host->proxy_hostid, revision); + } + + if (0 != proxy_hostid) + { + if (0 == found || host->proxy_hostid != proxy_hostid) + { + zbx_vector_dc_host_ptr_append(&proxy_hosts, host); + } + else + { + if (NULL != (proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, + &proxy_hostid))) + { + proxy->revision = revision; + } + } + } + } + host->proxy_hostid = proxy_hostid; /* update 'hosts_h' and 'hosts_p' indexes using new data, if not done already */ @@ -1409,13 +1624,22 @@ done: if (0 == found) { proxy->location = ZBX_LOC_NOWHERE; - proxy->version = 0; + proxy->revision = revision; + + proxy->version_int = ZBX_COMPONENT_VERSION_UNDEFINED; + proxy->version_str = dc_strpool_intern(ZBX_VERSION_UNDEFINED_STR); + proxy->compatibility = ZBX_PROXY_VERSION_UNDEFINED; proxy->lastaccess = atoi(row[12]); proxy->last_cfg_error_time = 0; proxy->proxy_delay = 0; proxy->nodata_win.flags = ZBX_PROXY_SUPPRESS_DISABLE; proxy->nodata_win.values_num = 0; proxy->nodata_win.period_end = 0; + + zbx_vector_dc_host_ptr_create_ext(&proxy->hosts, __config_shmem_malloc_func, + __config_shmem_realloc_func, __config_shmem_free_func); + zbx_vector_host_rev_create_ext(&proxy->removed_hosts, __config_shmem_malloc_func, + __config_shmem_realloc_func, __config_shmem_free_func); } proxy->auto_compress = atoi(row[16 + ZBX_HOST_TLS_OFFSET]); @@ -1445,6 +1669,9 @@ done: host->status = status; } + for (i = 0; i < proxy_hosts.values_num; i++) + dc_host_register_proxy(proxy_hosts.values[i], proxy_hosts.values[i]->proxy_hostid, revision); + /* remove deleted hosts from buffer */ for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag)) { @@ -1482,6 +1709,9 @@ done: } zbx_vector_uint64_append(active_avail_diff, host->hostid); + + if (0 != host->proxy_hostid) + dc_host_deregister_proxy(host, host->proxy_hostid, revision); } else if (HOST_STATUS_PROXY_ACTIVE == host->status || HOST_STATUS_PROXY_PASSIVE == host->status) { @@ -1517,24 +1747,28 @@ done: } #endif zbx_vector_ptr_destroy(&host->interfaces_v); - zbx_vector_dc_item_ptr_destroy(&host->active_items); + zbx_vector_dc_item_ptr_destroy(&host->items); zbx_hashset_remove_direct(&config->hosts, host); + + zbx_vector_dc_httptest_ptr_destroy(&host->httptests); } #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) zbx_hashset_destroy(&psk_owners); #endif + zbx_vector_dc_host_ptr_destroy(&proxy_hosts); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); } -static void DCsync_host_inventory(zbx_dbsync_t *sync) +static void DCsync_host_inventory(zbx_dbsync_t *sync, zbx_uint64_t revision) { ZBX_DC_HOST_INVENTORY *host_inventory, *host_inventory_auto; zbx_uint64_t rowid, hostid; int found, ret, i; char **row; unsigned char tag; + ZBX_DC_HOST *dc_host; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); @@ -1576,6 +1810,9 @@ static void DCsync_host_inventory(zbx_dbsync_t *sync) for (i = 0; i < HOST_INVENTORY_FIELD_COUNT; i++) host_inventory_auto->values[i] = NULL; } + + if (NULL != (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &hostid))) + dc_host_update_revision(dc_host, revision); } /* remove deleted host inventory from cache */ @@ -1587,6 +1824,9 @@ static void DCsync_host_inventory(zbx_dbsync_t *sync) continue; } + if (NULL != (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &host_inventory->hostid))) + dc_host_update_revision(dc_host, revision); + for (i = 0; i < HOST_INVENTORY_FIELD_COUNT; i++) dc_strpool_release(host_inventory->values[i]); @@ -1674,7 +1914,7 @@ void DCsync_kvs_paths(const struct zbx_json_parse *jp_kvs_paths) { START_SYNC; - config->revision++; + config->revision.config++; for (j = 0; j < diff.values_num; j++) { @@ -1693,8 +1933,8 @@ void DCsync_kvs_paths(const struct zbx_json_parse *jp_kvs_paths) dc_kv->value = NULL; } - config->um_cache = um_cache_set_value_to_macros(config->um_cache, config->revision, - &dc_kv->macros, dc_kv->value); + config->um_cache = um_cache_set_value_to_macros(config->um_cache, + config->revision.config, &dc_kv->macros, dc_kv->value); dc_kv->update = 0; } @@ -1862,7 +2102,7 @@ static void dc_interface_snmp_remove(zbx_uint64_t interfaceid) return; } -static void DCsync_interfaces(zbx_dbsync_t *sync, zbx_uint32_t revision) +static void DCsync_interfaces(zbx_dbsync_t *sync, zbx_uint64_t revision) { char **row; zbx_uint64_t rowid; @@ -2150,6 +2390,12 @@ static void dc_interface_snmpitems_remove(ZBX_DC_ITEM *item) } } +static void dc_masteritem_free(ZBX_DC_MASTERITEM *masteritem) +{ + zbx_vector_uint64_pair_destroy(&masteritem->dep_itemids); + __config_shmem_free_func(masteritem); +} + /****************************************************************************** * * * Purpose: remove itemid from master item dependent itemid vector * @@ -2161,10 +2407,14 @@ static void dc_interface_snmpitems_remove(ZBX_DC_ITEM *item) static void dc_masteritem_remove_depitem(zbx_uint64_t master_itemid, zbx_uint64_t dep_itemid) { ZBX_DC_MASTERITEM *masteritem; + ZBX_DC_ITEM *item; int index; zbx_uint64_pair_t pair; - if (NULL == (masteritem = (ZBX_DC_MASTERITEM *)zbx_hashset_search(&config->masteritems, &master_itemid))) + if (NULL == (item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &master_itemid))) + return; + + if (NULL == (masteritem = item->master_item)) return; pair.first = dep_itemid; @@ -2178,8 +2428,8 @@ static void dc_masteritem_remove_depitem(zbx_uint64_t master_itemid, zbx_uint64_ if (0 == masteritem->dep_itemids.values_num) { - zbx_vector_uint64_pair_destroy(&masteritem->dep_itemids); - zbx_hashset_remove_direct(&config->masteritems, masteritem); + dc_masteritem_free(item->master_item); + item->master_item = NULL; } } @@ -2234,7 +2484,14 @@ static unsigned char *config_decode_serialized_expression(const char *src) return dst; } -static void DCsync_items(zbx_dbsync_t *sync, zbx_uint32_t revision, int flags, zbx_synced_new_config_t synced) +static void dc_preprocitem_free(ZBX_DC_PREPROCITEM *preprocitem) +{ + zbx_vector_ptr_destroy(&preprocitem->preproc_ops); + __config_shmem_free_func(preprocitem); +} + +static void DCsync_items(zbx_dbsync_t *sync, zbx_uint64_t revision, int flags, zbx_synced_new_config_t synced, + zbx_vector_uint64_t *deleted_itemids) { char **row; zbx_uint64_t rowid; @@ -2256,8 +2513,6 @@ static void DCsync_items(zbx_dbsync_t *sync, zbx_uint32_t revision, int flags, z ZBX_DC_JMXITEM *jmxitem; ZBX_DC_CALCITEM *calcitem; ZBX_DC_INTERFACE_ITEM *interface_snmpitem; - ZBX_DC_MASTERITEM *master; - ZBX_DC_PREPROCITEM *preprocitem; ZBX_DC_HTTPITEM *httpitem; ZBX_DC_SCRIPTITEM *scriptitem; ZBX_DC_ITEM_HK *item_hk, item_hk_local; @@ -2332,24 +2587,6 @@ static void DCsync_items(zbx_dbsync_t *sync, zbx_uint32_t revision, int flags, z update_index = 1; } - if (0 == found || item->type != type) - { - if (1 == found) - { - if (ITEM_TYPE_ZABBIX_ACTIVE == item->type) - { - if (FAIL != (i = zbx_vector_dc_item_ptr_search(&host->active_items, item, - ZBX_DEFAULT_PTR_COMPARE_FUNC))) - { - zbx_vector_dc_item_ptr_remove(&host->active_items, i); - } - } - } - - if (ITEM_TYPE_ZABBIX_ACTIVE == type) - zbx_vector_dc_item_ptr_append(&host->active_items, item); - } - /* store new information in item structure */ item->hostid = hostid; @@ -2389,6 +2626,11 @@ static void DCsync_items(zbx_dbsync_t *sync, zbx_uint32_t revision, int flags, z zbx_vector_ptr_create_ext(&item->tags, __config_shmem_malloc_func, __config_shmem_realloc_func, __config_shmem_free_func); + + zbx_vector_dc_item_ptr_append(&host->items, item); + + item->preproc_item = NULL; + item->master_item = NULL; } else { @@ -2842,31 +3084,36 @@ static void DCsync_items(zbx_dbsync_t *sync, zbx_uint32_t revision, int flags, z depitem = (ZBX_DC_DEPENDENTITEM *)dep_items.values[i]; dc_masteritem_remove_depitem(depitem->last_master_itemid, depitem->itemid); + + if (NULL == (item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &depitem->master_itemid))) + continue; + pair.first = depitem->itemid; pair.second = depitem->flags; - /* append item to dependent item vector of master item */ - if (NULL == (master = (ZBX_DC_MASTERITEM *)zbx_hashset_search(&config->masteritems, - &depitem->master_itemid))) + if (NULL == item->master_item) { - ZBX_DC_MASTERITEM master_local; + item->master_item = (ZBX_DC_MASTERITEM *)__config_shmem_malloc_func(NULL, + sizeof(ZBX_DC_MASTERITEM)); - master_local.itemid = depitem->master_itemid; - master = (ZBX_DC_MASTERITEM *)zbx_hashset_insert(&config->masteritems, &master_local, - sizeof(master_local)); - - zbx_vector_uint64_pair_create_ext(&master->dep_itemids, __config_shmem_malloc_func, + zbx_vector_uint64_pair_create_ext(&item->master_item->dep_itemids, __config_shmem_malloc_func, __config_shmem_realloc_func, __config_shmem_free_func); } - zbx_vector_uint64_pair_append(&master->dep_itemids, pair); + zbx_vector_uint64_pair_append(&item->master_item->dep_itemids, pair); } zbx_vector_ptr_destroy(&dep_items); + if (NULL != deleted_itemids) + zbx_vector_uint64_reserve(deleted_itemids, sync->remove_num); + /* remove deleted items from cache */ for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag)) { + if (NULL != deleted_itemids) + zbx_vector_uint64_append(deleted_itemids, rowid); + if (NULL == (item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &rowid))) continue; @@ -2874,13 +3121,10 @@ static void DCsync_items(zbx_dbsync_t *sync, zbx_uint32_t revision, int flags, z { dc_host_update_revision(host, revision); - if (ITEM_TYPE_ZABBIX_ACTIVE == item->type) + if (FAIL != (i = zbx_vector_dc_item_ptr_search(&host->items, item, + ZBX_DEFAULT_PTR_COMPARE_FUNC))) { - if (FAIL != (i = zbx_vector_dc_item_ptr_search(&host->active_items, item, - ZBX_DEFAULT_PTR_COMPARE_FUNC))) - { - zbx_vector_dc_item_ptr_remove(&host->active_items, i); - } + zbx_vector_dc_item_ptr_remove(&host->items, i); } } @@ -3098,12 +3342,11 @@ static void DCsync_items(zbx_dbsync_t *sync, zbx_uint32_t revision, int flags, z zbx_vector_ptr_destroy(&item->tags); - if (NULL != (preprocitem = (ZBX_DC_PREPROCITEM *)zbx_hashset_search(&config->preprocitems, - &item->itemid))) - { - zbx_vector_ptr_destroy(&preprocitem->preproc_ops); - zbx_hashset_remove_direct(&config->preprocitems, preprocitem); - } + if (NULL != item->preproc_item) + dc_preprocitem_free(item->preproc_item); + + if (NULL != item->master_item) + dc_masteritem_free(item->master_item); zbx_hashset_remove_direct(&config->items, item); } @@ -3221,7 +3464,7 @@ static void DCsync_prototype_items(zbx_dbsync_t *sync) zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); } -static void DCsync_triggers(zbx_dbsync_t *sync, zbx_uint32_t revision) +static void DCsync_triggers(zbx_dbsync_t *sync, zbx_uint64_t revision) { char **row; zbx_uint64_t rowid; @@ -3826,7 +4069,7 @@ static void dc_schedule_trigger_timers(zbx_hashset_t *trend_queue, int now) } } -static void DCsync_functions(zbx_dbsync_t *sync, zbx_uint32_t revision) +static void DCsync_functions(zbx_dbsync_t *sync, zbx_uint64_t revision) { char **row; zbx_uint64_t rowid; @@ -3931,7 +4174,7 @@ static ZBX_DC_REGEXP *dc_regexp_remove_expression(const char *regexp_name, zbx_u * Parameters: result - [IN] the result of expressions database select * * * ******************************************************************************/ -static void DCsync_expressions(zbx_dbsync_t *sync, zbx_uint32_t revision) +static void DCsync_expressions(zbx_dbsync_t *sync, zbx_uint64_t revision) { char **row; zbx_uint64_t rowid; @@ -3978,6 +4221,8 @@ static void DCsync_expressions(zbx_dbsync_t *sync, zbx_uint32_t revision) } zbx_vector_uint64_append(®exp->expressionids, expressionid); + + config->revision.expression = revision; } /* remove regexps with no expressions related to it */ @@ -4015,7 +4260,7 @@ static void DCsync_expressions(zbx_dbsync_t *sync, zbx_uint32_t revision) } if (0 != sync->add_num || 0 != sync->update_num || 0 != sync->remove_num) - config->expression_revision = revision; + config->revision.expression = revision; zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); } @@ -4204,7 +4449,7 @@ static void DCsync_action_conditions(zbx_dbsync_t *sync) zbx_vector_ptr_append(&action->conditions, condition); } - if (CONDITION_EVAL_TYPE_AND_OR == action->evaltype) + if (ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR == action->evaltype) zbx_vector_ptr_append(&actions, action); } @@ -4224,7 +4469,7 @@ static void DCsync_action_conditions(zbx_dbsync_t *sync) { zbx_vector_ptr_remove_noorder(&action->conditions, index); - if (CONDITION_EVAL_TYPE_AND_OR == action->evaltype) + if (ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR == action->evaltype) zbx_vector_ptr_append(&actions, action); } } @@ -4244,7 +4489,7 @@ static void DCsync_action_conditions(zbx_dbsync_t *sync) { action = (zbx_dc_action_t *)actions.values[i]; - if (CONDITION_EVAL_TYPE_AND_OR == action->evaltype) + if (ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR == action->evaltype) zbx_vector_ptr_sort(&action->conditions, dc_compare_action_conditions_by_type); } @@ -4511,7 +4756,7 @@ static void DCsync_corr_conditions(zbx_dbsync_t *sync) zbx_vector_ptr_append(&correlation->conditions, condition); /* sort the conditions later */ - if (CONDITION_EVAL_TYPE_AND_OR == correlation->evaltype) + if (ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR == correlation->evaltype) zbx_vector_ptr_append(&correlations, correlation); } @@ -4533,7 +4778,7 @@ static void DCsync_corr_conditions(zbx_dbsync_t *sync) ZBX_DEFAULT_PTR_COMPARE_FUNC))) { /* sort the conditions later */ - if (CONDITION_EVAL_TYPE_AND_OR == correlation->evaltype) + if (ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR == correlation->evaltype) zbx_vector_ptr_append(&correlations, correlation); zbx_vector_ptr_remove_noorder(&correlation->conditions, index); @@ -5038,20 +5283,21 @@ static int dc_compare_preprocops_by_step(const void *d1, const void *d2) * 3 - params * * * ******************************************************************************/ -static void DCsync_item_preproc(zbx_dbsync_t *sync, int timestamp) +static void DCsync_item_preproc(zbx_dbsync_t *sync, zbx_uint64_t revision) { - char **row; - zbx_uint64_t rowid; - unsigned char tag; - zbx_uint64_t item_preprocid, itemid; - int found, ret, i, index; - ZBX_DC_PREPROCITEM *preprocitem = NULL; - zbx_dc_preproc_op_t *op; - zbx_vector_ptr_t items; + char **row; + zbx_uint64_t rowid; + unsigned char tag; + zbx_uint64_t item_preprocid, itemid; + int found, ret, i, index; + ZBX_DC_PREPROCITEM *preprocitem = NULL; + zbx_dc_preproc_op_t *op; + ZBX_DC_ITEM *item; + zbx_vector_dc_item_ptr_t items; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); - zbx_vector_ptr_create(&items); + zbx_vector_dc_item_ptr_create(&items); while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag))) { @@ -5061,25 +5307,19 @@ static void DCsync_item_preproc(zbx_dbsync_t *sync, int timestamp) ZBX_STR2UINT64(itemid, row[1]); - if (NULL == preprocitem || itemid != preprocitem->itemid) - { - if (NULL == (preprocitem = (ZBX_DC_PREPROCITEM *)zbx_hashset_search(&config->preprocitems, - &itemid))) - { - ZBX_DC_PREPROCITEM preprocitem_local; + if (NULL == (item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &itemid))) + continue; - preprocitem_local.itemid = itemid; - preprocitem_local.update_time = timestamp; + if (NULL == (preprocitem = item->preproc_item)) + { + preprocitem = (ZBX_DC_PREPROCITEM *)__config_shmem_malloc_func(NULL, sizeof(ZBX_DC_PREPROCITEM)); - zbx_vector_ptr_create_ext(&preprocitem_local.preproc_ops, __config_shmem_malloc_func, - __config_shmem_realloc_func, __config_shmem_free_func); + zbx_vector_ptr_create_ext(&preprocitem->preproc_ops, __config_shmem_malloc_func, + __config_shmem_realloc_func, __config_shmem_free_func); - preprocitem = (ZBX_DC_PREPROCITEM *)zbx_hashset_insert(&config->preprocitems, - &preprocitem_local, sizeof(preprocitem_local)); - } - else - preprocitem->update_time = timestamp; + item->preproc_item = preprocitem; } + zbx_vector_dc_item_ptr_append(&items, item); ZBX_STR2UINT64(item_preprocid, row[0]); @@ -5097,8 +5337,6 @@ static void DCsync_item_preproc(zbx_dbsync_t *sync, int timestamp) op->itemid = itemid; zbx_vector_ptr_append(&preprocitem->preproc_ops, op); } - - zbx_vector_ptr_append(&items, preprocitem); } /* remove deleted item preprocessing operations */ @@ -5108,14 +5346,14 @@ static void DCsync_item_preproc(zbx_dbsync_t *sync, int timestamp) if (NULL == (op = (zbx_dc_preproc_op_t *)zbx_hashset_search(&config->preprocops, &rowid))) continue; - if (NULL != (preprocitem = (ZBX_DC_PREPROCITEM *)zbx_hashset_search(&config->preprocitems, - &op->itemid))) + if (NULL != (item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &op->itemid)) && + NULL != (preprocitem = item->preproc_item)) { if (FAIL != (index = zbx_vector_ptr_search(&preprocitem->preproc_ops, op, ZBX_DEFAULT_PTR_COMPARE_FUNC))) { zbx_vector_ptr_remove_noorder(&preprocitem->preproc_ops, index); - zbx_vector_ptr_append(&items, preprocitem); + zbx_vector_dc_item_ptr_append(&items, item); } } @@ -5126,23 +5364,28 @@ static void DCsync_item_preproc(zbx_dbsync_t *sync, int timestamp) /* sort item preprocessing operations by step */ - zbx_vector_ptr_sort(&items, ZBX_DEFAULT_PTR_COMPARE_FUNC); - zbx_vector_ptr_uniq(&items, ZBX_DEFAULT_PTR_COMPARE_FUNC); + zbx_vector_dc_item_ptr_sort(&items, ZBX_DEFAULT_PTR_COMPARE_FUNC); + zbx_vector_dc_item_ptr_uniq(&items, ZBX_DEFAULT_PTR_COMPARE_FUNC); for (i = 0; i < items.values_num; i++) { - preprocitem = (ZBX_DC_PREPROCITEM *)items.values[i]; + item = items.values[i]; + + if (NULL == (preprocitem = item->preproc_item)) + continue; + + dc_item_update_revision(item, revision); if (0 == preprocitem->preproc_ops.values_num) { - zbx_vector_ptr_destroy(&preprocitem->preproc_ops); - zbx_hashset_remove_direct(&config->preprocitems, preprocitem); + dc_preprocitem_free(preprocitem); + item->preproc_item = NULL; } else zbx_vector_ptr_sort(&preprocitem->preproc_ops, dc_compare_preprocops_by_step); } - zbx_vector_ptr_destroy(&items); + zbx_vector_dc_item_ptr_destroy(&items); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); } @@ -5160,7 +5403,7 @@ static void DCsync_item_preproc(zbx_dbsync_t *sync, int timestamp) * 3 - value * * * ******************************************************************************/ -static void DCsync_itemscript_param(zbx_dbsync_t *sync) +static void DCsync_itemscript_param(zbx_dbsync_t *sync, zbx_uint64_t revision) { char **row; zbx_uint64_t rowid; @@ -5170,6 +5413,7 @@ static void DCsync_itemscript_param(zbx_dbsync_t *sync) ZBX_DC_SCRIPTITEM *scriptitem; zbx_dc_scriptitem_param_t *scriptitem_params; zbx_vector_ptr_t items; + ZBX_DC_ITEM *dc_item; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); @@ -5241,6 +5485,9 @@ static void DCsync_itemscript_param(zbx_dbsync_t *sync) { scriptitem = (ZBX_DC_SCRIPTITEM *)items.values[i]; + if (NULL != (dc_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &scriptitem->itemid))) + dc_item_update_revision(dc_item, revision); + if (0 == scriptitem->params.values_num) { zbx_vector_ptr_destroy(&scriptitem->params); @@ -5257,21 +5504,6 @@ static void DCsync_itemscript_param(zbx_dbsync_t *sync) /****************************************************************************** * * - * Purpose: update host revision * - * * - ******************************************************************************/ -static int dc_host_update_revision(ZBX_DC_HOST *host, zbx_uint32_t revision) -{ - if (host->revision == revision) - return SUCCEED; - - host->revision = revision; - - return SUCCEED; -} - -/****************************************************************************** - * * * Purpose: Updates group hosts in configuration cache * * * * Parameters: sync - [IN] the db synchronization data * @@ -5334,6 +5566,588 @@ static void DCsync_hostgroup_hosts(zbx_dbsync_t *sync) /****************************************************************************** * * + * Purpose: calculate nextcheck timestamp * + * * + * Parameters: seend - [IN] the seed * + * delay - [IN] the delay in seconds * + * now - [IN] current timestamp * + * * + * Return value: nextcheck value * + * * + ******************************************************************************/ +static time_t dc_calculate_nextcheck(zbx_uint64_t seed, int delay, time_t now) +{ + time_t nextcheck; + + if (0 == delay) + return ZBX_JAN_2038; + + nextcheck = delay * (now / delay) + (unsigned int)(seed % (unsigned int)delay); + + while (nextcheck <= now) + nextcheck += delay; + + return nextcheck; +} + +static void dc_drule_queue(zbx_dc_drule_t *drule) +{ + zbx_binary_heap_elem_t elem; + + elem.key = drule->druleid; + elem.data = (const void *)drule; + + if (ZBX_LOC_QUEUE != drule->location) + { + zbx_binary_heap_insert(&config->drule_queue, &elem); + drule->location = ZBX_LOC_QUEUE; + } + else + zbx_binary_heap_update_direct(&config->drule_queue, &elem); +} + +static void dc_drule_dequeue(zbx_dc_drule_t *drule) +{ + if (ZBX_LOC_QUEUE == drule->location) + { + zbx_binary_heap_remove_direct(&config->drule_queue, drule->druleid); + drule->location = ZBX_LOC_NOWHERE; + } +} + +static void dc_sync_drules(zbx_dbsync_t *sync, zbx_uint64_t revision) +{ + char **row, *delay_str; + zbx_uint64_t rowid, druleid, proxy_hostid; + unsigned char tag; + int found, ret, delay = 0; + ZBX_DC_PROXY *proxy; + zbx_dc_drule_t *drule; + time_t now; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + + now = time(NULL); + + while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag))) + { + /* removed rows will be always added at the end */ + if (ZBX_DBSYNC_ROW_REMOVE == tag) + break; + + ZBX_STR2UINT64(druleid, row[0]); + ZBX_DBROW2UINT64(proxy_hostid, row[1]); + + drule = (zbx_dc_drule_t *)DCfind_id(&config->drules, druleid, sizeof(zbx_dc_drule_t), &found); + + ZBX_STR2UCHAR(drule->status, row[3]); + + if (0 == found) + { + drule->location = ZBX_LOC_NOWHERE; + drule->nextcheck = 0; + } + else + { + if (0 != drule->proxy_hostid && proxy_hostid != drule->proxy_hostid && + NULL != (proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, + &drule->proxy_hostid))) + { + proxy->revision = revision; + } + } + + drule->proxy_hostid = proxy_hostid; + if (0 != drule->proxy_hostid) + { + if (NULL != (proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &drule->proxy_hostid))) + proxy->revision = revision; + } + + delay_str = dc_expand_user_macros_dyn(row[2], NULL, 0, ZBX_MACRO_ENV_NONSECURE); + if (SUCCEED != zbx_is_time_suffix(delay_str, &delay, ZBX_LENGTH_UNLIMITED)) + delay = ZBX_DEFAULT_INTERVAL; + zbx_free(delay_str); + + if (DRULE_STATUS_MONITORED == drule->status && 0 == drule->proxy_hostid) + { + int delay_new = 0; + + if (0 == found && 0 < config->revision.config) + delay_new = delay > SEC_PER_MIN ? SEC_PER_MIN : delay; + else if (ZBX_LOC_NOWHERE == drule->location || delay != drule->delay) + delay_new = delay; + + if (0 != delay_new) + { + drule->nextcheck = dc_calculate_nextcheck(drule->druleid, delay_new, now); + dc_drule_queue(drule); + } + } + else + dc_drule_dequeue(drule); + + drule->delay = delay; + drule->revision = revision; + } + + /* remove deleted discovery rules from cache and update proxy revision */ + for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag)) + { + if (NULL == (drule = (zbx_dc_drule_t *)zbx_hashset_search(&config->drules, &rowid))) + continue; + + if (0 != drule->proxy_hostid) + { + if (NULL != (proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &drule->proxy_hostid))) + proxy->revision = revision; + } + + dc_drule_dequeue(drule); + zbx_hashset_remove_direct(&config->drules, drule); + } + + zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); +} + +static void dc_sync_dchecks(zbx_dbsync_t *sync, zbx_uint64_t revision) +{ + char **row; + zbx_uint64_t rowid, druleid, dcheckid; + unsigned char tag; + int found, ret; + ZBX_DC_PROXY *proxy; + zbx_dc_drule_t *drule; + zbx_dc_dcheck_t *dcheck; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + + while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag))) + { + /* removed rows will be always added at the end */ + if (ZBX_DBSYNC_ROW_REMOVE == tag) + break; + + ZBX_STR2UINT64(dcheckid, row[0]); + ZBX_STR2UINT64(druleid, row[1]); + + if (NULL == (drule = (zbx_dc_drule_t *)zbx_hashset_search(&config->drules, &druleid))) + continue; + + dcheck = (zbx_dc_dcheck_t *)DCfind_id(&config->dchecks, dcheckid, sizeof(zbx_dc_dcheck_t), &found); + dcheck->druleid = druleid; + + if (drule->revision == revision) + continue; + + drule->revision = revision; + + if (NULL != (proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &drule->proxy_hostid))) + proxy->revision = revision; + } + + /* remove deleted discovery checks from cache and update proxy revision */ + for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag)) + { + if (NULL == (dcheck = (zbx_dc_dcheck_t *)zbx_hashset_search(&config->dchecks, &rowid))) + continue; + + if (NULL != (drule = (zbx_dc_drule_t *)zbx_hashset_search(&config->drules, &dcheck->druleid)) && + 0 != drule->proxy_hostid && drule->revision != revision) + { + if (NULL != (proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &drule->proxy_hostid))) + proxy->revision = revision; + + drule->revision = revision; + } + + zbx_hashset_remove_direct(&config->dchecks, dcheck); + } + + zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); +} + +/****************************************************************************** + * * + * Purpose: update host and its proxy revision * + * * + ******************************************************************************/ +static int dc_host_update_revision(ZBX_DC_HOST *host, zbx_uint64_t revision) +{ + ZBX_DC_PROXY *proxy; + + if (host->revision == revision) + return SUCCEED; + + host->revision = revision; + + if (0 == host->proxy_hostid) + return SUCCEED; + + if (NULL == (proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &host->proxy_hostid))) + return FAIL; + + proxy->revision = revision; + + return SUCCEED; +} + +/****************************************************************************** + * * + * Purpose: update item, host and its proxy revision * + * * + ******************************************************************************/ +static int dc_item_update_revision(ZBX_DC_ITEM *item, zbx_uint64_t revision) +{ + ZBX_DC_HOST *host; + + if (item->revision == revision) + return SUCCEED; + + item->revision = revision; + + if (NULL == (host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &item->hostid))) + return FAIL; + + dc_host_update_revision(host, revision); + + return SUCCEED; +} + +/****************************************************************************** + * * + * Purpose: update httptest and its parent object revision * + * * + ******************************************************************************/ +static int dc_httptest_update_revision(zbx_dc_httptest_t *httptest, zbx_uint64_t revision) +{ + ZBX_DC_HOST *host; + + if (httptest->revision == revision) + return SUCCEED; + + httptest->revision = revision; + + if (NULL == (host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &httptest->hostid))) + return FAIL; + + dc_host_update_revision(host, revision); + + return SUCCEED; +} + +/****************************************************************************** + * * + * Purpose: update httptest step and its parent object revision * + * * + ******************************************************************************/ +static int dc_httpstep_update_revision(zbx_dc_httpstep_t *httpstep, zbx_uint64_t revision) +{ + zbx_dc_httptest_t *httptest; + + if (httpstep->revision == revision) + return SUCCEED; + + httpstep->revision = revision; + + if (NULL == (httptest = (zbx_dc_httptest_t *)zbx_hashset_search(&config->httptests, &httpstep->httptestid))) + return FAIL; + + return dc_httptest_update_revision(httptest, revision); +} + +static void dc_httptest_queue(zbx_dc_httptest_t *httptest) +{ + zbx_binary_heap_elem_t elem; + + elem.key = httptest->httptestid; + elem.data = (const void *)httptest; + + if (ZBX_LOC_QUEUE != httptest->location) + { + zbx_binary_heap_insert(&config->httptest_queue, &elem); + httptest->location = ZBX_LOC_QUEUE; + } + else + zbx_binary_heap_update_direct(&config->httptest_queue, &elem); +} + +static void dc_httptest_dequeue(zbx_dc_httptest_t *httptest) +{ + if (ZBX_LOC_QUEUE == httptest->location) + { + zbx_binary_heap_remove_direct(&config->httptest_queue, httptest->httptestid); + httptest->location = ZBX_LOC_NOWHERE; + } +} + +/****************************************************************************** + * * + * Purpose: update httpstep and its parent object revision * + * * + ******************************************************************************/ +static void dc_sync_httptests(zbx_dbsync_t *sync, zbx_uint64_t revision) +{ + char **row, *delay_str; + zbx_uint64_t rowid, httptestid, hostid; + unsigned char tag; + int found, ret, delay; + ZBX_DC_HOST *host; + zbx_dc_httptest_t *httptest; + time_t now; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + + now = time(NULL); + + while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag))) + { + /* removed rows will be always added at the end */ + if (ZBX_DBSYNC_ROW_REMOVE == tag) + break; + + ZBX_STR2UINT64(hostid, row[1]); + + if (NULL == (host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &hostid))) + continue; + + dc_host_update_revision(host, revision); + + ZBX_STR2UINT64(httptestid, row[0]); + + httptest = (zbx_dc_httptest_t *)DCfind_id(&config->httptests, httptestid, sizeof(zbx_dc_httptest_t), + &found); + + ZBX_STR2UCHAR(httptest->status, row[3]); + + if (0 == found) + { + httptest->location = ZBX_LOC_NOWHERE; + httptest->nextcheck = 0; + zbx_vector_dc_httptest_ptr_append(&host->httptests, httptest); + } + + delay_str = dc_expand_user_macros_dyn(row[2], &hostid, 1, ZBX_MACRO_ENV_NONSECURE); + if (SUCCEED != zbx_is_time_suffix(delay_str, &delay, ZBX_LENGTH_UNLIMITED)) + delay = ZBX_DEFAULT_INTERVAL; + zbx_free(delay_str); + + if (HTTPTEST_STATUS_MONITORED == httptest->status && HOST_STATUS_MONITORED == host->status && + 0 == host->proxy_hostid) + { + int delay_new = 0; + + if (0 == found && 0 < config->revision.config) + delay_new = delay > SEC_PER_MIN ? SEC_PER_MIN : delay; + else if (ZBX_LOC_NOWHERE == httptest->location || delay != httptest->delay) + delay_new = delay; + + if (0 != delay_new) + { + httptest->nextcheck = dc_calculate_nextcheck(httptest->httptestid, delay_new, now); + dc_httptest_queue(httptest); + } + } + else + dc_httptest_dequeue(httptest); + + httptest->hostid = hostid; + httptest->delay = delay; + httptest->revision = revision; + } + + /* remove deleted httptest rules from cache and update host revision */ + for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag)) + { + int index; + + if (NULL == (httptest = (zbx_dc_httptest_t *)zbx_hashset_search(&config->httptests, &rowid))) + continue; + + if (NULL != (host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &httptest->hostid))) + { + dc_host_update_revision(host, revision); + + if (FAIL != (index = zbx_vector_dc_httptest_ptr_search(&host->httptests, httptest, + ZBX_DEFAULT_PTR_COMPARE_FUNC))) + { + zbx_vector_dc_httptest_ptr_remove(&host->httptests, index); + } + } + + dc_httptest_dequeue(httptest); + zbx_hashset_remove_direct(&config->httptests, httptest); + } + + zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); +} + +static void dc_sync_httptest_fields(zbx_dbsync_t *sync, zbx_uint64_t revision) +{ + char **row; + zbx_uint64_t rowid, httptestid, httptest_fieldid; + unsigned char tag; + int found, ret; + zbx_dc_httptest_t *httptest; + zbx_dc_httptest_field_t *httptest_field; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + + while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag))) + { + /* removed rows will be always added at the end */ + if (ZBX_DBSYNC_ROW_REMOVE == tag) + break; + + ZBX_STR2UINT64(httptestid, row[1]); + + if (NULL == (httptest = (zbx_dc_httptest_t *)zbx_hashset_search(&config->httptests, &httptestid))) + continue; + + dc_httptest_update_revision(httptest, revision); + + ZBX_STR2UINT64(httptest_fieldid, row[0]); + + httptest_field = (zbx_dc_httptest_field_t *)DCfind_id(&config->httptest_fields, httptest_fieldid, + sizeof(zbx_dc_httptest_field_t), &found); + + httptest_field->httptestid = httptestid; + + } + + /* remove deleted httptest fields from cache and update host revision */ + for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag)) + { + if (NULL == (httptest_field = (zbx_dc_httptest_field_t *)zbx_hashset_search(&config->httptest_fields, + &rowid))) + { + continue; + } + + if (NULL != (httptest = (zbx_dc_httptest_t *)zbx_hashset_search(&config->httptests, + &httptest_field->httptestid))) + { + dc_httptest_update_revision(httptest, revision); + } + + zbx_hashset_remove_direct(&config->httptest_fields, httptest_field); + } + + zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); +} + +static void dc_sync_httpsteps(zbx_dbsync_t *sync, zbx_uint64_t revision) +{ + char **row; + zbx_uint64_t rowid, httptestid, httpstepid; + unsigned char tag; + int found, ret; + zbx_dc_httptest_t *httptest; + zbx_dc_httpstep_t *httpstep; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + + while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag))) + { + /* removed rows will be always added at the end */ + if (ZBX_DBSYNC_ROW_REMOVE == tag) + break; + + ZBX_STR2UINT64(httptestid, row[1]); + + if (NULL == (httptest = (zbx_dc_httptest_t *)zbx_hashset_search(&config->httptests, &httptestid))) + continue; + + dc_httptest_update_revision(httptest, revision); + + httptest->revision = revision; + + ZBX_STR2UINT64(httpstepid, row[0]); + + httpstep = (zbx_dc_httpstep_t *)DCfind_id(&config->httpsteps, httpstepid, + sizeof(zbx_dc_httpstep_t), &found); + + httpstep->httptestid = httptestid; + httpstep->revision = revision; + } + + /* remove deleted httptest fields from cache and update host revision */ + for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag)) + { + if (NULL == (httpstep = (zbx_dc_httpstep_t *)zbx_hashset_search(&config->httpsteps, + &rowid))) + { + continue; + } + + if (NULL != (httptest = (zbx_dc_httptest_t *)zbx_hashset_search(&config->httptests, + &httpstep->httptestid))) + { + dc_httptest_update_revision(httptest, revision); + } + + zbx_hashset_remove_direct(&config->httpsteps, httpstep); + } + + zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); +} + +static void dc_sync_httpstep_fields(zbx_dbsync_t *sync, zbx_uint64_t revision) +{ + char **row; + zbx_uint64_t rowid, httpstep_fieldid, httpstepid; + unsigned char tag; + int found, ret; + zbx_dc_httpstep_t *httpstep; + zbx_dc_httpstep_field_t *httpstep_field; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + + while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag))) + { + /* removed rows will be always added at the end */ + if (ZBX_DBSYNC_ROW_REMOVE == tag) + break; + + ZBX_STR2UINT64(httpstepid, row[1]); + + if (NULL == (httpstep = (zbx_dc_httpstep_t *)zbx_hashset_search(&config->httpsteps, &httpstepid))) + continue; + + dc_httpstep_update_revision(httpstep, revision); + + ZBX_STR2UINT64(httpstep_fieldid, row[0]); + + httpstep_field = (zbx_dc_httpstep_field_t *)DCfind_id(&config->httpstep_fields, httpstep_fieldid, + sizeof(zbx_dc_httpstep_field_t), &found); + + httpstep_field->httpstepid = httpstep_fieldid; + + } + + /* remove deleted httpstep fields from cache and update host revision */ + for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag)) + { + if (NULL == (httpstep_field = (zbx_dc_httpstep_field_t *)zbx_hashset_search(&config->httpstep_fields, + &rowid))) + { + continue; + } + + if (NULL != (httpstep = (zbx_dc_httpstep_t *)zbx_hashset_search(&config->httpsteps, + &httpstep_field->httpstepid))) + { + dc_httpstep_update_revision(httpstep, revision); + } + + zbx_hashset_remove_direct(&config->httpstep_fields, httpstep_field); + } + + zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); +} + +/****************************************************************************** + * * * Purpose: updates trigger topology after trigger dependency changes * * * ******************************************************************************/ @@ -5423,8 +6237,8 @@ static void dc_trigger_add_itemids(ZBX_DC_TRIGGER *trigger, const zbx_vector_uin * Purpose: reset item trigger links and remove corresponding itemids from * * affected triggers * * * - * Parameters: item - the item to reset * - * trigger - the trigger to exclude * + * Parameters: item - the item to reset * + * trigger_exclude - the trigger to exclude * * * ******************************************************************************/ static void dc_item_reset_triggers(ZBX_DC_ITEM *item, ZBX_DC_TRIGGER *trigger_exclude) @@ -5667,7 +6481,7 @@ static void zbx_dbsync_process_active_avail_diff(zbx_vector_uint64_t *diff) * Purpose: Synchronize configuration data from database * * * ******************************************************************************/ -void DCsync_configuration(unsigned char mode, zbx_synced_new_config_t synced) +void DCsync_configuration(unsigned char mode, zbx_synced_new_config_t synced, zbx_vector_uint64_t *deleted_itemids) { static int sync_status = ZBX_DBSYNC_STATUS_UNKNOWN; @@ -5679,7 +6493,8 @@ void DCsync_configuration(unsigned char mode, zbx_synced_new_config_t synced) correlation_sec, correlation_sec2, corr_condition_sec, corr_condition_sec2, corr_operation_sec, corr_operation_sec2, hgroups_sec, hgroups_sec2, itempp_sec, itempp_sec2, itemscrp_sec, itemscrp_sec2, total, total2, update_sec, maintenance_sec, maintenance_sec2, item_tag_sec, - item_tag_sec2, um_cache_sec, queues_sec, changelog_sec; + item_tag_sec2, um_cache_sec, queues_sec, changelog_sec, drules_sec, drules_sec2, httptest_sec, + httptest_sec2; zbx_dbsync_t config_sync, hosts_sync, hi_sync, htmpl_sync, gmacro_sync, hmacro_sync, if_sync, items_sync, template_items_sync, prototype_items_sync, item_discovery_sync, triggers_sync, tdep_sync, @@ -5687,7 +6502,8 @@ void DCsync_configuration(unsigned char mode, zbx_synced_new_config_t synced) item_tag_sync, host_tag_sync, correlation_sync, corr_condition_sync, corr_operation_sync, hgroups_sync, itempp_sync, itemscrp_sync, maintenance_sync, maintenance_period_sync, maintenance_tag_sync, maintenance_group_sync, maintenance_host_sync, hgroup_host_sync, - autoreg_host_sync; + drules_sync, dchecks_sync, httptest_sync, httptest_field_sync, httpstep_sync, + httpstep_field_sync, autoreg_host_sync; double autoreg_csec, autoreg_csec2, autoreg_host_csec, autoreg_host_csec2; zbx_dbsync_t autoreg_config_sync; @@ -5696,8 +6512,8 @@ void DCsync_configuration(unsigned char mode, zbx_synced_new_config_t synced) zbx_hashset_t trend_queue; zbx_vector_uint64_t active_avail_diff; - zbx_uint32_t new_revision = config->revision + 1; zbx_hashset_t activated_hosts; + zbx_uint64_t new_revision = config->revision.config + 1; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); @@ -5717,6 +6533,7 @@ void DCsync_configuration(unsigned char mode, zbx_synced_new_config_t synced) /* global configuration must be synchronized directly with database */ zbx_dbsync_init(&config_sync, ZBX_DBSYNC_INIT); + zbx_dbsync_init(&autoreg_config_sync, mode); zbx_dbsync_init(&autoreg_host_sync, mode); zbx_dbsync_init(&hosts_sync, changelog_sync_mode); @@ -5758,6 +6575,15 @@ void DCsync_configuration(unsigned char mode, zbx_synced_new_config_t synced) zbx_dbsync_init(&maintenance_group_sync, mode); zbx_dbsync_init(&maintenance_host_sync, mode); + zbx_dbsync_init(&drules_sync, changelog_sync_mode); + zbx_dbsync_init(&dchecks_sync, changelog_sync_mode); + + zbx_dbsync_init(&httptest_sync, changelog_sync_mode); + zbx_dbsync_init(&httptest_field_sync, changelog_sync_mode); + zbx_dbsync_init(&httpstep_sync, changelog_sync_mode); + zbx_dbsync_init(&httpstep_field_sync, changelog_sync_mode); + + #ifdef HAVE_ORACLE /* With Oracle fetch statements can fail before all data has been fetched. */ /* In such cache next sync will need to do full scan rather than just */ @@ -5784,11 +6610,12 @@ void DCsync_configuration(unsigned char mode, zbx_synced_new_config_t synced) /* sync global configuration settings */ START_SYNC; sec = zbx_time(); - DCsync_config(&config_sync, &flags); + DCsync_config(&config_sync, new_revision, &flags); csec2 = zbx_time() - sec; + /* must be done in the same cache locking with config sync */ sec = zbx_time(); - DCsync_autoreg_config(&autoreg_config_sync); /* must be done in the same cache locking with config sync */ + DCsync_autoreg_config(&autoreg_config_sync, new_revision); autoreg_csec2 = zbx_time() - sec; sec = zbx_time(); @@ -5828,6 +6655,7 @@ void DCsync_configuration(unsigned char mode, zbx_synced_new_config_t synced) host_tag_sec2 = zbx_time() - sec; FINISH_SYNC; + /* postpone configuration sync until macro secrets are received from Zabbix server */ if (0 == (program_type & ZBX_PROGRAM_TYPE_SERVER) && 0 != config->kvs_paths.values_num && ZBX_DBSYNC_INIT == mode) @@ -5867,14 +6695,33 @@ void DCsync_configuration(unsigned char mode, zbx_synced_new_config_t synced) goto out; maintenance_sec = zbx_time() - sec; + sec = zbx_time(); + if (FAIL == zbx_dbsync_prepare_drules(&drules_sync)) + goto out; + if (FAIL == zbx_dbsync_prepare_dchecks(&dchecks_sync)) + goto out; + drules_sec = zbx_time() - sec; + + sec = zbx_time(); + if (FAIL == zbx_dbsync_prepare_httptests(&httptest_sync)) + goto out; + if (FAIL == zbx_dbsync_prepare_httptest_fields(&httptest_field_sync)) + goto out; + if (FAIL == zbx_dbsync_prepare_httpsteps(&httpstep_sync)) + goto out; + if (FAIL == zbx_dbsync_prepare_httpstep_fields(&httpstep_field_sync)) + goto out; + httptest_sec = zbx_time() - sec; + START_SYNC; sec = zbx_time(); zbx_vector_uint64_create(&active_avail_diff); DCsync_hosts(&hosts_sync, new_revision, &active_avail_diff, &activated_hosts); + zbx_dbsync_clear_user_macros(); hsec2 = zbx_time() - sec; sec = zbx_time(); - DCsync_host_inventory(&hi_sync); + DCsync_host_inventory(&hi_sync, new_revision); hisec2 = zbx_time() - sec; sec = zbx_time(); @@ -5956,7 +6803,7 @@ void DCsync_configuration(unsigned char mode, zbx_synced_new_config_t synced) /* relies on hosts, proxies and interfaces, must be after DCsync_{hosts,interfaces}() */ sec = zbx_time(); - DCsync_items(&items_sync, new_revision, flags, synced); + DCsync_items(&items_sync, new_revision, flags, synced, deleted_itemids); isec2 = zbx_time() - sec; sec = zbx_time(); @@ -5973,12 +6820,12 @@ void DCsync_configuration(unsigned char mode, zbx_synced_new_config_t synced) /* relies on items, must be after DCsync_items() */ sec = zbx_time(); - DCsync_item_preproc(&itempp_sync, sec); + DCsync_item_preproc(&itempp_sync, new_revision); itempp_sec2 = zbx_time() - sec; /* relies on items, must be after DCsync_items() */ sec = zbx_time(); - DCsync_itemscript_param(&itemscrp_sync); + DCsync_itemscript_param(&itemscrp_sync, new_revision); itemscrp_sec2 = zbx_time() - sec; config->item_sync_ts = time(NULL); @@ -6106,6 +6953,18 @@ void DCsync_configuration(unsigned char mode, zbx_synced_new_config_t synced) corr_operation_sec2 = zbx_time() - sec; sec = zbx_time(); + dc_sync_drules(&drules_sync, new_revision); + dc_sync_dchecks(&dchecks_sync, new_revision); + drules_sec2 = zbx_time() - sec; + + sec = zbx_time(); + dc_sync_httptests(&httptest_sync, new_revision); + dc_sync_httptest_fields(&httptest_field_sync, new_revision); + dc_sync_httpsteps(&httpstep_sync, new_revision); + dc_sync_httpstep_fields(&httpstep_field_sync, new_revision); + httptest_sec2 = zbx_time() - sec; + + sec = zbx_time(); if (0 != hosts_sync.add_num + hosts_sync.update_num + hosts_sync.remove_num) update_flags |= ZBX_DBSYNC_UPDATE_HOSTS; @@ -6145,18 +7004,19 @@ void DCsync_configuration(unsigned char mode, zbx_synced_new_config_t synced) update_sec = zbx_time() - sec; - config->revision = new_revision; + config->revision.config = new_revision; if (SUCCEED == ZBX_CHECK_LOG_LEVEL(LOG_LEVEL_DEBUG)) { total = csec + hsec + hisec + htsec + gmsec + hmsec + ifsec + idsec + isec + tisec + pisec + tsec + dsec + fsec + expr_sec + action_sec + action_op_sec + action_condition_sec + trigger_tag_sec + correlation_sec + corr_condition_sec + corr_operation_sec + - hgroups_sec + itempp_sec + maintenance_sec + item_tag_sec; + hgroups_sec + itempp_sec + maintenance_sec + item_tag_sec + drules_sec + httptest_sec; total2 = csec2 + hsec2 + hisec2 + ifsec2 + idsec2 + isec2 + tisec2 + pisec2 + tsec2 + dsec2 + fsec2 + expr_sec2 + action_op_sec2 + action_sec2 + action_condition_sec2 + trigger_tag_sec2 + correlation_sec2 + corr_condition_sec2 + corr_operation_sec2 + hgroups_sec2 + - itempp_sec2 + maintenance_sec2 + item_tag_sec2 + update_sec + um_cache_sec; + itempp_sec2 + maintenance_sec2 + item_tag_sec2 + update_sec + um_cache_sec + + drules_sec2 + httptest_sec2; zabbix_log(LOG_LEVEL_DEBUG, "%s() changelog : sql:" ZBX_FS_DBL " sec (%d records)", __func__, changelog_sec, changelog_num); @@ -6287,6 +7147,25 @@ void DCsync_configuration(unsigned char mode, zbx_synced_new_config_t synced) ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").", __func__, maintenance_sec, maintenance_sec2, maintenance_sync.add_num, maintenance_sync.update_num, maintenance_sync.remove_num); + zabbix_log(LOG_LEVEL_DEBUG, "%s() drules : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec (" + ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").", + __func__, drules_sec, drules_sec2, drules_sync.add_num, drules_sync.update_num, + drules_sync.remove_num); + zabbix_log(LOG_LEVEL_DEBUG, "%s() dchecks : (" ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").", + __func__, dchecks_sync.add_num, dchecks_sync.update_num, dchecks_sync.remove_num); + + zabbix_log(LOG_LEVEL_DEBUG, "%s() httptests : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec (" + ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").", + __func__, httptest_sec, httptest_sec2, httptest_sync.add_num, httptest_sync.update_num, + httptest_sync.remove_num); + zabbix_log(LOG_LEVEL_DEBUG, "%s() httptestfld : (" ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").", + __func__, httptest_field_sync.add_num, httptest_field_sync.update_num, + httptest_field_sync.remove_num); + zabbix_log(LOG_LEVEL_DEBUG, "%s() httpsteps : (" ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").", + __func__, httpstep_sync.add_num, httpstep_sync.update_num, httpstep_sync.remove_num); + zabbix_log(LOG_LEVEL_DEBUG, "%s() httpstepfld : (" ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").", + __func__, httpstep_field_sync.add_num, httpstep_field_sync.update_num, + httpstep_field_sync.remove_num); zabbix_log(LOG_LEVEL_DEBUG, "%s() macro cache: " ZBX_FS_DBL " sec.", __func__, um_cache_sec); zabbix_log(LOG_LEVEL_DEBUG, "%s() reindex : " ZBX_FS_DBL " sec.", __func__, update_sec); @@ -6336,8 +7215,6 @@ void DCsync_configuration(unsigned char mode, zbx_synced_new_config_t synced) zabbix_log(LOG_LEVEL_DEBUG, "%s() numitems : %d (%d slots)", __func__, config->numitems.num_data, config->numitems.num_slots); zabbix_log(LOG_LEVEL_DEBUG, "%s() preprocitems: %d (%d slots)", __func__, - config->preprocitems.num_data, config->preprocitems.num_slots); - zabbix_log(LOG_LEVEL_DEBUG, "%s() preprocops : %d (%d slots)", __func__, config->preprocops.num_data, config->preprocops.num_slots); zabbix_log(LOG_LEVEL_DEBUG, "%s() snmpitems : %d (%d slots)", __func__, config->snmpitems.num_data, config->snmpitems.num_slots); @@ -6399,6 +7276,20 @@ void DCsync_configuration(unsigned char mode, zbx_synced_new_config_t synced) zabbix_log(LOG_LEVEL_DEBUG, "%s() maint time : %d (%d slots)", __func__, config->maintenance_periods.num_data, config->maintenance_periods.num_slots); + zabbix_log(LOG_LEVEL_DEBUG, "%s() drules : %d (%d slots)", __func__, + config->drules.num_data, config->drules.num_slots); + zabbix_log(LOG_LEVEL_DEBUG, "%s() dchecks : %d (%d slots)", __func__, + config->dchecks.num_data, config->dchecks.num_slots); + + zabbix_log(LOG_LEVEL_DEBUG, "%s() httptests : %d (%d slots)", __func__, + config->httptests.num_data, config->httptests.num_slots); + zabbix_log(LOG_LEVEL_DEBUG, "%s() httptestfld: %d (%d slots)", __func__, + config->httptest_fields.num_data, config->httptest_fields.num_slots); + zabbix_log(LOG_LEVEL_DEBUG, "%s() httpsteps : %d (%d slots)", __func__, + config->httpsteps.num_data, config->httpsteps.num_slots); + zabbix_log(LOG_LEVEL_DEBUG, "%s() httpstepfld: %d (%d slots)", __func__, + config->httpstep_fields.num_data, config->httpstep_fields.num_slots); + for (i = 0; ZBX_POLLER_TYPE_COUNT > i; i++) { zabbix_log(LOG_LEVEL_DEBUG, "%s() queue[%d] : %d (%d allocated)", __func__, @@ -6460,7 +7351,12 @@ out: if (0 != (update_flags & (ZBX_DBSYNC_UPDATE_HOSTS | ZBX_DBSYNC_UPDATE_ITEMS | ZBX_DBSYNC_UPDATE_MACROS))) { sec = zbx_time(); + dc_reschedule_items(&activated_hosts); + + if (0 != activated_hosts.num_data) + dc_reschedule_httptests(&activated_hosts); + queues_sec = zbx_time() - sec; zabbix_log(LOG_LEVEL_DEBUG, "%s() reschedule : " ZBX_FS_DBL " sec.", __func__, queues_sec); } @@ -6500,6 +7396,12 @@ clean: zbx_dbsync_clear(&maintenance_group_sync); zbx_dbsync_clear(&maintenance_host_sync); zbx_dbsync_clear(&hgroup_host_sync); + zbx_dbsync_clear(&drules_sync); + zbx_dbsync_clear(&dchecks_sync); + zbx_dbsync_clear(&httptest_sync); + zbx_dbsync_clear(&httptest_field_sync); + zbx_dbsync_clear(&httpstep_sync); + zbx_dbsync_clear(&httpstep_field_sync); if (ZBX_DBSYNC_INIT == mode) zbx_hashset_destroy(&trend_queue); @@ -6783,6 +7685,28 @@ static int __config_timer_compare(const void *d1, const void *d2) return 0; } +static int __config_drule_compare(const void *d1, const void *d2) +{ + const zbx_binary_heap_elem_t *e1 = (const zbx_binary_heap_elem_t *)d1; + const zbx_binary_heap_elem_t *e2 = (const zbx_binary_heap_elem_t *)d2; + + const zbx_dc_drule_t *r1 = (const zbx_dc_drule_t *)e1->data; + const zbx_dc_drule_t *r2 = (const zbx_dc_drule_t *)e2->data; + + return (int)(r1->nextcheck - r2->nextcheck); +} + +static int __config_httptest_compare(const void *d1, const void *d2) +{ + const zbx_binary_heap_elem_t *e1 = (const zbx_binary_heap_elem_t *)d1; + const zbx_binary_heap_elem_t *e2 = (const zbx_binary_heap_elem_t *)d2; + + const zbx_dc_httptest_t *ht1 = (const zbx_dc_httptest_t *)e1->data; + const zbx_dc_httptest_t *ht2 = (const zbx_dc_httptest_t *)e2->data; + + return (int)(ht1->nextcheck - ht2->nextcheck); +} + static zbx_hash_t __config_session_hash(const void *data) { const zbx_session_t *session = (const zbx_session_t *)data; @@ -6846,8 +7770,6 @@ int init_configuration_cache(char **error) CREATE_HASHSET(config->simpleitems, 0); CREATE_HASHSET(config->jmxitems, 0); CREATE_HASHSET(config->calcitems, 0); - CREATE_HASHSET(config->masteritems, 0); - CREATE_HASHSET(config->preprocitems, 0); CREATE_HASHSET(config->httpitems, 0); CREATE_HASHSET(config->scriptitems, 0); CREATE_HASHSET(config->itemscript_params, 0); @@ -6954,6 +7876,27 @@ int init_configuration_cache(char **error) __config_shmem_realloc_func, __config_shmem_free_func); + zbx_binary_heap_create_ext(&config->drule_queue, + __config_drule_compare, + ZBX_BINARY_HEAP_OPTION_DIRECT, + __config_shmem_malloc_func, + __config_shmem_realloc_func, + __config_shmem_free_func); + + zbx_binary_heap_create_ext(&config->httptest_queue, + __config_httptest_compare, + ZBX_BINARY_HEAP_OPTION_DIRECT, + __config_shmem_malloc_func, + __config_shmem_realloc_func, + __config_shmem_free_func); + + CREATE_HASHSET(config->drules, 0); + CREATE_HASHSET(config->dchecks, 0); + + CREATE_HASHSET(config->httptests, 0); + CREATE_HASHSET(config->httptest_fields, 0); + CREATE_HASHSET(config->httpsteps, 0); + CREATE_HASHSET(config->httpstep_fields, 0); for (i = 0; i < ZBX_SESSION_TYPE_COUNT; i++) CREATE_HASHSET_EXT(config->sessions[i], 0, __config_session_hash, __config_session_compare); @@ -6961,6 +7904,7 @@ int init_configuration_cache(char **error) config->status = (ZBX_DC_STATUS *)__config_shmem_malloc_func(NULL, sizeof(ZBX_DC_STATUS)); config->status->last_update = 0; + config->status->sync_ts = 0; config->availability_diff_ts = 0; config->sync_ts = 0; @@ -6968,8 +7912,8 @@ int init_configuration_cache(char **error) config->internal_actions = 0; config->auto_registration_actions = 0; - config->revision = 0; - config->expression_revision = 0; + + memset(&config->revision, 0, sizeof(config->revision)); config->um_cache = um_cache_create(); @@ -7245,7 +8189,7 @@ int DCcheck_proxy_permissions(const char *host, const zbx_socket_t *sock, zbx_ui * * ******************************************************************************/ int DCcheck_host_permissions(const char *host, const zbx_socket_t *sock, zbx_uint64_t *hostid, - zbx_uint32_t *revision, char **error) + zbx_uint64_t *revision, char **error) { const ZBX_DC_HOST *dc_host; #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) @@ -7290,14 +8234,14 @@ int DCcheck_host_permissions(const char *host, const zbx_socket_t *sock, zbx_uin #endif *hostid = dc_host->hostid; - *revision = MAX(dc_host->revision, config->expression_revision); + *revision = MAX(dc_host->revision, config->revision.expression); um_cache_get_host_revision(config->um_cache, ZBX_UM_CACHE_GLOBAL_MACRO_HOSTID, revision); um_cache_get_host_revision(config->um_cache, *hostid, revision); /* configuration is not yet fully synced */ - if (*revision > config->revision) - *revision = config->revision; + if (*revision > config->revision.config) + *revision = config->revision.config; UNLOCK_CACHE; @@ -7677,7 +8621,7 @@ static void DCget_item(DC_ITEM *dst_item, const ZBX_DC_ITEM *src_item, unsigned *dst_item->snmp_community_orig = '\0'; *dst_item->snmp_oid_orig = '\0'; *dst_item->snmpv3_securityname_orig = '\0'; - dst_item->snmpv3_securitylevel = ITEM_SNMPV3_SECURITYLEVEL_NOAUTHNOPRIV; + dst_item->snmpv3_securitylevel = ZBX_ITEM_SNMPV3_SECURITYLEVEL_NOAUTHNOPRIV; *dst_item->snmpv3_authpassphrase_orig = '\0'; *dst_item->snmpv3_privpassphrase_orig = '\0'; dst_item->snmpv3_authprotocol = 0; @@ -8179,11 +9123,19 @@ void DCconfig_get_items_by_itemids(DC_ITEM *items, const zbx_uint64_t *itemids, int DCconfig_get_active_items_count_by_hostid(zbx_uint64_t hostid) { const ZBX_DC_HOST *dc_host; - int num = 0; + int i, num = 0; RDLOCK_CACHE; + if (NULL != (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &hostid))) - num = dc_host->active_items.values_num; + { + for (i = 0; i < dc_host->items.values_num; i++) + { + if (ITEM_TYPE_ZABBIX_ACTIVE == dc_host->items.values[i]->type) + num++; + } + } + UNLOCK_CACHE; return num; @@ -8192,33 +9144,39 @@ int DCconfig_get_active_items_count_by_hostid(zbx_uint64_t hostid) void DCconfig_get_active_items_by_hostid(DC_ITEM *items, zbx_uint64_t hostid, int *errcodes, size_t num) { const ZBX_DC_HOST *dc_host; - size_t i = 0; + size_t i, j = 0; RDLOCK_CACHE; if (NULL != (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &hostid)) && - 0 != dc_host->active_items.values_num) + 0 != dc_host->items.values_num) { - DCget_host(&items[0].host, dc_host, ZBX_ITEM_GET_ALL); - - for (; i < MIN((size_t)dc_host->active_items.values_num, num); i++) + for (i = 0; i < (size_t)dc_host->items.values_num && j < num; i++) { const ZBX_DC_ITEM *dc_item; - dc_item = dc_host->active_items.values[i]; + dc_item = dc_host->items.values[i]; - if (0 != i) - items[i].host = items[0].host; + if (ITEM_TYPE_ZABBIX_ACTIVE != dc_item->type) + continue; - DCget_item(&items[i], dc_item, ZBX_ITEM_GET_DEFAULT); - errcodes[i] = SUCCEED; + DCget_item(&items[j], dc_item, ZBX_ITEM_GET_DEFAULT); + errcodes[j++] = SUCCEED; + } + + if (0 != j) + { + DCget_host(&items[0].host, dc_host, ZBX_ITEM_GET_ALL); + + for (i = 1; i < j; i++) + items[i].host = items[0].host; } } UNLOCK_CACHE; - for (; i < num; i++) - errcodes[i] = FAIL; + for (; j < num; j++) + errcodes[j] = FAIL; } /****************************************************************************** @@ -8324,60 +9282,185 @@ void DCconfig_get_items_by_itemids_partial(DC_ITEM *items, const zbx_uint64_t *i zbx_dc_close_user_macros(um_handle); } +static void dc_preproc_dump(zbx_hashset_t *items) +{ + zbx_hashset_iter_t iter; + zbx_preproc_item_t *item; + int i; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + + zbx_hashset_iter_reset(items, &iter); + while (NULL != (item = (zbx_preproc_item_t *)zbx_hashset_iter_next(&iter))) + { + zabbix_log(LOG_LEVEL_TRACE, "itemid:" ZBX_FS_UI64 " type:%u value_type:%u revision:" ZBX_FS_UI64, + item->itemid, item->type, item->value_type, item->preproc_revision); + + zabbix_log(LOG_LEVEL_TRACE, " dependent items:"); + for (i = 0; i < item->dep_itemids_num; i++) + { + zabbix_log(LOG_LEVEL_TRACE, " depitemid:" ZBX_FS_UI64 "," ZBX_FS_UI64, + item->dep_itemids[i].first, item->dep_itemids[i].second); + } + + zabbix_log(LOG_LEVEL_TRACE, " preprocessing steps:"); + for (i = 0; i < item->preproc_ops_num; i++) + { + zabbix_log(LOG_LEVEL_TRACE, " type:%u params:%s error_handler:%u error_handler_params:%s", + item->preproc_ops[i].type, ZBX_NULL2EMPTY_STR(item->preproc_ops[i].params), + item->preproc_ops[i].error_handler, + ZBX_NULL2EMPTY_STR(item->preproc_ops[i].error_handler_params)); + } + } + + zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); +} + +static void dc_preproc_free_ops(zbx_preproc_op_t *ops, int ops_num) +{ + int i; + + for (i = 0; i < ops_num; i++) + { + zbx_free(ops[i].params); + zbx_free(ops[i].error_handler_params); + } + zbx_free(ops); +} + /****************************************************************************** * * - * Purpose: initialize new preprocessor item from configuration cache * + * Purpose: sync item preprocessing steps with preprocessing manager cache, * + * updating preprocessing revision if any changes were detected * * * - * Parameters: item - [OUT] the item to initialize * - * itemid - [IN] the item identifier * + ******************************************************************************/ +static void dc_preproc_sync_preprocitem(zbx_preproc_item_t *item, const ZBX_DC_PREPROCITEM *preprocitem, + zbx_uint64_t revision) +{ + int i, ops_num = 0; + zbx_preproc_op_t *ops; + + if (NULL == preprocitem) + { + dc_preproc_free_ops(item->preproc_ops, item->preproc_ops_num); + item->preproc_ops = NULL; + item->preproc_ops_num = 0; + return; + } + + ops = (zbx_preproc_op_t *)zbx_malloc(NULL, sizeof(zbx_preproc_op_t) * preprocitem->preproc_ops.values_num); + + for (i = 0; i < preprocitem->preproc_ops.values_num; i++) + { + zbx_dc_preproc_op_t *op = (zbx_dc_preproc_op_t *)preprocitem->preproc_ops.values[i]; + + ops[i].type = op->type; + ops[i].error_handler = op->error_handler; + + ops[i].params = dc_expand_user_macros_dyn(op->params, &item->hostid, 1, ZBX_MACRO_ENV_NONSECURE); + ops[i].error_handler_params = zbx_strdup(NULL, op->error_handler_params); + } + + if (preprocitem->preproc_ops.values_num == item->preproc_ops_num) + { + for (;ops_num < item->preproc_ops_num; ops_num++) + { + zbx_preproc_op_t *src = &ops[ops_num]; + zbx_preproc_op_t *dst = &item->preproc_ops[ops_num]; + + if (src->type != dst->type) + break; + + if (src->error_handler != dst->error_handler) + break; + + if (0 != zbx_strcmp_null(src->params, dst->params)) + break; + + if (0 != zbx_strcmp_null(src->error_handler_params, dst->error_handler_params)) + break; + } + } + + if (ops_num != item->preproc_ops_num) + item->preproc_revision = revision; + + dc_preproc_free_ops(item->preproc_ops, item->preproc_ops_num); + + item->preproc_ops = ops; + item->preproc_ops_num = preprocitem->preproc_ops.values_num; +} + +/****************************************************************************** * * - * Return value: SUCCEED - the item was initialized successfully * - * FAIL - item with the specified itemid is not cached or * - * monitored * + * Purpose: sync mater-dependent item links * * * ******************************************************************************/ -static int dc_preproc_item_init(zbx_preproc_item_t *item, zbx_uint64_t itemid) +static void dc_preproc_sync_masteritem(zbx_preproc_item_t *item, const ZBX_DC_MASTERITEM *masteritem) { - const ZBX_DC_ITEM *dc_item; - const ZBX_DC_HOST *dc_host; + if (NULL == masteritem) + { + zbx_free(item->dep_itemids); + item->dep_itemids_num = 0; + return; + } - if (NULL == (dc_item = (const ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &itemid))) - return FAIL; + if (masteritem->dep_itemids.values_num > item->dep_itemids_num) + { + item->dep_itemids = (zbx_uint64_pair_t *)zbx_realloc(item->dep_itemids, + sizeof(zbx_uint64_pair_t) * masteritem->dep_itemids.values_num); + } - if (ITEM_STATUS_ACTIVE != dc_item->status) - return FAIL; + memcpy(item->dep_itemids, masteritem->dep_itemids.values, + sizeof(zbx_uint64_pair_t) * masteritem->dep_itemids.values_num); - if (NULL == (dc_host = (const ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid))) - return FAIL; + item->dep_itemids_num = masteritem->dep_itemids.values_num; +} - if (HOST_STATUS_MONITORED != dc_host->status) - return FAIL; +static void dc_preproc_sync_item(zbx_hashset_t *items, ZBX_DC_ITEM *dc_item, zbx_uint64_t revision) +{ + zbx_preproc_item_t *pp_item; - switch (dc_item->type) + if (NULL == (pp_item = (zbx_preproc_item_t *)zbx_hashset_search(items, &dc_item->itemid))) { - case ITEM_TYPE_INTERNAL: - case ITEM_TYPE_CALCULATED: - case ITEM_TYPE_DEPENDENT: - break; - default: - if (0 != dc_host->proxy_hostid) - return FAIL; + zbx_preproc_item_t pp_item_local = {.itemid = dc_item->itemid}; + + pp_item = (zbx_preproc_item_t *)zbx_hashset_insert(items, &pp_item_local, sizeof(pp_item_local)); + pp_item->hostid = dc_item->hostid; + pp_item->preproc_revision = revision; } - item->itemid = itemid; - item->hostid = dc_item->hostid; - item->type = dc_item->type; - item->value_type = dc_item->value_type; + pp_item->type = dc_item->type; + pp_item->value_type = dc_item->value_type; + pp_item->revision = revision; - item->dep_itemids = NULL; - item->dep_itemids_num = 0; + dc_preproc_sync_masteritem(pp_item, dc_item->master_item); + dc_preproc_sync_preprocitem(pp_item, dc_item->preproc_item, revision); +} - item->preproc_ops = NULL; - item->preproc_ops_num = 0; - item->update_time = 0; - item->macro_update = ZBX_PREPROC_MACRO_UPDATE_FALSE; - return SUCCEED; +static void dc_preproc_add_item_rec(ZBX_DC_ITEM *dc_item, zbx_vector_dc_item_ptr_t *items_sync) +{ + if (NULL != dc_item->master_item || NULL != dc_item->preproc_item || ITEM_TYPE_INTERNAL == dc_item->type) + zbx_vector_dc_item_ptr_append(items_sync, dc_item); + + if (NULL != dc_item->master_item) + { + int i; + + for (i = 0; i < dc_item->master_item->dep_itemids.values_num; i++) + { + ZBX_DC_ITEM *dep_item; + + if (NULL == (dep_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, + &dc_item->master_item->dep_itemids.values[i].first))) + { + continue; + } + + dc_preproc_add_item_rec(dep_item, items_sync); + } + } } /****************************************************************************** @@ -8391,196 +9474,101 @@ static int dc_preproc_item_init(zbx_preproc_item_t *item, zbx_uint64_t itemid) * timestamp - [IN/OUT] timestamp of a last update * * * ******************************************************************************/ -void DCconfig_get_preprocessable_items(zbx_hashset_t *items, int *timestamp) +void DCconfig_get_preprocessable_items(zbx_hashset_t *items, zbx_uint64_t *revision) { - const ZBX_DC_PREPROCITEM *dc_preprocitem; - const ZBX_DC_MASTERITEM *dc_masteritem; - const ZBX_DC_ITEM *dc_item; - const zbx_dc_preproc_op_t *dc_op; - zbx_preproc_item_t *item, item_local; + ZBX_DC_HOST *dc_host; + zbx_preproc_item_t *pp_item; zbx_hashset_iter_t iter; - zbx_hashset_t ids; - zbx_preproc_op_t *op; int i; - zbx_dc_um_handle_t *um_handle; - - zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); - - /* no changes */ - if (0 != *timestamp && *timestamp == config->item_sync_ts) - goto out; + zbx_uint64_t global_revision = *revision; + zbx_vector_dc_item_ptr_t items_sync; - zbx_hashset_create(&ids, MAX((size_t)items->num_data, 1000), ZBX_DEFAULT_UINT64_HASH_FUNC, - ZBX_DEFAULT_UINT64_COMPARE_FUNC); + if (config->revision.config == *revision) + return; - *timestamp = config->item_sync_ts; + zbx_vector_dc_item_ptr_create(&items_sync); + zbx_vector_dc_item_ptr_reserve(&items_sync, 100); RDLOCK_CACHE; - zbx_hashset_iter_reset(&config->preprocitems, &iter); - while (NULL != (dc_preprocitem = (const ZBX_DC_PREPROCITEM *)zbx_hashset_iter_next(&iter))) + if (SUCCEED != um_cache_get_host_revision(config->um_cache, 0, &global_revision)) + global_revision = 0; + + zbx_hashset_iter_reset(&config->hosts, &iter); + while (NULL != (dc_host = (ZBX_DC_HOST *)zbx_hashset_iter_next(&iter))) { - if (FAIL == dc_preproc_item_init(&item_local, dc_preprocitem->itemid)) + if (HOST_STATUS_MONITORED != dc_host->status) continue; - if (NULL != (item = (zbx_preproc_item_t *)zbx_hashset_search(items, &item_local))) + for (i = 0; i < dc_host->items.values_num; i++) { - if (item->update_time == dc_preprocitem->update_time && - item->preproc_ops_num == dc_preprocitem->preproc_ops.values_num) - { - for (i = 0; i < dc_preprocitem->preproc_ops.values_num; i++) - { - dc_op = (const zbx_dc_preproc_op_t *)dc_preprocitem->preproc_ops.values[i]; - op = &item->preproc_ops[i]; - - op->params_orig = zbx_strdup(NULL, dc_op->params); - } + ZBX_DC_ITEM *dc_item = dc_host->items.values[i]; - item->dep_itemids_num = 0; - zbx_free(item->dep_itemids); - - zbx_hashset_insert(&ids, &item->itemid, sizeof(item->itemid)); + if (ITEM_STATUS_ACTIVE != dc_item->status || ITEM_TYPE_DEPENDENT == dc_item->type) continue; - } - else - zbx_hashset_remove_direct(items, item); - } - - item = (zbx_preproc_item_t *)zbx_hashset_insert(items, &item_local, sizeof(item_local)); - item->preproc_ops_num = dc_preprocitem->preproc_ops.values_num; - item->preproc_ops = (zbx_preproc_op_t *)zbx_malloc(NULL, sizeof(zbx_preproc_op_t) * - item->preproc_ops_num); - item->update_time = dc_preprocitem->update_time; - - for (i = 0; i < dc_preprocitem->preproc_ops.values_num; i++) - { - dc_op = (const zbx_dc_preproc_op_t *)dc_preprocitem->preproc_ops.values[i]; - op = &item->preproc_ops[i]; - op->type = dc_op->type; - op->params = NULL; - op->params_orig = zbx_strdup(NULL, dc_op->params); - op->error_handler = dc_op->error_handler; - op->error_handler_params = zbx_strdup(NULL, dc_op->error_handler_params); - } - - zbx_hashset_insert(&ids, &item->itemid, sizeof(item->itemid)); - } - - zbx_hashset_iter_reset(&config->masteritems, &iter); - while (NULL != (dc_masteritem = (const ZBX_DC_MASTERITEM *)zbx_hashset_iter_next(&iter))) - { - if (NULL == (item = (zbx_preproc_item_t *)zbx_hashset_search(items, &dc_masteritem->itemid))) - { - if (FAIL == dc_preproc_item_init(&item_local, dc_masteritem->itemid)) - continue; - - item = (zbx_preproc_item_t *)zbx_hashset_insert(items, &item_local, sizeof(item_local)); - } - else - { - if (NULL == zbx_hashset_search(&ids, &item->itemid)) + if (NULL == dc_item->preproc_item && NULL == dc_item->master_item && + ITEM_TYPE_INTERNAL != dc_item->type) { - if (FAIL == dc_preproc_item_init(&item_local, dc_masteritem->itemid)) - continue; - - /* remove preprocessing and reset dep_itemids */ - zbx_hashset_remove_direct(items, item); - item = (zbx_preproc_item_t *)zbx_hashset_insert(items, &item_local, sizeof(item_local)); + continue; } - } - - zbx_hashset_insert(&ids, &item->itemid, sizeof(item->itemid)); - - item->dep_itemids_num = 0; - item->dep_itemids = (zbx_uint64_pair_t *)zbx_malloc(NULL, sizeof(zbx_uint64_pair_t) * - dc_masteritem->dep_itemids.values_num); - for (i = 0; i < dc_masteritem->dep_itemids.values_num; i++) - { - if (NULL == (dc_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, - &dc_masteritem->dep_itemids.values[i].first)) || - ITEM_STATUS_ACTIVE != dc_item->status) + if (0 == dc_host->proxy_hostid || + SUCCEED == is_item_processed_by_server(dc_item->type, dc_item->key)) { - continue; + dc_preproc_add_item_rec(dc_item, &items_sync); } - item->dep_itemids[item->dep_itemids_num++] = dc_masteritem->dep_itemids.values[i]; } - } - zbx_hashset_iter_reset(&config->items, &iter); - while (NULL != (dc_item = (const ZBX_DC_ITEM *)zbx_hashset_iter_next(&iter))) - { - if (ITEM_TYPE_INTERNAL != dc_item->type) + /* don't check host macro revision if the host does not have locally pre-processable items */ + if (0 == items_sync.values_num) continue; - if (NULL == (item = zbx_hashset_search(items, &dc_item->itemid))) + if (*revision >= global_revision && *revision >= dc_host->revision) { - if (FAIL == dc_preproc_item_init(&item_local, dc_item->itemid)) - continue; + zbx_uint64_t macro_revision = *revision; - item = zbx_hashset_insert(items, &item_local, sizeof(item_local)); - } - else - { - if (NULL == zbx_hashset_search(&ids, &item->itemid)) + if (SUCCEED == um_cache_get_host_revision(config->um_cache, dc_host->hostid, ¯o_revision) && + *revision >= macro_revision) { - if (FAIL == dc_preproc_item_init(&item_local, dc_item->itemid)) - continue; + for (i = 0; i < items_sync.values_num; i++) + { + if (NULL != (pp_item = (zbx_preproc_item_t *)zbx_hashset_search(items, + &items_sync.values[i]->itemid))) + { + pp_item->revision = config->revision.config; + } - /* remove preprocessing and dependent */ - zbx_hashset_remove_direct(items, item); - item = (zbx_preproc_item_t *)zbx_hashset_insert(items, &item_local, sizeof(item_local)); + } + zbx_vector_dc_item_ptr_clear(&items_sync); } } - zbx_hashset_insert(&ids, &item->itemid, sizeof(item->itemid)); + for (i = 0; i < items_sync.values_num; i++) + dc_preproc_sync_item(items, items_sync.values[i], config->revision.config); + + zbx_vector_dc_item_ptr_clear(&items_sync); } - UNLOCK_CACHE; + *revision = config->revision.config; - zbx_hashset_iter_reset(items, &iter); - while (NULL != (item = (zbx_preproc_item_t *)zbx_hashset_iter_next(&iter))) - { - if (NULL == zbx_hashset_search(&ids, &item->itemid)) - zbx_hashset_iter_remove(&iter); - } + UNLOCK_CACHE; - um_handle = zbx_dc_open_user_macros(); + /* remove items without preprocessing */ zbx_hashset_iter_reset(items, &iter); - while (NULL != (item = (zbx_preproc_item_t *)zbx_hashset_iter_next(&iter))) + while (NULL != (pp_item = (zbx_preproc_item_t *)zbx_hashset_iter_next(&iter))) { - for (i = 0; i < item->preproc_ops_num; i++) - { - (void)zbx_dc_expand_user_macros(um_handle, &item->preproc_ops[i].error_handler_params, - &item->hostid, 1, NULL); - - if (NULL != strstr(item->preproc_ops[i].params_orig, "{$")) - { - (void)zbx_dc_expand_user_macros(um_handle, &item->preproc_ops[i].params_orig, - &item->hostid, 1, NULL); - - if (NULL != item->preproc_ops[i].params && - 0 != strcmp(item->preproc_ops[i].params, - item->preproc_ops[i].params_orig)) - { - item->macro_update = ZBX_PREPROC_MACRO_UPDATE_TRUE; - } - } - - zbx_free(item->preproc_ops[i].params); - item->preproc_ops[i].params = item->preproc_ops[i].params_orig; - item->preproc_ops[i].params_orig = NULL; - } + if (pp_item->revision == *revision) + continue; + zbx_hashset_iter_remove(&iter); } - zbx_dc_close_user_macros(um_handle); + zbx_vector_dc_item_ptr_destroy(&items_sync); - zbx_hashset_destroy(&ids); -out: - zabbix_log(LOG_LEVEL_DEBUG, "End of %s() items:%d", __func__, items->num_data); + if (SUCCEED == ZBX_CHECK_LOG_LEVEL(LOG_LEVEL_TRACE)) + dc_preproc_dump(items); } void DCconfig_get_hosts_by_itemids(DC_HOST *hosts, const zbx_uint64_t *itemids, int *errcodes, size_t num) @@ -10739,11 +11727,16 @@ static void DCget_proxy(DC_PROXY *dst_proxy, const ZBX_DC_PROXY *src_proxy) dst_proxy->proxy_data_nextcheck = src_proxy->proxy_data_nextcheck; dst_proxy->proxy_tasks_nextcheck = src_proxy->proxy_tasks_nextcheck; dst_proxy->last_cfg_error_time = src_proxy->last_cfg_error_time; - dst_proxy->version = src_proxy->version; + zbx_strlcpy(dst_proxy->version_str, src_proxy->version_str, sizeof(dst_proxy->version_str)); + dst_proxy->version_int = src_proxy->version_int; + dst_proxy->compatibility = src_proxy->compatibility; dst_proxy->lastaccess = src_proxy->lastaccess; dst_proxy->auto_compress = src_proxy->auto_compress; dst_proxy->last_version_error_time = src_proxy->last_version_error_time; + dst_proxy->revision = src_proxy->revision; + dst_proxy->macro_revision = config->um_cache->revision; + if (NULL != (host = (const ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &src_proxy->hostid))) { zbx_strscpy(dst_proxy->host, host->host); @@ -11113,56 +12106,7 @@ int DCget_item_queue(zbx_vector_ptr_t *queue, int from, int to) /****************************************************************************** * * - * Purpose: check that functionids in trigger (recovery) expression * - * * - * Parameters: expression - [IN] trigger (recovery) expression * - * data - [IN] parsed and serialized expression * - * * - * Return value: SUCCEED - all functionids correspond to enabled items and * - * enabled hosts * - * FAIL - at least one item or host is disabled * - * * - ******************************************************************************/ -static int dc_trigger_items_hosts_enabled(const char *expression, const unsigned char *data) -{ - zbx_uint64_t functionid; - const ZBX_DC_ITEM *dc_item; - const ZBX_DC_FUNCTION *dc_function; - const ZBX_DC_HOST *dc_host; - int i, ret = FAIL; - zbx_vector_uint64_t functionids; - - zbx_vector_uint64_create(&functionids); - zbx_get_serialized_expression_functionids(expression, data, &functionids); - - for (i = 0; i < functionids.values_num; i++) - { - functionid = functionids.values[i]; - - if (NULL == (dc_function = (ZBX_DC_FUNCTION *)zbx_hashset_search(&config->functions, &functionid))) - goto out; - - if (NULL == (dc_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &dc_function->itemid))) - goto out; - - if (ITEM_STATUS_ACTIVE != dc_item->status) - goto out; - - if (NULL == (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid))) - goto out; - - if (HOST_STATUS_MONITORED != dc_host->status) - goto out; - } - - ret = SUCCEED; -out: - zbx_vector_uint64_destroy(&functionids); - - return ret; -} - -/****************************************************************************** + * Function: dc_status_update * * * * Purpose: check when status information stored in configuration cache was * * updated last time and update it if necessary * @@ -11197,10 +12141,17 @@ static void dc_status_update(void) ZBX_DC_HOST *dc_host, *dc_proxy_host; const ZBX_DC_ITEM *dc_item; const ZBX_DC_TRIGGER *dc_trigger; + int reset; if (0 != config->status->last_update && config->status->last_update + ZBX_STATUS_LIFETIME > time(NULL)) return; + + if (config->status->sync_ts != config->sync_ts) + reset = SUCCEED; + else + reset = FAIL; + /* reset global counters */ config->status->hosts_monitored = 0; @@ -11211,17 +12162,22 @@ static void dc_status_update(void) config->status->triggers_enabled_ok = 0; config->status->triggers_enabled_problem = 0; config->status->triggers_disabled = 0; - config->status->required_performance = 0.0; - /* loop over proxies to reset per-proxy host and required performance counters */ + if (SUCCEED == reset) + config->status->required_performance = 0.0; - zbx_hashset_iter_reset(&config->proxies, &iter); + /* loop over proxies to reset per-proxy host and required performance counters */ - while (NULL != (dc_proxy = (ZBX_DC_PROXY *)zbx_hashset_iter_next(&iter))) + if (SUCCEED == reset) { - dc_proxy->hosts_monitored = 0; - dc_proxy->hosts_not_monitored = 0; - dc_proxy->required_performance = 0.0; + zbx_hashset_iter_reset(&config->proxies, &iter); + + while (NULL != (dc_proxy = (ZBX_DC_PROXY *)zbx_hashset_iter_next(&iter))) + { + dc_proxy->hosts_monitored = 0; + dc_proxy->hosts_not_monitored = 0; + dc_proxy->required_performance = 0.0; + } } /* loop over hosts */ @@ -11243,25 +12199,33 @@ static void dc_status_update(void) config->status->hosts_monitored++; if (0 == dc_host->proxy_hostid) break; - if (NULL == (dc_proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, - &dc_host->proxy_hostid))) + + if (SUCCEED == reset) { - break; - } + if (NULL == (dc_proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, + &dc_host->proxy_hostid))) + { + break; + } - dc_proxy->hosts_monitored++; + dc_proxy->hosts_monitored++; + } break; case HOST_STATUS_NOT_MONITORED: config->status->hosts_not_monitored++; if (0 == dc_host->proxy_hostid) break; - if (NULL == (dc_proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, - &dc_host->proxy_hostid))) + + if (SUCCEED == reset) { - break; - } + if (NULL == (dc_proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, + &dc_host->proxy_hostid))) + { + break; + } - dc_proxy->hosts_not_monitored++; + dc_proxy->hosts_not_monitored++; + } break; } } @@ -11283,7 +12247,9 @@ static void dc_status_update(void) if (0 != dc_host->proxy_hostid) { - dc_proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &dc_host->proxy_hostid); + if (SUCCEED == reset) + dc_proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &dc_host->proxy_hostid); + dc_proxy_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_host->proxy_hostid); } @@ -11292,22 +12258,25 @@ static void dc_status_update(void) case ITEM_STATUS_ACTIVE: if (HOST_STATUS_MONITORED == dc_host->status) { - int delay; - char *delay_s; + if (SUCCEED == reset) + { + int delay; + char *delay_s; - delay_s = dc_expand_user_macros_dyn(dc_item->delay, &dc_item->hostid, 1, - ZBX_MACRO_ENV_NONSECURE); + delay_s = dc_expand_user_macros_dyn(dc_item->delay, &dc_item->hostid, 1, + ZBX_MACRO_ENV_NONSECURE); - if (SUCCEED == zbx_interval_preproc(delay_s, &delay, NULL, NULL) && - 0 != delay) - { - config->status->required_performance += 1.0 / delay; + if (SUCCEED == zbx_interval_preproc(delay_s, &delay, NULL, NULL) && + 0 != delay) + { + config->status->required_performance += 1.0 / delay; - if (NULL != dc_proxy) - dc_proxy->required_performance += 1.0 / delay; - } + if (NULL != dc_proxy) + dc_proxy->required_performance += 1.0 / delay; + } - zbx_free(delay_s); + zbx_free(delay_s); + } switch (dc_item->state) { @@ -11352,11 +12321,7 @@ static void dc_status_update(void) switch (dc_trigger->status) { case TRIGGER_STATUS_ENABLED: - if (SUCCEED == dc_trigger_items_hosts_enabled(dc_trigger->expression, - dc_trigger->expression_bin) && - (TRIGGER_RECOVERY_MODE_RECOVERY_EXPRESSION != - dc_trigger->recovery_mode || SUCCEED == dc_trigger_items_hosts_enabled( - dc_trigger->recovery_expression, dc_trigger->recovery_expression_bin))) + if (TRIGGER_FUNCTIONAL_TRUE == dc_trigger->functional) { switch (dc_trigger->value) { @@ -11381,6 +12346,7 @@ static void dc_status_update(void) } } + config->status->sync_ts = config->sync_ts; config->status->last_update = time(NULL); #undef ZBX_STATUS_LIFETIME @@ -11970,6 +12936,8 @@ void zbx_config_clean(zbx_config_t *cfg) ********************************************************************************/ int DCreset_interfaces_availability(zbx_vector_availability_ptr_t *interfaces) { +#define ZBX_INTERFACE_MOVE_TOLERANCE_INTERVAL (10 * SEC_PER_MIN) + ZBX_DC_HOST *host; ZBX_DC_INTERFACE *interface; zbx_hashset_iter_t iter; @@ -12004,7 +12972,7 @@ int DCreset_interfaces_availability(zbx_vector_availability_ptr_t *interfaces) if (NULL != (proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &host->proxy_hostid))) { /* SEC_PER_MIN is a tolerance interval, it was chosen arbitrarily */ - if (ZBX_PROXY_HEARTBEAT_FREQUENCY_MAX + SEC_PER_MIN >= now - proxy->lastaccess) + if (ZBX_INTERFACE_MOVE_TOLERANCE_INTERVAL >= now - proxy->lastaccess) continue; } @@ -12044,6 +13012,7 @@ int DCreset_interfaces_availability(zbx_vector_availability_ptr_t *interfaces) zabbix_log(LOG_LEVEL_DEBUG, "End of %s() interfaces:%d", __func__, interfaces->values_num); return 0 == interfaces->values_num ? FAIL : SUCCEED; +#undef ZBX_INTERFACE_MOVE_TOLERANCE_INTERVAL } /******************************************************************************* @@ -12372,17 +13341,20 @@ static char *dc_correlation_formula_dup(const zbx_dc_correlation_t *dc_correlati const zbx_dc_corr_condition_t *dc_condition; zbx_uint64_t last_id; - if (CONDITION_EVAL_TYPE_EXPRESSION == dc_correlation->evaltype || 0 == dc_correlation->conditions.values_num) + if (ZBX_ACTION_CONDITION_EVAL_TYPE_EXPRESSION == dc_correlation->evaltype || 0 == + dc_correlation->conditions.values_num) + { return zbx_strdup(NULL, dc_correlation->formula); + } dc_condition = (const zbx_dc_corr_condition_t *)dc_correlation->conditions.values[0]; switch (dc_correlation->evaltype) { - case CONDITION_EVAL_TYPE_OR: + case ZBX_ACTION_CONDITION_EVAL_TYPE_OR: op = " or"; break; - case CONDITION_EVAL_TYPE_AND: + case ZBX_ACTION_CONDITION_EVAL_TYPE_AND: op = " and"; break; } @@ -12832,14 +13804,14 @@ int zbx_dc_update_passive_proxy_nextcheck(zbx_uint64_t proxyid) * Purpose: retrieve proxyids for all cached proxies * * * ******************************************************************************/ -void zbx_dc_get_all_proxies(zbx_vector_cached_proxy_t *proxies) +void zbx_dc_get_all_proxies(zbx_vector_cached_proxy_ptr_t *proxies) { ZBX_DC_HOST_H *dc_host; zbx_hashset_iter_t iter; RDLOCK_CACHE; - zbx_vector_cached_proxy_reserve(proxies, (size_t)config->hosts_p.num_data); + zbx_vector_cached_proxy_ptr_reserve(proxies, (size_t)config->hosts_p.num_data); zbx_hashset_iter_reset(&config->hosts_p, &iter); while (NULL != (dc_host = (ZBX_DC_HOST_H *)zbx_hashset_iter_next(&iter))) @@ -12852,12 +13824,18 @@ void zbx_dc_get_all_proxies(zbx_vector_cached_proxy_t *proxies) proxy->hostid = dc_host->host_ptr->hostid; proxy->status = dc_host->host_ptr->status; - zbx_vector_cached_proxy_append(proxies, proxy); + zbx_vector_cached_proxy_ptr_append(proxies, proxy); } UNLOCK_CACHE; } +void zbx_cached_proxy_free(zbx_cached_proxy_t *proxy) +{ + zbx_free(proxy->name); + zbx_free(proxy); +} + int zbx_dc_get_proxy_name_type_by_id(zbx_uint64_t proxyid, int *status, char **name) { int ret = SUCCEED; @@ -13225,7 +14203,7 @@ void zbx_dc_get_trigger_dependencies(const zbx_vector_uint64_t *triggerids, zbx_ * Purpose: reschedules items that are processed by the target daemon * * * * Parameter: itemids - [IN] the item identifiers * - * nextcheck - [IN] the schedueld time * + * nextcheck - [IN] the scheduled time * * proxy_hostids - [OUT] the proxy_hostids of the given itemids * * (optional, can be NULL) * * * @@ -13344,8 +14322,7 @@ void zbx_dc_update_proxy(zbx_proxy_diff_t *diff) { int lost = 0; /* communication lost */ - if (0 != (diff->flags & - (ZBX_FLAGS_PROXY_DIFF_UPDATE_HEARTBEAT | ZBX_FLAGS_PROXY_DIFF_UPDATE_CONFIG))) + if (0 != (diff->flags & ZBX_FLAGS_PROXY_DIFF_UPDATE_CONFIG)) { int delay = diff->lastaccess - proxy->lastaccess; @@ -13363,8 +14340,14 @@ void zbx_dc_update_proxy(zbx_proxy_diff_t *diff) if (0 != (diff->flags & ZBX_FLAGS_PROXY_DIFF_UPDATE_VERSION)) { - if (proxy->version != diff->version) - proxy->version = diff->version; + if (0 != strcmp(proxy->version_str, diff->version_str)) + dc_strpool_replace(1, &proxy->version_str, diff->version_str); + + if (proxy->version_int != diff->version_int) + { + proxy->version_int = diff->version_int; + proxy->compatibility = diff->compatibility; + } else diff->flags &= (~ZBX_FLAGS_PROXY_DIFF_UPDATE_VERSION); } @@ -13467,7 +14450,7 @@ const char *zbx_dc_get_session_token(void) /****************************************************************************** * * - * Purpose: returns data session, creates a new session if none found * + * Purpose: return session, create a new session if none found * * * * Parameter: hostid - [IN] the host (proxy) identifier * * token - [IN] the session token (not NULL) * @@ -13513,6 +14496,56 @@ zbx_session_t *zbx_dc_get_or_create_session(zbx_uint64_t hostid, const char *tok /****************************************************************************** * * + * Purpose: update session revision/lastaccess in cache or create new session * + * if necessary * + * * + * Parameter: hostid - [IN] the host (proxy) identifier * + * token - [IN] the session token (not NULL) * + * session_config_revision - [IN] the session configuration * + * revision * + * dc_revision - [OUT] - the cached configuration revision * + * * + * Return value: The number of created sessions * + * * + ******************************************************************************/ +int zbx_dc_register_config_session(zbx_uint64_t hostid, const char *token, zbx_uint64_t session_config_revision, + zbx_dc_revision_t *dc_revision) +{ + zbx_session_t *session, session_local; + time_t now; + + now = time(NULL); + session_local.hostid = hostid; + session_local.token = token; + + RDLOCK_CACHE; + if (NULL != (session = (zbx_session_t *)zbx_hashset_search(&config->sessions[ZBX_SESSION_TYPE_CONFIG], + &session_local))) + { + /* one session cannot be updated at the same time by different processes, */ + /* so updating its properties without reallocating memory can be done with read lock */ + session->last_id = session_config_revision; + session_local.lastaccess = now; + } + *dc_revision = config->revision; + UNLOCK_CACHE; + + if (NULL != session) + return 0; + + session_local.last_id = session_config_revision; + session_local.lastaccess = now; + + WRLOCK_CACHE; + session_local.token = dc_strdup(token); + zbx_hashset_insert(&config->sessions[ZBX_SESSION_TYPE_CONFIG], &session_local, sizeof(session_local)); + UNLOCK_CACHE; + + return 1; /* a session was created */ +} + +/****************************************************************************** + * * * Purpose: removes data sessions not accessed for 25 hours * * * ******************************************************************************/ @@ -13829,6 +14862,138 @@ int DCget_proxy_lastaccess_by_name(const char *name, int *lastaccess, char **err /****************************************************************************** * * + * Purpose: get data of all proxies from configuration cache and pack into * + * JSON for LLD * + * * + * Parameter: data - [OUT] JSON with proxy data * + * error - [OUT] error message * + * * + * Return value: SUCCEED - interface data in JSON, 'data' is allocated * + * FAIL - proxy not found, 'error' message is allocated * + * * + * Comments: Allocates memory. * + * If there are no proxies, an empty JSON {"data":[]} is returned. * + * * + ******************************************************************************/ +int zbx_proxy_discovery_get(char **data, char **error) +{ + int i, ret = SUCCEED; + zbx_vector_cached_proxy_ptr_t proxies; + struct zbx_json json; + + WRLOCK_CACHE; + + dc_status_update(); + + UNLOCK_CACHE; + + zbx_json_initarray(&json, ZBX_JSON_STAT_BUF_LEN); + zbx_vector_cached_proxy_ptr_create(&proxies); + zbx_dc_get_all_proxies(&proxies); + + RDLOCK_CACHE; + + for (i = 0; i < proxies.values_num; i++) + { + zbx_cached_proxy_t *proxy; + const ZBX_DC_HOST *dc_host; + const ZBX_DC_PROXY *dc_proxy; + + proxy = proxies.values[i]; + + zbx_json_addobject(&json, NULL); + + zbx_json_addstring(&json, "name", proxy->name, ZBX_JSON_TYPE_STRING); + + if (HOST_STATUS_PROXY_PASSIVE == proxy->status) + zbx_json_addstring(&json, "passive", "true", ZBX_JSON_TYPE_INT); + else + zbx_json_addstring(&json, "passive", "false", ZBX_JSON_TYPE_INT); + + dc_host = DCfind_proxy(proxy->name); + + if (NULL == dc_host) + { + *error = zbx_dsprintf(*error, "Proxy \"%s\" not found in configuration cache.", proxy->name); + ret = FAIL; + goto clean; + } + else + { + unsigned int encryption; + + if (HOST_STATUS_PROXY_PASSIVE == proxy->status) + encryption = dc_host->tls_connect; + else + encryption = dc_host->tls_accept; + + if (0 < (encryption & ZBX_TCP_SEC_UNENCRYPTED)) + zbx_json_addstring(&json, "unencrypted", "true", ZBX_JSON_TYPE_INT); + else + zbx_json_addstring(&json, "unencrypted", "false", ZBX_JSON_TYPE_INT); + + if (0 < (encryption & ZBX_TCP_SEC_TLS_PSK)) + zbx_json_addstring(&json, "psk", "true", ZBX_JSON_TYPE_INT); + else + zbx_json_addstring(&json, "psk", "false", ZBX_JSON_TYPE_INT); + + if (0 < (encryption & ZBX_TCP_SEC_TLS_CERT)) + zbx_json_addstring(&json, "cert", "true", ZBX_JSON_TYPE_INT); + else + zbx_json_addstring(&json, "cert", "false", ZBX_JSON_TYPE_INT); + + zbx_json_adduint64(&json, "items", dc_host->items_active_normal + + dc_host->items_active_notsupported); + + if (NULL != (dc_proxy = (const ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, + &dc_host->hostid))) + { + if (1 == dc_proxy->auto_compress) + zbx_json_addstring(&json, "compression", "true", ZBX_JSON_TYPE_INT); + else + zbx_json_addstring(&json, "compression", "false", ZBX_JSON_TYPE_INT); + + zbx_json_addstring(&json, "version", dc_proxy->version_str, ZBX_JSON_TYPE_STRING); + + zbx_json_adduint64(&json, "compatibility", dc_proxy->compatibility); + + if (0 < dc_proxy->lastaccess) + zbx_json_addint64(&json, "last_seen", time(NULL) - dc_proxy->lastaccess); + else + zbx_json_addint64(&json, "last_seen", -1); + + zbx_json_adduint64(&json, "hosts", dc_proxy->hosts_monitored); + + zbx_json_addfloat(&json, "requiredperformance", dc_proxy->required_performance); + } + else + { + *error = zbx_dsprintf(*error, "Proxy \"%s\" not found in configuration cache.", + proxy->name); + ret = FAIL; + goto clean; + } + } + zbx_json_close(&json); + } +clean: + UNLOCK_CACHE; + + if (SUCCEED == ret) + { + zbx_json_close(&json); + *data = zbx_strdup(NULL, json.buffer); + } + + zbx_json_free(&json); + zbx_vector_cached_proxy_ptr_clear_ext(&proxies, zbx_cached_proxy_free); + zbx_vector_cached_proxy_ptr_destroy(&proxies); + + return ret; +} + +/****************************************************************************** + * * * Purpose: returns server/proxy instance id * * * * Return value: the instance id * @@ -14321,7 +15486,396 @@ static void dc_reschedule_items(const zbx_hashset_t *activated_hosts) zbx_vector_item_delay_destroy(&items); } +/****************************************************************************** + * * + * Purpose: reschedule httptests on hosts that were re-enabled or unassigned * + * from proxy * + * * + * Comments: Cache is not locked for read access because this function is * + * called from configuration syncer and nobody else can add/remove * + * objects or change their configuration. * + * * + ******************************************************************************/ +static void dc_reschedule_httptests(zbx_hashset_t *activated_hosts) +{ + zbx_vector_dc_httptest_ptr_t httptests; + zbx_hashset_iter_t iter; + int i; + zbx_uint64_t *phostid; + ZBX_DC_HOST *host; + time_t now; + + zbx_vector_dc_httptest_ptr_create(&httptests); + + now = time(NULL); + + zbx_hashset_iter_reset(activated_hosts, &iter); + while (NULL != (phostid = (zbx_uint64_t *)zbx_hashset_iter_next(&iter))) + { + if (NULL == (host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, phostid))) + continue; + + for (i = 0; i < host->httptests.values_num; i++) + { + if (ZBX_LOC_NOWHERE != host->httptests.values[i]->location) + continue; + + zbx_vector_dc_httptest_ptr_append(&httptests, host->httptests.values[i]); + } + } + + if (0 != httptests.values_num) + { + WRLOCK_CACHE; + + for (i = 0; i < httptests.values_num; i++) + { + zbx_dc_httptest_t *httptest = httptests.values[i]; + + httptest->nextcheck = dc_calculate_nextcheck(httptest->httptestid, httptest->delay, now); + dc_httptest_queue(httptest); + } + + UNLOCK_CACHE; + } + + zbx_vector_dc_httptest_ptr_destroy(&httptests); +} + + +/****************************************************************************** + * * + * Purpose: get next drule to be processed * + * * + * Parameter: now - [IN] the current timestamp * + * druleid - [OUT] the id of drule to be processed * + * nextcheck - [OUT] the timestamp of next drule to be processed, * + * if there is no rule to be processed now and * + * the queue is not empty. 0 otherwise * + * * + * Return value: SUCCEED - the drule id was returned successfully * + * FAIL - no drules are scheduled at current time * + * * + ******************************************************************************/ +int zbx_dc_drule_next(time_t now, zbx_uint64_t *druleid, time_t *nextcheck) +{ + zbx_binary_heap_elem_t *elem; + zbx_dc_drule_t *drule; + int ret = FAIL; + + *nextcheck = 0; + + WRLOCK_CACHE; + + if (FAIL == zbx_binary_heap_empty(&config->drule_queue)) + { + elem = zbx_binary_heap_find_min(&config->drule_queue); + drule = (zbx_dc_drule_t *)elem->data; + + if (drule->nextcheck <= now) + { + zbx_binary_heap_remove_min(&config->drule_queue); + *druleid = drule->druleid; + drule->location = ZBX_LOC_POLLER; + ret = SUCCEED; + } + else + *nextcheck = drule->nextcheck; + } + + UNLOCK_CACHE; + + return ret; +} + +/****************************************************************************** + * * + * Purpose: queue drule to be processed according to the delay * + * * + * Parameter: now - [IN] the current timestamp * + * druleid - [IN] the id of drule to be queued * + * delay - [IN] the number of seconds between drule processing * + * * + ******************************************************************************/ +void zbx_dc_drule_queue(time_t now, zbx_uint64_t druleid, int delay) +{ + zbx_dc_drule_t *drule; + + WRLOCK_CACHE; + + if (NULL != (drule = (zbx_dc_drule_t *)zbx_hashset_search(&config->drules, &druleid))) + { + drule->delay = delay; + drule->nextcheck = dc_calculate_nextcheck(drule->druleid, drule->delay, now); + dc_drule_queue(drule); + } + + UNLOCK_CACHE; +} + +/****************************************************************************** + * * + * Purpose: get next httptest to be processed * + * * + * Parameter: now - [IN] the current timestamp * + * httptestid - [OUT] the id of httptest to be processed * + * nextcheck - [OUT] the timestamp of next httptest to be * + * processed, if there is no httptest to be * + * processed now and the queue is not empty. * + * 0 - otherwise * + * * + * Return value: SUCCEED - the httptest id was returned successfully * + * FAIL - no httptests are scheduled at current time * + * * + ******************************************************************************/ +int zbx_dc_httptest_next(time_t now, zbx_uint64_t *httptestid, time_t *nextcheck) +{ + zbx_binary_heap_elem_t *elem; + zbx_dc_httptest_t *httptest; + int ret = FAIL; + ZBX_DC_HOST *dc_host; + + *nextcheck = 0; + + WRLOCK_CACHE; + + while (FAIL == zbx_binary_heap_empty(&config->httptest_queue)) + { + elem = zbx_binary_heap_find_min(&config->httptest_queue); + httptest = (zbx_dc_httptest_t *)elem->data; + + if (httptest->nextcheck <= now) + { + zbx_binary_heap_remove_min(&config->httptest_queue); + httptest->location = ZBX_LOC_NOWHERE; + + if (NULL == (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &httptest->hostid))) + continue; + + if (HOST_STATUS_MONITORED != dc_host->status || 0 != dc_host->proxy_hostid) + continue; + + if (HOST_MAINTENANCE_STATUS_ON == dc_host->maintenance_status && + MAINTENANCE_TYPE_NODATA == dc_host->maintenance_type) + { + httptest->nextcheck = dc_calculate_nextcheck(httptest->httptestid, httptest->delay, now); + dc_httptest_queue(httptest); + + continue; + } + + httptest->location = ZBX_LOC_POLLER; + *httptestid = httptest->httptestid; + + ret = SUCCEED; + } + else + *nextcheck = httptest->nextcheck; + + break; + } + + UNLOCK_CACHE; + + return ret; +} + +/****************************************************************************** + * * + * Purpose: queue httptest to be processed according to the delay * + * * + * Parameter: now - [IN] the current timestamp * + * httptestid - [IN] the id of httptest to be queued * + * delay - [IN] the number of seconds between httptest * + * processing * + * * + ******************************************************************************/ +void zbx_dc_httptest_queue(time_t now, zbx_uint64_t httptestid, int delay) +{ + zbx_dc_httptest_t *httptest; + + WRLOCK_CACHE; + + if (NULL != (httptest = (zbx_dc_httptest_t *)zbx_hashset_search(&config->httptests, &httptestid))) + { + httptest->delay = delay; + httptest->nextcheck = dc_calculate_nextcheck(httptest->httptestid, httptest->delay, now); + dc_httptest_queue(httptest); + } + + UNLOCK_CACHE; +} + +/****************************************************************************** + * * + * Purpose: get the configuration revision received from server * + * * + * Comments: The revision is accessed without locking because no other process* + * can access it at the same time. * + * * + ******************************************************************************/ +zbx_uint64_t zbx_dc_get_received_revision(void) +{ + return config->revision.upstream; +} + +/****************************************************************************** + * * + * Purpose: cache the configuration revision received from server * + * * + * Comments: The revision is updated without locking because no other process * + * can access it at the same time. * + * * + ******************************************************************************/ +void zbx_dc_update_received_revision(zbx_uint64_t revision) +{ + config->revision.upstream = revision; +} + +/****************************************************************************** + * * + * Purpose: get hosts/httptests for proxy configuration update * + * * + * Parameters: proxy_hostid - [IN] * + * revision - [IN] the current proxy configuration revision* + * hostids - [OUT] the monitored hosts * + * updated_hostids - [OUT] the hosts updated since specified * + * configuration revision, sorted * + * removed_hostids - [OUT] the hosts removed since specified * + * configuration revision, sorted * + * httptestids - [OUT] the web scenarios monitored by proxy * + * * + ******************************************************************************/ +void zbx_dc_get_proxy_config_updates(zbx_uint64_t proxy_hostid, zbx_uint64_t revision, zbx_vector_uint64_t *hostids, + zbx_vector_uint64_t *updated_hostids, zbx_vector_uint64_t *removed_hostids, + zbx_vector_uint64_t *httptestids) +{ + ZBX_DC_PROXY *proxy; + + RDLOCK_CACHE; + + if (NULL != (proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &proxy_hostid))) + { + int i, j; + + zbx_vector_uint64_reserve(hostids, (size_t)proxy->hosts.values_num); + + for (i = 0; i < proxy->hosts.values_num; i++) + { + ZBX_DC_HOST *host = proxy->hosts.values[i]; + + zbx_vector_uint64_append(hostids, host->hostid); + + if (host->revision > revision) + { + zbx_vector_uint64_append(updated_hostids, host->hostid); + + for (j = 0; j < host->httptests.values_num; j++) + zbx_vector_uint64_append(httptestids, host->httptests.values[j]->httptestid); + } + } + + /* skip when full sync */ + if (0 != revision) + { + for (i = 0; i < proxy->removed_hosts.values_num; ) + { + if (proxy->removed_hosts.values[i].revision > revision) + { + zbx_vector_uint64_append(removed_hostids, proxy->removed_hosts.values[i].hostid); + + /* this operation can be done with read lock: */ + /* - removal from vector does not allocate/free memory */ + /* - two configuration requests for the same proxy cannot be */ + /* processed at the same time */ + /* - configuration syncer uses write lock to update */ + /* removed hosts on proxy */ + zbx_vector_host_rev_remove_noorder(&proxy->removed_hosts, i); + } + else + i++; + } + } + } + + UNLOCK_CACHE; + + zbx_vector_uint64_sort(hostids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); + zbx_vector_uint64_sort(updated_hostids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); + zbx_vector_uint64_sort(removed_hostids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); + zbx_vector_uint64_sort(httptestids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); +} + +void zbx_dc_get_macro_updates(const zbx_vector_uint64_t *hostids, const zbx_vector_uint64_t *updated_hostids, + zbx_uint64_t revision, zbx_vector_uint64_t *macro_hostids, int *global, + zbx_vector_uint64_t *del_macro_hostids) +{ + zbx_vector_uint64_t hostids_tmp, globalids; + zbx_uint64_t globalhostid = 0; + + /* force full sync for updated hosts (in the case host was assigned to proxy) */ + /* and revision based sync for the monitored hosts (except updated hosts that */ + /* were already synced) */ + + zbx_vector_uint64_create(&hostids_tmp); + if (0 != hostids->values_num) + { + zbx_vector_uint64_append_array(&hostids_tmp, hostids->values, hostids->values_num); + zbx_vector_uint64_setdiff(&hostids_tmp, updated_hostids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); + } + + zbx_vector_uint64_create(&globalids); + + RDLOCK_CACHE; + + /* check revision of global macro 'host' (hostid 0) */ + um_cache_get_macro_updates(config->um_cache, &globalhostid, 1, revision, &globalids, del_macro_hostids); + + if (0 != hostids_tmp.values_num) + { + um_cache_get_macro_updates(config->um_cache, hostids_tmp.values, hostids_tmp.values_num, revision, + macro_hostids, del_macro_hostids); + } + + if (0 != updated_hostids->values_num) + { + um_cache_get_macro_updates(config->um_cache, updated_hostids->values, updated_hostids->values_num, 0, + macro_hostids, del_macro_hostids); + } + + UNLOCK_CACHE; + + *global = (0 < globalids.values_num ? SUCCEED : FAIL); + + if (0 != macro_hostids->values_num) + zbx_vector_uint64_sort(macro_hostids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); + + if (0 != del_macro_hostids->values_num) + zbx_vector_uint64_sort(del_macro_hostids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); + + zbx_vector_uint64_destroy(&globalids); + zbx_vector_uint64_destroy(&hostids_tmp); +} + +void zbx_dc_get_unused_macro_templates(zbx_hashset_t *templates, const zbx_vector_uint64_t *hostids, + zbx_vector_uint64_t *templateids) +{ + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + + RDLOCK_CACHE; + + um_cache_get_unused_templates(config->um_cache, templates, hostids, templateids); + + UNLOCK_CACHE; + + if (0 != templateids->values_num) + zbx_vector_uint64_sort(templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); + + zabbix_log(LOG_LEVEL_DEBUG, "End of %s() templateids_num:%d", __func__, templateids->values_num); +} + #ifdef HAVE_TESTS # include "../../../tests/libs/zbxdbcache/dc_item_poller_type_update_test.c" # include "../../../tests/libs/zbxdbcache/dc_function_calculate_nextcheck_test.c" #endif + diff --git a/src/libs/zbxdbcache/dbconfig.h b/src/libs/zbxdbcache/dbconfig.h index bc1d60585c2..b9d3e5a77e2 100644 --- a/src/libs/zbxdbcache/dbconfig.h +++ b/src/libs/zbxdbcache/dbconfig.h @@ -24,6 +24,7 @@ #include "zbxalgo.h" #include "dbcache.h" #include "user_macro.h" +#include "zbxversion.h" #define ZBX_MAINTENANCE_IDLE 0 #define ZBX_MAINTENANCE_RUNNING 1 @@ -41,8 +42,8 @@ typedef struct const unsigned char *expression_bin; const unsigned char *recovery_expression_bin; int lastchange; - zbx_uint32_t revision; - zbx_uint32_t timer_revision; + zbx_uint64_t revision; + zbx_uint64_t timer_revision; unsigned char topoindex; unsigned char priority; unsigned char type; @@ -84,14 +85,26 @@ typedef struct zbx_uint64_t itemid; const char *function; const char *parameter; - zbx_uint32_t revision; - zbx_uint32_t timer_revision; + zbx_uint64_t revision; + zbx_uint64_t timer_revision; unsigned char type; } ZBX_DC_FUNCTION; typedef struct { + zbx_vector_uint64_pair_t dep_itemids; +} +ZBX_DC_MASTERITEM; + +typedef struct +{ + zbx_vector_ptr_t preproc_ops; +} +ZBX_DC_PREPROCITEM; + +typedef struct +{ zbx_uint64_t itemid; zbx_uint64_t hostid; zbx_uint64_t interfaceid; @@ -107,7 +120,7 @@ typedef struct int nextcheck; int mtime; int data_expected_from; - zbx_uint32_t revision; + zbx_uint64_t revision; unsigned char type; unsigned char value_type; unsigned char poller_type; @@ -120,6 +133,8 @@ typedef struct unsigned char queue_priority; unsigned char update_triggers; zbx_uint64_t templateid; + ZBX_DC_PREPROCITEM *preproc_item; + ZBX_DC_MASTERITEM *master_item; zbx_vector_ptr_t tags; } @@ -259,21 +274,6 @@ ZBX_DC_CALCITEM; typedef struct { - zbx_uint64_t itemid; - zbx_vector_uint64_pair_t dep_itemids; -} -ZBX_DC_MASTERITEM; - -typedef struct -{ - zbx_uint64_t itemid; - int update_time; - zbx_vector_ptr_t preproc_ops; -} -ZBX_DC_PREPROCITEM; - -typedef struct -{ zbx_uint64_t itemid; const char *timeout; const char *url; @@ -321,6 +321,42 @@ ZBX_PTR_VECTOR_DECL(dc_item_ptr, ZBX_DC_ITEM *) typedef struct { + zbx_uint64_t httptestid; + zbx_uint64_t hostid; + time_t nextcheck; + int delay; + unsigned char status; + unsigned char location; + zbx_uint64_t revision; +} +zbx_dc_httptest_t; + +typedef struct +{ + zbx_uint64_t httptest_fieldid; + zbx_uint64_t httptestid; +} +zbx_dc_httptest_field_t; + +typedef struct +{ + zbx_uint64_t httpstepid; + zbx_uint64_t httptestid; + zbx_uint64_t revision; +} +zbx_dc_httpstep_t; + +typedef struct +{ + zbx_uint64_t httpstep_fieldid; + zbx_uint64_t httpstepid; +} +zbx_dc_httpstep_field_t; + +ZBX_PTR_VECTOR_DECL(dc_httptest_ptr, zbx_dc_httptest_t *) + +typedef struct +{ zbx_uint64_t hostid; zbx_uint64_t proxy_hostid; zbx_uint64_t items_active_normal; /* On enabled hosts these two fields store number of enabled */ @@ -335,15 +371,12 @@ typedef struct const char *name; int maintenance_from; int data_expected_from; - zbx_uint32_t revision; + zbx_uint64_t revision; unsigned char maintenance_status; unsigned char maintenance_type; unsigned char status; - /* flag to force update for all items */ - unsigned char update_items; - /* 'tls_connect' and 'tls_accept' must be respected even if encryption support is not compiled in */ unsigned char tls_connect; unsigned char tls_accept; @@ -355,10 +388,14 @@ typedef struct zbx_vector_ptr_t interfaces_v; /* for quick finding of all host interfaces in */ /* 'config->interfaces' hashset */ - zbx_vector_dc_item_ptr_t active_items; + + zbx_vector_dc_httptest_ptr_t httptests; + zbx_vector_dc_item_ptr_t items; } ZBX_DC_HOST; +ZBX_PTR_VECTOR_DECL(dc_host_ptr, ZBX_DC_HOST *) + typedef struct { const char *host; @@ -388,24 +425,39 @@ ZBX_DC_HOST_H; typedef struct { - zbx_uint64_t hostid; - zbx_uint64_t hosts_monitored; /* number of enabled hosts assigned to proxy */ - zbx_uint64_t hosts_not_monitored; /* number of disabled hosts assigned to proxy */ - double required_performance; - int proxy_config_nextcheck; - int proxy_data_nextcheck; - int proxy_tasks_nextcheck; - int nextcheck; - int lastaccess; - int proxy_delay; - zbx_proxy_suppress_t nodata_win; - int last_cfg_error_time; /* time when passive proxy misconfiguration error was seen */ - /* or 0 if no error */ - int version; - unsigned char location; - unsigned char auto_compress; - const char *proxy_address; - int last_version_error_time; + zbx_uint64_t hostid; + zbx_uint64_t revision; +} +zbx_host_rev_t; + +ZBX_VECTOR_DECL(host_rev, zbx_host_rev_t) + +typedef struct +{ + zbx_uint64_t hostid; + zbx_uint64_t hosts_monitored; /* number of enabled hosts assigned to proxy */ + zbx_uint64_t hosts_not_monitored; /* number of disabled hosts assigned to proxy */ + double required_performance; + int proxy_config_nextcheck; + int proxy_data_nextcheck; + int proxy_tasks_nextcheck; + int nextcheck; + int lastaccess; + int proxy_delay; + zbx_proxy_suppress_t nodata_win; + int last_cfg_error_time; /* time when passive proxy misconfiguration error was seen */ + /* or 0 if no error */ + const char *version_str; + int version_int; + zbx_proxy_compatibility_t compatibility; + unsigned char location; + unsigned char auto_compress; + const char *proxy_address; + int last_version_error_time; + zbx_uint64_t revision; + + zbx_vector_dc_host_ptr_t hosts; + zbx_vector_host_rev_t removed_hosts; } ZBX_DC_PROXY; @@ -550,6 +602,7 @@ typedef struct /* disabled then trigger is counted as disabled) */ double required_performance; /* required performance of server (values per second) */ time_t last_update; + int sync_ts; } ZBX_DC_STATUS; @@ -771,6 +824,25 @@ zbx_dc_macro_kv_t; typedef struct { + zbx_uint64_t druleid; + zbx_uint64_t proxy_hostid; + time_t nextcheck; + int delay; + unsigned char status; + unsigned char location; + zbx_uint64_t revision; +} +zbx_dc_drule_t; + +typedef struct +{ + zbx_uint64_t dcheckid; + zbx_uint64_t druleid; +} +zbx_dc_dcheck_t; + +typedef struct +{ /* timestamp of the last host availability diff sent to sever, used only by proxies */ int availability_diff_ts; int proxy_lastaccess_ts; @@ -780,8 +852,7 @@ typedef struct unsigned int internal_actions; /* number of enabled internal actions */ unsigned int auto_registration_actions; /* number of enabled auto resistration actions */ - zbx_uint32_t revision; - zbx_uint32_t expression_revision; + zbx_dc_revision_t revision; /* maintenance processing management */ unsigned char maintenance_update; /* flag to trigger maintenance update by timers */ @@ -808,8 +879,6 @@ typedef struct zbx_hashset_t simpleitems; zbx_hashset_t jmxitems; zbx_hashset_t calcitems; - zbx_hashset_t masteritems; - zbx_hashset_t preprocitems; zbx_hashset_t httpitems; zbx_hashset_t scriptitems; zbx_hashset_t functions; @@ -858,10 +927,19 @@ typedef struct zbx_hashset_t psks; /* for keeping PSK-identity and PSK pairs and for searching */ /* by PSK identity */ #endif + zbx_hashset_t data_sessions; + zbx_hashset_t drules; + zbx_hashset_t dchecks; + zbx_hashset_t httptests; + zbx_hashset_t httptest_fields; + zbx_hashset_t httpsteps; + zbx_hashset_t httpstep_fields; zbx_hashset_t sessions[ZBX_SESSION_TYPE_COUNT]; zbx_binary_heap_t queues[ZBX_POLLER_TYPE_COUNT]; zbx_binary_heap_t pqueue; zbx_binary_heap_t trigger_queue; + zbx_binary_heap_t drule_queue; + zbx_binary_heap_t httptest_queue; /* web scenario queue */ ZBX_DC_CONFIG_TABLE *config; ZBX_DC_STATUS *status; zbx_hashset_t strpool; @@ -927,8 +1005,7 @@ char *dc_expand_user_macros(const char *text, const zbx_uint64_t *hostids, int h #define ZBX_TRIGGER_TIMER_FUNCTION_TREND 0x0004 #define ZBX_TRIGGER_TIMER_FUNCTION (ZBX_TRIGGER_TIMER_FUNCTION_TIME | ZBX_TRIGGER_TIMER_FUNCTION_TREND) - -zbx_um_cache_t *um_cache_sync(zbx_um_cache_t *cache, zbx_uint32_t revision, zbx_dbsync_t *gmacros, +zbx_um_cache_t *um_cache_sync(zbx_um_cache_t *cache, zbx_uint64_t revision, zbx_dbsync_t *gmacros, zbx_dbsync_t *hmacros, zbx_dbsync_t *htmpls); #endif diff --git a/src/libs/zbxdbcache/dbconfig_dump.c b/src/libs/zbxdbcache/dbconfig_dump.c index d7847bd10b2..95f1876ade7 100644 --- a/src/libs/zbxdbcache/dbconfig_dump.c +++ b/src/libs/zbxdbcache/dbconfig_dump.c @@ -33,6 +33,7 @@ static void DCdump_config(void) if (NULL == config->config) goto out; + zabbix_log(LOG_LEVEL_TRACE, "revision:" ZBX_FS_UI64, config->revision.config_table); zabbix_log(LOG_LEVEL_TRACE, "discovery_groupid:" ZBX_FS_UI64, config->config->discovery_groupid); zabbix_log(LOG_LEVEL_TRACE, "snmptrap_logging:%hhu", config->config->snmptrap_logging); zabbix_log(LOG_LEVEL_TRACE, "default_inventory_mode:%d", config->config->default_inventory_mode); @@ -99,7 +100,7 @@ static void DCdump_hosts(void) int j; host = (ZBX_DC_HOST *)index.values[i]; - zabbix_log(LOG_LEVEL_TRACE, "hostid:" ZBX_FS_UI64 " host:'%s' name:'%s' status:%u revision:%u", + zabbix_log(LOG_LEVEL_TRACE, "hostid:" ZBX_FS_UI64 " host:'%s' name:'%s' status:%u revision:" ZBX_FS_UI64, host->hostid, host->host, host->name, host->status, host->revision); zabbix_log(LOG_LEVEL_TRACE, " proxy_hostid:" ZBX_FS_UI64, host->proxy_hostid); @@ -128,12 +129,16 @@ static void DCdump_hosts(void) zabbix_log(LOG_LEVEL_TRACE, " interfaceid:" ZBX_FS_UI64, interface->interfaceid); } - for (j = 0; j < host->active_items.values_num; j++) + zabbix_log(LOG_LEVEL_TRACE, " httptests:"); + for (j = 0; j < host->httptests.values_num; j++) { - ZBX_DC_ITEM *item = host->active_items.values[j]; - - zabbix_log(LOG_LEVEL_TRACE, " itemid:" ZBX_FS_UI64, item->itemid); + zabbix_log(LOG_LEVEL_TRACE, " httptestid:" ZBX_FS_UI64, + host->httptests.values[j]->httptestid); } + + zabbix_log(LOG_LEVEL_TRACE, " items:"); + for (j = 0; j < host->items.values_num; j++) + zabbix_log(LOG_LEVEL_TRACE, " itemid:" ZBX_FS_UI64, host->items.values[j]->itemid); } zbx_vector_ptr_destroy(&index); @@ -204,7 +209,7 @@ static void DCdump_proxies(void) ZBX_DC_PROXY *proxy; zbx_hashset_iter_t iter; zbx_vector_ptr_t index; - int i; + int i, j; zabbix_log(LOG_LEVEL_TRACE, "In %s()", __func__); @@ -219,10 +224,20 @@ static void DCdump_proxies(void) for (i = 0; i < index.values_num; i++) { proxy = (ZBX_DC_PROXY *)index.values[i]; - zabbix_log(LOG_LEVEL_TRACE, "hostid:" ZBX_FS_UI64 " location:%u", proxy->hostid, proxy->location); + zabbix_log(LOG_LEVEL_TRACE, "hostid:" ZBX_FS_UI64 " location:%u revision:" ZBX_FS_UI64, proxy->hostid, + proxy->location, proxy->revision); zabbix_log(LOG_LEVEL_TRACE, " proxy_address:'%s'", proxy->proxy_address); zabbix_log(LOG_LEVEL_TRACE, " compress:%d", proxy->auto_compress); zabbix_log(LOG_LEVEL_TRACE, " lastaccess:%d", proxy->lastaccess); + + zabbix_log(LOG_LEVEL_TRACE, " hosts:%d", proxy->hosts.values_num); + for (j = 0; j < proxy->hosts.values_num; j++) + zabbix_log(LOG_LEVEL_TRACE, " hostid:" ZBX_FS_UI64, proxy->hosts.values[j]->hostid); + + zabbix_log(LOG_LEVEL_TRACE, " removed hosts:%d", proxy->removed_hosts.values_num); + for (j = 0; j < proxy->removed_hosts.values_num; j++) + zabbix_log(LOG_LEVEL_TRACE, " hostid:" ZBX_FS_UI64 " revision:" ZBX_FS_UI64, + proxy->removed_hosts.values[j].hostid, proxy->removed_hosts.values[j].revision); } zbx_vector_ptr_destroy(&index); @@ -503,7 +518,6 @@ static void DCdump_preprocitem(const ZBX_DC_PREPROCITEM *preprocitem) int i; zabbix_log(LOG_LEVEL_TRACE, " preprocessing:"); - zabbix_log(LOG_LEVEL_TRACE, " update_time:%d", preprocitem->update_time); for (i = 0; i < preprocitem->preproc_ops.values_num; i++) { @@ -567,8 +581,6 @@ static void DCdump_items(void) {&config->simpleitems, (zbx_dc_dump_func_t)DCdump_simpleitem}, {&config->jmxitems, (zbx_dc_dump_func_t)DCdump_jmxitem}, {&config->calcitems, (zbx_dc_dump_func_t)DCdump_calcitem}, - {&config->masteritems, (zbx_dc_dump_func_t)DCdump_masteritem}, - {&config->preprocitems, (zbx_dc_dump_func_t)DCdump_preprocitem}, {&config->httpitems, (zbx_dc_dump_func_t)DCdump_httpitem}, {&config->scriptitems, (zbx_dc_dump_func_t)DCdump_scriptitem}, }; @@ -586,7 +598,7 @@ static void DCdump_items(void) for (i = 0; i < index.values_num; i++) { item = (ZBX_DC_ITEM *)index.values[i]; - zabbix_log(LOG_LEVEL_TRACE, "itemid:" ZBX_FS_UI64 " hostid:" ZBX_FS_UI64 " key:'%s' revision:%u", + zabbix_log(LOG_LEVEL_TRACE, "itemid:" ZBX_FS_UI64 " hostid:" ZBX_FS_UI64 " key:'%s' revision:" ZBX_FS_UI64, item->itemid, item->hostid, item->key, item->revision); zabbix_log(LOG_LEVEL_TRACE, " type:%u value_type:%u", item->type, item->value_type); zabbix_log(LOG_LEVEL_TRACE, " interfaceid:" ZBX_FS_UI64, item->interfaceid); @@ -607,6 +619,12 @@ static void DCdump_items(void) trace_items[j].dump_func(ptr); } + if (NULL != item->master_item) + DCdump_masteritem(item->master_item); + + if (NULL != item->preproc_item) + DCdump_preprocitem(item->preproc_item); + if (0 != item->tags.values_num) DCdump_item_tags(item); @@ -715,41 +733,6 @@ static void DCdump_item_discovery(void) zabbix_log(LOG_LEVEL_TRACE, "End of %s()", __func__); } -static void DCdump_master_items(void) -{ - ZBX_DC_MASTERITEM *master_item; - zbx_hashset_iter_t iter; - int i, j; - zbx_vector_ptr_t index; - - zabbix_log(LOG_LEVEL_TRACE, "In %s()", __func__); - - zbx_vector_ptr_create(&index); - zbx_hashset_iter_reset(&config->masteritems, &iter); - - while (NULL != (master_item = (ZBX_DC_MASTERITEM *)zbx_hashset_iter_next(&iter))) - zbx_vector_ptr_append(&index, master_item); - - zbx_vector_ptr_sort(&index, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC); - - for (i = 0; i < index.values_num; i++) - { - master_item = (ZBX_DC_MASTERITEM *)index.values[i]; - zabbix_log(LOG_LEVEL_TRACE, "master itemid:" ZBX_FS_UI64, master_item->itemid); - - for (j = 0; j < master_item->dep_itemids.values_num; j++) - { - zabbix_log(LOG_LEVEL_TRACE, " itemid:" ZBX_FS_UI64 " flags:" ZBX_FS_UI64, - master_item->dep_itemids.values[j].first, - master_item->dep_itemids.values[j].second); - } - } - - zbx_vector_ptr_destroy(&index); - - zabbix_log(LOG_LEVEL_TRACE, "End of %s()", __func__); -} - static void DCdump_prototype_items(void) { ZBX_DC_PROTOTYPE_ITEM *proto_item; @@ -800,7 +783,7 @@ static void DCdump_functions(void) { function = (ZBX_DC_FUNCTION *)index.values[i]; zabbix_log(LOG_LEVEL_DEBUG, "functionid:" ZBX_FS_UI64 " triggerid:" ZBX_FS_UI64 " itemid:" - ZBX_FS_UI64 " function:'%s' parameter:'%s' type:%u timer_revision:%u", + ZBX_FS_UI64 " function:'%s' parameter:'%s' type:%u timer_revision:" ZBX_FS_UI64, function->functionid, function->triggerid, function->itemid, function->function, function->parameter, function->type, function->timer_revision); @@ -937,7 +920,7 @@ static void DCdump_expressions(void) zabbix_log(LOG_LEVEL_TRACE, "In %s()", __func__); - zabbix_log(LOG_LEVEL_TRACE, "expression_revision:%u", config->expression_revision); + zabbix_log(LOG_LEVEL_TRACE, "expression_revision:" ZBX_FS_UI64, config->revision.expression); zbx_vector_ptr_create(&index); zbx_hashset_iter_reset(&config->expressions, &iter); @@ -1315,9 +1298,155 @@ static void DCdump_maintenances(void) zabbix_log(LOG_LEVEL_TRACE, "End of %s()", __func__); } +/* stringpool dumping is disabled by default to avoid leaking secret macro data */ +#ifdef HAVE_TESTS +static int strpool_compare(const void *v1, const void *v2) +{ + const char *s1 = *(const char * const *)v1 + sizeof(zbx_uint32_t); + const char *s2 = *(const char * const *)v2 + sizeof(zbx_uint32_t); + + return strcmp(s1, s2); +} + +static void DCdump_strpool() +{ + zbx_hashset_iter_t iter; + zbx_vector_ptr_t records; + char *record; + int i; + + zabbix_log(LOG_LEVEL_TRACE, "In %s()", __func__); + + zbx_vector_ptr_create(&records); + zbx_hashset_iter_reset(&config->strpool, &iter); + + while (NULL != (record = (char *)zbx_hashset_iter_next(&iter))) + zbx_vector_ptr_append(&records, record); + + zbx_vector_ptr_sort(&records, strpool_compare); + + for (i = 0; i < records.values_num; i++) + { + zabbix_log(LOG_LEVEL_TRACE, " %s: %u", (char *)records.values[i] + sizeof(zbx_uint32_t), + *(zbx_uint32_t *)records.values[i]); + } + + zbx_vector_ptr_destroy(&records); +} +#endif + +static void DCdump_drules(void) +{ + zbx_hashset_iter_t iter; + zbx_dc_drule_t *drule; + + zabbix_log(LOG_LEVEL_TRACE, "In %s()", __func__); + + zbx_hashset_iter_reset(&config->drules, &iter); + while (NULL != (drule = (zbx_dc_drule_t *)zbx_hashset_iter_next(&iter))) + { + zabbix_log(LOG_LEVEL_TRACE, "druleid:" ZBX_FS_UI64 " proxy_hostid:" ZBX_FS_UI64 " revision:" ZBX_FS_UI64, + drule->druleid, drule->proxy_hostid, drule->revision); + zabbix_log(LOG_LEVEL_TRACE, " status:%u delay:%d location:%d nextcheck:%ld", + drule->status, drule->delay, drule->location, (long int)drule->nextcheck); + } + + zabbix_log(LOG_LEVEL_TRACE, "End of %s()", __func__); +} + +static void DCdump_dchecks(void) +{ + zbx_hashset_iter_t iter; + zbx_dc_dcheck_t *dcheck; + + zabbix_log(LOG_LEVEL_TRACE, "In %s()", __func__); + + zbx_hashset_iter_reset(&config->dchecks, &iter); + while (NULL != (dcheck = (zbx_dc_dcheck_t *)zbx_hashset_iter_next(&iter))) + { + zabbix_log(LOG_LEVEL_TRACE, "dcheckid:" ZBX_FS_UI64 " druleid:" ZBX_FS_UI64, + dcheck->dcheckid, dcheck->druleid); + } + + zabbix_log(LOG_LEVEL_TRACE, "End of %s()", __func__); +} + +static void DCdump_httptests(void) +{ + zbx_hashset_iter_t iter; + zbx_dc_httptest_t *httptest; + + zabbix_log(LOG_LEVEL_TRACE, "In %s()", __func__); + + zbx_hashset_iter_reset(&config->httptests, &iter); + while (NULL != (httptest = (zbx_dc_httptest_t *)zbx_hashset_iter_next(&iter))) + { + zabbix_log(LOG_LEVEL_TRACE, "httptestid:" ZBX_FS_UI64 " hostid:" ZBX_FS_UI64 " revision:" ZBX_FS_UI64, + httptest->httptestid, httptest->hostid, httptest->revision); + zabbix_log(LOG_LEVEL_TRACE, " status:%u delay:%d location:%d nextcheck:%ld", + httptest->status, httptest->delay, httptest->location, (long int)httptest->nextcheck); + } + + zabbix_log(LOG_LEVEL_TRACE, "End of %s()", __func__); +} + +static void DCdump_httptest_fields(void) +{ + zbx_hashset_iter_t iter; + zbx_dc_httptest_field_t *httptest_field; + + zabbix_log(LOG_LEVEL_TRACE, "In %s()", __func__); + + zbx_hashset_iter_reset(&config->httptest_fields, &iter); + while (NULL != (httptest_field = (zbx_dc_httptest_field_t *)zbx_hashset_iter_next(&iter))) + { + zabbix_log(LOG_LEVEL_TRACE, "httptest_fieldid:" ZBX_FS_UI64 " httptestid:" ZBX_FS_UI64, + httptest_field->httptest_fieldid, httptest_field->httptestid); + } + + zabbix_log(LOG_LEVEL_TRACE, "End of %s()", __func__); +} + +static void DCdump_httpsteps(void) +{ + zbx_hashset_iter_t iter; + zbx_dc_httpstep_t *httpstep; + + zabbix_log(LOG_LEVEL_TRACE, "In %s()", __func__); + + zbx_hashset_iter_reset(&config->httpsteps, &iter); + while (NULL != (httpstep = (zbx_dc_httpstep_t *)zbx_hashset_iter_next(&iter))) + { + zabbix_log(LOG_LEVEL_TRACE, "httpstepid:" ZBX_FS_UI64 " httptestid:" ZBX_FS_UI64, + httpstep->httpstepid, httpstep->httptestid); + } + + zabbix_log(LOG_LEVEL_TRACE, "End of %s()", __func__); +} + +static void DCdump_httpstep_fields(void) +{ + zbx_hashset_iter_t iter; + zbx_dc_httpstep_field_t *httpstep_field; + + zabbix_log(LOG_LEVEL_TRACE, "In %s()", __func__); + + zbx_hashset_iter_reset(&config->httpstep_fields, &iter); + while (NULL != (httpstep_field = (zbx_dc_httpstep_field_t *)zbx_hashset_iter_next(&iter))) + { + zabbix_log(LOG_LEVEL_TRACE, "httpstep_fieldid:" ZBX_FS_UI64 " httpstepid:" ZBX_FS_UI64, + httpstep_field->httpstep_fieldid, httpstep_field->httpstepid); + } + + zabbix_log(LOG_LEVEL_TRACE, "End of %s()", __func__); +} + void DCdump_configuration(void) { - zabbix_log(LOG_LEVEL_TRACE, "=== Configuration cache contents (revision:%u) ===", config->revision); + zabbix_log(LOG_LEVEL_TRACE, "=== Configuration cache contents (revision:" ZBX_FS_UI64 ") ===", + config->revision.config); + + zabbix_log(LOG_LEVEL_TRACE, " autoreg_tls_revision:" ZBX_FS_UI64, config->revision.autoreg_tls); DCdump_config(); DCdump_hosts(); @@ -1332,7 +1461,6 @@ void DCdump_configuration(void) DCdump_item_discovery(); DCdump_interface_snmpitems(); DCdump_template_items(); - DCdump_master_items(); DCdump_prototype_items(); DCdump_triggers(); DCdump_trigdeps(); @@ -1343,5 +1471,14 @@ void DCdump_configuration(void) DCdump_host_groups(); DCdump_host_group_index(); DCdump_maintenances(); + DCdump_drules(); + DCdump_dchecks(); + DCdump_httptests(); + DCdump_httptest_fields(); + DCdump_httpsteps(); + DCdump_httpstep_fields(); DCdump_autoreg_hosts(); +#ifdef HAVE_TESTS + DCdump_strpool(); +#endif } diff --git a/src/libs/zbxdbcache/dbconfig_maintenance.c b/src/libs/zbxdbcache/dbconfig_maintenance.c index 19ec3fd7265..e7094673ed0 100644 --- a/src/libs/zbxdbcache/dbconfig_maintenance.c +++ b/src/libs/zbxdbcache/dbconfig_maintenance.c @@ -1368,9 +1368,9 @@ static int dc_maintenance_match_tags(const zbx_dc_maintenance_t *maintenance, co { switch (maintenance->tags_evaltype) { - case MAINTENANCE_TAG_EVAL_TYPE_AND_OR: + case ZBX_MAINTENANCE_TAG_EVAL_TYPE_AND_OR: /* break; is not missing here */ - case MAINTENANCE_TAG_EVAL_TYPE_OR: + case ZBX_MAINTENANCE_TAG_EVAL_TYPE_OR: if (0 == maintenance->tags.values_num) return SUCCEED; @@ -1382,7 +1382,7 @@ static int dc_maintenance_match_tags(const zbx_dc_maintenance_t *maintenance, co return FAIL; } - if (MAINTENANCE_TAG_EVAL_TYPE_AND_OR == maintenance->tags_evaltype) + if (ZBX_MAINTENANCE_TAG_EVAL_TYPE_AND_OR == maintenance->tags_evaltype) return dc_maintenance_match_tags_andor(maintenance, tags); else return dc_maintenance_match_tags_or(maintenance, tags); diff --git a/src/libs/zbxdbcache/dbsync.c b/src/libs/zbxdbcache/dbsync.c index a973e21259e..e3e61718a5a 100644 --- a/src/libs/zbxdbcache/dbsync.c +++ b/src/libs/zbxdbcache/dbsync.c @@ -34,9 +34,16 @@ #define ZBX_DBSYNC_OBJ_TRIGGER_TAG 6 #define ZBX_DBSYNC_OBJ_FUNCTION 7 #define ZBX_DBSYNC_OBJ_ITEM_PREPROC 8 - +#define ZBX_DBSYNC_OBJ_DRULE 9 +#define ZBX_DBSYNC_OBJ_DCHECK 10 +#define ZBX_DBSYNC_OBJ_HTTPTEST 11 +#define ZBX_DBSYNC_OBJ_HTTPTEST_FIELD 12 +#define ZBX_DBSYNC_OBJ_HTTPTESTITEM 13 +#define ZBX_DBSYNC_OBJ_HTTPSTEP 14 +#define ZBX_DBSYNC_OBJ_HTTPSTEP_FIELD 15 +#define ZBX_DBSYNC_OBJ_HTTPSTEP_ITEM 16 /* number of dbsync objects - keep in sync with above defines */ -#define ZBX_DBSYNC_OBJ_COUNT 8 +#define ZBX_DBSYNC_OBJ_COUNT 16 #define ZBX_DBSYNC_JOURNAL(X) (X - 1) @@ -511,8 +518,8 @@ int zbx_dbsync_env_prepare(unsigned char mode) static void dbsync_env_flush_journal(zbx_dbsync_journal_t *journal) { - zbx_vector_uint64_t objectids; - int i, j, objects_num; + zbx_hashset_t objectids; + int i, j, objects_num; if (0 == journal->changelog.values_num) return; @@ -522,8 +529,8 @@ static void dbsync_env_flush_journal(zbx_dbsync_journal_t *journal) for (i = 0; i < journal->syncs.values_num; i++) objects_num += journal->syncs.values[i]->rows.values_num; - zbx_vector_uint64_create(&objectids); - zbx_vector_uint64_reserve(&objectids, (size_t)objects_num); + zbx_hashset_create(&objectids, (size_t)objects_num, ZBX_DEFAULT_UINT64_HASH_FUNC, + ZBX_DEFAULT_UINT64_COMPARE_FUNC); for (j = 0; j < journal->syncs.values_num; j++) { @@ -531,29 +538,26 @@ static void dbsync_env_flush_journal(zbx_dbsync_journal_t *journal) { zbx_dbsync_row_t *row = (zbx_dbsync_row_t *)journal->syncs.values[j]->rows.values[i]; - zbx_vector_uint64_append(&objectids, row->rowid); + zbx_hashset_insert(&objectids, &row->rowid, sizeof(row->rowid)); } } - if (0 != journal->inserts.values_num) - zbx_vector_uint64_append_array(&objectids, journal->inserts.values, journal->inserts.values_num); - - if (0 != journal->updates.values_num) - zbx_vector_uint64_append_array(&objectids, journal->updates.values, journal->updates.values_num); + for (i = 0; i < journal->inserts.values_num; i++) + zbx_hashset_insert(&objectids, &journal->inserts.values[i], sizeof(journal->inserts.values[i])); - zbx_vector_uint64_sort(&objectids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); + for (i = 0; i < journal->updates.values_num; i++) + zbx_hashset_insert(&objectids, &journal->updates.values[i], sizeof(journal->updates.values[i])); for (i = 0; i < journal->changelog.values_num; i++) { - if (FAIL != zbx_vector_uint64_bsearch(&objectids, journal->changelog.values[i].objectid, - ZBX_DEFAULT_UINT64_COMPARE_FUNC)) + if (NULL != zbx_hashset_search(&objectids, &journal->changelog.values[i].objectid)) { zbx_hashset_insert(&dbsync_env.changelog, &journal->changelog.values[i].changelog, sizeof(zbx_dbsync_changelog_t)); } } - zbx_vector_uint64_destroy(&objectids); + zbx_hashset_destroy(&objectids); } void zbx_dbsync_env_flush_changelog(void) @@ -592,7 +596,7 @@ int zbx_dbsync_env_changelog_num(void) * * ******************************************************************************/ static int dbsync_get_rows(zbx_dbsync_t *sync, char **sql, size_t *sql_alloc, size_t *sql_offset, - const char *field, zbx_vector_uint64_t *ids, unsigned char tag) + const char *field, const char *order_field, zbx_vector_uint64_t *ids, unsigned char tag) { DB_ROW dbrow; DB_RESULT result; @@ -609,6 +613,8 @@ static int dbsync_get_rows(zbx_dbsync_t *sync, char **sql, size_t *sql_alloc, si { batch_size = MIN(ZBX_DBSYNC_BATCH_SIZE, ids->values + ids->values_num - batch); DBadd_condition_alloc(sql, sql_alloc, sql_offset, field, batch, batch_size); + if (NULL != order_field) + zbx_snprintf_alloc(sql, sql_alloc, sql_offset, " order by %s", order_field); if (NULL == (result = DBselect("%s", *sql))) return FAIL; @@ -640,7 +646,7 @@ static int dbsync_get_rows(zbx_dbsync_t *sync, char **sql, size_t *sql_alloc, si * * ******************************************************************************/ static int dbsync_read_journal(zbx_dbsync_t *sync, char **sql, size_t *sql_alloc, size_t *sql_offset, - const char *field, const char *keyword, zbx_dbsync_journal_t *journal) + const char *field, const char *keyword, const char *order_field, zbx_dbsync_journal_t *journal) { int i, inserts_num, updates_num; @@ -656,8 +662,8 @@ static int dbsync_read_journal(zbx_dbsync_t *sync, char **sql, size_t *sql_alloc if (0 != journal->inserts.values_num) { - if (FAIL == dbsync_get_rows(sync, sql, sql_alloc, sql_offset, field, &journal->inserts, - ZBX_DBSYNC_ROW_ADD)) + if (FAIL == dbsync_get_rows(sync, sql, sql_alloc, sql_offset, field, order_field, + &journal->inserts, ZBX_DBSYNC_ROW_ADD)) { return FAIL; } @@ -665,8 +671,8 @@ static int dbsync_read_journal(zbx_dbsync_t *sync, char **sql, size_t *sql_alloc if (0 != journal->updates.values_num) { - if (FAIL == dbsync_get_rows(sync, sql, sql_alloc, sql_offset, field, &journal->updates, - ZBX_DBSYNC_ROW_UPDATE)) + if (FAIL == dbsync_get_rows(sync, sql, sql_alloc, sql_offset, field, order_field, + &journal->updates, ZBX_DBSYNC_ROW_UPDATE)) { return FAIL; } @@ -925,11 +931,7 @@ int zbx_dbsync_compare_autoreg_psk(zbx_dbsync_t *sync) { unsigned char tag = ZBX_DBSYNC_ROW_NONE; - if ('\0' == dbsync_env.cache->autoreg_psk_identity[0]) /* no autoregistration PSK in cache */ - { - tag = ZBX_DBSYNC_ROW_ADD; - } - else if (FAIL == dbsync_compare_str(dbrow[0], dbsync_env.cache->autoreg_psk_identity) || + if (FAIL == dbsync_compare_str(dbrow[0], dbsync_env.cache->autoreg_psk_identity) || FAIL == dbsync_compare_str(dbrow[1], dbsync_env.cache->autoreg_psk)) { tag = ZBX_DBSYNC_ROW_UPDATE; @@ -1035,7 +1037,8 @@ int zbx_dbsync_compare_hosts(zbx_dbsync_t *sync) goto out; } - ret = dbsync_read_journal(sync, &sql, &sql_alloc, &sql_offset, "h.hostid", "and", + /* sort by h.proxy_hostid to ensure that proxies are synced before hosts assigned to them */ + ret = dbsync_read_journal(sync, &sql, &sql_alloc, &sql_offset, "h.hostid", "and", NULL, &dbsync_env.journals[ZBX_DBSYNC_JOURNAL(ZBX_DBSYNC_OBJ_HOST)]); out: zbx_free(sql); @@ -1730,7 +1733,7 @@ int zbx_dbsync_compare_items(zbx_dbsync_t *sync) goto out; } - ret = dbsync_read_journal(sync, &sql, &sql_alloc, &sql_offset, "i.itemid", "and", + ret = dbsync_read_journal(sync, &sql, &sql_alloc, &sql_offset, "i.itemid", "and", NULL, &dbsync_env.journals[ZBX_DBSYNC_JOURNAL(ZBX_DBSYNC_OBJ_ITEM)]); out: zbx_free(sql); @@ -1918,7 +1921,7 @@ int zbx_dbsync_compare_prototype_items(zbx_dbsync_t *sync) goto out; } - ret = dbsync_read_journal(sync, &sql, &sql_alloc, &sql_offset, "i.itemid", "and", + ret = dbsync_read_journal(sync, &sql, &sql_alloc, &sql_offset, "i.itemid", "and", NULL, &dbsync_env.journals[ZBX_DBSYNC_JOURNAL(ZBX_DBSYNC_OBJ_ITEM)]); out: zbx_free(sql); @@ -2030,7 +2033,7 @@ int zbx_dbsync_compare_triggers(zbx_dbsync_t *sync) goto out; } - ret = dbsync_read_journal(sync, &sql, &sql_alloc, &sql_offset, "triggerid", "where", + ret = dbsync_read_journal(sync, &sql, &sql_alloc, &sql_offset, "triggerid", "where", NULL, &dbsync_env.journals[ZBX_DBSYNC_JOURNAL(ZBX_DBSYNC_OBJ_TRIGGER)]); out: zbx_free(sql); @@ -2169,7 +2172,7 @@ int zbx_dbsync_compare_functions(zbx_dbsync_t *sync) goto out; } - ret = dbsync_read_journal(sync, &sql, &sql_alloc, &sql_offset, "functionid", "where", + ret = dbsync_read_journal(sync, &sql, &sql_alloc, &sql_offset, "functionid", "where", NULL, &dbsync_env.journals[ZBX_DBSYNC_JOURNAL(ZBX_DBSYNC_OBJ_FUNCTION)]); out: zbx_free(sql); @@ -2598,7 +2601,7 @@ int zbx_dbsync_compare_trigger_tags(zbx_dbsync_t *sync) goto out; } - ret = dbsync_read_journal(sync, &sql, &sql_alloc, &sql_offset, "triggertagid", "where", + ret = dbsync_read_journal(sync, &sql, &sql_alloc, &sql_offset, "triggertagid", "where", NULL, &dbsync_env.journals[ZBX_DBSYNC_JOURNAL(ZBX_DBSYNC_OBJ_TRIGGER_TAG)]); out: zbx_free(sql); @@ -2633,7 +2636,7 @@ int zbx_dbsync_compare_item_tags(zbx_dbsync_t *sync) goto out; } - ret = dbsync_read_journal(sync, &sql, &sql_alloc, &sql_offset, "itemtagid", "where", + ret = dbsync_read_journal(sync, &sql, &sql_alloc, &sql_offset, "itemtagid", "where", NULL, &dbsync_env.journals[ZBX_DBSYNC_JOURNAL(ZBX_DBSYNC_OBJ_ITEM_TAG)]); out: zbx_free(sql); @@ -2668,7 +2671,7 @@ int zbx_dbsync_compare_host_tags(zbx_dbsync_t *sync) goto out; } - ret = dbsync_read_journal(sync, &sql, &sql_alloc, &sql_offset, "hosttagid", "where", + ret = dbsync_read_journal(sync, &sql, &sql_alloc, &sql_offset, "hosttagid", "where", NULL, &dbsync_env.journals[ZBX_DBSYNC_JOURNAL(ZBX_DBSYNC_OBJ_HOST_TAG)]); out: zbx_free(sql); @@ -3114,7 +3117,7 @@ int zbx_dbsync_compare_item_preprocs(zbx_dbsync_t *sync) goto out; } - ret = dbsync_read_journal(sync, &sql, &sql_alloc, &sql_offset, "item_preprocid", "where", + ret = dbsync_read_journal(sync, &sql, &sql_alloc, &sql_offset, "item_preprocid", "where", NULL, &dbsync_env.journals[ZBX_DBSYNC_JOURNAL(ZBX_DBSYNC_OBJ_ITEM_PREPROC)]); out: zbx_free(sql); @@ -3763,3 +3766,221 @@ int zbx_dbsync_compare_host_group_hosts(zbx_dbsync_t *sync) return SUCCEED; } + +/****************************************************************************** + * * + * Purpose: prepare dbsync object for drules table * + * * + * Parameter: sync - [OUT] the changeset * + * * + * Return value: SUCCEED - the changeset was successfully calculated * + * FAIL - otherwise * + * * + ******************************************************************************/ +int zbx_dbsync_prepare_drules(zbx_dbsync_t *sync) +{ + char *sql = NULL; + size_t sql_alloc = 0, sql_offset = 0; + int ret = SUCCEED; + + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "select druleid,proxy_hostid,delay,status from drules"); + + dbsync_prepare(sync, 4, NULL); + + if (ZBX_DBSYNC_INIT == sync->mode) + { + if (NULL == (sync->dbresult = DBselect("%s", sql))) + ret = FAIL; + goto out; + } + + ret = dbsync_read_journal(sync, &sql, &sql_alloc, &sql_offset, "druleid", "where", NULL, + &dbsync_env.journals[ZBX_DBSYNC_JOURNAL(ZBX_DBSYNC_OBJ_DRULE)]); +out: + zbx_free(sql); + + return ret; +} + +/****************************************************************************** + * * + * Purpose: prepare dbsync object for dchecks tabkle * + * * + * Parameter: sync - [OUT] the changeset * + * * + * Return value: SUCCEED - the changeset was successfully calculated * + * FAIL - otherwise * + * * + ******************************************************************************/ +int zbx_dbsync_prepare_dchecks(zbx_dbsync_t *sync) +{ + char *sql = NULL; + size_t sql_alloc = 0, sql_offset = 0; + int ret = SUCCEED; + + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "select dcheckid,druleid from dchecks"); + + dbsync_prepare(sync, 2, NULL); + + if (ZBX_DBSYNC_INIT == sync->mode) + { + if (NULL == (sync->dbresult = DBselect("%s", sql))) + ret = FAIL; + goto out; + } + + ret = dbsync_read_journal(sync, &sql, &sql_alloc, &sql_offset, "dcheckid", "where", NULL, + &dbsync_env.journals[ZBX_DBSYNC_JOURNAL(ZBX_DBSYNC_OBJ_DCHECK)]); +out: + zbx_free(sql); + + return ret; +} + +/****************************************************************************** + * * + * Purpose: prepare dbsync object for httptest table * + * * + * Parameter: sync - [OUT] the changeset * + * * + * Return value: SUCCEED - the changeset was successfully calculated * + * FAIL - otherwise * + * * + ******************************************************************************/ +int zbx_dbsync_prepare_httptests(zbx_dbsync_t *sync) +{ + char *sql = NULL; + size_t sql_alloc = 0, sql_offset = 0; + int ret = SUCCEED; + + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "select httptestid,hostid,delay,status from httptest"); + + dbsync_prepare(sync, 4, NULL); + + if (ZBX_DBSYNC_INIT == sync->mode) + { + if (NULL == (sync->dbresult = DBselect("%s", sql))) + ret = FAIL; + goto out; + } + + ret = dbsync_read_journal(sync, &sql, &sql_alloc, &sql_offset, "httptestid", "where", NULL, + &dbsync_env.journals[ZBX_DBSYNC_JOURNAL(ZBX_DBSYNC_OBJ_HTTPTEST)]); +out: + zbx_free(sql); + + return ret; +} + +/****************************************************************************** + * * + * Purpose: prepare dbsync object for httptest_field table * + * * + * Parameter: sync - [OUT] the changeset * + * * + * Return value: SUCCEED - the changeset was successfully calculated * + * FAIL - otherwise * + * * + ******************************************************************************/ +int zbx_dbsync_prepare_httptest_fields(zbx_dbsync_t *sync) +{ + char *sql = NULL; + size_t sql_alloc = 0, sql_offset = 0; + int ret = SUCCEED; + + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "select httptest_fieldid,httptestid from httptest_field"); + + dbsync_prepare(sync, 2, NULL); + + if (ZBX_DBSYNC_INIT == sync->mode) + { + if (NULL == (sync->dbresult = DBselect("%s", sql))) + ret = FAIL; + goto out; + } + + ret = dbsync_read_journal(sync, &sql, &sql_alloc, &sql_offset, "httptest_fieldid", "where", NULL, + &dbsync_env.journals[ZBX_DBSYNC_JOURNAL(ZBX_DBSYNC_OBJ_HTTPTEST_FIELD)]); +out: + zbx_free(sql); + + return ret; +} + +/****************************************************************************** + * * + * Purpose: prepare dbsync object for httpstep table * + * * + * Parameter: sync - [OUT] the changeset * + * * + * Return value: SUCCEED - the changeset was successfully calculated * + * FAIL - otherwise * + * * + ******************************************************************************/ +int zbx_dbsync_prepare_httpsteps(zbx_dbsync_t *sync) +{ + char *sql = NULL; + size_t sql_alloc = 0, sql_offset = 0; + int ret = SUCCEED; + + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "select httpstepid,httptestid from httpstep"); + dbsync_prepare(sync, 2, NULL); + + if (ZBX_DBSYNC_INIT == sync->mode) + { + if (NULL == (sync->dbresult = DBselect("%s", sql))) + ret = FAIL; + goto out; + } + + ret = dbsync_read_journal(sync, &sql, &sql_alloc, &sql_offset, "httpstepid", "where", NULL, + &dbsync_env.journals[ZBX_DBSYNC_JOURNAL(ZBX_DBSYNC_OBJ_HTTPSTEP)]); +out: + zbx_free(sql); + + return ret; +} + +/****************************************************************************** + * * + * Purpose: prepare dbsync object for httpstep_field table * + * * + * Parameter: sync - [OUT] the changeset * + * * + * Return value: SUCCEED - the changeset was successfully calculated * + * FAIL - otherwise * + * * + ******************************************************************************/ +int zbx_dbsync_prepare_httpstep_fields(zbx_dbsync_t *sync) +{ + char *sql = NULL; + size_t sql_alloc = 0, sql_offset = 0; + int ret = SUCCEED; + + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "select httpstep_fieldid,httpstepid from httpstep_field"); + dbsync_prepare(sync, 2, NULL); + + if (ZBX_DBSYNC_INIT == sync->mode) + { + if (NULL == (sync->dbresult = DBselect("%s", sql))) + ret = FAIL; + goto out; + } + + ret = dbsync_read_journal(sync, &sql, &sql_alloc, &sql_offset, "httpstep_fieldid", "where", NULL, + &dbsync_env.journals[ZBX_DBSYNC_JOURNAL(ZBX_DBSYNC_OBJ_HTTPSTEP_FIELD)]); +out: + zbx_free(sql); + + return ret; +} + +/****************************************************************************** + * * + * Purpose: remove deleted hosts/templates from user macro cache * + * * + ******************************************************************************/ +void zbx_dbsync_clear_user_macros(void) +{ + um_cache_remove_hosts(config->um_cache, &dbsync_env.journals[ZBX_DBSYNC_JOURNAL(ZBX_DBSYNC_OBJ_HOST)].deletes); +} diff --git a/src/libs/zbxdbcache/dbsync.h b/src/libs/zbxdbcache/dbsync.h index a1fd8d529ca..d92abd060cb 100644 --- a/src/libs/zbxdbcache/dbsync.h +++ b/src/libs/zbxdbcache/dbsync.h @@ -154,4 +154,14 @@ int zbx_dbsync_compare_maintenance_groups(zbx_dbsync_t *sync); int zbx_dbsync_compare_maintenance_hosts(zbx_dbsync_t *sync); int zbx_dbsync_compare_host_group_hosts(zbx_dbsync_t *sync); +int zbx_dbsync_prepare_drules(zbx_dbsync_t *sync); +int zbx_dbsync_prepare_dchecks(zbx_dbsync_t *sync); + +int zbx_dbsync_prepare_httptests(zbx_dbsync_t *sync); +int zbx_dbsync_prepare_httptest_fields(zbx_dbsync_t *sync); +int zbx_dbsync_prepare_httpsteps(zbx_dbsync_t *sync); +int zbx_dbsync_prepare_httpstep_fields(zbx_dbsync_t *sync); +void zbx_dbsync_clear_user_macros(void); + + #endif /* BUILD_SRC_LIBS_ZBXDBCACHE_DBSYNC_H_ */ diff --git a/src/libs/zbxdbcache/user_macro.c b/src/libs/zbxdbcache/user_macro.c index ae2cc7a4e05..1a51243910e 100644 --- a/src/libs/zbxdbcache/user_macro.c +++ b/src/libs/zbxdbcache/user_macro.c @@ -36,6 +36,13 @@ ZBX_PTR_VECTOR_IMPL(um_host, zbx_um_host_t *) extern char *CONFIG_VAULTDBPATH; extern unsigned char program_type; +typedef enum +{ + ZBX_UM_UPDATE_HOST, + ZBX_UM_UPDATE_MACRO +} +zbx_um_update_cause_t; + /********************************************************************************* * * * Purpose: create duplicate user macro cache * @@ -76,7 +83,7 @@ static int um_macro_compare_by_name_context(const void *d1, const void *d2) if (0 != (ret = strcmp(m1->name, m2->name))) return ret; - /* CONDITION_OPERATOR_EQUAL (0) has higher priority than CONDITION_OPERATOR_REGEXP (8) */ + /* ZBX_CONDITION_OPERATOR_EQUAL (0) has higher priority than ZBX_CONDITION_OPERATOR_REGEXP (8) */ ZBX_RETURN_IF_NOT_EQUAL(m1->context_op, m2->context_op); return zbx_strcmp_null(m1->context, m2->context); @@ -132,7 +139,7 @@ zbx_um_cache_t *um_cache_create(void) cache = (zbx_um_cache_t *)__config_shmem_malloc_func(NULL, sizeof(zbx_um_cache_t)); cache->refcount = 1; cache->revision = 0; - zbx_hashset_create_ext(&cache->hosts, 10, um_host_hash, um_host_compare,NULL, + zbx_hashset_create_ext(&cache->hosts, 10, um_host_hash, um_host_compare, NULL, __config_shmem_malloc_func, __config_shmem_realloc_func, __config_shmem_free_func); return cache; @@ -235,6 +242,8 @@ static zbx_um_host_t *um_host_dup(zbx_um_host_t *host) dup = (zbx_um_host_t *)__config_shmem_malloc_func(NULL, sizeof(zbx_um_host_t)); dup->hostid = host->hostid; dup->refcount = 1; + dup->macro_revision = host->macro_revision; + dup->link_revision = host->link_revision; zbx_vector_uint64_create_ext(&dup->templateids, __config_shmem_malloc_func, __config_shmem_realloc_func, __config_shmem_free_func); @@ -293,7 +302,8 @@ static zbx_um_host_t *um_cache_create_host(zbx_um_cache_t *cache, zbx_uint64_t h host = (zbx_um_host_t *)__config_shmem_malloc_func(NULL, sizeof(zbx_um_host_t)); host->hostid = hostid; host->refcount = 1; - host->revision = cache->revision; + host->macro_revision = cache->revision; + host->link_revision = cache->revision; zbx_vector_uint64_create_ext(&host->templateids, __config_shmem_malloc_func, __config_shmem_realloc_func, __config_shmem_free_func); zbx_vector_um_macro_create_ext(&host->macros, __config_shmem_malloc_func, __config_shmem_realloc_func, @@ -311,7 +321,8 @@ static zbx_um_host_t *um_cache_create_host(zbx_um_cache_t *cache, zbx_uint64_t h * Comments: If the host is used by other processes it will be duplicated. * * * *********************************************************************************/ -static zbx_um_host_t *um_cache_acquire_host(zbx_um_cache_t *cache, zbx_uint64_t hostid) +static zbx_um_host_t *um_cache_acquire_host(zbx_um_cache_t *cache, zbx_uint64_t hostid, + zbx_um_update_cause_t cause) { zbx_uint64_t *phostid = &hostid; zbx_um_host_t **phost; @@ -326,9 +337,18 @@ static zbx_um_host_t *um_cache_acquire_host(zbx_um_cache_t *cache, zbx_uint64_t /* hosts are acquired when there are changes to be made, */ /* meaning host revision must be updated */ - (*phost)->revision = cache->revision; + switch (cause) + { + case ZBX_UM_UPDATE_HOST: + (*phost)->link_revision = cache->revision; + break; + case ZBX_UM_UPDATE_MACRO: + (*phost)->macro_revision = cache->revision; + break; + } return *phost; + } return NULL; @@ -419,6 +439,10 @@ static void um_macro_kv_remove(zbx_um_macro_t *macro, zbx_dc_macro_kv_t *mkv) if (0 == mkv->kv->macros.values_num) { zbx_vector_uint64_pair_destroy(&mkv->kv->macros); + dc_strpool_release(mkv->kv->key); + if (NULL != mkv->kv->value) + dc_strpool_release(mkv->kv->value); + zbx_hashset_remove_direct(&mkv->kv_path->kvs, mkv->kv); if (0 == mkv->kv_path->kvs.num_data) dc_kvs_path_remove(mkv->kv_path); @@ -646,7 +670,7 @@ static void um_cache_sync_macros(zbx_um_cache_t *cache, zbx_dbsync_t *sync, int if (NULL != (pmacro = (zbx_um_macro_t **)zbx_hashset_search(user_macros, &pmacroid))) { - host = um_cache_acquire_host(cache, (*pmacro)->hostid); + host = um_cache_acquire_host(cache, (*pmacro)->hostid, ZBX_UM_UPDATE_MACRO); if (SUCCEED == um_macro_is_locked(*pmacro)) { @@ -671,7 +695,7 @@ static void um_cache_sync_macros(zbx_um_cache_t *cache, zbx_dbsync_t *sync, int } /* acquire new host */ - host = um_cache_acquire_host(cache, hostid); + host = um_cache_acquire_host(cache, hostid, ZBX_UM_UPDATE_MACRO); } dc_strpool_release((*pmacro)->name); @@ -698,7 +722,7 @@ static void um_cache_sync_macros(zbx_um_cache_t *cache, zbx_dbsync_t *sync, int macro->value = NULL; pmacro = zbx_hashset_insert(user_macros, ¯o, sizeof(macro)); - host = um_cache_acquire_host(cache, hostid); + host = um_cache_acquire_host(cache, hostid, ZBX_UM_UPDATE_MACRO); } (*pmacro)->hostid = hostid; @@ -734,7 +758,7 @@ static void um_cache_sync_macros(zbx_um_cache_t *cache, zbx_dbsync_t *sync, int if (ZBX_MACRO_VALUE_VAULT == (*pmacro)->type) um_macro_deregister_kvs(*pmacro); - if (NULL != (host = um_cache_acquire_host(cache, (*pmacro)->hostid))) + if (NULL != (host = um_cache_acquire_host(cache, (*pmacro)->hostid, ZBX_UM_UPDATE_MACRO))) { um_host_remove_macro(host, *pmacro); zbx_vector_um_host_append(&hosts, host); @@ -752,18 +776,10 @@ static void um_cache_sync_macros(zbx_um_cache_t *cache, zbx_dbsync_t *sync, int { if (0 == hosts.values[i]->macros.values_num) { - if (0 == hosts.values[i]->templateids.values_num) - { - zbx_hashset_remove(&cache->hosts, &hosts.values[i]); - um_host_release(hosts.values[i]); - } - else - { - /* recreate empty-macros vector to release memory */ - zbx_vector_um_macro_destroy(&hosts.values[i]->macros); - zbx_vector_um_macro_create_ext(&hosts.values[i]->macros, __config_shmem_malloc_func, - __config_shmem_realloc_func, __config_shmem_free_func); - } + /* recreate empty-macros vector to release memory */ + zbx_vector_um_macro_destroy(&hosts.values[i]->macros); + zbx_vector_um_macro_create_ext(&hosts.values[i]->macros, __config_shmem_malloc_func, + __config_shmem_realloc_func, __config_shmem_free_func); } else zbx_vector_um_macro_sort(&hosts.values[i]->macros, um_macro_compare_by_name_context); @@ -793,7 +809,7 @@ static void um_cache_sync_hosts(zbx_um_cache_t *cache, zbx_dbsync_t *sync) ZBX_STR2UINT64(hostid, row[0]); - if (NULL == (host = um_cache_acquire_host(cache, hostid))) + if (NULL == (host = um_cache_acquire_host(cache, hostid, ZBX_UM_UPDATE_HOST))) host = um_cache_create_host(cache, hostid); ZBX_DBROW2UINT64(templateid, row[1]); @@ -807,7 +823,7 @@ static void um_cache_sync_hosts(zbx_um_cache_t *cache, zbx_dbsync_t *sync) ZBX_STR2UINT64(hostid, row[0]); - if (NULL == (host = um_cache_acquire_host(cache, hostid))) + if (NULL == (host = um_cache_acquire_host(cache, hostid, ZBX_UM_UPDATE_HOST))) continue; ZBX_DBROW2UINT64(templateid, row[1]); @@ -819,18 +835,9 @@ static void um_cache_sync_hosts(zbx_um_cache_t *cache, zbx_dbsync_t *sync) zbx_vector_uint64_remove_noorder(&host->templateids, i); if (0 == host->templateids.values_num) { - if (0 == host->macros.values_num) - { - zbx_hashset_remove(&cache->hosts, &host); - um_host_release(host); - } - else - { - zbx_vector_uint64_destroy(&host->templateids); - zbx_vector_uint64_create_ext(&host->templateids, - __config_shmem_malloc_func, __config_shmem_realloc_func, - __config_shmem_free_func); - } + zbx_vector_uint64_destroy(&host->templateids); + zbx_vector_uint64_create_ext(&host->templateids, __config_shmem_malloc_func, + __config_shmem_realloc_func, __config_shmem_free_func); } break; } @@ -843,7 +850,7 @@ static void um_cache_sync_hosts(zbx_um_cache_t *cache, zbx_dbsync_t *sync) * Purpose: sync user macro cache * * * *********************************************************************************/ -zbx_um_cache_t *um_cache_sync(zbx_um_cache_t *cache, zbx_uint32_t revision, zbx_dbsync_t *gmacros, +zbx_um_cache_t *um_cache_sync(zbx_um_cache_t *cache, zbx_uint64_t revision, zbx_dbsync_t *gmacros, zbx_dbsync_t *hmacros, zbx_dbsync_t *htmpls) { if (ZBX_DBSYNC_INIT != gmacros->mode && ZBX_DBSYNC_INIT != hmacros->mode && ZBX_DBSYNC_INIT != htmpls->mode && @@ -888,11 +895,11 @@ static int um_macro_match(const zbx_um_macro_t *macro, const char *name, const c { switch (macro->context_op) { - case CONDITION_OPERATOR_EQUAL: + case ZBX_CONDITION_OPERATOR_EQUAL: if (0 == strcmp(macro->context, context)) return ZBX_UM_MATCH_FULL; break; - case CONDITION_OPERATOR_REGEXP: + case ZBX_CONDITION_OPERATOR_REGEXP: if (NULL != zbx_regexp_match(context, macro->context, NULL)) return ZBX_UM_MATCH_FULL; break; @@ -1125,11 +1132,12 @@ void um_cache_resolve(const zbx_um_cache_t *cache, const zbx_uint64_t *hostids, * Purpose: set value to the specified macros * * * * Parameters: cache - [IN] the user macro cache * + * revision - [IN] the configuration revision * * host_macro_ids - [IN] a vector of hostid,macroid pairs * * value - [IN] the new value (stored in string pool) * * * *********************************************************************************/ -zbx_um_cache_t *um_cache_set_value_to_macros(zbx_um_cache_t *cache, zbx_uint32_t revision, +zbx_um_cache_t *um_cache_set_value_to_macros(zbx_um_cache_t *cache, zbx_uint64_t revision, const zbx_vector_uint64_pair_t *host_macro_ids, const char *value) { int i; @@ -1156,7 +1164,7 @@ zbx_um_cache_t *um_cache_set_value_to_macros(zbx_um_cache_t *cache, zbx_uint32_t if (NULL == (pmacro = (zbx_um_macro_t **)zbx_hashset_search(user_macros, &pmacroid))) continue; - if (NULL == (host = um_cache_acquire_host(cache, (*pmacro)->hostid))) + if (NULL == (host = um_cache_acquire_host(cache, (*pmacro)->hostid, ZBX_UM_UPDATE_MACRO))) continue; if (SUCCEED == um_macro_is_locked(*pmacro)) @@ -1195,16 +1203,17 @@ void um_cache_dump(zbx_um_cache_t *cache) zbx_vector_uint64_t ids; int i; - zabbix_log(LOG_LEVEL_TRACE, "In %s() hosts:%d refcount:%u revision:%u", __func__, cache->hosts.num_data, - cache->refcount, cache->revision); + zabbix_log(LOG_LEVEL_TRACE, "In %s() hosts:%d refcount:%u revision:" ZBX_FS_UI64, __func__, + cache->hosts.num_data, cache->refcount, cache->revision); zbx_vector_uint64_create(&ids); zbx_hashset_iter_reset(&cache->hosts, &iter); while (NULL != (phost = (zbx_um_host_t **)zbx_hashset_iter_next(&iter))) { - zabbix_log(LOG_LEVEL_TRACE, "hostid:" ZBX_FS_UI64 " refcount:%u revision:%u", (*phost)->hostid, - (*phost)->refcount, (*phost)->revision); + zabbix_log(LOG_LEVEL_TRACE, "hostid:" ZBX_FS_UI64 " refcount:%u link_revision:" ZBX_FS_UI64 + " macro_revision:" ZBX_FS_UI64, (*phost)->hostid, + (*phost)->refcount, (*phost)->link_revision, (*phost)->macro_revision); zabbix_log(LOG_LEVEL_TRACE, " macros:"); @@ -1250,7 +1259,7 @@ void um_cache_dump(zbx_um_cache_t *cache) zabbix_log(LOG_LEVEL_TRACE, "End of %s()", __func__); } -int um_cache_get_host_revision(const zbx_um_cache_t *cache, zbx_uint64_t hostid, zbx_uint32_t *revision) +int um_cache_get_host_revision(const zbx_um_cache_t *cache, zbx_uint64_t hostid, zbx_uint64_t *revision) { const zbx_um_host_t * const *phost; int i; @@ -1259,11 +1268,156 @@ int um_cache_get_host_revision(const zbx_um_cache_t *cache, zbx_uint64_t hostid, if (NULL == (phost = (const zbx_um_host_t * const *)zbx_hashset_search(&cache->hosts, &phostid))) return FAIL; - if ((*phost)->revision > *revision) - *revision = (*phost)->revision; + if ((*phost)->macro_revision > *revision) + *revision = (*phost)->macro_revision; for (i = 0; i < (*phost)->templateids.values_num; i++) um_cache_get_host_revision(cache, (*phost)->templateids.values[i], revision); return SUCCEED; } + +static void um_cache_get_hosts(const zbx_um_cache_t *cache, const zbx_uint64_t *phostid, zbx_uint64_t revision, + zbx_vector_um_host_t *hosts) +{ + zbx_um_host_t **phost; + int i; + + if (NULL == (phost = (zbx_um_host_t **)zbx_hashset_search(&cache->hosts, &phostid))) + return; + + /* if host-template linking has changed, force macro update for all children */ + if ((*phost)->link_revision > revision) + revision = 0; + + if ((*phost)->macro_revision > revision || (*phost)->link_revision > revision) + zbx_vector_um_host_append(hosts, *phost); + + for (i = 0; i < (*phost)->templateids.values_num; i++) + um_cache_get_hosts(cache, &(*phost)->templateids.values[i], revision, hosts); +} + +/********************************************************************************* + * * + * Purpose: get identifiers of user macro host objects that were updated since * + * the specified revision * + * * + * Parameters: cache - [IN] the user macro cache * + * hostids - [IN] identifiers of the hosts to check * + * hostids_num - [IN] the number of hosts to check * + * revision - [IN] the revision * + * macro_hostids - [OUT] the identifiers of updated host objects * + * del_macro_hostids - [OUT] the identifiers of cleared host objects * + * (without macros or linked templates), * + * optional * + * * + *********************************************************************************/ +void um_cache_get_macro_updates(const zbx_um_cache_t *cache, const zbx_uint64_t *hostids, int hostids_num, + zbx_uint64_t revision, zbx_vector_uint64_t *macro_hostids, zbx_vector_uint64_t *del_macro_hostids) +{ + int i; + zbx_vector_um_host_t hosts; + + zbx_vector_um_host_create(&hosts); + + for (i = 0; i < hostids_num; i++) + um_cache_get_hosts(cache, &hostids[i], revision, &hosts); + + if (0 != hosts.values_num) + { + zbx_vector_um_host_sort(&hosts, ZBX_DEFAULT_PTR_COMPARE_FUNC); + zbx_vector_um_host_uniq(&hosts, ZBX_DEFAULT_PTR_COMPARE_FUNC); + + for (i = 0; i < hosts.values_num; i++) + { + if (0 != hosts.values[i]->macros.values_num || 0 != hosts.values[i]->templateids.values_num) + zbx_vector_uint64_append(macro_hostids, hosts.values[i]->hostid); + else + zbx_vector_uint64_append(del_macro_hostids, hosts.values[i]->hostid); + } + } + + zbx_vector_um_host_destroy(&hosts); +} + +/********************************************************************************* + * * + * Purpose: recursively remove templates linked to the hostid from unused_hosts * + * the specified revision * + * * + * Parameters: cache - [IN] the user macro cache * + * hostid - [IN] the parent hostid * + * templates - [IN/OUT] the leftover (not linked to hosts) * + * templates * + * * + *********************************************************************************/ +static void um_cache_check_used_templates(const zbx_um_cache_t *cache, zbx_uint64_t hostid, + zbx_hashset_t *templates) +{ + void *data; + zbx_um_host_t **phost; + zbx_uint64_t *phostid = &hostid; + int i; + + if (NULL != (data = zbx_hashset_search(templates, &hostid))) + zbx_hashset_remove_direct(templates, data); + + if (NULL == (phost = (zbx_um_host_t **)zbx_hashset_search(&cache->hosts, &phostid))) + return; + + for (i = 0; i < (*phost)->templateids.values_num; i++) + um_cache_check_used_templates(cache, (*phost)->templateids.values[i], templates); +} + +/********************************************************************************* + * * + * Purpose: get identifiers of templates not linked to the specified hosts * + * neither directly nor through other templates * + * * + * Parameters: cache - [IN] the user macro cache * + * templates - [IN] the database templates * + * hostids - [IN] the database hosts * + * templateids - [IN/OUT] the templates not linked to any host * + * neither directly nor through other * + * templates * + * * + *********************************************************************************/ +void um_cache_get_unused_templates(zbx_um_cache_t *cache, zbx_hashset_t *templates, + const zbx_vector_uint64_t *hostids, zbx_vector_uint64_t *templateids) +{ + zbx_hashset_iter_t iter; + int i; + zbx_uint64_t *phostid; + + for (i = 0; i < hostids->values_num; i++) + um_cache_check_used_templates(cache, hostids->values[i], templates); + + zbx_hashset_iter_reset(templates, &iter); + while (NULL != (phostid = (zbx_uint64_t *)zbx_hashset_iter_next(&iter))) + zbx_vector_uint64_append(templateids, *phostid); +} + +/********************************************************************************* + * * + * Purpose: remove deleted hosts/templates from user macro cache * + * * + * Parameters: cache - [IN] the user macro cache * + * hostids - [IN] the deleted host/template identifiers * + * * + *********************************************************************************/ +void um_cache_remove_hosts(zbx_um_cache_t *cache, const zbx_vector_uint64_t *hostids) +{ + zbx_um_host_t **phost; + int i; + + for (i = 0; i < hostids->values_num; i++) + { + zbx_uint64_t *phostid = &hostids->values[i]; + + if (NULL != (phost = (zbx_um_host_t **)zbx_hashset_search(&cache->hosts, &phostid))) + { + zbx_hashset_remove_direct(&cache->hosts, phost); + um_host_release(*phost); + } + } +} diff --git a/src/libs/zbxdbcache/user_macro.h b/src/libs/zbxdbcache/user_macro.h index b3b288958a0..3ec3defaf07 100644 --- a/src/libs/zbxdbcache/user_macro.h +++ b/src/libs/zbxdbcache/user_macro.h @@ -46,7 +46,8 @@ typedef struct zbx_vector_uint64_t templateids; zbx_vector_um_macro_t macros; zbx_uint32_t refcount; - zbx_uint32_t revision; + zbx_uint64_t macro_revision; + zbx_uint64_t link_revision; } zbx_um_host_t; @@ -56,7 +57,7 @@ typedef struct { zbx_hashset_t hosts; zbx_uint32_t refcount; - zbx_uint32_t revision; + zbx_uint64_t revision; } zbx_um_cache_t; @@ -67,7 +68,7 @@ zbx_um_cache_t *um_cache_create(void); void um_cache_release(zbx_um_cache_t *cache); void um_macro_release(zbx_um_macro_t *macro); -zbx_um_cache_t *um_cache_set_value_to_macros(zbx_um_cache_t *cache, zbx_uint32_t revision, +zbx_um_cache_t *um_cache_set_value_to_macros(zbx_um_cache_t *cache, zbx_uint64_t revision, const zbx_vector_uint64_pair_t *host_macro_ids, const char *value); int um_macro_check_vault_location(const zbx_um_macro_t *macro, const char *location); @@ -76,7 +77,13 @@ void um_cache_resolve_const(const zbx_um_cache_t *cache, const zbx_uint64_t *hos const char *macro, int env, const char **value); void um_cache_resolve(const zbx_um_cache_t *cache, const zbx_uint64_t *hostids, int hostids_num, const char *macro, int env, char **value); -int um_cache_get_host_revision(const zbx_um_cache_t *cache, zbx_uint64_t hostid, zbx_uint32_t *revision); +int um_cache_get_host_revision(const zbx_um_cache_t *cache, zbx_uint64_t hostid, zbx_uint64_t *revision); +void um_cache_get_macro_updates(const zbx_um_cache_t *cache, const zbx_uint64_t *hostids, int hostids_num, + zbx_uint64_t revision, zbx_vector_uint64_t *macro_hostids, zbx_vector_uint64_t *del_macro_hostids); + +void um_cache_get_unused_templates(zbx_um_cache_t *cache, zbx_hashset_t *templates, + const zbx_vector_uint64_t *hostids, zbx_vector_uint64_t *templateids); +void um_cache_remove_hosts(zbx_um_cache_t *cache, const zbx_vector_uint64_t *hostids); void um_cache_dump(zbx_um_cache_t *cache); diff --git a/src/libs/zbxdbcache/valuecache.c b/src/libs/zbxdbcache/valuecache.c index d2d2e0bb587..d6bbe498676 100644 --- a/src/libs/zbxdbcache/valuecache.c +++ b/src/libs/zbxdbcache/valuecache.c @@ -285,7 +285,7 @@ static void vc_history_record_vector_clean(zbx_vector_history_record_t *vector, static size_t vch_item_free_cache(zbx_vc_item_t *item); static size_t vch_item_free_chunk(zbx_vc_item_t *item, zbx_vc_chunk_t *chunk); static int vch_item_add_values_at_tail(zbx_vc_item_t *item, const zbx_history_record_t *values, int values_num); -static void vch_item_clean_cache(zbx_vc_item_t *item); +static void vch_item_clean_cache(zbx_vc_item_t *item, int timestamp); /********************************************************************************* * * @@ -541,12 +541,12 @@ static int vc_db_get_values(zbx_uint64_t itemid, int value_type, zbx_vector_hist static zbx_hash_t vc_strpool_hash_func(const void *data) { - return ZBX_DEFAULT_STRING_HASH_FUNC((char *)data + REFCOUNT_FIELD_SIZE); + return ZBX_DEFAULT_STRING_HASH_FUNC((const char *)data + REFCOUNT_FIELD_SIZE); } static int vc_strpool_compare_func(const void *d1, const void *d2) { - return strcmp((char *)d1 + REFCOUNT_FIELD_SIZE, (char *)d2 + REFCOUNT_FIELD_SIZE); + return strcmp((const char *)d1 + REFCOUNT_FIELD_SIZE, (const char *)d2 + REFCOUNT_FIELD_SIZE); } /****************************************************************************** @@ -649,7 +649,7 @@ static void vc_update_statistics(zbx_vc_item_t *item, int hits, int misses, int { int hour; - item->hits += hits; + item->hits += (zbx_uint64_t)hits; item->last_accessed = now; hour = item->last_accessed / SEC_PER_HOUR; @@ -666,8 +666,8 @@ static void vc_update_statistics(zbx_vc_item_t *item, int hits, int misses, int if (ZBX_VC_ENABLED == vc_state) { - vc_cache->hits += hits; - vc_cache->misses += misses; + vc_cache->hits += (zbx_uint64_t)hits; + vc_cache->misses += (zbx_uint64_t)misses; } } @@ -678,8 +678,8 @@ static void vc_update_statistics(zbx_vc_item_t *item, int hits, int misses, int ******************************************************************************/ static int vc_compare_items_by_total_values(const void *d1, const void *d2) { - zbx_vc_item_t *c1 = *(zbx_vc_item_t **)d1; - zbx_vc_item_t *c2 = *(zbx_vc_item_t **)d2; + const zbx_vc_item_t *c1 = *(const zbx_vc_item_t * const *)d1; + const zbx_vc_item_t *c2 = *(const zbx_vc_item_t * const *)d2; ZBX_RETURN_IF_NOT_EQUAL(c2->values_total, c1->values_total); @@ -738,7 +738,7 @@ static void vc_warn_low_memory(void) { int now; - now = time(NULL); + now = (int)time(NULL); if (now - vc_cache->mode_time > ZBX_VC_LOW_MEMORY_RESET_PERIOD) { @@ -779,7 +779,7 @@ static size_t vc_release_unused_items(const zbx_vc_item_t *source_item) if (NULL == vc_cache) return freed; - timestamp = time(NULL) - ZBX_VC_ITEM_EXPIRE_PERIOD; + timestamp = (int)time(NULL) - ZBX_VC_ITEM_EXPIRE_PERIOD; zbx_hashset_iter_reset(&vc_cache->items, &iter); @@ -797,25 +797,6 @@ static size_t vc_release_unused_items(const zbx_vc_item_t *source_item) /****************************************************************************** * * - * Purpose: release unused items from value cache * - * * - * Comments: If unused items are not cleared from value cache periodically * - * then they will only be cleared when value cache is full, see * - * vc_release_space(). * - * * - ******************************************************************************/ -void zbx_vc_housekeeping_value_cache(void) -{ - if (ZBX_VC_DISABLED == vc_state) - return; - - WRLOCK_CACHE; - vc_release_unused_items(NULL); - UNLOCK_CACHE; -} - -/****************************************************************************** - * * * Purpose: frees space in cache to store the specified number of bytes by * * dropping the least accessed items * * * @@ -847,7 +828,7 @@ static void vc_release_space(zbx_vc_item_t *source_item, size_t space) /* failed to free enough space by removing old items, entering low memory mode */ vc_cache->mode = ZBX_VC_MODE_LOWMEM; - vc_cache->mode_time = time(NULL); + vc_cache->mode_time = (int)time(NULL); vc_warn_low_memory(); @@ -1189,6 +1170,36 @@ static void vc_remove_item_by_id(zbx_uint64_t itemid) vch_item_free_cache(item); zbx_hashset_remove_direct(&vc_cache->items, item); } + +/****************************************************************************** + * * + * Purpose: removes items from cache and frees resources allocated for them * + * * + * Parameters: itemids - [IN] the item identifiers * + * * + * Comments: If unused items are not cleared from value cache periodically * + * then they will only be cleared when value cache is full, see * + * vc_release_space(). Cleared items can be cached again. * + * * + ******************************************************************************/ +void zbx_vc_remove_items_by_ids(zbx_vector_uint64_t *itemids) +{ + int i; + + if (ZBX_VC_DISABLED == vc_state) + return; + + if (0 == itemids->values_num) + return; + + WRLOCK_CACHE; + + for (i = 0; i < itemids->values_num; i++) + vc_remove_item_by_id(itemids->values[i]); + + UNLOCK_CACHE; +} + /****************************************************************************** * * * Purpose: updates the timestamp from which the item is being cached * @@ -1256,7 +1267,8 @@ static void vc_item_update_db_cached_from(zbx_vc_item_t *item, int timestamp) ******************************************************************************/ static void vch_item_update_range(zbx_vc_item_t *item, int range, int now) { - int hour, diff; + int diff, last_value_timestamp; + unsigned char hour; if (VC_MIN_RANGE > range) range = VC_MIN_RANGE; @@ -1264,12 +1276,18 @@ static void vch_item_update_range(zbx_vc_item_t *item, int range, int now) if (item->daily_range < range) item->daily_range = range; - hour = (now / SEC_PER_HOUR) & 0xff; + hour = (unsigned char)((now / SEC_PER_HOUR) & 0xff); if (0 > (diff = hour - item->range_sync_hour)) diff += 0xff; - if (item->active_range < item->daily_range || ZBX_VC_RANGE_SYNC_PERIOD < diff) + if (NULL != item->head) + last_value_timestamp = item->head->slots[item->head->last_value].timestamp.sec; + else + last_value_timestamp = now; + + if (item->active_range < item->daily_range || (ZBX_VC_RANGE_SYNC_PERIOD < diff && + (now - last_value_timestamp) / SEC_PER_HOUR < ZBX_VC_RANGE_SYNC_PERIOD)) { item->active_range = item->daily_range; item->daily_range = range; @@ -1299,7 +1317,7 @@ static int vch_item_chunk_slot_count(zbx_vc_item_t *item, int values_new) values = item->values_total + values_new; - nslots = zbx_isqrt32(values); + nslots = (int)zbx_isqrt32((unsigned int)values); if ((values + nslots - 1) / nslots + 1 > 32) nslots = values / 32; @@ -1330,9 +1348,9 @@ static int vch_item_chunk_slot_count(zbx_vc_item_t *item, int values_new) static int vch_item_add_chunk(zbx_vc_item_t *item, int nslots, zbx_vc_chunk_t *insert_before) { zbx_vc_chunk_t *chunk; - int chunk_size; + size_t chunk_size; - chunk_size = sizeof(zbx_vc_chunk_t) + sizeof(zbx_history_record_t) * (nslots - 1); + chunk_size =sizeof(zbx_vc_chunk_t) + sizeof(zbx_history_record_t) * (size_t)(nslots - 1); if (NULL == (chunk = (zbx_vc_chunk_t *)vc_item_malloc(item, chunk_size))) return FAIL; @@ -1562,7 +1580,7 @@ static int vch_item_copy_values_at_tail(zbx_vc_item_t *item, const zbx_history_r break; default: memcpy(&item->tail->slots[item->tail->first_value - values_num], values, - values_num * sizeof(zbx_history_record_t)); + (size_t)values_num * sizeof(zbx_history_record_t)); item->tail->first_value -= values_num; ret = SUCCEED; } @@ -1586,7 +1604,7 @@ static size_t vch_item_free_chunk(zbx_vc_item_t *item, zbx_vc_chunk_t *chunk) { size_t freed; - freed = sizeof(zbx_vc_chunk_t) + (chunk->slots_num - 1) * sizeof(zbx_history_record_t); + freed = sizeof(zbx_vc_chunk_t) + (size_t)(chunk->slots_num - 1) * sizeof(zbx_history_record_t); freed += vc_item_free_values(item, chunk->slots, chunk->first_value, chunk->last_value); __vc_shmem_free_func(chunk); @@ -1624,10 +1642,11 @@ static void vch_item_remove_chunk(zbx_vc_item_t *item, zbx_vc_chunk_t *chunk) * Purpose: removes item history data that are outside (older) the maximum * * request range * * * - * Parameters: item - [IN] the target item * + * Parameters: item - [IN] the target item * + * timestamp - [IN] last timestamp in active range * * * ******************************************************************************/ -static void vch_item_clean_cache(zbx_vc_item_t *item) +static void vch_item_clean_cache(zbx_vc_item_t *item, int timestamp) { zbx_vc_chunk_t *next; @@ -1635,11 +1654,12 @@ static void vch_item_clean_cache(zbx_vc_item_t *item) { zbx_vc_chunk_t *tail = item->tail; zbx_vc_chunk_t *chunk = tail; - int timestamp; - timestamp = time(NULL) - item->active_range; + timestamp -= item->active_range; - /* try to remove chunks with all history values older than maximum request range */ + /* Try to remove chunks with all history values older than maximum request range, maximum */ + /* request range should be calculated from last received value with which active range */ + /* was calculated to avoid dropping of chunks that might be still used in count request. */ while (NULL != chunk && chunk->slots[chunk->last_value].timestamp.sec < timestamp && chunk->slots[chunk->last_value].timestamp.sec != item->head->slots[item->head->last_value].timestamp.sec) @@ -2128,7 +2148,7 @@ static void vch_item_get_values_by_time(const zbx_vc_item_t *item, zbx_vector_hi /* range which might be greater than the current request range. */ if (0 != item->active_range || ZBX_ITEM_STATUS_CACHED_ALL != item->status) { - now = time(NULL); + now = (int)time(NULL); /* add another second to include nanosecond shifts */ vc_cache_item_update(item->itemid, ZBX_VC_UPDATE_RANGE, seconds + now - ts->sec + 1, now); } @@ -2227,7 +2247,7 @@ out: range_timestamp = values->values[values->values_num - 1].timestamp.sec - 1; } - now = time(NULL); + now = (int)time(NULL); vc_cache_item_update(item->itemid, ZBX_VC_UPDATE_RANGE, now - range_timestamp, now); } @@ -2494,7 +2514,6 @@ int zbx_vc_add_values(zbx_vector_ptr_t *history, int *ret_flush) zbx_vc_item_t *item; int i; ZBX_DC_HISTORY *h; - time_t expire_timestamp; if (SUCCEED != zbx_history_add_values(history, ret_flush)) return FAIL; @@ -2502,8 +2521,6 @@ int zbx_vc_add_values(zbx_vector_ptr_t *history, int *ret_flush) if (ZBX_VC_DISABLED == vc_state) return SUCCEED; - expire_timestamp = time(NULL) - ZBX_VC_ITEM_EXPIRE_PERIOD; - WRLOCK_CACHE; for (i = 0; i < history->values_num; i++) @@ -2514,6 +2531,12 @@ int zbx_vc_add_values(zbx_vector_ptr_t *history, int *ret_flush) { zbx_history_record_t record = {h->ts, h->value}; zbx_vc_chunk_t *head = item->head; + int last_value_timestamp; + + if (NULL != head) + last_value_timestamp = head->slots[head->last_value].timestamp.sec; + else + last_value_timestamp = (int)time(NULL); /* If the new value type does not match the item's type in cache remove it, */ /* so it's cached with the correct type from correct tables when accessed */ @@ -2521,8 +2544,7 @@ int zbx_vc_add_values(zbx_vector_ptr_t *history, int *ret_flush) /* Also remove item if the value adding failed. In this case we */ /* won't have the latest data in cache - so the requests must go directly */ /* to the database. */ - if (item->value_type != h->value_type || item->last_accessed < expire_timestamp || - FAIL == vch_item_add_value_at_head(item, &record)) + if (item->value_type != h->value_type || FAIL == vch_item_add_value_at_head(item, &record)) { vc_remove_item(item); continue; @@ -2530,8 +2552,7 @@ int zbx_vc_add_values(zbx_vector_ptr_t *history, int *ret_flush) /* try to remove old (unused) chunks if a new chunk was added */ if (head != item->head) - vch_item_clean_cache(item); - + vch_item_clean_cache(item, last_value_timestamp); } } @@ -2563,8 +2584,8 @@ int zbx_vc_add_values(zbx_vector_ptr_t *history, int *ret_flush) * seconds before <timestamp>. * * * ******************************************************************************/ -int zbx_vc_get_values(zbx_uint64_t itemid, int value_type, zbx_vector_history_record_t *values, int seconds, - int count, const zbx_timespec_t *ts) +int zbx_vc_get_values(zbx_uint64_t itemid, unsigned char value_type, zbx_vector_history_record_t *values, + int seconds, int count, const zbx_timespec_t *ts) { zbx_vc_item_t *item, new_item; int ret = FAIL, cache_used = 1; @@ -2607,7 +2628,7 @@ out: vc_remove_item_by_id(itemid); if (SUCCEED == ret) - vc_update_statistics(NULL, 0, values->values_num, time(NULL)); + vc_update_statistics(NULL, 0, values->values_num, (int)time(NULL)); } UNLOCK_CACHE; @@ -2636,7 +2657,8 @@ out: * function. * * * ******************************************************************************/ -int zbx_vc_get_value(zbx_uint64_t itemid, int value_type, const zbx_timespec_t *ts, zbx_history_record_t *value) +int zbx_vc_get_value(zbx_uint64_t itemid, unsigned char value_type, const zbx_timespec_t *ts, + zbx_history_record_t *value) { zbx_vector_history_record_t values; int ret = FAIL; @@ -2730,12 +2752,12 @@ void zbx_vc_get_diag_stats(zbx_uint64_t *items_num, zbx_uint64_t *values_num, in RDLOCK_CACHE; - *items_num = vc_cache->items.num_data; + *items_num = (zbx_uint64_t)vc_cache->items.num_data; *mode = vc_cache->mode; zbx_hashset_iter_reset(&vc_cache->items, &iter); while (NULL != (item = (zbx_vc_item_t *)zbx_hashset_iter_next(&iter))) - *values_num += item->values_total; + *values_num += (zbx_uint64_t)item->values_total; UNLOCK_CACHE; } @@ -2774,7 +2796,7 @@ void zbx_vc_get_item_stats(zbx_vector_ptr_t *stats) RDLOCK_CACHE; - zbx_vector_ptr_reserve(stats, vc_cache->items.num_data); + zbx_vector_ptr_reserve(stats, (size_t)vc_cache->items.num_data); zbx_hashset_iter_reset(&vc_cache->items, &iter); while (NULL != (item = (zbx_vc_item_t *)zbx_hashset_iter_next(&iter))) @@ -2805,7 +2827,7 @@ void zbx_vc_flush_stats(void) zbx_vector_vc_itemupdate_sort(&vc_itemupdates, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - now = time(NULL); + now = (int)time(NULL); WRLOCK_CACHE; diff --git a/src/libs/zbxdbcache/valuecache.h b/src/libs/zbxdbcache/valuecache.h index 3b280e5a4df..d61e1b52d22 100644 --- a/src/libs/zbxdbcache/valuecache.h +++ b/src/libs/zbxdbcache/valuecache.h @@ -102,16 +102,17 @@ void zbx_vc_enable(void); void zbx_vc_disable(void); -int zbx_vc_get_values(zbx_uint64_t itemid, int value_type, zbx_vector_history_record_t *values, int seconds, - int count, const zbx_timespec_t *ts); +int zbx_vc_get_values(zbx_uint64_t itemid, unsigned char value_type, zbx_vector_history_record_t *values, + int seconds, int count, const zbx_timespec_t *ts); -int zbx_vc_get_value(zbx_uint64_t itemid, int value_type, const zbx_timespec_t *ts, zbx_history_record_t *value); +int zbx_vc_get_value(zbx_uint64_t itemid, unsigned char value_type, const zbx_timespec_t *ts, + zbx_history_record_t *value); int zbx_vc_add_values(zbx_vector_ptr_t *history, int *ret_flush); int zbx_vc_get_statistics(zbx_vc_stats_t *stats); -void zbx_vc_housekeeping_value_cache(void); +void zbx_vc_remove_items_by_ids(zbx_vector_uint64_t *itemids); void zbx_vc_get_diag_stats(zbx_uint64_t *items_num, zbx_uint64_t *values_num, int *mode); void zbx_vc_get_mem_stats(zbx_shmem_stats_t *mem); diff --git a/src/libs/zbxdbhigh/graph_linking.c b/src/libs/zbxdbhigh/graph_linking.c index 37809d4d2d1..133afb11433 100644 --- a/src/libs/zbxdbhigh/graph_linking.c +++ b/src/libs/zbxdbhigh/graph_linking.c @@ -1051,7 +1051,7 @@ static int update_graphs_items_updates(char **sql, size_t *sql_alloc, size_t *sq d2 = ","; zbx_audit_graph_update_json_update_gitem_update_drawtype(graphid, - (int)graph_flags, host_items_entry->gitemid, + graph_flags, host_items_entry->gitemid, host_items_entry->drawtype_orig, host_items_entry->drawtype_new); } @@ -1063,7 +1063,7 @@ static int update_graphs_items_updates(char **sql, size_t *sql_alloc, size_t *sq d2 = ","; zbx_audit_graph_update_json_update_gitem_update_sortorder(graphid, - (int)graph_flags, host_items_entry->gitemid, + graph_flags, host_items_entry->gitemid, host_items_entry->sortorder_orig, host_items_entry->sortorder_new); } @@ -1077,7 +1077,7 @@ static int update_graphs_items_updates(char **sql, size_t *sql_alloc, size_t *sq zbx_free(color_esc); d2 = ","; - zbx_audit_graph_update_json_update_gitem_update_color(graphid, (int)graph_flags, + zbx_audit_graph_update_json_update_gitem_update_color(graphid, graph_flags, host_items_entry->gitemid, host_items_entry->color_orig, host_items_entry->color_new); } @@ -1089,7 +1089,7 @@ static int update_graphs_items_updates(char **sql, size_t *sql_alloc, size_t *sq d2 = ","; zbx_audit_graph_update_json_update_gitem_update_yaxisside(graphid, - (int)graph_flags, host_items_entry->gitemid, + graph_flags, host_items_entry->gitemid, host_items_entry->yaxisside_orig, host_items_entry->yaxisside_new); } @@ -1101,7 +1101,7 @@ static int update_graphs_items_updates(char **sql, size_t *sql_alloc, size_t *sq d2 = ","; zbx_audit_graph_update_json_update_gitem_update_calc_fnc(graphid, - (int)graph_flags, host_items_entry->gitemid, + graph_flags, host_items_entry->gitemid, host_items_entry->calc_fnc_orig, host_items_entry->calc_fnc_new); } @@ -1111,7 +1111,7 @@ static int update_graphs_items_updates(char **sql, size_t *sql_alloc, size_t *sq zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%stype=%d", d2, host_items_entry->type_new); - zbx_audit_graph_update_json_update_gitem_update_type(graphid, (int)graph_flags, + zbx_audit_graph_update_json_update_gitem_update_type(graphid, graph_flags, host_items_entry->gitemid, host_items_entry->type_orig, host_items_entry->type_new); } diff --git a/src/libs/zbxdbhigh/host.c b/src/libs/zbxdbhigh/host.c index a186bfe5065..f8b7f6b4596 100644 --- a/src/libs/zbxdbhigh/host.c +++ b/src/libs/zbxdbhigh/host.c @@ -1020,7 +1020,7 @@ void DBdelete_triggers(zbx_vector_uint64_t *triggerids) } for (i = 0; i < triggerids->values_num; i++) - DBdelete_action_conditions(CONDITION_TYPE_TRIGGER, triggerids->values[i]); + DBdelete_action_conditions(ZBX_CONDITION_TYPE_TRIGGER, triggerids->values[i]); zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from trigger_tag where"); DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "triggerid", triggerids->values, triggerids->values_num); @@ -1456,6 +1456,7 @@ static void DBdelete_httptests(const zbx_vector_uint64_t *httptestids) char *sql = NULL; size_t sql_alloc = 256, sql_offset = 0; zbx_vector_uint64_t itemids; + zbx_vector_uint64_t httpstepids; zabbix_log(LOG_LEVEL_DEBUG, "In %s() values_num:%d", __func__, httptestids->values_num); @@ -1464,6 +1465,7 @@ static void DBdelete_httptests(const zbx_vector_uint64_t *httptestids) sql = (char *)zbx_malloc(sql, sql_alloc); zbx_vector_uint64_create(&itemids); + zbx_vector_uint64_create(&httpstepids); /* httpstepitem, httptestitem */ sql_offset = 0; @@ -1485,6 +1487,45 @@ static void DBdelete_httptests(const zbx_vector_uint64_t *httptestids) if (FAIL == zbx_audit_DBselect_delete_for_item(sql, &itemids)) goto clean; + + sql_offset = 0; + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select httpstepid from httpstep where"); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "httptestid", + httptestids->values, httptestids->values_num); + DBselect_uint64(sql, &httpstepids); + + sql_offset = 0; + zbx_DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset); + + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from httptest_field where"); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "httptestid", + httptestids->values, httptestids->values_num); + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n"); + + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from httptestitem where"); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "httptestid", + httptestids->values, httptestids->values_num); + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n"); + + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from httpstep_field where"); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "httpstepid", + httpstepids.values, httpstepids.values_num); + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n"); + + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from httpstepitem where"); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "httpstepid", + httpstepids.values, httpstepids.values_num); + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n"); + + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from httpstep where"); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "httpstepid", + httpstepids.values, httpstepids.values_num); + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n"); + + zbx_DBend_multiple_update(&sql, &sql_alloc, &sql_offset); + + DBexecute("%s", sql); + DBdelete_items(&itemids); sql_offset = 0; @@ -1493,6 +1534,7 @@ static void DBdelete_httptests(const zbx_vector_uint64_t *httptestids) httptestids->values, httptestids->values_num); DBexecute("%s", sql); clean: + zbx_vector_uint64_destroy(&httpstepids); zbx_vector_uint64_destroy(&itemids); zbx_free(sql); out: @@ -5871,7 +5913,7 @@ void DBdelete_hosts(const zbx_vector_uint64_t *hostids, const zbx_vector_str_t * /* delete action conditions */ for (i = 0; i < hostids->values_num; i++) - DBdelete_action_conditions(CONDITION_TYPE_HOST, hostids->values[i]); + DBdelete_action_conditions(ZBX_CONDITION_TYPE_HOST, hostids->values[i]); /* delete host tags */ zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from host_tag where"); @@ -6375,7 +6417,7 @@ void DBdelete_groups(zbx_vector_uint64_t *groupids) goto out; for (i = 0; i < groupids->values_num; i++) - DBdelete_action_conditions(CONDITION_TYPE_HOST_GROUP, groupids->values[i]); + DBdelete_action_conditions(ZBX_CONDITION_TYPE_HOST_GROUP, groupids->values[i]); sql = (char *)zbx_malloc(sql, sql_alloc); diff --git a/src/libs/zbxdbhigh/proxy.c b/src/libs/zbxdbhigh/proxy.c index d7f2ba26752..984b40843f0 100644 --- a/src/libs/zbxdbhigh/proxy.c +++ b/src/libs/zbxdbhigh/proxy.c @@ -37,9 +37,10 @@ #include "zbxnum.h" #include "zbxtime.h" #include "zbxip.h" +#include "version.h" +#include "zbxversion.h" extern char *CONFIG_SERVER; -extern char *CONFIG_VAULTDBPATH; /* the space reserved in json buffer to hold at least one record plus service data */ #define ZBX_DATA_JSON_RESERVED (ZBX_HISTORY_TEXT_VALUE_LEN * 4 + ZBX_KIBIBYTE * 4) @@ -81,13 +82,6 @@ typedef struct } zbx_history_table_t; -typedef struct -{ - zbx_uint64_t id; - size_t offset; -} -zbx_id_offset_t; - typedef int (*zbx_client_item_validator_t)(DC_ITEM *item, zbx_socket_t *sock, void *args, char **error); typedef struct @@ -127,13 +121,6 @@ static zbx_history_table_t areg = { } }; -typedef struct -{ - char *path; - zbx_hashset_t keys; -} -zbx_keys_path_t; - /****************************************************************************** * * * Purpose: check proxy connection permissions (encryption configuration and * @@ -330,7 +317,7 @@ static int zbx_host_check_permissions(const DC_HOST *host, const zbx_socket_t *s * configured in passive mode or access denied) * * * ******************************************************************************/ -int get_active_proxy_from_request(struct zbx_json_parse *jp, DC_PROXY *proxy, char **error) +int get_active_proxy_from_request(const struct zbx_json_parse *jp, DC_PROXY *proxy, char **error) { char *ch_error, host[ZBX_HOSTNAME_BUF_LEN]; @@ -436,1666 +423,6 @@ int check_access_passive_proxy(zbx_socket_t *sock, int send_response, const char /****************************************************************************** * * - * Purpose: add database row to the proxy config json data * - * * - * Parameters: j - [OUT] the output json * - * row - [IN] the database row to add * - * table - [IN] the table configuration * - * * - ******************************************************************************/ -static void proxyconfig_add_row(struct zbx_json *j, const DB_ROW row, const ZBX_TABLE *table) -{ - int fld = 0, i; - - zbx_json_addstring(j, NULL, row[fld++], ZBX_JSON_TYPE_INT); - - for (i = 0; 0 != table->fields[i].name; i++) - { - if (0 == (table->fields[i].flags & ZBX_PROXY)) - continue; - - switch (table->fields[i].type) - { - case ZBX_TYPE_INT: - case ZBX_TYPE_UINT: - case ZBX_TYPE_ID: - if (SUCCEED != DBis_null(row[fld])) - zbx_json_addstring(j, NULL, row[fld], ZBX_JSON_TYPE_INT); - else - zbx_json_addstring(j, NULL, NULL, ZBX_JSON_TYPE_NULL); - break; - default: - zbx_json_addstring(j, NULL, row[fld], ZBX_JSON_TYPE_STRING); - break; - } - fld++; - } -} - -typedef struct -{ - zbx_uint64_t itemid; - zbx_uint64_t master_itemid; - char *buffer; -} -zbx_proxy_item_config_t; - -/****************************************************************************** - * * - * Purpose: prepare items table proxy configuration data * - * * - ******************************************************************************/ -static int get_proxyconfig_table_items(zbx_uint64_t proxy_hostid, struct zbx_json *j, const ZBX_TABLE *table, - zbx_hashset_t *itemids) -{ - char *sql = NULL; - size_t sql_alloc = 4 * ZBX_KIBIBYTE, sql_offset = 0; - int f, fld, fld_type = -1, fld_key = -1, fld_master = -1, ret = SUCCEED; - DB_RESULT result; - DB_ROW row; - zbx_hashset_t proxy_items; - zbx_vector_ptr_t items; - zbx_uint64_t itemid; - zbx_hashset_iter_t iter; - struct zbx_json json_array; - - zabbix_log(LOG_LEVEL_DEBUG, "In %s() proxy_hostid:" ZBX_FS_UI64, __func__, proxy_hostid); - - zbx_json_addobject(j, table->table); - zbx_json_addarray(j, "fields"); - - sql = (char *)zbx_malloc(sql, sql_alloc); - - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "select t.%s", table->recid); - - zbx_json_addstring(j, NULL, table->recid, ZBX_JSON_TYPE_STRING); - - for (f = 0, fld = 1; 0 != table->fields[f].name; f++) - { - if (0 == (table->fields[f].flags & ZBX_PROXY)) - continue; - - zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ",t."); - zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, table->fields[f].name); - - zbx_json_addstring(j, NULL, table->fields[f].name, ZBX_JSON_TYPE_STRING); - - if (0 == strcmp(table->fields[f].name, "type")) - fld_type = fld; - else if (0 == strcmp(table->fields[f].name, "key_")) - fld_key = fld; - else if (0 == strcmp(table->fields[f].name, "master_itemid")) - fld_master = fld; - fld++; - } - - if (-1 == fld_type || -1 == fld_key || -1 == fld_master) - { - THIS_SHOULD_NEVER_HAPPEN; - exit(EXIT_FAILURE); - } - - zbx_json_close(j); /* fields */ - - zbx_json_addarray(j, "data"); - - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, - " from items t,hosts r where t.hostid=r.hostid" - " and r.proxy_hostid=" ZBX_FS_UI64 - " and r.status in (%d,%d)" - " and t.flags<>%d" - " and t.type in (%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)" - " order by t.%s", - proxy_hostid, - HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED, - ZBX_FLAG_DISCOVERY_PROTOTYPE, - ITEM_TYPE_ZABBIX, ITEM_TYPE_ZABBIX_ACTIVE, ITEM_TYPE_SNMP, ITEM_TYPE_IPMI, ITEM_TYPE_TRAPPER, - ITEM_TYPE_SIMPLE, ITEM_TYPE_HTTPTEST, ITEM_TYPE_EXTERNAL, ITEM_TYPE_DB_MONITOR, ITEM_TYPE_SSH, - ITEM_TYPE_TELNET, ITEM_TYPE_JMX, ITEM_TYPE_SNMPTRAP, ITEM_TYPE_INTERNAL, - ITEM_TYPE_HTTPAGENT, ITEM_TYPE_DEPENDENT, ITEM_TYPE_SCRIPT, - table->recid); - - if (NULL == (result = DBselect("%s", sql))) - { - ret = FAIL; - goto skip_data; - } - - zbx_hashset_create(&proxy_items, 1000, ZBX_DEFAULT_UINT64_HASH_FUNC, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - zbx_json_initarray(&json_array, 256); - - while (NULL != (row = DBfetch(result))) - { - if (SUCCEED == is_item_processed_by_server(atoi(row[fld_type]), row[fld_key])) - continue; - - if (SUCCEED != DBis_null(row[fld_master])) - { - zbx_proxy_item_config_t proxy_item_local, *proxy_item; - - ZBX_STR2UINT64(proxy_item_local.itemid, row[0]); - ZBX_STR2UINT64(proxy_item_local.master_itemid, row[fld_master]); - proxy_item = zbx_hashset_insert(&proxy_items, &proxy_item_local, sizeof(proxy_item_local)); - - proxyconfig_add_row(&json_array, row, table); - - proxy_item->buffer = zbx_malloc(NULL, json_array.buffer_size + 1); - memcpy(proxy_item->buffer, json_array.buffer, json_array.buffer_size + 1); - - zbx_json_cleanarray(&json_array); - } - else - { - ZBX_STR2UINT64(itemid, row[0]); - zbx_hashset_insert(itemids, &itemid, sizeof(itemid)); - - zbx_json_addarray(j, NULL); - proxyconfig_add_row(j, row, table); - zbx_json_close(j); - } - } - DBfree_result(result); - zbx_json_free(&json_array); - - /* flush cached dependent items */ - - zbx_vector_ptr_create(&items); - while (0 != proxy_items.num_data) - { - zbx_proxy_item_config_t *proxy_item; - int i; - - zbx_hashset_iter_reset(&proxy_items, &iter); - while (NULL != (proxy_item = (zbx_proxy_item_config_t *)zbx_hashset_iter_next(&iter))) - { - if (NULL == zbx_hashset_search(&proxy_items, &proxy_item->master_itemid)) - zbx_vector_ptr_append(&items, proxy_item); - } - - if (0 == items.values_num) - { - THIS_SHOULD_NEVER_HAPPEN; - exit(EXIT_FAILURE); - } - - zbx_vector_ptr_sort(&items, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC); - for (i = 0; i < items.values_num; i++) - { - proxy_item = (zbx_proxy_item_config_t *)items.values[i]; - if (NULL != zbx_hashset_search(itemids, &proxy_item->master_itemid)) - { - zbx_hashset_insert(itemids, &proxy_item->itemid, sizeof(itemid)); - zbx_json_addraw(j, NULL, proxy_item->buffer); - } - zbx_free(proxy_item->buffer); - zbx_hashset_remove_direct(&proxy_items, proxy_item); - } - - zbx_vector_ptr_clear(&items); - } - zbx_vector_ptr_destroy(&items); - zbx_hashset_destroy(&proxy_items); -skip_data: - zbx_free(sql); - - zbx_json_close(j); /* data */ - zbx_json_close(j); /* table->table */ - - zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); - - return ret; -} - -/****************************************************************************** - * * - * Purpose: prepare items table proxy configuration data * - * * - ******************************************************************************/ -static int get_proxyconfig_table_items_ext(zbx_uint64_t proxy_hostid, const zbx_hashset_t *itemids, - struct zbx_json *j, const ZBX_TABLE *table) -{ - char *sql = NULL; - size_t sql_alloc = 4 * ZBX_KIBIBYTE, sql_offset = 0; - int f, ret = SUCCEED, index = 1, itemid_index = 0; - DB_RESULT result; - DB_ROW row; - - zabbix_log(LOG_LEVEL_DEBUG, "In %s() table:%s", __func__, table->table); - - zbx_json_addobject(j, table->table); - zbx_json_addarray(j, "fields"); - - sql = (char *)zbx_malloc(sql, sql_alloc); - - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "select t.%s", table->recid); - - zbx_json_addstring(j, NULL, table->recid, ZBX_JSON_TYPE_STRING); - - for (f = 0; 0 != table->fields[f].name; f++) - { - if (0 == (table->fields[f].flags & ZBX_PROXY)) - continue; - - /* either the table uses itemid as primary key, then it will be stored in the */ - /* first (0) column as record id, or it will have reference to items table */ - /* through itemid field */ - if (0 == strcmp(table->fields[f].name, "itemid")) - itemid_index = index; - - zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ",t."); - zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, table->fields[f].name); - zbx_json_addstring(j, NULL, table->fields[f].name, ZBX_JSON_TYPE_STRING); - index++; - } - - zbx_json_close(j); /* fields */ - - zbx_json_addarray(j, "data"); - - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, - " from %s t,items i,hosts h" - " where t.itemid=i.itemid" - " and i.hostid=h.hostid" - " and h.proxy_hostid=" ZBX_FS_UI64, - table->table, proxy_hostid); - zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " order by t."); - zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, table->recid); - - if (NULL == (result = DBselect("%s", sql))) - { - ret = FAIL; - goto skip_data; - } - - while (NULL != (row = DBfetch(result))) - { - zbx_uint64_t itemid; - - ZBX_STR2UINT64(itemid, row[itemid_index]); - if (NULL != zbx_hashset_search((zbx_hashset_t *)itemids, &itemid)) - { - zbx_json_addarray(j, NULL); - proxyconfig_add_row(j, row, table); - zbx_json_close(j); - } - } - DBfree_result(result); -skip_data: - zbx_free(sql); - - zbx_json_close(j); /* data */ - zbx_json_close(j); /* table->table */ - - zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); - - return ret; -} - -static int keys_path_compare(const void *d1, const void *d2) -{ - const zbx_keys_path_t *ptr1 = *((const zbx_keys_path_t **)d1); - const zbx_keys_path_t *ptr2 = *((const zbx_keys_path_t **)d2); - - return strcmp(ptr1->path, ptr2->path); -} - -static zbx_hash_t keys_hash(const void *data) -{ - return ZBX_DEFAULT_STRING_HASH_ALGO(*(const char **)data, strlen(*(const char **)data), ZBX_DEFAULT_HASH_SEED); -} - -static int keys_compare(const void *d1, const void *d2) -{ - return strcmp(*(const char **)d1, *(const char **)d2); -} - -static void key_path_free(void *data) -{ - zbx_hashset_iter_t iter; - char **ptr; - zbx_keys_path_t *keys_path = (zbx_keys_path_t *)data; - - zbx_hashset_iter_reset(&keys_path->keys, &iter); - while (NULL != (ptr = (char **)zbx_hashset_iter_next(&iter))) - zbx_free(*ptr); - zbx_hashset_destroy(&keys_path->keys); - - zbx_free(keys_path->path); - zbx_free(keys_path); -} - -/****************************************************************************** - * * - * Purpose: prepare proxy configuration data * - * * - ******************************************************************************/ -static int get_proxyconfig_table(zbx_uint64_t proxy_hostid, struct zbx_json *j, const ZBX_TABLE *table, - const zbx_vector_uint64_t *hosts, const zbx_vector_uint64_t *httptests, zbx_vector_ptr_t *keys_paths) -{ - char *sql = NULL; - size_t sql_alloc = 4 * ZBX_KIBIBYTE, sql_offset = 0; - int f, ret = SUCCEED, i, is_macro = 0; - DB_RESULT result; - DB_ROW row; - int offset; - - zabbix_log(LOG_LEVEL_DEBUG, "In %s() proxy_hostid:" ZBX_FS_UI64 " table:'%s'", - __func__, proxy_hostid, table->table); - - if (0 == strcmp(table->table, "globalmacro")) - { - is_macro = 1; - offset = 0; - } - else if (0 == strcmp(table->table, "hostmacro")) - { - is_macro = 1; - offset = 1; - } - - zbx_json_addobject(j, table->table); - zbx_json_addarray(j, "fields"); - - sql = (char *)zbx_malloc(sql, sql_alloc); - - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "select t.%s", table->recid); - - zbx_json_addstring(j, NULL, table->recid, ZBX_JSON_TYPE_STRING); - - for (f = 0; 0 != table->fields[f].name; f++) - { - if (0 == (table->fields[f].flags & ZBX_PROXY)) - continue; - - zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ",t."); - zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, table->fields[f].name); - - zbx_json_addstring(j, NULL, table->fields[f].name, ZBX_JSON_TYPE_STRING); - } - - zbx_json_close(j); /* fields */ - - zbx_json_addarray(j, "data"); - - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " from %s t", table->table); - - if (SUCCEED == zbx_str_in_list("hosts,interface,host_inventory,hosts_templates,hostmacro", table->table, ',')) - { - if (0 == hosts->values_num) - goto skip_data; - - zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " where"); - DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "t.hostid", hosts->values, hosts->values_num); - } - else if (0 == strcmp(table->table, "interface_snmp")) - { - if (0 == hosts->values_num) - goto skip_data; - - zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ",interface h where t.interfaceid=h.interfaceid and"); - DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "h.hostid", hosts->values, hosts->values_num); - } - else if (0 == strcmp(table->table, "drules")) - { - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, - " where t.proxy_hostid=" ZBX_FS_UI64 - " and t.status=%d", - proxy_hostid, DRULE_STATUS_MONITORED); - } - else if (0 == strcmp(table->table, "dchecks")) - { - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, - ",drules r where t.druleid=r.druleid" - " and r.proxy_hostid=" ZBX_FS_UI64 - " and r.status=%d", - proxy_hostid, DRULE_STATUS_MONITORED); - } - else if (0 == strcmp(table->table, "hstgrp")) - { - zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ",config r where t.groupid=r.discovery_groupid"); - } - else if (SUCCEED == zbx_str_in_list("httptest,httptest_field,httptestitem,httpstep", table->table, ',')) - { - if (0 == httptests->values_num) - goto skip_data; - - zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " where"); - DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "t.httptestid", - httptests->values, httptests->values_num); - } - else if (SUCCEED == zbx_str_in_list("httpstepitem,httpstep_field", table->table, ',')) - { - if (0 == httptests->values_num) - goto skip_data; - - zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, - ",httpstep r where t.httpstepid=r.httpstepid" - " and"); - DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "r.httptestid", - httptests->values, httptests->values_num); - } - - zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " order by t."); - zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, table->recid); - - if (NULL == (result = DBselect("%s", sql))) - { - ret = FAIL; - goto skip_data; - } - - while (NULL != (row = DBfetch(result))) - { - zbx_json_addarray(j, NULL); - proxyconfig_add_row(j, row, table); - zbx_json_close(j); - if (1 == is_macro) - { - zbx_keys_path_t *keys_path, keys_path_local; - unsigned char type; - char *path, *key; - - ZBX_STR2UCHAR(type, row[3 + offset]); - - if (ZBX_MACRO_VALUE_VAULT != type) - continue; - - zbx_strsplit_last(row[2 + offset], ':', &path, &key); - - if (NULL == key) - { - zabbix_log(LOG_LEVEL_WARNING, "cannot parse macro \"%s\" value \"%s\"", - row[1 + offset], row[2 + offset]); - goto next; - } - - if (NULL != CONFIG_VAULTDBPATH && 0 == strcasecmp(CONFIG_VAULTDBPATH, path) && - (0 == strcasecmp(key, ZBX_PROTO_TAG_PASSWORD) - || 0 == strcasecmp(key, ZBX_PROTO_TAG_USERNAME))) - { - zabbix_log(LOG_LEVEL_WARNING, "cannot parse macro \"%s\" value \"%s\":" - " database credentials should not be used with Vault macros", - row[1 + offset], row[2 + offset]); - goto next; - } - - keys_path_local.path = path; - - if (FAIL == (i = zbx_vector_ptr_search(keys_paths, &keys_path_local, keys_path_compare))) - { - keys_path = zbx_malloc(NULL, sizeof(zbx_keys_path_t)); - keys_path->path = path; - - zbx_hashset_create(&keys_path->keys, 0, keys_hash, keys_compare); - zbx_hashset_insert(&keys_path->keys, &key, sizeof(char **)); - - zbx_vector_ptr_append(keys_paths, keys_path); - path = key = NULL; - } - else - { - keys_path = (zbx_keys_path_t *)keys_paths->values[i]; - if (NULL == zbx_hashset_search(&keys_path->keys, &key)) - { - zbx_hashset_insert(&keys_path->keys, &key, sizeof(char **)); - key = NULL; - } - } -next: - zbx_free(key); - zbx_free(path); - } - } - DBfree_result(result); -skip_data: - zbx_free(sql); - - zbx_json_close(j); /* data */ - zbx_json_close(j); /* table->table */ - - zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); - - return ret; -} - -static void get_proxy_monitored_hosts(zbx_uint64_t proxy_hostid, zbx_vector_uint64_t *hosts) -{ - DB_RESULT result; - DB_ROW row; - zbx_uint64_t hostid, *ids = NULL; - int ids_alloc = 0, ids_num = 0; - char *sql = NULL; - size_t sql_alloc = 512, sql_offset; - - sql = (char *)zbx_malloc(sql, sql_alloc * sizeof(char)); - - result = DBselect( - "select hostid" - " from hosts" - " where proxy_hostid=" ZBX_FS_UI64 - " and status in (%d,%d)" - " and flags<>%d", - proxy_hostid, HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED, ZBX_FLAG_DISCOVERY_PROTOTYPE); - - while (NULL != (row = DBfetch(result))) - { - ZBX_STR2UINT64(hostid, row[0]); - - zbx_vector_uint64_append(hosts, hostid); - uint64_array_add(&ids, &ids_alloc, &ids_num, hostid, 64); - } - DBfree_result(result); - - while (0 != ids_num) - { - sql_offset = 0; - zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, - "select distinct templateid" - " from hosts_templates" - " where"); - DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid", ids, ids_num); - - ids_num = 0; - - result = DBselect("%s", sql); - - while (NULL != (row = DBfetch(result))) - { - ZBX_STR2UINT64(hostid, row[0]); - - zbx_vector_uint64_append(hosts, hostid); - uint64_array_add(&ids, &ids_alloc, &ids_num, hostid, 64); - } - DBfree_result(result); - } - - zbx_free(ids); - zbx_free(sql); - - zbx_vector_uint64_sort(hosts, ZBX_DEFAULT_UINT64_COMPARE_FUNC); -} - -static void get_proxy_monitored_httptests(zbx_uint64_t proxy_hostid, zbx_vector_uint64_t *httptests) -{ - DB_RESULT result; - DB_ROW row; - zbx_uint64_t httptestid; - - result = DBselect( - "select httptestid" - " from httptest t,hosts h" - " where t.hostid=h.hostid" - " and t.status=%d" - " and h.proxy_hostid=" ZBX_FS_UI64 - " and h.status=%d", - HTTPTEST_STATUS_MONITORED, proxy_hostid, HOST_STATUS_MONITORED); - - while (NULL != (row = DBfetch(result))) - { - ZBX_STR2UINT64(httptestid, row[0]); - - zbx_vector_uint64_append(httptests, httptestid); - } - DBfree_result(result); - - zbx_vector_uint64_sort(httptests, ZBX_DEFAULT_UINT64_COMPARE_FUNC); -} - -static void get_macro_secrets(const zbx_vector_ptr_t *keys_paths, struct zbx_json *j) -{ - int i; - zbx_kvs_t kvs; - - zbx_kvs_create(&kvs, 100); - - zbx_json_addobject(j, "macro.secrets"); - - for (i = 0; i < keys_paths->values_num; i++) - { - zbx_keys_path_t *keys_path; - char *error = NULL, **ptr; - zbx_hashset_iter_t iter; - - keys_path = (zbx_keys_path_t *)keys_paths->values[i]; - if (FAIL == zbx_vault_kvs_get(keys_path->path, &kvs, &error)) - { - zabbix_log(LOG_LEVEL_WARNING, "cannot get secrets for path \"%s\": %s", keys_path->path, error); - zbx_free(error); - continue; - } - - zbx_json_addobject(j, keys_path->path); - - zbx_hashset_iter_reset(&keys_path->keys, &iter); - while (NULL != (ptr = (char **)zbx_hashset_iter_next(&iter))) - { - zbx_kv_t *kv, kv_local; - - kv_local.key = *ptr; - - if (NULL != (kv = zbx_kvs_search(&kvs, &kv_local))) - zbx_json_addstring(j, kv->key, kv->value, ZBX_JSON_TYPE_STRING); - } - zbx_json_close(j); - - zbx_kvs_clear(&kvs); - } - - zbx_json_close(j); - zbx_kvs_destroy(&kvs); -} - -/****************************************************************************** - * * - * Purpose: prepare proxy configuration data * - * * - ******************************************************************************/ -int get_proxyconfig_data(zbx_uint64_t proxy_hostid, struct zbx_json *j, char **error) -{ - static const char *proxytable[] = - { - "globalmacro", - "hosts", - "interface", - "interface_snmp", - "host_inventory", - "hosts_templates", - "hostmacro", - "items", - "item_rtdata", - "item_preproc", - "item_parameter", - "drules", - "dchecks", - "regexps", - "expressions", - "hstgrp", - "config", - "httptest", - "httptestitem", - "httptest_field", - "httpstep", - "httpstepitem", - "httpstep_field", - "config_autoreg_tls", - NULL - }; - - int i, ret = FAIL; - const ZBX_TABLE *table; - zbx_vector_uint64_t hosts, httptests; - zbx_hashset_t itemids; - zbx_vector_ptr_t keys_paths; - - zabbix_log(LOG_LEVEL_DEBUG, "In %s() proxy_hostid:" ZBX_FS_UI64, __func__, proxy_hostid); - - zbx_hashset_create(&itemids, 1000, ZBX_DEFAULT_UINT64_HASH_FUNC, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - zbx_vector_uint64_create(&hosts); - zbx_vector_uint64_create(&httptests); - zbx_vector_ptr_create(&keys_paths); - - DBbegin(); - get_proxy_monitored_hosts(proxy_hostid, &hosts); - get_proxy_monitored_httptests(proxy_hostid, &httptests); - - for (i = 0; NULL != proxytable[i]; i++) - { - table = DBget_table(proxytable[i]); - - if (0 == strcmp(proxytable[i], "items")) - { - ret = get_proxyconfig_table_items(proxy_hostid, j, table, &itemids); - } - else if (0 == strcmp(proxytable[i], "item_preproc") || 0 == strcmp(proxytable[i], "item_rtdata") || - 0 == strcmp(proxytable[i], "item_parameter")) - { - if (0 != itemids.num_data) - ret = get_proxyconfig_table_items_ext(proxy_hostid, &itemids, j, table); - } - else - ret = get_proxyconfig_table(proxy_hostid, j, table, &hosts, &httptests, &keys_paths); - - if (SUCCEED != ret) - { - *error = zbx_dsprintf(*error, "failed to get data from table \"%s\"", table->table); - goto out; - } - } - - get_macro_secrets(&keys_paths, j); - - ret = SUCCEED; -out: - DBcommit(); - zbx_vector_ptr_clear_ext(&keys_paths, key_path_free); - zbx_vector_ptr_destroy(&keys_paths); - zbx_vector_uint64_destroy(&httptests); - zbx_vector_uint64_destroy(&hosts); - zbx_hashset_destroy(&itemids); - - zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); - - return ret; -} - -/****************************************************************************** - * * - * Purpose: A record is stored as a sequence of fields and flag bytes for * - * handling NULL values. A field is stored as a null-terminated * - * string to preserve field boundaries. If a field value can be NULL * - * a flag byte is inserted after the field to distinguish between * - * empty string and NULL value. The flag byte can be '\1' * - * (not NULL value) or '\2' (NULL value). * - * * - * Examples of representation: * - * \0\2 - the field can be NULL and it is NULL * - * \0\1 - the field can be NULL but is empty string * - * abc\0\1 - the field can be NULL but is a string "abc" * - * \0 - the field can not be NULL and is empty string * - * abc\0 - the field can not be NULL and is a string "abc" * - * * - ******************************************************************************/ -static void remember_record(const ZBX_FIELD **fields, int fields_count, char **recs, size_t *recs_alloc, - size_t *recs_offset, DB_ROW row) -{ - int f; - - for (f = 0; f < fields_count; f++) - { - if (0 != (fields[f]->flags & ZBX_NOTNULL)) - { - zbx_strcpy_alloc(recs, recs_alloc, recs_offset, row[f]); - *recs_offset += sizeof(char); - } - else if (SUCCEED != DBis_null(row[f])) - { - zbx_strcpy_alloc(recs, recs_alloc, recs_offset, row[f]); - *recs_offset += sizeof(char); - zbx_chrcpy_alloc(recs, recs_alloc, recs_offset, '\1'); - } - else - { - zbx_strcpy_alloc(recs, recs_alloc, recs_offset, ""); - *recs_offset += sizeof(char); - zbx_chrcpy_alloc(recs, recs_alloc, recs_offset, '\2'); - } - } -} - -static zbx_hash_t id_offset_hash_func(const void *data) -{ - const zbx_id_offset_t *p = (zbx_id_offset_t *)data; - - return ZBX_DEFAULT_UINT64_HASH_ALGO(&p->id, sizeof(zbx_uint64_t), ZBX_DEFAULT_HASH_SEED); -} - -static int id_offset_compare_func(const void *d1, const void *d2) -{ - const zbx_id_offset_t *p1 = (zbx_id_offset_t *)d1, *p2 = (zbx_id_offset_t *)d2; - - return ZBX_DEFAULT_UINT64_COMPARE_FUNC(&p1->id, &p2->id); -} - -/****************************************************************************** - * * - * Purpose: find a number of the field * - * * - ******************************************************************************/ -static int find_field_by_name(const ZBX_FIELD **fields, int fields_count, const char *field_name) -{ - int f; - - for (f = 0; f < fields_count; f++) - { - if (0 == strcmp(fields[f]->name, field_name)) - break; - } - - return f; -} - -/****************************************************************************** - * * - * Purpose: This function compares a value from JSON record with the value * - * of the n-th field of DB record. For description how DB record is * - * stored in memory see comments in function remember_record(). * - * * - * Comparing deals with 4 cases: * - * - JSON value is not NULL, DB value is not NULL * - * - JSON value is not NULL, DB value is NULL * - * - JSON value is NULL, DB value is NULL * - * - JSON value is NULL, DB value is not NULL * - * * - ******************************************************************************/ -static int compare_nth_field(const ZBX_FIELD **fields, const char *rec_data, int n, const char *str, int is_null, - int *last_n, size_t *last_pos) -{ - int i = *last_n, null_in_db = 0; - const char *p = rec_data + *last_pos, *field_start = NULL; - - do /* find starting position of the n-th field */ - { - field_start = p; - while ('\0' != *p++) - ; - - null_in_db = 0; - - if (0 == (fields[i++]->flags & ZBX_NOTNULL)) /* field could be NULL */ - { - if ('\2' == *p && (rec_data == p - 1 || '\0' == *(p - 2) || '\1' == *(p - 2) || - '\2' == *(p - 2))) /* field value is NULL */ - { - null_in_db = 1; - p++; - } - else if ('\1' == *p) - { - p++; - } - else - { - THIS_SHOULD_NEVER_HAPPEN; - *last_n = 0; - *last_pos = 0; - return 1; - } - } - } - while (n >= i); - - *last_n = i; /* preserve number of field and its start position */ - *last_pos = (size_t)(p - rec_data); /* across calls to avoid searching from start */ - - if (0 == is_null) /* value in JSON is not NULL */ - { - if (0 == null_in_db) - return strcmp(field_start, str); - else - return 1; - } - else - { - if ('\0' == *str) - { - if (1 == null_in_db) - return 0; /* fields are "equal" - both contain NULL */ - else - return 1; - } - else - { - THIS_SHOULD_NEVER_HAPPEN; - *last_n = 0; - *last_pos = 0; - return 1; - } - } -} - -/****************************************************************************** - * * - * Purpose: update configuration table * - * * - * Parameters: ... * - * del - [OUT] ids of the removed records that must be deleted * - * from database * - * * - * Return value: SUCCEED - processed successfully * - * FAIL - an error occurred * - * * - ******************************************************************************/ -static int process_proxyconfig_table(const ZBX_TABLE *table, struct zbx_json_parse *jp_obj, - zbx_vector_uint64_t *del, char **error) -{ - int f, fields_count, ret = FAIL, id_field_nr = 0, move_out = 0, - move_field_nr = 0; - const ZBX_FIELD *fields[ZBX_MAX_FIELDS]; - struct zbx_json_parse jp_data, jp_row; - const char *p, *pf; - zbx_uint64_t recid, *p_recid = NULL; - zbx_vector_uint64_t ins, moves, availability_interfaceids; - char *buf = NULL, *esc, *sql = NULL, *recs = NULL; - size_t sql_alloc = 4 * ZBX_KIBIBYTE, sql_offset, - recs_alloc = 20 * ZBX_KIBIBYTE, recs_offset = 0, - buf_alloc = 0; - DB_RESULT result; - DB_ROW row; - zbx_hashset_t h_id_offsets, h_del; - zbx_hashset_iter_t iter; - zbx_id_offset_t id_offset, *p_id_offset = NULL; - zbx_db_insert_t db_insert; - zbx_vector_ptr_t values; - static zbx_vector_ptr_t skip_fields; - static const ZBX_TABLE *table_items, *table_interface; - - zabbix_log(LOG_LEVEL_DEBUG, "In %s() table:'%s'", __func__, table->table); - - /************************************************************************************/ - /* T1. RECEIVED JSON (jp_obj) DATA FORMAT */ - /************************************************************************************/ - /* Line | Data | Corresponding structure in DB */ - /* -----+-------------------------------------------+------------------------------ */ - /* 1 | { | */ - /* 2 | "hosts": { | first table */ - /* 3 | "fields": [ | list of table's columns */ - /* 4 | "hostid", | first column */ - /* 5 | "host", | second column */ - /* 6 | ... | ...columns */ - /* 7 | ], | */ - /* 8 | "data": [ | the table data */ - /* 9 | [ | first entry */ - /* 10 | 1, | value for first column */ - /* 11 | "zbx01", | value for second column */ - /* 12 | ... | ...values */ - /* 13 | ], | */ - /* 14 | [ | second entry */ - /* 15 | 2, | value for first column */ - /* 16 | "zbx02", | value for second column */ - /* 17 | ... | ...values */ - /* 18 | ], | */ - /* 19 | ... | ...entries */ - /* 20 | ] | */ - /* 21 | }, | */ - /* 22 | "items": { | second table */ - /* 23 | ... | ... */ - /* 24 | }, | */ - /* 25 | ... | ...tables */ - /* 26 | } | */ - /************************************************************************************/ - - if (NULL == table_items) - { - table_items = DBget_table("item_rtdata"); - - /* do not update existing lastlogsize and mtime fields */ - zbx_vector_ptr_create(&skip_fields); - zbx_vector_ptr_append(&skip_fields, (void *)DBget_field(table_items, "lastlogsize")); - zbx_vector_ptr_append(&skip_fields, (void *)DBget_field(table_items, "mtime")); - zbx_vector_ptr_sort(&skip_fields, ZBX_DEFAULT_PTR_COMPARE_FUNC); - } - - if (NULL == table_interface) - table_interface = DBget_table("interface"); - - /* get table columns (line 3 in T1) */ - if (FAIL == zbx_json_brackets_by_name(jp_obj, "fields", &jp_data)) - { - *error = zbx_strdup(*error, zbx_json_strerror()); - goto out; - } - - p = NULL; - /* iterate column names (lines 4-6 in T1) */ - for (fields_count = 0; NULL != (p = zbx_json_next_value_dyn(&jp_data, p, &buf, &buf_alloc, NULL)); fields_count++) - { - if (NULL == (fields[fields_count] = DBget_field(table, buf))) - { - *error = zbx_dsprintf(*error, "invalid field name \"%s.%s\"", table->table, buf); - goto out; - } - - if (0 == (fields[fields_count]->flags & ZBX_PROXY) && - (0 != strcmp(table->recid, buf) || ZBX_TYPE_ID != fields[fields_count]->type)) - { - *error = zbx_dsprintf(*error, "unexpected field \"%s.%s\"", table->table, buf); - goto out; - } - } - - if (0 == fields_count) - { - *error = zbx_dsprintf(*error, "empty list of field names"); - goto out; - } - - /* get the entries (line 8 in T1) */ - if (FAIL == zbx_json_brackets_by_name(jp_obj, ZBX_PROTO_TAG_DATA, &jp_data)) - { - *error = zbx_strdup(*error, zbx_json_strerror()); - goto out; - } - - /* all records will be stored in one large string */ - recs = (char *)zbx_malloc(recs, recs_alloc); - - /* hash set as index for fast access to records via IDs */ - zbx_hashset_create(&h_id_offsets, 10000, id_offset_hash_func, id_offset_compare_func); - - /* a hash set as a list for finding records to be deleted */ - zbx_hashset_create(&h_del, 10000, ZBX_DEFAULT_UINT64_HASH_FUNC, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - - sql = (char *)zbx_malloc(sql, sql_alloc); - - sql_offset = 0; - zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select "); - - /* make a string with a list of fields for SELECT */ - for (f = 0; f < fields_count; f++) - { - zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, fields[f]->name); - zbx_chrcpy_alloc(&sql, &sql_alloc, &sql_offset, ','); - } - - sql_offset--; - zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " from "); - zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, table->table); - - /* Find a number of the ID field. Usually the 1st field. */ - id_field_nr = find_field_by_name(fields, fields_count, table->recid); - - /* select all existing records */ - result = DBselect("%s", sql); - - while (NULL != (row = DBfetch(result))) - { - ZBX_STR2UINT64(recid, row[id_field_nr]); - - id_offset.id = recid; - id_offset.offset = recs_offset; - - zbx_hashset_insert(&h_id_offsets, &id_offset, sizeof(id_offset)); - zbx_hashset_insert(&h_del, &recid, sizeof(recid)); - - remember_record(fields, fields_count, &recs, &recs_alloc, &recs_offset, row); - } - DBfree_result(result); - - /* these tables have unique indices, need special preparation to avoid conflicts during inserts/updates */ - if (0 == strcmp("globalmacro", table->table)) - { - move_out = 1; - move_field_nr = find_field_by_name(fields, fields_count, "macro"); - } - else if (0 == strcmp("hosts_templates", table->table)) - { - move_out = 1; - move_field_nr = find_field_by_name(fields, fields_count, "templateid"); - } - else if (0 == strcmp("hostmacro", table->table)) - { - move_out = 1; - move_field_nr = find_field_by_name(fields, fields_count, "macro"); - } - else if (0 == strcmp("items", table->table)) - { - move_out = 1; - move_field_nr = find_field_by_name(fields, fields_count, "key_"); - } - else if (0 == strcmp("drules", table->table)) - { - move_out = 1; - move_field_nr = find_field_by_name(fields, fields_count, "name"); - } - else if (0 == strcmp("regexps", table->table)) - { - move_out = 1; - move_field_nr = find_field_by_name(fields, fields_count, "name"); - } - else if (0 == strcmp("httptest", table->table)) - { - move_out = 1; - move_field_nr = find_field_by_name(fields, fields_count, "name"); - } - - zbx_vector_uint64_create(&ins); - - if (1 == move_out) - zbx_vector_uint64_create(&moves); - - zbx_vector_uint64_create(&availability_interfaceids); - - p = NULL; - /* iterate the entries (lines 9, 14 and 19 in T1) */ - while (NULL != (p = zbx_json_next(&jp_data, p))) - { - if (FAIL == zbx_json_brackets_open(p, &jp_row) || - NULL == (pf = zbx_json_next_value_dyn(&jp_row, NULL, &buf, &buf_alloc, NULL))) - { - *error = zbx_strdup(*error, zbx_json_strerror()); - goto clean2; - } - - /* check whether we need to update existing entry or insert a new one */ - - ZBX_STR2UINT64(recid, buf); - - if (NULL != zbx_hashset_search(&h_del, &recid)) - { - zbx_hashset_remove(&h_del, &recid); - - if (1 == move_out) - { - int last_n = 0; - size_t last_pos = 0; - zbx_json_type_t type; - - /* locate a copy of this record as found in database */ - id_offset.id = recid; - if (NULL == (p_id_offset = (zbx_id_offset_t *)zbx_hashset_search(&h_id_offsets, &id_offset))) - { - THIS_SHOULD_NEVER_HAPPEN; - goto clean2; - } - - /* find the field requiring special preprocessing in JSON record */ - f = 1; - while (NULL != (pf = zbx_json_next_value_dyn(&jp_row, pf, &buf, &buf_alloc, &type))) - { - /* parse values for the entry (lines 10-12 in T1) */ - - if (fields_count == f) - { - *error = zbx_dsprintf(*error, "invalid number of fields \"%.*s\"", - (int)(jp_row.end - jp_row.start + 1), jp_row.start); - goto clean2; - } - - if (move_field_nr == f) - break; - f++; - } - - if (0 != compare_nth_field(fields, recs + p_id_offset->offset, move_field_nr, buf, - (ZBX_JSON_TYPE_NULL == type), &last_n, &last_pos)) - { - zbx_vector_uint64_append(&moves, recid); - } - } - } - else - zbx_vector_uint64_append(&ins, recid); - } - - /* copy IDs of records to be deleted from hash set to vector */ - zbx_hashset_iter_reset(&h_del, &iter); - while (NULL != (p_recid = (uint64_t *)zbx_hashset_iter_next(&iter))) - zbx_vector_uint64_append(del, *p_recid); - zbx_vector_uint64_sort(del, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - - zbx_vector_uint64_sort(&ins, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - - if (1 == move_out) - { - /* special preprocessing for 'hosts_templates' table to eliminate conflicts */ - /* in the 'hostid, templateid' unique index */ - if (0 == strcmp("hosts_templates", table->table)) - { - /* Making the 'hostid, templateid' combination unique to avoid collisions when new records */ - /* are inserted and existing ones are updated is a bit complex. Let's take a simpler approach */ - /* - delete affected old records and insert the new ones. */ - if (0 != moves.values_num) - { - zbx_vector_uint64_append_array(&ins, moves.values, moves.values_num); - zbx_vector_uint64_sort(&ins, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - zbx_vector_uint64_append_array(del, moves.values, moves.values_num); - zbx_vector_uint64_sort(del, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - } - - if (0 != del->values_num) - { - sql_offset = 0; - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "delete from %s where", table->table); - DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, table->recid, del->values, - del->values_num); - - if (ZBX_DB_OK > DBexecute("%s", sql)) - goto clean2; - - zbx_vector_uint64_clear(del); - } - } - else - { - /* force index field update for removed records to avoid potential conflicts */ - if (0 != del->values_num) - zbx_vector_uint64_append_array(&moves, del->values, del->values_num); - - /* special preprocessing for 'globalmacro', 'hostmacro', 'items', 'drules', 'regexps' and */ - /* 'httptest' tables to eliminate conflicts in the 'macro', 'hostid,macro', 'hostid,key_', */ - /* 'name', 'name' and 'hostid,name' unique indices */ - if (0 < moves.values_num) - { - sql_offset = 0; -#ifdef HAVE_MYSQL - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, - "update %s set %s=concat('#',%s) where", - table->table, fields[move_field_nr]->name, table->recid); -#else - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "update %s set %s='#'||%s where", - table->table, fields[move_field_nr]->name, table->recid); -#endif - zbx_vector_uint64_sort(&moves, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, table->recid, moves.values, - moves.values_num); - - if (ZBX_DB_OK > DBexecute("%s", sql)) - goto clean2; - } - } - } - - /* apply insert operations */ - - if (0 != ins.values_num) - { - zbx_vector_ptr_create(&values); - zbx_db_insert_prepare_dyn(&db_insert, table, fields, fields_count); - - p = NULL; - /* iterate the entries (lines 9, 14 and 19 in T1) */ - while (NULL != (p = zbx_json_next(&jp_data, p))) - { - zbx_json_type_t type; - zbx_db_value_t *value; - - if (FAIL == zbx_json_brackets_open(p, &jp_row)) - { - *error = zbx_dsprintf(*error, "invalid data format: %s", zbx_json_strerror()); - goto clean; - } - - pf = zbx_json_next_value_dyn(&jp_row, NULL, &buf, &buf_alloc, NULL); - - /* check whether we need to insert a new entry or update an existing one */ - ZBX_STR2UINT64(recid, buf); - if (FAIL == zbx_vector_uint64_bsearch(&ins, recid, ZBX_DEFAULT_UINT64_COMPARE_FUNC)) - continue; - - /* add the id field */ - value = (zbx_db_value_t *)zbx_malloc(NULL, sizeof(zbx_db_value_t)); - value->ui64 = recid; - zbx_vector_ptr_append(&values, value); - - /* add the rest of fields */ - for (f = 1; NULL != (pf = zbx_json_next_value_dyn(&jp_row, pf, &buf, &buf_alloc, &type)); - f++) - { - if (f == fields_count) - { - *error = zbx_dsprintf(*error, "invalid number of fields \"%.*s\"", - (int)(jp_row.end - jp_row.start + 1), jp_row.start); - goto clean; - } - - if (ZBX_JSON_TYPE_NULL == type && 0 != (fields[f]->flags & ZBX_NOTNULL)) - { - *error = zbx_dsprintf(*error, "column \"%s.%s\" cannot be null", - table->table, fields[f]->name); - goto clean; - } - - value = (zbx_db_value_t *)zbx_malloc(NULL, sizeof(zbx_db_value_t)); - - switch (fields[f]->type) - { - case ZBX_TYPE_INT: - value->i32 = atoi(buf); - break; - case ZBX_TYPE_UINT: - ZBX_STR2UINT64(value->ui64, buf); - break; - case ZBX_TYPE_ID: - if (ZBX_JSON_TYPE_NULL != type) - ZBX_STR2UINT64(value->ui64, buf); - else - value->ui64 = 0; - break; - case ZBX_TYPE_FLOAT: - value->dbl = atof(buf); - break; - case ZBX_TYPE_CHAR: - case ZBX_TYPE_TEXT: - case ZBX_TYPE_SHORTTEXT: - case ZBX_TYPE_LONGTEXT: - value->str = zbx_strdup(NULL, buf); - break; - default: - *error = zbx_dsprintf(*error, "unsupported field type %d in \"%s.%s\"", - (int)fields[f]->type, table->table, fields[f]->name); - zbx_free(value); - goto clean; - - } - - zbx_vector_ptr_append(&values, value); - } - - zbx_db_insert_add_values_dyn(&db_insert, (const zbx_db_value_t **)values.values, - values.values_num); - - for (f = 0; f < fields_count; f++) - { - switch (fields[f]->type) - { - case ZBX_TYPE_CHAR: - case ZBX_TYPE_TEXT: - case ZBX_TYPE_SHORTTEXT: - case ZBX_TYPE_LONGTEXT: - value = (zbx_db_value_t *)values.values[f]; - zbx_free(value->str); - } - } - zbx_vector_ptr_clear_ext(&values, zbx_ptr_free); - - if (f != fields_count) - { - *error = zbx_dsprintf(*error, "invalid number of fields \"%.*s\"", - (int)(jp_row.end - jp_row.start + 1), jp_row.start); - goto clean; - } - } - - if (FAIL == zbx_db_insert_execute(&db_insert)) - goto clean; - } - - /* apply update operations */ - - sql_offset = 0; - zbx_DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset); - - p = NULL; - /* iterate the entries (lines 9, 14 and 19 in T1) */ - while (NULL != (p = zbx_json_next(&jp_data, p))) - { - int rec_differ = 0; /* how many fields differ */ - int last_n = 0; - size_t tmp_offset = sql_offset, last_pos = 0; - zbx_json_type_t type; - - if (FAIL == zbx_json_brackets_open(p, &jp_row)) - { - *error = zbx_dsprintf(*error, "invalid data format: %s", zbx_json_strerror()); - goto clean; - } - - pf = zbx_json_next_value_dyn(&jp_row, NULL, &buf, &buf_alloc, NULL); - - /* check whether we need to insert a new entry or update an existing one */ - ZBX_STR2UINT64(recid, buf); - if (FAIL != zbx_vector_uint64_bsearch(&ins, recid, ZBX_DEFAULT_UINT64_COMPARE_FUNC)) - continue; - - if (1 == fields_count) /* only primary key given, no update needed */ - continue; - - /* locate a copy of this record as found in database */ - id_offset.id = recid; - if (NULL == (p_id_offset = (zbx_id_offset_t *)zbx_hashset_search(&h_id_offsets, &id_offset))) - { - THIS_SHOULD_NEVER_HAPPEN; - goto clean; - } - - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "update %s set ", table->table); - - for (f = 1; NULL != (pf = zbx_json_next_value_dyn(&jp_row, pf, &buf, &buf_alloc, &type)); - f++) - { - /* parse values for the entry (lines 10-12 in T1) */ - - if (f == fields_count) - { - *error = zbx_dsprintf(*error, "invalid number of fields \"%.*s\"", - (int)(jp_row.end - jp_row.start + 1), jp_row.start); - goto clean; - } - - if (ZBX_JSON_TYPE_NULL == type && 0 != (fields[f]->flags & ZBX_NOTNULL)) - { - *error = zbx_dsprintf(*error, "column \"%s.%s\" cannot be null", - table->table, fields[f]->name); - goto clean; - } - - /* do not update existing lastlogsize and mtime fields */ - if (FAIL != zbx_vector_ptr_bsearch(&skip_fields, fields[f], - ZBX_DEFAULT_PTR_COMPARE_FUNC)) - { - continue; - } - - if (0 == compare_nth_field(fields, recs + p_id_offset->offset, f, buf, - (ZBX_JSON_TYPE_NULL == type), &last_n, &last_pos)) - { - continue; - } - - if (table == table_interface && 0 == strcmp(fields[f]->name, "available")) - { - /* host availability on server differs from local (proxy) availability - */ - /* reset availability timestamp to re-send availability data to server */ - zbx_vector_uint64_append(&availability_interfaceids, recid); - continue; - } - - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%s=", fields[f]->name); - rec_differ++; - - if (ZBX_JSON_TYPE_NULL == type) - { - zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "null,"); - continue; - } - - switch (fields[f]->type) - { - case ZBX_TYPE_INT: - case ZBX_TYPE_UINT: - case ZBX_TYPE_ID: - case ZBX_TYPE_FLOAT: - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%s,", buf); - break; - default: - esc = DBdyn_escape_string(buf); - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "'%s',", esc); - zbx_free(esc); - } - } - - if (f != fields_count) - { - *error = zbx_dsprintf(*error, "invalid number of fields \"%.*s\"", - (int)(jp_row.end - jp_row.start + 1), jp_row.start); - goto clean; - } - - sql_offset--; - - if (0 != rec_differ) - { - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " where %s=" ZBX_FS_UI64 ";\n", - table->recid, recid); - - if (SUCCEED != DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset)) - goto clean; - } - else - { - sql_offset = tmp_offset; /* discard this update, all fields are the same */ - *(sql + sql_offset) = '\0'; - } - } - - if (16 < sql_offset) /* in ORACLE always present begin..end; */ - { - zbx_DBend_multiple_update(&sql, &sql_alloc, &sql_offset); - - if (ZBX_DB_OK > DBexecute("%s", sql)) - goto clean; - } - - /* delete operations are performed by the caller using the returned del vector */ - - if (0 != availability_interfaceids.values_num) - { - zbx_vector_uint64_sort(&availability_interfaceids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - zbx_vector_uint64_uniq(&availability_interfaceids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - DCtouch_interfaces_availability(&availability_interfaceids); - } - - ret = SUCCEED; -clean: - if (0 != ins.values_num) - { - zbx_db_insert_clean(&db_insert); - zbx_vector_ptr_destroy(&values); - } -clean2: - zbx_hashset_destroy(&h_id_offsets); - zbx_hashset_destroy(&h_del); - zbx_vector_uint64_destroy(&availability_interfaceids); - zbx_vector_uint64_destroy(&ins); - if (1 == move_out) - zbx_vector_uint64_destroy(&moves); - zbx_free(sql); - zbx_free(recs); -out: - zbx_free(buf); - - zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); - - return ret; -} - -/****************************************************************************** - * * - * Purpose: update configuration * - * * - ******************************************************************************/ -int process_proxyconfig(struct zbx_json_parse *jp_data, struct zbx_json_parse *jp_kvs_paths) -{ - typedef struct - { - const ZBX_TABLE *table; - zbx_vector_uint64_t ids; - } - table_ids_t; - - char buf[ZBX_TABLENAME_LEN_MAX]; - const char *p = NULL; - struct zbx_json_parse jp_obj; - char *error = NULL; - int i, ret = SUCCEED; - - table_ids_t *table_ids; - zbx_vector_ptr_t tables_proxy; - const ZBX_TABLE *table; - - zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); - - zbx_vector_ptr_create(&tables_proxy); - - DBbegin(); - - /* iterate the tables (lines 2, 22 and 25 in T1) */ - while (NULL != (p = zbx_json_pair_next(jp_data, p, buf, sizeof(buf))) && SUCCEED == ret) - { - if (FAIL == zbx_json_brackets_open(p, &jp_obj)) - { - error = zbx_strdup(error, zbx_json_strerror()); - ret = FAIL; - break; - } - - if (0 == strcmp(buf, "macro.secrets")) - { - *jp_kvs_paths = jp_obj; - continue; - } - - if (NULL == (table = DBget_table(buf))) - { - error = zbx_dsprintf(error, "invalid table name \"%s\"", buf); - ret = FAIL; - break; - } - - table_ids = (table_ids_t *)zbx_malloc(NULL, sizeof(table_ids_t)); - table_ids->table = table; - zbx_vector_uint64_create(&table_ids->ids); - zbx_vector_ptr_append(&tables_proxy, table_ids); - - ret = process_proxyconfig_table(table, &jp_obj, &table_ids->ids, &error); - } - - if (SUCCEED == ret) - { - char *sql = NULL; - size_t sql_alloc = 512, sql_offset = 0; - - sql = (char *)zbx_malloc(sql, sql_alloc * sizeof(char)); - - zbx_DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset); - - for (i = tables_proxy.values_num - 1; 0 <= i; i--) - { - table_ids = (table_ids_t *)tables_proxy.values[i]; - - if (0 == table_ids->ids.values_num) - continue; - - if (0 == strcmp(table_ids->table->table, "items")) - { - /* special case for item preprocessing - remove before removing items */ - zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from item_preproc where"); - DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, table_ids->table->recid, - table_ids->ids.values, table_ids->ids.values_num); - zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n"); - - /* reset master_itemid to avoid recursive removal of dependent items */ - zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, - "update items set master_itemid=null where"); - DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid", table_ids->ids.values, - table_ids->ids.values_num); - zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " and master_itemid is not null;\n"); - } - - zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "delete from %s where", - table_ids->table->table); - DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, table_ids->table->recid, - table_ids->ids.values, table_ids->ids.values_num); - zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n"); - - DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset); - } - - if (sql_offset > 16) /* in ORACLE always present begin..end; */ - { - zbx_DBend_multiple_update(&sql, &sql_alloc, &sql_offset); - - if (ZBX_DB_OK > DBexecute("%s", sql)) - ret = FAIL; - } - - zbx_free(sql); - } - - for (i = 0; i < tables_proxy.values_num; i++) - { - table_ids = (table_ids_t *)tables_proxy.values[i]; - - zbx_vector_uint64_destroy(&table_ids->ids); - zbx_free(table_ids); - } - zbx_vector_ptr_destroy(&tables_proxy); - - if (SUCCEED != (ret = DBend(ret))) - { - zabbix_log(LOG_LEVEL_ERR, "failed to update local proxy configuration copy: %s", - (NULL == error ? "database error" : error)); - } - - zbx_free(error); - - zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); - - return ret; -} - -/****************************************************************************** - * * * Return value: SUCCEED - processed successfully * * FAIL - no interface availability has been changed * * * @@ -2434,7 +761,6 @@ zbx_history_data_t; static int proxy_get_history_data(zbx_uint64_t lastid, zbx_history_data_t **data, size_t *data_alloc, char **string_buffer, size_t *string_buffer_alloc, int *more) { - DB_RESULT result; DB_ROW row; char *sql = NULL; @@ -2972,7 +1298,7 @@ static int process_history_data_value(DC_ITEM *item, zbx_agent_value_t *value, i { AGENT_RESULT result; - init_result(&result); + zbx_init_agent_result(&result); if (NULL != value->value) { @@ -3006,11 +1332,11 @@ static int process_history_data_value(DC_ITEM *item, zbx_agent_value_t *value, i SET_LOG_RESULT(&result, log); } else - set_result_type(&result, ITEM_VALUE_TYPE_TEXT, value->value); + zbx_set_agent_result_type(&result, ITEM_VALUE_TYPE_TEXT, value->value); } if (0 != value->meta) - set_result_meta(&result, value->lastlogsize, value->mtime); + zbx_set_agent_result_meta(&result, value->lastlogsize, value->mtime); if (0 != ZBX_ISSET_VALUE(&result) || 0 != ZBX_ISSET_META(&result)) { @@ -3018,7 +1344,7 @@ static int process_history_data_value(DC_ITEM *item, zbx_agent_value_t *value, i process_item_value(item, &result, &value->ts, h_num, NULL); } - free_result(&result); + zbx_free_agent_result(&result); } return SUCCEED; @@ -3857,7 +2183,7 @@ static int process_client_history_data(zbx_socket_t *sock, struct zbx_json_parse { size_t token_len; - if (zbx_get_token_len() != (token_len = strlen(token))) + if (ZBX_SESSION_TOKEN_SIZE != (token_len = strlen(token))) { *info = zbx_dsprintf(*info, "invalid session token length %d", (int)token_len); ret = FAIL; @@ -3866,12 +2192,12 @@ static int process_client_history_data(zbx_socket_t *sock, struct zbx_json_parse } if (SUCCEED != zbx_json_value_by_name(jp, ZBX_PROTO_TAG_VERSION, tmp, sizeof(tmp), NULL) || - FAIL == (version = zbx_get_component_version(tmp))) + FAIL == (version = zbx_get_component_version_without_patch(tmp))) { - version = ZBX_COMPONENT_VERSION(4, 2); + version = ZBX_COMPONENT_VERSION(4, 2, 0); } - if (ZBX_COMPONENT_VERSION(4, 4) <= version && + if (ZBX_COMPONENT_VERSION(4, 4, 0) <= version && SUCCEED == zbx_json_value_by_name(jp, ZBX_PROTO_TAG_HOST, tmp, sizeof(tmp), NULL)) { zbx_session_t *session; @@ -4353,7 +2679,6 @@ static int process_autoregistration_contents(struct zbx_json_parse *jp_data, zbx unsigned short port; size_t host_metadata_alloc = 1; /* for at least NUL-terminating string */ zbx_vector_ptr_t autoreg_hosts; - zbx_conn_flags_t flags = ZBX_CONN_DEFAULT; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); @@ -4369,7 +2694,8 @@ static int process_autoregistration_contents(struct zbx_json_parse *jp_data, zbx while (NULL != (p = zbx_json_next(jp_data, p))) { - unsigned int connection_type; + unsigned int connection_type; + zbx_conn_flags_t flags = ZBX_CONN_DEFAULT; if (FAIL == (ret = zbx_json_brackets_open(p, &jp_row))) break; @@ -4527,23 +2853,50 @@ int proxy_get_history_count(void) * Parameters: * * jp - [IN] JSON with the proxy version * * * - * Return value: The protocol version. * - * SUCCEED - proxy version was successfully extracted * - * FAIL - otherwise * + * Return value: The protocol version in textual representation, for example, * + * "6.4.0alpha1", * + * actual proxy version - if proxy version was successfully extracted * + * undefined version - otherwise * + * * + * Comments: allocates memory * * * ******************************************************************************/ -int zbx_get_proxy_protocol_version(struct zbx_json_parse *jp) +char *zbx_get_proxy_protocol_version_str(const struct zbx_json_parse *jp) { char value[MAX_STRING_LEN]; - int version; - if (NULL != jp && SUCCEED == zbx_json_value_by_name(jp, ZBX_PROTO_TAG_VERSION, value, sizeof(value), NULL) && - FAIL != (version = zbx_get_component_version(value))) + if (NULL != jp && SUCCEED == zbx_json_value_by_name(jp, ZBX_PROTO_TAG_VERSION, value, sizeof(value), NULL)) + return strdup(value); + + return strdup(ZBX_VERSION_UNDEFINED_STR); +} + +/****************************************************************************** + * * + * Purpose: converts protocol version fom textual to numeric representation * + * for version comparison. The function truncates release candidate * + * part of the version. * + * * + * Parameters: * + * version_str - [IN] proxy version, for example "6.4.0alpha1". * + * * + * Return value: The protocol version in numeric representation, for example, * + * 060400 * + * actual proxy version - if proxy version was successfully extracted * + * proxy version 3.2 - otherwise * + * * + ******************************************************************************/ +int zbx_get_proxy_protocol_version_int(const char *version_str) +{ + int version_int; + + if (0 != strcmp(ZBX_VERSION_UNDEFINED_STR, version_str) && + FAIL != (version_int = zbx_get_component_version(version_str))) { - return version; + return version_int; } - else - return ZBX_COMPONENT_VERSION(3, 2); + + return ZBX_COMPONENT_VERSION(3, 2, 0); } /****************************************************************************** @@ -4728,7 +3081,7 @@ int process_proxy_data(const DC_PROXY *proxy, struct zbx_json_parse *jp, zbx_tim { size_t token_len; - if (zbx_get_token_len() != (token_len = strlen(value))) + if (ZBX_SESSION_TOKEN_SIZE != (token_len = strlen(value))) { *error = zbx_dsprintf(*error, "invalid session token length %d", (int)token_len); ret = FAIL; @@ -4912,40 +3265,112 @@ static void zbx_db_flush_proxy_lastaccess(void) /****************************************************************************** * * + * Purpose: updates proxy version and compatibility with server in database * + * * + * Parameters: proxy - [IN] the proxy to update version for * + * diff - [IN] indicates changes to the proxy * + * * + ******************************************************************************/ +static void db_update_proxy_version(DC_PROXY *proxy, zbx_proxy_diff_t *diff) +{ + if (0 != (diff->flags & ZBX_FLAGS_PROXY_DIFF_UPDATE_VERSION)) + { + if (0 != proxy->version_int) + { + zabbix_log(LOG_LEVEL_DEBUG, "proxy \"%s\" protocol version updated from %u.%u to %u.%u", + proxy->host, + ZBX_COMPONENT_VERSION_MAJOR(proxy->version_int), + ZBX_COMPONENT_VERSION_MINOR(proxy->version_int), + ZBX_COMPONENT_VERSION_MAJOR(diff->version_int), + ZBX_COMPONENT_VERSION_MINOR(diff->version_int)); + } + + if (ZBX_DB_OK > DBexecute( + "update host_rtdata" + " set version=%u,compatibility=%u" + " where hostid=" ZBX_FS_UI64, + ZBX_COMPONENT_VERSION_TO_DEC_FORMAT(diff->version_int), diff->compatibility, + diff->hostid)) + { + zabbix_log(LOG_LEVEL_WARNING, "Failed to update proxy version and compatibility with server for" + " proxy '%s'.", proxy->host); + } + } +} + +/****************************************************************************** + * * + * Purpose: gets proxy version compatibility with server version * + * * + * Parameters: proxy_version - [IN] proxy_version * + * * + * Return value: proxy version compatibility with server version * + * * + ******************************************************************************/ +static zbx_proxy_compatibility_t zbx_get_proxy_compatibility(int proxy_version) +{ +#define SERVER_VERSION ZBX_COMPONENT_VERSION(ZABBIX_VERSION_MAJOR, ZABBIX_VERSION_MINOR, 0) + + if (0 == proxy_version) + return ZBX_PROXY_VERSION_UNDEFINED; + + proxy_version = ZBX_COMPONENT_VERSION_WITHOUT_PATCH(proxy_version); + + if (SERVER_VERSION == proxy_version) + return ZBX_PROXY_VERSION_CURRENT; + + if (SERVER_VERSION < proxy_version) + return ZBX_PROXY_VERSION_UNSUPPORTED; +#if (ZABBIX_VERSION_MINOR == 0) + if (ZABBIX_VERSION_MAJOR == 1 + ZBX_COMPONENT_VERSION_MAJOR(proxy_version)) + return ZBX_PROXY_VERSION_STATUS_OUTDATED; +#elif (ZABBIX_VERSION_MINOR > 0) + if (ZABBIX_VERSION_MAJOR == ZBX_COMPONENT_VERSION_MAJOR(proxy_version)) + return ZBX_PROXY_VERSION_OUTDATED; +#endif + return ZBX_PROXY_VERSION_UNSUPPORTED; + +#undef SERVER_VERSION +} + +/****************************************************************************** + * * * Purpose: updates proxy runtime properties in cache and database. * * * - * Parameters: proxy - [IN/OUT] the proxy * - * version - [IN] the proxy version * - * lastaccess - [IN] the last proxy access time * - * compress - [IN] 1 if proxy is using data compression, * - * 0 otherwise * - * flags_add - [IN] additional flags for update proxy * + * Parameters: proxy - [IN/OUT] the proxy * + * version_str - [IN] the proxy version as string * + * version_int - [IN] the proxy version in numeric representation * + * lastaccess - [IN] the last proxy access time * + * compress - [IN] 1 if proxy is using data compression, * + * 0 otherwise * + * flags_add - [IN] additional flags for update proxy * * * * Comments: The proxy parameter properties are also updated. * * * ******************************************************************************/ -void zbx_update_proxy_data(DC_PROXY *proxy, int version, int lastaccess, int compress, zbx_uint64_t flags_add) +void zbx_update_proxy_data(DC_PROXY *proxy, char *version_str, int version_int, int lastaccess, int compress, + zbx_uint64_t flags_add) { - zbx_proxy_diff_t diff; + zbx_proxy_diff_t diff; + zbx_proxy_compatibility_t compatibility; + + compatibility = zbx_get_proxy_compatibility(version_int); diff.hostid = proxy->hostid; diff.flags = ZBX_FLAGS_PROXY_DIFF_UPDATE | flags_add; - diff.version = version; + diff.version_str = version_str; + diff.version_int = version_int; + diff.compatibility = compatibility; diff.lastaccess = lastaccess; diff.compress = compress; zbx_dc_update_proxy(&diff); - if (0 != (diff.flags & ZBX_FLAGS_PROXY_DIFF_UPDATE_VERSION) && 0 != proxy->version) - { - zabbix_log(LOG_LEVEL_DEBUG, "proxy \"%s\" protocol version updated from %d.%d to %d.%d", proxy->host, - ZBX_COMPONENT_VERSION_MAJOR(proxy->version), - ZBX_COMPONENT_VERSION_MINOR(proxy->version), - ZBX_COMPONENT_VERSION_MAJOR(diff.version), - ZBX_COMPONENT_VERSION_MINOR(diff.version)); - } + db_update_proxy_version(proxy, &diff); - proxy->version = version; + zbx_strlcpy(proxy->version_str, version_str, sizeof(proxy->version_str)); + proxy->version_int = version_int; + proxy->compatibility = compatibility; proxy->auto_compress = compress; proxy->lastaccess = lastaccess; @@ -4986,15 +3411,14 @@ static void zbx_update_proxy_lasterror(DC_PROXY *proxy) ******************************************************************************/ int zbx_check_protocol_version(DC_PROXY *proxy, int version) { - int server_version; - int ret = SUCCEED; - int now; - int print_log = 0; + zbx_proxy_compatibility_t compatibility; + + compatibility = zbx_get_proxy_compatibility(version); /* warn if another proxy version is used and proceed with compatibility rules*/ - if ((server_version = ZBX_COMPONENT_VERSION(ZABBIX_VERSION_MAJOR, ZABBIX_VERSION_MINOR)) != version) + if (ZBX_PROXY_VERSION_CURRENT != compatibility) { - now = (int)time(NULL); + int now = zbx_time(), print_log = 0; if (proxy->last_version_error_time <= now) { @@ -5003,36 +3427,30 @@ int zbx_check_protocol_version(DC_PROXY *proxy, int version) zbx_update_proxy_lasterror(proxy); } - /* don't accept pre 4.2 data */ - if (ZBX_COMPONENT_VERSION(4, 2) > version) + if (ZBX_PROXY_VERSION_UNSUPPORTED == compatibility) { if (1 == print_log) { - zabbix_log(LOG_LEVEL_WARNING, "cannot process proxy \"%s\":" - " protocol version %d.%d is not supported anymore", - proxy->host, ZBX_COMPONENT_VERSION_MAJOR(version), - ZBX_COMPONENT_VERSION_MINOR(version)); + zabbix_log(LOG_LEVEL_WARNING, "Proxy \"%s\" version %u.%u.%u is not supported by server" + " version %d.%d.%d.", proxy->host, + ZBX_COMPONENT_VERSION_MAJOR(version), + ZBX_COMPONENT_VERSION_MINOR(version), + ZBX_COMPONENT_VERSION_PATCH(version), ZABBIX_VERSION_MAJOR, + ZABBIX_VERSION_MINOR, ZABBIX_VERSION_PATCH); } - ret = FAIL; - goto out; - } - - if (1 == print_log) - { - zabbix_log(LOG_LEVEL_WARNING, "proxy \"%s\" protocol version %d.%d differs from server version" - " %d.%d", proxy->host, ZBX_COMPONENT_VERSION_MAJOR(version), - ZBX_COMPONENT_VERSION_MINOR(version), - ZABBIX_VERSION_MAJOR, ZABBIX_VERSION_MINOR); + return FAIL; } - - if (version > server_version) + else if (ZBX_PROXY_VERSION_OUTDATED == compatibility && 1 == print_log) { - if (1 == print_log) - zabbix_log(LOG_LEVEL_WARNING, "cannot accept proxy data"); - ret = FAIL; + zabbix_log(LOG_LEVEL_WARNING, "Proxy \"%s\" version %u.%u.%u is outdated, only data collection" + " and remote execution is available with server version %d.%d.%d.", proxy->host, + ZBX_COMPONENT_VERSION_MAJOR(version), ZBX_COMPONENT_VERSION_MINOR(version), + ZBX_COMPONENT_VERSION_PATCH(version), ZABBIX_VERSION_MAJOR, + ZABBIX_VERSION_MINOR, ZABBIX_VERSION_PATCH); } - + else if (ZBX_PROXY_VERSION_UNDEFINED == compatibility) + return FAIL; } -out: - return ret; + + return SUCCEED; } diff --git a/src/libs/zbxdbhigh/template_item.c b/src/libs/zbxdbhigh/template_item.c index b93519cd3fe..9500bb99dbb 100644 --- a/src/libs/zbxdbhigh/template_item.c +++ b/src/libs/zbxdbhigh/template_item.c @@ -722,8 +722,11 @@ static void update_template_lld_rule_formulas(zbx_vector_ptr_t *items, zbx_vecto { zbx_template_item_t *item = (zbx_template_item_t *)items->values[i]; - if (0 == (ZBX_FLAG_DISCOVERY_RULE & item->flags) || CONDITION_EVAL_TYPE_EXPRESSION != item->evaltype) + if (0 == (ZBX_FLAG_DISCOVERY_RULE & item->flags) || ZBX_ACTION_CONDITION_EVAL_TYPE_EXPRESSION != + item->evaltype) + { continue; + } index = zbx_vector_ptr_bsearch(rules, &item->templateid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC); @@ -1676,7 +1679,7 @@ static void copy_template_item_tags(const zbx_vector_ptr_t *items) for (j = 0; j < item->item_tags.values_num; j++) { - tag = (zbx_db_tag_t *)item->item_tags.values[j]; + tag = item->item_tags.values[j]; if (0 != (tag->flags & ZBX_FLAG_DB_TAG_REMOVE)) { @@ -1715,7 +1718,8 @@ static void copy_template_item_tags(const zbx_vector_ptr_t *items) { const char *d = ""; - tag = (zbx_db_tag_t *)item->item_tags.values[j]; + tag = item->item_tags.values[j]; + if (0 == tag->tagid) { zbx_db_insert_add_values(&db_insert, new_tagid, item->itemid, tag->tag, tag->value); @@ -1828,7 +1832,7 @@ static void copy_template_item_script_params(const zbx_vector_ptr_t *items) for (j = 0; j < item->item_params.values_num; j++) { - param = (zbx_item_param_t *)item->item_params.values[j]; + param = item->item_params.values[j]; if (0 != (param->flags & ZBX_FLAG_ITEM_PARAM_DELETE)) { @@ -1868,7 +1872,8 @@ static void copy_template_item_script_params(const zbx_vector_ptr_t *items) { const char *d = ""; - param = (zbx_item_param_t *)item->item_params.values[j]; + param = item->item_params.values[j]; + if (0 == param->item_parameterid) { zbx_db_insert_add_values(&db_insert, item_parameter_id, item->itemid, param->name, @@ -2292,7 +2297,7 @@ static void save_template_lld_overrides(zbx_vector_ptr_t *overrides, zbx_hashset override_conditionid, (int)override_condition->operator, override_condition->macro, override_condition->value); - if (CONDITION_EVAL_TYPE_EXPRESSION == override->evaltype) + if (ZBX_ACTION_CONDITION_EVAL_TYPE_EXPRESSION == override->evaltype) { update_template_lld_formula(&override->formula, override_condition->override_conditionid, override_conditionid); diff --git a/src/libs/zbxdbhigh/trigger_linking.c b/src/libs/zbxdbhigh/trigger_linking.c index 6ce54f44676..b82a1ba1457 100644 --- a/src/libs/zbxdbhigh/trigger_linking.c +++ b/src/libs/zbxdbhigh/trigger_linking.c @@ -1209,8 +1209,8 @@ static int get_funcs_for_insert(zbx_uint64_t hostid, zbx_vector_uint64_t *insert zbx_vector_uint64_append(&(found->itemids), itemid); zbx_vector_str_append(&(found->functionids), zbx_strdup(NULL, row[1])); zbx_vector_str_append(&(found->itemkeys), zbx_strdup(NULL, row[4])); - zbx_vector_str_append(&(found->names), DBdyn_escape_string(row[2])); - zbx_vector_str_append(&(found->parameters), DBdyn_escape_string(row[3])); + zbx_vector_str_append(&(found->names), zbx_strdup(NULL, row[2])); + zbx_vector_str_append(&(found->parameters), zbx_strdup(NULL, row[3])); } else { @@ -1225,8 +1225,8 @@ static int get_funcs_for_insert(zbx_uint64_t hostid, zbx_vector_uint64_t *insert zbx_vector_uint64_append(&(local_temp_t.itemids), itemid); zbx_vector_str_append(&(local_temp_t.functionids), zbx_strdup(NULL, row[1])); zbx_vector_str_append(&(local_temp_t.itemkeys), zbx_strdup(NULL, row[4])); - zbx_vector_str_append(&(local_temp_t.names), DBdyn_escape_string(row[2])); - zbx_vector_str_append(&(local_temp_t.parameters), DBdyn_escape_string(row[3])); + zbx_vector_str_append(&(local_temp_t.names),zbx_strdup(NULL, row[2])); + zbx_vector_str_append(&(local_temp_t.parameters), zbx_strdup(NULL, row[3])); local_temp_t.triggerid = temp_t.triggerid; @@ -1280,7 +1280,7 @@ static int execute_triggers_inserts(zbx_vector_trigger_copies_insert_t *trigger_ zbx_db_insert_add_values(&db_insert, triggerid, trigger_copy_template->description, (int)trigger_copy_template->priority, (int)trigger_copy_template->status, trigger_copy_template->comments, trigger_copy_template->url, - (int)trigger_copy_template->type, (int)TRIGGER_VALUE_OK, (int)TRIGGER_STATE_NORMAL, + (int)trigger_copy_template->type, TRIGGER_VALUE_OK, TRIGGER_STATE_NORMAL, trigger_copy_template->templateid, (int)trigger_copy_template->flags, (int)trigger_copy_template->recovery_mode, (int)trigger_copy_template->correlation_mode, trigger_copy_template->correlation_tag, (int)trigger_copy_template->manual_close, diff --git a/src/libs/zbxdbupgrade/dbupgrade_2010.c b/src/libs/zbxdbupgrade/dbupgrade_2010.c index c893cf5f9a7..66abf788163 100644 --- a/src/libs/zbxdbupgrade/dbupgrade_2010.c +++ b/src/libs/zbxdbupgrade/dbupgrade_2010.c @@ -945,14 +945,14 @@ static int DBpatch_2010101(void) if (1 != zbx_num_param(param)) { - if (FAIL == (ret = quote_key_param(¶m, 0))) + if (FAIL == (ret = zbx_quote_key_param(¶m, 0))) { error_message = zbx_dsprintf(error_message, "unique description" " \"%s\" contains invalid symbols and cannot be quoted", param); } } - if (SUCCEED == ret && FAIL == (ret = quote_key_param(&dsn, 0))) + if (SUCCEED == ret && FAIL == (ret = zbx_quote_key_param(&dsn, 0))) { error_message = zbx_dsprintf(error_message, "data source name" " \"%s\" contains invalid symbols and cannot be quoted", dsn); @@ -1685,7 +1685,7 @@ static int DBpatch_2010195_replace_key_param_cb(const char *data, int key_type, param = zbx_strdup(NULL, data); - unquote_key_param(param); + zbx_unquote_key_param(param); if ('\0' == *param) { @@ -1697,7 +1697,7 @@ static int DBpatch_2010195_replace_key_param_cb(const char *data, int key_type, zbx_free(param); - if (FAIL == (ret = quote_key_param(new_param, quoted))) + if (FAIL == (ret = zbx_quote_key_param(new_param, quoted))) zbx_free(new_param); return ret; diff --git a/src/libs/zbxdbupgrade/dbupgrade_2030.c b/src/libs/zbxdbupgrade/dbupgrade_2030.c index 787cbe5f9a4..bfeb5e1d524 100644 --- a/src/libs/zbxdbupgrade/dbupgrade_2030.c +++ b/src/libs/zbxdbupgrade/dbupgrade_2030.c @@ -22,6 +22,7 @@ #include "zbxdbhigh.h" #include "log.h" #include "zbxnum.h" +#include "zbxexpr.h" /* * 2.4 development database patches @@ -331,7 +332,7 @@ static int DBpatch_2030030(void) static int DBpatch_2030031(void) { - /* 16 - CONDITION_TYPE_MAINTENANCE */ + /* 16 - ZBX_CONDITION_TYPE_MAINTENANCE */ if (ZBX_DB_OK > DBexecute("update conditions set value='' where conditiontype=16")) return FAIL; @@ -478,7 +479,7 @@ static int DBpatch_2030044(void) static int DBpatch_2030045(void) { - /* 17 - CONDITION_TYPE_NODE */ + /* 17 - ZBX_CONDITION_TYPE_NODE */ const char *sql = "delete from conditions where conditiontype=17"; if (ZBX_DB_OK <= DBexecute("%s", sql)) @@ -1002,7 +1003,7 @@ static int parse_function(char **exp, char **func, char **params) for (p = *exp, s = *exp, state_fn = 0; '\0' != *p; p++) /* check for function */ { - if (SUCCEED == is_function_char(*p)) + if (SUCCEED == zbx_is_function_char(*p)) { state_fn = 1; continue; diff --git a/src/libs/zbxdbupgrade/dbupgrade_2050.c b/src/libs/zbxdbupgrade/dbupgrade_2050.c index 6e0adf91e04..fcf473918a6 100644 --- a/src/libs/zbxdbupgrade/dbupgrade_2050.c +++ b/src/libs/zbxdbupgrade/dbupgrade_2050.c @@ -57,7 +57,7 @@ static int DBpatch_2050001(void) param = zbx_strdup(NULL, row[1]); zbx_snprintf_alloc(&oid, &oid_alloc, &oid_offset, "discovery[{#SNMPVALUE},%s]", param); - if (FAIL == quote_key_param(¶m, 0)) + if (FAIL == zbx_quote_key_param(¶m, 0)) { zabbix_log(LOG_LEVEL_WARNING, "cannot convert SNMP discovery OID \"%s\":" " OID contains invalid character(s)", row[1]); @@ -178,9 +178,9 @@ static int DBpatch_2050012(void) while (SUCCEED == ret && NULL != (row = DBfetch(result))) { - init_request(&request); + zbx_init_agent_request(&request); - if (SUCCEED != parse_item_key(row[2], &request)) + if (SUCCEED != zbx_parse_item_key(row[2], &request)) { zabbix_log(LOG_LEVEL_WARNING, "cannot parse item key \"%s\"", row[2]); continue; @@ -191,7 +191,7 @@ static int DBpatch_2050012(void) /* NULL check to silence static analyzer warning */ if (NULL == param || (0 != strcmp("service.ntp", param) && 0 != strcmp("ntp", param))) { - free_request(&request); + zbx_free_agent_request(&request); continue; } @@ -212,7 +212,7 @@ static int DBpatch_2050012(void) while ('\0' != *(p++)); } - free_request(&request); + zbx_free_agent_request(&request); /* replace "net.tcp.service" with "net.udp.service" */ diff --git a/src/libs/zbxdbupgrade/dbupgrade_3010.c b/src/libs/zbxdbupgrade/dbupgrade_3010.c index ad235022307..5b27f3904da 100644 --- a/src/libs/zbxdbupgrade/dbupgrade_3010.c +++ b/src/libs/zbxdbupgrade/dbupgrade_3010.c @@ -465,7 +465,7 @@ static int DBpatch_3010024_validate_action(zbx_uint64_t actionid, int eventsourc DB_RESULT result; int conditiontype, ret = ZBX_3010024_ACTION_DISABLE, value; - /* evaltype: 0 - CONDITION_EVAL_TYPE_AND_OR, 1 - CONDITION_EVAL_TYPE_AND */ + /* evaltype: 0 - ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR, 1 - ZBX_ACTION_CONDITION_EVAL_TYPE_AND */ if (evaltype != 0 && evaltype != 1) return ret; @@ -478,7 +478,7 @@ static int DBpatch_3010024_validate_action(zbx_uint64_t actionid, int eventsourc /* eventsource: 0 - EVENT_SOURCE_TRIGGERS, 3 - EVENT_SOURCE_INTERNAL */ if (0 == eventsource) { - /* conditiontype: 5 - CONDITION_TYPE_TRIGGER_VALUE */ + /* conditiontype: 5 - ZBX_CONDITION_TYPE_TRIGGER_VALUE */ if (5 != conditiontype) continue; @@ -510,7 +510,7 @@ static int DBpatch_3010024_validate_action(zbx_uint64_t actionid, int eventsourc } else if (3 == eventsource) { - /* conditiontype: 23 - CONDITION_TYPE_EVENT_TYPE */ + /* conditiontype: 23 - ZBX_CONDITION_TYPE_EVENT_TYPE */ if (23 != conditiontype) continue; @@ -695,7 +695,7 @@ static void DBpatch_3010026_get_conditionids(zbx_uint64_t actionid, const char * /* eventsource: 0 - EVENT_SOURCE_TRIGGERS, 3 - EVENT_SOURCE_INTERNAL */ if (0 == eventsource) { - /* conditiontype: 5 - CONDITION_TYPE_TRIGGER_VALUE */ + /* conditiontype: 5 - ZBX_CONDITION_TYPE_TRIGGER_VALUE */ result = DBselect("select conditionid,value from conditions" " where actionid=" ZBX_FS_UI64 " and conditiontype=5", @@ -703,7 +703,7 @@ static void DBpatch_3010026_get_conditionids(zbx_uint64_t actionid, const char * } else if (3 == eventsource) { - /* conditiontype: 23 - CONDITION_TYPE_EVENT_TYPE */ + /* conditiontype: 23 - ZBX_CONDITION_TYPE_EVENT_TYPE */ result = DBselect("select conditionid,value from conditions" " where actionid=" ZBX_FS_UI64 " and conditiontype=23" @@ -1045,7 +1045,7 @@ static int DBpatch_3010026(void) index = conditionids.values_num; DBpatch_3010026_get_conditionids(actionid, row[4], eventsource, &conditionids); - /* evaltype: 3 - CONDITION_EVAL_TYPE_EXPRESSION */ + /* evaltype: 3 - ZBX_ACTION_CONDITION_EVAL_TYPE_EXPRESSION */ if (3 != evaltype) continue; diff --git a/src/libs/zbxdbupgrade/dbupgrade_3030.c b/src/libs/zbxdbupgrade/dbupgrade_3030.c index ee01303790c..1a549a26713 100644 --- a/src/libs/zbxdbupgrade/dbupgrade_3030.c +++ b/src/libs/zbxdbupgrade/dbupgrade_3030.c @@ -1749,7 +1749,7 @@ static int DBpatch_3030139(void) static int DBpatch_3030140(void) { - /* CONDITION_TYPE_TIME_PERIOD */ + /* ZBX_CONDITION_TYPE_TIME_PERIOD */ return DBpatch_trailing_semicolon_remove("conditions", "conditionid", "value", " where conditiontype=6"); } diff --git a/src/libs/zbxdbupgrade/dbupgrade_3050.c b/src/libs/zbxdbupgrade/dbupgrade_3050.c index 33a8eb25d7e..07253445bd6 100644 --- a/src/libs/zbxdbupgrade/dbupgrade_3050.c +++ b/src/libs/zbxdbupgrade/dbupgrade_3050.c @@ -1660,8 +1660,8 @@ static int DBpatch_3050145(void) if (0 == (program_type & ZBX_PROGRAM_TYPE_SERVER)) return SUCCEED; - /* CONDITION_OPERATOR_IN (4) -> CONDITION_OPERATOR_YES (10) */ - /* for conditiontype CONDITION_TYPE_SUPPRESSED (16) */ + /* ZBX_CONDITION_OPERATOR_IN (4) -> ZBX_CONDITION_OPERATOR_YES (10) */ + /* for conditiontype ZBX_CONDITION_TYPE_SUPPRESSED (16) */ ret = DBexecute("update conditions" " set operator=10" " where conditiontype=16" @@ -1680,8 +1680,8 @@ static int DBpatch_3050146(void) if (0 == (program_type & ZBX_PROGRAM_TYPE_SERVER)) return SUCCEED; - /* CONDITION_OPERATOR_NOT_IN (7) -> CONDITION_OPERATOR_NO (11) */ - /* for conditiontype CONDITION_TYPE_SUPPRESSED (16) */ + /* ZBX_CONDITION_OPERATOR_NOT_IN (7) -> ZBX_CONDITION_OPERATOR_NO (11) */ + /* for conditiontype ZBX_CONDITION_TYPE_SUPPRESSED (16) */ ret = DBexecute("update conditions" " set operator=11" " where conditiontype=16" diff --git a/src/libs/zbxdbupgrade/dbupgrade_4030.c b/src/libs/zbxdbupgrade/dbupgrade_4030.c index 31cd0dc1598..6151c5f3c8d 100644 --- a/src/libs/zbxdbupgrade/dbupgrade_4030.c +++ b/src/libs/zbxdbupgrade/dbupgrade_4030.c @@ -19,9 +19,7 @@ #include "dbupgrade.h" -#include "zbxexpr.h" #include "zbxdbhigh.h" -#include "zbxnum.h" /* * 4.4 development database patches diff --git a/src/libs/zbxdbupgrade/dbupgrade_5010.c b/src/libs/zbxdbupgrade/dbupgrade_5010.c index 04e38b7756c..7c982585efc 100644 --- a/src/libs/zbxdbupgrade/dbupgrade_5010.c +++ b/src/libs/zbxdbupgrade/dbupgrade_5010.c @@ -19,7 +19,6 @@ #include "dbupgrade.h" -#include "zbxexpr.h" #include "zbxdbhigh.h" #include "log.h" #include "zbxalgo.h" diff --git a/src/libs/zbxdbupgrade/dbupgrade_5030.c b/src/libs/zbxdbupgrade/dbupgrade_5030.c index 00797634b13..5c814e629c8 100644 --- a/src/libs/zbxdbupgrade/dbupgrade_5030.c +++ b/src/libs/zbxdbupgrade/dbupgrade_5030.c @@ -3858,18 +3858,18 @@ static int DBpatch_5030123(void) static int DBpatch_5030127(void) { -#define CONDITION_TYPE_APPLICATION 15 +#define ZBX_CONDITION_TYPE_APPLICATION 15 /* deprecated */ if (0 == (program_type & ZBX_PROGRAM_TYPE_SERVER)) return SUCCEED; if (ZBX_DB_OK > DBexecute("update conditions set conditiontype=%d,value2='Application' where conditiontype=%d", - CONDITION_TYPE_EVENT_TAG_VALUE, CONDITION_TYPE_APPLICATION)) + ZBX_CONDITION_TYPE_EVENT_TAG_VALUE, ZBX_CONDITION_TYPE_APPLICATION)) { return FAIL; } return SUCCEED; -#undef CONDITION_TYPE_APPLICATION +#undef ZBX_CONDITION_TYPE_APPLICATION } static int DBpatch_5030128(void) @@ -5168,7 +5168,7 @@ static char *dbpatch_formula_to_expression(zbx_uint64_t itemid, const char *form ZBX_FS_UI64 "\" formula host:key parameter at %s", itemid, ptr); } - ret = parse_host_key(arg0, &host, &key); + ret = zbx_parse_host_key(arg0, &host, &key); zbx_free(arg0); if (FAIL == ret) @@ -5469,9 +5469,9 @@ static int DBpatch_5030169(void) params_offset = 0; - init_request(&request); + zbx_init_agent_request(&request); - if (SUCCEED != parse_item_key(row[1], &request)) + if (SUCCEED != zbx_parse_item_key(row[1], &request)) { zabbix_log(LOG_LEVEL_WARNING, "Cannot parse aggregate checks item key \"%s\"", row[1]); continue; @@ -5479,7 +5479,7 @@ static int DBpatch_5030169(void) ret_formula = dbpatch_aggregate2formula(row[0], &request, ¶ms, ¶ms_alloc, ¶ms_offset, &error); - free_request(&request); + zbx_free_agent_request(&request); if (FAIL == ret_formula) { diff --git a/src/libs/zbxdbupgrade/dbupgrade_5050.c b/src/libs/zbxdbupgrade/dbupgrade_5050.c index 19019031141..3a0300d2a02 100644 --- a/src/libs/zbxdbupgrade/dbupgrade_5050.c +++ b/src/libs/zbxdbupgrade/dbupgrade_5050.c @@ -1590,6 +1590,7 @@ static void services_times_convert_downtime(zbx_vector_services_times_t *service service_time_new.note = zbx_strdup(NULL, ""); zbx_vector_services_times_append(services_times, service_time_new); + service_time = &services_times->values[j]; } service_time->to = service_downtime->from; diff --git a/src/libs/zbxdbupgrade/dbupgrade_6010.c b/src/libs/zbxdbupgrade/dbupgrade_6010.c index a25487ad766..eb9334c7033 100644 --- a/src/libs/zbxdbupgrade/dbupgrade_6010.c +++ b/src/libs/zbxdbupgrade/dbupgrade_6010.c @@ -759,7 +759,7 @@ static int DBpatch_6010033_split_groups(void) ADD_GROUPIDS_FROM("opgroup"); ADD_GROUPIDS_FROM("scripts"); - /* 0 - CONDITION_TYPE_HOST_GROUP */ + /* 0 - ZBX_CONDITION_TYPE_HOST_GROUP */ result = DBselect("select distinct value from conditions where conditiontype=0"); while (NULL != (row = DBfetch(result))) diff --git a/src/libs/zbxdbupgrade/dbupgrade_6030.c b/src/libs/zbxdbupgrade/dbupgrade_6030.c index f081969c31a..c9a97e161f2 100644 --- a/src/libs/zbxdbupgrade/dbupgrade_6030.c +++ b/src/libs/zbxdbupgrade/dbupgrade_6030.c @@ -20,6 +20,7 @@ #include "zbxcommon.h" #include "zbxdbhigh.h" #include "dbupgrade.h" +#include "zbxdbschema.h" extern unsigned char program_type; @@ -162,6 +163,305 @@ static int DBpatch_6030006(void) return DBmodify_field_type("proxy_autoreg_host", &field, &old_field); } +static int DBpatch_6030007(void) +{ + const ZBX_FIELD field = {"server_status", "", NULL, NULL, 0, ZBX_TYPE_SHORTTEXT, ZBX_NOTNULL, 0}; + + return DBadd_field("config", &field); +} + +static int DBpatch_6030008(void) +{ + const ZBX_FIELD field = {"version", "0", NULL, NULL, 0, ZBX_TYPE_INT, ZBX_NOTNULL, 0}; + + return DBadd_field("host_rtdata", &field); +} + +static int DBpatch_6030009(void) +{ + const ZBX_FIELD field = {"compatibility", "0", NULL, NULL, 0, ZBX_TYPE_INT, ZBX_NOTNULL, 0}; + + return DBadd_field("host_rtdata", &field); +} + +static int DBpatch_6030010(void) +{ + const ZBX_FIELD field = {"url", "", NULL, NULL, 2048, ZBX_TYPE_CHAR, ZBX_NOTNULL, 0}; + + return DBmodify_field_type("users", &field, NULL); +} + +static int DBpatch_6030011(void) +{ + return DBcreate_changelog_insert_trigger("drules", "druleid"); +} + +static int DBpatch_6030012(void) +{ + return DBcreate_changelog_update_trigger("drules", "druleid"); +} + +static int DBpatch_6030013(void) +{ + return DBcreate_changelog_delete_trigger("drules", "druleid"); +} + +static int DBpatch_6030014(void) +{ + return DBcreate_changelog_insert_trigger("dchecks", "dcheckid"); +} + +static int DBpatch_6030015(void) +{ + return DBcreate_changelog_update_trigger("dchecks", "dcheckid"); +} + +static int DBpatch_6030016(void) +{ + return DBcreate_changelog_delete_trigger("dchecks", "dcheckid"); +} + +static int DBpatch_6030017(void) +{ + return DBcreate_changelog_insert_trigger("httptest", "httptestid"); +} + +static int DBpatch_6030018(void) +{ + return DBcreate_changelog_update_trigger("httptest", "httptestid"); +} + +static int DBpatch_6030019(void) +{ + return DBcreate_changelog_delete_trigger("httptest", "httptestid"); +} + +static int DBpatch_6030020(void) +{ + return DBcreate_changelog_insert_trigger("httptest_field", "httptest_fieldid"); +} + +static int DBpatch_6030021(void) +{ + return DBcreate_changelog_update_trigger("httptest_field", "httptest_fieldid"); +} + +static int DBpatch_6030022(void) +{ + return DBcreate_changelog_delete_trigger("httptest_field", "httptest_fieldid"); +} + +static int DBpatch_6030023(void) +{ + return DBcreate_changelog_insert_trigger("httptestitem", "httptestitemid"); +} + +static int DBpatch_6030024(void) +{ + return DBcreate_changelog_update_trigger("httptestitem", "httptestitemid"); +} + +static int DBpatch_6030025(void) +{ + return DBcreate_changelog_delete_trigger("httptestitem", "httptestitemid"); +} + +static int DBpatch_6030026(void) +{ + return DBcreate_changelog_insert_trigger("httpstep", "httpstepid"); +} + +static int DBpatch_6030027(void) +{ + return DBcreate_changelog_update_trigger("httpstep", "httpstepid"); +} + +static int DBpatch_6030028(void) +{ + return DBcreate_changelog_delete_trigger("httpstep", "httpstepid"); +} + +static int DBpatch_6030029(void) +{ + return DBcreate_changelog_insert_trigger("httpstep_field", "httpstep_fieldid"); +} + +static int DBpatch_6030030(void) +{ + return DBcreate_changelog_update_trigger("httpstep_field", "httpstep_fieldid"); +} + +static int DBpatch_6030031(void) +{ + return DBcreate_changelog_delete_trigger("httpstep_field", "httpstep_fieldid"); +} + +static int DBpatch_6030032(void) +{ + return DBcreate_changelog_insert_trigger("httpstepitem", "httpstepitemid"); +} + +static int DBpatch_6030033(void) +{ + return DBcreate_changelog_update_trigger("httpstepitem", "httpstepitemid"); +} + +static int DBpatch_6030034(void) +{ + return DBcreate_changelog_delete_trigger("httpstepitem", "httpstepitemid"); +} + +static int DBpatch_6030035(void) +{ + return DBdrop_field("drules", "nextcheck"); +} + +static int DBpatch_6030036(void) +{ + return DBdrop_field("httptest", "nextcheck"); +} + +static int DBpatch_6030037(void) +{ + const ZBX_FIELD field = {"discovery_groupid", NULL, NULL, NULL, 0, ZBX_TYPE_ID, 0, 0}; + + return DBdrop_not_null("config", &field); +} + +static int DBpatch_6030038(void) +{ + return DBdrop_foreign_key("dchecks", 1); +} + +static int DBpatch_6030039(void) +{ + const ZBX_FIELD field = {"druleid", NULL, "drules", "druleid", 0, ZBX_TYPE_ID, 0, 0}; + + return DBadd_foreign_key("dchecks", 1, &field); +} + +static int DBpatch_6030040(void) +{ + return DBdrop_foreign_key("httptest", 2); +} + +static int DBpatch_6030041(void) +{ + const ZBX_FIELD field = {"hostid", NULL, "hosts", "hostid", 0, ZBX_TYPE_ID, 0, 0}; + + return DBadd_foreign_key("httptest", 2, &field); +} + +static int DBpatch_6030042(void) +{ + return DBdrop_foreign_key("httptest", 3); +} + +static int DBpatch_6030043(void) +{ + const ZBX_FIELD field = {"templateid", NULL, "httptest", "httptestid", 0, ZBX_TYPE_ID, 0, 0}; + + return DBadd_foreign_key("httptest", 3, &field); +} + +static int DBpatch_6030044(void) +{ + return DBdrop_foreign_key("httpstep", 1); +} + +static int DBpatch_6030045(void) +{ + const ZBX_FIELD field = {"httptestid", NULL, "httptest", "httptestid", 0, ZBX_TYPE_ID, 0, 0}; + + return DBadd_foreign_key("httpstep", 1, &field); +} + +static int DBpatch_6030046(void) +{ + return DBdrop_foreign_key("httptestitem", 1); +} + +static int DBpatch_6030047(void) +{ + const ZBX_FIELD field = {"httptestid", NULL, "httptest", "httptestid", 0, ZBX_TYPE_ID, 0, 0}; + + return DBadd_foreign_key("httptestitem", 1, &field); +} + +static int DBpatch_6030048(void) +{ + return DBdrop_foreign_key("httptestitem", 2); +} + +static int DBpatch_6030049(void) +{ + const ZBX_FIELD field = {"itemid", NULL, "items", "itemid", 0, ZBX_TYPE_ID, 0, 0}; + + return DBadd_foreign_key("httptestitem", 2, &field); +} + +static int DBpatch_6030050(void) +{ + return DBdrop_foreign_key("httpstepitem", 1); +} + +static int DBpatch_6030051(void) +{ + const ZBX_FIELD field = {"httpstepid", NULL, "httpstep", "httpstepid", 0, ZBX_TYPE_ID, 0, 0}; + + return DBadd_foreign_key("httpstepitem", 1, &field); +} + +static int DBpatch_6030052(void) +{ + return DBdrop_foreign_key("httpstepitem", 2); +} + +static int DBpatch_6030053(void) +{ + const ZBX_FIELD field = {"itemid", NULL, "items", "itemid", 0, ZBX_TYPE_ID, 0, 0}; + + return DBadd_foreign_key("httpstepitem", 2, &field); +} + +static int DBpatch_6030054(void) +{ + return DBdrop_foreign_key("httptest_field", 1); +} + +static int DBpatch_6030055(void) +{ + const ZBX_FIELD field = {"httptestid", NULL, "httptest", "httptestid", 0, ZBX_TYPE_ID, 0, 0}; + + return DBadd_foreign_key("httptest_field", 1, &field); +} + +static int DBpatch_6030056(void) +{ + return DBdrop_foreign_key("httpstep_field", 1); +} + +static int DBpatch_6030057(void) +{ + const ZBX_FIELD field = {"httpstepid", NULL, "httpstep", "httpstepid", 0, ZBX_TYPE_ID, 0, 0}; + + return DBadd_foreign_key("httpstep_field", 1, &field); +} + +static int DBpatch_6030058(void) +{ + const ZBX_FIELD field = {"provider", "0", NULL, NULL, 0, ZBX_TYPE_INT, ZBX_NOTNULL, 0}; + + return DBadd_field("media_type", &field); +} + +static int DBpatch_6030059(void) +{ + const ZBX_FIELD field = {"status", "1", NULL, NULL, 0, ZBX_TYPE_INT, ZBX_NOTNULL, 0}; + + return DBset_default("media_type", &field); +} + #endif DBPATCH_START(6030) @@ -175,5 +475,58 @@ DBPATCH_ADD(6030003, 0, 1) DBPATCH_ADD(6030004, 0, 1) DBPATCH_ADD(6030005, 0, 1) DBPATCH_ADD(6030006, 0, 1) +DBPATCH_ADD(6030007, 0, 1) +DBPATCH_ADD(6030008, 0, 1) +DBPATCH_ADD(6030009, 0, 1) +DBPATCH_ADD(6030010, 0, 1) +DBPATCH_ADD(6030011, 0, 1) +DBPATCH_ADD(6030012, 0, 1) +DBPATCH_ADD(6030013, 0, 1) +DBPATCH_ADD(6030014, 0, 1) +DBPATCH_ADD(6030015, 0, 1) +DBPATCH_ADD(6030016, 0, 1) +DBPATCH_ADD(6030017, 0, 1) +DBPATCH_ADD(6030018, 0, 1) +DBPATCH_ADD(6030019, 0, 1) +DBPATCH_ADD(6030020, 0, 1) +DBPATCH_ADD(6030021, 0, 1) +DBPATCH_ADD(6030022, 0, 1) +DBPATCH_ADD(6030023, 0, 1) +DBPATCH_ADD(6030024, 0, 1) +DBPATCH_ADD(6030025, 0, 1) +DBPATCH_ADD(6030026, 0, 1) +DBPATCH_ADD(6030027, 0, 1) +DBPATCH_ADD(6030028, 0, 1) +DBPATCH_ADD(6030029, 0, 1) +DBPATCH_ADD(6030030, 0, 1) +DBPATCH_ADD(6030031, 0, 1) +DBPATCH_ADD(6030032, 0, 1) +DBPATCH_ADD(6030033, 0, 1) +DBPATCH_ADD(6030034, 0, 1) +DBPATCH_ADD(6030035, 0, 1) +DBPATCH_ADD(6030036, 0, 1) +DBPATCH_ADD(6030037, 0, 1) +DBPATCH_ADD(6030038, 0, 1) +DBPATCH_ADD(6030039, 0, 1) +DBPATCH_ADD(6030040, 0, 1) +DBPATCH_ADD(6030041, 0, 1) +DBPATCH_ADD(6030042, 0, 1) +DBPATCH_ADD(6030043, 0, 1) +DBPATCH_ADD(6030044, 0, 1) +DBPATCH_ADD(6030045, 0, 1) +DBPATCH_ADD(6030046, 0, 1) +DBPATCH_ADD(6030047, 0, 1) +DBPATCH_ADD(6030048, 0, 1) +DBPATCH_ADD(6030049, 0, 1) +DBPATCH_ADD(6030050, 0, 1) +DBPATCH_ADD(6030051, 0, 1) +DBPATCH_ADD(6030052, 0, 1) +DBPATCH_ADD(6030053, 0, 1) +DBPATCH_ADD(6030054, 0, 1) +DBPATCH_ADD(6030055, 0, 1) +DBPATCH_ADD(6030056, 0, 1) +DBPATCH_ADD(6030057, 0, 1) +DBPATCH_ADD(6030058, 0, 1) +DBPATCH_ADD(6030059, 0, 1) DBPATCH_END() diff --git a/src/libs/zbxembed/global.c b/src/libs/zbxembed/global.c index 914705dac28..cebb8553ec4 100644 --- a/src/libs/zbxembed/global.c +++ b/src/libs/zbxembed/global.c @@ -23,7 +23,6 @@ #include "embed.h" #include "duktape.h" #include "base64.h" -#include "zbxhash.h" #include "zbxcrypto.h" /****************************************************************************** diff --git a/src/libs/zbxeval/execute.c b/src/libs/zbxeval/execute.c index 3c4870341b8..8a669661a69 100644 --- a/src/libs/zbxeval/execute.c +++ b/src/libs/zbxeval/execute.c @@ -2031,7 +2031,7 @@ static int eval_execute_function_char(const zbx_eval_context_t *ctx, const zbx_e if (SUCCEED != eval_convert_function_arg(ctx, token, ZBX_VARIANT_UI64, arg, error)) return FAIL; - if (255 < arg->data.ui64) + if (127 < arg->data.ui64) { *error = zbx_dsprintf(*error, "function argument \"%s\" is out of allowed range at \"%s\"", zbx_variant_value_desc(arg), ctx->expression + token->loc.l); diff --git a/src/libs/zbxeval/parse.c b/src/libs/zbxeval/parse.c index be33b950d38..e626eaa92f1 100644 --- a/src/libs/zbxeval/parse.c +++ b/src/libs/zbxeval/parse.c @@ -642,7 +642,7 @@ size_t eval_parse_query(const char *str, const char **phost, const char **pkey, } else if ('/' != *key) { - while (SUCCEED == is_hostname_char(*key)) + while (SUCCEED == zbx_is_hostname_char(*key)) key++; } @@ -675,7 +675,7 @@ size_t eval_parse_query(const char *str, const char **phost, const char **pkey, end += ZBX_CONST_STRLEN(MVAR_ITEM_KEY) + offset; } } - else if (SUCCEED != parse_key(&end)) + else if (SUCCEED != zbx_parse_key(&end)) return 0; if (*end == '?') diff --git a/src/libs/zbxexpr/Makefile.am b/src/libs/zbxexpr/Makefile.am index 75027d380ce..72cbe843035 100644 --- a/src/libs/zbxexpr/Makefile.am +++ b/src/libs/zbxexpr/Makefile.am @@ -3,6 +3,9 @@ noinst_LIBRARIES = libzbxexpr.a libzbxexpr_a_SOURCES = \ + host.c \ + macro.c \ + function.c \ expr.c \ interval.c \ token.c diff --git a/src/libs/zbxexpr/expr.c b/src/libs/zbxexpr/expr.c index feb4b44cf0d..e9a20c3bb13 100644 --- a/src/libs/zbxexpr/expr.c +++ b/src/libs/zbxexpr/expr.c @@ -24,811 +24,144 @@ /****************************************************************************** * * - * Purpose: validate parameters and give position of terminator if found and * - * not quoted * - * * - * Parameters: expr - [IN] string to parse that contains parameters * - * * - * terminator - [IN] use ')' if parameters end with * - * parenthesis or '\0' if ends with NULL * - * terminator * - * par_r - [OUT] position of the terminator if found * - * lpp_offset - [OUT] offset of the last parsed parameter * - * lpp_len - [OUT] length of the last parsed parameter * + * Return value: SUCCEED - the char is allowed in the item key * + * FAIL - otherwise * * * - * Return value: SUCCEED - closing parenthesis was found or other custom * - * terminator and not quoted and return info about a * - * last processed parameter. * - * FAIL - does not look like a valid function parameter * - * list and return info about a last processed * - * parameter. * + * Comments: in key allowed characters: '0-9a-zA-Z._-' * + * !!! Don't forget to sync the code with PHP !!! * * * ******************************************************************************/ -static int function_validate_parameters(const char *expr, char terminator, size_t *par_r, size_t *lpp_offset, - size_t *lpp_len) +int zbx_is_key_char(unsigned char c) { -#define ZBX_FUNC_PARAM_NEXT 0 -#define ZBX_FUNC_PARAM_QUOTED 1 -#define ZBX_FUNC_PARAM_UNQUOTED 2 -#define ZBX_FUNC_PARAM_POSTQUOTED 3 - - const char *ptr; - int state = ZBX_FUNC_PARAM_NEXT; - - *lpp_offset = 0; - - for (ptr = expr; '\0' != *ptr; ptr++) - { - if (terminator == *ptr && ZBX_FUNC_PARAM_QUOTED != state) - { - *par_r = ptr - expr; - return SUCCEED; - } - - switch (state) - { - case ZBX_FUNC_PARAM_NEXT: - *lpp_offset = ptr - expr; - if ('"' == *ptr) - state = ZBX_FUNC_PARAM_QUOTED; - else if (' ' != *ptr && ',' != *ptr) - state = ZBX_FUNC_PARAM_UNQUOTED; - break; - case ZBX_FUNC_PARAM_QUOTED: - if ('"' == *ptr && '\\' != *(ptr - 1)) - state = ZBX_FUNC_PARAM_POSTQUOTED; - break; - case ZBX_FUNC_PARAM_UNQUOTED: - if (',' == *ptr) - state = ZBX_FUNC_PARAM_NEXT; - break; - case ZBX_FUNC_PARAM_POSTQUOTED: - if (',' == *ptr) - { - state = ZBX_FUNC_PARAM_NEXT; - } - else if (' ' != *ptr) - { - *lpp_len = ptr - (expr + *lpp_offset); - return FAIL; - } - break; - default: - THIS_SHOULD_NEVER_HAPPEN; - } - } - - *lpp_len = ptr - (expr + *lpp_offset); - - if (terminator == *ptr && ZBX_FUNC_PARAM_QUOTED != state) - { - *par_r = ptr - expr; + if (0 != isalnum(c)) return SUCCEED; - } - return FAIL; - -#undef ZBX_FUNC_PARAM_NEXT -#undef ZBX_FUNC_PARAM_QUOTED -#undef ZBX_FUNC_PARAM_UNQUOTED -#undef ZBX_FUNC_PARAM_POSTQUOTED -} - -/****************************************************************************** - * * - * Purpose: given the position of opening function parenthesis find the * - * position of a closing one * - * * - * Parameters: expr - [IN] string to parse * - * par_l - [IN] position of the opening parenthesis * - * par_r - [OUT] position of the closing parenthesis * - * lpp_offset - [OUT] offset of the last parsed parameter * - * lpp_len - [OUT] length of the last parsed parameter * - * * - * Return value: SUCCEED - closing parenthesis was found * - * FAIL - string after par_l does not look like a valid * - * function parameter list * - * * - ******************************************************************************/ -static int function_match_parenthesis(const char *expr, size_t par_l, size_t *par_r, size_t *lpp_offset, - size_t *lpp_len) -{ - if (SUCCEED == function_validate_parameters(expr + par_l + 1, ')', par_r, lpp_offset, lpp_len)) - { - *par_r += par_l + 1; + if (c == '.' || c == '_' || c == '-') return SUCCEED; - } - *lpp_offset += par_l + 1; return FAIL; } /****************************************************************************** * * - * Purpose: parses function name * + * Purpose: advances pointer to first invalid character in string * + * ensuring that everything before it is a valid key * * * - * Parameters: expr - [IN] the function expression: func(p1, p2,...) * - * length - [OUT] the function name length or the amount of * - * characters that can be safely skipped * + * e.g., system.run[cat /etc/passwd | awk -F: '{ print $1 }'] * * * - * Return value: SUCCEED - the function name was successfully parsed * - * FAIL - failed to parse function name * + * Parameters: exp - [IN/OUT] pointer to the first char of key * * * - ******************************************************************************/ -static int function_parse_name(const char *expr, size_t *length) -{ - const char *ptr; - - for (ptr = expr; SUCCEED == is_function_char(*ptr); ptr++) - ; - - *length = ptr - expr; - - return ptr != expr && '(' == *ptr ? SUCCEED : FAIL; -} - -/****************************************************************************** + * e.g., {host:system.run[cat /etc/passwd | awk -F: '{ print $1 }'].last(0)} * + * ^ * + * Return value: returns FAIL only if no key is present (length 0), * + * or the whole string is invalid. SUCCEED otherwise. * * * - * Purpose: check whether expression starts with a valid function * - * * - * Parameters: expr - [IN] string to parse * - * par_l - [OUT] position of the opening parenthesis * - * or the amount of characters to skip * - * par_r - [OUT] position of the closing parenthesis * - * error - [OUT] error message * - * max_error_len - [IN] error size * - * * - * Return value: SUCCEED - string starts with a valid function * - * FAIL - string does not start with a function and par_l * - * characters can be safely skipped * - * * - ******************************************************************************/ -int zbx_function_validate(const char *expr, size_t *par_l, size_t *par_r, char *error, int max_error_len) -{ - size_t lpp_offset, lpp_len; - - /* try to validate function name */ - if (SUCCEED == function_parse_name(expr, par_l)) - { - /* now we know the position of '(', try to find ')' */ - if (SUCCEED == function_match_parenthesis(expr, *par_l, par_r, &lpp_offset, &lpp_len)) - return SUCCEED; - - if (NULL != error && *par_l > *par_r) - { - zbx_snprintf(error, max_error_len, "Incorrect function '%.*s' expression. " - "Check expression part starting from: %.*s", - (int)*par_l, expr, (int)lpp_len, expr + lpp_offset); - - return FAIL; - } - } - - if (NULL != error) - zbx_snprintf(error, max_error_len, "Incorrect function expression: %s", expr); - - return FAIL; -} - -/****************************************************************************** - * * - * Purpose: validate parameters that end with '\0' * - * * - * Parameters: expr - [IN] string to parse that contains parameters * - * length - [OUT] length of parameters * - * * - * Return value: SUCCEED - null termination encountered when quotes are * - * closed and no other error * - * FAIL - does not look like a valid * - * function parameter list * + * Comments: the pointer is advanced to the first invalid character even if * + * FAIL is returned (meaning there is a syntax error in item key). * + * If necessary, the caller must keep a copy of pointer original * + * value. * * * ******************************************************************************/ -int zbx_function_validate_parameters(const char *expr, size_t *length) +int zbx_parse_key(const char **exp) { - size_t offset, len; - - return function_validate_parameters(expr, '\0', length, &offset, &len); -} - -#define ZBX_MACRO_REGEX_PREFIX "regex:" + const char *s; -/****************************************************************************** - * * - * Purpose: * - * parses user macro and finds its end position and context location * - * * - * Parameters: * - * macro - [IN] the macro to parse * - * macro_r - [OUT] the position of ending '}' character * - * context_l - [OUT] the position of context start character (first non * - * space character after context separator ':') * - * 0 if macro does not have context specified. * - * context_r - [OUT] the position of context end character (either the * - * ending '"' for quoted context values or the last * - * character before the ending '}' character) * - * 0 if macro does not have context specified. * - * context_op - [OUT] the context matching operator (optional): * - * CONDITION_OPERATOR_EQUAL * - * CONDITION_OPERATOR_REGEXP * - * * - * Return value: * - * SUCCEED - the macro was parsed successfully. * - * FAIL - the macro parsing failed, the content of output variables * - * is not defined. * - * * - ******************************************************************************/ -int zbx_user_macro_parse(const char *macro, int *macro_r, int *context_l, int *context_r, unsigned char *context_op) -{ - int i; - - /* find the end of macro name by skipping {$ characters and iterating through */ - /* valid macro name characters */ - for (i = 2; SUCCEED == is_macro_char(macro[i]); i++) + for (s = *exp; SUCCEED == zbx_is_key_char(*s); s++) ; - /* check for empty macro name */ - if (2 == i) - return FAIL; - - if ('}' == macro[i]) - { - /* no macro context specified, parsing done */ - *macro_r = i; - *context_l = 0; - *context_r = 0; - - if (NULL != context_op) - *context_op = CONDITION_OPERATOR_EQUAL; - - return SUCCEED; - } - - /* fail if the next character is not a macro context separator */ - if (':' != macro[i]) - return FAIL; - - i++; - if (NULL != context_op) - { - if (0 == strncmp(macro + i, ZBX_MACRO_REGEX_PREFIX, ZBX_CONST_STRLEN(ZBX_MACRO_REGEX_PREFIX))) - { - *context_op = CONDITION_OPERATOR_REGEXP; - i += ZBX_CONST_STRLEN(ZBX_MACRO_REGEX_PREFIX); - } - else - *context_op = CONDITION_OPERATOR_EQUAL; - } - - /* skip the whitespace after macro context separator */ - while (' ' == macro[i]) - i++; - - *context_l = i; - - if ('"' == macro[i]) - { - i++; - - /* process quoted context */ - for (; '"' != macro[i]; i++) - { - if ('\0' == macro[i]) - return FAIL; - - if ('\\' == macro[i] && '"' == macro[i + 1]) - i++; - } - - *context_r = i; - - while (' ' == macro[++i]) - ; - } - else - { - /* process unquoted context */ - for (; '}' != macro[i]; i++) - { - if ('\0' == macro[i]) - return FAIL; - } - - *context_r = i - 1; - } - - if ('}' != macro[i]) - return FAIL; - - *macro_r = i; - - return SUCCEED; -} - -/****************************************************************************** - * * - * Purpose: * - * parses user macro {$MACRO:<context>} into {$MACRO} and <context> * - * strings * - * * - * Parameters: * - * macro - [IN] the macro to parse * - * name - [OUT] the macro name without context * - * context - [OUT] the unquoted macro context, NULL for macros without * - * context * - * length - [OUT] the length of parsed macro (optional) * - * context_op - [OUT] the context matching operator (optional): * - * CONDITION_OPERATOR_EQUAL * - * CONDITION_OPERATOR_REGEXP * - * * - * Return value: * - * SUCCEED - the macro was parsed successfully * - * FAIL - the macro parsing failed, invalid parameter syntax * - * * - ******************************************************************************/ -int zbx_user_macro_parse_dyn(const char *macro, char **name, char **context, int *length, unsigned char *context_op) -{ - const char *ptr; - int macro_r, context_l, context_r; - size_t len; - - if (SUCCEED != zbx_user_macro_parse(macro, ¯o_r, &context_l, &context_r, context_op)) + if (*exp == s) /* the key is empty */ return FAIL; - zbx_free(*context); - - if (0 != context_l) - { - ptr = macro + context_l; - - /* find the context separator ':' by stripping spaces before context */ - while (' ' == *(--ptr)) - ; - - /* remove regex: prefix from macro name for regex contexts */ - if (NULL != context_op && CONDITION_OPERATOR_REGEXP == *context_op) - ptr -= ZBX_CONST_STRLEN(ZBX_MACRO_REGEX_PREFIX); - - /* extract the macro name and close with '}' character */ - len = ptr - macro + 1; - *name = (char *)zbx_realloc(*name, len + 1); - memcpy(*name, macro, len - 1); - (*name)[len - 1] = '}'; - (*name)[len] = '\0'; - - *context = zbx_user_macro_unquote_context_dyn(macro + context_l, context_r - context_l + 1); - } - else - { - *name = (char *)zbx_realloc(*name, macro_r + 2); - zbx_strlcpy(*name, macro, macro_r + 2); - } - - if (NULL != length) - *length = macro_r + 1; - - return SUCCEED; -} - -#undef ZBX_MACRO_REGEX_PREFIX - -/****************************************************************************** - * * - * Purpose: * - * extracts the macro context unquoting if necessary * - * * - * Parameters: * - * context - [IN] the macro context inside a user macro * - * len - [IN] the macro context length (including quotes for quoted * - * contexts) * - * * - * Return value: * - * A string containing extracted macro context. This string must be freed * - * by the caller. * - * * - ******************************************************************************/ -char *zbx_user_macro_unquote_context_dyn(const char *context, int len) -{ - int quoted = 0; - char *buffer, *ptr; - - ptr = buffer = (char *)zbx_malloc(NULL, len + 1); - - if ('"' == *context) - { - quoted = 1; - context++; - len--; - } - - while (0 < len) - { - if (1 == quoted && '\\' == *context && '"' == context[1]) - { - context++; - len--; - } - - *ptr++ = *context++; - len--; - } - - if (1 == quoted) - ptr--; - - *ptr = '\0'; - - return buffer; -} - -/****************************************************************************** - * * - * Purpose: * - * quotes user macro context if necessary * - * * - * Parameters: * - * context - [IN] the macro context * - * force_quote - [IN] if non zero then context quoting is enforced * - * error - [OUT] the error message * - * * - * Return value: * - * A string containing quoted macro context on success, NULL on error. * - * * - ******************************************************************************/ -char *zbx_user_macro_quote_context_dyn(const char *context, int force_quote, char **error) -{ - int len, quotes = 0; - char *buffer, *ptr_buffer; - const char *ptr_context = context, *start = context; - - if ('"' == *ptr_context || ' ' == *ptr_context) - force_quote = 1; - - for (; '\0' != *ptr_context; ptr_context++) - { - if ('}' == *ptr_context) - force_quote = 1; - - if ('"' == *ptr_context) - quotes++; - } - - if (0 == force_quote) - return zbx_strdup(NULL, context); - - len = (int)strlen(context) + 2 + quotes; - ptr_buffer = buffer = (char *)zbx_malloc(NULL, len + 1); - - *ptr_buffer++ = '"'; - - while ('\0' != *context) - { - if ('"' == *context) - *ptr_buffer++ = '\\'; - - *ptr_buffer++ = *context++; - } - - if ('\\' == *(ptr_buffer - 1)) - { - *error = zbx_dsprintf(*error, "quoted context \"%s\" cannot end with '\\' character", start); - zbx_free(buffer); - return NULL; - } - - *ptr_buffer++ = '"'; - *ptr_buffer++ = '\0'; - - return buffer; -} - -/****************************************************************************** - * * - * Purpose: count calculated item (prototype) formula characters that can be * - * skipped without the risk of missing a function * - * * - ******************************************************************************/ -static size_t zbx_no_function(const char *expr) -{ - const char *ptr = expr; - int inside_quote = 0, len, c_l, c_r; - zbx_token_t token; - - while ('\0' != *ptr) - { - switch (*ptr) - { - case '\\': - if (0 != inside_quote) - ptr++; - break; - case '"': - inside_quote = !inside_quote; - ptr++; - continue; - } - - if (inside_quote) - { - if ('\0' == *ptr) - break; - ptr++; - continue; - } - - if ('{' == *ptr && '$' == *(ptr + 1) && SUCCEED == zbx_user_macro_parse(ptr, &len, &c_l, &c_r, NULL)) - { - ptr += len + 1; /* skip to the position after user macro */ - } - else if ('{' == *ptr && '{' == *(ptr + 1) && '#' == *(ptr + 2) && - SUCCEED == zbx_token_parse_nested_macro(ptr, ptr, 0, &token)) - { - ptr += token.loc.r - token.loc.l + 1; - } - else if (SUCCEED != is_function_char(*ptr)) - { - ptr++; /* skip one character which cannot belong to function name */ - } - else if ((0 == strncmp("and", ptr, len = ZBX_CONST_STRLEN("and")) || - 0 == strncmp("not", ptr, len = ZBX_CONST_STRLEN("not")) || - 0 == strncmp("or", ptr, len = ZBX_CONST_STRLEN("or"))) && - NULL != strchr("()" ZBX_WHITESPACE, ptr[len])) - { - ptr += len; /* skip to the position after and/or/not operator */ - } - else if (ptr > expr && 0 != isdigit(*(ptr - 1)) && NULL != strchr(ZBX_UNIT_SYMBOLS, *ptr)) - { - ptr++; /* skip unit suffix symbol if it's preceded by a digit */ - } - else - break; - } - - return ptr - expr; -} - -/****************************************************************************** - * * - * Purpose: find the location of the next function and its parameters in * - * calculated item (prototype) formula * - * * - * Parameters: expr - [IN] string to parse * - * func_pos - [OUT] function position in the string * - * par_l - [OUT] position of the opening parenthesis * - * par_r - [OUT] position of the closing parenthesis * - * error - [OUT] error message * - * max_error_len - [IN] error size * - * * - * Return value: SUCCEED - function was found at func_pos * - * FAIL - there are no functions in the expression * - * * - ******************************************************************************/ -int zbx_function_find(const char *expr, size_t *func_pos, size_t *par_l, size_t *par_r, char *error, - int max_error_len) -{ - const char *ptr; - - for (ptr = expr; '\0' != *ptr; ptr += *par_l) - { - /* skip the part of expression that is definitely not a function */ - ptr += zbx_no_function(ptr); - *par_r = 0; - - /* try to validate function candidate */ - if (SUCCEED != zbx_function_validate(ptr, par_l, par_r, error, max_error_len)) - { - if (*par_l > *par_r) - return FAIL; - - continue; - } - - *func_pos = ptr - expr; - *par_l += *func_pos; - *par_r += *func_pos; - return SUCCEED; - } - - zbx_snprintf(error, max_error_len, "Incorrect function expression: %s", expr); - - return FAIL; -} - -/****************************************************************************** - * * - * Purpose: parses function parameter * - * * - * Parameters: expr - [IN] pre-validated function parameter list * - * param_pos - [OUT] the parameter position, excluding leading * - * whitespace * - * length - [OUT] the parameter length including trailing * - * whitespace for unquoted parameter * - * sep_pos - [OUT] the parameter separator character * - * (',' or '\0' or ')') position * - * * - ******************************************************************************/ -void zbx_function_param_parse(const char *expr, size_t *param_pos, size_t *length, size_t *sep_pos) -{ - const char *ptr = expr; - - /* skip the leading whitespace */ - while (' ' == *ptr) - ptr++; - - *param_pos = ptr - expr; - - if ('"' == *ptr) /* quoted parameter */ - { - for (ptr++; '"' != *ptr || '\\' == *(ptr - 1); ptr++) - ; - - *length = ++ptr - expr - *param_pos; - - /* skip trailing whitespace to find the next parameter */ - while (' ' == *ptr) - ptr++; - } - else /* unquoted parameter */ + if ('[' == *s) /* for instance, net.tcp.port[,80] */ { - for (ptr = expr; '\0' != *ptr && ')' != *ptr && ',' != *ptr; ptr++) - ; + int state = 0; /* 0 - init, 1 - inside quoted param, 2 - inside unquoted param */ + int array = 0; /* array nest level */ - *length = ptr - expr - *param_pos; - } - - *sep_pos = ptr - expr; -} - -/****************************************************************************** - * * - * Purpose: unquotes function parameter * - * * - * Parameters: param - [IN] the parameter to unquote * - * len - [IN] the parameter length * - * quoted - [OUT] the flag that specifies whether parameter was * - * quoted before extraction * - * * - * Return value: The unquoted parameter. This value must be freed by the * - * caller. * - * * - ******************************************************************************/ -char *zbx_function_param_unquote_dyn(const char *param, size_t len, int *quoted) -{ - char *out; - - out = (char *)zbx_malloc(NULL, len + 1); - - if (0 == (*quoted = (0 != len && '"' == *param))) - { - /* unquoted parameter - simply copy it */ - memcpy(out, param, len); - out[len] = '\0'; - } - else - { - /* quoted parameter - remove enclosing " and replace \" with " */ - const char *pin; - char *pout = out; - - for (pin = param + 1; (size_t)(pin - param) < len - 1; pin++) + for (s++; '\0' != *s; s++) { - if ('\\' == pin[0] && '"' == pin[1]) - pin++; - - *pout++ = *pin; + switch (state) + { + /* init state */ + case 0: + if (',' == *s) + ; + else if ('"' == *s) + state = 1; + else if ('[' == *s) + { + if (0 == array) + array = 1; + else + goto fail; /* incorrect syntax: multi-level array */ + } + else if (']' == *s && 0 != array) + { + array = 0; + s++; + + while (' ' == *s) /* skip trailing spaces after closing ']' */ + s++; + + if (']' == *s) + goto succeed; + + if (',' != *s) + goto fail; /* incorrect syntax */ + } + else if (']' == *s && 0 == array) + goto succeed; + else if (' ' != *s) + state = 2; + break; + /* quoted */ + case 1: + if ('"' == *s) + { + while (' ' == s[1]) /* skip trailing spaces after closing quotes */ + s++; + + if (0 == array && ']' == s[1]) + { + s++; + goto succeed; + } + + if (',' != s[1] && !(0 != array && ']' == s[1])) + { + s++; + goto fail; /* incorrect syntax */ + } + + state = 0; + } + else if ('\\' == *s && '"' == s[1]) + s++; + break; + /* unquoted */ + case 2: + if (',' == *s || (']' == *s && 0 != array)) + { + s--; + state = 0; + } + else if (']' == *s && 0 == array) + goto succeed; + break; + } } - - *pout = '\0'; - } - - return out; -} - -/****************************************************************************** - * * - * Purpose: quotes function parameter * - * * - * Parameters: param - [IN/OUT] function parameter * - * forced - [IN] 1 - enclose parameter in " even if it does not * - * contain any special characters * - * 0 - do nothing if the parameter does not * - * contain any special characters * - * * - * Return value: SUCCEED - if parameter was successfully quoted or quoting * - * was not necessary * - * FAIL - if parameter needs to but cannot be quoted due to * - * backslash in the end * - * * - ******************************************************************************/ -int zbx_function_param_quote(char **param, int forced) -{ - size_t sz_src, sz_dst; - - if (0 == forced && '"' != **param && ' ' != **param && NULL == strchr(*param, ',') && - NULL == strchr(*param, ')')) - { - return SUCCEED; - } - - if (0 != (sz_src = strlen(*param)) && '\\' == (*param)[sz_src - 1]) +fail: + *exp = s; return FAIL; - - sz_dst = zbx_get_escape_string_len(*param, "\"") + 3; - - *param = (char *)zbx_realloc(*param, sz_dst); - - (*param)[--sz_dst] = '\0'; - (*param)[--sz_dst] = '"'; - - while (0 < sz_src) - { - (*param)[--sz_dst] = (*param)[--sz_src]; - if ('"' == (*param)[sz_src]) - (*param)[--sz_dst] = '\\'; +succeed: + s++; } - (*param)[--sz_dst] = '"'; + *exp = s; return SUCCEED; } /****************************************************************************** * * - * Purpose: return parameter by index (Nparam) from parameter list (params) * - * * - * Parameters: * - * params - [IN] parameter list * - * Nparam - [IN] requested parameter index (from 1) * - * * - * Return value: * - * NULL - requested parameter missing * - * otherwise - requested parameter * - * * - ******************************************************************************/ -char *zbx_function_get_param_dyn(const char *params, int Nparam) -{ - const char *ptr; - size_t sep_pos, params_len; - char *out = NULL; - int idx = 0; - - params_len = strlen(params) + 1; - - for (ptr = params; ++idx <= Nparam && ptr < params + params_len; ptr += sep_pos + 1) - { - size_t param_pos, param_len; - int quoted; - - zbx_function_param_parse(ptr, ¶m_pos, ¶m_len, &sep_pos); - - if (idx == Nparam) - out = zbx_function_param_unquote_dyn(ptr + param_pos, param_len, "ed); - } - - return out; -} - -/****************************************************************************** - * * - * Purpose: Returns function type based on its name * - * * - * Return value: Function type. * - * * - ******************************************************************************/ -zbx_function_type_t zbx_get_function_type(const char *func) -{ - if (0 == strncmp(func, "trend", 5)) - return ZBX_FUNCTION_TYPE_TRENDS; - - if (0 == strncmp(func, "baseline", 8)) - return ZBX_FUNCTION_TYPE_TRENDS; - - if (0 == strcmp(func, "nodata")) - return ZBX_FUNCTION_TYPE_TIMER; - - return ZBX_FUNCTION_TYPE_HISTORY; -} - -/****************************************************************************** - * * * Purpose: check if the string is double * * * * Parameters: str - string to check * @@ -922,19 +255,19 @@ int zbx_strmatch_condition(const char *value, const char *pattern, unsigned char switch (op) { - case CONDITION_OPERATOR_EQUAL: + case ZBX_CONDITION_OPERATOR_EQUAL: if (0 == strcmp(value, pattern)) ret = SUCCEED; break; - case CONDITION_OPERATOR_NOT_EQUAL: + case ZBX_CONDITION_OPERATOR_NOT_EQUAL: if (0 != strcmp(value, pattern)) ret = SUCCEED; break; - case CONDITION_OPERATOR_LIKE: + case ZBX_CONDITION_OPERATOR_LIKE: if (NULL != strstr(value, pattern)) ret = SUCCEED; break; - case CONDITION_OPERATOR_NOT_LIKE: + case ZBX_CONDITION_OPERATOR_NOT_LIKE: if (NULL == strstr(value, pattern)) ret = SUCCEED; break; diff --git a/src/libs/zbxexpr/function.c b/src/libs/zbxexpr/function.c new file mode 100644 index 00000000000..3fb34d2907f --- /dev/null +++ b/src/libs/zbxexpr/function.c @@ -0,0 +1,555 @@ +/* +** Zabbix +** Copyright (C) 2001-2022 Zabbix SIA +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +**/ + +#include "zbxexpr.h" + +#include "zbxnum.h" +#include "zbxstr.h" + +/****************************************************************************** + * * + * Return value: SUCCEED - the char is allowed in the trigger function * + * FAIL - otherwise * + * * + * Comments: in trigger function allowed characters: 'a-z' * + * !!! Don't forget to sync the code with PHP !!! * + * * + ******************************************************************************/ +int zbx_is_function_char(unsigned char c) +{ + if (0 != islower(c)) + return SUCCEED; + + return FAIL; +} + +/****************************************************************************** + * * + * Purpose: validate parameters and give position of terminator if found and * + * not quoted * + * * + * Parameters: expr - [IN] string to parse that contains parameters * + * * + * terminator - [IN] use ')' if parameters end with * + * parenthesis or '\0' if ends with NULL * + * terminator * + * par_r - [OUT] position of the terminator if found * + * lpp_offset - [OUT] offset of the last parsed parameter * + * lpp_len - [OUT] length of the last parsed parameter * + * * + * Return value: SUCCEED - closing parenthesis was found or other custom * + * terminator and not quoted and return info about a * + * last processed parameter. * + * FAIL - does not look like a valid function parameter * + * list and return info about a last processed * + * parameter. * + * * + ******************************************************************************/ +static int function_validate_parameters(const char *expr, char terminator, size_t *par_r, size_t *lpp_offset, + size_t *lpp_len) +{ +#define ZBX_FUNC_PARAM_NEXT 0 +#define ZBX_FUNC_PARAM_QUOTED 1 +#define ZBX_FUNC_PARAM_UNQUOTED 2 +#define ZBX_FUNC_PARAM_POSTQUOTED 3 + + const char *ptr; + int state = ZBX_FUNC_PARAM_NEXT; + + *lpp_offset = 0; + + for (ptr = expr; '\0' != *ptr; ptr++) + { + if (terminator == *ptr && ZBX_FUNC_PARAM_QUOTED != state) + { + *par_r = ptr - expr; + return SUCCEED; + } + + switch (state) + { + case ZBX_FUNC_PARAM_NEXT: + *lpp_offset = ptr - expr; + if ('"' == *ptr) + state = ZBX_FUNC_PARAM_QUOTED; + else if (' ' != *ptr && ',' != *ptr) + state = ZBX_FUNC_PARAM_UNQUOTED; + break; + case ZBX_FUNC_PARAM_QUOTED: + if ('"' == *ptr && '\\' != *(ptr - 1)) + state = ZBX_FUNC_PARAM_POSTQUOTED; + break; + case ZBX_FUNC_PARAM_UNQUOTED: + if (',' == *ptr) + state = ZBX_FUNC_PARAM_NEXT; + break; + case ZBX_FUNC_PARAM_POSTQUOTED: + if (',' == *ptr) + { + state = ZBX_FUNC_PARAM_NEXT; + } + else if (' ' != *ptr) + { + *lpp_len = ptr - (expr + *lpp_offset); + return FAIL; + } + break; + default: + THIS_SHOULD_NEVER_HAPPEN; + } + } + + *lpp_len = ptr - (expr + *lpp_offset); + + if (terminator == *ptr && ZBX_FUNC_PARAM_QUOTED != state) + { + *par_r = ptr - expr; + return SUCCEED; + } + + return FAIL; + +#undef ZBX_FUNC_PARAM_NEXT +#undef ZBX_FUNC_PARAM_QUOTED +#undef ZBX_FUNC_PARAM_UNQUOTED +#undef ZBX_FUNC_PARAM_POSTQUOTED +} + +/****************************************************************************** + * * + * Purpose: given the position of opening function parenthesis find the * + * position of a closing one * + * * + * Parameters: expr - [IN] string to parse * + * par_l - [IN] position of the opening parenthesis * + * par_r - [OUT] position of the closing parenthesis * + * lpp_offset - [OUT] offset of the last parsed parameter * + * lpp_len - [OUT] length of the last parsed parameter * + * * + * Return value: SUCCEED - closing parenthesis was found * + * FAIL - string after par_l does not look like a valid * + * function parameter list * + * * + ******************************************************************************/ +static int function_match_parenthesis(const char *expr, size_t par_l, size_t *par_r, size_t *lpp_offset, + size_t *lpp_len) +{ + if (SUCCEED == function_validate_parameters(expr + par_l + 1, ')', par_r, lpp_offset, lpp_len)) + { + *par_r += par_l + 1; + return SUCCEED; + } + + *lpp_offset += par_l + 1; + return FAIL; +} + +/****************************************************************************** + * * + * Purpose: parses function name * + * * + * Parameters: expr - [IN] the function expression: func(p1, p2,...) * + * length - [OUT] the function name length or the amount of * + * characters that can be safely skipped * + * * + * Return value: SUCCEED - the function name was successfully parsed * + * FAIL - failed to parse function name * + * * + ******************************************************************************/ +static int function_parse_name(const char *expr, size_t *length) +{ + const char *ptr; + + for (ptr = expr; SUCCEED == zbx_is_function_char(*ptr); ptr++) + ; + + *length = ptr - expr; + + return ptr != expr && '(' == *ptr ? SUCCEED : FAIL; +} + +/****************************************************************************** + * * + * Purpose: check whether expression starts with a valid function * + * * + * Parameters: expr - [IN] string to parse * + * par_l - [OUT] position of the opening parenthesis * + * or the amount of characters to skip * + * par_r - [OUT] position of the closing parenthesis * + * error - [OUT] error message * + * max_error_len - [IN] error size * + * * + * Return value: SUCCEED - string starts with a valid function * + * FAIL - string does not start with a function and par_l * + * characters can be safely skipped * + * * + ******************************************************************************/ +int zbx_function_validate(const char *expr, size_t *par_l, size_t *par_r, char *error, int max_error_len) +{ + size_t lpp_offset, lpp_len; + + /* try to validate function name */ + if (SUCCEED == function_parse_name(expr, par_l)) + { + /* now we know the position of '(', try to find ')' */ + if (SUCCEED == function_match_parenthesis(expr, *par_l, par_r, &lpp_offset, &lpp_len)) + return SUCCEED; + + if (NULL != error && *par_l > *par_r) + { + zbx_snprintf(error, max_error_len, "Incorrect function '%.*s' expression. " + "Check expression part starting from: %.*s", + (int)*par_l, expr, (int)lpp_len, expr + lpp_offset); + + return FAIL; + } + } + + if (NULL != error) + zbx_snprintf(error, max_error_len, "Incorrect function expression: %s", expr); + + return FAIL; +} + +/****************************************************************************** + * * + * Purpose: validate parameters that end with '\0' * + * * + * Parameters: expr - [IN] string to parse that contains parameters * + * length - [OUT] length of parameters * + * * + * Return value: SUCCEED - null termination encountered when quotes are * + * closed and no other error * + * FAIL - does not look like a valid * + * function parameter list * + * * + ******************************************************************************/ +int zbx_function_validate_parameters(const char *expr, size_t *length) +{ + size_t offset, len; + + return function_validate_parameters(expr, '\0', length, &offset, &len); +} + +/****************************************************************************** + * * + * Purpose: count calculated item (prototype) formula characters that can be * + * skipped without the risk of missing a function * + * * + ******************************************************************************/ +static size_t zbx_no_function(const char *expr) +{ + const char *ptr = expr; + int inside_quote = 0, len, c_l, c_r; + zbx_token_t token; + + while ('\0' != *ptr) + { + switch (*ptr) + { + case '\\': + if (0 != inside_quote) + ptr++; + break; + case '"': + inside_quote = !inside_quote; + ptr++; + continue; + } + + if (inside_quote) + { + if ('\0' == *ptr) + break; + ptr++; + continue; + } + + if ('{' == *ptr && '$' == *(ptr + 1) && SUCCEED == zbx_user_macro_parse(ptr, &len, &c_l, &c_r, NULL)) + { + ptr += len + 1; /* skip to the position after user macro */ + } + else if ('{' == *ptr && '{' == *(ptr + 1) && '#' == *(ptr + 2) && + SUCCEED == zbx_token_parse_nested_macro(ptr, ptr, 0, &token)) + { + ptr += token.loc.r - token.loc.l + 1; + } + else if (SUCCEED != zbx_is_function_char(*ptr)) + { + ptr++; /* skip one character which cannot belong to function name */ + } + else if ((0 == strncmp("and", ptr, len = ZBX_CONST_STRLEN("and")) || + 0 == strncmp("not", ptr, len = ZBX_CONST_STRLEN("not")) || + 0 == strncmp("or", ptr, len = ZBX_CONST_STRLEN("or"))) && + NULL != strchr("()" ZBX_WHITESPACE, ptr[len])) + { + ptr += len; /* skip to the position after and/or/not operator */ + } + else if (ptr > expr && 0 != isdigit(*(ptr - 1)) && NULL != strchr(ZBX_UNIT_SYMBOLS, *ptr)) + { + ptr++; /* skip unit suffix symbol if it's preceded by a digit */ + } + else + break; + } + + return ptr - expr; +} + + +/****************************************************************************** + * * + * Purpose: find the location of the next function and its parameters in * + * calculated item (prototype) formula * + * * + * Parameters: expr - [IN] string to parse * + * func_pos - [OUT] function position in the string * + * par_l - [OUT] position of the opening parenthesis * + * par_r - [OUT] position of the closing parenthesis * + * error - [OUT] error message * + * max_error_len - [IN] error size * + * * + * Return value: SUCCEED - function was found at func_pos * + * FAIL - there are no functions in the expression * + * * + ******************************************************************************/ +int zbx_function_find(const char *expr, size_t *func_pos, size_t *par_l, size_t *par_r, char *error, + int max_error_len) +{ + const char *ptr; + + for (ptr = expr; '\0' != *ptr; ptr += *par_l) + { + /* skip the part of expression that is definitely not a function */ + ptr += zbx_no_function(ptr); + *par_r = 0; + + /* try to validate function candidate */ + if (SUCCEED != zbx_function_validate(ptr, par_l, par_r, error, max_error_len)) + { + if (*par_l > *par_r) + return FAIL; + + continue; + } + + *func_pos = ptr - expr; + *par_l += *func_pos; + *par_r += *func_pos; + return SUCCEED; + } + + zbx_snprintf(error, max_error_len, "Incorrect function expression: %s", expr); + + return FAIL; +} + +/****************************************************************************** + * * + * Purpose: parses function parameter * + * * + * Parameters: expr - [IN] pre-validated function parameter list * + * param_pos - [OUT] the parameter position, excluding leading * + * whitespace * + * length - [OUT] the parameter length including trailing * + * whitespace for unquoted parameter * + * sep_pos - [OUT] the parameter separator character * + * (',' or '\0' or ')') position * + * * + ******************************************************************************/ +void zbx_function_param_parse(const char *expr, size_t *param_pos, size_t *length, size_t *sep_pos) +{ + const char *ptr = expr; + + /* skip the leading whitespace */ + while (' ' == *ptr) + ptr++; + + *param_pos = ptr - expr; + + if ('"' == *ptr) /* quoted parameter */ + { + for (ptr++; '"' != *ptr || '\\' == *(ptr - 1); ptr++) + ; + + *length = ++ptr - expr - *param_pos; + + /* skip trailing whitespace to find the next parameter */ + while (' ' == *ptr) + ptr++; + } + else /* unquoted parameter */ + { + for (ptr = expr; '\0' != *ptr && ')' != *ptr && ',' != *ptr; ptr++) + ; + + *length = ptr - expr - *param_pos; + } + + *sep_pos = ptr - expr; +} + +/****************************************************************************** + * * + * Purpose: unquotes function parameter * + * * + * Parameters: param - [IN] the parameter to unquote * + * len - [IN] the parameter length * + * quoted - [OUT] the flag that specifies whether parameter was * + * quoted before extraction * + * * + * Return value: The unquoted parameter. This value must be freed by the * + * caller. * + * * + ******************************************************************************/ +char *zbx_function_param_unquote_dyn(const char *param, size_t len, int *quoted) +{ + char *out; + + out = (char *)zbx_malloc(NULL, len + 1); + + if (0 == (*quoted = (0 != len && '"' == *param))) + { + /* unquoted parameter - simply copy it */ + memcpy(out, param, len); + out[len] = '\0'; + } + else + { + /* quoted parameter - remove enclosing " and replace \" with " */ + const char *pin; + char *pout = out; + + for (pin = param + 1; (size_t)(pin - param) < len - 1; pin++) + { + if ('\\' == pin[0] && '"' == pin[1]) + pin++; + + *pout++ = *pin; + } + + *pout = '\0'; + } + + return out; +} + +/****************************************************************************** + * * + * Purpose: quotes function parameter * + * * + * Parameters: param - [IN/OUT] function parameter * + * forced - [IN] 1 - enclose parameter in " even if it does not * + * contain any special characters * + * 0 - do nothing if the parameter does not * + * contain any special characters * + * * + * Return value: SUCCEED - if parameter was successfully quoted or quoting * + * was not necessary * + * FAIL - if parameter needs to but cannot be quoted due to * + * backslash in the end * + * * + ******************************************************************************/ +int zbx_function_param_quote(char **param, int forced) +{ + size_t sz_src, sz_dst; + + if (0 == forced && '"' != **param && ' ' != **param && NULL == strchr(*param, ',') && + NULL == strchr(*param, ')')) + { + return SUCCEED; + } + + if (0 != (sz_src = strlen(*param)) && '\\' == (*param)[sz_src - 1]) + return FAIL; + + sz_dst = zbx_get_escape_string_len(*param, "\"") + 3; + + *param = (char *)zbx_realloc(*param, sz_dst); + + (*param)[--sz_dst] = '\0'; + (*param)[--sz_dst] = '"'; + + while (0 < sz_src) + { + (*param)[--sz_dst] = (*param)[--sz_src]; + if ('"' == (*param)[sz_src]) + (*param)[--sz_dst] = '\\'; + } + (*param)[--sz_dst] = '"'; + + return SUCCEED; +} + +/****************************************************************************** + * * + * Purpose: return parameter by index (Nparam) from parameter list (params) * + * * + * Parameters: * + * params - [IN] parameter list * + * Nparam - [IN] requested parameter index (from 1) * + * * + * Return value: * + * NULL - requested parameter missing * + * otherwise - requested parameter * + * * + ******************************************************************************/ +char *zbx_function_get_param_dyn(const char *params, int Nparam) +{ + const char *ptr; + size_t sep_pos, params_len; + char *out = NULL; + int idx = 0; + + params_len = strlen(params) + 1; + + for (ptr = params; ++idx <= Nparam && ptr < params + params_len; ptr += sep_pos + 1) + { + size_t param_pos, param_len; + int quoted; + + zbx_function_param_parse(ptr, ¶m_pos, ¶m_len, &sep_pos); + + if (idx == Nparam) + out = zbx_function_param_unquote_dyn(ptr + param_pos, param_len, "ed); + } + + return out; +} + +/****************************************************************************** + * * + * Purpose: Returns function type based on its name * + * * + * Return value: Function type. * + * * + ******************************************************************************/ +zbx_function_type_t zbx_get_function_type(const char *func) +{ + if (0 == strncmp(func, "trend", 5)) + return ZBX_FUNCTION_TYPE_TRENDS; + + if (0 == strncmp(func, "baseline", 8)) + return ZBX_FUNCTION_TYPE_TRENDS; + + if (0 == strcmp(func, "nodata")) + return ZBX_FUNCTION_TYPE_TIMER; + + return ZBX_FUNCTION_TYPE_HISTORY; +} diff --git a/src/libs/zbxexpr/host.c b/src/libs/zbxexpr/host.c new file mode 100644 index 00000000000..1bd3ed993c3 --- /dev/null +++ b/src/libs/zbxexpr/host.c @@ -0,0 +1,150 @@ +/* +** Zabbix +** Copyright (C) 2001-2022 Zabbix SIA +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +**/ + +#include "zbxexpr.h" + +/****************************************************************************** + * * + * Return value: SUCCEED - the char is allowed in the host name * + * FAIL - otherwise * + * * + * Comments: in host name allowed characters: '0-9a-zA-Z. _-' * + * !!! Don't forget to sync the code with PHP !!! * + * * + ******************************************************************************/ +int zbx_is_hostname_char(unsigned char c) +{ + if (0 != isalnum(c)) + return SUCCEED; + + if (c == '.' || c == ' ' || c == '_' || c == '-') + return SUCCEED; + + return FAIL; +} + +/****************************************************************************** + * * + * Purpose: return hostname and key * + * <hostname:>key * + * * + * Parameters: * + * exp - pointer to the first char of hostname * + * host:key[key params] * + * ^ * + * * + * Return value: return SUCCEED or FAIL * + * * + ******************************************************************************/ +int zbx_parse_host_key(char *exp, char **host, char **key) +{ + char *p, *s; + + if (NULL == exp || '\0' == *exp) + return FAIL; + + for (p = exp, s = exp; '\0' != *p; p++) /* check for optional hostname */ + { + if (':' == *p) /* hostname:vfs.fs.size[/,total] + * --------^ + */ + { + *p = '\0'; + *host = zbx_strdup(NULL, s); + *p++ = ':'; + + s = p; + break; + } + + if (SUCCEED != zbx_is_hostname_char(*p)) + break; + } + + *key = zbx_strdup(NULL, s); + + return SUCCEED; +} + +/****************************************************************************** + * * + * Purpose: replace all not-allowed hostname characters in the string * + * * + * Parameters: host - the target C-style string * + * * + * Comments: the string must be null-terminated, otherwise not secure! * + * * + ******************************************************************************/ +void zbx_make_hostname(char *host) +{ + char *c; + + assert(host); + + for (c = host; '\0' != *c; ++c) + { + if (FAIL == zbx_is_hostname_char(*c)) + *c = '_'; + } +} + +/****************************************************************************** + * * + * Purpose: check a byte stream for a valid hostname * + * * + * Parameters: hostname - pointer to the first char of hostname * + * error - pointer to the error message (can be NULL) * + * * + * Return value: return SUCCEED if hostname is valid * + * or FAIL if hostname contains invalid chars, is empty * + * or is longer than ZBX_MAX_HOSTNAME_LEN * + * * + ******************************************************************************/ +int zbx_check_hostname(const char *hostname, char **error) +{ + int len = 0; + + while ('\0' != hostname[len]) + { + if (FAIL == zbx_is_hostname_char(hostname[len])) + { + if (NULL != error) + *error = zbx_dsprintf(NULL, "name contains invalid character '%c'", hostname[len]); + return FAIL; + } + + len++; + } + + if (0 == len) + { + if (NULL != error) + *error = zbx_strdup(NULL, "name is empty"); + return FAIL; + } + + if (ZBX_MAX_HOSTNAME_LEN < len) + { + if (NULL != error) + *error = zbx_dsprintf(NULL, "name is too long (max %d characters)", ZBX_MAX_HOSTNAME_LEN); + return FAIL; + } + + return SUCCEED; +} diff --git a/src/libs/zbxexpr/macro.c b/src/libs/zbxexpr/macro.c new file mode 100644 index 00000000000..3440fbcbaa8 --- /dev/null +++ b/src/libs/zbxexpr/macro.c @@ -0,0 +1,360 @@ +/* +** Zabbix +** Copyright (C) 2001-2022 Zabbix SIA +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +**/ + +#include "zbxexpr.h" + +/****************************************************************************** + * * + * Return value: SUCCEED - the char is allowed in the macro name * + * FAIL - otherwise * + * * + * Comments: allowed characters in macro names: '0-9A-Z._' * + * !!! Don't forget to sync the code with PHP !!! * + * * + ******************************************************************************/ +int zbx_is_macro_char(unsigned char c) +{ + if (0 != isupper(c)) + return SUCCEED; + + if ('.' == c || '_' == c) + return SUCCEED; + + if (0 != isdigit(c)) + return SUCCEED; + + return FAIL; +} + +/****************************************************************************** + * * + * Purpose: checks if the name is a valid discovery macro * + * * + * Return value: SUCCEED - the name is a valid discovery macro * + * FAIL - otherwise * + * * + ******************************************************************************/ +int zbx_is_discovery_macro(const char *name) +{ + if ('{' != *name++ || '#' != *name++) + return FAIL; + + do + { + if (SUCCEED != zbx_is_macro_char(*name++)) + return FAIL; + + } while ('}' != *name); + + if ('\0' != name[1]) + return FAIL; + + return SUCCEED; +} + +#define ZBX_MACRO_REGEX_PREFIX "regex:" + +/****************************************************************************** + * * + * Purpose: * + * parses user macro and finds its end position and context location * + * * + * Parameters: * + * macro - [IN] the macro to parse * + * macro_r - [OUT] the position of ending '}' character * + * context_l - [OUT] the position of context start character (first non * + * space character after context separator ':') * + * 0 if macro does not have context specified. * + * context_r - [OUT] the position of context end character (either the * + * ending '"' for quoted context values or the last * + * character before the ending '}' character) * + * 0 if macro does not have context specified. * + * context_op - [OUT] the context matching operator (optional): * + * ZBX_CONDITION_OPERATOR_EQUAL * + * ZBX_CONDITION_OPERATOR_REGEXP * + * * + * Return value: * + * SUCCEED - the macro was parsed successfully. * + * FAIL - the macro parsing failed, the content of output variables * + * is not defined. * + * * + ******************************************************************************/ +int zbx_user_macro_parse(const char *macro, int *macro_r, int *context_l, int *context_r, unsigned char *context_op) +{ + int i; + + /* find the end of macro name by skipping {$ characters and iterating through */ + /* valid macro name characters */ + for (i = 2; SUCCEED == zbx_is_macro_char(macro[i]); i++) + ; + + /* check for empty macro name */ + if (2 == i) + return FAIL; + + if ('}' == macro[i]) + { + /* no macro context specified, parsing done */ + *macro_r = i; + *context_l = 0; + *context_r = 0; + + if (NULL != context_op) + *context_op = ZBX_CONDITION_OPERATOR_EQUAL; + + return SUCCEED; + } + + /* fail if the next character is not a macro context separator */ + if (':' != macro[i]) + return FAIL; + + i++; + if (NULL != context_op) + { + if (0 == strncmp(macro + i, ZBX_MACRO_REGEX_PREFIX, ZBX_CONST_STRLEN(ZBX_MACRO_REGEX_PREFIX))) + { + *context_op = ZBX_CONDITION_OPERATOR_REGEXP; + i += ZBX_CONST_STRLEN(ZBX_MACRO_REGEX_PREFIX); + } + else + *context_op = ZBX_CONDITION_OPERATOR_EQUAL; + } + + /* skip the whitespace after macro context separator */ + while (' ' == macro[i]) + i++; + + *context_l = i; + + if ('"' == macro[i]) + { + i++; + + /* process quoted context */ + for (; '"' != macro[i]; i++) + { + if ('\0' == macro[i]) + return FAIL; + + if ('\\' == macro[i] && '"' == macro[i + 1]) + i++; + } + + *context_r = i; + + while (' ' == macro[++i]) + ; + } + else + { + /* process unquoted context */ + for (; '}' != macro[i]; i++) + { + if ('\0' == macro[i]) + return FAIL; + } + + *context_r = i - 1; + } + + if ('}' != macro[i]) + return FAIL; + + *macro_r = i; + + return SUCCEED; +} + +/****************************************************************************** + * * + * Purpose: * + * parses user macro {$MACRO:<context>} into {$MACRO} and <context> * + * strings * + * * + * Parameters: * + * macro - [IN] the macro to parse * + * name - [OUT] the macro name without context * + * context - [OUT] the unquoted macro context, NULL for macros without * + * context * + * length - [OUT] the length of parsed macro (optional) * + * context_op - [OUT] the context matching operator (optional): * + * ZBX_CONDITION_OPERATOR_EQUAL * + * ZBX_CONDITION_OPERATOR_REGEXP * + * * + * Return value: * + * SUCCEED - the macro was parsed successfully * + * FAIL - the macro parsing failed, invalid parameter syntax * + * * + ******************************************************************************/ +int zbx_user_macro_parse_dyn(const char *macro, char **name, char **context, int *length, unsigned char *context_op) +{ + const char *ptr; + int macro_r, context_l, context_r; + size_t len; + + if (SUCCEED != zbx_user_macro_parse(macro, ¯o_r, &context_l, &context_r, context_op)) + return FAIL; + + zbx_free(*context); + + if (0 != context_l) + { + ptr = macro + context_l; + + /* find the context separator ':' by stripping spaces before context */ + while (' ' == *(--ptr)) + ; + + /* remove regex: prefix from macro name for regex contexts */ + if (NULL != context_op && ZBX_CONDITION_OPERATOR_REGEXP == *context_op) + ptr -= ZBX_CONST_STRLEN(ZBX_MACRO_REGEX_PREFIX); + + /* extract the macro name and close with '}' character */ + len = ptr - macro + 1; + *name = (char *)zbx_realloc(*name, len + 1); + memcpy(*name, macro, len - 1); + (*name)[len - 1] = '}'; + (*name)[len] = '\0'; + + *context = zbx_user_macro_unquote_context_dyn(macro + context_l, context_r - context_l + 1); + } + else + { + *name = (char *)zbx_realloc(*name, macro_r + 2); + zbx_strlcpy(*name, macro, macro_r + 2); + } + + if (NULL != length) + *length = macro_r + 1; + + return SUCCEED; +} + +#undef ZBX_MACRO_REGEX_PREFIX + +/****************************************************************************** + * * + * Purpose: * + * extracts the macro context unquoting if necessary * + * * + * Parameters: * + * context - [IN] the macro context inside a user macro * + * len - [IN] the macro context length (including quotes for quoted * + * contexts) * + * * + * Return value: * + * A string containing extracted macro context. This string must be freed * + * by the caller. * + * * + ******************************************************************************/ +char *zbx_user_macro_unquote_context_dyn(const char *context, int len) +{ + int quoted = 0; + char *buffer, *ptr; + + ptr = buffer = (char *)zbx_malloc(NULL, len + 1); + + if ('"' == *context) + { + quoted = 1; + context++; + len--; + } + + while (0 < len) + { + if (1 == quoted && '\\' == *context && '"' == context[1]) + { + context++; + len--; + } + + *ptr++ = *context++; + len--; + } + + if (1 == quoted) + ptr--; + + *ptr = '\0'; + + return buffer; +} + +/****************************************************************************** + * * + * Purpose: * + * quotes user macro context if necessary * + * * + * Parameters: * + * context - [IN] the macro context * + * force_quote - [IN] if non zero then context quoting is enforced * + * error - [OUT] the error message * + * * + * Return value: * + * A string containing quoted macro context on success, NULL on error. * + * * + ******************************************************************************/ +char *zbx_user_macro_quote_context_dyn(const char *context, int force_quote, char **error) +{ + int len, quotes = 0; + char *buffer, *ptr_buffer; + const char *ptr_context = context, *start = context; + + if ('"' == *ptr_context || ' ' == *ptr_context) + force_quote = 1; + + for (; '\0' != *ptr_context; ptr_context++) + { + if ('}' == *ptr_context) + force_quote = 1; + + if ('"' == *ptr_context) + quotes++; + } + + if (0 == force_quote) + return zbx_strdup(NULL, context); + + len = (int)strlen(context) + 2 + quotes; + ptr_buffer = buffer = (char *)zbx_malloc(NULL, len + 1); + + *ptr_buffer++ = '"'; + + while ('\0' != *context) + { + if ('"' == *context) + *ptr_buffer++ = '\\'; + + *ptr_buffer++ = *context++; + } + + if ('\\' == *(ptr_buffer - 1)) + { + *error = zbx_dsprintf(*error, "quoted context \"%s\" cannot end with '\\' character", start); + zbx_free(buffer); + return NULL; + } + + *ptr_buffer++ = '"'; + *ptr_buffer++ = '\0'; + + return buffer; +} diff --git a/src/libs/zbxexpr/token.c b/src/libs/zbxexpr/token.c index 2480c22a766..9bf129d7376 100644 --- a/src/libs/zbxexpr/token.c +++ b/src/libs/zbxexpr/token.c @@ -106,7 +106,7 @@ static int token_parse_lld_macro(const char *expression, const char *macro, zbx_ if ('\0' == *ptr) return FAIL; - if (SUCCEED != is_macro_char(*ptr)) + if (SUCCEED != zbx_is_macro_char(*ptr)) return FAIL; } @@ -554,7 +554,7 @@ static int token_parse_simple_macro_key(const char *expression, const char *macr const char *ptr = key; zbx_strloc_t key_loc, func_loc, func_param; - if (SUCCEED != parse_key(&ptr)) + if (SUCCEED != zbx_parse_key(&ptr)) { zbx_token_t key_token; @@ -564,7 +564,7 @@ static int token_parse_simple_macro_key(const char *expression, const char *macr ptr = expression + key_token.loc.r + 1; } - /* If the key is without parameters, then parse_key() will move cursor past function name - */ + /* If the key is without parameters, then zbx_parse_key() will move cursor past function name - */ /* at the start of its parameters. In this case move cursor back before function. */ if ('(' == *ptr) { @@ -643,7 +643,7 @@ static int token_parse_simple_macro(const char *expression, const char *macro, z if ('\0' == *ptr) return FAIL; - if (SUCCEED != is_hostname_char(*ptr)) + if (SUCCEED != zbx_is_hostname_char(*ptr)) return FAIL; } @@ -865,7 +865,7 @@ int zbx_token_parse_nested_macro(const char *expression, const char *macro, int if ('\0' == *ptr) return FAIL; - if (SUCCEED != is_macro_char(*ptr)) + if (SUCCEED != zbx_is_macro_char(*ptr)) return FAIL; } diff --git a/src/libs/zbxlog/log.c b/src/libs/zbxlog/log.c index acb3357380c..41f166b0998 100644 --- a/src/libs/zbxlog/log.c +++ b/src/libs/zbxlog/log.c @@ -265,7 +265,7 @@ static void unlock_log(void) static void lock_log(void) { #ifdef ZABBIX_AGENT - if (0 == (ZBX_MUTEX_LOGGING_DENIED & get_thread_global_mutex_flag())) + if (0 == (ZBX_MUTEX_LOGGING_DENIED & zbx_get_thread_global_mutex_flag())) #endif LOCK_LOG; } @@ -273,7 +273,7 @@ static void lock_log(void) static void unlock_log(void) { #ifdef ZABBIX_AGENT - if (0 == (ZBX_MUTEX_LOGGING_DENIED & get_thread_global_mutex_flag())) + if (0 == (ZBX_MUTEX_LOGGING_DENIED & zbx_get_thread_global_mutex_flag())) #endif UNLOCK_LOG; } diff --git a/src/libs/zbxmedia/email.c b/src/libs/zbxmedia/email.c index 7bcc3835ca3..9f7512f704b 100644 --- a/src/libs/zbxmedia/email.c +++ b/src/libs/zbxmedia/email.c @@ -37,6 +37,8 @@ /* separator for multipart mixed messages */ #define ZBX_MULTIPART_MIXED_BOUNDARY "MULTIPART-MIXED-BOUNDARY" +#define OK_250 "250" + extern char *CONFIG_SSL_CA_LOCATION; /****************************************************************************** @@ -433,19 +435,107 @@ out: } #endif +static char *smtp_get_helo_from_system(void) +{ + struct utsname name; + + if (-1 == uname(&name)) + return NULL; + + return zbx_strdup(NULL, name.nodename); +} + +static char *smtp_get_helo_from_addr(const char *addr) +{ + const char *domain; + char *helo_addr; + size_t addr_len; + + if (NULL == addr || '\0' == *addr || NULL == (domain = strrchr(addr, '@'))) + return NULL; + + addr_len = strlen(domain + 1); + + if (1 == addr_len && '>' == *(domain + 1)) + return NULL; + + helo_addr = zbx_strdup(NULL, domain + 1); + helo_addr[addr_len - 1] = '\0'; + + return helo_addr; +} + +static int send_smtp_helo_plain(const char *addr, const char *helo, zbx_socket_t *s, char **error, + size_t max_error_len) +{ + char cmd[MAX_STRING_LEN], *helo_parsed = NULL; + const char *response; + int ret = SUCCEED; + + if ('\0' != *helo) + { + zbx_snprintf(cmd, sizeof(cmd), "HELO %s\r\n", helo); + } + else + { + if (NULL == (helo_parsed = smtp_get_helo_from_addr(addr))) + { + zabbix_log(LOG_LEVEL_DEBUG, "%s() HELO is not specified and failed to parse HELO from email " + "address, trying to form HELO command using system's hostname", __func__); + + if (NULL == (helo_parsed = smtp_get_helo_from_system())) + { + zbx_snprintf(*error, max_error_len, "failed to retrieve domain name for HELO command"); + ret = FAIL; + goto out; + } + } + + zbx_snprintf(cmd, sizeof(cmd), "HELO %s\r\n", helo_parsed); + } + + if (-1 == write(s->socket, cmd, strlen(cmd))) + { + zbx_snprintf(*error, max_error_len, "error sending HELO to mailserver: %s", + zbx_strerror(errno)); + + ret = FAIL; + goto out; + } + + if (FAIL == smtp_readln(s, &response)) + { + zbx_snprintf(*error, max_error_len, "error receiving answer on HELO request: %s", + zbx_strerror(errno)); + + ret = FAIL; + goto out; + } + + if (0 != strncmp(response, OK_250, ZBX_CONST_STRLEN(OK_250))) + { + zbx_snprintf(*error, max_error_len, "wrong answer on HELO \"%s\"", response); + ret = FAIL; + goto out; + } +out: + zbx_free(helo_parsed); + + return ret; +} + static int send_email_plain(const char *smtp_server, unsigned short smtp_port, const char *smtp_helo, zbx_vector_ptr_t *from_mails, zbx_vector_ptr_t *to_mails, const char *inreplyto, const char *mailsubject, const char *mailbody, unsigned char content_type, int timeout, char *error, size_t max_error_len) { +#define OK_220 "220" +#define OK_251 "251" +#define OK_354 "354" zbx_socket_t s; int err, ret = FAIL, i; - char cmd[MAX_STRING_LEN], *cmdp = NULL; + char cmd[MAX_STRING_LEN], *cmdp = NULL, *helo_addr = NULL; - const char *OK_220 = "220"; - const char *OK_250 = "250"; - const char *OK_251 = "251"; - const char *OK_354 = "354"; const char *response; zbx_alarm_on(timeout); @@ -467,38 +557,18 @@ static int send_email_plain(const char *smtp_server, unsigned short smtp_port, c goto close; } - if (0 != strncmp(response, OK_220, strlen(OK_220))) + if (0 != strncmp(response, OK_220, ZBX_CONST_STRLEN(OK_220))) { zbx_snprintf(error, max_error_len, "no welcome message 220* from SMTP server \"%s\"", response); goto close; } /* send HELO */ + if (0 != from_mails->values_num) + helo_addr = ((zbx_mailaddr_t *)from_mails->values[0])->addr; - if ('\0' != *smtp_helo) - { - zbx_snprintf(cmd, sizeof(cmd), "HELO %s\r\n", smtp_helo); - - if (-1 == write(s.socket, cmd, strlen(cmd))) - { - zbx_snprintf(error, max_error_len, "error sending HELO to mailserver: %s", - zbx_strerror(errno)); - goto close; - } - - if (FAIL == smtp_readln(&s, &response)) - { - zbx_snprintf(error, max_error_len, "error receiving answer on HELO request: %s", - zbx_strerror(errno)); - goto close; - } - - if (0 != strncmp(response, OK_250, strlen(OK_250))) - { - zbx_snprintf(error, max_error_len, "wrong answer on HELO \"%s\"", response); - goto close; - } - } + if (FAIL == send_smtp_helo_plain(helo_addr, smtp_helo, &s, &error, max_error_len)) + goto close; /* send MAIL FROM */ @@ -518,7 +588,7 @@ static int send_email_plain(const char *smtp_server, unsigned short smtp_port, c goto close; } - if (0 != strncmp(response, OK_250, strlen(OK_250))) + if (0 != strncmp(response, OK_250, ZBX_CONST_STRLEN(OK_250))) { zbx_snprintf(error, max_error_len, "wrong answer on MAIL FROM \"%s\"", response); goto close; @@ -544,7 +614,8 @@ static int send_email_plain(const char *smtp_server, unsigned short smtp_port, c } /* May return 251 as well: User not local; will forward to <forward-path>. See RFC825. */ - if (0 != strncmp(response, OK_250, strlen(OK_250)) && 0 != strncmp(response, OK_251, strlen(OK_251))) + if (0 != strncmp(response, OK_250, ZBX_CONST_STRLEN(OK_250)) && + 0 != strncmp(response, OK_251, ZBX_CONST_STRLEN(OK_251))) { zbx_snprintf(error, max_error_len, "wrong answer on RCPT TO \"%s\"", response); goto close; @@ -567,7 +638,7 @@ static int send_email_plain(const char *smtp_server, unsigned short smtp_port, c goto close; } - if (0 != strncmp(response, OK_354, strlen(OK_354))) + if (0 != strncmp(response, OK_354, ZBX_CONST_STRLEN(OK_354))) { zbx_snprintf(error, max_error_len, "wrong answer on DATA \"%s\"", response); goto close; @@ -600,7 +671,7 @@ static int send_email_plain(const char *smtp_server, unsigned short smtp_port, c goto close; } - if (0 != strncmp(response, OK_250, strlen(OK_250))) + if (0 != strncmp(response, OK_250, ZBX_CONST_STRLEN(OK_250))) { zbx_snprintf(error, max_error_len, "wrong answer on end of data \"%s\"", response); goto close; @@ -623,6 +694,9 @@ out: zbx_alarm_off(); return ret; +#undef OK_220 +#undef OK_251 +#undef OK_354 } static int send_email_curl(const char *smtp_server, unsigned short smtp_port, const char *smtp_helo, @@ -657,7 +731,36 @@ static int send_email_curl(const char *smtp_server, unsigned short smtp_port, co url_offset += zbx_snprintf(url + url_offset, sizeof(url) - url_offset, "%s:%hu", smtp_server, smtp_port); if ('\0' != *smtp_helo) + { zbx_snprintf(url + url_offset, sizeof(url) - url_offset, "/%s", smtp_helo); + } + else + { + char *helo_domain = NULL; + + if (0 != from_mails->values_num) + { + if (NULL == (helo_domain = + smtp_get_helo_from_addr(((zbx_mailaddr_t *)from_mails->values[0])->addr))) + { + zabbix_log(LOG_LEVEL_DEBUG, "%s() HELO is not specified and failed to parse HELO " + "from email address, trying to form HELO command using system's " + "hostname", __func__); + } + } + + if (NULL == helo_domain) + { + if (NULL == (helo_domain = smtp_get_helo_from_system())) + { + zbx_strlcpy(error, "failed to retrieve domain name for HELO command", max_error_len); + goto clean; + } + } + + zbx_snprintf(url + url_offset, sizeof(url) - url_offset, "/%s", helo_domain); + zbx_free(helo_domain); + } if (CURLE_OK != (err = curl_easy_setopt(easyhandle, CURLOPT_URL, url))) goto error; diff --git a/src/libs/zbxmodules/modules.c b/src/libs/zbxmodules/modules.c index 34c7f26d2ba..237ec00a98c 100644 --- a/src/libs/zbxmodules/modules.c +++ b/src/libs/zbxmodules/modules.c @@ -64,7 +64,7 @@ static int zbx_register_module_items(ZBX_METRIC *metrics, char *error, size_t ma /* the flag means that the items comes from a loadable module */ metrics[i].flags |= CF_MODULE; - if (SUCCEED != add_metric(&metrics[i], error, max_error_len)) + if (SUCCEED != zbx_add_metric(&metrics[i], error, max_error_len)) return FAIL; } diff --git a/src/libs/zbxmutexs/mutexs.c b/src/libs/zbxmutexs/mutexs.c index c050ed56fe3..30048fa0914 100644 --- a/src/libs/zbxmutexs/mutexs.c +++ b/src/libs/zbxmutexs/mutexs.c @@ -412,7 +412,7 @@ void __zbx_mutex_lock(const char *filename, int line, zbx_mutex_t mutex) #ifdef _WINDOWS #ifdef ZABBIX_AGENT - if (0 != (ZBX_MUTEX_THREAD_DENIED & get_thread_global_mutex_flag())) + if (0 != (ZBX_MUTEX_THREAD_DENIED & zbx_get_thread_global_mutex_flag())) { zbx_error("[file:'%s',line:%d] lock failed: ZBX_MUTEX_THREAD_DENIED is set for thread with id = %d", filename, line, zbx_get_thread_id()); diff --git a/src/libs/zbxnum/num.c b/src/libs/zbxnum/num.c index 4dc2036bec6..9c06ffa138f 100644 --- a/src/libs/zbxnum/num.c +++ b/src/libs/zbxnum/num.c @@ -42,7 +42,7 @@ int zbx_is_uint_n_range(const char *str, size_t n, void *value, size_t size, zbx_uint64_t min, zbx_uint64_t max) { zbx_uint64_t value_uint64 = 0, c; - const zbx_uint64_t max_uint64 = ~(zbx_uint64_t)__UINT64_C(0); + const zbx_uint64_t max_uint64 = ~__UINT64_C(0); if ('\0' == *str || 0 == n || sizeof(zbx_uint64_t) < size || (0 == size && NULL != value)) return FAIL; @@ -100,7 +100,7 @@ int zbx_is_uint_n_range(const char *str, size_t n, void *value, size_t size, zbx int zbx_is_hex_n_range(const char *str, size_t n, void *value, size_t size, zbx_uint64_t min, zbx_uint64_t max) { zbx_uint64_t value_uint64 = 0, c; - const zbx_uint64_t max_uint64 = ~(zbx_uint64_t)__UINT64_C(0); + const zbx_uint64_t max_uint64 = ~__UINT64_C(0); int len = 0; if ('\0' == *str || 0 == n || sizeof(zbx_uint64_t) < size || (0 == size && NULL != value)) @@ -575,3 +575,41 @@ int zbx_is_hex_string(const char *str) return SUCCEED; } + +/****************************************************************************** + * * + * Purpose: validate and optionally convert a string to a number of type * + * 'int' * + * * + * Parameters: str - [IN] string to check * + * value - [OUT] output buffer where to write the converted value * + * (optional, can be NULL) * + * * + * Return value: SUCCEED - the string can be converted to 'int' and * + * was converted if 'value' is not NULL * + * FAIL - the string does not represent a valid 'int' or * + * its value is outside of valid range * + * * + ******************************************************************************/ +int zbx_is_int(const char *str, int *value) +{ + const char *ptr; + zbx_uint32_t value_ui32; + int sign; + + if ('-' == *(ptr = str)) + { + ptr++; + sign = -1; + } + else + sign = 1; + + if (SUCCEED != zbx_is_uint31(ptr, &value_ui32)) + return FAIL; + + if (NULL != value) + *value = ((int)value_ui32 * sign); + + return SUCCEED; +} diff --git a/src/libs/zbxparam/param.c b/src/libs/zbxparam/param.c index 3750713010e..662006cc873 100644 --- a/src/libs/zbxparam/param.c +++ b/src/libs/zbxparam/param.c @@ -512,7 +512,7 @@ int zbx_replace_key_params_dyn(char **data, int key_type, zbx_replace_key_param_ if (ZBX_KEY_TYPE_ITEM == key_type) { - for (; SUCCEED == is_key_char((*data)[i]) && '\0' != (*data)[i]; i++) + for (; SUCCEED == zbx_is_key_char((*data)[i]) && '\0' != (*data)[i]; i++) ; if (0 == i) diff --git a/src/libs/zbxrtc/rtc_client.c b/src/libs/zbxrtc/rtc_client.c index a43872563c9..3233d3b175e 100644 --- a/src/libs/zbxrtc/rtc_client.c +++ b/src/libs/zbxrtc/rtc_client.c @@ -303,12 +303,12 @@ int zbx_rtc_wait(zbx_ipc_async_socket_t *rtc, zbx_uint32_t *cmd, unsigned char * int ret; if (0 != timeout) - update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); ret = zbx_ipc_async_socket_recv(rtc, timeout, &message); if (0 != timeout) - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); if (FAIL == ret) return FAIL; diff --git a/src/libs/zbxself/selfmon.c b/src/libs/zbxself/selfmon.c index 06482bd3e1a..e3790981982 100644 --- a/src/libs/zbxself/selfmon.c +++ b/src/libs/zbxself/selfmon.c @@ -105,7 +105,6 @@ extern int CONFIG_TIMER_FORKS; extern int CONFIG_HOUSEKEEPER_FORKS; extern int CONFIG_DATASENDER_FORKS; extern int CONFIG_CONFSYNCER_FORKS; -extern int CONFIG_HEARTBEAT_FORKS; extern int CONFIG_SELFMON_FORKS; extern int CONFIG_VMWARE_FORKS; extern int CONFIG_COLLECTOR_FORKS; @@ -175,8 +174,6 @@ int get_process_type_forks(unsigned char proc_type) return CONFIG_DATASENDER_FORKS; case ZBX_PROCESS_TYPE_CONFSYNCER: return CONFIG_CONFSYNCER_FORKS; - case ZBX_PROCESS_TYPE_HEARTBEAT: - return CONFIG_HEARTBEAT_FORKS; case ZBX_PROCESS_TYPE_SELFMON: return CONFIG_SELFMON_FORKS; case ZBX_PROCESS_TYPE_VMWARE: @@ -225,7 +222,7 @@ int get_process_type_forks(unsigned char proc_type) * for self-monitoring collector * * * ******************************************************************************/ -int init_selfmon_collector(char **error) +int zbx_init_selfmon_collector(char **error) { size_t sz, sz_array, sz_process[ZBX_PROCESS_TYPE_COUNT], sz_total; char *p; @@ -293,7 +290,7 @@ out: * Purpose: Free memory allocated for self-monitoring collector * * * ******************************************************************************/ -void free_selfmon_collector(void) +void zbx_free_selfmon_collector(void) { zabbix_log(LOG_LEVEL_DEBUG, "In %s() collector:%p", __func__, (void *)collector); @@ -317,7 +314,7 @@ void free_selfmon_collector(void) * Parameters: state - [IN] new process state; ZBX_PROCESS_STATE_* * * * ******************************************************************************/ -void update_selfmon_counter(unsigned char state) +void zbx_update_selfmon_counter(unsigned char state) { zbx_stat_process_t *process; clock_t ticks; @@ -379,7 +376,7 @@ void update_selfmon_counter(unsigned char state) process->cache.ticks = ticks; } -void collect_selfmon_stats(void) +void zbx_collect_selfmon_stats(void) { zbx_stat_process_t *process; clock_t ticks, ticks_done; @@ -466,7 +463,7 @@ out: * requested statistics * * * ******************************************************************************/ -void get_selfmon_stats(unsigned char proc_type, unsigned char aggr_func, int proc_num, unsigned char state, +void zbx_get_selfmon_stats(unsigned char proc_type, unsigned char aggr_func, int proc_num, unsigned char state, double *value) { unsigned int total = 0, counter = 0; @@ -663,7 +660,7 @@ void zbx_sleep_loop(int sleeptime) sleep_remains = sleeptime; - update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); do { @@ -671,16 +668,6 @@ void zbx_sleep_loop(int sleeptime) } while (0 < --sleep_remains); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); -} - -void zbx_wakeup(void) -{ - sleep_remains = 0; -} - -int zbx_sleep_get_remainder(void) -{ - return sleep_remains; + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); } #endif diff --git a/src/libs/zbxserver/anomalystl.c b/src/libs/zbxserver/anomalystl.c index 48e5098773b..effaaa0f98a 100644 --- a/src/libs/zbxserver/anomalystl.c +++ b/src/libs/zbxserver/anomalystl.c @@ -316,7 +316,7 @@ static void apply_loess_smoothing(const zbx_vector_history_record_t *y, int n, i { int nsh; - nsh = (int)((length + 1) / 2); + nsh = (length + 1) / 2; nleft = 1; nright = length; @@ -345,7 +345,7 @@ static void apply_loess_smoothing(const zbx_vector_history_record_t *y, int n, i { int nsh; - nsh = (int)((length + 1) / 2); + nsh = (length + 1) / 2; for (i = 1; i < n + 1; i = i + newnj) { @@ -395,7 +395,7 @@ static void apply_loess_smoothing(const zbx_vector_history_record_t *y, int n, i ys->values[j].value.dbl = ys->values[i].value.dbl + (delta * (j - i)); } - k = (int)(((n - 1)/newnj) * newnj + 1); + k = ((n - 1)/newnj) * newnj + 1; if (k != n) { diff --git a/src/libs/zbxserver/calc_checks_eval.c b/src/libs/zbxserver/calc_checks_eval.c index ac2a824d4b4..d7c06b854a2 100644 --- a/src/libs/zbxserver/calc_checks_eval.c +++ b/src/libs/zbxserver/calc_checks_eval.c @@ -324,12 +324,12 @@ static int replace_key_param_wildcard_cb(const char *data, int key_type, int lev return SUCCEED; tmp = zbx_strdup(NULL, data); - unquote_key_param(tmp); + zbx_unquote_key_param(tmp); *param = zbx_dyn_escape_string(tmp, "\\%%"); zbx_free(tmp); /* escaping cannot result in unquotable parameter */ - if (FAIL == quote_key_param(param, quoted)) + if (FAIL == zbx_quote_key_param(param, quoted)) { THIS_SHOULD_NEVER_HAPPEN; zbx_free(*param); @@ -351,9 +351,9 @@ static int expression_match_item_key(const char *item_key, const AGENT_REQUEST * AGENT_REQUEST key; int i, ret = FAIL; - init_request(&key); + zbx_init_agent_request(&key); - if (SUCCEED != parse_item_key(item_key, &key)) + if (SUCCEED != zbx_parse_item_key(item_key, &key)) goto out; if (pattern->nparam != key.nparam) @@ -373,7 +373,7 @@ static int expression_match_item_key(const char *item_key, const AGENT_REQUEST * ret = SUCCEED; out: - free_request(&key); + zbx_free_agent_request(&key); return ret; } @@ -413,8 +413,8 @@ static void expression_get_item_candidates(zbx_expression_eval_t *eval, const zb if (0 != (query->flags & ZBX_ITEM_QUERY_KEY_SOME)) { - init_request(&pattern); - if (SUCCEED != parse_item_key(query->ref.key, &pattern)) + zbx_init_agent_request(&pattern); + if (SUCCEED != zbx_parse_item_key(query->ref.key, &pattern)) { THIS_SHOULD_NEVER_HAPPEN; zbx_free(sql); @@ -524,7 +524,7 @@ static void expression_get_item_candidates(zbx_expression_eval_t *eval, const zb DBfree_result(result); if (0 != (query->flags & ZBX_ITEM_QUERY_KEY_SOME)) - free_request(&pattern); + zbx_free_agent_request(&pattern); zbx_free(sql); } diff --git a/src/libs/zbxserver/evalfunc.c b/src/libs/zbxserver/evalfunc.c index e5a9177392d..cc2bf8048c7 100644 --- a/src/libs/zbxserver/evalfunc.c +++ b/src/libs/zbxserver/evalfunc.c @@ -2827,7 +2827,7 @@ static int evaluate_TREND(zbx_variant_t *value, const DC_ITEM *item, const char season_processed = (int)((double)season / 3600); ret = trends_eval_stl(table, item->itemid, start, end, start_detect_period, end_detect_period, - (int)season_processed, deviations, dev_alg, (int)s_window, &value_dbl, error); + season_processed, deviations, dev_alg, (int)s_window, &value_dbl, error); zbx_free(dev_alg); } diff --git a/src/libs/zbxserver/expression.c b/src/libs/zbxserver/expression.c index e3bbe0c79c9..9891873f2e6 100644 --- a/src/libs/zbxserver/expression.c +++ b/src/libs/zbxserver/expression.c @@ -6388,7 +6388,7 @@ static int replace_key_param_cb(const char *data, int key_type, int level, int n *param = zbx_strdup(NULL, data); if (0 != level) - unquote_key_param(*param); + zbx_unquote_key_param(*param); if (NULL == jp_row) substitute_simple_macros_impl(NULL, NULL, NULL, NULL, hostid, NULL, dc_item, NULL, NULL, NULL, NULL, @@ -6398,7 +6398,7 @@ static int replace_key_param_cb(const char *data, int key_type, int level, int n if (0 != level) { - if (FAIL == (ret = quote_key_param(param, quoted))) + if (FAIL == (ret = zbx_quote_key_param(param, quoted))) zbx_free(*param); } @@ -6530,7 +6530,7 @@ int zbx_substitute_function_lld_param(const char *e, size_t len, unsigned char k { char *key = NULL, *host = NULL; - if (SUCCEED != parse_host_key(param, &host, &key) || + if (SUCCEED != zbx_parse_host_key(param, &host, &key) || SUCCEED != substitute_key_macros_impl(&key, NULL, NULL, jp_row, lld_macro_paths, MACRO_TYPE_ITEM_KEY, NULL, 0)) { diff --git a/src/libs/zbxserver/zabbix_stats.c b/src/libs/zbxserver/zabbix_stats.c index 9411a8023dc..387366cded8 100644 --- a/src/libs/zbxserver/zabbix_stats.c +++ b/src/libs/zbxserver/zabbix_stats.c @@ -17,27 +17,28 @@ ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. **/ -#include "zbxserver.h" +#include "zbxstats.h" #include "zbxcommon.h" #include "dbcache.h" #include "zbxself.h" #include "../../zabbix_server/vmware/vmware.h" #include "preproc.h" +#include "zbxcomms.h" extern unsigned char program_type; extern int CONFIG_SERVER_STARTUP_TIME; -static zbx_get_zabbix_stats_ext_func_t stats_ex_cb; +static zbx_zabbix_stats_ext_get_func_t stats_ex_cb; /****************************************************************************** * * * Purpose: sets stats callback function * * * - * Parameters: cb - [IN] callback function * + * Parameters: cb - [IN] callback function * * * ******************************************************************************/ -void zbx_zabbix_stats_init(zbx_get_zabbix_stats_ext_func_t cb) +void zbx_zabbix_stats_init(zbx_zabbix_stats_ext_get_func_t cb) { stats_ex_cb = cb; } @@ -46,10 +47,11 @@ void zbx_zabbix_stats_init(zbx_get_zabbix_stats_ext_func_t cb) * * * Purpose: collects all metrics required for Zabbix stats request * * * - * Parameters: json - [OUT] the json data * + * Parameters: json - [OUT] the json data * + * zbx_config - [IN] Zabbix server/proxy config * * * ******************************************************************************/ -void zbx_get_zabbix_stats(struct zbx_json *json) +void zbx_zabbix_stats_get(struct zbx_json *json, const zbx_config_comms_args_t *zbx_config) { zbx_config_cache_info_t count_stats; zbx_vmware_stats_t vmware_stats; @@ -71,8 +73,8 @@ void zbx_get_zabbix_stats(struct zbx_json *json) /* zabbix[items] */ zbx_json_adduint64(json, "items", count_stats.items); - /* zabbix[item_unsupported] */ - zbx_json_adduint64(json, "item_unsupported", count_stats.items_unsupported); + /* zabbix[items_unsupported] */ + zbx_json_adduint64(json, "items_unsupported", count_stats.items_unsupported); /* zabbix[requiredperformance] */ zbx_json_addfloat(json, "requiredperformance", count_stats.requiredperformance); @@ -80,7 +82,7 @@ void zbx_get_zabbix_stats(struct zbx_json *json) /* zabbix[preprocessing_queue] */ zbx_json_adduint64(json, "preprocessing_queue", zbx_preprocessor_get_queue_size()); - stats_ex_cb(json); + stats_ex_cb(json, zbx_config); /* zabbix[rcache,<cache>,<mode>] */ zbx_json_addobject(json, "rcache"); diff --git a/src/libs/zbxshmem/memalloc.c b/src/libs/zbxshmem/memalloc.c index 67453bc1f07..89f5355eb79 100644 --- a/src/libs/zbxshmem/memalloc.c +++ b/src/libs/zbxshmem/memalloc.c @@ -548,8 +548,8 @@ int zbx_shmem_create(zbx_shmem_info_t **info, zbx_uint64_t size, const char *des if (!(SHMEM_MIN_SIZE <= size && size <= SHMEM_MAX_SIZE)) { - *error = zbx_dsprintf(*error, "requested size " ZBX_FS_SIZE_T " not within bounds [" ZBX_FS_UI64 - " <= size <= " ZBX_FS_UI64 "]", (zbx_fs_size_t)size, SHMEM_MIN_SIZE, SHMEM_MAX_SIZE); + *error = zbx_dsprintf(*error, "requested size " ZBX_FS_UI64 " not within bounds [" ZBX_FS_UI64 + " <= size <= " ZBX_FS_UI64 "]", size, SHMEM_MIN_SIZE, SHMEM_MAX_SIZE); goto out; } diff --git a/src/libs/zbxsysinfo/agent/agent.c b/src/libs/zbxsysinfo/agent/agent.c index 754da15cb3d..cc04634700a 100644 --- a/src/libs/zbxsysinfo/agent/agent.c +++ b/src/libs/zbxsysinfo/agent/agent.c @@ -74,8 +74,8 @@ static int AGENT_HOSTMETADATA(AGENT_REQUEST *request, AGENT_RESULT *result) } else if (NULL != CONFIG_HOST_METADATA_ITEM) { - if (SUCCEED != process(CONFIG_HOST_METADATA_ITEM, ZBX_PROCESS_LOCAL_COMMAND | ZBX_PROCESS_WITH_ALIAS, - result) || NULL == ZBX_GET_STR_RESULT(result)) + if (SUCCEED != zbx_execute_agent_check(CONFIG_HOST_METADATA_ITEM, ZBX_PROCESS_LOCAL_COMMAND | + ZBX_PROCESS_WITH_ALIAS, result) || NULL == ZBX_GET_STR_RESULT(result)) { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot get host metadata using item \"%s\"", CONFIG_HOST_METADATA_ITEM)); diff --git a/src/libs/zbxsysinfo/aix/cpu.c b/src/libs/zbxsysinfo/aix/cpu.c index e438a92e260..940313474de 100644 --- a/src/libs/zbxsysinfo/aix/cpu.c +++ b/src/libs/zbxsysinfo/aix/cpu.c @@ -214,6 +214,8 @@ int SYSTEM_CPU_SWITCHES(AGENT_REQUEST *request, AGENT_RESULT *result) #ifdef HAVE_LIBPERFSTAT perfstat_cpu_total_t ps_cpu_total; + ZBX_UNUSED(request); + if (-1 == perfstat_cpu_total(NULL, &ps_cpu_total, sizeof(ps_cpu_total), 1)) { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain system information: %s", zbx_strerror(errno))); @@ -224,6 +226,8 @@ int SYSTEM_CPU_SWITCHES(AGENT_REQUEST *request, AGENT_RESULT *result) return SYSINFO_RET_OK; #else + ZBX_UNUSED(request); + SET_MSG_RESULT(result, zbx_strdup(NULL, "Agent was compiled without support for Perfstat API.")); return SYSINFO_RET_FAIL; @@ -232,6 +236,7 @@ int SYSTEM_CPU_SWITCHES(AGENT_REQUEST *request, AGENT_RESULT *result) int SYSTEM_CPU_INTR(AGENT_REQUEST *request, AGENT_RESULT *result) { + ZBX_UNUSED(request); #ifdef HAVE_LIBPERFSTAT perfstat_cpu_total_t ps_cpu_total; diff --git a/src/libs/zbxsysinfo/aix/diskio.c b/src/libs/zbxsysinfo/aix/diskio.c index be41b53160d..387e1ecce51 100644 --- a/src/libs/zbxsysinfo/aix/diskio.c +++ b/src/libs/zbxsysinfo/aix/diskio.c @@ -31,8 +31,11 @@ typedef struct } zbx_perfstat_t; -int get_diskstat(const char *devname, zbx_uint64_t *dstat) +int zbx_get_diskstat(const char *devname, zbx_uint64_t *dstat) { + ZBX_UNUSED(devname); + ZBX_UNUSED(dstat); + return FAIL; } diff --git a/src/libs/zbxsysinfo/aix/diskspace.c b/src/libs/zbxsysinfo/aix/diskspace.c index 1dc8b98531a..64517ca45a1 100644 --- a/src/libs/zbxsysinfo/aix/diskspace.c +++ b/src/libs/zbxsysinfo/aix/diskspace.c @@ -240,6 +240,8 @@ int VFS_FS_DISCOVERY(AGENT_REQUEST *request, AGENT_RESULT *result) struct vmount *vms = NULL, *vm; struct zbx_json j; + ZBX_UNUSED(request); + /* check how many bytes to allocate for the mounted filesystems */ if (-1 == (rc = mntctl(MCTL_QUERY, sizeof(sz), (char *)&sz))) { @@ -302,6 +304,8 @@ static int vfs_fs_get(AGENT_REQUEST *request, AGENT_RESULT *result) zbx_mpoint_t *mntpoint; char *mpoint; + ZBX_UNUSED(request); + /* check how many bytes to allocate for the mounted filesystems */ if (-1 == (rc = mntctl(MCTL_QUERY, sizeof(sz), (char *)&sz))) { diff --git a/src/libs/zbxsysinfo/aix/hostname.c b/src/libs/zbxsysinfo/aix/hostname.c index 5913dd7b4a0..f17648f076e 100644 --- a/src/libs/zbxsysinfo/aix/hostname.c +++ b/src/libs/zbxsysinfo/aix/hostname.c @@ -18,6 +18,7 @@ **/ #include "zbxsysinfo.h" +#include "../sysinfo.h" #include "log.h" diff --git a/src/libs/zbxsysinfo/aix/inodes.c b/src/libs/zbxsysinfo/aix/inodes.c index c0de3f2e700..0b9ae8f4d73 100644 --- a/src/libs/zbxsysinfo/aix/inodes.c +++ b/src/libs/zbxsysinfo/aix/inodes.c @@ -18,7 +18,7 @@ **/ #include "zbxsysinfo.h" - +#include "../sysinfo.h" #include "inodes.h" #include "log.h" diff --git a/src/libs/zbxsysinfo/aix/net.c b/src/libs/zbxsysinfo/aix/net.c index 75d7a0f9041..e09a0c7ef24 100644 --- a/src/libs/zbxsysinfo/aix/net.c +++ b/src/libs/zbxsysinfo/aix/net.c @@ -210,6 +210,8 @@ int NET_IF_DISCOVERY(AGENT_REQUEST *request, AGENT_RESULT *result) perfstat_netinterface_t *ps_netif = NULL; struct zbx_json j; + ZBX_UNUSED(request); + /* check how many perfstat_netinterface_t structures are available */ if (-1 == (rc = perfstat_netinterface(NULL, NULL, sizeof(perfstat_netinterface_t), 0))) { @@ -253,6 +255,8 @@ end: return ret; #else + ZBX_UNUSED(request); + SET_MSG_RESULT(result, zbx_strdup(NULL, "Agent was compiled without support for Perfstat API.")); return SYSINFO_RET_FAIL; diff --git a/src/libs/zbxsysinfo/aix/proc.c b/src/libs/zbxsysinfo/aix/proc.c index 4ded8679021..fa8d43a96e8 100644 --- a/src/libs/zbxsysinfo/aix/proc.c +++ b/src/libs/zbxsysinfo/aix/proc.c @@ -43,8 +43,8 @@ static int check_procstate(struct procentry64 *procentry, int zbx_proc_stat) static int check_procargs(struct procentry64 *procentry, const char *proccomm) { - int i; - char procargs[MAX_BUFFER_LEN]; + unsigned int i; + char procargs[MAX_BUFFER_LEN]; if (0 != getargs(procentry, (int)sizeof(*procentry), procargs, (int)sizeof(procargs))) return FAIL; diff --git a/src/libs/zbxsysinfo/aix/software.c b/src/libs/zbxsysinfo/aix/software.c index 43cffe3022f..f1c84189cf3 100644 --- a/src/libs/zbxsysinfo/aix/software.c +++ b/src/libs/zbxsysinfo/aix/software.c @@ -29,6 +29,8 @@ int SYSTEM_SW_ARCH(AGENT_REQUEST *request, AGENT_RESULT *result) { struct utsname name; + ZBX_UNUSED(request); + if (-1 == uname(&name)) { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain system information: %s", zbx_strerror(errno))); diff --git a/src/libs/zbxsysinfo/aix/system.c b/src/libs/zbxsysinfo/aix/system.c index ec3f8896f84..21ee95f65a8 100644 --- a/src/libs/zbxsysinfo/aix/system.c +++ b/src/libs/zbxsysinfo/aix/system.c @@ -29,6 +29,8 @@ int SYSTEM_UNAME(AGENT_REQUEST *request, AGENT_RESULT *result) { struct utsname name; + ZBX_UNUSED(request); + if (-1 == uname(&name)) { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain system information: %s", zbx_strerror(errno))); diff --git a/src/libs/zbxsysinfo/aix/uptime.c b/src/libs/zbxsysinfo/aix/uptime.c index eedf3574e4d..2133ed86df5 100644 --- a/src/libs/zbxsysinfo/aix/uptime.c +++ b/src/libs/zbxsysinfo/aix/uptime.c @@ -28,6 +28,8 @@ int SYSTEM_UPTIME(AGENT_REQUEST *request, AGENT_RESULT *result) #if defined(HAVE_LIBPERFSTAT) perfstat_cpu_total_t ps_cpu_total; + ZBX_UNUSED(request); + if (0 >= hertz) { hertz = sysconf(_SC_CLK_TCK); @@ -58,6 +60,8 @@ int SYSTEM_UPTIME(AGENT_REQUEST *request, AGENT_RESULT *result) return SYSINFO_RET_OK; #else + ZBX_UNUSED(request); + SET_MSG_RESULT(result, zbx_strdup(NULL, "Agent was compiled without support for Perfstat API.")); return SYSINFO_RET_FAIL; diff --git a/src/libs/zbxsysinfo/alias/alias.c b/src/libs/zbxsysinfo/alias/alias.c index 8b05876fb1f..d400a246fc9 100644 --- a/src/libs/zbxsysinfo/alias/alias.c +++ b/src/libs/zbxsysinfo/alias/alias.c @@ -22,6 +22,7 @@ #include "zbxstr.h" #include "log.h" +#include "zbxexpr.h" static ALIAS *aliasList = NULL; @@ -30,7 +31,7 @@ void test_aliases(void) ALIAS *alias; for (alias = aliasList; NULL != alias; alias = alias->next) - test_parameter(alias->name); + zbx_test_parameter(alias->name); } void zbx_add_alias(const char *name, const char *value) @@ -89,7 +90,7 @@ const char *zbx_alias_get(const char *orig) size_t buffer_offset = 0; const char *p = orig; - if (SUCCEED != parse_key(&p) || '\0' != *p) + if (SUCCEED != zbx_parse_key(&p) || '\0' != *p) return orig; for (alias = aliasList; NULL != alias; alias = alias->next) diff --git a/src/libs/zbxsysinfo/common/dir.c b/src/libs/zbxsysinfo/common/dir.c index f427e1559f4..1aa33e2ed03 100644 --- a/src/libs/zbxsysinfo/common/dir.c +++ b/src/libs/zbxsysinfo/common/dir.c @@ -19,6 +19,7 @@ #include "dir.h" #include "zbxsysinfo.h" +#include "../sysinfo.h" #include "zbxstr.h" #include "zbxnum.h" diff --git a/src/libs/zbxsysinfo/common/dns.c b/src/libs/zbxsysinfo/common/dns.c index 37df7ec7029..5877c074e0b 100644 --- a/src/libs/zbxsysinfo/common/dns.c +++ b/src/libs/zbxsysinfo/common/dns.c @@ -19,6 +19,7 @@ #include "dns.h" #include "zbxsysinfo.h" +#include "../sysinfo.h" #include "zbxstr.h" #include "zbxnum.h" diff --git a/src/libs/zbxsysinfo/common/zabbix_stats.c b/src/libs/zbxsysinfo/common/zabbix_stats.c index 8f703911efe..ff579f729b7 100644 --- a/src/libs/zbxsysinfo/common/zabbix_stats.c +++ b/src/libs/zbxsysinfo/common/zabbix_stats.c @@ -94,7 +94,7 @@ static void get_remote_zabbix_stats(const struct zbx_json *json, const char *ip, "Cannot obtain internal statistics: received empty response.")); } else if (SUCCEED == check_response(s.buffer, result)) - set_result_type(result, ITEM_VALUE_TYPE_TEXT, s.buffer); + zbx_set_agent_result_type(result, ITEM_VALUE_TYPE_TEXT, s.buffer); } else { diff --git a/src/libs/zbxsysinfo/common/zbxsysinfo_common.c b/src/libs/zbxsysinfo/common/zbxsysinfo_common.c index 22e6e5a00e7..f772ecdbb23 100644 --- a/src/libs/zbxsysinfo/common/zbxsysinfo_common.c +++ b/src/libs/zbxsysinfo/common/zbxsysinfo_common.c @@ -96,7 +96,7 @@ ZBX_METRIC parameters_common[] = static const char *user_parameter_dir = NULL; -void set_user_parameter_dir(const char *path) +void zbx_set_user_parameter_dir(const char *path) { user_parameter_dir = path; } diff --git a/src/libs/zbxsysinfo/freebsd/diskio.c b/src/libs/zbxsysinfo/freebsd/diskio.c index fdf03ddfc69..2a73712bff7 100644 --- a/src/libs/zbxsysinfo/freebsd/diskio.c +++ b/src/libs/zbxsysinfo/freebsd/diskio.c @@ -29,7 +29,7 @@ static struct statinfo *si = NULL; -int get_diskstat(const char *devname, zbx_uint64_t *dstat) +int zbx_get_diskstat(const char *devname, zbx_uint64_t *dstat) { int i; struct devstat *ds = NULL; @@ -148,7 +148,7 @@ static int vfs_dev_rw(AGENT_REQUEST *request, AGENT_RESULT *result, int rw) return SYSINFO_RET_FAIL; } - if (FAIL == get_diskstat(pd, dstats)) + if (FAIL == zbx_get_diskstat(pd, dstats)) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain disk information.")); return SYSINFO_RET_FAIL; @@ -190,7 +190,7 @@ static int vfs_dev_rw(AGENT_REQUEST *request, AGENT_RESULT *result, int rw) if (NULL == (device = collector_diskdevice_get(pd))) { - if (FAIL == get_diskstat(pd, dstats)) /* validate device name */ + if (FAIL == zbx_get_diskstat(pd, dstats)) /* validate device name */ { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain disk information.")); return SYSINFO_RET_FAIL; diff --git a/src/libs/zbxsysinfo/freebsd/hostname.c b/src/libs/zbxsysinfo/freebsd/hostname.c index 5913dd7b4a0..f17648f076e 100644 --- a/src/libs/zbxsysinfo/freebsd/hostname.c +++ b/src/libs/zbxsysinfo/freebsd/hostname.c @@ -18,6 +18,7 @@ **/ #include "zbxsysinfo.h" +#include "../sysinfo.h" #include "log.h" diff --git a/src/libs/zbxsysinfo/freebsd/inodes.c b/src/libs/zbxsysinfo/freebsd/inodes.c index 4a3e67267f5..d3e27b90bac 100644 --- a/src/libs/zbxsysinfo/freebsd/inodes.c +++ b/src/libs/zbxsysinfo/freebsd/inodes.c @@ -17,8 +17,9 @@ ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. **/ -#include "inodes.h" #include "zbxsysinfo.h" +#include "inodes.h" +#include "../sysinfo.h" #include "log.h" diff --git a/src/libs/zbxsysinfo/freebsd/proc.c b/src/libs/zbxsysinfo/freebsd/proc.c index 44db5c149b6..f313c4b90f3 100644 --- a/src/libs/zbxsysinfo/freebsd/proc.c +++ b/src/libs/zbxsysinfo/freebsd/proc.c @@ -147,18 +147,25 @@ static void proc_data_free(proc_data_t *proc_data) zbx_free(proc_data); } +#define ARGV_START_SIZE 64 static char *get_commandline(struct kinfo_proc *proc) { int mib[4], i; size_t sz; static char *args = NULL; +#if (__FreeBSD_version >= 802510) static int args_alloc = 0; +#else + int argv_max, err = -1; + static int args_alloc = ARGV_START_SIZE; +#endif mib[0] = CTL_KERN; mib[1] = KERN_PROC; mib[2] = KERN_PROC_ARGS; mib[3] = proc->ZBX_PROC_PID; +#if (__FreeBSD_version >= 802510) if (-1 == sysctl(mib, 4, NULL, &sz, NULL, 0)) return NULL; @@ -175,16 +182,50 @@ static char *get_commandline(struct kinfo_proc *proc) if (-1 == sysctl(mib, 4, args, &sz, NULL, 0)) return NULL; +#else + /* + * Before FreeBSD 8.3 sysctl() API for kern.proc.args didn't follow the regular convention + * that a user can query the needed size for results by passing in a NULL old pointer + * and a valid oldsize, given that we have to estimate the required output buffer size manually: + * + * https://github.com/freebsd/freebsd-src/commit/9f688f2ce3c01f30b0c98d17c6ce057660819c8c + */ + + if (NULL == args) + args = zbx_malloc(args, args_alloc); + + if (-1 == (argv_max = sysconf(_SC_ARG_MAX))) + return NULL; + + while (0 != err && args_alloc < argv_max) + { + sz = (size_t)args_alloc; + if (-1 == (err = sysctl(mib, 4, args, &sz, NULL, 0))) + { + if (ENOMEM == errno) + { + args_alloc *= 2; + args = zbx_realloc(args, args_alloc); + } + else + return NULL; + } + } + + if (-1 == err) + return NULL; +#endif for (i = 0; i < (int)(sz - 1); i++) if (args[i] == '\0') args[i] = ' '; - if (sz == 0) + if (0 == sz) zbx_strlcpy(args, proc->ZBX_PROC_COMM, args_alloc); return args; } +#undef ARGV_START_SIZE int PROC_MEM(AGENT_REQUEST *request, AGENT_RESULT *result) { diff --git a/src/libs/zbxsysinfo/hpux/diskio.c b/src/libs/zbxsysinfo/hpux/diskio.c index f2dd74e02a2..606ca389bc3 100644 --- a/src/libs/zbxsysinfo/hpux/diskio.c +++ b/src/libs/zbxsysinfo/hpux/diskio.c @@ -19,7 +19,7 @@ #include "zbxsysinfo.h" -int get_diskstat(const char *devname, zbx_uint64_t *dstat) +int zbx_get_diskstat(const char *devname, zbx_uint64_t *dstat) { return FAIL; } diff --git a/src/libs/zbxsysinfo/hpux/hostname.c b/src/libs/zbxsysinfo/hpux/hostname.c index 0fff7cca94f..1b20aadc1e7 100644 --- a/src/libs/zbxsysinfo/hpux/hostname.c +++ b/src/libs/zbxsysinfo/hpux/hostname.c @@ -18,6 +18,7 @@ **/ #include "zbxsysinfo.h" +#include "../sysinfo.h" #include "log.h" diff --git a/src/libs/zbxsysinfo/linux/diskio.c b/src/libs/zbxsysinfo/linux/diskio.c index 81eee4e571f..873f66c6608 100644 --- a/src/libs/zbxsysinfo/linux/diskio.c +++ b/src/libs/zbxsysinfo/linux/diskio.c @@ -72,7 +72,7 @@ ) continue #endif -int get_diskstat(const char *devname, zbx_uint64_t *dstat) +int zbx_get_diskstat(const char *devname, zbx_uint64_t *dstat) { FILE *f; char tmp[MAX_STRING_LEN], name[MAX_STRING_LEN], dev_path[MAX_STRING_LEN]; @@ -211,7 +211,7 @@ static int vfs_dev_rw(AGENT_REQUEST *request, AGENT_RESULT *result, int rw) return SYSINFO_RET_FAIL; } - if (SUCCEED != get_diskstat(devname, dstats)) + if (SUCCEED != zbx_get_diskstat(devname, dstats)) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain disk information.")); return SYSINFO_RET_FAIL; @@ -263,7 +263,7 @@ static int vfs_dev_rw(AGENT_REQUEST *request, AGENT_RESULT *result, int rw) if (NULL == (device = collector_diskdevice_get(kernel_devname))) { - if (SUCCEED != get_diskstat(kernel_devname, dstats)) + if (SUCCEED != zbx_get_diskstat(kernel_devname, dstats)) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain disk information.")); diff --git a/src/libs/zbxsysinfo/linux/hostname.c b/src/libs/zbxsysinfo/linux/hostname.c index 5913dd7b4a0..f17648f076e 100644 --- a/src/libs/zbxsysinfo/linux/hostname.c +++ b/src/libs/zbxsysinfo/linux/hostname.c @@ -18,6 +18,7 @@ **/ #include "zbxsysinfo.h" +#include "../sysinfo.h" #include "log.h" diff --git a/src/libs/zbxsysinfo/linux/inodes.c b/src/libs/zbxsysinfo/linux/inodes.c index 4dea50b9de5..791bbdb7322 100644 --- a/src/libs/zbxsysinfo/linux/inodes.c +++ b/src/libs/zbxsysinfo/linux/inodes.c @@ -19,6 +19,7 @@ #include "inodes.h" #include "zbxsysinfo.h" +#include "../sysinfo.h" #include "log.h" diff --git a/src/libs/zbxsysinfo/linux/memory.c b/src/libs/zbxsysinfo/linux/memory.c index 9a84e307778..02907b9a72d 100644 --- a/src/libs/zbxsysinfo/linux/memory.c +++ b/src/libs/zbxsysinfo/linux/memory.c @@ -168,7 +168,7 @@ static int VM_MEMORY_PAVAILABLE(AGENT_RESULT *result) return SYSINFO_RET_FAIL; } - init_result(&result_tmp); + zbx_init_agent_result(&result_tmp); ret = VM_MEMORY_AVAILABLE(&result_tmp); @@ -190,7 +190,7 @@ static int VM_MEMORY_PAVAILABLE(AGENT_RESULT *result) SET_DBL_RESULT(result, available / (double)total * 100); clean: - free_result(&result_tmp); + zbx_free_agent_result(&result_tmp); return ret; } diff --git a/src/libs/zbxsysinfo/netbsd/diskio.c b/src/libs/zbxsysinfo/netbsd/diskio.c index f2dd74e02a2..606ca389bc3 100644 --- a/src/libs/zbxsysinfo/netbsd/diskio.c +++ b/src/libs/zbxsysinfo/netbsd/diskio.c @@ -19,7 +19,7 @@ #include "zbxsysinfo.h" -int get_diskstat(const char *devname, zbx_uint64_t *dstat) +int zbx_get_diskstat(const char *devname, zbx_uint64_t *dstat) { return FAIL; } diff --git a/src/libs/zbxsysinfo/netbsd/hostname.c b/src/libs/zbxsysinfo/netbsd/hostname.c index 5913dd7b4a0..f17648f076e 100644 --- a/src/libs/zbxsysinfo/netbsd/hostname.c +++ b/src/libs/zbxsysinfo/netbsd/hostname.c @@ -18,6 +18,7 @@ **/ #include "zbxsysinfo.h" +#include "../sysinfo.h" #include "log.h" diff --git a/src/libs/zbxsysinfo/netbsd/inodes.c b/src/libs/zbxsysinfo/netbsd/inodes.c index 85060eace97..072bcd18836 100644 --- a/src/libs/zbxsysinfo/netbsd/inodes.c +++ b/src/libs/zbxsysinfo/netbsd/inodes.c @@ -19,6 +19,7 @@ #include "inodes.h" #include "zbxsysinfo.h" +#include "../sysinfo.h" #include "log.h" diff --git a/src/libs/zbxsysinfo/openbsd/diskio.c b/src/libs/zbxsysinfo/openbsd/diskio.c index 85a09df212b..5cea1603a41 100644 --- a/src/libs/zbxsysinfo/openbsd/diskio.c +++ b/src/libs/zbxsysinfo/openbsd/diskio.c @@ -22,7 +22,7 @@ #include "log.h" #include "zbxstr.h" -int get_diskstat(const char *devname, zbx_uint64_t *dstat) +int zbx_get_diskstat(const char *devname, zbx_uint64_t *dstat) { return FAIL; } diff --git a/src/libs/zbxsysinfo/openbsd/hostname.c b/src/libs/zbxsysinfo/openbsd/hostname.c index 5913dd7b4a0..f17648f076e 100644 --- a/src/libs/zbxsysinfo/openbsd/hostname.c +++ b/src/libs/zbxsysinfo/openbsd/hostname.c @@ -18,6 +18,7 @@ **/ #include "zbxsysinfo.h" +#include "../sysinfo.h" #include "log.h" diff --git a/src/libs/zbxsysinfo/osf/diskio.c b/src/libs/zbxsysinfo/osf/diskio.c index f2dd74e02a2..606ca389bc3 100644 --- a/src/libs/zbxsysinfo/osf/diskio.c +++ b/src/libs/zbxsysinfo/osf/diskio.c @@ -19,7 +19,7 @@ #include "zbxsysinfo.h" -int get_diskstat(const char *devname, zbx_uint64_t *dstat) +int zbx_get_diskstat(const char *devname, zbx_uint64_t *dstat) { return FAIL; } diff --git a/src/libs/zbxsysinfo/osf/diskspace.c b/src/libs/zbxsysinfo/osf/diskspace.c index 2bcd38bbfad..76df1a5b190 100644 --- a/src/libs/zbxsysinfo/osf/diskspace.c +++ b/src/libs/zbxsysinfo/osf/diskspace.c @@ -18,6 +18,7 @@ **/ #include "zbxsysinfo.h" +#include "../sysinfo.h" #include "log.h" diff --git a/src/libs/zbxsysinfo/osf/hostname.c b/src/libs/zbxsysinfo/osf/hostname.c index 5913dd7b4a0..f17648f076e 100644 --- a/src/libs/zbxsysinfo/osf/hostname.c +++ b/src/libs/zbxsysinfo/osf/hostname.c @@ -18,6 +18,7 @@ **/ #include "zbxsysinfo.h" +#include "../sysinfo.h" #include "log.h" diff --git a/src/libs/zbxsysinfo/osf/inodes.c b/src/libs/zbxsysinfo/osf/inodes.c index 4c983a03b43..cc9d1cc3658 100644 --- a/src/libs/zbxsysinfo/osf/inodes.c +++ b/src/libs/zbxsysinfo/osf/inodes.c @@ -18,6 +18,7 @@ **/ #include "zbxsysinfo.h" +#include "../sysinfo.h" #include "log.h" diff --git a/src/libs/zbxsysinfo/osf/memory.c b/src/libs/zbxsysinfo/osf/memory.c index c4af371dae3..de910b18479 100644 --- a/src/libs/zbxsysinfo/osf/memory.c +++ b/src/libs/zbxsysinfo/osf/memory.c @@ -36,7 +36,7 @@ static int VM_MEMORY_USED(AGENT_RESULT *result) AGENT_RESULT result_tmp; zbx_uint64_t free, total; - init_result(&result_tmp); + zbx_init_agent_result(&result_tmp); if (SYSINFO_RET_OK != VM_MEMORY_FREE(&result_tmp)) { @@ -58,7 +58,7 @@ static int VM_MEMORY_USED(AGENT_RESULT *result) ret = SYSINFO_RET_OK; clean: - free_result(&result_tmp); + zbx_free_agent_result(&result_tmp); return ret; } @@ -69,7 +69,7 @@ static int VM_MEMORY_PUSED(AGENT_RESULT *result) AGENT_RESULT result_tmp; zbx_uint64_t free, total; - init_result(&result_tmp); + zbx_init_agent_result(&result_tmp); if (SYSINFO_RET_OK != VM_MEMORY_FREE(&result_tmp)) { @@ -97,7 +97,7 @@ static int VM_MEMORY_PUSED(AGENT_RESULT *result) ret = SYSINFO_RET_OK; clean: - free_result(&result_tmp); + zbx_free_agent_result(&result_tmp); return ret; } @@ -113,7 +113,7 @@ static int VM_MEMORY_PAVAILABLE(AGENT_RESULT *result) AGENT_RESULT result_tmp; zbx_uint64_t free, total; - init_result(&result_tmp); + zbx_init_agent_result(&result_tmp); if (SYSINFO_RET_OK != VM_MEMORY_FREE(&result_tmp)) { @@ -141,7 +141,7 @@ static int VM_MEMORY_PAVAILABLE(AGENT_RESULT *result) ret = SYSINFO_RET_OK; clean: - free_result(&result_tmp); + zbx_free_agent_result(&result_tmp); return ret; } diff --git a/src/libs/zbxsysinfo/osf/swap.c b/src/libs/zbxsysinfo/osf/swap.c index 74da58c6c2a..11c08179bec 100644 --- a/src/libs/zbxsysinfo/osf/swap.c +++ b/src/libs/zbxsysinfo/osf/swap.c @@ -202,7 +202,7 @@ static int SYSTEM_SWAP_PFREE(AGENT_RESULT *result) zbx_uint64_t tot_val = 0; zbx_uint64_t free_val = 0; - init_result(&result_tmp); + zbx_init_agent_result(&result_tmp); if (SYSINFO_RET_OK != SYSTEM_SWAP_TOTAL(&result_tmp) || !(result_tmp.type & AR_UINT64)) return SYSINFO_RET_FAIL; @@ -211,7 +211,7 @@ static int SYSTEM_SWAP_PFREE(AGENT_RESULT *result) /* Check for division by zero */ if (0 == tot_val) { - free_result(&result_tmp); + zbx_free_agent_result(&result_tmp); return SYSINFO_RET_FAIL; } @@ -219,7 +219,7 @@ static int SYSTEM_SWAP_PFREE(AGENT_RESULT *result) return SYSINFO_RET_FAIL; free_val = result_tmp.ui64; - free_result(&result_tmp); + zbx_free_agent_result(&result_tmp); SET_DBL_RESULT(result, (100.0 * (double)free_val) / (double)tot_val); @@ -232,7 +232,7 @@ static int SYSTEM_SWAP_PUSED(AGENT_RESULT *result) zbx_uint64_t tot_val = 0; zbx_uint64_t free_val = 0; - init_result(&result_tmp); + zbx_init_agent_result(&result_tmp); if (SYSINFO_RET_OK != SYSTEM_SWAP_TOTAL(&result_tmp) || !(result_tmp.type & AR_UINT64)) return SYSINFO_RET_FAIL; @@ -241,7 +241,7 @@ static int SYSTEM_SWAP_PUSED(AGENT_RESULT *result) /* Check for division by zero */ if (0 == tot_val) { - free_result(&result_tmp); + zbx_free_agent_result(&result_tmp); return SYSINFO_RET_FAIL; } @@ -249,7 +249,7 @@ static int SYSTEM_SWAP_PUSED(AGENT_RESULT *result) return SYSINFO_RET_FAIL; free_val = result_tmp.ui64; - free_result(&result_tmp); + zbx_free_agent_result(&result_tmp); SET_DBL_RESULT(result, 100.0 - (100.0 * (double)free_val) / (double)tot_val); diff --git a/src/libs/zbxsysinfo/osx/diskio.c b/src/libs/zbxsysinfo/osx/diskio.c index f2dd74e02a2..606ca389bc3 100644 --- a/src/libs/zbxsysinfo/osx/diskio.c +++ b/src/libs/zbxsysinfo/osx/diskio.c @@ -19,7 +19,7 @@ #include "zbxsysinfo.h" -int get_diskstat(const char *devname, zbx_uint64_t *dstat) +int zbx_get_diskstat(const char *devname, zbx_uint64_t *dstat) { return FAIL; } diff --git a/src/libs/zbxsysinfo/osx/hostname.c b/src/libs/zbxsysinfo/osx/hostname.c index 5913dd7b4a0..f17648f076e 100644 --- a/src/libs/zbxsysinfo/osx/hostname.c +++ b/src/libs/zbxsysinfo/osx/hostname.c @@ -18,6 +18,7 @@ **/ #include "zbxsysinfo.h" +#include "../sysinfo.h" #include "log.h" diff --git a/src/libs/zbxsysinfo/solaris/Makefile.am b/src/libs/zbxsysinfo/solaris/Makefile.am index a2f8e6fe46b..662bf67e13c 100644 --- a/src/libs/zbxsysinfo/solaris/Makefile.am +++ b/src/libs/zbxsysinfo/solaris/Makefile.am @@ -5,6 +5,8 @@ noinst_LIBRARIES = libspecsysinfo.a libspechostnamesysinfo.a libspecsysinfo_a_CFLAGS = -I$(top_srcdir)/src/zabbix_agent libspecsysinfo_a_SOURCES = \ + zbx_sysinfo_kstat.c \ + zbx_sysinfo_kstat.h \ boottime.c \ cpu.c \ diskio.c \ diff --git a/src/libs/zbxsysinfo/solaris/boottime.c b/src/libs/zbxsysinfo/solaris/boottime.c index c463cbc2a69..20786fd3fbd 100644 --- a/src/libs/zbxsysinfo/solaris/boottime.c +++ b/src/libs/zbxsysinfo/solaris/boottime.c @@ -18,6 +18,7 @@ **/ #include "zbxsysinfo.h" +#include "zbx_sysinfo_kstat.h" #include "log.h" diff --git a/src/libs/zbxsysinfo/solaris/cpu.c b/src/libs/zbxsysinfo/solaris/cpu.c index 623f9e51c36..c18da58e2cc 100644 --- a/src/libs/zbxsysinfo/solaris/cpu.c +++ b/src/libs/zbxsysinfo/solaris/cpu.c @@ -18,6 +18,7 @@ **/ #include "zbxsysinfo.h" +#include "zbx_sysinfo_kstat.h" #include "stats.h" #include "log.h" diff --git a/src/libs/zbxsysinfo/solaris/diskio.c b/src/libs/zbxsysinfo/solaris/diskio.c index 3ecc1df13ba..544b40360a3 100644 --- a/src/libs/zbxsysinfo/solaris/diskio.c +++ b/src/libs/zbxsysinfo/solaris/diskio.c @@ -18,6 +18,7 @@ **/ #include "zbxsysinfo.h" +#include "../sysinfo.h" #include "log.h" @@ -30,7 +31,7 @@ typedef struct } zbx_kstat_t; -int get_diskstat(const char *devname, zbx_uint64_t *dstat) +int zbx_get_diskstat(const char *devname, zbx_uint64_t *dstat) { return FAIL; } @@ -170,6 +171,13 @@ static int VFS_DEV_WRITE_OPERATIONS(const char *devname, AGENT_RESULT *result) return SYSINFO_RET_OK; } +typedef struct +{ + const char *mode; + int (*function)(const char *devname, AGENT_RESULT *result); +} +MODE_FUNCTION; + static int process_mode_function(AGENT_REQUEST *request, AGENT_RESULT *result, const MODE_FUNCTION *fl) { const char *devname, *mode; diff --git a/src/libs/zbxsysinfo/solaris/hostname.c b/src/libs/zbxsysinfo/solaris/hostname.c index 5913dd7b4a0..f17648f076e 100644 --- a/src/libs/zbxsysinfo/solaris/hostname.c +++ b/src/libs/zbxsysinfo/solaris/hostname.c @@ -18,6 +18,7 @@ **/ #include "zbxsysinfo.h" +#include "../sysinfo.h" #include "log.h" diff --git a/src/libs/zbxsysinfo/solaris/inodes.c b/src/libs/zbxsysinfo/solaris/inodes.c index 85060eace97..072bcd18836 100644 --- a/src/libs/zbxsysinfo/solaris/inodes.c +++ b/src/libs/zbxsysinfo/solaris/inodes.c @@ -19,6 +19,7 @@ #include "inodes.h" #include "zbxsysinfo.h" +#include "../sysinfo.h" #include "log.h" diff --git a/src/libs/zbxsysinfo/solaris/net.c b/src/libs/zbxsysinfo/solaris/net.c index efa76407d7e..aed08bdbfa4 100644 --- a/src/libs/zbxsysinfo/solaris/net.c +++ b/src/libs/zbxsysinfo/solaris/net.c @@ -19,6 +19,7 @@ #include "zbxsysinfo.h" #include "../common/zbxsysinfo_common.h" +#include "zbx_sysinfo_kstat.h" #include "zbxjson.h" #include "log.h" diff --git a/src/libs/zbxsysinfo/solaris/zbx_sysinfo_kstat.c b/src/libs/zbxsysinfo/solaris/zbx_sysinfo_kstat.c new file mode 100644 index 00000000000..7ecb54bca98 --- /dev/null +++ b/src/libs/zbxsysinfo/solaris/zbx_sysinfo_kstat.c @@ -0,0 +1,41 @@ +/* +** Zabbix +** Copyright (C) 2001-2022 Zabbix SIA +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +**/ + +#include "zbx_sysinfo_kstat.h" +#include "zbxcommon.h" + +#ifdef HAVE_KSTAT_H +zbx_uint64_t get_kstat_numeric_value(const kstat_named_t *kn) +{ + switch (kn->data_type) + { + case KSTAT_DATA_INT32: + return kn->value.i32; + case KSTAT_DATA_UINT32: + return kn->value.ui32; + case KSTAT_DATA_INT64: + return kn->value.i64; + case KSTAT_DATA_UINT64: + return kn->value.ui64; + default: + THIS_SHOULD_NEVER_HAPPEN; + return 0; + } +} +#endif /* HAVE_KSTAT_H */ diff --git a/src/zabbix_server/trapper/proxyconfig.h b/src/libs/zbxsysinfo/solaris/zbx_sysinfo_kstat.h index 579ebe33b61..6b42dc1a06b 100644 --- a/src/zabbix_server/trapper/proxyconfig.h +++ b/src/libs/zbxsysinfo/solaris/zbx_sysinfo_kstat.h @@ -17,16 +17,8 @@ ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. **/ -#ifndef ZABBIX_PROXYCFG_H -#define ZABBIX_PROXYCFG_H +#include "zbxtypes.h" -#include "zbxcomms.h" -#include "zbxjson.h" - -extern int CONFIG_TIMEOUT; -extern int CONFIG_TRAPPER_TIMEOUT; - -void send_proxyconfig(zbx_socket_t *sock, struct zbx_json_parse *jp); -void recv_proxyconfig(zbx_socket_t *sock, struct zbx_json_parse *jp, const zbx_config_tls_t *zbx_config_tls); - -#endif +#ifdef HAVE_KSTAT_H +zbx_uint64_t get_kstat_numeric_value(const kstat_named_t *kn); +#endif /* HAVE_KSTAT_H */ diff --git a/src/libs/zbxsysinfo/sysinfo.c b/src/libs/zbxsysinfo/sysinfo.c index b626bf9e718..167c135e0a6 100644 --- a/src/libs/zbxsysinfo/sysinfo.c +++ b/src/libs/zbxsysinfo/sysinfo.c @@ -18,6 +18,7 @@ **/ #include "zbxsysinfo.h" +#include "sysinfo.h" #include "alias/alias.h" #include "log.h" @@ -30,6 +31,7 @@ #include "zbxstr.h" #include "zbxnum.h" #include "zbxparam.h" +#include "zbxexpr.h" extern int CONFIG_TIMEOUT; @@ -75,7 +77,7 @@ zbx_vector_ptr_t key_access_rules; #define ZBX_COMMAND_WITH_PARAMS 2 static int compare_key_access_rules(const void *rule_a, const void *rule_b); -static int parse_key_access_rule(char *pattern, zbx_key_access_rule_t *rule); +static int zbx_parse_key_access_rule(char *pattern, zbx_key_access_rule_t *rule); /****************************************************************************** * * @@ -92,7 +94,7 @@ static int parse_command_dyn(const char *command, char **cmd, char **param) size_t cmd_alloc = 0, param_alloc = 0, cmd_offset = 0, param_offset = 0; - for (pl = command; SUCCEED == is_key_char(*pl); pl++) + for (pl = command; SUCCEED == zbx_is_key_char(*pl); pl++) ; if (pl == command) @@ -147,7 +149,7 @@ static int add_to_metrics(ZBX_METRIC **metrics, ZBX_METRIC *metric, char *error, * Purpose: registers a new item key into the system * * * ******************************************************************************/ -int add_metric(ZBX_METRIC *metric, char *error, size_t max_error_len) +int zbx_add_metric(ZBX_METRIC *metric, char *error, size_t max_error_len) { return add_to_metrics(&commands, metric, error, max_error_len); } @@ -157,22 +159,22 @@ int add_metric(ZBX_METRIC *metric, char *error, size_t max_error_len) * Purpose: registers a new item key as local into the system * * * ******************************************************************************/ -int add_metric_local(ZBX_METRIC *metric, char *error, size_t max_error_len) +static int add_metric_local(ZBX_METRIC *metric, char *error, size_t max_error_len) { return add_to_metrics(&commands_local, metric, error, max_error_len); } #if !defined(__MINGW32__) -int add_user_parameter(const char *itemkey, char *command, char *error, size_t max_error_len) +int zbx_add_user_parameter(const char *itemkey, char *command, char *error, size_t max_error_len) { int ret; unsigned flags = CF_USERPARAMETER; ZBX_METRIC metric; AGENT_REQUEST request; - init_request(&request); + zbx_init_agent_request(&request); - if (SUCCEED == (ret = parse_item_key(itemkey, &request))) + if (SUCCEED == (ret = zbx_parse_item_key(itemkey, &request))) { if (1 == get_rparams_num(&request) && 0 == strcmp("[*]", itemkey + strlen(get_rkey(&request)))) flags |= CF_HAVEPARAMS; @@ -187,17 +189,17 @@ int add_user_parameter(const char *itemkey, char *command, char *error, size_t m metric.function = &EXECUTE_USER_PARAMETER; metric.test_param = command; - ret = add_metric(&metric, error, max_error_len); + ret = zbx_add_metric(&metric, error, max_error_len); } else zbx_strlcpy(error, "syntax error", max_error_len); - free_request(&request); + zbx_free_agent_request(&request); return ret; } -void remove_user_parameters(void) +void zbx_remove_user_parameters(void) { int i, usr = -1; @@ -227,7 +229,7 @@ void remove_user_parameters(void) } } -void get_metrics_copy(ZBX_METRIC **metrics) +void zbx_get_metrics_copy(ZBX_METRIC **metrics) { unsigned int i; @@ -254,19 +256,19 @@ void get_metrics_copy(ZBX_METRIC **metrics) memset(&(*metrics)[i], 0, sizeof(ZBX_METRIC)); } -void set_metrics(ZBX_METRIC *metrics) +void zbx_set_metrics(ZBX_METRIC *metrics) { - free_metrics_ext(&commands); + zbx_free_metrics_ext(&commands); commands = metrics; } #endif -void init_metrics(void) +void zbx_init_metrics(void) { int i; char error[MAX_STRING_LEN]; - init_key_access_rules(); + zbx_init_key_access_rules(); commands = (ZBX_METRIC *)zbx_malloc(commands, sizeof(ZBX_METRIC)); commands[0].key = NULL; @@ -276,7 +278,7 @@ void init_metrics(void) #ifdef WITH_AGENT_METRICS for (i = 0; NULL != parameters_agent[i].key; i++) { - if (SUCCEED != add_metric(¶meters_agent[i], error, sizeof(error))) + if (SUCCEED != zbx_add_metric(¶meters_agent[i], error, sizeof(error))) { zabbix_log(LOG_LEVEL_CRIT, "cannot add item key: %s", error); exit(EXIT_FAILURE); @@ -287,7 +289,7 @@ void init_metrics(void) #ifdef WITH_COMMON_METRICS for (i = 0; NULL != parameters_common[i].key; i++) { - if (SUCCEED != add_metric(¶meters_common[i], error, sizeof(error))) + if (SUCCEED != zbx_add_metric(¶meters_common[i], error, sizeof(error))) { zabbix_log(LOG_LEVEL_CRIT, "cannot add item key: %s", error); exit(EXIT_FAILURE); @@ -307,7 +309,7 @@ void init_metrics(void) #ifdef WITH_HTTP_METRICS for (i = 0; NULL != parameters_common_http[i].key; i++) { - if (SUCCEED != add_metric(¶meters_common_http[i], error, sizeof(error))) + if (SUCCEED != zbx_add_metric(¶meters_common_http[i], error, sizeof(error))) { zabbix_log(LOG_LEVEL_CRIT, "cannot add item key: %s", error); exit(EXIT_FAILURE); @@ -318,7 +320,7 @@ void init_metrics(void) #ifdef WITH_SPECIFIC_METRICS for (i = 0; NULL != parameters_specific[i].key; i++) { - if (SUCCEED != add_metric(¶meters_specific[i], error, sizeof(error))) + if (SUCCEED != zbx_add_metric(¶meters_specific[i], error, sizeof(error))) { zabbix_log(LOG_LEVEL_CRIT, "cannot add item key: %s", error); exit(EXIT_FAILURE); @@ -329,7 +331,7 @@ void init_metrics(void) #ifdef WITH_SIMPLE_METRICS for (i = 0; NULL != parameters_simple[i].key; i++) { - if (SUCCEED != add_metric(¶meters_simple[i], error, sizeof(error))) + if (SUCCEED != zbx_add_metric(¶meters_simple[i], error, sizeof(error))) { zabbix_log(LOG_LEVEL_CRIT, "cannot add item key: %s", error); exit(EXIT_FAILURE); @@ -338,7 +340,7 @@ void init_metrics(void) #endif #ifdef WITH_HOSTNAME_METRIC - if (SUCCEED != add_metric(¶meter_hostname, error, sizeof(error))) + if (SUCCEED != zbx_add_metric(¶meter_hostname, error, sizeof(error))) { zabbix_log(LOG_LEVEL_CRIT, "cannot add item key: %s", error); exit(EXIT_FAILURE); @@ -346,7 +348,7 @@ void init_metrics(void) #endif } -void free_metrics_ext(ZBX_METRIC **metrics) +void zbx_free_metrics_ext(ZBX_METRIC **metrics) { if (NULL != *metrics) { @@ -362,11 +364,11 @@ void free_metrics_ext(ZBX_METRIC **metrics) } } -void free_metrics(void) +void zbx_free_metrics(void) { - free_metrics_ext(&commands); - free_metrics_ext(&commands_local); - free_key_access_rules(); + zbx_free_metrics_ext(&commands); + zbx_free_metrics_ext(&commands_local); + zbx_free_key_access_rules(); } /****************************************************************************** @@ -374,7 +376,7 @@ void free_metrics(void) * Purpose: initializes key access rule list * * * ******************************************************************************/ -void init_key_access_rules(void) +void zbx_init_key_access_rules(void) { zbx_vector_ptr_create(&key_access_rules); } @@ -411,7 +413,7 @@ static zbx_key_access_rule_t *zbx_key_access_rule_create(char *pattern, zbx_key_ rule->pattern = zbx_strdup(NULL, pattern); zbx_vector_str_create(&rule->elements); - if (SUCCEED != parse_key_access_rule(pattern, rule)) + if (SUCCEED != zbx_parse_key_access_rule(pattern, rule)) { zbx_key_access_rule_free(rule); rule = NULL; @@ -424,7 +426,7 @@ static zbx_key_access_rule_t *zbx_key_access_rule_create(char *pattern, zbx_key_ * Purpose: validates key access rules configuration * * * ******************************************************************************/ -void finalize_key_access_rules_configuration(void) +void zbx_finalize_key_access_rules_configuration(void) { int i, j, rules_num, sysrun_index = ZBX_MAX_UINT31_1; zbx_key_access_rule_t *rule, *sysrun_deny; @@ -525,13 +527,13 @@ void finalize_key_access_rules_configuration(void) * FAIL - pattern parsing failed * * * ******************************************************************************/ -static int parse_key_access_rule(char *pattern, zbx_key_access_rule_t *rule) +static int zbx_parse_key_access_rule(char *pattern, zbx_key_access_rule_t *rule) { char *pl, *pr = NULL, *param; size_t alloc = 0, offset = 0; int i, size; - for (pl = pattern; SUCCEED == is_key_char(*pl) || '*' == *pl; pl++); + for (pl = pattern; SUCCEED == zbx_is_key_char(*pl) || '*' == *pl; pl++); if (pl == pattern) return FAIL; /* empty key */ @@ -634,7 +636,7 @@ static int compare_key_access_rules(const void *rule_a, const void *rule_b) * FAIL - pattern parsing failed * * * ******************************************************************************/ -int add_key_access_rule(const char *parameter, char *pattern, zbx_key_access_rule_type_t type) +int zbx_add_key_access_rule(const char *parameter, char *pattern, zbx_key_access_rule_type_t type) { zbx_key_access_rule_t *rule, *r; int i; @@ -673,7 +675,7 @@ int add_key_access_rule(const char *parameter, char *pattern, zbx_key_access_rul * ZBX_KEY_ACCESS_DENY - metric access denied * * * ******************************************************************************/ -int check_request_access_rules(AGENT_REQUEST *request) +int zbx_check_request_access_rules(AGENT_REQUEST *request) { int i, j, empty_arguments; zbx_key_access_rule_t *rule; @@ -757,19 +759,19 @@ int check_request_access_rules(AGENT_REQUEST *request) * ZBX_KEY_ACCESS_DENY - metric access denied * * * ******************************************************************************/ -int check_key_access_rules(const char *metric) +int zbx_check_key_access_rules(const char *metric) { int ret; AGENT_REQUEST request; - init_request(&request); + zbx_init_agent_request(&request); - if (SUCCEED == parse_item_key(metric, &request)) - ret = check_request_access_rules(&request); + if (SUCCEED == zbx_parse_item_key(metric, &request)) + ret = zbx_check_request_access_rules(&request); else ret = ZBX_KEY_ACCESS_DENY; - free_request(&request); + zbx_free_agent_request(&request); return ret; } @@ -779,7 +781,7 @@ int check_key_access_rules(const char *metric) * Purpose: cleanup key access rule list * * * ******************************************************************************/ -void free_key_access_rules(void) +void zbx_free_key_access_rules(void) { int i; @@ -798,7 +800,7 @@ static void zbx_log_init(zbx_log_t *log) log->logeventid = 0; } -void init_result(AGENT_RESULT *result) +void zbx_init_agent_result(AGENT_RESULT *result) { memset(result, 0, sizeof(AGENT_RESULT)); } @@ -815,7 +817,7 @@ void zbx_log_free(zbx_log_t *log) zbx_free(log); } -void free_result(AGENT_RESULT *result) +void zbx_free_agent_result(AGENT_RESULT *result) { ZBX_UNSET_UI64_RESULT(result); ZBX_UNSET_DBL_RESULT(result); @@ -832,7 +834,7 @@ void free_result(AGENT_RESULT *result) * Parameters: request - pointer to the structure * * * ******************************************************************************/ -void init_request(AGENT_REQUEST *request) +void zbx_init_agent_request(AGENT_REQUEST *request) { request->key = NULL; request->nparam = 0; @@ -868,7 +870,7 @@ static void free_request_params(AGENT_REQUEST *request) * Parameters: request - pointer to the request structure * * * ******************************************************************************/ -void free_request(AGENT_REQUEST *request) +void zbx_free_agent_request(AGENT_REQUEST *request) { zbx_free(request->key); free_request_params(request); @@ -904,7 +906,7 @@ static void add_request_param(AGENT_REQUEST *request, char *pvalue, zbx_request_ * Comments: thread-safe * * * ******************************************************************************/ -int parse_item_key(const char *itemkey, AGENT_REQUEST *request) +int zbx_parse_item_key(const char *itemkey, AGENT_REQUEST *request) { int i, ret = FAIL; char *key = NULL, *params = NULL; @@ -940,16 +942,16 @@ out: #undef ZBX_COMMAND_WITHOUT_PARAMS #undef ZBX_COMMAND_WITH_PARAMS -void test_parameter(const char *key) +void zbx_test_parameter(const char *key) { #define ZBX_KEY_COLUMN_WIDTH 45 AGENT_RESULT result; printf("%-*s", ZBX_KEY_COLUMN_WIDTH, key); - init_result(&result); + zbx_init_agent_result(&result); - if (SUCCEED == process(key, ZBX_PROCESS_WITH_ALIAS, &result)) + if (SUCCEED == zbx_execute_agent_check(key, ZBX_PROCESS_WITH_ALIAS, &result)) { char buffer[ZBX_MAX_DOUBLE_LEN + 1]; @@ -976,7 +978,7 @@ void test_parameter(const char *key) printf(" [m|" ZBX_NOTSUPPORTED "]"); } - free_result(&result); + zbx_free_agent_result(&result); printf("\n"); @@ -984,7 +986,7 @@ void test_parameter(const char *key) #undef ZBX_KEY_COLUMN_WIDTH } -void test_parameters(void) +void zbx_test_parameters(void) { int i; char *key = NULL; @@ -1005,8 +1007,8 @@ void test_parameters(void) zbx_chrcpy_alloc(&key, &key_alloc, &key_offset, ']'); } - if (ZBX_KEY_ACCESS_ALLOW == check_key_access_rules(key)) - test_parameter(key); + if (ZBX_KEY_ACCESS_ALLOW == zbx_check_key_access_rules(key)) + zbx_test_parameter(key); } } @@ -1104,8 +1106,6 @@ static int replace_param(const char *cmd, const AGENT_REQUEST *request, char **o /********************************************************************************** * * - * Purpose: execute agent check * - * * * Parameters: in_command - item key * * flags - ZBX_PROCESS_LOCAL_COMMAND, allow execution of system.run * * ZBX_PROCESS_MODULE_COMMAND, execute item from a module * @@ -1116,22 +1116,23 @@ static int replace_param(const char *cmd, const AGENT_REQUEST *request, char **o * result - contains item value or error message * * * **********************************************************************************/ -int process(const char *in_command, unsigned flags, AGENT_RESULT *result) +int zbx_execute_agent_check(const char *in_command, unsigned flags, AGENT_RESULT *result) { int ret = NOTSUPPORTED; ZBX_METRIC *command = NULL; AGENT_REQUEST request; - init_request(&request); + zbx_init_agent_request(&request); - if (SUCCEED != parse_item_key((0 == (flags & ZBX_PROCESS_WITH_ALIAS) ? in_command : zbx_alias_get(in_command)), - &request)) + if (SUCCEED != zbx_parse_item_key((0 == (flags & ZBX_PROCESS_WITH_ALIAS) ? in_command : + zbx_alias_get(in_command)), &request)) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid item key format.")); goto notsupported; } - if (0 == (flags & ZBX_PROCESS_LOCAL_COMMAND) && ZBX_KEY_ACCESS_ALLOW != check_request_access_rules(&request)) + if (0 == (flags & ZBX_PROCESS_LOCAL_COMMAND) && ZBX_KEY_ACCESS_ALLOW != + zbx_check_request_access_rules(&request)) { zabbix_log(LOG_LEVEL_DEBUG, "Key access denied: \"%s\"", in_command); SET_MSG_RESULT(result, zbx_strdup(NULL, "Unsupported item key.")); @@ -1220,7 +1221,7 @@ int process(const char *in_command, unsigned flags, AGENT_RESULT *result) ret = SUCCEED; notsupported: - free_request(&request); + zbx_free_agent_request(&request); return ret; } @@ -1235,7 +1236,7 @@ static void add_log_result(AGENT_RESULT *result, const char *value) result->type |= AR_LOG; } -int set_result_type(AGENT_RESULT *result, int value_type, char *c) +int zbx_set_agent_result_type(AGENT_RESULT *result, int value_type, char *c) { zbx_uint64_t value_uint64; int ret = FAIL; @@ -1285,7 +1286,7 @@ int set_result_type(AGENT_RESULT *result, int value_type, char *c) return ret; } -void set_result_meta(AGENT_RESULT *result, zbx_uint64_t lastlogsize, int mtime) +void zbx_set_agent_result_meta(AGENT_RESULT *result, zbx_uint64_t lastlogsize, int mtime) { result->lastlogsize = lastlogsize; result->mtime = mtime; @@ -1522,7 +1523,7 @@ void *get_result_value_by_type(AGENT_RESULT *result, int require_type) * "\"param\"" => "param" * * * ******************************************************************************/ -void unquote_key_param(char *param) +void zbx_unquote_key_param(char *param) { char *dst; @@ -1555,7 +1556,7 @@ void unquote_key_param(char *param) * backslash in the end * * * ******************************************************************************/ -int quote_key_param(char **param, int forced) +int zbx_quote_key_param(char **param, int forced) { size_t sz_src, sz_dst; @@ -1589,26 +1590,6 @@ int quote_key_param(char **param, int forced) return SUCCEED; } -#ifdef HAVE_KSTAT_H -zbx_uint64_t get_kstat_numeric_value(const kstat_named_t *kn) -{ - switch (kn->data_type) - { - case KSTAT_DATA_INT32: - return kn->value.i32; - case KSTAT_DATA_UINT32: - return kn->value.ui32; - case KSTAT_DATA_INT64: - return kn->value.i64; - case KSTAT_DATA_UINT64: - return kn->value.ui64; - default: - THIS_SHOULD_NEVER_HAPPEN; - return 0; - } -} -#endif - #if !defined(_WINDOWS) && !defined(__MINGW32__) #if defined(WITH_AGENT2_METRICS) int zbx_execute_threaded_metric(zbx_metric_func_t metric_func, AGENT_REQUEST *request, AGENT_RESULT *result) @@ -1731,16 +1712,16 @@ static int deserialize_agent_result(char *data, AGENT_RESULT *result) switch (type) { case 't': - ret = set_result_type(result, ITEM_VALUE_TYPE_TEXT, data); + ret = zbx_set_agent_result_type(result, ITEM_VALUE_TYPE_TEXT, data); break; case 's': - ret = set_result_type(result, ITEM_VALUE_TYPE_STR, data); + ret = zbx_set_agent_result_type(result, ITEM_VALUE_TYPE_STR, data); break; case 'u': - ret = set_result_type(result, ITEM_VALUE_TYPE_UINT64, data); + ret = zbx_set_agent_result_type(result, ITEM_VALUE_TYPE_UINT64, data); break; case 'd': - ret = set_result_type(result, ITEM_VALUE_TYPE_FLOAT, data); + ret = zbx_set_agent_result_type(result, ITEM_VALUE_TYPE_FLOAT, data); break; default: ret = SUCCEED; @@ -1805,7 +1786,7 @@ int zbx_execute_threaded_metric(zbx_metric_func_t metric_func, AGENT_REQUEST *re ret = zbx_write_all(fds[1], data, data_offset); zbx_free(data); - free_result(result); + zbx_free_agent_result(result); close(fds[1]); @@ -1891,7 +1872,7 @@ out: static ZBX_THREAD_LOCAL zbx_uint32_t mutex_flag = ZBX_MUTEX_ALL_ALLOW; -zbx_uint32_t get_thread_global_mutex_flag() +zbx_uint32_t zbx_get_thread_global_mutex_flag() { return mutex_flag; } diff --git a/src/libs/zbxsysinfo/sysinfo.h b/src/libs/zbxsysinfo/sysinfo.h index 3ac199797bf..7c2a2a59a82 100644 --- a/src/libs/zbxsysinfo/sysinfo.h +++ b/src/libs/zbxsysinfo/sysinfo.h @@ -20,6 +20,9 @@ #ifndef ZABBIX_SYSINFO_H #define ZABBIX_SYSINFO_H +#include "zbxsysinfo.h" +#include "module.h" + #define ZBX_PROC_STAT_ALL 0 #define ZBX_PROC_STAT_RUN 1 #define ZBX_PROC_STAT_SLEEP 2 @@ -74,4 +77,46 @@ #define ZBX_SYSINFO_FILE_TAG_TIME_MODIFY "modify" #define ZBX_SYSINFO_FILE_TAG_TIME_CHANGE "change" +#if defined(_WINDOWS) || defined(__MINGW32__) +typedef int (*zbx_metric_func_t)(AGENT_REQUEST *request, AGENT_RESULT *result, HANDLE timeout_event); +#else +typedef int (*zbx_metric_func_t)(AGENT_REQUEST *request, AGENT_RESULT *result); +#endif + +typedef struct +{ + zbx_uint64_t total; + zbx_uint64_t not_used; + zbx_uint64_t used; + double pfree; + double pused; +} +zbx_fs_metrics_t; + +typedef struct +{ + char fsname[MAX_STRING_LEN]; + char fstype[MAX_STRING_LEN]; + zbx_fs_metrics_t bytes; + zbx_fs_metrics_t inodes; + char *options; +} +zbx_mpoint_t; + +int zbx_execute_threaded_metric(zbx_metric_func_t metric_func, AGENT_REQUEST *request, AGENT_RESULT *result); +void zbx_mpoints_free(zbx_mpoint_t *mpoint); + +#ifndef _WINDOWS +int hostname_handle_params(AGENT_REQUEST *request, AGENT_RESULT *result, char *hostname); + +typedef struct +{ + zbx_uint64_t flag; + const char *name; +} +zbx_mntopt_t; + +char *zbx_format_mntopt_string(zbx_mntopt_t mntopts[], int flags); +#endif + #endif /* ZABBIX_SYSINFO_H */ diff --git a/src/libs/zbxsysinfo/unknown/diskio.c b/src/libs/zbxsysinfo/unknown/diskio.c index f2dd74e02a2..606ca389bc3 100644 --- a/src/libs/zbxsysinfo/unknown/diskio.c +++ b/src/libs/zbxsysinfo/unknown/diskio.c @@ -19,7 +19,7 @@ #include "zbxsysinfo.h" -int get_diskstat(const char *devname, zbx_uint64_t *dstat) +int zbx_get_diskstat(const char *devname, zbx_uint64_t *dstat) { return FAIL; } diff --git a/src/libs/zbxsysinfo/win32/diskio.c b/src/libs/zbxsysinfo/win32/diskio.c index f2dd74e02a2..606ca389bc3 100644 --- a/src/libs/zbxsysinfo/win32/diskio.c +++ b/src/libs/zbxsysinfo/win32/diskio.c @@ -19,7 +19,7 @@ #include "zbxsysinfo.h" -int get_diskstat(const char *devname, zbx_uint64_t *dstat) +int zbx_get_diskstat(const char *devname, zbx_uint64_t *dstat) { return FAIL; } diff --git a/src/libs/zbxthreads/threads.c b/src/libs/zbxthreads/threads.c index f53f74f26ea..debb07e06c0 100644 --- a/src/libs/zbxthreads/threads.c +++ b/src/libs/zbxthreads/threads.c @@ -22,20 +22,11 @@ #include "log.h" #if defined(_WINDOWS) || defined(__MINGW32__) -int zbx_win_exception_filter(unsigned int code, struct _EXCEPTION_POINTERS *ep); - static ZBX_THREAD_ENTRY(zbx_win_thread_entry, args) { - __try - { - zbx_thread_args_t *thread_args = (zbx_thread_args_t *)args; + zbx_thread_args_t *thread_args = (zbx_thread_args_t *)args; - return thread_args->entry(thread_args); - } - __except(zbx_win_exception_filter(GetExceptionCode(), GetExceptionInformation())) - { - zbx_thread_exit(EXIT_SUCCESS); - } + return thread_args->entry(thread_args); } void CALLBACK ZBXEndThread(ULONG_PTR dwParam) diff --git a/src/libs/zbxversion/version.c b/src/libs/zbxversion/version.c index 91c984d4228..4ccdd2f4406 100644 --- a/src/libs/zbxversion/version.c +++ b/src/libs/zbxversion/version.c @@ -17,33 +17,62 @@ ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. **/ -#include "version.h" +#include "zbxversion.h" #include "zbxtypes.h" +#include "zbxcommon.h" /****************************************************************************** * * - * Purpose: extracts protocol version from value * - * * - * Note: Function modifies argument 'value'! * + * Purpose: Extracts protocol version from string cont. Alphanumeric release * + * candidate version part is ignored. * * * * Parameters: * - * value - [IN] textual representation of version * + * version_str - [IN] textual representation of version * + * Example: "6.4.0alpha1", "6.4.0" or "6.4" * * * * Return value: The protocol version if it was successfully extracted, * * otherwise FAIL * * * ******************************************************************************/ -int zbx_get_component_version(char *value) +int zbx_get_component_version(const char *version_str) { - char *pminor, *ptr; + char *pmid, *plow; + char version_buf[ZBX_VERSION_BUF_LEN]; + + zbx_strlcpy(version_buf, version_str, sizeof(version_buf)); - if (NULL == (pminor = strchr(value, '.'))) + if (NULL == (pmid = strchr(version_buf, '.'))) return FAIL; - *pminor++ = '\0'; + *pmid++ = '\0'; + + if (NULL == (plow = strchr(pmid, '.'))) + return ZBX_COMPONENT_VERSION(atoi(version_buf), atoi(pmid), 0); + + *plow++ = '\0'; + + return ZBX_COMPONENT_VERSION(atoi(version_buf), atoi(pmid), atoi(plow)); +} + +/****************************************************************************** + * * + * Purpose: Extracts protocol version from string. Only the two most * + * significant groups of digits are extracted. * + * * + * Parameters: * + * value - [IN] textual representation of version * + * Example: "6.4.0alpha1" * + * * + * Return value: The protocol version if it was successfully extracted, * + * otherwise FAIL * + * * + ******************************************************************************/ +int zbx_get_component_version_without_patch(const char *value) +{ + int ver; - if (NULL != (ptr = strchr(pminor, '.'))) - *ptr = '\0'; + if (FAIL == (ver = zbx_get_component_version(value))) + return FAIL; - return ZBX_COMPONENT_VERSION(atoi(value), atoi(pminor)); + return ZBX_COMPONENT_VERSION_WITHOUT_PATCH(ver); } diff --git a/src/libs/zbxwin32/fatal.c b/src/libs/zbxwin32/fatal.c index e4923f5f2ec..9e040c6dca5 100644 --- a/src/libs/zbxwin32/fatal.c +++ b/src/libs/zbxwin32/fatal.c @@ -231,10 +231,10 @@ static void print_backtrace(CONTEXT *pctx) zbx_free(pSym); } -int zbx_win_exception_filter(unsigned int code, struct _EXCEPTION_POINTERS *ep) +int zbx_win_exception_filter(struct _EXCEPTION_POINTERS *ep) { - zabbix_log(LOG_LEVEL_CRIT, "Unhandled exception %x detected at 0x%p. Crashing ...", code, - ep->ExceptionRecord->ExceptionAddress); + zabbix_log(LOG_LEVEL_CRIT, "Unhandled exception %x detected at 0x%p. Crashing ...", + ep->ExceptionRecord->ExceptionCode, ep->ExceptionRecord->ExceptionAddress); print_fatal_info(ep->ContextRecord); print_backtrace(ep->ContextRecord); diff --git a/src/libs/zbxwin32/service.c b/src/libs/zbxwin32/service.c index 503ab50d729..af9ce932f73 100644 --- a/src/libs/zbxwin32/service.c +++ b/src/libs/zbxwin32/service.c @@ -78,6 +78,19 @@ static VOID WINAPI ServiceCtrlHandler(DWORD ctrlCode) switch (ctrlCode) { case SERVICE_CONTROL_STOP: + zabbix_log(LOG_LEVEL_INFORMATION, "Zabbix Agent received stop request."); + break; + case SERVICE_CONTROL_SHUTDOWN: + zabbix_log(LOG_LEVEL_INFORMATION, "Zabbix Agent received shutdown request."); + break; + default: + zabbix_log(LOG_LEVEL_DEBUG, "Zabbix Agent received request:%u.", ctrlCode); + break; + } + + switch (ctrlCode) + { + case SERVICE_CONTROL_STOP: case SERVICE_CONTROL_SHUTDOWN: serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; serviceStatus.dwWaitHint = 4000; diff --git a/src/zabbix_agent/active.c b/src/zabbix_agent/active.c index 979e3e1f85f..2be2e632cfb 100644 --- a/src/zabbix_agent/active.c +++ b/src/zabbix_agent/active.c @@ -272,16 +272,16 @@ static int mode_parameter_is_skip(unsigned char flags, const char *itemkey) else /* log.count[] */ max_num_parameters = 6; - init_request(&request); + zbx_init_agent_request(&request); - if (SUCCEED == parse_item_key(itemkey, &request) && 0 < get_rparams_num(&request) && + if (SUCCEED == zbx_parse_item_key(itemkey, &request) && 0 < get_rparams_num(&request) && max_num_parameters >= get_rparams_num(&request) && NULL != (skip = get_rparam(&request, 4)) && 0 == strcmp(skip, "skip")) { ret = SUCCEED; } - free_request(&request); + zbx_free_agent_request(&request); return ret; } @@ -559,9 +559,9 @@ static void process_config_item(struct zbx_json *json, char *config, size_t leng config_type = "interface"; } - init_result(&result); + zbx_init_agent_result(&result); - if (SUCCEED == process(config, ZBX_PROCESS_LOCAL_COMMAND | ZBX_PROCESS_WITH_ALIAS, &result) && + if (SUCCEED == zbx_execute_agent_check(config, ZBX_PROCESS_LOCAL_COMMAND | ZBX_PROCESS_WITH_ALIAS, &result) && NULL != (value = ZBX_GET_STR_RESULT(&result)) && NULL != *value) { if (SUCCEED != zbx_is_utf8(*value)) @@ -590,7 +590,7 @@ static void process_config_item(struct zbx_json *json, char *config, size_t leng zabbix_log(LOG_LEVEL_WARNING, "cannot get host %s using \"%s\" item specified by" " \"%s\" configuration parameter",config_type, config,config_name); - free_result(&result); + zbx_free_agent_result(&result); } /****************************************************************************** @@ -1159,9 +1159,9 @@ static int process_common_check(zbx_vector_ptr_t *addrs, ZBX_ACTIVE_METRIC *metr AGENT_RESULT result; char **pvalue; - init_result(&result); + zbx_init_agent_result(&result); - if (SUCCEED != (ret = process(metric->key, 0, &result))) + if (SUCCEED != (ret = zbx_execute_agent_check(metric->key, 0, &result))) { if (NULL != (pvalue = ZBX_GET_MSG_RESULT(&result))) *error = zbx_strdup(*error, *pvalue); @@ -1176,7 +1176,7 @@ static int process_common_check(zbx_vector_ptr_t *addrs, ZBX_ACTIVE_METRIC *metr NULL, NULL, NULL, NULL, metric->flags, zbx_config_tls); } out: - free_result(&result); + zbx_free_agent_result(&result); return ret; } diff --git a/src/zabbix_agent/diskdevices.c b/src/zabbix_agent/diskdevices.c index 32efdb0c9df..1dc9aa7c324 100644 --- a/src/zabbix_agent/diskdevices.c +++ b/src/zabbix_agent/diskdevices.c @@ -102,7 +102,7 @@ static void process_diskstat(ZBX_SINGLE_DISKDEVICE_DATA *device) zbx_uint64_t dstat[ZBX_DSTAT_MAX]; now = time(NULL); - if (FAIL == get_diskstat(device->name, dstat)) + if (FAIL == zbx_get_diskstat(device->name, dstat)) return; apply_diskstat(device, now, dstat); diff --git a/src/zabbix_agent/eventlog.c b/src/zabbix_agent/eventlog.c index d9adfae948f..9797537654b 100644 --- a/src/zabbix_agent/eventlog.c +++ b/src/zabbix_agent/eventlog.c @@ -1701,9 +1701,9 @@ int process_eventlog_check(zbx_vector_ptr_t *addrs, zbx_vector_ptr_t *agent2_res int rate; OSVERSIONINFO versionInfo; - init_request(&request); + zbx_init_agent_request(&request); - if (SUCCEED != parse_item_key(metric->key, &request)) + if (SUCCEED != zbx_parse_item_key(metric->key, &request)) { *error = zbx_strdup(*error, "Invalid item key format."); goto out; @@ -1827,7 +1827,7 @@ int process_eventlog_check(zbx_vector_ptr_t *addrs, zbx_vector_ptr_t *agent2_res error); } out: - free_request(&request); + zbx_free_agent_request(&request); return ret; } diff --git a/src/zabbix_agent/listener.c b/src/zabbix_agent/listener.c index d75a3b5d0a7..230d46f980a 100644 --- a/src/zabbix_agent/listener.c +++ b/src/zabbix_agent/listener.c @@ -50,9 +50,9 @@ static void process_listener(zbx_socket_t *s) zabbix_log(LOG_LEVEL_DEBUG, "Requested [%s]", s->buffer); - init_result(&result); + zbx_init_agent_result(&result); - if (SUCCEED == process(s->buffer, ZBX_PROCESS_WITH_ALIAS, &result)) + if (SUCCEED == zbx_execute_agent_check(s->buffer, ZBX_PROCESS_WITH_ALIAS, &result)) { if (NULL != (value = ZBX_GET_TEXT_RESULT(&result))) { @@ -90,7 +90,7 @@ static void process_listener(zbx_socket_t *s) } } - free_result(&result); + zbx_free_agent_result(&result); } if (FAIL == ret) @@ -126,7 +126,7 @@ ZBX_THREAD_ENTRY(listener_thread, args) get_program_type_string(init_child_args_in->zbx_get_program_type_cb_arg()), server_num, get_process_type_string(process_type), process_num); - memcpy(&s, (zbx_socket_t *)(init_child_args_in->listen_sock), sizeof(zbx_socket_t)); + memcpy(&s, init_child_args_in->listen_sock, sizeof(zbx_socket_t)); zbx_free(args); diff --git a/src/zabbix_agent/logfiles/logfiles.c b/src/zabbix_agent/logfiles/logfiles.c index 0f632cd7d19..475855af795 100644 --- a/src/zabbix_agent/logfiles/logfiles.c +++ b/src/zabbix_agent/logfiles/logfiles.c @@ -3850,7 +3850,7 @@ int process_log_check(zbx_vector_ptr_t *addrs, zbx_vector_ptr_t *agent2_result, else is_count_item = 0; - init_request(&request); + zbx_init_agent_request(&request); /* Expected parameters by item: */ /* log [file, <regexp>,<encoding>,<maxlines>, <mode>,<output>,<maxdelay>, <options>,<persistent_dir>] 9 params */ @@ -3858,7 +3858,7 @@ int process_log_check(zbx_vector_ptr_t *addrs, zbx_vector_ptr_t *agent2_result, /* logrt [file_regexp,<regexp>,<encoding>,<maxlines>, <mode>,<output>,<maxdelay>, <options>,<persistent_dir>] 9 params */ /* logrt.count[file_regexp,<regexp>,<encoding>,<maxproclines>,<mode>, <maxdelay>, <options>,<persistent_dir>] 8 params */ - if (SUCCEED != parse_item_key(metric->key, &request)) + if (SUCCEED != zbx_parse_item_key(metric->key, &request)) { *error = zbx_strdup(*error, "Invalid item key format."); goto out; @@ -4146,7 +4146,7 @@ int process_log_check(zbx_vector_ptr_t *addrs, zbx_vector_ptr_t *agent2_result, } out: zbx_free(encoding_uc); - free_request(&request); + zbx_free_agent_request(&request); return ret; } diff --git a/src/zabbix_agent/zabbix_agentd.c b/src/zabbix_agent/zabbix_agentd.c index 30094fe19c1..ff4d1877c13 100644 --- a/src/zabbix_agent/zabbix_agentd.c +++ b/src/zabbix_agent/zabbix_agentd.c @@ -24,6 +24,7 @@ #include "modbtype.h" #include "zbxstr.h" #include "zbxip.h" +#include "zbxexpr.h" static char *CONFIG_PID_FILE = NULL; @@ -261,7 +262,6 @@ int CONFIG_JAVAPOLLER_FORKS = 0; int CONFIG_ESCALATOR_FORKS = 0; int CONFIG_SELFMON_FORKS = 0; int CONFIG_DATASENDER_FORKS = 0; -int CONFIG_HEARTBEAT_FORKS = 0; int CONFIG_PROXYPOLLER_FORKS = 0; int CONFIG_HISTSYNCER_FORKS = 0; int CONFIG_CONFSYNCER_FORKS = 0; @@ -286,6 +286,7 @@ char *opt = NULL; #ifdef _WINDOWS void zbx_co_uninitialize(); +int zbx_win_exception_filter(struct _EXCEPTION_POINTERS *ep); #endif int get_process_info_by_thread(int local_server_num, unsigned char *local_process_type, int *local_process_num); @@ -554,10 +555,10 @@ static void set_defaults(void) if (NULL == CONFIG_HOSTNAME_ITEM) CONFIG_HOSTNAME_ITEM = zbx_strdup(CONFIG_HOSTNAME_ITEM, "system.hostname"); - init_result(&result); + zbx_init_agent_result(&result); - if (SUCCEED == process(CONFIG_HOSTNAME_ITEM, ZBX_PROCESS_LOCAL_COMMAND | ZBX_PROCESS_WITH_ALIAS, - &result) && NULL != (value = ZBX_GET_STR_RESULT(&result))) + if (SUCCEED == zbx_execute_agent_check(CONFIG_HOSTNAME_ITEM, ZBX_PROCESS_LOCAL_COMMAND | + ZBX_PROCESS_WITH_ALIAS, &result) && NULL != (value = ZBX_GET_STR_RESULT(&result))) { assert(*value); zbx_trim_str_list(*value, ','); @@ -573,7 +574,7 @@ static void set_defaults(void) else zabbix_log(LOG_LEVEL_WARNING, "failed to get system hostname from [%s])", CONFIG_HOSTNAME_ITEM); - free_result(&result); + zbx_free_agent_result(&result); } else if (NULL != CONFIG_HOSTNAME_ITEM) zabbix_log(LOG_LEVEL_WARNING, "both Hostname and HostnameItem defined, using [%s]", CONFIG_HOSTNAMES); @@ -800,7 +801,7 @@ static int load_enable_remote_commands(const char *value, const struct cfg_line zabbix_log(LOG_LEVEL_WARNING, "EnableRemoteCommands parameter is deprecated," " use AllowKey=system.run[*] or DenyKey=system.run[*] instead"); - return add_key_access_rule(cfg->parameter, sysrun, rule_type); + return zbx_add_key_access_rule(cfg->parameter, sysrun, rule_type); } /****************************************************************************** @@ -955,7 +956,7 @@ static void zbx_load_config(int requirement, ZBX_TASK_EX *task) #endif parse_cfg_file(CONFIG_FILE, cfg, requirement, ZBX_CFG_STRICT, ZBX_CFG_EXIT_FAILURE); - finalize_key_access_rules_configuration(); + zbx_finalize_key_access_rules_configuration(); set_defaults(); @@ -1079,6 +1080,8 @@ int MAIN_ZABBIX_ENTRY(int flags) int i, j = 0, ret = SUCCEED; #ifdef _WINDOWS DWORD res; + + AddVectoredExceptionHandler(1, (PVECTORED_EXCEPTION_HANDLER)&zbx_win_exception_filter); #endif if (0 != (flags & ZBX_TASK_FLAG_FOREGROUND)) { @@ -1305,7 +1308,7 @@ void zbx_free_service_resources(int ret) #ifdef HAVE_PTHREAD_PROCESS_SHARED zbx_locks_disable(); #endif - free_metrics(); + zbx_free_metrics(); zbx_alias_list_free(); free_collector_data(); zbx_deinit_modbus(); @@ -1361,7 +1364,7 @@ int main(int argc, char **argv) #endif /* this is needed to set default hostname in zbx_load_config() */ - init_metrics(); + zbx_init_metrics(); switch (t.task) { @@ -1404,7 +1407,7 @@ int main(int argc, char **argv) while (0 == WSACleanup()) ; - free_metrics(); + zbx_free_metrics(); exit(SUCCEED == ret ? EXIT_SUCCESS : EXIT_FAILURE); break; #endif @@ -1430,7 +1433,7 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } #endif - set_user_parameter_dir(CONFIG_USER_PARAMETER_DIR); + zbx_set_user_parameter_dir(CONFIG_USER_PARAMETER_DIR); if (FAIL == load_user_parameters(CONFIG_USER_PARAMETERS, &error)) { @@ -1442,9 +1445,9 @@ int main(int argc, char **argv) load_aliases(CONFIG_ALIASES); zbx_free_config(); if (ZBX_TASK_TEST_METRIC == t.task) - test_parameter(TEST_METRIC); + zbx_test_parameter(TEST_METRIC); else - test_parameters(); + zbx_test_parameters(); #ifdef _WINDOWS free_perf_collector(); /* cpu_collector must be freed before perf_collector is freed */ @@ -1456,7 +1459,7 @@ int main(int argc, char **argv) #ifndef _WINDOWS zbx_unload_modules(); #endif - free_metrics(); + zbx_free_metrics(); zbx_alias_list_free(); exit(EXIT_SUCCESS); break; @@ -1478,7 +1481,7 @@ int main(int argc, char **argv) break; default: zbx_load_config(ZBX_CFG_FILE_REQUIRED, &t); - set_user_parameter_dir(CONFIG_USER_PARAMETER_DIR); + zbx_set_user_parameter_dir(CONFIG_USER_PARAMETER_DIR); load_aliases(CONFIG_ALIASES); break; } diff --git a/src/zabbix_agent/zbxconf.c b/src/zabbix_agent/zbxconf.c index 9dbe6a18c7c..1b406cb8ad7 100644 --- a/src/zabbix_agent/zbxconf.c +++ b/src/zabbix_agent/zbxconf.c @@ -23,6 +23,7 @@ #include "zbxsysinfo.h" #include "zbxstr.h" #include "zbxparam.h" +#include "zbxexpr.h" #ifdef _WINDOWS # include "perfstat.h" @@ -46,7 +47,7 @@ void load_aliases(char **lines) char *c; const char *r = *pline; - if (SUCCEED != parse_key(&r) || ':' != *r) + if (SUCCEED != zbx_parse_key(&r) || ':' != *r) { zabbix_log(LOG_LEVEL_CRIT, "cannot add alias \"%s\": invalid character at position %d", *pline, (int)((r - *pline) + 1)); @@ -55,7 +56,7 @@ void load_aliases(char **lines) c = (char *)r++; - if (SUCCEED != parse_key(&r) || '\0' != *r) + if (SUCCEED != zbx_parse_key(&r) || '\0' != *r) { zabbix_log(LOG_LEVEL_CRIT, "cannot add alias \"%s\": invalid character at position %d", *pline, (int)((r - *pline) + 1)); @@ -80,7 +81,7 @@ void load_aliases(char **lines) * Return value: SUCCEED - successfully loaded user parameters * * FAIL - failed to load user parameters * * * - * Comments: calls add_user_parameter() for each entry * + * Comments: calls zbx_add_user_parameter() for each entry * * * ******************************************************************************/ int load_user_parameters(char **lines, char **err) @@ -96,7 +97,7 @@ int load_user_parameters(char **lines, char **err) } *p = '\0'; - if (FAIL == add_user_parameter(*pline, p + 1, error, sizeof(error))) + if (FAIL == zbx_add_user_parameter(*pline, p + 1, error, sizeof(error))) { *p = ','; *err = zbx_dsprintf(*err, "user parameter \"%s\": %s", *pline, error); @@ -130,7 +131,7 @@ int load_key_access_rule(const char *value, const struct cfg_line *cfg) else return FAIL; - return add_key_access_rule(cfg->parameter, (char *)value, rule_type); + return zbx_add_key_access_rule(cfg->parameter, (char *)value, rule_type); } #ifdef _WINDOWS @@ -259,19 +260,19 @@ void reload_user_parameters(unsigned char process_type, int process_num) goto out; } - get_metrics_copy(&metrics_fallback); - remove_user_parameters(); + zbx_get_metrics_copy(&metrics_fallback); + zbx_remove_user_parameters(); if (FAIL == load_user_parameters(CONFIG_USER_PARAMETERS, &error)) { - set_metrics(metrics_fallback); + zbx_set_metrics(metrics_fallback); zabbix_log(LOG_LEVEL_ERR, "cannot reload user parameters [%s #%d], %s", get_process_type_string(process_type), process_num, error); zbx_free(error); goto out; } - free_metrics_ext(&metrics_fallback); + zbx_free_metrics_ext(&metrics_fallback); zabbix_log(LOG_LEVEL_INFORMATION, "user parameters reloaded [%s #%d]", get_process_type_string(process_type), process_num); out: diff --git a/src/zabbix_java/src/com/zabbix/gateway/GeneralInformation.java b/src/zabbix_java/src/com/zabbix/gateway/GeneralInformation.java index 80855ec682e..89f4a89ea14 100644 --- a/src/zabbix_java/src/com/zabbix/gateway/GeneralInformation.java +++ b/src/zabbix_java/src/com/zabbix/gateway/GeneralInformation.java @@ -22,9 +22,9 @@ package com.zabbix.gateway; class GeneralInformation { static final String APPLICATION_NAME = "Zabbix Java Gateway"; - static final String REVISION_DATE = "14 September 2022"; + static final String REVISION_DATE = "29 September 2022"; static final String REVISION = "{ZABBIX_REVISION}"; - static final String VERSION = "6.4.0alpha2"; + static final String VERSION = "6.4.0beta2"; static void printVersion() { diff --git a/src/zabbix_proxy/Makefile.am b/src/zabbix_proxy/Makefile.am index c905ae3dc3a..fbe48e46723 100644 --- a/src/zabbix_proxy/Makefile.am +++ b/src/zabbix_proxy/Makefile.am @@ -2,12 +2,12 @@ SUBDIRS = \ diag \ - heart \ housekeeper \ proxyconfig \ datasender \ stats \ - taskmanager + taskmanager \ + proxyconfigwrite sbin_PROGRAMS = zabbix_proxy @@ -25,7 +25,6 @@ zabbix_proxy_SOURCES = proxy.c zabbix_proxy_LDADD = \ diag/libzbxdiag_proxy.a \ - heart/libzbxheart.a \ $(top_builddir)/src/zabbix_server/dbsyncer/libzbxdbsyncer.a \ $(top_builddir)/src/zabbix_server/discoverer/libzbxdiscoverer.a \ housekeeper/libzbxhousekeeper.a \ @@ -39,6 +38,7 @@ zabbix_proxy_LDADD = \ $(top_builddir)/src/zabbix_server/snmptrapper/libzbxsnmptrapper.a \ $(top_builddir)/src/zabbix_server/odbc/libzbxodbc.a \ datasender/libzbxdatasender.a \ + proxyconfigwrite/libzbxproxyconfigwrite.a \ $(top_builddir)/src/zabbix_server/preprocessor/libpreprocessor.a \ $(top_builddir)/src/libs/zbxvariant/libzbxvariant.a \ $(top_builddir)/src/libs/zbxxml/libzbxxml.a \ diff --git a/src/zabbix_proxy/datasender/datasender.c b/src/zabbix_proxy/datasender/datasender.c index f17ba9982b9..cf47e50b201 100644 --- a/src/zabbix_proxy/datasender/datasender.c +++ b/src/zabbix_proxy/datasender/datasender.c @@ -141,7 +141,7 @@ static int proxy_data_sender(int *more, int now, int *hist_upload_state, time_t { task_timestamp = now; - zbx_tm_get_remote_tasks(&tasks, 0); + zbx_tm_get_remote_tasks(&tasks, 0, 0); if (0 != tasks.values_num) { @@ -184,20 +184,20 @@ static int proxy_data_sender(int *more, int now, int *hist_upload_state, time_t reserved = j.buffer_size; zbx_json_free(&j); /* json buffer can be large, free as fast as possible */ - update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); /* retry till have a connection */ if (FAIL == zbx_connect_to_server(&sock, CONFIG_SOURCE_IP, &zbx_addrs, 600, CONFIG_TIMEOUT, CONFIG_PROXYDATA_FREQUENCY, LOG_LEVEL_WARNING, zbx_config_tls)) { - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); if (*last_conn_time + ZBX_PROXY_ACTIVE_CHECK_AVAIL_TIMEOUT >= time(NULL)) zbx_availability_send(ZBX_IPC_AVAILMAN_PROXY_FLUSH_ALL_HOSTS, NULL, 0, NULL); goto clean; } - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); upload_state = zbx_put_data_to_server(&sock, &buffer, buffer_size, reserved, &error); get_hist_upload_state(sock.buffer, hist_upload_state); @@ -306,7 +306,7 @@ ZBX_THREAD_ENTRY(datasender_thread, args) get_program_type_string(datasender_args_in->zbx_get_program_type_cb_arg()), server_num, get_process_type_string(process_type), process_num); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) zbx_tls_init_child(datasender_args_in->zbx_config_tls, datasender_args_in->zbx_get_program_type_cb_arg); diff --git a/src/zabbix_proxy/heart/Makefile.am b/src/zabbix_proxy/heart/Makefile.am deleted file mode 100644 index a96da81e936..00000000000 --- a/src/zabbix_proxy/heart/Makefile.am +++ /dev/null @@ -1,7 +0,0 @@ -## Process this file with automake to produce Makefile.in - -noinst_LIBRARIES = libzbxheart.a - -libzbxheart_a_SOURCES = \ - heart.c \ - heart.h diff --git a/src/zabbix_proxy/heart/heart.c b/src/zabbix_proxy/heart/heart.c deleted file mode 100644 index 81c18200274..00000000000 --- a/src/zabbix_proxy/heart/heart.c +++ /dev/null @@ -1,165 +0,0 @@ -/* -** Zabbix -** Copyright (C) 2001-2022 Zabbix SIA -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -**/ - -#include "heart.h" - -#include "zbxnix.h" -#include "log.h" -#include "zbxjson.h" -#include "zbxself.h" -#include "zbxtime.h" - -#include "zbxcompress.h" -#include "zbxcommshigh.h" - -extern ZBX_THREAD_LOCAL unsigned char process_type; -extern ZBX_THREAD_LOCAL int server_num, process_num; - -extern zbx_vector_ptr_t zbx_addrs; -extern char *CONFIG_HOSTNAME; -extern char *CONFIG_SOURCE_IP; -extern int CONFIG_TIMEOUT; - -static int send_heartbeat(const zbx_config_tls_t *zbx_config_tls) -{ - zbx_socket_t sock; - struct zbx_json j; - int ret = SUCCEED; - char *error = NULL, *buffer = NULL; - size_t buffer_size, reserved; - - zabbix_log(LOG_LEVEL_DEBUG, "In send_heartbeat()"); - - zbx_json_init(&j, 128); - zbx_json_addstring(&j, "request", ZBX_PROTO_VALUE_PROXY_HEARTBEAT, ZBX_JSON_TYPE_STRING); - zbx_json_addstring(&j, "host", CONFIG_HOSTNAME, ZBX_JSON_TYPE_STRING); - zbx_json_addstring(&j, ZBX_PROTO_TAG_VERSION, ZABBIX_VERSION, ZBX_JSON_TYPE_STRING); - - if (SUCCEED != zbx_compress(j.buffer, j.buffer_size, &buffer, &buffer_size)) - { - zabbix_log(LOG_LEVEL_ERR,"cannot compress data: %s", zbx_compress_strerror()); - goto clean; - } - - reserved = j.buffer_size; - - if (FAIL == (ret = zbx_connect_to_server(&sock, CONFIG_SOURCE_IP, &zbx_addrs, CONFIG_HEARTBEAT_FREQUENCY, - CONFIG_TIMEOUT, 0, LOG_LEVEL_DEBUG, zbx_config_tls))) /* do not retry */ - { - goto clean; - } - - if (SUCCEED != (ret = zbx_put_data_to_server(&sock, &buffer, buffer_size, reserved, &error))) - { - zabbix_log(LOG_LEVEL_WARNING, "cannot send heartbeat message to server at \"%s\": %s", sock.peer, - error); - } - - zbx_disconnect_from_server(&sock); - zbx_free(error); -clean: - zbx_free(buffer); - zbx_json_free(&j); - - return ret; -} - -/****************************************************************************** - * * - * Purpose: periodically send heartbeat message to the server * - * * - ******************************************************************************/ -ZBX_THREAD_ENTRY(heart_thread, args) -{ - zbx_thread_heart_args *heart_args_in = (zbx_thread_heart_args *) (((zbx_thread_args_t *)args)->args); - int start, sleeptime = 0, res; - double sec, total_sec = 0.0, old_total_sec = 0.0; - time_t last_stat_time; - -#define STAT_INTERVAL 5 /* if a process is busy and does not sleep then update status not faster than */ - /* once in STAT_INTERVAL seconds */ - - process_type = ((zbx_thread_args_t *)args)->process_type; - server_num = ((zbx_thread_args_t *)args)->server_num; - process_num = ((zbx_thread_args_t *)args)->process_num; - - zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", - get_program_type_string(heart_args_in->zbx_get_program_type_cb_arg()), - server_num, get_process_type_string(process_type), process_num); - - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); - -#if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) - zbx_tls_init_child(heart_args_in->zbx_config_tls, heart_args_in->zbx_get_program_type_cb_arg); -#endif - last_stat_time = time(NULL); - - zbx_setproctitle("%s [sending heartbeat message]", get_process_type_string(process_type)); - - while (ZBX_IS_RUNNING()) - { - sec = zbx_time(); - zbx_update_env(sec); - - if (0 != sleeptime) - { - zbx_setproctitle("%s [sending heartbeat message %s in " ZBX_FS_DBL " sec, " - "sending heartbeat message]", - get_process_type_string(process_type), - SUCCEED == res ? "success" : "failed", old_total_sec); - } - - start = time(NULL); - res = send_heartbeat(heart_args_in->zbx_config_tls); - total_sec += zbx_time() - sec; - - sleeptime = CONFIG_HEARTBEAT_FREQUENCY - (time(NULL) - start); - - if (0 != sleeptime || STAT_INTERVAL <= time(NULL) - last_stat_time) - { - if (0 == sleeptime) - { - zbx_setproctitle("%s [sending heartbeat message %s in " ZBX_FS_DBL " sec, " - "sending heartbeat message]", - get_process_type_string(process_type), - SUCCEED == res ? "success" : "failed", total_sec); - - } - else - { - zbx_setproctitle("%s [sending heartbeat message %s in " ZBX_FS_DBL " sec, " - "idle %d sec]", - get_process_type_string(process_type), - SUCCEED == res ? "success" : "failed", total_sec, sleeptime); - - old_total_sec = total_sec; - } - total_sec = 0.0; - last_stat_time = time(NULL); - } - - zbx_sleep_loop(sleeptime); - } - - zbx_setproctitle("%s #%d [terminated]", get_process_type_string(process_type), process_num); - - while (1) - zbx_sleep(SEC_PER_MIN); -#undef STAT_INTERVAL -} diff --git a/src/zabbix_proxy/housekeeper/housekeeper.c b/src/zabbix_proxy/housekeeper/housekeeper.c index e58fbd65d79..263d0eb1011 100644 --- a/src/zabbix_proxy/housekeeper/housekeeper.c +++ b/src/zabbix_proxy/housekeeper/housekeeper.c @@ -156,7 +156,7 @@ ZBX_THREAD_ENTRY(housekeeper_thread, args) zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(program_type), server_num, get_process_type_string(process_type), process_num); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); if (0 == CONFIG_HOUSEKEEPING_FREQUENCY) { diff --git a/src/zabbix_proxy/proxy.c b/src/zabbix_proxy/proxy.c index 93a983a4ec4..2c7e09d6fd0 100644 --- a/src/zabbix_proxy/proxy.c +++ b/src/zabbix_proxy/proxy.c @@ -43,7 +43,6 @@ #include "../zabbix_server/snmptrapper/snmptrapper.h" #include "proxyconfig/proxyconfig.h" #include "datasender/datasender.h" -#include "heart/heart.h" #include "taskmanager/taskmanager.h" #include "../zabbix_server/selfmon/selfmon.h" #include "../zabbix_server/vmware/vmware.h" @@ -58,7 +57,7 @@ #include "diag/diag_proxy.h" #include "zbxrtc.h" #include "../zabbix_server/availability/avail_manager.h" -#include "zbxserver.h" +#include "zbxstats.h" #include "stats/zabbix_stats.h" #include "zbxip.h" @@ -103,9 +102,9 @@ const char *help_message[] = { " Log level control targets:", " process-type All processes of specified type", " (configuration syncer, data sender, discoverer,", - " heartbeat sender, history syncer, housekeeper,", - " http poller, icmp pinger, ipmi manager,", - " ipmi poller, java poller, poller,", + " history syncer, housekeeper, http poller,", + " icmp pinger, ipmi manager, ipmi poller,", + " java poller, poller,", " self-monitoring, snmp trapper, task manager,", " trapper, unreachable poller, vmware collector," " availability manager, odbc poller)", @@ -175,7 +174,6 @@ int CONFIG_PROXYPOLLER_FORKS = 0; int CONFIG_ESCALATOR_FORKS = 0; int CONFIG_ALERTER_FORKS = 0; int CONFIG_TIMER_FORKS = 0; -int CONFIG_HEARTBEAT_FORKS = 1; int CONFIG_COLLECTOR_FORKS = 0; int CONFIG_PASSIVE_FORKS = 0; int CONFIG_ACTIVE_FORKS = 0; @@ -202,15 +200,16 @@ int CONFIG_HOUSEKEEPING_FREQUENCY = 1; int CONFIG_PROXY_LOCAL_BUFFER = 0; int CONFIG_PROXY_OFFLINE_BUFFER = 1; -int CONFIG_HEARTBEAT_FREQUENCY = 60; +int CONFIG_HEARTBEAT_FREQUENCY = -1; /* how often active Zabbix proxy requests configuration data from server, in seconds */ -int CONFIG_PROXYCONFIG_FREQUENCY = SEC_PER_MIN * 5; +int CONFIG_PROXYCONFIG_FREQUENCY = 0; /* will be set to default 5 seconds if not configured */ int CONFIG_PROXYDATA_FREQUENCY = 1; int CONFIG_HISTSYNCER_FORKS = 4; int CONFIG_HISTSYNCER_FREQUENCY = 1; int CONFIG_CONFSYNCER_FORKS = 1; +int CONFIG_CONFSYNCER_FREQUENCY = 0; int CONFIG_VMWARE_FORKS = 0; int CONFIG_VMWARE_FREQUENCY = 60; @@ -336,11 +335,6 @@ int get_process_info_by_thread(int local_server_num, unsigned char *local_proces *local_process_type = ZBX_PROCESS_TYPE_PREPROCESSOR; *local_process_num = local_server_num - server_count + CONFIG_PREPROCESSOR_FORKS; } - else if (local_server_num <= (server_count += CONFIG_HEARTBEAT_FORKS)) - { - *local_process_type = ZBX_PROCESS_TYPE_HEARTBEAT; - *local_process_num = local_server_num - server_count + CONFIG_HEARTBEAT_FORKS; - } else if (local_server_num <= (server_count += CONFIG_DATASENDER_FORKS)) { *local_process_type = ZBX_PROCESS_TYPE_DATASENDER; @@ -449,9 +443,9 @@ static void zbx_set_defaults(void) if (NULL == CONFIG_HOSTNAME_ITEM) CONFIG_HOSTNAME_ITEM = zbx_strdup(CONFIG_HOSTNAME_ITEM, "system.hostname"); - init_result(&result); + zbx_init_agent_result(&result); - if (SUCCEED == process(CONFIG_HOSTNAME_ITEM, ZBX_PROCESS_LOCAL_COMMAND, &result) && + if (SUCCEED == zbx_execute_agent_check(CONFIG_HOSTNAME_ITEM, ZBX_PROCESS_LOCAL_COMMAND, &result) && NULL != (value = ZBX_GET_STR_RESULT(&result))) { assert(*value); @@ -467,7 +461,7 @@ static void zbx_set_defaults(void) else zabbix_log(LOG_LEVEL_WARNING, "failed to get proxy name from [%s])", CONFIG_HOSTNAME_ITEM); - free_result(&result); + zbx_free_agent_result(&result); } else if (NULL != CONFIG_HOSTNAME_ITEM) { @@ -504,9 +498,6 @@ static void zbx_set_defaults(void) if (NULL == CONFIG_SSL_KEY_LOCATION) CONFIG_SSL_KEY_LOCATION = zbx_strdup(CONFIG_SSL_KEY_LOCATION, DEFAULT_SSL_KEY_LOCATION); #endif - if (ZBX_PROXYMODE_ACTIVE != CONFIG_PROXYMODE || 0 == CONFIG_HEARTBEAT_FREQUENCY) - CONFIG_HEARTBEAT_FORKS = 0; - if (ZBX_PROXYMODE_PASSIVE == CONFIG_PROXYMODE) { CONFIG_DATASENDER_FORKS = 0; @@ -525,6 +516,9 @@ static void zbx_set_defaults(void) if (NULL == CONFIG_VAULTURL) CONFIG_VAULTURL = zbx_strdup(CONFIG_VAULTURL, "https://127.0.0.1:8200"); + if (-1 != CONFIG_HEARTBEAT_FREQUENCY) + zabbix_log(LOG_LEVEL_WARNING, "HeartbeatFrequency parameter is deprecated, and has no effect"); + if (0 == CONFIG_SERVER_PORT) { CONFIG_SERVER_PORT = ZBX_DEFAULT_SERVER_PORT; @@ -655,6 +649,25 @@ static void zbx_validate_config(ZBX_TASK_EX *task) #if !defined(HAVE_OPENIPMI) err |= (FAIL == check_cfg_feature_int("StartIPMIPollers", CONFIG_IPMIPOLLER_FORKS, "IPMI support")); #endif + if (0 != CONFIG_CONFSYNCER_FREQUENCY) + { + if (0 != CONFIG_PROXYCONFIG_FREQUENCY) + { + zabbix_log(LOG_LEVEL_CRIT, "Deprecated \"ConfigFrequency\" configuration parameter cannot" + " be used together with \"ProxyConfigFrequency\" parameter"); + err = 1; + } + else + { + CONFIG_PROXYCONFIG_FREQUENCY = CONFIG_CONFSYNCER_FREQUENCY; + zabbix_log(LOG_LEVEL_WARNING, "\"ConfigFrequency\" configuration parameter is deprecated, " + "use \"ProxyConfigFrequency\" instead"); + } + } + + /* assign default ProxyConfigFrequency value if not configured */ + if (0 == CONFIG_PROXYCONFIG_FREQUENCY) + CONFIG_PROXYCONFIG_FREQUENCY = 10; err |= (FAIL == zbx_db_validate_config_features()); @@ -735,7 +748,9 @@ static void zbx_load_config(ZBX_TASK_EX *task) PARM_OPT, 1, 720}, {"HeartbeatFrequency", &CONFIG_HEARTBEAT_FREQUENCY, TYPE_INT, PARM_OPT, 0, ZBX_PROXY_HEARTBEAT_FREQUENCY_MAX}, - {"ConfigFrequency", &CONFIG_PROXYCONFIG_FREQUENCY, TYPE_INT, + {"ConfigFrequency", &CONFIG_CONFSYNCER_FREQUENCY, TYPE_INT, + PARM_OPT, 1, SEC_PER_WEEK}, + {"ProxyConfigFrequency", &CONFIG_PROXYCONFIG_FREQUENCY, TYPE_INT, PARM_OPT, 1, SEC_PER_WEEK}, {"DataSenderFrequency", &CONFIG_PROXYDATA_FREQUENCY, TYPE_INT, PARM_OPT, 1, SEC_PER_HOUR}, @@ -956,7 +971,7 @@ static void zbx_on_exit(int ret) #ifdef HAVE_PTHREAD_PROCESS_SHARED zbx_locks_disable(); #endif - free_metrics(); + zbx_free_metrics(); zbx_ipc_service_free_env(); DBconnect(ZBX_DB_CONNECT_EXIT); @@ -969,7 +984,7 @@ static void zbx_on_exit(int ret) /* free vmware support */ zbx_vmware_destroy(); - free_selfmon_collector(); + zbx_free_selfmon_collector(); free_proxy_history_lock(); zbx_unload_modules(); @@ -1079,7 +1094,7 @@ int main(int argc, char **argv) CONFIG_FILE = zbx_strdup(NULL, DEFAULT_CONFIG_FILE); /* required for simple checks */ - init_metrics(); + zbx_init_metrics(); zbx_load_config(&t); @@ -1185,14 +1200,16 @@ int MAIN_ZABBIX_ENTRY(int flags) zbx_rtc_t rtc; zbx_timespec_t rtc_timeout = {1, 0}; + zbx_config_comms_args_t zbx_config = {zbx_config_tls, CONFIG_HOSTNAME, CONFIG_PROXYMODE}; + zbx_thread_args_t thread_args; - zbx_thread_poller_args poller_args = {zbx_config_tls, get_program_type, ZBX_NO_POLLER}; - zbx_thread_heart_args heart_args = {zbx_config_tls, get_program_type}; + zbx_thread_poller_args poller_args = {&zbx_config, get_program_type, ZBX_NO_POLLER}; zbx_thread_proxyconfig_args proxyconfig_args = {zbx_config_tls, get_program_type}; zbx_thread_datasender_args datasender_args = {zbx_config_tls, get_program_type}; - zbx_thread_taskmanager_args taskmanager_args = {zbx_config_tls, get_program_type}; + zbx_thread_taskmanager_args taskmanager_args = {&zbx_config, get_program_type}; zbx_thread_discoverer_args discoverer_args = {zbx_config_tls, get_program_type}; - zbx_thread_trapper_args trapper_args = {zbx_config_tls, get_program_type, &listen_sock}; + zbx_thread_trapper_args trapper_args = {&zbx_config, get_program_type, &listen_sock}; + if (0 != (flags & ZBX_TASK_FLAG_FOREGROUND)) { @@ -1323,7 +1340,7 @@ int MAIN_ZABBIX_ENTRY(int flags) exit(EXIT_FAILURE); } - if (SUCCEED != init_selfmon_collector(&error)) + if (SUCCEED != zbx_init_selfmon_collector(&error)) { zabbix_log(LOG_LEVEL_CRIT, "cannot initialize self-monitoring: %s", error); zbx_free(error); @@ -1362,7 +1379,7 @@ int MAIN_ZABBIX_ENTRY(int flags) change_proxy_history_count(proxy_get_history_count()); - threads_num = CONFIG_CONFSYNCER_FORKS + CONFIG_HEARTBEAT_FORKS + CONFIG_DATASENDER_FORKS + threads_num = CONFIG_CONFSYNCER_FORKS + CONFIG_DATASENDER_FORKS + CONFIG_POLLER_FORKS + CONFIG_UNREACHABLE_POLLER_FORKS + CONFIG_TRAPPER_FORKS + CONFIG_PINGER_FORKS + CONFIG_HOUSEKEEPER_FORKS + CONFIG_HTTPPOLLER_FORKS + CONFIG_DISCOVERER_FORKS + CONFIG_HISTSYNCER_FORKS + CONFIG_IPMIPOLLER_FORKS @@ -1387,7 +1404,7 @@ int MAIN_ZABBIX_ENTRY(int flags) zabbix_log(LOG_LEVEL_INFORMATION, "proxy #0 started [main process]"); - zbx_zabbix_stats_init(zbx_get_zabbix_stats_ext); + zbx_zabbix_stats_init(zbx_zabbix_stats_ext_get); zbx_diag_init(diag_add_section_info); for (i = 0; i < threads_num; i++) @@ -1413,10 +1430,6 @@ int MAIN_ZABBIX_ENTRY(int flags) thread_args.args = &trapper_args; zbx_thread_start(trapper_thread, &thread_args, &threads[i]); break; - case ZBX_PROCESS_TYPE_HEARTBEAT: - thread_args.args = &heart_args; - zbx_thread_start(heart_thread, &thread_args, &threads[i]); - break; case ZBX_PROCESS_TYPE_DATASENDER: thread_args.args = &datasender_args; zbx_thread_start(datasender_thread, &thread_args, &threads[i]); diff --git a/src/zabbix_proxy/proxyconfig/Makefile.am b/src/zabbix_proxy/proxyconfig/Makefile.am index a6497c5b978..0d5d718c86d 100644 --- a/src/zabbix_proxy/proxyconfig/Makefile.am +++ b/src/zabbix_proxy/proxyconfig/Makefile.am @@ -5,3 +5,5 @@ noinst_LIBRARIES = libzbxproxyconfig.a libzbxproxyconfig_a_SOURCES = \ proxyconfig.c \ proxyconfig.h + +libzbxproxyconfig_a_CFLAGS = -I$(top_srcdir)/src/zabbix_proxy diff --git a/src/zabbix_proxy/proxyconfig/proxyconfig.c b/src/zabbix_proxy/proxyconfig/proxyconfig.c index 0013622be08..8513189e87c 100644 --- a/src/zabbix_proxy/proxyconfig/proxyconfig.c +++ b/src/zabbix_proxy/proxyconfig/proxyconfig.c @@ -28,6 +28,7 @@ #include "zbxcompress.h" #include "zbxrtc.h" #include "zbxcommshigh.h" +#include "proxyconfigwrite/proxyconfig_write.h" #define CONFIG_PROXYCONFIG_RETRY 120 /* seconds */ @@ -47,6 +48,7 @@ static void process_configuration_sync(size_t *data_size, zbx_synced_new_config_ char value[16], *error = NULL, *buffer = NULL; size_t buffer_size, reserved; struct zbx_json j; + int ret = FAIL; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); @@ -57,6 +59,8 @@ static void process_configuration_sync(size_t *data_size, zbx_synced_new_config_ zbx_json_addstring(&j, "request", ZBX_PROTO_VALUE_PROXY_CONFIG, ZBX_JSON_TYPE_STRING); zbx_json_addstring(&j, "host", CONFIG_HOSTNAME, ZBX_JSON_TYPE_STRING); zbx_json_addstring(&j, ZBX_PROTO_TAG_VERSION, ZABBIX_VERSION, ZBX_JSON_TYPE_STRING); + zbx_json_addstring(&j, ZBX_PROTO_TAG_SESSION, zbx_dc_get_session_token(), ZBX_JSON_TYPE_STRING); + zbx_json_adduint64(&j, ZBX_PROTO_TAG_CONFIG_REVISION, zbx_dc_get_received_revision()); if (SUCCEED != zbx_compress(j.buffer, j.buffer_size, &buffer, &buffer_size)) { @@ -67,16 +71,16 @@ static void process_configuration_sync(size_t *data_size, zbx_synced_new_config_ reserved = j.buffer_size; zbx_json_free(&j); - update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); if (FAIL == zbx_connect_to_server(&sock,CONFIG_SOURCE_IP, &zbx_addrs, 600, CONFIG_TIMEOUT, CONFIG_PROXYCONFIG_RETRY, LOG_LEVEL_WARNING, zbx_config_tls)) /* retry till have a connection */ { - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); goto out; } - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); if (SUCCEED != zbx_get_data_from_server(&sock, &buffer, buffer_size, reserved, &error)) { @@ -118,21 +122,30 @@ static void process_configuration_sync(size_t *data_size, zbx_synced_new_config_ goto error; } - zabbix_log(LOG_LEVEL_WARNING, "received configuration data from server at \"%s\", datalen " ZBX_FS_SIZE_T, - sock.peer, (zbx_fs_size_t)*data_size); - - if (SUCCEED == process_proxyconfig(&jp, &jp_kvs_paths)) + if (SUCCEED == (ret = zbx_proxyconfig_process(sock.peer, &jp, &error))) { - DCsync_configuration(ZBX_DBSYNC_UPDATE, *synced); + DCsync_configuration(ZBX_DBSYNC_UPDATE, *synced, NULL); *synced = ZBX_SYNCED_NEW_CONFIG_YES; - if (NULL != jp_kvs_paths.start) + if (SUCCEED == zbx_json_brackets_by_name(&jp, ZBX_PROTO_TAG_MACRO_SECRETS, &jp_kvs_paths)) DCsync_kvs_paths(&jp_kvs_paths); DCupdate_interfaces_availability(); } + else + { + zabbix_log(LOG_LEVEL_WARNING, "cannot process received configuration data from server at \"%s\": %s", + sock.peer, error); + zbx_free(error); + } error: zbx_disconnect_from_server(&sock); + if (SUCCEED != ret) + { + /* reset received config_revision to force full resync after data transfer failure */ + zbx_dc_update_received_revision(0); + } + out: zbx_free(error); zbx_free(buffer); @@ -141,6 +154,80 @@ out: zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); } +static void proxyconfig_remove_unused_templates(void) +{ + zbx_vector_uint64_t hostids, templateids; + zbx_hashset_t templates; + int removed_num; + DB_ROW row; + DB_RESULT result; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + + zbx_vector_uint64_create(&hostids); + zbx_vector_uint64_create(&templateids); + zbx_hashset_create(&templates, 100, ZBX_DEFAULT_UINT64_HASH_FUNC, ZBX_DEFAULT_UINT64_COMPARE_FUNC); + + result = DBselect("select hostid,status from hosts"); + + while (NULL != (row = DBfetch(result))) + { + zbx_uint64_t hostid; + unsigned char status; + + ZBX_STR2UINT64(hostid, row[0]); + ZBX_STR2UCHAR(status, row[1]); + + if (HOST_STATUS_TEMPLATE == status) + zbx_hashset_insert(&templates, &hostid, sizeof(hostid)); + else + zbx_vector_uint64_append(&hostids, hostid); + } + DBfree_result(result); + + zbx_dc_get_unused_macro_templates(&templates, &hostids, &templateids); + + if (0 != templateids.values_num) + { + char *sql = NULL; + size_t sql_alloc = 0, sql_offset = 0; + + DBbegin(); + + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from hosts_templates where"); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid", templateids.values, + templateids.values_num); + if (ZBX_DB_OK > DBexecute("%s", sql)) + goto fail; + + sql_offset = 0; + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from hostmacro where"); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid", templateids.values, + templateids.values_num); + if (ZBX_DB_OK > DBexecute("%s", sql)) + goto fail; + + sql_offset = 0; + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from hosts where"); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid", templateids.values, + templateids.values_num); + if (ZBX_DB_OK > DBexecute("%s", sql)) + goto fail; +fail: + DBcommit(); + + zbx_free(sql); + } + + removed_num = templateids.values_num; + + zbx_hashset_destroy(&templates); + zbx_vector_uint64_destroy(&templateids); + zbx_vector_uint64_destroy(&hostids); + + zabbix_log(LOG_LEVEL_DEBUG, "End of %s() removed:%d", __func__, removed_num); +} + /****************************************************************************** * * * Purpose: periodically request config data * @@ -153,7 +240,7 @@ ZBX_THREAD_ENTRY(proxyconfig_thread, args) zbx_thread_proxyconfig_args *proxyconfig_args_in = (zbx_thread_proxyconfig_args *) (((zbx_thread_args_t *)args)->args); size_t data_size; - double sec; + double sec, last_template_cleanup_sec = 0, interval; zbx_ipc_async_socket_t rtc; int sleeptime; zbx_synced_new_config_t synced = ZBX_SYNCED_NEW_CONFIG_NO; @@ -165,7 +252,7 @@ ZBX_THREAD_ENTRY(proxyconfig_thread, args) zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(proxyconfig_args_in->zbx_get_program_type_cb_arg()), server_num, get_process_type_string(process_type), process_num); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) zbx_tls_init_child(proxyconfig_args_in->zbx_config_tls, proxyconfig_args_in->zbx_get_program_type_cb_arg); #endif @@ -177,7 +264,7 @@ ZBX_THREAD_ENTRY(proxyconfig_thread, args) DBconnect(ZBX_DB_CONNECT_NORMAL); zbx_setproctitle("%s [syncing configuration]", get_process_type_string(process_type)); - DCsync_configuration(ZBX_DBSYNC_INIT, ZBX_SYNCED_NEW_CONFIG_NO); + DCsync_configuration(ZBX_DBSYNC_INIT, ZBX_SYNCED_NEW_CONFIG_NO, NULL); zbx_rtc_notify_config_sync(&rtc); @@ -208,11 +295,17 @@ ZBX_THREAD_ENTRY(proxyconfig_thread, args) { zbx_setproctitle("%s [loading configuration]", get_process_type_string(process_type)); - DCsync_configuration(ZBX_DBSYNC_UPDATE, synced); + DCsync_configuration(ZBX_DBSYNC_UPDATE, synced, NULL); synced = ZBX_SYNCED_NEW_CONFIG_YES; DCupdate_interfaces_availability(); zbx_rtc_notify_config_sync(&rtc); + if (SEC_PER_HOUR < sec - last_template_cleanup_sec) + { + proxyconfig_remove_unused_templates(); + last_template_cleanup_sec = sec; + } + zbx_setproctitle("%s [synced config in " ZBX_FS_DBL " sec]", get_process_type_string(process_type), zbx_time() - sec); } @@ -227,12 +320,18 @@ ZBX_THREAD_ENTRY(proxyconfig_thread, args) zbx_setproctitle("%s [loading configuration]", get_process_type_string(process_type)); process_configuration_sync(&data_size, &synced, proxyconfig_args_in->zbx_config_tls); - sec = zbx_time() - sec; + interval = zbx_time() - sec; zbx_setproctitle("%s [synced config " ZBX_FS_SIZE_T " bytes in " ZBX_FS_DBL " sec, idle %d sec]", - get_process_type_string(process_type), (zbx_fs_size_t)data_size, sec, + get_process_type_string(process_type), (zbx_fs_size_t)data_size, interval, CONFIG_PROXYCONFIG_FREQUENCY); + if (SEC_PER_HOUR < sec - last_template_cleanup_sec) + { + proxyconfig_remove_unused_templates(); + last_template_cleanup_sec = sec; + } + sleeptime = CONFIG_PROXYCONFIG_FREQUENCY; } stop: diff --git a/src/zabbix_proxy/proxyconfigwrite/Makefile.am b/src/zabbix_proxy/proxyconfigwrite/Makefile.am new file mode 100644 index 00000000000..175513c0de6 --- /dev/null +++ b/src/zabbix_proxy/proxyconfigwrite/Makefile.am @@ -0,0 +1,9 @@ +## Process this file with automake to produce Makefile.in + +noinst_LIBRARIES = libzbxproxyconfigwrite.a + +libzbxproxyconfigwrite_a_SOURCES = \ + proxyconfig_write.c \ + proxyconfig_write.h + +libzbxproxyconfigwrite_a_CFLAGS = -I$(top_srcdir)/src diff --git a/src/zabbix_proxy/proxyconfigwrite/proxyconfig_write.c b/src/zabbix_proxy/proxyconfigwrite/proxyconfig_write.c new file mode 100644 index 00000000000..e364e87d80d --- /dev/null +++ b/src/zabbix_proxy/proxyconfigwrite/proxyconfig_write.c @@ -0,0 +1,2133 @@ +/* +** Zabbix +** Copyright (C) 2001-2022 Zabbix SIA +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +**/ + +#include "proxyconfig_write.h" + +#include "proxy.h" +#include "zbxdbhigh.h" +#include "zbxcommshigh.h" +#include "zbxrtc.h" + +/* + * The configuration sync is split into 4 parts for each table: + * 1) proxyconfig_prepare_rows() + * Renames rename_field to '#'||rename_field for all rows to be updated. It's done to avoid + * possible conflicts when two field values used in unique index are swapped. + * Resets reset_field to null for all rows to be deleted or updated. It's done to avoid + * possible foreign key violation when rows in self referencing table are updated or deleted. + * The changed fields are marked as updated, so during update processing the correct values + * will be assigned to them. + * + * 2) proxyconfig_delete_rows() + * Deletes all existing rows within scope that are not present in received table data. The scope + * is limited to received hosts when partial updates are done. + * + * 3) proxyconfig_insert_rows() + * Inserts new rows that were not present in database. + * + * 4) proxyconfig_update_rows() + * Update changed fields. + * + * When processing related tables (for example drules, dchecks) the prepare and delete operations are + * done from child tables to master tables. The insert and update operations are done from master + * tables to child tables. This is done to avoid child rows being removed with cascaded deletes and + * have parent rows updated/inserted when updating/inserting child rows. + * + */ + +extern int CONFIG_TRAPPER_TIMEOUT; + +typedef struct +{ + const ZBX_FIELD *field; +} +zbx_const_field_ptr_t; + +ZBX_VECTOR_DECL(const_field, zbx_const_field_ptr_t) +ZBX_VECTOR_IMPL(const_field, zbx_const_field_ptr_t) + +/* + * 128 bit flags to support update flags for host_invetory table which has more that 64 columns + */ +typedef struct +{ + zbx_uint64_t blocks[128 / 64]; +} +zbx_flags128_t; + +static void zbx_flags128_set(zbx_flags128_t *flags, int bit) +{ + flags->blocks[bit >> 6] |= (__UINT64_C(1) << (bit & 0x3f)); +} + +static void zbx_flags128_clear(zbx_flags128_t *flags, int bit) +{ + flags->blocks[bit >> 6] &= ~(__UINT64_C(1) << (bit & 0x3f)); +} + +static void zbx_flags128_init(zbx_flags128_t *flags) +{ + memset(flags->blocks, 0, sizeof(zbx_uint64_t) * (128 / 64)); +} + +static int zbx_flags128_isset(zbx_flags128_t *flags, int bit) +{ + return (0 != (flags->blocks[bit >> 6] & (__UINT64_C(1) << (bit & 0x3f)))) ? SUCCEED : FAIL; +} + +static int zbx_flags128_isclear(zbx_flags128_t *flags) +{ + if (0 != flags->blocks[0]) + return FAIL; + + if (0 != flags->blocks[1]) + return FAIL; + + return SUCCEED; +} + +ZBX_PTR_VECTOR_DECL(table_row_ptr, struct zbx_table_row *) + +/* bit defines for proxyconfig row flags, lower bits are reserved for field update flags */ +#define PROXYCONFIG_ROW_EXISTS 127 + +typedef struct zbx_table_row +{ + zbx_uint64_t recid; + struct zbx_json_parse columns; + zbx_flags128_t flags; +} +zbx_table_row_t; + +ZBX_PTR_VECTOR_IMPL(table_row_ptr, zbx_table_row_t *) + +typedef struct +{ + const ZBX_TABLE *table; + zbx_vector_const_field_t fields; + zbx_hashset_t rows; + + /* identifiers of the rows that must be deleted */ + zbx_vector_uint64_t del_ids; + + /* row that must be updated */ + zbx_vector_table_row_ptr_t updates; + + /* to avoid unique key conflicts when syncing rows the key */ + /* field will be renamed for all update rows and marked */ + /* for update */ + const char *rename_field; + + /* To avoid self referencing foreign key conflicts when */ + /* syncing rows the reset field will be set to NULL for */ + /* all update and delete rows and marked for update. */ + /* As such only ID fields can be set as reset_field. */ + const char *reset_field; + + /* optional sql filter to limit managed object scope (exclude templates from hosts) */ + char *sql_filter; +} +zbx_table_data_t; + +ZBX_PTR_VECTOR_DECL(table_data_ptr, zbx_table_data_t *) +ZBX_PTR_VECTOR_IMPL(table_data_ptr, zbx_table_data_t *) + +static void table_data_free(zbx_table_data_t *td) +{ + zbx_vector_const_field_destroy(&td->fields); + zbx_vector_uint64_destroy(&td->del_ids); + zbx_vector_table_row_ptr_destroy(&td->updates); + zbx_hashset_destroy(&td->rows); + zbx_free(td->sql_filter); + zbx_free(td); +} + +/****************************************************************************** + * * + * Purpose: get table data by name from configuration updates * + * * + * Return: The parsed table data or NULL if table data was not found * + * * + ******************************************************************************/ +static zbx_table_data_t *proxyconfig_get_table(zbx_vector_table_data_ptr_t *config_tables, const char *name) +{ + int i; + + for (i = 0; i < config_tables->values_num; i++) + { + if (0 == strcmp(config_tables->values[i]->table->table, name)) + return config_tables->values[i]; + } + + return NULL; +} + +/****************************************************************************** + * * + * Purpose: validate parsed table fields against fields retrieved from * + * database schema * + * * + * Parameters: td - [IN] the table * + * jp_table - [IN] the received table data in json format * + * error - [OUT] the error message * + * * + * Return: SUCCEED - the parsed fields match schema fields * + * FAIL - otherwise * + * * + ******************************************************************************/ +static int proxyconfig_validate_table_fields(const zbx_table_data_t *td, struct zbx_json_parse *jp_table, + char **error) +{ + const char *p; + int ret = FAIL, i; + struct zbx_json_parse jp; + char buf[ZBX_FIELDNAME_LEN_MAX]; + + /* get table columns (line 3 in T1) */ + if (FAIL == zbx_json_brackets_by_name(jp_table, "fields", &jp)) + { + *error = zbx_strdup(*error, zbx_json_strerror()); + goto out; + } + + /* validate received fields */ + + p = NULL; + /* iterate column names (lines 4-6 in T1) */ + for (i = 0; NULL != (p = zbx_json_next_value(&jp, p, buf, sizeof(buf), NULL)); i++) + { + if (i >= td->fields.values_num || 0 != strcmp(buf, td->fields.values[i].field->name)) + { + *error = zbx_dsprintf(*error, "unexpected field \"%s.%s\"", td->table->table, buf); + goto out; + } + } + + if (i != td->fields.values_num) + { + *error = zbx_dsprintf(*error, "missing field \"%s.%s\"", td->table->table, + td->fields.values[i].field->name); + goto out; + } + + ret = SUCCEED; +out: + return ret; +} + +/****************************************************************************** + * * + * Purpose: parse table rows in received configuration data * + * * + * Parameters: td - [IN] the table * + * jp_table - [IN] the received table data in json format * + * error - [OUT] the error message * + * * + * Return: SUCCEED - the rows were parsed successfully * + * FAIL - otherwise * + * * + ******************************************************************************/ +static int proxyconfig_parse_table_rows(zbx_table_data_t *td, struct zbx_json_parse *jp_table, char **error) +{ + const char *p; + int ret = FAIL; + struct zbx_json_parse jp, jp_row; + char *buf; + size_t buf_alloc = ZBX_KIBIBYTE; + + buf = (char *)zbx_malloc(NULL, buf_alloc); + + /* get the entries (line 8 in T1) */ + if (FAIL == zbx_json_brackets_by_name(jp_table, ZBX_PROTO_TAG_DATA, &jp)) + { + *error = zbx_strdup(*error, zbx_json_strerror()); + goto out; + } + + for (p = NULL; NULL != (p = zbx_json_next(&jp, p)); ) + { + zbx_table_row_t *row, row_local; + + if (FAIL == zbx_json_brackets_open(p, &jp_row) || + NULL == zbx_json_next_value_dyn(&jp_row, NULL, &buf, &buf_alloc, NULL)) + { + *error = zbx_strdup(*error, zbx_json_strerror()); + goto out; + } + + if (SUCCEED != zbx_is_uint64(buf, &row_local.recid)) + { + *error = zbx_dsprintf(*error, "invalid record identifier: \"%s\"", buf); + goto out; + } + row = (zbx_table_row_t *)zbx_hashset_insert(&td->rows, &row_local, sizeof(row_local)); + row->columns = jp_row; + zbx_flags128_init(&row->flags); + } + + ret = SUCCEED; +out: + zbx_free(buf); + + return ret; +} + +/****************************************************************************** + * * + * Purpose: create and initialize table data object * + * * + * Parameters: name - [IN] the table name * + * * + * Return: The table data object or null, if invalid table name was given. * + * * + ******************************************************************************/ +static zbx_table_data_t *proxyconfig_create_table(const char *name) +{ + const ZBX_TABLE *table; + const ZBX_FIELD *field; + zbx_table_data_t *td; + zbx_const_field_ptr_t ptr; + + if (NULL == (table = DBget_table(name))) + return NULL; + + td = (zbx_table_data_t *)zbx_malloc(NULL, sizeof(zbx_table_data_t)); + + td->table = table; + td->rename_field = NULL; + td->reset_field = NULL; + td->sql_filter = NULL; + + zbx_vector_const_field_create(&td->fields); + zbx_hashset_create(&td->rows, 100, ZBX_DEFAULT_UINT64_HASH_FUNC, ZBX_DEFAULT_UINT64_COMPARE_FUNC); + zbx_vector_uint64_create(&td->del_ids); + zbx_vector_table_row_ptr_create(&td->updates); + + /* apply table specific configuration settings */ + + if (0 == strcmp(table->table, "globalmacro")) + { + td->rename_field = "macro"; + } + if (0 == strcmp(table->table, "hostmacro")) + { + td->rename_field = "macro"; + } + else if (0 == strcmp(table->table, "drules")) + { + td->rename_field = "name"; + } + else if (0 == strcmp(table->table, "regexps")) + { + td->rename_field = "name"; + } + else if (0 == strcmp(table->table, "httptest")) + { + td->rename_field = "name"; + } + else if (0 == strcmp(table->table, "hosts")) + { + td->sql_filter = zbx_dsprintf(NULL, "status<>%d", HOST_STATUS_TEMPLATE); + } + else if (0 == strcmp(table->table, "items")) + td->reset_field = "master_itemid"; + + /* get table fields from database schema */ + + field = table->fields; + ptr.field = field++; + zbx_vector_const_field_append(&td->fields, ptr); + + for (; NULL != field->name; field++) + { + if (0 != (field->flags & ZBX_PROXY)) + { + ptr.field = field; + zbx_vector_const_field_append(&td->fields, ptr); + } + } + + return td; +} + +/****************************************************************************** + * * + * Purpose: parse received configuration data * + * * + * Parameters: jp_data - [IN] the configuration data in json format * + * config_tables - [OUT] the parsed table data * + * error - [IN] the error message * + * * + * Return: SUCCEED - the rows were parsed successfully * + * FAIL - otherwise * + * * + ******************************************************************************/ +static int proxyconfig_parse_data(struct zbx_json_parse *jp_data, zbx_vector_table_data_ptr_t *config_tables, + char **error) +{ + const char *p; + char buf[ZBX_TABLENAME_LEN_MAX]; + struct zbx_json_parse jp_table; + int ret = FAIL; + + /************************************************************************************/ + /* T1. RECEIVED JSON (jp_obj) DATA FORMAT */ + /************************************************************************************/ + /* Line | Data | Corresponding structure in DB */ + /* -----+-------------------------------------------+------------------------------ */ + /* 1 | { | */ + /* 2 | "hosts": { | first table */ + /* 3 | "fields": [ | list of table's columns */ + /* 4 | "hostid", | first column */ + /* 5 | "host", | second column */ + /* 6 | ... | ...columns */ + /* 7 | ], | */ + /* 8 | "data": [ | the table data */ + /* 9 | [ | first entry */ + /* 10 | 1, | value for first column */ + /* 11 | "zbx01", | value for second column */ + /* 12 | ... | ...values */ + /* 13 | ], | */ + /* 14 | [ | second entry */ + /* 15 | 2, | value for first column */ + /* 16 | "zbx02", | value for second column */ + /* 17 | ... | ...values */ + /* 18 | ], | */ + /* 19 | ... | ...entries */ + /* 20 | ] | */ + /* 21 | }, | */ + /* 22 | "items": { | second table */ + /* 23 | ... | ... */ + /* 24 | }, | */ + /* 25 | ... | ...tables */ + /* 26 | } | */ + /************************************************************************************/ + + /* iterate the tables (lines 2, 22 and 25 in T1) */ + for (p = NULL; NULL != (p = zbx_json_pair_next(jp_data, p, buf, sizeof(buf))); ) + { + zbx_table_data_t *td; + + if (FAIL == zbx_json_brackets_open(p, &jp_table)) + { + *error = zbx_strdup(NULL, zbx_json_strerror()); + goto out; + } + + if (NULL == (td = proxyconfig_create_table(buf))) + { + *error = zbx_dsprintf(NULL, "invalid table name \"%s\"", buf); + goto out; + } + + if (SUCCEED != proxyconfig_validate_table_fields(td, &jp_table, error) || + SUCCEED != proxyconfig_parse_table_rows(td, &jp_table, error)) + { + table_data_free(td); + goto out; + } + + zbx_vector_table_data_ptr_append(config_tables, td); + } + + ret = SUCCEED; +out: + return ret; +} + +/****************************************************************************** + * * + * Purpose: add default tables to configuration data * + * * + * Parameters: config_tables - [IN] the parsed table data * + * * + * Comments: In some cases empty tables might not be sent, but still need to * + * be processed to support old data removal. This function adds * + * empty tables that will be used to check and remove old records. * + * * + ******************************************************************************/ +static void proxyconfig_add_default_tables(zbx_vector_table_data_ptr_t *config_tables) +{ + if (NULL != proxyconfig_get_table(config_tables, "hosts") && + NULL == proxyconfig_get_table(config_tables, "httptest")) + { + char *httptest_tables[] = {"httptest", "httptestitem", "httptest_field", + "httpstep", "httpstepitem", "httpstep_field"}; + size_t i; + + for (i = 0; i < ARRSIZE(httptest_tables); i++) + zbx_vector_table_data_ptr_append(config_tables, proxyconfig_create_table(httptest_tables[i])); + } +} + +/****************************************************************************** + * * + * Purpose: dump table data object contents * + * * + * Parameters: td - [IN] the table data object * + * * + ******************************************************************************/ +static void proxyconfig_dump_table(zbx_table_data_t *td) +{ + char *str = NULL; + size_t str_alloc = 0, str_offset = 0, buf_alloc = ZBX_KIBIBYTE; + int i; + zbx_hashset_iter_t iter; + zbx_table_row_t *row; + char *buf; + + buf = (char *)zbx_malloc(NULL, buf_alloc); + + zabbix_log(LOG_LEVEL_TRACE, "table:%s", td->table->table); + + zbx_strcpy_alloc(&str, &str_alloc, &str_offset, "||"); + + for (i = 0; i < td->fields.values_num; i++) + zbx_snprintf_alloc(&str, &str_alloc, &str_offset, "%s||", td->fields.values[i].field->name); + + zabbix_log(LOG_LEVEL_TRACE, " %s", str); + + zbx_hashset_iter_reset(&td->rows, &iter); + while (NULL != (row = (zbx_table_row_t *)zbx_hashset_iter_next(&iter))) + { + const char *pf = NULL; + + str_offset = 0; + zbx_chrcpy_alloc(&str, &str_alloc, &str_offset, '|'); + + while (NULL != (pf = zbx_json_next_value_dyn(&row->columns, pf, &buf, &buf_alloc, NULL))) + zbx_snprintf_alloc(&str, &str_alloc, &str_offset, "%s|", buf); + + zabbix_log(LOG_LEVEL_TRACE, " %s", str); + } + + zbx_free(str); + zbx_free(buf); +} + +/****************************************************************************** + * * + * Purpose: dump parsed configuration contents * + * * + * Parameters: config_tables - [IN] the parsed table data * + * * + ******************************************************************************/ +static void proxyconfig_dump_data(const zbx_vector_table_data_ptr_t *config_tables) +{ + int i; + + zabbix_log(LOG_LEVEL_TRACE, "=== Received configuration ==="); + + for (i = 0; i < config_tables->values_num; i++) + proxyconfig_dump_table(config_tables->values[i]); +} + +/****************************************************************************** + * * + * Purpose: compare database row with received data * + * * + * Parameters: row - [IN] the received row * + * dbrow - [IN] the database row * + * buf - [IN/OUT] the buffer for value parsing * + * buf_alloc - [IN/OUT] the buffer size * + * * + * Return value: SUCCEED - the rows match * + * FAIl - the rows doesn't match * + * * + * Comments: The checked rows will be flagged as 'exists'. Also update flag * + * will be set for each not matching column. Finally global row * + * update flag will be set if at last one match failed. * + * * + ******************************************************************************/ +static int proxyconfig_compare_row(zbx_table_row_t *row, DB_ROW dbrow, char **buf, size_t *buf_alloc) +{ + int i, ret = SUCCEED; + const char *pf; + zbx_json_type_t type; + + /* skip first row containing record id */ + pf = zbx_json_next(&row->columns, NULL); + + for (i = 1; NULL != (pf = zbx_json_next_value_dyn(&row->columns, pf, buf, buf_alloc, &type)); i++) + { + if (ZBX_JSON_TYPE_NULL == type) + { + if (SUCCEED != DBis_null(dbrow[i])) + zbx_flags128_set(&row->flags, i); + continue; + } + + if (SUCCEED == DBis_null(dbrow[i]) || 0 != strcmp(*buf, dbrow[i])) + zbx_flags128_set(&row->flags, i); + } + + if (SUCCEED != zbx_flags128_isclear(&row->flags)) + ret = FAIL; + + zbx_flags128_set(&row->flags, PROXYCONFIG_ROW_EXISTS); + + return ret; +} + +/****************************************************************************** + * * + * Purpose: get field index in table fields list by name * + * * + * Parameters: td - [IN] the table data object * + * field_name - [OUT] the field name * + * * + * Return value: The field index or -1 if field was not found. * + * * + ******************************************************************************/ +static int table_data_get_field_index(const zbx_table_data_t *td, const char *field_name) +{ + int i; + + /* skip first field - recid */ + for (i = 1; i < td->fields.values_num; i++) + { + if (0 == strcmp(td->fields.values[i].field->name, field_name)) + return i; + } + + return -1; +} + +/****************************************************************************** + * * + * Purpose: delete rows that are not present in new configuration data * + * * + * Parameters: td - [IN] the table data object * + * error - [OUT] the error message * + * * + * Return value: SUCCEED - the rows were deleted successfully * + * FAIL - otherwise * + * * + ******************************************************************************/ +static int proxyconfig_delete_rows(const zbx_table_data_t *td, char **error) +{ + char *sql = NULL; + size_t sql_alloc = 0, sql_offset = 0; + int ret; + + if (0 == td->del_ids.values_num) + return SUCCEED; + + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "delete from %s where", td->table->table); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, td->table->recid, td->del_ids.values, + td->del_ids.values_num); + + if (ZBX_DB_OK > DBexecute("%s", sql)) + { + *error = zbx_dsprintf(NULL, "cannot remove old objects from table \"%s\"", td->table->table); + ret = FAIL; + } + else + ret = SUCCEED; + + zbx_free(sql); + + return ret; +} + +/****************************************************************************** + * * + * Purpose: prepare existing rows for udpate/delete * + * * + * Parameters: td - [IN] the table data object * + * error - [OUT] the error message * + * * + * Return value: SUCCEED - the rows were prepared successfully * + * FAIL - otherwise * + * * + ******************************************************************************/ +static int proxyconfig_prepare_rows(zbx_table_data_t *td, char **error) +{ + char *sql = NULL, delim = ' '; + size_t sql_alloc = 0, sql_offset = 0; + int i, ret, rename_index = -1, reset_index = -1; + zbx_vector_uint64_t updateids; + + if (NULL == td->rename_field && NULL == td->reset_field) + return SUCCEED; + + if (NULL != td->rename_field && -1 == (rename_index = table_data_get_field_index(td, td->rename_field))) + { + *error = zbx_dsprintf(NULL, "unknown rename field \"%s\" for table \"%s\"", td->rename_field, + td->table->table); + return FAIL; + } + + if (NULL != td->reset_field) + { + if (-1 == (reset_index = table_data_get_field_index(td, td->reset_field))) + { + *error = zbx_dsprintf(NULL, "unknown rename field \"%s\" for table \"%s\"", td->reset_field, + td->table->table); + return FAIL; + } + + if (ZBX_TYPE_ID != td->fields.values[reset_index].field->type) + { + *error = zbx_dsprintf(NULL, "only ID fields can be reset"); + return FAIL; + } + } + + zbx_vector_uint64_create(&updateids); + zbx_vector_uint64_reserve(&updateids, (size_t)td->updates.values_num); + + for (i = 0; i < td->updates.values_num; i++) + { + zbx_vector_uint64_append(&updateids, td->updates.values[i]->recid); + + /* force renamed/reset fields to be updated */ + + if (-1 != rename_index) + zbx_flags128_set(&td->updates.values[i]->flags, rename_index); + + if (-1 != reset_index) + zbx_flags128_set(&td->updates.values[i]->flags, reset_index); + } + + if (-1 != reset_index) + zbx_vector_uint64_append_array(&updateids, td->del_ids.values, td->del_ids.values_num); + + if (0 == updateids.values_num) + { + ret = SUCCEED; + goto out; + } + + zbx_vector_uint64_sort(&updateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); + + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "update %s set", td->table->table); + + if (-1 != rename_index) + { + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%c%s=" ZBX_SQL_CONCAT(), + delim, td->rename_field, "'#'", td->rename_field); + delim = ','; + } + + if (-1 != reset_index) + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%c%s=null", delim, td->reset_field); + + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " where"); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, td->table->recid, updateids.values, updateids.values_num); + + if (ZBX_DB_OK > DBexecute("%s", sql)) + { + *error = zbx_dsprintf(NULL, "cannot prepare rows for update in table \"%s\"", td->table->table); + ret = FAIL; + } + else + ret = SUCCEED; + + zbx_free(sql); +out: + zbx_vector_uint64_destroy(&updateids); + + return ret; +} + +/****************************************************************************** + * * + * Purpose: convert text value to the database value according to its field * + * type * + * * + * Parameters: table - [IN] * + * field - [IN] * + * buf - [IN] the value to convert * + * type - [IN] the json value type * + * value - [OUT] the converted value (optional) * + * error - [OUT] the error message * + * * + * Return value: SUCCEED - the operation was successful * + * FAIL - otherwise * + * * + * Comments: This function can be used to validate buffer by using NULL * + * output value. * + * * + ******************************************************************************/ +static int proxyconfig_convert_value(const ZBX_TABLE *table, const ZBX_FIELD *field, const char *buf, + zbx_json_type_t type, zbx_db_value_t **value, char **error) +{ + zbx_db_value_t value_local; + int ret; + + switch (field->type) + { + case ZBX_TYPE_INT: + ret = zbx_is_int(buf, &value_local.i32); + break; + case ZBX_TYPE_UINT: + ret = zbx_is_uint64(buf, &value_local.ui64); + break; + case ZBX_TYPE_ID: + if (ZBX_JSON_TYPE_NULL == type) + { + value_local.ui64 = 0; + ret = SUCCEED; + } + else + ret = zbx_is_uint64(buf, &value_local.ui64); + break; + case ZBX_TYPE_FLOAT: + ret = zbx_is_double(buf, &value_local.dbl); + break; + case ZBX_TYPE_CHAR: + case ZBX_TYPE_TEXT: + case ZBX_TYPE_SHORTTEXT: + case ZBX_TYPE_LONGTEXT: + if (NULL != value) + value_local.str = zbx_strdup(NULL, ZBX_NULL2EMPTY_STR(buf)); + ret = SUCCEED; + break; + default: + *error = zbx_dsprintf(*error, "unsupported field type %d in \"%s.%s\"", + field->type, table->table, field->name); + return FAIL; + } + + if (SUCCEED != ret) + { + *error = zbx_dsprintf(*error, "invalid field \"%s.%s\" value \"%s\"", + table->table, field->name, buf); + return FAIL; + } + + if (NULL != value) + { + *value = (zbx_db_value_t *)zbx_malloc(NULL, sizeof(zbx_db_value_t)); + **value = value_local; + } + + return SUCCEED; +} + +/****************************************************************************** + * * + * Purpose: update existing rows with new field values * + * * + * Parameters: td - [IN] the table data object * + * error - [OUT] the error message * + * * + * Return value: SUCCEED - the rows were updated successfully * + * FAIL - otherwise * + * * + ******************************************************************************/ +static int proxyconfig_update_rows(zbx_table_data_t *td, char **error) +{ + char *sql = NULL, *buf; + size_t sql_alloc = 0, sql_offset = 0, buf_alloc = ZBX_KIBIBYTE; + int i, j, ret = FAIL; + + if (0 == td->updates.values_num) + return SUCCEED; + + buf = (char *)zbx_malloc(NULL, buf_alloc); + + zbx_DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset); + + for (i = 0; i < td->updates.values_num; i++) + { + char delim = ' '; + const char *pf; + zbx_table_row_t *row = td->updates.values[i]; + zbx_json_type_t type; + + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "update %s set", td->table->table); + + pf = zbx_json_next(&row->columns, NULL); + + for (j = 1; NULL != (pf = zbx_json_next_value_dyn(&row->columns, pf, &buf, &buf_alloc, &type)); j++) + { + const ZBX_FIELD *field = td->fields.values[j].field; + char *value_esc; + + if (SUCCEED != zbx_flags128_isset(&row->flags, j)) + continue; + + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%c%s=", delim, field->name); + delim = ','; + + if (ZBX_JSON_TYPE_NULL == type) + { + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "null"); + continue; + } + + if (SUCCEED != proxyconfig_convert_value(td->table, field, buf, type, NULL, error)) + goto out; + + switch (field->type) + { + case ZBX_TYPE_ID: + case ZBX_TYPE_UINT: + case ZBX_TYPE_FLOAT: + case ZBX_TYPE_INT: + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, buf); + break; + case ZBX_TYPE_CHAR: + case ZBX_TYPE_TEXT: + case ZBX_TYPE_SHORTTEXT: + case ZBX_TYPE_LONGTEXT: + value_esc = DBdyn_escape_string_len(buf, field->length); + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "'%s'", value_esc); + zbx_free(value_esc); + break; + default: + *error = zbx_dsprintf(*error, "unsupported field type %d in \"%s.%s\"", + (int)field->type, td->table->table, field->name); + goto out; + } + } + + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " where %s=" ZBX_FS_UI64 ";\n", + td->table->recid, row->recid); + + if (SUCCEED != DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset)) + goto out; + } + + zbx_DBend_multiple_update(&sql, &sql_alloc, &sql_offset); + + if (16 < sql_offset && ZBX_DB_OK > DBexecute("%s", sql)) + goto out; + + ret = SUCCEED; +out: + zbx_free(sql); + zbx_free(buf); + + if (SUCCEED != ret && NULL == *error) + *error = zbx_dsprintf(NULL, "cannot update rows in table \"%s\"", td->table->table); + + return ret; +} + +ZBX_PTR_VECTOR_DECL(db_value_ptr, zbx_db_value_t *) +ZBX_PTR_VECTOR_IMPL(db_value_ptr, zbx_db_value_t *) + +/****************************************************************************** + * * + * Purpose: insert new rows * + * * + * Parameters: td - [IN] the table data object * + * error - [OUT] the error message * + * * + * Return value: SUCCEED - the rows were inserted successfully * + * FAIL - otherwise * + * * + ******************************************************************************/ +static int proxyconfig_insert_rows(zbx_table_data_t *td, char **error) +{ + int ret = SUCCEED, reset_index = -1; + zbx_hashset_iter_t iter; + zbx_vector_table_row_ptr_t rows; + zbx_table_row_t *row; + + /* invalid reset_index would have generated error during row preparation */ + if (NULL != td->reset_field) + reset_index = table_data_get_field_index(td, td->reset_field); + + zbx_vector_table_row_ptr_create(&rows); + + zbx_hashset_iter_reset(&td->rows, &iter); + while (NULL != (row = (zbx_table_row_t *)zbx_hashset_iter_next(&iter))) + { + if (SUCCEED != zbx_flags128_isset(&row->flags, PROXYCONFIG_ROW_EXISTS)) + zbx_vector_table_row_ptr_append(&rows, row); + } + + if (0 != rows.values_num) + { + zbx_vector_db_value_ptr_t values; + zbx_db_insert_t db_insert; + const ZBX_FIELD *fields[ZBX_MAX_FIELDS]; + int i, j; + char *buf; + size_t buf_alloc = ZBX_KIBIBYTE; + + buf = (char *)zbx_malloc(NULL, buf_alloc); + + zbx_vector_db_value_ptr_create(&values); + + for (i = 0; i < td->fields.values_num; i++) + fields[i] = td->fields.values[i].field; + + zbx_db_insert_prepare_dyn(&db_insert, td->table, fields, td->fields.values_num); + + for (i = 0; i < rows.values_num && SUCCEED == ret; i++) + { + const char *pf = NULL; + zbx_json_type_t type; + + row = rows.values[i]; + + for (j = 0; NULL != (pf = zbx_json_next_value_dyn(&row->columns, pf, &buf, &buf_alloc, &type)); + j++) + { + zbx_db_value_t *value; + + if (j == reset_index) + { + if (ZBX_TYPE_ID != fields[j]->type) + { + /* Field resetting is used to avoid foreign key conflicts in self */ + /* referenced tables during inserts. Such fields are inserted as */ + /* nulls and then updated to correct values. */ + /* For now only ID fields can be used in foreign keys. */ + THIS_SHOULD_NEVER_HAPPEN; + + *error = zbx_dsprintf(NULL, "cannot reset field \"%s.%s\" of type %d " + "to NULL value", + td->table->table, fields[j]->name, fields[j]->type); + ret = FAIL; + goto clean; + } + + /* insert null ID and add this row to updates, */ + /* so the correct ID will be updated later */ + zbx_flags128_set(&row->flags, PROXYCONFIG_ROW_EXISTS); + zbx_flags128_set(&row->flags, j); + zbx_vector_table_row_ptr_append(&td->updates, row); + + value = (zbx_db_value_t *)zbx_malloc(NULL, sizeof(zbx_db_value_t)); + value->ui64 = 0; + } + else + { + if (SUCCEED != (ret = proxyconfig_convert_value(td->table, fields[j], buf, type, + &value, error))) + { + goto clean; + } + } + + zbx_vector_db_value_ptr_append(&values, value); + } + + zbx_db_insert_add_values_dyn(&db_insert, (const zbx_db_value_t **)values.values, + values.values_num); +clean: + for (j = 0; j < values.values_num; j++) + { + switch (fields[j]->type) + { + case ZBX_TYPE_CHAR: + case ZBX_TYPE_TEXT: + case ZBX_TYPE_SHORTTEXT: + case ZBX_TYPE_LONGTEXT: + zbx_free(values.values[j]->str); + } + zbx_free(values.values[j]); + } + zbx_vector_db_value_ptr_clear(&values); + } + + if (SUCCEED == ret) + ret = zbx_db_insert_execute(&db_insert); + + zbx_db_insert_clean(&db_insert); + zbx_vector_db_value_ptr_destroy(&values); + zbx_free(buf); + + } + + zbx_vector_table_row_ptr_destroy(&rows); + + if (SUCCEED != ret && NULL == *error) + *error = zbx_dsprintf(NULL, "cannot insert rows in table \"%s\"", td->table->table); + + return ret; +} + +/****************************************************************************** + * * + * Purpose: prepare table for configuration sync by checking existing data * + * against received data and mark row updates/deletes accordingly * + * * + * Parameters: td - [IN] the table data object * + * key_field - [IN] the key field (optional) * + * key_ids - [IN] the key identifiers (optional) * + * recids - [OUT] the selected row record identifiers * + * (optional) * + * * + * Comments: The key_field and key_ids allow to specify scope within which the* + * table sync will be made. * + * * + ******************************************************************************/ +static void proxyconfig_prepare_table(zbx_table_data_t *td, const char *key_field, zbx_vector_uint64_t *key_ids, + zbx_vector_uint64_t *recids) +{ + DB_RESULT result; + DB_ROW dbrow; + char *sql = NULL, *buf, *delim = " where"; + size_t sql_alloc = 0, sql_offset = 0, buf_alloc = ZBX_KIBIBYTE; + zbx_uint64_t recid; + zbx_table_row_t *row; + int i; + + if (NULL != key_ids && 0 == key_ids->values_num) + return; + + buf = (char *)zbx_malloc(NULL, buf_alloc); + + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "select %s", td->table->recid); + + for (i = 1; i < td->fields.values_num; i++) + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, ",%s", td->fields.values[i].field->name); + + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " from %s", td->table->table); + if (NULL != key_ids) + { + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, delim); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, key_field, key_ids->values, key_ids->values_num); + delim = " and"; + } + + if (NULL != td->sql_filter) + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%s %s", delim, td->sql_filter); + + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " order by %s", td->table->recid); + + result = DBselect("%s", sql); + + while (NULL != (dbrow = DBfetch(result))) + { + ZBX_STR2UINT64(recid, dbrow[0]); + + if (NULL != recids) + zbx_vector_uint64_append(recids, recid); + + if (NULL == (row = (zbx_table_row_t *)zbx_hashset_search(&td->rows, &recid))) + { + zbx_vector_uint64_append(&td->del_ids, recid); + continue; + } + + if (SUCCEED != proxyconfig_compare_row(row, dbrow, &buf, &buf_alloc)) + zbx_vector_table_row_ptr_append(&td->updates, row); + } + DBfree_result(result); + + zbx_free(sql); + zbx_free(buf); + + if (0 != td->del_ids.values_num) + zbx_vector_uint64_sort(&td->del_ids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); + + if (0 != td->updates.values_num) + zbx_vector_table_row_ptr_sort(&td->updates, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC); + + if (NULL != recids) + zbx_vector_uint64_sort(recids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); +} + +/****************************************************************************** + * * + * Purpose: sync table rows * + * * + * Parameters: config_tables - [IN] the received table data * + * table - [IN] the name of table to sync * + * error - [OUT] the error message * + * * + * Return value: SUCCEED - the table was synced successfully * + * FAIL - otherwise * + * * + ******************************************************************************/ +static int proxyconfig_sync_table(zbx_vector_table_data_ptr_t *config_tables, const char *table, char **error) +{ + zbx_table_data_t *td; + + if (NULL == (td = proxyconfig_get_table(config_tables, table))) + return SUCCEED; + + proxyconfig_prepare_table(td, NULL, NULL, NULL); + + if (SUCCEED != proxyconfig_prepare_rows(td, error)) + return FAIL; + + if (SUCCEED != proxyconfig_delete_rows(td, error)) + return FAIL; + + if (SUCCEED != proxyconfig_insert_rows(td, error)) + return FAIL; + + return proxyconfig_update_rows(td, error); +} + +/****************************************************************************** + * * + * Purpose: sync network discovery tables * + * * + * Parameters: config_tables - [IN] the received table data * + * error - [OUT] the error message * + * * + * Return value: SUCCEED - the tables were synced successfully * + * FAIL - otherwise * + * * + ******************************************************************************/ +static int proxyconfig_sync_network_discovery(zbx_vector_table_data_ptr_t *config_tables, char **error) +{ + zbx_table_data_t *dchecks; + + dchecks = proxyconfig_get_table(config_tables, "dchecks"); + + if (NULL != dchecks) + { + proxyconfig_prepare_table(dchecks, NULL, NULL, NULL); + + if (SUCCEED != proxyconfig_prepare_rows(dchecks, error)) + return FAIL; + + if (SUCCEED != proxyconfig_delete_rows(dchecks, error)) + return FAIL; + } + + if (SUCCEED != proxyconfig_sync_table(config_tables, "drules", error)) + return FAIL; + + if (NULL == dchecks) + return SUCCEED; + + if (SUCCEED != proxyconfig_insert_rows(dchecks, error)) + return FAIL; + + return proxyconfig_update_rows(dchecks, error); +} + +/****************************************************************************** + * * + * Purpose: sync global regular expression tables * + * * + * Parameters: config_tables - [IN] the received table data * + * error - [OUT] the error message * + * * + * Return value: SUCCEED - the tables were synced successfully * + * FAIL - otherwise * + * * + ******************************************************************************/ +static int proxyconfig_sync_regexps(zbx_vector_table_data_ptr_t *config_tables, char **error) +{ + zbx_table_data_t *expressions; + + expressions = proxyconfig_get_table(config_tables, "expressions"); + + if (NULL != expressions) + { + proxyconfig_prepare_table(expressions, NULL, NULL, NULL); + + if (SUCCEED != proxyconfig_prepare_rows(expressions, error)) + return FAIL; + + if (SUCCEED != proxyconfig_delete_rows(expressions, error)) + return FAIL; + } + + if (SUCCEED != proxyconfig_sync_table(config_tables, "regexps", error)) + return FAIL; + + if (NULL == expressions) + return SUCCEED; + + if (SUCCEED != proxyconfig_insert_rows(expressions, error)) + return FAIL; + + return proxyconfig_update_rows(expressions, error); +} + +/****************************************************************************** + * * + * Purpose: force proxy to re-send host availability data if server and proxy * + * interface availability value is different and block proxy from * + * updating interface availability in database * + * * + * Parameters: td - [IN] the interface table data * + * * + ******************************************************************************/ +static void proxyconfig_check_interface_availability(zbx_table_data_t *td) +{ + zbx_vector_uint64_t interfaceids; + int i, index; + + if (-1 == (index = table_data_get_field_index(td, "available"))) + return; + + zbx_vector_uint64_create(&interfaceids); + + for (i = 0; i < td->updates.values_num;) + { + if (SUCCEED == zbx_flags128_isset(&td->updates.values[i]->flags, index)) + { + zbx_flags128_t flags; + + zbx_vector_uint64_append(&interfaceids, td->updates.values[i]->recid); + zbx_flags128_clear(&td->updates.values[i]->flags, index); + + flags = td->updates.values[i]->flags; + zbx_flags128_clear(&flags, PROXYCONFIG_ROW_EXISTS); + if (SUCCEED == zbx_flags128_isclear(&flags)) + { + zbx_vector_table_row_ptr_remove(&td->updates, i); + continue; + } + } + + i++; + } + + if (0 != interfaceids.values_num) + DCtouch_interfaces_availability(&interfaceids); + + zbx_vector_uint64_destroy(&interfaceids); +} + +#define ZBX_PROXYCONFIG_GET_TABLE(table) \ + if (NULL == (table = proxyconfig_get_table(config_tables, #table))) \ + { \ + *error = zbx_strdup(NULL, "cannot find " #table " data"); \ + goto out; \ + } \ + zbx_vector_table_data_ptr_append(&host_tables, table) + +/****************************************************************************** + * * + * Purpose: sync host and related tables * + * * + * Parameters: config_tables - [IN] the received table data * + * full_sync - [IN] 1 if full sync must be done, 0 otherwise * + * table - [IN] the name of table to sync * + * error - [OUT] the error message * + * * + * Return value: SUCCEED - the tables were synced successfully * + * FAIL - otherwise * + * * + ******************************************************************************/ +static int proxyconfig_sync_hosts(zbx_vector_table_data_ptr_t *config_tables, int full_sync, char **error) +{ + zbx_table_data_t *hosts, *host_inventory, *interface, *interface_snmp, *items, *item_rtdata, + *item_preproc, *item_parameter, *httptest, *httptestitem, *httptest_field, + *httpstep, *httpstepitem, *httpstep_field; + int i, ret = FAIL; + zbx_vector_table_data_ptr_t host_tables; + + if (NULL == (hosts = proxyconfig_get_table(config_tables, "hosts"))) + return SUCCEED; + + zbx_vector_table_data_ptr_create(&host_tables); + zbx_vector_table_data_ptr_append(&host_tables, hosts); + + /* host related tables must always be present (even empty) if at least one host is synced */ + ZBX_PROXYCONFIG_GET_TABLE(host_inventory); + ZBX_PROXYCONFIG_GET_TABLE(interface); + ZBX_PROXYCONFIG_GET_TABLE(interface_snmp); + ZBX_PROXYCONFIG_GET_TABLE(items); + ZBX_PROXYCONFIG_GET_TABLE(item_rtdata); + ZBX_PROXYCONFIG_GET_TABLE(item_preproc); + ZBX_PROXYCONFIG_GET_TABLE(item_parameter); + ZBX_PROXYCONFIG_GET_TABLE(httptest); + ZBX_PROXYCONFIG_GET_TABLE(httptestitem); + ZBX_PROXYCONFIG_GET_TABLE(httptest_field); + ZBX_PROXYCONFIG_GET_TABLE(httpstep); + ZBX_PROXYCONFIG_GET_TABLE(httpstepitem); + ZBX_PROXYCONFIG_GET_TABLE(httpstep_field); + + if (0 == full_sync) + { + zbx_vector_uint64_t recids, hostids, interfaceids, itemids, httptestids, httpstepids; + zbx_hashset_iter_t iter; + zbx_table_row_t *row; + + zbx_vector_uint64_create(&recids); + zbx_vector_uint64_create(&hostids); + zbx_vector_uint64_create(&interfaceids); + zbx_vector_uint64_create(&itemids); + zbx_vector_uint64_create(&httptestids); + zbx_vector_uint64_create(&httpstepids); + + zbx_hashset_iter_reset(&hosts->rows, &iter); + while (NULL != (row = (zbx_table_row_t *)zbx_hashset_iter_next(&iter))) + zbx_vector_uint64_append(&recids, row->recid); + + proxyconfig_prepare_table(hosts, "hostid", &recids, &hostids); + proxyconfig_prepare_table(host_inventory, "hostid", &hostids, NULL); + proxyconfig_prepare_table(interface, "hostid", &hostids, &interfaceids); + proxyconfig_prepare_table(interface_snmp, "interfaceid", &interfaceids, NULL); + + proxyconfig_prepare_table(items, "hostid", &hostids, &itemids); + proxyconfig_prepare_table(item_rtdata, "itemid", &itemids, NULL); + proxyconfig_prepare_table(item_preproc, "itemid", &itemids, NULL); + proxyconfig_prepare_table(item_parameter, "itemid", &itemids, NULL); + + proxyconfig_prepare_table(httptest, "hostid", &hostids, &httptestids); + proxyconfig_prepare_table(httptestitem, "httptestid", &httptestids, NULL); + proxyconfig_prepare_table(httptest_field, "httptestid", &httptestids, NULL); + proxyconfig_prepare_table(httpstep, "httptestid", &httptestids, &httpstepids); + proxyconfig_prepare_table(httpstepitem, "httpstepid", &httpstepids, NULL); + proxyconfig_prepare_table(httpstep_field, "httpstepid", &httpstepids, NULL); + + zbx_vector_uint64_destroy(&httpstepids); + zbx_vector_uint64_destroy(&httptestids); + zbx_vector_uint64_destroy(&itemids); + zbx_vector_uint64_destroy(&interfaceids); + zbx_vector_uint64_destroy(&hostids); + zbx_vector_uint64_destroy(&recids); + } + else + { + proxyconfig_prepare_table(hosts, NULL, NULL, NULL); + proxyconfig_prepare_table(host_inventory, NULL, NULL, NULL); + proxyconfig_prepare_table(interface, NULL, NULL, NULL); + proxyconfig_prepare_table(interface_snmp, NULL, NULL, NULL); + + proxyconfig_prepare_table(items, NULL, NULL, NULL); + proxyconfig_prepare_table(item_rtdata, NULL, NULL, NULL); + proxyconfig_prepare_table(item_preproc, NULL, NULL, NULL); + proxyconfig_prepare_table(item_parameter, NULL, NULL, NULL); + + proxyconfig_prepare_table(httptest, NULL, NULL, NULL); + proxyconfig_prepare_table(httptestitem, NULL, NULL, NULL); + proxyconfig_prepare_table(httptest_field, NULL, NULL, NULL); + proxyconfig_prepare_table(httpstep, NULL, NULL, NULL); + proxyconfig_prepare_table(httpstepitem, NULL, NULL, NULL); + proxyconfig_prepare_table(httpstep_field, NULL, NULL, NULL); + } + + /* item_rtdata must be only inserted/removed and never updated */ + zbx_vector_table_row_ptr_clear(&item_rtdata->updates); + + /* interface availability changes are never updated in database, but must be marked in cache */ + proxyconfig_check_interface_availability(interface); + + /* remove rows in reverse order to avoid depending on cascaded deletes */ + for (i = host_tables.values_num - 1; 0 <= i; i--) + { + if (SUCCEED != proxyconfig_prepare_rows(host_tables.values[i], error)) + goto out; + + if (SUCCEED != proxyconfig_delete_rows(host_tables.values[i], error)) + goto out; + } + + for (i = 0; i < host_tables.values_num; i++) + { + if (SUCCEED != proxyconfig_insert_rows(host_tables.values[i], error)) + goto out; + + if (SUCCEED != proxyconfig_update_rows(host_tables.values[i], error)) + goto out; + } + + ret = SUCCEED; +out: + zbx_vector_table_data_ptr_destroy(&host_tables); + + return ret; +} + +/****************************************************************************** + * * + * Purpose: prepare hostmacro and hosts_templates tables * + * * + * Parameters: hostmacro - [IN] the hostmacro table * + * hosts_templates - [IN] the hosts templates table * + * full_sync - [IN] 1 if full sync must be done, 0 otherwise* + * * + ******************************************************************************/ +static void proxyconfig_prepare_hostmacros(zbx_table_data_t *hostmacro, zbx_table_data_t *hosts_templates, + int full_sync) +{ + zbx_vector_uint64_t hostids, *key_ids = NULL; + zbx_hashset_iter_t iter; + zbx_table_row_t *row; + char *key_field = NULL; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + + zbx_vector_uint64_create(&hostids); + + if (0 == full_sync) + { + /* limit the scope to the hosts sent with hostmacros or hosts_templates */ + zbx_hashset_iter_reset(&hostmacro->rows, &iter); + while (NULL != (row = (zbx_table_row_t *)zbx_hashset_iter_next(&iter))) + { + const char *pf; + char buf[ZBX_MAX_UINT64_LEN + 1]; + zbx_uint64_t hostid; + + pf = zbx_json_next(&row->columns, NULL); + + if (NULL != zbx_json_next_value(&row->columns, pf, buf, sizeof(buf), NULL) && + SUCCEED == zbx_is_uint64(buf, &hostid)) + { + zbx_vector_uint64_append(&hostids, hostid); + } + } + + zbx_hashset_iter_reset(&hosts_templates->rows, &iter); + while (NULL != (row = (zbx_table_row_t *)zbx_hashset_iter_next(&iter))) + { + const char *pf; + char buf[ZBX_MAX_UINT64_LEN + 1]; + zbx_uint64_t hostid; + + pf = zbx_json_next(&row->columns, NULL); + + if (NULL != zbx_json_next_value(&row->columns, pf, buf, sizeof(buf), NULL) && + SUCCEED == zbx_is_uint64(buf, &hostid)) + { + zbx_vector_uint64_append(&hostids, hostid); + } + } + + zbx_vector_uint64_sort(&hostids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); + zbx_vector_uint64_uniq(&hostids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); + + key_ids = &hostids; + key_field = "hostid"; + } + + proxyconfig_prepare_table(hostmacro, key_field, key_ids, NULL); + proxyconfig_prepare_table(hosts_templates, key_field, key_ids, NULL); + + zbx_vector_uint64_destroy(&hostids); + + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); +} + +/****************************************************************************** + * * + * Purpose: sync templates by creating empty templates when necessary to link * + * to other templates * + * * + * Parameters: hosts_templates - [IN] the hosts_temlates data * + * hostmacro - [IN] the hostmacro data * + * error - [OUT] the error message * + * * + * Return value: SUCCEED - the templates were synced successfully * + * FAIL - otherwise * + * * + ******************************************************************************/ +static int proxyconfig_sync_templates(zbx_table_data_t *hosts_templates, zbx_table_data_t *hostmacro, char **error) +{ + zbx_hashset_iter_t iter; + zbx_table_row_t *row; + zbx_vector_uint64_t templateids; + int ret; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + + zbx_vector_uint64_create(&templateids); + + zbx_hashset_iter_reset(&hosts_templates->rows, &iter); + while (NULL != (row = (zbx_table_row_t *)zbx_hashset_iter_next(&iter))) + { + const char *pf; + char buf[ZBX_MAX_UINT64_LEN + 1]; + zbx_uint64_t templateid; + + pf = zbx_json_next(&row->columns, NULL); + + if (NULL != (pf = zbx_json_next_value(&row->columns, pf, buf, sizeof(buf), NULL)) && + SUCCEED == zbx_is_uint64(buf, &templateid)) + { + zbx_vector_uint64_append(&templateids, templateid); + } + + if (NULL != zbx_json_next_value(&row->columns, pf, buf, sizeof(buf), NULL) && + SUCCEED == zbx_is_uint64(buf, &templateid)) + { + zbx_vector_uint64_append(&templateids, templateid); + } + } + + zbx_hashset_iter_reset(&hostmacro->rows, &iter); + while (NULL != (row = (zbx_table_row_t *)zbx_hashset_iter_next(&iter))) + { + const char *pf; + char buf[ZBX_MAX_UINT64_LEN + 1]; + zbx_uint64_t templateid; + + pf = zbx_json_next(&row->columns, NULL); + + if (NULL != zbx_json_next_value(&row->columns, pf, buf, sizeof(buf), NULL) && + SUCCEED == zbx_is_uint64(buf, &templateid)) + { + zbx_vector_uint64_append(&templateids, templateid); + } + } + + /* check for existing templates and create empty templates if necessary */ + if (0 != templateids.values_num) + { + DB_ROW dbrow; + DB_RESULT result; + char *sql = NULL; + size_t sql_alloc = 0, sql_offset = 0; + zbx_hashset_t templates; + zbx_db_insert_t db_insert; + int i; + + zbx_hashset_create(&templates, 100, ZBX_DEFAULT_UINT64_HASH_FUNC, ZBX_DEFAULT_UINT64_COMPARE_FUNC); + + zbx_vector_uint64_sort(&templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); + zbx_vector_uint64_uniq(&templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); + + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "select hostid from hosts where"); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid", templateids.values, + templateids.values_num); + + result = DBselect("%s", sql); + zbx_free(sql); + + while (NULL != (dbrow = DBfetch(result))) + { + zbx_uint64_t templateid; + + ZBX_STR2UINT64(templateid, dbrow[0]); + zbx_hashset_insert(&templates, &templateid, sizeof(templateid)); + } + DBfree_result(result); + + zbx_db_insert_prepare(&db_insert, "hosts", "hostid", "status", NULL); + + for (i = 0; i < templateids.values_num; i++) + { + if (NULL != zbx_hashset_search(&templates, &templateids.values[i])) + continue; + + zbx_db_insert_add_values(&db_insert, templateids.values[i], (int)HOST_STATUS_TEMPLATE); + } + + ret = zbx_db_insert_execute(&db_insert); + zbx_db_insert_clean(&db_insert); + + zbx_hashset_destroy(&templates); + + if (SUCCEED != ret) + goto out; + } + + if (SUCCEED != proxyconfig_insert_rows(hosts_templates, error)) + goto out; + + ret = proxyconfig_update_rows(hosts_templates, error); +out: + zbx_vector_uint64_destroy(&templateids); + + zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); + + return ret; +} + +/****************************************************************************** + * * + * Purpose: sync received configuration data * + * * + * Parameters: config_tables - [IN] the received table data * + * full_sync - [IN] 1 if full sync must be done, 0 otherwise * + * error - [OUT] the error message * + * * + * Return value: SUCCEED - the tables were synced successfully * + * FAIL - otherwise * + * * + ******************************************************************************/ +static int proxyconfig_sync_data(zbx_vector_table_data_ptr_t *config_tables, int full_sync, char **error) +{ + zbx_table_data_t *hostmacro, *hosts_templates; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + + /* first sync isolated tables without relations to other tables */ + + if (SUCCEED != proxyconfig_sync_table(config_tables, "globalmacro", error)) + return FAIL; + + if (SUCCEED != proxyconfig_sync_table(config_tables, "config_autoreg_tls", error)) + return FAIL; + + if (SUCCEED != proxyconfig_sync_table(config_tables, "config", error)) + return FAIL; + + /* process related tables by scope */ + + if (SUCCEED != proxyconfig_sync_network_discovery(config_tables, error)) + return FAIL; + + if (SUCCEED != proxyconfig_sync_regexps(config_tables, error)) + return FAIL; + + if (NULL != (hostmacro = proxyconfig_get_table(config_tables, "hostmacro"))) + { + if (NULL == (hosts_templates = proxyconfig_get_table(config_tables, "hosts_templates"))) + { + *error = zbx_strdup(NULL, "cannot find host template data"); + return FAIL; + } + + proxyconfig_prepare_hostmacros(hostmacro, hosts_templates, full_sync); + + if (SUCCEED != proxyconfig_prepare_rows(hostmacro, error)) + return FAIL; + + if (SUCCEED != proxyconfig_delete_rows(hostmacro, error)) + return FAIL; + + if (SUCCEED != proxyconfig_prepare_rows(hosts_templates, error)) + return FAIL; + + if (SUCCEED != proxyconfig_delete_rows(hosts_templates, error)) + return FAIL; + } + + if (SUCCEED != proxyconfig_sync_hosts(config_tables, full_sync, error)) + return FAIL; + + if (NULL != hostmacro) + { + if (SUCCEED != proxyconfig_sync_templates(hosts_templates, hostmacro, error)) + return FAIL; + + if (SUCCEED != proxyconfig_insert_rows(hostmacro, error)) + return FAIL; + + if (SUCCEED != proxyconfig_update_rows(hostmacro, error)) + return FAIL; + } + + zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); + + return SUCCEED; +} + +/****************************************************************************** + * * + * Purpose: delete unmonitored hosts and their contents * + * * + * Parameters: hostids - [IN] identifiers of the hosts to delete * + * error - [OUT] the error message * + * * + * Return value: SUCCEED - the hosts were deleted successfully * + * FAIL - otherwise * + * * + ******************************************************************************/ +static int proxyconfig_delete_hosts(const zbx_vector_uint64_t *hostids, char **error) +{ + char *sql = NULL; + size_t sql_alloc = 0, sql_offset = 0; + int ret = FAIL; + zbx_vector_uint64_t itemids, httptestids, httpstepids; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + + zbx_vector_uint64_create(&itemids); + zbx_vector_uint64_create(&httptestids); + zbx_vector_uint64_create(&httpstepids); + + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select itemid from items where"); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid", hostids->values, hostids->values_num); + DBselect_uint64(sql, &itemids); + + sql_offset = 0; + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select httptestid from httptest where"); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid", hostids->values, hostids->values_num); + DBselect_uint64(sql, &httptestids); + + if (0 != httptestids.values_num) + { + sql_offset = 0; + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select httpstepid from httpstep where"); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "httptestid", httptestids.values, + httptestids.values_num); + DBselect_uint64(sql, &httpstepids); + + if (0 != httpstepids.values_num) + { + sql_offset = 0; + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from httpstep_field where"); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "httpstepid", httpstepids.values, + httpstepids.values_num); + if (ZBX_DB_OK > DBexecute("%s", sql)) + goto out; + + sql_offset = 0; + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from httpstepitem where"); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "httpstepid", httpstepids.values, + httpstepids.values_num); + if (ZBX_DB_OK > DBexecute("%s", sql)) + goto out; + + sql_offset = 0; + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from httpstep where"); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "httpstepid", httpstepids.values, + httpstepids.values_num); + if (ZBX_DB_OK > DBexecute("%s", sql)) + goto out; + + } + sql_offset = 0; + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from httptest_field where"); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "httptestid", httptestids.values, + httptestids.values_num); + if (ZBX_DB_OK > DBexecute("%s", sql)) + goto out; + + sql_offset = 0; + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from httptestitem where"); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "httptestid", httptestids.values, + httptestids.values_num); + if (ZBX_DB_OK > DBexecute("%s", sql)) + goto out; + + sql_offset = 0; + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from httptest where"); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "httptestid", httptestids.values, + httptestids.values_num); + if (ZBX_DB_OK > DBexecute("%s", sql)) + goto out; + } + + if (0 != itemids.values_num) + { + sql_offset = 0; + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from item_preproc where"); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid", itemids.values, itemids.values_num); + if (ZBX_DB_OK > DBexecute("%s", sql)) + goto out; + + sql_offset = 0; + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "update items set master_itemid=null where"); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid", itemids.values, itemids.values_num); + if (ZBX_DB_OK > DBexecute("%s", sql)) + goto out; + + sql_offset = 0; + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from items where"); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid", itemids.values, itemids.values_num); + if (ZBX_DB_OK > DBexecute("%s", sql)) + goto out; + } + + sql_offset = 0; + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from hosts where"); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid", hostids->values, hostids->values_num); + if (ZBX_DB_OK > DBexecute("%s", sql)) + goto out; + + ret = SUCCEED; +out: + zbx_free(sql); + + zbx_vector_uint64_destroy(&httpstepids); + zbx_vector_uint64_destroy(&httptestids); + zbx_vector_uint64_destroy(&itemids); + + if (SUCCEED != ret) + *error = zbx_strdup(NULL, "cannot delete hosts"); + + zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); + + return ret; +} + +/****************************************************************************** + * * + * Purpose: delete corresponding records when all macros are removed/templates* + * unlinked from a host * + * * + * Parameters: hostids - [IN] identifiers of the cleared hosts * + * error - [OUT] the error message * + * * + * Return value: SUCCEED - the hosts were cleared successfully * + * FAIL - otherwise * + * * + ******************************************************************************/ +static int proxyconfig_delete_hostmacros(const zbx_vector_uint64_t *hostids, char **error) +{ + char *sql = NULL; + size_t sql_alloc = 0, sql_offset = 0; + int ret = FAIL; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from hostmacro where"); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid", hostids->values, hostids->values_num); + if (ZBX_DB_OK > DBexecute("%s", sql)) + goto out; + + sql_offset = 0; + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from hosts_templates where"); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid", hostids->values, hostids->values_num); + if (ZBX_DB_OK > DBexecute("%s", sql)) + goto out; + + ret = SUCCEED; + +out: + zbx_free(sql); + + if (FAIL == ret) + *error = zbx_strdup(NULL, "cannot delete host macros"); + + zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); + + return ret; +} + +/****************************************************************************** + * * + * Purpose: delete all global macros * + * * + * Return value: SUCCEED - the global macros were deleted successfully * + * FAIL - otherwise * + * * + ******************************************************************************/ +static int proxyconfig_delete_globalmacros(char **error) +{ + int ret; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + + if (ZBX_DB_OK > DBexecute("delete from globalmacro")) + { + *error = zbx_strdup(NULL, "cannot delete global macros"); + ret = FAIL; + } + else + ret = SUCCEED; + + zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); + + return ret; +} + +#define proxyconfig_ZBX_TABLE_NUM 24 + +/****************************************************************************** + * * + * Purpose: update configuration * + * * + ******************************************************************************/ +int zbx_proxyconfig_process(const char *addr, struct zbx_json_parse *jp, char **error) +{ + zbx_vector_table_data_ptr_t config_tables; + int ret = SUCCEED, full_sync = 0, delete_globalmacros = 0, loglevel; + char tmp[ZBX_MAX_UINT64_LEN + 1]; + struct zbx_json_parse jp_data = {NULL, NULL}, jp_del_hostids = {NULL, NULL}, + jp_del_macro_hostids = {NULL, NULL}; + zbx_uint64_t config_revision; + zbx_vector_uint64_t del_hostids, del_macro_hostids; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + + (void)zbx_json_brackets_by_name(jp, ZBX_PROTO_TAG_DATA, &jp_data); + (void)zbx_json_brackets_by_name(jp, ZBX_PROTO_TAG_REMOVED_HOSTIDS, &jp_del_hostids); + (void)zbx_json_brackets_by_name(jp, ZBX_PROTO_TAG_REMOVED_MACRO_HOSTIDS, &jp_del_macro_hostids); + + if ((NULL == jp_data.start || 1 == jp_data.end - jp_data.start) && NULL == jp_del_hostids.start && + NULL == jp_del_macro_hostids.start) + { + loglevel = LOG_LEVEL_DEBUG; + } + else + loglevel = LOG_LEVEL_WARNING; + + zabbix_log(loglevel, "received configuration data from server at \"%s\", datalen " ZBX_FS_SSIZE_T, + addr, jp->end - jp->start + 1); + + if (1 == jp->end - jp->start) + { + /* no configuration updates */ + goto out; + } + + if (SUCCEED != (ret = zbx_json_value_by_name(jp, ZBX_PROTO_TAG_CONFIG_REVISION, tmp, sizeof(tmp), NULL))) + { + *error = zbx_strdup(NULL, "no config_revision tag in proxy configuration response"); + goto out; + } + + if (SUCCEED != (ret = zbx_is_uint64(tmp, &config_revision))) + { + *error = zbx_strdup(NULL, "invalid config_revision value in proxy configuration response"); + goto out; + } + + if (SUCCEED == zbx_json_value_by_name(jp, ZBX_PROTO_TAG_FULL_SYNC, tmp, sizeof(tmp), NULL)) + full_sync = atoi(tmp); + + zbx_vector_table_data_ptr_create(&config_tables); + zbx_vector_table_data_ptr_reserve(&config_tables, proxyconfig_ZBX_TABLE_NUM); + zbx_vector_uint64_create(&del_hostids); + zbx_vector_uint64_create(&del_macro_hostids); + + if (NULL != jp_data.start) + { + if (SUCCEED != (ret = proxyconfig_parse_data(&jp_data, &config_tables, error))) + goto clean; + + if (SUCCEED == ZBX_CHECK_LOG_LEVEL(LOG_LEVEL_TRACE)) + proxyconfig_dump_data(&config_tables); + + proxyconfig_add_default_tables(&config_tables); + } + + if (NULL != jp_del_hostids.start) + { + const char *p; + zbx_uint64_t hostid; + + for (p = 0; NULL != (p = zbx_json_next_value(&jp_del_hostids, p, tmp, sizeof(tmp), NULL));) + { + if (SUCCEED == zbx_is_uint64(tmp, &hostid)) + zbx_vector_uint64_append(&del_hostids, hostid); + } + } + + if (NULL != jp_del_macro_hostids.start) + { + const char *p; + zbx_uint64_t hostid; + + for (p = 0; NULL != (p = zbx_json_next_value(&jp_del_macro_hostids, p, tmp, sizeof(tmp), NULL));) + { + if (SUCCEED == zbx_is_uint64(tmp, &hostid)) + { + if (0 != hostid) + zbx_vector_uint64_append(&del_macro_hostids, hostid); + else + delete_globalmacros = 1; + } + } + } + + DBbegin(); + + if (0 != config_tables.values_num) + ret = proxyconfig_sync_data(&config_tables, full_sync, error); + + if (SUCCEED == ret && 0 != del_hostids.values_num) + ret = proxyconfig_delete_hosts(&del_hostids, error); + + if (SUCCEED == ret && 0 != del_macro_hostids.values_num) + ret = proxyconfig_delete_hostmacros(&del_macro_hostids, error); + + if (SUCCEED == ret && 0 != delete_globalmacros) + ret = proxyconfig_delete_globalmacros(error); + + if (SUCCEED == ret) + { + if (ZBX_DB_OK == DBcommit()) + zbx_dc_update_received_revision(config_revision); + } + else + DBrollback(); +clean: + zbx_vector_uint64_destroy(&del_macro_hostids); + zbx_vector_uint64_destroy(&del_hostids); + zbx_vector_table_data_ptr_clear_ext(&config_tables, table_data_free); + zbx_vector_table_data_ptr_destroy(&config_tables); + +out: + zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); + + return ret; +} + +/****************************************************************************** + * * + * Purpose: receive configuration tables from server (passive proxies) * + * * + ******************************************************************************/ +void zbx_recv_proxyconfig(zbx_socket_t *sock, const zbx_config_tls_t *zbx_config_tls) +{ + struct zbx_json_parse jp_config, jp_kvs_paths = {0}; + int ret; + struct zbx_json j; + char *error = NULL; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + + if (SUCCEED != check_access_passive_proxy(sock, ZBX_SEND_RESPONSE, "configuration update", zbx_config_tls)) + goto out; + + zbx_json_init(&j, 1024); + zbx_json_addstring(&j, ZBX_PROTO_TAG_VERSION, ZABBIX_VERSION, ZBX_JSON_TYPE_STRING); + zbx_json_addstring(&j, ZBX_PROTO_TAG_SESSION, zbx_dc_get_session_token(), ZBX_JSON_TYPE_STRING); + zbx_json_adduint64(&j, ZBX_PROTO_TAG_CONFIG_REVISION, (zbx_uint64_t)zbx_dc_get_received_revision()); + + if (SUCCEED != zbx_tcp_send_ext(sock, j.buffer, j.buffer_size, 0, (unsigned char)sock->protocol, + CONFIG_TIMEOUT)) + { + zabbix_log(LOG_LEVEL_WARNING, "cannot send proxy configuration information to sever at \"%s\": %s", + sock->peer, zbx_json_strerror()); + goto out; + } + + if (FAIL == zbx_tcp_recv_ext(sock, CONFIG_TRAPPER_TIMEOUT, ZBX_TCP_LARGE)) + { + zabbix_log(LOG_LEVEL_WARNING, "cannot receive proxy configuration data from server at \"%s\": %s", + sock->peer, zbx_json_strerror()); + goto out; + } + + if (NULL == sock->buffer) + { + zabbix_log(LOG_LEVEL_WARNING, "cannot parse empty proxy configuration data received from server at" + " \"%s\"", sock->peer); + zbx_send_proxy_response(sock, FAIL, "cannot parse empty data", CONFIG_TIMEOUT); + goto out; + } + + if (SUCCEED != (ret = zbx_json_open(sock->buffer, &jp_config))) + { + zabbix_log(LOG_LEVEL_WARNING, "cannot parse proxy configuration data received from server at" + " \"%s\": %s", sock->peer, zbx_json_strerror()); + zbx_send_proxy_response(sock, ret, zbx_json_strerror(), CONFIG_TIMEOUT); + goto out; + } + + if (SUCCEED == (ret = zbx_proxyconfig_process(sock->peer, &jp_config, &error))) + { + if (SUCCEED == zbx_rtc_reload_config_cache(&error)) + { + if (SUCCEED == zbx_json_brackets_by_name(&jp_config, ZBX_PROTO_TAG_MACRO_SECRETS, &jp_kvs_paths)) + DCsync_kvs_paths(&jp_kvs_paths); + } + else + { + THIS_SHOULD_NEVER_HAPPEN; + zabbix_log(LOG_LEVEL_WARNING, "cannot send message to configuration syncer: %s", error); + zbx_free(error); + } + } + else + { + zabbix_log(LOG_LEVEL_WARNING, "cannot process proxy onfiguration data received from server at" + " \"%s\": %s", sock->peer, error); + } + zbx_send_proxy_response(sock, ret, error, CONFIG_TIMEOUT); + zbx_free(error); +out: + zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); +} diff --git a/src/zabbix_proxy/heart/heart.h b/src/zabbix_proxy/proxyconfigwrite/proxyconfig_write.h index 41d951cc819..c88200a340d 100644 --- a/src/zabbix_proxy/heart/heart.h +++ b/src/zabbix_proxy/proxyconfigwrite/proxyconfig_write.h @@ -17,22 +17,14 @@ ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. **/ -#ifndef ZABBIX_HEART_H -#define ZABBIX_HEART_H - -#include "zbxthreads.h" +#ifndef ZABBIX_PROXYCONFIG_READ_H +#define ZABBIX_PROXYCONFIG_READ_H #include "zbxcomms.h" +#include "zbxjson.h" -extern int CONFIG_HEARTBEAT_FREQUENCY; - -typedef struct -{ - zbx_config_tls_t *zbx_config_tls; - zbx_get_program_type_f zbx_get_program_type_cb_arg; -} -zbx_thread_heart_args; +int zbx_proxyconfig_process(const char *addr, struct zbx_json_parse *jp, char **error); -ZBX_THREAD_ENTRY(heart_thread, args); +void zbx_recv_proxyconfig(zbx_socket_t *sock, const zbx_config_tls_t *zbx_config_tls); #endif diff --git a/src/zabbix_proxy/stats/zabbix_stats.h b/src/zabbix_proxy/stats/zabbix_stats.h index 10b610ef9f0..608d63ad1f5 100644 --- a/src/zabbix_proxy/stats/zabbix_stats.h +++ b/src/zabbix_proxy/stats/zabbix_stats.h @@ -21,7 +21,8 @@ #define ZABBIX_ZABBIX_STATS_H_ #include "zbxjson.h" +#include "zbxstats.h" -void zbx_get_zabbix_stats_ext(struct zbx_json *json); +void zbx_zabbix_stats_ext_get(struct zbx_json *json, const zbx_config_comms_args_t *zbx_config); #endif /* ZABBIX_ZABBIX_STATS_H_ */ diff --git a/src/zabbix_proxy/stats/zabbix_stats_proxy.c b/src/zabbix_proxy/stats/zabbix_stats_proxy.c index 1c230ee3162..2ab441acc48 100644 --- a/src/zabbix_proxy/stats/zabbix_stats_proxy.c +++ b/src/zabbix_proxy/stats/zabbix_stats_proxy.c @@ -18,22 +18,47 @@ **/ #include "zabbix_stats.h" - -#include "zbxcommon.h" +#include "proxy.h" +#include "zbxcomms.h" +#include "zbxjson.h" +#include "zbxstr.h" /****************************************************************************** * * * Purpose: get program type (proxy) specific internal statistics * * * - * Parameters: json - [IN/OUT] the json data * + * Parameters: json - [OUT] the json data * + * zbx_config - [IN] proxy config * * * * Comments: This function is used to gather proxy specific internal * * statistics. * * * ******************************************************************************/ -void zbx_get_zabbix_stats_ext(struct zbx_json *json) +void zbx_zabbix_stats_ext_get(struct zbx_json *json, const zbx_config_comms_args_t *zbx_config) { - ZBX_UNUSED(json); + unsigned int encryption; + + zbx_json_addstring(json, "name", ZBX_NULL2EMPTY_STR(zbx_config->hostname), ZBX_JSON_TYPE_STRING); + + if (ZBX_PROXYMODE_PASSIVE == zbx_config->proxymode) + { + zbx_json_addstring(json, "passive", "true", ZBX_JSON_TYPE_INT); + encryption = zbx_config->zbx_config_tls->accept_modes; + } + else + { + zbx_json_addstring(json, "passive", "false", ZBX_JSON_TYPE_INT); + encryption = zbx_config->zbx_config_tls->connect_mode; + } + + zbx_json_addstring(json, ZBX_TCP_SEC_UNENCRYPTED_TXT, + 0 < (encryption & ZBX_TCP_SEC_UNENCRYPTED) ? "true" : "false", ZBX_JSON_TYPE_INT); + + zbx_json_addstring(json, ZBX_TCP_SEC_TLS_PSK_TXT, + 0 < (encryption & ZBX_TCP_SEC_TLS_PSK) ? "true" : "false", ZBX_JSON_TYPE_INT); + + zbx_json_addstring(json, ZBX_TCP_SEC_TLS_CERT_TXT, + 0 < (encryption & ZBX_TCP_SEC_TLS_CERT) ? "true" : "false", ZBX_JSON_TYPE_INT); return; } diff --git a/src/zabbix_proxy/taskmanager/server_tasks.c b/src/zabbix_proxy/taskmanager/server_tasks.c index 6c4c7e2908d..d68a980fb20 100644 --- a/src/zabbix_proxy/taskmanager/server_tasks.c +++ b/src/zabbix_proxy/taskmanager/server_tasks.c @@ -20,24 +20,28 @@ #include "zbxtasks.h" #include "zbxnum.h" #include "zbxdbhigh.h" +#include "zbxversion.h" /****************************************************************************** * * * Purpose: get tasks scheduled to be executed on the server * * * - * Parameters: tasks - [OUT] the tasks to execute * - * proxy_hostid - [IN] (ignored) * + * Parameters: tasks - [OUT] the tasks to execute * + * proxy_hostid - [IN] (ignored) * + * compatibility - [IN] (ignored) * * * * Comments: This function is used by proxy to get tasks to be sent to the * * server. * * * ******************************************************************************/ -void zbx_tm_get_remote_tasks(zbx_vector_ptr_t *tasks, zbx_uint64_t proxy_hostid) +void zbx_tm_get_remote_tasks(zbx_vector_ptr_t *tasks, zbx_uint64_t proxy_hostid, + zbx_proxy_compatibility_t compatibility) { DB_RESULT result; DB_ROW row; ZBX_UNUSED(proxy_hostid); + ZBX_UNUSED(compatibility); result = DBselect( "select t.taskid,t.type,t.clock,t.ttl," diff --git a/src/zabbix_proxy/taskmanager/taskmanager.c b/src/zabbix_proxy/taskmanager/taskmanager.c index 09b39a005c3..ec67459511f 100644 --- a/src/zabbix_proxy/taskmanager/taskmanager.c +++ b/src/zabbix_proxy/taskmanager/taskmanager.c @@ -78,7 +78,7 @@ static int tm_execute_remote_command(zbx_uint64_t taskid, int clock, int ttl, in if (NULL == (row = DBfetch(result))) goto finish; - task = zbx_tm_task_create(0, ZBX_TM_TASK_REMOTE_COMMAND_RESULT, ZBX_TM_STATUS_NEW, time(NULL), 0, 0); + task = zbx_tm_task_create(0, ZBX_TM_TASK_REMOTE_COMMAND_RESULT, ZBX_TM_STATUS_NEW, zbx_time(), 0, 0); ZBX_STR2UINT64(parent_taskid, row[9]); @@ -195,7 +195,7 @@ static int tm_process_check_now(zbx_vector_uint64_t *taskids) DBfree_result(result); if (0 != (processed_num = itemids.values_num)) - zbx_dc_reschedule_items(&itemids, time(NULL), NULL); + zbx_dc_reschedule_items(&itemids, zbx_time(), NULL); if (0 != taskids->values_num) { @@ -223,7 +223,7 @@ static int tm_process_check_now(zbx_vector_uint64_t *taskids) * FAIL - otherwise * * * ******************************************************************************/ -static int tm_execute_data_json(int type, const char *data, char **info) +static int tm_execute_data_json(int type, const char *data, char **info, const zbx_config_comms_args_t *zbx_config) { struct zbx_json_parse jp_data; @@ -236,7 +236,7 @@ static int tm_execute_data_json(int type, const char *data, char **info) switch (type) { case ZBX_TM_DATA_TYPE_TEST_ITEM: - return zbx_trapper_item_test_run(&jp_data, 0, info); + return zbx_trapper_item_test_run(&jp_data, 0, info, zbx_config); case ZBX_TM_DATA_TYPE_DIAGINFO: return zbx_diag_get_info(&jp_data, info); } @@ -255,7 +255,8 @@ static int tm_execute_data_json(int type, const char *data, char **info) * FAIL - otherwise * * * ******************************************************************************/ -static int tm_execute_data(zbx_ipc_async_socket_t *rtc, zbx_uint64_t taskid, int clock, int ttl, int now) +static int tm_execute_data(zbx_ipc_async_socket_t *rtc, zbx_uint64_t taskid, int clock, int ttl, int now, + const zbx_config_comms_args_t *zbx_config) { DB_ROW row; DB_RESULT result; @@ -272,7 +273,7 @@ static int tm_execute_data(zbx_ipc_async_socket_t *rtc, zbx_uint64_t taskid, int if (NULL == (row = DBfetch(result))) goto finish; - task = zbx_tm_task_create(0, ZBX_TM_TASK_DATA_RESULT, ZBX_TM_STATUS_NEW, time(NULL), 0, 0); + task = zbx_tm_task_create(0, ZBX_TM_TASK_DATA_RESULT, ZBX_TM_STATUS_NEW, zbx_time(), 0, 0); ZBX_STR2UINT64(parent_taskid, row[0]); if (0 != ttl && clock + ttl < now) @@ -285,7 +286,7 @@ static int tm_execute_data(zbx_ipc_async_socket_t *rtc, zbx_uint64_t taskid, int { case ZBX_TM_DATA_TYPE_TEST_ITEM: case ZBX_TM_DATA_TYPE_DIAGINFO: - ret = tm_execute_data_json(data_type, row[1], &info); + ret = tm_execute_data_json(data_type, row[1], &info, zbx_config); break; case ZBX_TM_DATA_TYPE_ACTIVE_PROXY_CONFIG_RELOAD: if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_ACTIVE)) @@ -324,7 +325,7 @@ finish: * Return value: The number of successfully processed tasks * * * ******************************************************************************/ -static int tm_process_tasks(zbx_ipc_async_socket_t *rtc, int now) +static int tm_process_tasks(zbx_ipc_async_socket_t *rtc, int now, const zbx_config_comms_args_t *zbx_config) { DB_ROW row; DB_RESULT result; @@ -359,7 +360,7 @@ static int tm_process_tasks(zbx_ipc_async_socket_t *rtc, int now) zbx_vector_uint64_append(&check_now_taskids, taskid); break; case ZBX_TM_TASK_DATA: - if (SUCCEED == tm_execute_data(rtc, taskid, clock, ttl, now)) + if (SUCCEED == tm_execute_data(rtc, taskid, clock, ttl, now, zbx_config)) processed_num++; break; default: @@ -440,10 +441,11 @@ ZBX_THREAD_ENTRY(taskmanager_thread, args) get_program_type_string(taskmanager_args_in->zbx_get_program_type_cb_arg()), server_num, get_process_type_string(process_type), process_num); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) - zbx_tls_init_child(taskmanager_args_in->zbx_config_tls, taskmanager_args_in->zbx_get_program_type_cb_arg); + zbx_tls_init_child(taskmanager_args_in->zbx_config->zbx_config_tls, + taskmanager_args_in->zbx_get_program_type_cb_arg); #endif zbx_setproctitle("%s [connecting to the database]", get_process_type_string(process_type)); DBconnect(ZBX_DB_CONNECT_NORMAL); @@ -481,7 +483,7 @@ ZBX_THREAD_ENTRY(taskmanager_thread, args) zbx_setproctitle("%s [processing tasks]", get_process_type_string(process_type)); - tasks_num = tm_process_tasks(&rtc, (int)sec1); + tasks_num = tm_process_tasks(&rtc, (int)sec1, taskmanager_args_in->zbx_config); if (ZBX_TM_CLEANUP_PERIOD <= sec1 - cleanup_time) { tm_remove_old_tasks((int)sec1); diff --git a/src/zabbix_proxy/taskmanager/taskmanager.h b/src/zabbix_proxy/taskmanager/taskmanager.h index c4125bd1456..c8d15e359a9 100644 --- a/src/zabbix_proxy/taskmanager/taskmanager.h +++ b/src/zabbix_proxy/taskmanager/taskmanager.h @@ -26,7 +26,7 @@ typedef struct { - zbx_config_tls_t *zbx_config_tls; + const zbx_config_comms_args_t *zbx_config; zbx_get_program_type_f zbx_get_program_type_cb_arg; } zbx_thread_taskmanager_args; diff --git a/src/zabbix_server/Makefile.am b/src/zabbix_server/Makefile.am index 4dbb8b72fdf..12295cfac89 100644 --- a/src/zabbix_server/Makefile.am +++ b/src/zabbix_server/Makefile.am @@ -27,7 +27,8 @@ SUBDIRS = \ lld \ reporter \ service \ - ha + ha \ + proxyconfigread sbin_PROGRAMS = zabbix_server @@ -69,6 +70,7 @@ zabbix_server_LDADD = \ httppoller/libzbxhttppoller.a \ escalator/libzbxescalator.a \ proxypoller/libzbxproxypoller.a \ + proxyconfigread/libzbxproxyconfigread.a \ selfmon/libzbxselfmon.a \ vmware/libzbxvmware.a \ taskmanager/libzbxtaskmanager.a \ diff --git a/src/zabbix_server/actions.c b/src/zabbix_server/actions.c index 6d91f311b72..02880e50e0d 100644 --- a/src/zabbix_server/actions.c +++ b/src/zabbix_server/actions.c @@ -140,7 +140,7 @@ static int check_host_group_condition(const zbx_vector_ptr_t *esc_events, zbx_co zbx_vector_uint64_t objectids, groupids; zbx_uint64_t condition_value; - if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_NOT_EQUAL != condition->op) + if (ZBX_CONDITION_OPERATOR_EQUAL != condition->op && ZBX_CONDITION_OPERATOR_NOT_EQUAL != condition->op) return NOTSUPPORTED; ZBX_STR2UINT64(condition_value, condition->value); @@ -172,7 +172,7 @@ static int check_host_group_condition(const zbx_vector_ptr_t *esc_events, zbx_co zbx_uint64_t objectid; ZBX_STR2UINT64(objectid, row[0]); - if (CONDITION_OPERATOR_NOT_EQUAL == condition->op) + if (ZBX_CONDITION_OPERATOR_NOT_EQUAL == condition->op) { int index; @@ -188,7 +188,7 @@ static int check_host_group_condition(const zbx_vector_ptr_t *esc_events, zbx_co } DBfree_result(result); - if (CONDITION_OPERATOR_NOT_EQUAL == condition->op) + if (ZBX_CONDITION_OPERATOR_NOT_EQUAL == condition->op) { int i; @@ -330,7 +330,7 @@ static void check_object_hierarchy(int object, const zbx_vector_ptr_t *esc_event if (value == condition_value) { - if (CONDITION_OPERATOR_EQUAL != condition->op) + if (ZBX_CONDITION_OPERATOR_EQUAL != condition->op) { int j; @@ -375,7 +375,7 @@ static void check_object_hierarchy(int object, const zbx_vector_ptr_t *esc_event } /* equals are deleted so copy to result those that are left (not equals) */ - if (CONDITION_OPERATOR_NOT_EQUAL == condition->op) + if (ZBX_CONDITION_OPERATOR_NOT_EQUAL == condition->op) { for (i = 0; i < objectids->values_num; i++) add_condition_match(esc_events, condition, objectids->values[i], object); @@ -407,7 +407,7 @@ static int check_host_template_condition(const zbx_vector_ptr_t *esc_events, zbx zbx_vector_uint64_t objectids; zbx_vector_uint64_pair_t objectids_pair; - if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_NOT_EQUAL != condition->op) + if (ZBX_CONDITION_OPERATOR_EQUAL != condition->op && ZBX_CONDITION_OPERATOR_NOT_EQUAL != condition->op) return NOTSUPPORTED; zbx_vector_uint64_create(&objectids); @@ -470,9 +470,9 @@ static int check_host_condition(const zbx_vector_ptr_t *esc_events, zbx_conditio zbx_vector_uint64_t objectids; zbx_uint64_t condition_value; - if (CONDITION_OPERATOR_EQUAL == condition->op) + if (ZBX_CONDITION_OPERATOR_EQUAL == condition->op) operation = " and"; - else if (CONDITION_OPERATOR_NOT_EQUAL == condition->op) + else if (ZBX_CONDITION_OPERATOR_NOT_EQUAL == condition->op) operation = " and not"; else return NOTSUPPORTED; @@ -530,7 +530,7 @@ static int check_trigger_id_condition(const zbx_vector_ptr_t *esc_events, zbx_co zbx_vector_uint64_pair_t objectids_pair; int i; - if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_NOT_EQUAL != condition->op) + if (ZBX_CONDITION_OPERATOR_EQUAL != condition->op && ZBX_CONDITION_OPERATOR_NOT_EQUAL != condition->op) return NOTSUPPORTED; ZBX_STR2UINT64(condition_value, condition->value); @@ -544,7 +544,7 @@ static int check_trigger_id_condition(const zbx_vector_ptr_t *esc_events, zbx_co if (event->objectid == condition_value) { - if (CONDITION_OPERATOR_EQUAL == condition->op) + if (ZBX_CONDITION_OPERATOR_EQUAL == condition->op) zbx_vector_uint64_append(&condition->eventids, event->eventid); } else @@ -585,7 +585,7 @@ static int check_trigger_name_condition(const zbx_vector_ptr_t *esc_events, zbx_ { int i; - if (CONDITION_OPERATOR_LIKE != condition->op && CONDITION_OPERATOR_NOT_LIKE != condition->op) + if (ZBX_CONDITION_OPERATOR_LIKE != condition->op && ZBX_CONDITION_OPERATOR_NOT_LIKE != condition->op) return NOTSUPPORTED; for (i = 0; i < esc_events->values_num; i++) @@ -594,11 +594,11 @@ static int check_trigger_name_condition(const zbx_vector_ptr_t *esc_events, zbx_ switch (condition->op) { - case CONDITION_OPERATOR_LIKE: + case ZBX_CONDITION_OPERATOR_LIKE: if (NULL != strstr(event->name, condition->value)) zbx_vector_uint64_append(&condition->eventids, event->eventid); break; - case CONDITION_OPERATOR_NOT_LIKE: + case ZBX_CONDITION_OPERATOR_NOT_LIKE: if (NULL == strstr(event->name, condition->value)) zbx_vector_uint64_append(&condition->eventids, event->eventid); break; @@ -633,19 +633,19 @@ static int check_trigger_severity_condition(const zbx_vector_ptr_t *esc_events, switch (condition->op) { - case CONDITION_OPERATOR_EQUAL: + case ZBX_CONDITION_OPERATOR_EQUAL: if (event->trigger.priority == condition_value) zbx_vector_uint64_append(&condition->eventids, event->eventid); break; - case CONDITION_OPERATOR_NOT_EQUAL: + case ZBX_CONDITION_OPERATOR_NOT_EQUAL: if (event->trigger.priority != condition_value) zbx_vector_uint64_append(&condition->eventids, event->eventid); break; - case CONDITION_OPERATOR_MORE_EQUAL: + case ZBX_CONDITION_OPERATOR_MORE_EQUAL: if (event->trigger.priority >= condition_value) zbx_vector_uint64_append(&condition->eventids, event->eventid); break; - case CONDITION_OPERATOR_LESS_EQUAL: + case ZBX_CONDITION_OPERATOR_LESS_EQUAL: if (event->trigger.priority <= condition_value) zbx_vector_uint64_append(&condition->eventids, event->eventid); break; @@ -674,7 +674,7 @@ static int check_time_period_condition(const zbx_vector_ptr_t *esc_events, zbx_c char *period; int i; - if (CONDITION_OPERATOR_IN != condition->op && CONDITION_OPERATOR_NOT_IN != condition->op) + if (ZBX_CONDITION_OPERATOR_IN != condition->op && ZBX_CONDITION_OPERATOR_NOT_IN != condition->op) return NOTSUPPORTED; period = zbx_strdup(NULL, condition->value); @@ -690,11 +690,11 @@ static int check_time_period_condition(const zbx_vector_ptr_t *esc_events, zbx_c { switch (condition->op) { - case CONDITION_OPERATOR_IN: + case ZBX_CONDITION_OPERATOR_IN: if (SUCCEED == res) zbx_vector_uint64_append(&condition->eventids, event->eventid); break; - case CONDITION_OPERATOR_NOT_IN: + case ZBX_CONDITION_OPERATOR_NOT_IN: if (FAIL == res) zbx_vector_uint64_append(&condition->eventids, event->eventid); break; @@ -722,11 +722,11 @@ static int check_suppressed_condition(const zbx_vector_ptr_t *esc_events, zbx_co switch (condition->op) { - case CONDITION_OPERATOR_YES: + case ZBX_CONDITION_OPERATOR_YES: if (ZBX_PROBLEM_SUPPRESSED_TRUE == event->suppressed) zbx_vector_uint64_append(&condition->eventids, event->eventid); break; - case CONDITION_OPERATOR_NO: + case ZBX_CONDITION_OPERATOR_NO: if (ZBX_PROBLEM_SUPPRESSED_FALSE == event->suppressed) zbx_vector_uint64_append(&condition->eventids, event->eventid); break; @@ -777,7 +777,7 @@ static int check_acknowledged_condition(const zbx_vector_ptr_t *esc_events, zbx_ ZBX_STR2UINT64(eventid, row[0]); switch (condition->op) { - case CONDITION_OPERATOR_EQUAL: + case ZBX_CONDITION_OPERATOR_EQUAL: zbx_vector_uint64_append(&condition->eventids, eventid); break; default: @@ -806,7 +806,7 @@ static void check_condition_event_tag(const zbx_vector_ptr_t *esc_events, zbx_co { int i, ret, ret_continue; - if (CONDITION_OPERATOR_NOT_EQUAL == condition->op || CONDITION_OPERATOR_NOT_LIKE == condition->op) + if (ZBX_CONDITION_OPERATOR_NOT_EQUAL == condition->op || ZBX_CONDITION_OPERATOR_NOT_LIKE == condition->op) ret_continue = SUCCEED; else ret_continue = FAIL; @@ -843,7 +843,7 @@ static void check_condition_event_tag_value(const zbx_vector_ptr_t *esc_events, { int i, ret, ret_continue; - if (CONDITION_OPERATOR_NOT_EQUAL == condition->op || CONDITION_OPERATOR_NOT_LIKE == condition->op) + if (ZBX_CONDITION_OPERATOR_NOT_EQUAL == condition->op || ZBX_CONDITION_OPERATOR_NOT_LIKE == condition->op) ret_continue = SUCCEED; else ret_continue = FAIL; @@ -887,38 +887,38 @@ static void check_trigger_condition(const zbx_vector_ptr_t *esc_events, zbx_cond switch (condition->conditiontype) { - case CONDITION_TYPE_HOST_GROUP: + case ZBX_CONDITION_TYPE_HOST_GROUP: ret = check_host_group_condition(esc_events, condition); break; - case CONDITION_TYPE_HOST_TEMPLATE: + case ZBX_CONDITION_TYPE_HOST_TEMPLATE: ret = check_host_template_condition(esc_events, condition); break; - case CONDITION_TYPE_HOST: + case ZBX_CONDITION_TYPE_HOST: ret = check_host_condition(esc_events, condition); break; - case CONDITION_TYPE_TRIGGER: + case ZBX_CONDITION_TYPE_TRIGGER: ret = check_trigger_id_condition(esc_events, condition); break; - case CONDITION_TYPE_TRIGGER_NAME: + case ZBX_CONDITION_TYPE_TRIGGER_NAME: ret = check_trigger_name_condition(esc_events, condition); break; - case CONDITION_TYPE_TRIGGER_SEVERITY: + case ZBX_CONDITION_TYPE_TRIGGER_SEVERITY: ret = check_trigger_severity_condition(esc_events, condition); break; - case CONDITION_TYPE_TIME_PERIOD: + case ZBX_CONDITION_TYPE_TIME_PERIOD: ret = check_time_period_condition(esc_events, condition); break; - case CONDITION_TYPE_SUPPRESSED: + case ZBX_CONDITION_TYPE_SUPPRESSED: ret = check_suppressed_condition(esc_events, condition); break; - case CONDITION_TYPE_EVENT_ACKNOWLEDGED: + case ZBX_CONDITION_TYPE_EVENT_ACKNOWLEDGED: ret = check_acknowledged_condition(esc_events, condition); break; - case CONDITION_TYPE_EVENT_TAG: + case ZBX_CONDITION_TYPE_EVENT_TAG: check_condition_event_tag(esc_events, condition); ret = SUCCEED; break; - case CONDITION_TYPE_EVENT_TAG_VALUE: + case ZBX_CONDITION_TYPE_EVENT_TAG_VALUE: check_condition_event_tag_value(esc_events,condition); ret = SUCCEED; break; @@ -986,12 +986,12 @@ static int check_drule_condition(const zbx_vector_ptr_t *esc_events, zbx_conditi zbx_vector_uint64_t objectids[2]; zbx_uint64_t condition_value; - if (CONDITION_OPERATOR_EQUAL == condition->op) + if (ZBX_CONDITION_OPERATOR_EQUAL == condition->op) { operation_and = " and"; operation_where = " where"; } - else if (CONDITION_OPERATOR_NOT_EQUAL == condition->op) + else if (ZBX_CONDITION_OPERATOR_NOT_EQUAL == condition->op) { operation_and = " and not"; operation_where = " where not"; @@ -1082,9 +1082,9 @@ static int check_dcheck_condition(const zbx_vector_ptr_t *esc_events, zbx_condit zbx_vector_uint64_t objectids; zbx_uint64_t condition_value; - if (CONDITION_OPERATOR_EQUAL == condition->op) + if (ZBX_CONDITION_OPERATOR_EQUAL == condition->op) operation_where = " where"; - else if (CONDITION_OPERATOR_NOT_EQUAL == condition->op) + else if (ZBX_CONDITION_OPERATOR_NOT_EQUAL == condition->op) operation_where = " where not"; else return NOTSUPPORTED; @@ -1149,7 +1149,7 @@ static int check_dobject_condition(const zbx_vector_ptr_t *esc_events, zbx_condi { int i, condition_value_i = atoi(condition->value); - if (CONDITION_OPERATOR_EQUAL != condition->op) + if (ZBX_CONDITION_OPERATOR_EQUAL != condition->op) return NOTSUPPORTED; for (i = 0; i < esc_events->values_num; i++) @@ -1185,9 +1185,9 @@ static int check_proxy_condition(const zbx_vector_ptr_t *esc_events, zbx_conditi zbx_vector_uint64_t objectids[2]; zbx_uint64_t condition_value; - if (CONDITION_OPERATOR_EQUAL == condition->op) + if (ZBX_CONDITION_OPERATOR_EQUAL == condition->op) operation_and = " and"; - else if (CONDITION_OPERATOR_NOT_EQUAL == condition->op) + else if (ZBX_CONDITION_OPERATOR_NOT_EQUAL == condition->op) operation_and = " and not"; else return NOTSUPPORTED; @@ -1279,12 +1279,12 @@ static int check_dvalue_condition(const zbx_vector_ptr_t *esc_events, zbx_condit switch (condition->op) { - case CONDITION_OPERATOR_EQUAL: - case CONDITION_OPERATOR_NOT_EQUAL: - case CONDITION_OPERATOR_MORE_EQUAL: - case CONDITION_OPERATOR_LESS_EQUAL: - case CONDITION_OPERATOR_LIKE: - case CONDITION_OPERATOR_NOT_LIKE: + case ZBX_CONDITION_OPERATOR_EQUAL: + case ZBX_CONDITION_OPERATOR_NOT_EQUAL: + case ZBX_CONDITION_OPERATOR_MORE_EQUAL: + case ZBX_CONDITION_OPERATOR_LESS_EQUAL: + case ZBX_CONDITION_OPERATOR_LIKE: + case ZBX_CONDITION_OPERATOR_NOT_LIKE: break; default: return NOTSUPPORTED; @@ -1321,27 +1321,27 @@ static int check_dvalue_condition(const zbx_vector_ptr_t *esc_events, zbx_condit switch (condition->op) { - case CONDITION_OPERATOR_EQUAL: + case ZBX_CONDITION_OPERATOR_EQUAL: if (0 == strcmp(condition->value, row[1])) add_condition_match(esc_events, condition, objectid, object); break; - case CONDITION_OPERATOR_NOT_EQUAL: + case ZBX_CONDITION_OPERATOR_NOT_EQUAL: if (0 != strcmp(condition->value, row[1])) add_condition_match(esc_events, condition, objectid, object); break; - case CONDITION_OPERATOR_MORE_EQUAL: + case ZBX_CONDITION_OPERATOR_MORE_EQUAL: if (0 <= strcmp(row[1], condition->value)) add_condition_match(esc_events, condition, objectid, object); break; - case CONDITION_OPERATOR_LESS_EQUAL: + case ZBX_CONDITION_OPERATOR_LESS_EQUAL: if (0 >= strcmp(row[1], condition->value)) add_condition_match(esc_events, condition, objectid, object); break; - case CONDITION_OPERATOR_LIKE: + case ZBX_CONDITION_OPERATOR_LIKE: if (NULL != strstr(row[1], condition->value)) add_condition_match(esc_events, condition, objectid, object); break; - case CONDITION_OPERATOR_NOT_LIKE: + case ZBX_CONDITION_OPERATOR_NOT_LIKE: if (NULL == strstr(row[1], condition->value)) add_condition_match(esc_events, condition, objectid, object); break; @@ -1378,7 +1378,7 @@ static int check_dhost_ip_condition(const zbx_vector_ptr_t *esc_events, zbx_cond zbx_vector_uint64_t objectids[2]; zbx_uint64_t condition_value; - if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_NOT_EQUAL != condition->op) + if (ZBX_CONDITION_OPERATOR_EQUAL != condition->op && ZBX_CONDITION_OPERATOR_NOT_EQUAL != condition->op) return NOTSUPPORTED; ZBX_STR2UINT64(condition_value, condition->value); @@ -1425,11 +1425,11 @@ static int check_dhost_ip_condition(const zbx_vector_ptr_t *esc_events, zbx_cond ZBX_STR2UINT64(objectid, row[0]); switch (condition->op) { - case CONDITION_OPERATOR_EQUAL: + case ZBX_CONDITION_OPERATOR_EQUAL: if (SUCCEED == zbx_ip_in_list(condition->value, row[1])) add_condition_match(esc_events, condition, objectid, objects[i]); break; - case CONDITION_OPERATOR_NOT_EQUAL: + case ZBX_CONDITION_OPERATOR_NOT_EQUAL: if (SUCCEED != zbx_ip_in_list(condition->value, row[1])) add_condition_match(esc_events, condition, objectid, objects[i]); break; @@ -1467,7 +1467,7 @@ static int check_dservice_type_condition(const zbx_vector_ptr_t *esc_events, zbx zbx_vector_uint64_t objectids; int i, condition_value_i; - if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_NOT_EQUAL != condition->op) + if (ZBX_CONDITION_OPERATOR_EQUAL != condition->op && ZBX_CONDITION_OPERATOR_NOT_EQUAL != condition->op) return NOTSUPPORTED; condition_value_i = atoi(condition->value); @@ -1506,11 +1506,11 @@ static int check_dservice_type_condition(const zbx_vector_ptr_t *esc_events, zbx switch (condition->op) { - case CONDITION_OPERATOR_EQUAL: + case ZBX_CONDITION_OPERATOR_EQUAL: if (condition_value_i == tmp_int) add_condition_match(esc_events, condition, objectid, object); break; - case CONDITION_OPERATOR_NOT_EQUAL: + case ZBX_CONDITION_OPERATOR_NOT_EQUAL: if (condition_value_i != tmp_int) add_condition_match(esc_events, condition, objectid, object); break; @@ -1547,11 +1547,11 @@ static int check_dstatus_condition(const zbx_vector_ptr_t *esc_events, zbx_condi switch (condition->op) { - case CONDITION_OPERATOR_EQUAL: + case ZBX_CONDITION_OPERATOR_EQUAL: if (condition_value_i == event->value) zbx_vector_uint64_append(&condition->eventids, event->eventid); break; - case CONDITION_OPERATOR_NOT_EQUAL: + case ZBX_CONDITION_OPERATOR_NOT_EQUAL: if (condition_value_i != event->value) zbx_vector_uint64_append(&condition->eventids, event->eventid); break; @@ -1585,7 +1585,7 @@ static int check_duptime_condition(const zbx_vector_ptr_t *esc_events, zbx_condi zbx_vector_uint64_t objectids[2]; int condition_value_i; - if (CONDITION_OPERATOR_LESS_EQUAL != condition->op && CONDITION_OPERATOR_MORE_EQUAL != condition->op) + if (ZBX_CONDITION_OPERATOR_LESS_EQUAL != condition->op && ZBX_CONDITION_OPERATOR_MORE_EQUAL != condition->op) return NOTSUPPORTED; condition_value_i = atoi(condition->value); @@ -1637,11 +1637,11 @@ static int check_duptime_condition(const zbx_vector_ptr_t *esc_events, zbx_condi switch (condition->op) { - case CONDITION_OPERATOR_LESS_EQUAL: + case ZBX_CONDITION_OPERATOR_LESS_EQUAL: if (0 != tmp_int && (now - tmp_int) <= condition_value_i) add_condition_match(esc_events, condition, objectid, objects[i]); break; - case CONDITION_OPERATOR_MORE_EQUAL: + case ZBX_CONDITION_OPERATOR_MORE_EQUAL: if (0 != tmp_int && (now - tmp_int) >= condition_value_i) add_condition_match(esc_events, condition, objectid, objects[i]); break; @@ -1679,7 +1679,7 @@ static int check_dservice_port_condition(const zbx_vector_ptr_t *esc_events, zbx zbx_vector_uint64_t objectids; int i; - if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_NOT_EQUAL != condition->op) + if (ZBX_CONDITION_OPERATOR_EQUAL != condition->op && ZBX_CONDITION_OPERATOR_NOT_EQUAL != condition->op) return NOTSUPPORTED; zbx_vector_uint64_create(&objectids); @@ -1712,11 +1712,11 @@ static int check_dservice_port_condition(const zbx_vector_ptr_t *esc_events, zbx ZBX_STR2UINT64(objectid, row[0]); switch (condition->op) { - case CONDITION_OPERATOR_EQUAL: + case ZBX_CONDITION_OPERATOR_EQUAL: if (SUCCEED == zbx_int_in_list(condition->value, atoi(row[1]))) add_condition_match(esc_events, condition, objectid, object); break; - case CONDITION_OPERATOR_NOT_EQUAL: + case ZBX_CONDITION_OPERATOR_NOT_EQUAL: if (SUCCEED != zbx_int_in_list(condition->value, atoi(row[1]))) add_condition_match(esc_events, condition, objectid, object); break; @@ -1750,34 +1750,34 @@ static void check_discovery_condition(const zbx_vector_ptr_t *esc_events, zbx_co switch (condition->conditiontype) { - case CONDITION_TYPE_DRULE: + case ZBX_CONDITION_TYPE_DRULE: ret = check_drule_condition(esc_events, condition); break; - case CONDITION_TYPE_DCHECK: + case ZBX_CONDITION_TYPE_DCHECK: ret = check_dcheck_condition(esc_events, condition); break; - case CONDITION_TYPE_DOBJECT: + case ZBX_CONDITION_TYPE_DOBJECT: ret = check_dobject_condition(esc_events, condition); break; - case CONDITION_TYPE_PROXY: + case ZBX_CONDITION_TYPE_PROXY: ret = check_proxy_condition(esc_events, condition); break; - case CONDITION_TYPE_DVALUE: + case ZBX_CONDITION_TYPE_DVALUE: ret = check_dvalue_condition(esc_events, condition); break; - case CONDITION_TYPE_DHOST_IP: + case ZBX_CONDITION_TYPE_DHOST_IP: ret = check_dhost_ip_condition(esc_events, condition); break; - case CONDITION_TYPE_DSERVICE_TYPE: + case ZBX_CONDITION_TYPE_DSERVICE_TYPE: ret = check_dservice_type_condition(esc_events, condition); break; - case CONDITION_TYPE_DSTATUS: + case ZBX_CONDITION_TYPE_DSTATUS: ret = check_dstatus_condition(esc_events, condition); break; - case CONDITION_TYPE_DUPTIME: + case ZBX_CONDITION_TYPE_DUPTIME: ret = check_duptime_condition(esc_events, condition); break; - case CONDITION_TYPE_DSERVICE_PORT: + case ZBX_CONDITION_TYPE_DSERVICE_PORT: ret = check_dservice_port_condition(esc_events, condition); break; default: @@ -1819,16 +1819,16 @@ static int check_hostname_metadata_condition(const zbx_vector_ptr_t *esc_events, switch(condition->op) { - case CONDITION_OPERATOR_LIKE: - case CONDITION_OPERATOR_NOT_LIKE: - case CONDITION_OPERATOR_REGEXP: - case CONDITION_OPERATOR_NOT_REGEXP: + case ZBX_CONDITION_OPERATOR_LIKE: + case ZBX_CONDITION_OPERATOR_NOT_LIKE: + case ZBX_CONDITION_OPERATOR_REGEXP: + case ZBX_CONDITION_OPERATOR_NOT_REGEXP: break; default: return NOTSUPPORTED; } - if (CONDITION_TYPE_HOST_NAME == condition->conditiontype) + if (ZBX_CONDITION_TYPE_HOST_NAME == condition->conditiontype) condition_field = "host"; else condition_field = "host_metadata"; @@ -1854,19 +1854,19 @@ static int check_hostname_metadata_condition(const zbx_vector_ptr_t *esc_events, switch (condition->op) { - case CONDITION_OPERATOR_LIKE: + case ZBX_CONDITION_OPERATOR_LIKE: if (NULL != strstr(row[1], condition->value)) add_condition_match(esc_events, condition, objectid, object); break; - case CONDITION_OPERATOR_NOT_LIKE: + case ZBX_CONDITION_OPERATOR_NOT_LIKE: if (NULL == strstr(row[1], condition->value)) add_condition_match(esc_events, condition, objectid, object); break; - case CONDITION_OPERATOR_REGEXP: + case ZBX_CONDITION_OPERATOR_REGEXP: if (NULL != zbx_regexp_match(row[1], condition->value, NULL)) add_condition_match(esc_events, condition, objectid, object); break; - case CONDITION_OPERATOR_NOT_REGEXP: + case ZBX_CONDITION_OPERATOR_NOT_REGEXP: if (NULL == zbx_regexp_match(row[1], condition->value, NULL)) add_condition_match(esc_events, condition, objectid, object); break; @@ -1904,7 +1904,7 @@ static int check_areg_proxy_condition(const zbx_vector_ptr_t *esc_events, zbx_co ZBX_STR2UINT64(condition_value, condition->value); - if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_NOT_EQUAL != condition->op) + if (ZBX_CONDITION_OPERATOR_EQUAL != condition->op && ZBX_CONDITION_OPERATOR_NOT_EQUAL != condition->op) return NOTSUPPORTED; zbx_vector_uint64_create(&objectids); @@ -1930,11 +1930,11 @@ static int check_areg_proxy_condition(const zbx_vector_ptr_t *esc_events, zbx_co switch (condition->op) { - case CONDITION_OPERATOR_EQUAL: + case ZBX_CONDITION_OPERATOR_EQUAL: if (id == condition_value) add_condition_match(esc_events, condition, objectid, object); break; - case CONDITION_OPERATOR_NOT_EQUAL: + case ZBX_CONDITION_OPERATOR_NOT_EQUAL: if (id != condition_value) add_condition_match(esc_events, condition, objectid, object); break; @@ -1968,11 +1968,11 @@ static void check_autoregistration_condition(const zbx_vector_ptr_t *esc_events, switch (condition->conditiontype) { - case CONDITION_TYPE_HOST_NAME: - case CONDITION_TYPE_HOST_METADATA: + case ZBX_CONDITION_TYPE_HOST_NAME: + case ZBX_CONDITION_TYPE_HOST_METADATA: ret = check_hostname_metadata_condition(esc_events, condition); break; - case CONDITION_TYPE_PROXY: + case ZBX_CONDITION_TYPE_PROXY: ret = check_areg_proxy_condition(esc_events, condition); break; default: @@ -2020,6 +2020,14 @@ static int is_supported_event_object(const ZBX_DB_EVENT *event) ******************************************************************************/ static int check_intern_event_type_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition) { +/* event type action condition values */ +/* SYNC WITH PHP! */ +#define EVENT_TYPE_ITEM_NOTSUPPORTED 0 +/* #define EVENT_TYPE_ITEM_NORMAL 1 deprecated */ +#define EVENT_TYPE_LLDRULE_NOTSUPPORTED 2 +/* #define EVENT_TYPE_LLDRULE_NORMAL 3 deprecated */ +#define EVENT_TYPE_TRIGGER_UNKNOWN 4 +/* #define EVENT_TYPE_TRIGGER_NORMAL 5 deprecated */ int i; zbx_uint64_t condition_value; @@ -2056,6 +2064,9 @@ static int check_intern_event_type_condition(const zbx_vector_ptr_t *esc_events, } return SUCCEED; +#undef EVENT_TYPE_ITEM_NOTSUPPORTED +#undef EVENT_TYPE_LLDRULE_NOTSUPPORTED +#undef EVENT_TYPE_TRIGGER_UNKNOWN } /****************************************************************************** @@ -2118,7 +2129,7 @@ static int check_intern_host_group_condition(const zbx_vector_ptr_t *esc_events, zbx_vector_uint64_t objectids[3], groupids; zbx_uint64_t condition_value; - if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_NOT_EQUAL != condition->op) + if (ZBX_CONDITION_OPERATOR_EQUAL != condition->op && ZBX_CONDITION_OPERATOR_NOT_EQUAL != condition->op) return NOTSUPPORTED; ZBX_STR2UINT64(condition_value, condition->value); @@ -2176,7 +2187,7 @@ static int check_intern_host_group_condition(const zbx_vector_ptr_t *esc_events, zbx_uint64_t objectid; ZBX_STR2UINT64(objectid, row[0]); - if (CONDITION_OPERATOR_NOT_EQUAL == condition->op) + if (ZBX_CONDITION_OPERATOR_NOT_EQUAL == condition->op) { int index; @@ -2194,7 +2205,7 @@ static int check_intern_host_group_condition(const zbx_vector_ptr_t *esc_events, for (i = 0; i < (int)ARRSIZE(objects); i++) { - if (CONDITION_OPERATOR_NOT_EQUAL == condition->op) + if (ZBX_CONDITION_OPERATOR_NOT_EQUAL == condition->op) { int j; @@ -2261,7 +2272,7 @@ static int check_intern_host_template_condition(const zbx_vector_ptr_t *esc_even zbx_vector_uint64_t objectids[3]; zbx_vector_uint64_pair_t objectids_pair[3]; - if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_NOT_EQUAL != condition->op) + if (ZBX_CONDITION_OPERATOR_EQUAL != condition->op && ZBX_CONDITION_OPERATOR_NOT_EQUAL != condition->op) return NOTSUPPORTED; for (i = 0; i < (int)ARRSIZE(objects); i++) @@ -2352,12 +2363,12 @@ static int check_intern_host_condition(const zbx_vector_ptr_t *esc_events, zbx_c zbx_vector_uint64_t objectids[3]; zbx_uint64_t condition_value; - if (CONDITION_OPERATOR_EQUAL == condition->op) + if (ZBX_CONDITION_OPERATOR_EQUAL == condition->op) { operation = " and"; operation_item = " where"; } - else if (CONDITION_OPERATOR_NOT_EQUAL == condition->op) + else if (ZBX_CONDITION_OPERATOR_NOT_EQUAL == condition->op) { operation = " and not"; operation_item = " where not"; @@ -2445,23 +2456,23 @@ static void check_internal_condition(const zbx_vector_ptr_t *esc_events, zbx_con switch (condition->conditiontype) { - case CONDITION_TYPE_EVENT_TYPE: + case ZBX_CONDITION_TYPE_EVENT_TYPE: ret = check_intern_event_type_condition(esc_events, condition); break; - case CONDITION_TYPE_HOST_GROUP: + case ZBX_CONDITION_TYPE_HOST_GROUP: ret = check_intern_host_group_condition(esc_events, condition); break; - case CONDITION_TYPE_HOST_TEMPLATE: + case ZBX_CONDITION_TYPE_HOST_TEMPLATE: ret = check_intern_host_template_condition(esc_events, condition); break; - case CONDITION_TYPE_HOST: + case ZBX_CONDITION_TYPE_HOST: ret = check_intern_host_condition(esc_events, condition); break; - case CONDITION_TYPE_EVENT_TAG: + case ZBX_CONDITION_TYPE_EVENT_TAG: check_condition_event_tag(esc_events, condition); ret = SUCCEED; break; - case CONDITION_TYPE_EVENT_TAG_VALUE: + case ZBX_CONDITION_TYPE_EVENT_TAG_VALUE: check_condition_event_tag_value(esc_events,condition); ret = SUCCEED; break; @@ -2575,15 +2586,15 @@ static int check_action_conditions(zbx_uint64_t eventid, const zbx_action_eval_t zabbix_log(LOG_LEVEL_DEBUG, "In %s() actionid:" ZBX_FS_UI64 " eventsource:%d", __func__, action->actionid, (int)action->eventsource); - if (CONDITION_EVAL_TYPE_EXPRESSION == action->evaltype) + if (ZBX_ACTION_CONDITION_EVAL_TYPE_EXPRESSION == action->evaltype) expression = zbx_strdup(expression, action->formula); for (i = 0; i < action->conditions.values_num; i++) { condition = (zbx_condition_t *)action->conditions.values[i]; - if (CONDITION_EVAL_TYPE_AND_OR == action->evaltype && old_type == condition->conditiontype && - SUCCEED == ret) + if (ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR == action->evaltype && + old_type == condition->conditiontype && SUCCEED == ret) { continue; /* short-circuit true OR condition block to the next AND condition */ } @@ -2597,8 +2608,8 @@ static int check_action_conditions(zbx_uint64_t eventid, const zbx_action_eval_t switch (action->evaltype) { - case CONDITION_EVAL_TYPE_AND_OR: - if (old_type == condition->conditiontype) /* assume conditions are sorted by type */ + case ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR: + if (old_type == condition->conditiontype) /* assume conditions are sorted by type */ { if (SUCCEED == condition_result) ret = SUCCEED; @@ -2613,7 +2624,7 @@ static int check_action_conditions(zbx_uint64_t eventid, const zbx_action_eval_t } break; - case CONDITION_EVAL_TYPE_AND: + case ZBX_ACTION_CONDITION_EVAL_TYPE_AND: if (FAIL == condition_result) /* break if any AND condition is FALSE */ { ret = FAIL; @@ -2621,7 +2632,7 @@ static int check_action_conditions(zbx_uint64_t eventid, const zbx_action_eval_t } break; - case CONDITION_EVAL_TYPE_OR: + case ZBX_ACTION_CONDITION_EVAL_TYPE_OR: if (SUCCEED == condition_result) /* break if any OR condition is TRUE */ { ret = SUCCEED; @@ -2630,7 +2641,7 @@ static int check_action_conditions(zbx_uint64_t eventid, const zbx_action_eval_t ret = FAIL; break; - case CONDITION_EVAL_TYPE_EXPRESSION: + case ZBX_ACTION_CONDITION_EVAL_TYPE_EXPRESSION: zbx_snprintf(tmp, sizeof(tmp), "{" ZBX_FS_UI64 "}", condition->conditionid); id_len = strlen(tmp); @@ -2647,7 +2658,7 @@ static int check_action_conditions(zbx_uint64_t eventid, const zbx_action_eval_t } } - if (CONDITION_EVAL_TYPE_EXPRESSION == action->evaltype) + if (ZBX_ACTION_CONDITION_EVAL_TYPE_EXPRESSION == action->evaltype) { if (SUCCEED == zbx_evaluate(&eval_result, expression, error, sizeof(error), NULL)) ret = (SUCCEED != zbx_double_compare(eval_result, 0) ? SUCCEED : FAIL); @@ -3041,7 +3052,7 @@ static void prepare_actions_conditions_eval(zbx_vector_ptr_t *actions, zbx_hashs } else { - if (CONDITION_EVAL_TYPE_EXPRESSION == action->evaltype) + if (ZBX_ACTION_CONDITION_EVAL_TYPE_EXPRESSION == action->evaltype) { char search[ZBX_MAX_UINT64_LEN + 2]; char replace[ZBX_MAX_UINT64_LEN + 2]; diff --git a/src/zabbix_server/alerter/alert_manager.c b/src/zabbix_server/alerter/alert_manager.c index c0799de6302..9a40b39246b 100644 --- a/src/zabbix_server/alerter/alert_manager.c +++ b/src/zabbix_server/alerter/alert_manager.c @@ -2251,7 +2251,7 @@ ZBX_THREAD_ENTRY(alert_manager_thread, args) zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(program_type), server_num, get_process_type_string(process_type), process_num); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); if (FAIL == am_init(&manager, &error)) { @@ -2324,9 +2324,9 @@ ZBX_THREAD_ENTRY(alert_manager_thread, args) time_mediatype = now; } - update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); ret = zbx_ipc_service_recv(&manager.ipc, &timeout, &client, &message); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); sec = zbx_time(); zbx_update_env(sec); diff --git a/src/zabbix_server/alerter/alert_syncer.c b/src/zabbix_server/alerter/alert_syncer.c index 684ac2bac0f..df66a409690 100644 --- a/src/zabbix_server/alerter/alert_syncer.c +++ b/src/zabbix_server/alerter/alert_syncer.c @@ -627,7 +627,7 @@ static void am_db_validate_tags_for_update(zbx_vector_events_tags_t *update_even for (j = 0; j < local_event_tags->tags.values_num; j++) { - tag = (zbx_tag_t *)(local_event_tags->tags).values[j]; + tag = local_event_tags->tags.values[j]; zbx_db_insert_add_values(db_event, __UINT64_C(0), local_event_tags->eventid, tag->tag, tag->value); diff --git a/src/zabbix_server/alerter/alerter.c b/src/zabbix_server/alerter/alerter.c index 157b516871d..01880350760 100644 --- a/src/zabbix_server/alerter/alerter.c +++ b/src/zabbix_server/alerter/alerter.c @@ -299,7 +299,7 @@ ZBX_THREAD_ENTRY(alerter_thread, args) zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(program_type), server_num, get_process_type_string(process_type), process_num); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); zbx_setproctitle("%s [connecting to the database]", get_process_type_string(process_type)); @@ -320,7 +320,7 @@ ZBX_THREAD_ENTRY(alerter_thread, args) zbx_setproctitle("%s #%d started", get_process_type_string(process_type), process_num); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); while (ZBX_IS_RUNNING()) { @@ -338,7 +338,7 @@ ZBX_THREAD_ENTRY(alerter_thread, args) fail_num = 0; } - update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); if (SUCCEED != zbx_ipc_socket_read(&alerter_socket, &message)) { @@ -346,7 +346,7 @@ ZBX_THREAD_ENTRY(alerter_thread, args) exit(EXIT_FAILURE); } - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); time_read = zbx_time(); time_idle += time_read - time_now; diff --git a/src/zabbix_server/availability/avail_manager.c b/src/zabbix_server/availability/avail_manager.c index 88726502a4b..8f2526fd8fa 100644 --- a/src/zabbix_server/availability/avail_manager.c +++ b/src/zabbix_server/availability/avail_manager.c @@ -418,7 +418,7 @@ ZBX_THREAD_ENTRY(availability_manager_thread, args) zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(program_type), server_num, get_process_type_string(process_type), process_num); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); zbx_setproctitle("%s #%d [connecting to the database]", get_process_type_string(process_type), process_num); @@ -461,9 +461,9 @@ ZBX_THREAD_ENTRY(availability_manager_thread, args) processed_num = 0; } - update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); ret = zbx_ipc_service_recv(&service, &timeout, &client, &message); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); sec = zbx_time(); zbx_update_env(sec); diff --git a/src/zabbix_server/dbconfig/Makefile.am b/src/zabbix_server/dbconfig/Makefile.am index e7cf0ff9301..279f9f08e16 100644 --- a/src/zabbix_server/dbconfig/Makefile.am +++ b/src/zabbix_server/dbconfig/Makefile.am @@ -5,3 +5,5 @@ noinst_LIBRARIES = libzbxdbconfig.a libzbxdbconfig_a_SOURCES = \ dbconfig.c \ dbconfig.h + +libzbxdbconfig_a_CFLAGS = -I$(top_srcdir)/src/libs/zbxdbcache diff --git a/src/zabbix_server/dbconfig/dbconfig.c b/src/zabbix_server/dbconfig/dbconfig.c index 885a4f4dd00..adeb3b2fe9f 100644 --- a/src/zabbix_server/dbconfig/dbconfig.c +++ b/src/zabbix_server/dbconfig/dbconfig.c @@ -25,6 +25,7 @@ #include "dbcache.h" #include "zbxrtc.h" #include "zbxtime.h" +#include "valuecache.h" extern int CONFIG_CONFSYNCER_FREQUENCY; extern ZBX_THREAD_LOCAL unsigned char process_type; @@ -41,7 +42,7 @@ extern ZBX_THREAD_LOCAL int server_num, process_num; ZBX_THREAD_ENTRY(dbconfig_thread, args) { double sec = 0.0; - int nextcheck = 0, sleeptime, secrets_reload = 0; + int nextcheck = 0, sleeptime, secrets_reload = 0, cache_reload = 0; zbx_ipc_async_socket_t rtc; process_type = ((zbx_thread_args_t *)args)->process_type; @@ -51,7 +52,7 @@ ZBX_THREAD_ENTRY(dbconfig_thread, args) zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(program_type), server_num, get_process_type_string(process_type), process_num); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); zbx_rtc_subscribe(&rtc, process_type, process_num); @@ -61,7 +62,7 @@ ZBX_THREAD_ENTRY(dbconfig_thread, args) sec = zbx_time(); zbx_setproctitle("%s [syncing configuration]", get_process_type_string(process_type)); - DCsync_configuration(ZBX_DBSYNC_INIT, ZBX_SYNCED_NEW_CONFIG_NO); + DCsync_configuration(ZBX_DBSYNC_INIT, ZBX_SYNCED_NEW_CONFIG_NO, NULL); DCsync_kvs_paths(NULL); zbx_setproctitle("%s [synced configuration in " ZBX_FS_DBL " sec, idle %d sec]", get_process_type_string(process_type), (sec = zbx_time() - sec), CONFIG_CONFSYNCER_FREQUENCY); @@ -81,10 +82,10 @@ ZBX_THREAD_ENTRY(dbconfig_thread, args) { if (ZBX_RTC_CONFIG_CACHE_RELOAD == rtc_cmd) { - if (0 != nextcheck) + if (0 == cache_reload) { zabbix_log(LOG_LEVEL_WARNING, "forced reloading of the configuration cache"); - nextcheck = 0; + cache_reload = 1; } else zabbix_log(LOG_LEVEL_WARNING, "configuration cache reloading is already in progress"); @@ -113,15 +114,29 @@ ZBX_THREAD_ENTRY(dbconfig_thread, args) if (0 == secrets_reload) { - DCsync_configuration(ZBX_DBSYNC_UPDATE, ZBX_SYNCED_NEW_CONFIG_YES); + zbx_vector_uint64_t deleted_itemids; + + zbx_vector_uint64_create(&deleted_itemids); + + DCsync_configuration(ZBX_DBSYNC_UPDATE, ZBX_SYNCED_NEW_CONFIG_YES, &deleted_itemids); DCsync_kvs_paths(NULL); DCupdate_interfaces_availability(); nextcheck = (int)time(NULL) + CONFIG_CONFSYNCER_FREQUENCY; + + zbx_vc_remove_items_by_ids(&deleted_itemids); + zbx_vector_uint64_destroy(&deleted_itemids); + + if (0 != cache_reload) + { + cache_reload = 0; + zabbix_log(LOG_LEVEL_WARNING, "finished forced reloading of the configuration cache"); + } } else { DCsync_kvs_paths(NULL); secrets_reload = 0; + zabbix_log(LOG_LEVEL_WARNING, "finished forced reloading of the secrets"); } sec = zbx_time() - sec; diff --git a/src/zabbix_server/dbsyncer/dbsyncer.c b/src/zabbix_server/dbsyncer/dbsyncer.c index fa951cb7142..6edf51720c6 100644 --- a/src/zabbix_server/dbsyncer/dbsyncer.c +++ b/src/zabbix_server/dbsyncer/dbsyncer.c @@ -97,7 +97,7 @@ ZBX_THREAD_ENTRY(dbsyncer_thread, args) zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(program_type), server_num, (process_name = get_process_type_string(process_type)), process_num); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); #define STAT_INTERVAL 5 /* if a process is busy and does not sleep then update status not faster than */ /* once in STAT_INTERVAL seconds */ diff --git a/src/zabbix_server/discoverer/discoverer.c b/src/zabbix_server/discoverer/discoverer.c index f48603e9609..fc94395d889 100644 --- a/src/zabbix_server/discoverer/discoverer.c +++ b/src/zabbix_server/discoverer/discoverer.c @@ -34,7 +34,6 @@ #include "zbxip.h" #include "zbxsysinfo.h" -extern int CONFIG_DISCOVERER_FORKS; extern ZBX_THREAD_LOCAL unsigned char process_type; extern unsigned char program_type; extern ZBX_THREAD_LOCAL int server_num, process_num; @@ -122,7 +121,7 @@ static int discover_service(const DB_DCHECK *dcheck, char *ip, int port, char ** zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); - init_result(&result); + zbx_init_agent_result(&result); **value = '\0'; @@ -198,8 +197,8 @@ static int discover_service(const DB_DCHECK *dcheck, char *ip, int port, char ** case SVC_TELNET: zbx_snprintf(key, sizeof(key), "net.tcp.service[%s,%s,%d]", service, ip, port); - if (SUCCEED != process(key, 0, &result) || NULL == ZBX_GET_UI64_RESULT(&result) || - 0 == result.ui64) + if (SUCCEED != zbx_execute_agent_check(key, 0, &result) || NULL == + ZBX_GET_UI64_RESULT(&result) || 0 == result.ui64) { ret = FAIL; } @@ -335,7 +334,7 @@ static int discover_service(const DB_DCHECK *dcheck, char *ip, int port, char ** zbx_alarm_off(); } - free_result(&result); + zbx_free_agent_result(&result); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); @@ -749,117 +748,80 @@ out: zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); } -static int process_discovery(void) +static int process_discovery(time_t *nextcheck) { DB_RESULT result; DB_ROW row; - int rule_count = 0; + int rule_count = 0, delay; char *delay_str = NULL; zbx_dc_um_handle_t *um_handle; + zbx_uint64_t druleid; + time_t now; - result = DBselect( - "select distinct r.druleid,r.iprange,r.name,c.dcheckid,r.proxy_hostid,r.delay" - " from drules r" - " left join dchecks c" - " on c.druleid=r.druleid" - " and c.uniq=1" - " where r.status=%d" - " and r.nextcheck<=%d" - " and " ZBX_SQL_MOD(r.druleid,%d) "=%d", - DRULE_STATUS_MONITORED, - (int)time(NULL), - CONFIG_DISCOVERER_FORKS, - process_num - 1); + now = time(NULL); + + if (SUCCEED != zbx_dc_drule_next(now, &druleid, nextcheck)) + return 0; um_handle = zbx_dc_open_user_macros(); - while (ZBX_IS_RUNNING() && NULL != (row = DBfetch(result))) + do { - int now, delay; - zbx_uint64_t druleid; - - rule_count++; - - ZBX_STR2UINT64(druleid, row[0]); - - delay_str = zbx_strdup(delay_str, row[5]); - zbx_substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - &delay_str, MACRO_TYPE_COMMON, NULL, 0); - - if (SUCCEED != zbx_is_time_suffix(delay_str, &delay, ZBX_LENGTH_UNLIMITED)) + result = DBselect( + "select distinct r.iprange,r.name,c.dcheckid,r.delay" + " from drules r" + " left join dchecks c" + " on c.druleid=r.druleid" + " and c.uniq=1" + " where r.druleid=" ZBX_FS_UI64, druleid); + + if (NULL != (row = DBfetch(result))) { - zabbix_log(LOG_LEVEL_WARNING, "discovery rule \"%s\": invalid update interval \"%s\"", - row[2], delay_str); + ZBX_DB_DRULE drule; - now = (int)time(NULL); + rule_count++; - DBexecute("update drules set nextcheck=%d where druleid=" ZBX_FS_UI64, - 0 > now ? ZBX_JAN_2038 : now + SEC_PER_MIN, druleid); + delay_str = zbx_strdup(delay_str, row[3]); + zbx_substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + &delay_str, MACRO_TYPE_COMMON, NULL, 0); - continue; - } + if (SUCCEED != zbx_is_time_suffix(delay_str, &delay, ZBX_LENGTH_UNLIMITED)) + { + zabbix_log(LOG_LEVEL_WARNING, "discovery rule \"%s\": invalid update interval \"%s\"", + row[1], delay_str); - if (SUCCEED == DBis_null(row[4])) - { - ZBX_DB_DRULE drule; + delay = ZBX_DEFAULT_INTERVAL; + } + else + { + memset(&drule, 0, sizeof(drule)); - memset(&drule, 0, sizeof(drule)); + drule.druleid = druleid; + drule.iprange = row[0]; + drule.name = row[1]; + ZBX_DBROW2UINT64(drule.unique_dcheckid, row[2]); - drule.druleid = druleid; - drule.iprange = row[1]; - drule.name = row[2]; - ZBX_DBROW2UINT64(drule.unique_dcheckid, row[3]); + process_rule(&drule); + } - process_rule(&drule); - } + zbx_dc_drule_queue(now, druleid, delay); + zbx_free(delay_str); - if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER)) - discovery_clean_services(druleid); + if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER)) + discovery_clean_services(druleid); - now = (int)time(NULL); - if (0 > now + delay) - { - zabbix_log(LOG_LEVEL_WARNING, "discovery rule \"%s\": nextcheck update causes overflow", - row[2]); - DBexecute("update drules set nextcheck=%d where druleid=" ZBX_FS_UI64, ZBX_JAN_2038, druleid); } - else - DBexecute("update drules set nextcheck=%d where druleid=" ZBX_FS_UI64, now + delay, druleid); + DBfree_result(result); + + now = time(NULL); } - DBfree_result(result); + while (ZBX_IS_RUNNING() && SUCCEED == zbx_dc_drule_next(now, &druleid, nextcheck)); zbx_dc_close_user_macros(um_handle); - zbx_free(delay_str); - return rule_count; /* performance metric */ } -static int get_minnextcheck(void) -{ - DB_RESULT result; - DB_ROW row; - int res = FAIL; - - result = DBselect( - "select count(*),min(nextcheck)" - " from drules" - " where status=%d" - " and " ZBX_SQL_MOD(druleid,%d) "=%d", - DRULE_STATUS_MONITORED, CONFIG_DISCOVERER_FORKS, process_num - 1); - - row = DBfetch(result); - - if (NULL == row || DBis_null(row[0]) == SUCCEED || DBis_null(row[1]) == SUCCEED) - zabbix_log(LOG_LEVEL_DEBUG, "get_minnextcheck(): no items to update"); - else if (0 != atoi(row[0])) - res = atoi(row[1]); - - DBfree_result(result); - - return res; -} - /****************************************************************************** * * * Purpose: periodically try to find new hosts and services * @@ -869,9 +831,9 @@ ZBX_THREAD_ENTRY(discoverer_thread, args) { zbx_thread_discoverer_args *discoverer_args_in = (zbx_thread_discoverer_args *) (((zbx_thread_args_t *)args)->args); - int nextcheck = 0, sleeptime = -1, rule_count = 0, old_rule_count = 0; + int sleeptime = -1, rule_count = 0, old_rule_count = 0; double sec, total_sec = 0.0, old_total_sec = 0.0; - time_t last_stat_time; + time_t last_stat_time, nextcheck = 0; zbx_ipc_async_socket_t rtc; process_type = ((zbx_thread_args_t *)args)->process_type; @@ -882,7 +844,7 @@ ZBX_THREAD_ENTRY(discoverer_thread, args) get_program_type_string(discoverer_args_in->zbx_get_program_type_cb_arg()), server_num, get_process_type_string(process_type), process_num); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); #define STAT_INTERVAL 5 /* if a process is busy and does not sleep then update status not faster than */ /* once in STAT_INTERVAL seconds */ @@ -914,10 +876,10 @@ ZBX_THREAD_ENTRY(discoverer_thread, args) if ((int)sec >= nextcheck) { - rule_count += process_discovery(); + rule_count += process_discovery(&nextcheck); total_sec += zbx_time() - sec; - if (FAIL == (nextcheck = get_minnextcheck())) + if (0 == nextcheck) nextcheck = time(NULL) + DISCOVERER_DELAY; } diff --git a/src/zabbix_server/escalator/escalator.c b/src/zabbix_server/escalator/escalator.c index 2bb94d9897b..fb2608dbac4 100644 --- a/src/zabbix_server/escalator/escalator.c +++ b/src/zabbix_server/escalator/escalator.c @@ -250,7 +250,7 @@ static int check_tag_based_permission(zbx_uint64_t userid, zbx_vector_uint64_t * DBfree_result(result); if (0 < tag_filters.values_num) - condition.op = CONDITION_OPERATOR_EQUAL; + condition.op = ZBX_CONDITION_OPERATOR_EQUAL; else ret = SUCCEED; @@ -270,13 +270,13 @@ static int check_tag_based_permission(zbx_uint64_t userid, zbx_vector_uint64_t * if (NULL != tag_filter->value && 0 != strlen(tag_filter->value)) { - condition.conditiontype = CONDITION_TYPE_EVENT_TAG_VALUE; + condition.conditiontype = ZBX_CONDITION_TYPE_EVENT_TAG_VALUE; condition.value2 = tag_filter->tag; condition.value = tag_filter->value; } else { - condition.conditiontype = CONDITION_TYPE_EVENT_TAG; + condition.conditiontype = ZBX_CONDITION_TYPE_EVENT_TAG; condition.value = tag_filter->tag; } @@ -1801,7 +1801,7 @@ static int check_operation_conditions(const ZBX_DB_EVENT *event, zbx_uint64_t op DB_ROW row; zbx_condition_t condition; - int ret = SUCCEED; /* SUCCEED required for CONDITION_EVAL_TYPE_AND_OR */ + int ret = SUCCEED; /* SUCCEED required for ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR */ int cond, exit = 0; unsigned char old_type = 0xff; @@ -1827,7 +1827,7 @@ static int check_operation_conditions(const ZBX_DB_EVENT *event, zbx_uint64_t op switch (evaltype) { - case CONDITION_EVAL_TYPE_AND_OR: + case ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR: if (old_type == condition.conditiontype) /* OR conditions */ { if (SUCCEED == check_action_condition(event, &condition)) @@ -1843,7 +1843,7 @@ static int check_operation_conditions(const ZBX_DB_EVENT *event, zbx_uint64_t op } old_type = condition.conditiontype; break; - case CONDITION_EVAL_TYPE_AND: + case ZBX_ACTION_CONDITION_EVAL_TYPE_AND: cond = check_action_condition(event, &condition); /* Break if any of AND conditions is FALSE */ if (cond == FAIL) @@ -1854,7 +1854,7 @@ static int check_operation_conditions(const ZBX_DB_EVENT *event, zbx_uint64_t op else ret = SUCCEED; break; - case CONDITION_EVAL_TYPE_OR: + case ZBX_ACTION_CONDITION_EVAL_TYPE_OR: cond = check_action_condition(event, &condition); /* Break if any of OR conditions is TRUE */ if (cond == SUCCEED) @@ -3447,7 +3447,7 @@ ZBX_THREAD_ENTRY(escalator_thread, args) get_program_type_string(escalator_args_in->zbx_get_program_type_cb_arg()), server_num, get_process_type_string(process_type), process_num); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); #define STAT_INTERVAL 5 /* if a process is busy and does not sleep then update status not faster than */ /* once in STAT_INTERVAL seconds */ diff --git a/src/zabbix_server/events.c b/src/zabbix_server/events.c index 0a301706578..afda25b219e 100644 --- a/src/zabbix_server/events.c +++ b/src/zabbix_server/events.c @@ -749,7 +749,7 @@ static const char *correlation_condition_match_new_event(zbx_corr_condition_t *c case ZBX_CORR_CONDITION_NEW_EVENT_HOSTGROUP: ret = correlation_match_event_hostgroup(event, condition->data.group.groupid); - if (CONDITION_OPERATOR_NOT_EQUAL == condition->data.group.op) + if (ZBX_CONDITION_OPERATOR_NOT_EQUAL == condition->data.group.op) return (SUCCEED == ret ? "0" : "1"); return (SUCCEED == ret ? "1" : "0"); @@ -866,19 +866,19 @@ static int correlation_has_old_event_operation(const zbx_correlation_t *correlat return FAIL; } -/****************************************************************************** - * * - * Purpose: adds sql statement to match tag according to the defined * - * matching operation * - * * - * Parameters: sql - [IN/OUT] * - * sql_alloc - [IN/OUT] * - * sql_offset - [IN/OUT] * - * tag - [IN] the tag to match * - * value - [IN] the tag value to match * - * op - [IN] the matching operation (CONDITION_OPERATOR_)* - * * - ******************************************************************************/ +/*********************************************************************************** + * * + * Purpose: adds sql statement to match tag according to the defined * + * matching operation * + * * + * Parameters: sql - [IN/OUT] * + * sql_alloc - [IN/OUT] * + * sql_offset - [IN/OUT] * + * tag - [IN] the tag to match * + * value - [IN] the tag value to match * + * op - [IN] the matching operation (ZBX_CONDITION_OPERATOR_) * + * * + ***********************************************************************************/ static void correlation_condition_add_tag_match(char **sql, size_t *sql_alloc, size_t *sql_offset, const char *tag, const char *value, unsigned char op) { @@ -889,8 +889,8 @@ static void correlation_condition_add_tag_match(char **sql, size_t *sql_alloc, s switch (op) { - case CONDITION_OPERATOR_NOT_EQUAL: - case CONDITION_OPERATOR_NOT_LIKE: + case ZBX_CONDITION_OPERATOR_NOT_EQUAL: + case ZBX_CONDITION_OPERATOR_NOT_LIKE: zbx_strcpy_alloc(sql, sql_alloc, sql_offset, "not "); break; } @@ -900,13 +900,13 @@ static void correlation_condition_add_tag_match(char **sql, size_t *sql_alloc, s switch (op) { - case CONDITION_OPERATOR_EQUAL: - case CONDITION_OPERATOR_NOT_EQUAL: + case ZBX_CONDITION_OPERATOR_EQUAL: + case ZBX_CONDITION_OPERATOR_NOT_EQUAL: zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "pt.tag='%s' and pt.value" ZBX_SQL_STRCMP, tag_esc, ZBX_SQL_STRVAL_EQ(value_esc)); break; - case CONDITION_OPERATOR_LIKE: - case CONDITION_OPERATOR_NOT_LIKE: + case ZBX_CONDITION_OPERATOR_LIKE: + case ZBX_CONDITION_OPERATOR_NOT_LIKE: zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "pt.tag='%s' and pt.value like '%%%s%%'", tag_esc, value_esc); break; diff --git a/src/zabbix_server/ha/ha.h b/src/zabbix_server/ha/ha.h index cc4588becba..0f2ae3497fb 100644 --- a/src/zabbix_server/ha/ha.h +++ b/src/zabbix_server/ha/ha.h @@ -28,16 +28,27 @@ typedef struct } zbx_cuid_t; +typedef struct +{ + char *ha_node_name; + char *ha_node_address; + char *default_node_ip; + int default_node_port; + int ha_status; +} +zbx_ha_config_t; + #define zbx_cuid_empty(a) ('\0' == *(a).str ? SUCCEED : FAIL) #define zbx_cuid_compare(a, b) (0 == memcmp((a).str, (b).str, CUID_LEN) ? SUCCEED : FAIL) #define zbx_cuid_clear(a) memset((a).str, 0, CUID_LEN) -int zbx_ha_start(zbx_rtc_t *rtc, int ha_status, char **error); +int zbx_ha_start(zbx_rtc_t *rtc, zbx_ha_config_t *ha_config, char **error); int zbx_ha_pause(char **error); int zbx_ha_stop(char **error); void zbx_ha_kill(void); -int zbx_ha_get_status(int *ha_status, int *ha_failover_delay, char **error); -int zbx_ha_dispatch_message(zbx_ipc_message_t *message, int *ha_status, int *ha_failover_delay, char **error); +int zbx_ha_get_status(const char *ha_node_name, int *ha_status, int *ha_failover_delay, char **error); +int zbx_ha_dispatch_message(const char *ha_node_name, zbx_ipc_message_t *message, int *ha_status, + int *ha_failover_delay, char **error); int zbx_ha_check_pid(pid_t pid); diff --git a/src/zabbix_server/ha/ha_manager.c b/src/zabbix_server/ha/ha_manager.c index db38ea955ed..8599c0ca9d6 100644 --- a/src/zabbix_server/ha/ha_manager.c +++ b/src/zabbix_server/ha/ha_manager.c @@ -31,6 +31,7 @@ #include "zbxnum.h" #include "zbxtime.h" #include "zbxip.h" +#include "zbxcomms.h" #define ZBX_HA_POLL_PERIOD 5 @@ -38,9 +39,6 @@ static pid_t ha_pid = ZBX_THREAD_ERROR; -extern char *CONFIG_HA_NODE_NAME; -extern char *CONFIG_NODE_ADDRESS; - extern zbx_cuid_t ha_sessionid; typedef struct @@ -102,6 +100,16 @@ static int ha_db_execute(zbx_ha_info_t *info, const char *sql, ...) __zbx_attr_f /****************************************************************************** * * + * Purpose: check if server is a part of HA cluster * + * * + ******************************************************************************/ +static int is_ha_cluster(const char *ha_node_name) +{ + return (NULL != ha_node_name && '\0' != *ha_node_name) ? 1 : 0; +} + +/****************************************************************************** + * * * Purpose: connect, send message and receive response in a given timeout * * * * Parameters: service_name - [IN] the IPC service name * @@ -459,9 +467,30 @@ static zbx_ha_node_t *ha_find_node_by_name(zbx_vector_ha_node_t *nodes, const ch * Purpose: get server external address and port from configuration * * * ******************************************************************************/ -static void ha_get_external_address(char **address, unsigned short *port) +static void ha_get_external_address(char **address, unsigned short *port, zbx_ha_config_t *ha_config) { - (void)zbx_parse_serveractive_element(CONFIG_NODE_ADDRESS, address, port, 10051); + if (NULL != ha_config->ha_node_address) + { + (void)zbx_parse_serveractive_element(ha_config->ha_node_address, address, port, 0); + } + else if (NULL != ha_config->default_node_ip) + { + char *tmp; + + zbx_strsplit_first(ha_config->default_node_ip, ',', address, &tmp); + zbx_free(tmp); + } + + if (NULL == *address || 0 == strcmp(*address, "0.0.0.0") || 0 == strcmp(*address, "::")) + *address = zbx_strdup(*address, "localhost"); + + if (0 == *port) + { + if (0 != ha_config->default_node_port) + *port = (unsigned short)ha_config->default_node_port; + else + *port = ZBX_DEFAULT_SERVER_PORT; + } } /****************************************************************************** @@ -641,7 +670,7 @@ static void ha_flush_audit(zbx_ha_info_t *info) * FAIL - node configuration or database error * * * ******************************************************************************/ -static void ha_db_create_node(zbx_ha_info_t *info) +static void ha_db_create_node(zbx_ha_info_t *info, zbx_ha_config_t *ha_config) { zbx_vector_ha_node_t nodes; int i, activate, db_time; @@ -673,7 +702,7 @@ static void ha_db_create_node(zbx_ha_info_t *info) if (SUCCEED != ha_db_get_time(info, &db_time)) goto out; - if (ZBX_HA_IS_CLUSTER()) + if (0 != is_ha_cluster(ha_config->ha_node_name)) { if (SUCCEED != ha_check_cluster_config(info, &nodes, db_time, &activate)) goto out; @@ -786,7 +815,7 @@ static int ha_db_check_unavailable_nodes(zbx_ha_info_t *info, zbx_vector_ha_node * In the case of critical error the error status will be set. * * * ******************************************************************************/ -static void ha_db_register_node(zbx_ha_info_t *info) +static void ha_db_register_node(zbx_ha_info_t *info, zbx_ha_config_t *ha_config) { zbx_vector_ha_node_t nodes; int ha_status = ZBX_NODE_STATUS_UNKNOWN, activate = SUCCEED, db_time; @@ -799,7 +828,7 @@ static void ha_db_register_node(zbx_ha_info_t *info) zbx_vector_ha_node_create(&nodes); - ha_db_create_node(info); + ha_db_create_node(info, ha_config); if (SUCCEED == zbx_cuid_empty(info->ha_nodeid)) goto finish; @@ -813,7 +842,7 @@ static void ha_db_register_node(zbx_ha_info_t *info) if (SUCCEED != ha_db_get_time(info, &db_time)) goto out; - if (ZBX_HA_IS_CLUSTER()) + if (0 != is_ha_cluster(ha_config->ha_node_name)) { if (SUCCEED != ha_check_cluster_config(info, &nodes, db_time, &activate)) goto out; @@ -831,7 +860,7 @@ static void ha_db_register_node(zbx_ha_info_t *info) } ha_status = SUCCEED == activate ? ZBX_NODE_STATUS_ACTIVE : ZBX_NODE_STATUS_STANDBY; - ha_get_external_address(&address, &port); + ha_get_external_address(&address, &port, ha_config); zbx_audit_init(info->auditlog); zbx_audit_ha_create_entry(ZBX_AUDIT_ACTION_UPDATE, info->ha_nodeid.str, info->name); @@ -863,14 +892,17 @@ static void ha_db_register_node(zbx_ha_info_t *info) if (SUCCEED == ha_db_execute(info, "%s where ha_nodeid='%s'", sql, info->ha_nodeid.str)) { - if (ZBX_HA_IS_CLUSTER()) + if (0 != is_ha_cluster(ha_config->ha_node_name)) ha_db_execute(info, "delete from ha_node where name=''"); else ha_db_execute(info, "delete from ha_node where name<>''"); } - if (ZBX_HA_IS_CLUSTER() && ZBX_NODE_STATUS_ERROR != info->ha_status && ZBX_NODE_STATUS_ACTIVE == ha_status) + if (0 != is_ha_cluster(ha_config->ha_node_name) && ZBX_NODE_STATUS_ERROR != info->ha_status && + ZBX_NODE_STATUS_ACTIVE == ha_status) + { ha_db_check_unavailable_nodes(info, &nodes, db_time); + } ha_flush_audit(info); @@ -975,7 +1007,7 @@ static int ha_check_active_node(zbx_ha_info_t *info, zbx_vector_ha_node_t *nodes * Comments: Sets error status on critical errors forcing manager to exit * * * ******************************************************************************/ -static void ha_check_nodes(zbx_ha_info_t *info) +static void ha_check_nodes(zbx_ha_info_t *info, zbx_ha_config_t *ha_config) { zbx_vector_ha_node_t nodes; zbx_ha_node_t *node; @@ -1024,7 +1056,7 @@ static void ha_check_nodes(zbx_ha_info_t *info) if (SUCCEED != ha_db_get_time(info, &db_time)) goto out; - if (ZBX_HA_IS_CLUSTER()) + if (0 != is_ha_cluster(ha_config->ha_node_name)) { if (ZBX_NODE_STATUS_ACTIVE == info->ha_status) { @@ -1116,7 +1148,7 @@ out: * Purpose: get cluster status in lld compatible json format * * * ******************************************************************************/ -static int ha_db_get_nodes_json(zbx_ha_info_t *info, char **nodes_json, char **error) +static int ha_db_get_nodes_json(zbx_ha_info_t *info, char **nodes_json, char **error, zbx_ha_config_t *ha_config) { zbx_vector_ha_node_t nodes; int i, db_time, ret = FAIL; @@ -1126,7 +1158,7 @@ static int ha_db_get_nodes_json(zbx_ha_info_t *info, char **nodes_json, char **e if (ZBX_DB_OK > info->db_status) goto out; - if (0 == ZBX_HA_IS_CLUSTER()) + if (0 == is_ha_cluster(ha_config->ha_node_name)) { /* return empty json array in standalone mode */ *nodes_json = zbx_strdup(NULL, "[]"); @@ -1403,7 +1435,7 @@ static void ha_get_failover_delay(zbx_ha_info_t *info, zbx_ipc_client_t *client) * Purpose: reply to get nodes request * * * ******************************************************************************/ -static void ha_send_node_list(zbx_ha_info_t *info, zbx_ipc_client_t *client) +static void ha_send_node_list(zbx_ha_info_t *info, zbx_ipc_client_t *client, zbx_ha_config_t *ha_config) { int ret; char *error = NULL, *nodes_json = NULL, *str; @@ -1412,7 +1444,7 @@ static void ha_send_node_list(zbx_ha_info_t *info, zbx_ipc_client_t *client) zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); - if (SUCCEED == (ret = ha_db_get_nodes_json(info, &nodes_json, &error))) + if (SUCCEED == (ret = ha_db_get_nodes_json(info, &nodes_json, &error, ha_config))) str = nodes_json; else str = error; @@ -1472,7 +1504,7 @@ out: * active - for standalone setup * * * ******************************************************************************/ -int zbx_ha_get_status(int *ha_status, int *ha_failover_delay, char **error) +int zbx_ha_get_status(const char *ha_node_name, int *ha_status, int *ha_failover_delay, char **error) { int ret; unsigned char *result = NULL; @@ -1498,7 +1530,7 @@ int zbx_ha_get_status(int *ha_status, int *ha_failover_delay, char **error) } else { - if (ZBX_HA_IS_CLUSTER()) + if (0 != is_ha_cluster(ha_node_name)) *ha_status = ZBX_NODE_STATUS_STANDBY; else *ha_status = ZBX_NODE_STATUS_ACTIVE; @@ -1520,7 +1552,8 @@ int zbx_ha_get_status(int *ha_status, int *ha_failover_delay, char **error) * process to switch to standby mode and initiate teardown process * * * ******************************************************************************/ -int zbx_ha_dispatch_message(zbx_ipc_message_t *message, int *ha_status, int *ha_failover_delay, char **error) +int zbx_ha_dispatch_message(const char *ha_node_name, zbx_ipc_message_t *message, int *ha_status, + int *ha_failover_delay, char **error) { static time_t last_hb; int ret = SUCCEED, ha_status_old; @@ -1561,7 +1594,7 @@ int zbx_ha_dispatch_message(zbx_ipc_message_t *message, int *ha_status, int *ha_ } } - if (ZBX_HA_IS_CLUSTER() && *ha_status == ZBX_NODE_STATUS_ACTIVE && 0 != last_hb) + if (0 != is_ha_cluster(ha_node_name) && *ha_status == ZBX_NODE_STATUS_ACTIVE && 0 != last_hb) { if (last_hb + *ha_failover_delay - ZBX_HA_POLL_PERIOD <= now || now < last_hb) *ha_status = ZBX_NODE_STATUS_STANDBY; @@ -1575,7 +1608,7 @@ out: * Purpose: start HA manager * * * ******************************************************************************/ -int zbx_ha_start(zbx_rtc_t *rtc, int ha_status, char **error) +int zbx_ha_start(zbx_rtc_t *rtc, zbx_ha_config_t *ha_config, char **error) { int ret = FAIL, status; zbx_uint32_t code = 0; @@ -1587,7 +1620,7 @@ int zbx_ha_start(zbx_rtc_t *rtc, int ha_status, char **error) zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); - args.args = (void *)(uintptr_t)ha_status; + args.args = (void *)ha_config; zbx_thread_start(ha_manager_thread, &args, &ha_pid); if (ZBX_THREAD_ERROR == ha_pid) @@ -1642,6 +1675,8 @@ out: zbx_ha_kill(); } + zbx_free(ha_config); + zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); return ret; @@ -1751,11 +1786,14 @@ ZBX_THREAD_ENTRY(ha_manager_thread, args) double now, tick; zbx_ha_info_t info; zbx_timespec_t timeout; + zbx_ha_config_t ha_config; zbx_setproctitle("ha manager"); zabbix_log(LOG_LEVEL_INFORMATION, "starting HA manager"); + ha_config = *(zbx_ha_config_t *)((zbx_thread_args_t *)args)->args; + if (FAIL == zbx_ipc_service_start(&service, ZBX_IPC_SERVICE_HA, &error)) { zabbix_log(LOG_LEVEL_CRIT, "cannot start HA manager service: %s", error); @@ -1778,8 +1816,8 @@ ZBX_THREAD_ENTRY(ha_manager_thread, args) } zbx_cuid_clear(info.ha_nodeid); - info.name = ZBX_NULL2EMPTY_STR(CONFIG_HA_NODE_NAME); - info.ha_status = (int)(uintptr_t)((zbx_thread_args_t *)args)->args; + info.name = ZBX_NULL2EMPTY_STR(ha_config.ha_node_name); + info.ha_status = ha_config.ha_status; info.error = NULL; info.db_status = ZBX_DB_DOWN; info.offline_ticks_active = 0; @@ -1791,7 +1829,7 @@ ZBX_THREAD_ENTRY(ha_manager_thread, args) if (ZBX_NODE_STATUS_UNKNOWN == info.ha_status) { - ha_db_register_node(&info); + ha_db_register_node(&info, &ha_config); if (ZBX_NODE_STATUS_ERROR == info.ha_status) goto pause; @@ -1817,9 +1855,9 @@ ZBX_THREAD_ENTRY(ha_manager_thread, args) int old_status = info.ha_status, delay; if (ZBX_NODE_STATUS_UNKNOWN == info.ha_status) - ha_db_register_node(&info); + ha_db_register_node(&info, &ha_config); else - ha_check_nodes(&info); + ha_check_nodes(&info, &ha_config); if (old_status != info.ha_status && ZBX_NODE_STATUS_UNKNOWN != info.ha_status) ha_update_parent(&rtc_socket, &info); @@ -1864,7 +1902,7 @@ ZBX_THREAD_ENTRY(ha_manager_thread, args) pause = SUCCEED; break; case ZBX_IPC_SERVICE_HA_GET_NODES: - ha_send_node_list(&info, client); + ha_send_node_list(&info, client, &ha_config); break; case ZBX_IPC_SERVICE_HA_REMOVE_NODE: ha_remove_node(&info, client, message); diff --git a/src/zabbix_server/housekeeper/housekeeper.c b/src/zabbix_server/housekeeper/housekeeper.c index 17297735733..cb8a8d260a1 100644 --- a/src/zabbix_server/housekeeper/housekeeper.c +++ b/src/zabbix_server/housekeeper/housekeeper.c @@ -27,7 +27,6 @@ #include "zbxnum.h" #include "zbxtime.h" #include "history_compress.h" -#include "../../libs/zbxdbcache/valuecache.h" extern ZBX_THREAD_LOCAL unsigned char process_type; extern unsigned char program_type; @@ -1130,7 +1129,7 @@ ZBX_THREAD_ENTRY(housekeeper_thread, args) zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(program_type), server_num, get_process_type_string(process_type), process_num); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); if (0 == CONFIG_HOUSEKEEPING_FREQUENCY) { @@ -1248,7 +1247,6 @@ ZBX_THREAD_ENTRY(housekeeper_thread, args) DBclose(); zbx_dc_cleanup_sessions(); - zbx_vc_housekeeping_value_cache(); zbx_setproctitle("%s [deleted %d hist/trends, %d items/triggers, %d events, %d sessions, %d alarms," " %d audit items, %d records in " ZBX_FS_DBL " sec, %s]", diff --git a/src/zabbix_server/housekeeper/trigger_housekeeper.c b/src/zabbix_server/housekeeper/trigger_housekeeper.c index 44464bb9eed..4915e651fcd 100644 --- a/src/zabbix_server/housekeeper/trigger_housekeeper.c +++ b/src/zabbix_server/housekeeper/trigger_housekeeper.c @@ -102,7 +102,7 @@ ZBX_THREAD_ENTRY(trigger_housekeeper_thread, args) zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(program_type), server_num, get_process_type_string(process_type), process_num); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); zbx_setproctitle("%s [connecting to the database]", get_process_type_string(process_type)); DBconnect(ZBX_DB_CONNECT_NORMAL); diff --git a/src/zabbix_server/httppoller/httppoller.c b/src/zabbix_server/httppoller/httppoller.c index 599757c0df6..8cbcabf2ae8 100644 --- a/src/zabbix_server/httppoller/httppoller.c +++ b/src/zabbix_server/httppoller/httppoller.c @@ -26,53 +26,12 @@ #include "httptest.h" #include "zbxtime.h" -extern int CONFIG_HTTPPOLLER_FORKS; extern ZBX_THREAD_LOCAL unsigned char process_type; extern unsigned char program_type; extern ZBX_THREAD_LOCAL int server_num, process_num; /****************************************************************************** * * - * Purpose: calculate when we have to process earliest httptest * - * * - * Return value: timestamp of earliest check or -1 if not found * - * * - ******************************************************************************/ -static int get_minnextcheck(void) -{ - DB_RESULT result; - DB_ROW row; - int res; - - result = DBselect( - "select min(t.nextcheck)" - " from httptest t,hosts h" - " where t.hostid=h.hostid" - " and " ZBX_SQL_MOD(t.httptestid,%d) "=%d" - " and t.status=%d" - " and h.proxy_hostid is null" - " and h.status=%d" - " and (h.maintenance_status=%d or h.maintenance_type=%d)", - CONFIG_HTTPPOLLER_FORKS, process_num - 1, - HTTPTEST_STATUS_MONITORED, - HOST_STATUS_MONITORED, - HOST_MAINTENANCE_STATUS_OFF, MAINTENANCE_TYPE_NORMAL); - - if (NULL == (row = DBfetch(result)) || SUCCEED == DBis_null(row[0])) - { - zabbix_log(LOG_LEVEL_DEBUG, "No httptests to process in get_minnextcheck."); - res = FAIL; - } - else - res = atoi(row[0]); - - DBfree_result(result); - - return res; -} - -/****************************************************************************** - * * * Purpose: main loop of processing of httptests * * * * Comments: never returns * @@ -80,9 +39,9 @@ static int get_minnextcheck(void) ******************************************************************************/ ZBX_THREAD_ENTRY(httppoller_thread, args) { - int now, nextcheck, sleeptime = -1, httptests_count = 0, old_httptests_count = 0; + int sleeptime = -1, httptests_count = 0, old_httptests_count = 0; double sec, total_sec = 0.0, old_total_sec = 0.0; - time_t last_stat_time; + time_t last_stat_time, nextcheck = 0; process_type = ((zbx_thread_args_t *)args)->process_type; server_num = ((zbx_thread_args_t *)args)->server_num; @@ -91,7 +50,7 @@ ZBX_THREAD_ENTRY(httppoller_thread, args) zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(program_type), server_num, get_process_type_string(process_type), process_num); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); #define STAT_INTERVAL 5 /* if a process is busy and does not sleep then update status not faster than */ /* once in STAT_INTERVAL seconds */ @@ -113,11 +72,15 @@ ZBX_THREAD_ENTRY(httppoller_thread, args) old_total_sec); } - now = time(NULL); - httptests_count += process_httptests(process_num, now); - total_sec += zbx_time() - sec; + if ((int)sec >= nextcheck) + { + httptests_count += process_httptests((int)sec, &nextcheck); + total_sec += zbx_time() - sec; + + if (0 == nextcheck) + nextcheck = time(NULL) + POLLER_DELAY; + } - nextcheck = get_minnextcheck(); sleeptime = zbx_calculate_sleeptime(nextcheck, POLLER_DELAY); if (0 != sleeptime || STAT_INTERVAL <= time(NULL) - last_stat_time) diff --git a/src/zabbix_server/httppoller/httptest.c b/src/zabbix_server/httppoller/httptest.c index 5aebfe284dd..9b57d866836 100644 --- a/src/zabbix_server/httppoller/httptest.c +++ b/src/zabbix_server/httppoller/httptest.c @@ -37,8 +37,6 @@ typedef struct } zbx_httpstat_t; -extern int CONFIG_HTTPPOLLER_FORKS; - #ifdef HAVE_LIBCURL typedef struct @@ -166,7 +164,7 @@ static void process_test_data(zbx_uint64_t httptestid, int lastfailedstep, doubl continue; } - init_result(&value); + zbx_init_agent_result(&value); switch (types[i]) { @@ -185,7 +183,7 @@ static void process_test_data(zbx_uint64_t httptestid, int lastfailedstep, doubl zbx_preprocess_item_value(items[i].itemid, items[i].host.hostid, items[i].value_type, 0, &value, ts, items[i].state, NULL); - free_result(&value); + zbx_free_agent_result(&value); } DCconfig_clean_items(items, errcodes, num); @@ -305,7 +303,7 @@ static void process_step_data(zbx_uint64_t httpstepid, zbx_httpstat_t *stat, zbx continue; } - init_result(&value); + zbx_init_agent_result(&value); switch (types[i]) { @@ -324,7 +322,7 @@ static void process_step_data(zbx_uint64_t httpstepid, zbx_httpstat_t *stat, zbx zbx_preprocess_item_value(items[i].itemid, items[i].host.hostid, items[i].value_type, 0, &value, ts, items[i].state, NULL); - free_result(&value); + zbx_free_agent_result(&value); } DCconfig_clean_items(items, errcodes, num); @@ -609,14 +607,13 @@ out: * Purpose: process single scenario of http test * * * ******************************************************************************/ -static void process_httptest(DC_HOST *host, zbx_httptest_t *httptest) +static void process_httptest(DC_HOST *host, zbx_httptest_t *httptest, int *delay) { DB_RESULT result; DB_HTTPSTEP db_httpstep; char *err_str = NULL, *buffer = NULL; int lastfailedstep = 0; zbx_timespec_t ts; - int delay; double speed_download = 0; int speed_download_num = 0; #ifdef HAVE_LIBCURL @@ -640,17 +637,18 @@ static void process_httptest(DC_HOST *host, zbx_httptest_t *httptest) buffer = zbx_strdup(buffer, httptest->httptest.delay); zbx_substitute_simple_macros(NULL, NULL, NULL, NULL, &host->hostid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - &buffer, MACRO_TYPE_COMMON, NULL, 0); + &buffer, MACRO_TYPE_COMMON, NULL, 0); /* Avoid the potential usage of uninitialized values when: */ /* 1) compile without libCURL support */ /* 2) update interval is invalid */ db_httpstep.name = NULL; - if (SUCCEED != zbx_is_time_suffix(buffer, &delay, ZBX_LENGTH_UNLIMITED)) + if (SUCCEED != zbx_is_time_suffix(buffer, delay, ZBX_LENGTH_UNLIMITED)) { err_str = zbx_dsprintf(err_str, "update interval \"%s\" is invalid", buffer); lastfailedstep = -1; + *delay = ZBX_DEFAULT_INTERVAL; goto httptest_error; } @@ -977,24 +975,6 @@ clean: httptest_error: zbx_timespec(&ts); - if (0 > lastfailedstep) /* update interval is invalid, delay is uninitialized */ - { - DBexecute("update httptest set nextcheck=%d where httptestid=" ZBX_FS_UI64, - 0 > ts.sec ? ZBX_JAN_2038 : ts.sec + SEC_PER_MIN, httptest->httptest.httptestid); - } - else if (0 > ts.sec + delay) - { - zabbix_log(LOG_LEVEL_WARNING, "nextcheck update causes overflow for web scenario \"%s\" on host \"%s\"", - httptest->httptest.name, host->name); - DBexecute("update httptest set nextcheck=%d where httptestid=" ZBX_FS_UI64, - ZBX_JAN_2038, httptest->httptest.httptestid); - } - else - { - DBexecute("update httptest set nextcheck=%d where httptestid=" ZBX_FS_UI64, - ts.sec + delay, httptest->httptest.httptestid); - } - if (NULL != err_str) { if (0 >= lastfailedstep) @@ -1036,10 +1016,11 @@ httptest_error: * Comments: always SUCCEED * * * ******************************************************************************/ -int process_httptests(int httppoller_num, int now) +int process_httptests(int now, time_t *nextcheck) { DB_RESULT result; DB_ROW row; + zbx_uint64_t httptestid; zbx_httptest_t httptest; DC_HOST host; int httptests_count = 0; @@ -1047,120 +1028,126 @@ int process_httptests(int httppoller_num, int now) zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + if (SUCCEED != zbx_dc_httptest_next(now, &httptestid, nextcheck)) + goto out; + um_handle = zbx_dc_open_user_macros(); /* create macro cache to use in http tests */ zbx_vector_ptr_pair_create(&httptest.macros); - result = DBselect( - "select h.hostid,h.host,h.name,t.httptestid,t.name,t.agent," - "t.authentication,t.http_user,t.http_password,t.http_proxy,t.retries,t.ssl_cert_file," - "t.ssl_key_file,t.ssl_key_password,t.verify_peer,t.verify_host,t.delay" - " from httptest t,hosts h" - " where t.hostid=h.hostid" - " and t.nextcheck<=%d" - " and " ZBX_SQL_MOD(t.httptestid,%d) "=%d" - " and t.status=%d" - " and h.proxy_hostid is null" - " and h.status=%d" - " and (h.maintenance_status=%d or h.maintenance_type=%d)", - now, - CONFIG_HTTPPOLLER_FORKS, httppoller_num - 1, - HTTPTEST_STATUS_MONITORED, - HOST_STATUS_MONITORED, - HOST_MAINTENANCE_STATUS_OFF, MAINTENANCE_TYPE_NORMAL); - - while (NULL != (row = DBfetch(result)) && ZBX_IS_RUNNING()) + do { - ZBX_STR2UINT64(host.hostid, row[0]); - zbx_strscpy(host.host, row[1]); - zbx_strlcpy_utf8(host.name, row[2], sizeof(host.name)); - - ZBX_STR2UINT64(httptest.httptest.httptestid, row[3]); - httptest.httptest.name = row[4]; - - if (SUCCEED != httptest_load_pairs(&host, &httptest)) + int delay = 0; + + result = DBselect( + "select h.hostid,h.host,h.name,t.httptestid,t.name,t.agent," + "t.authentication,t.http_user,t.http_password,t.http_proxy,t.retries,t.ssl_cert_file," + "t.ssl_key_file,t.ssl_key_password,t.verify_peer,t.verify_host,t.delay" + " from httptest t,hosts h" + " where t.hostid=h.hostid" + " and t.httptestid=" ZBX_FS_UI64, + httptestid); + + if (NULL != (row = DBfetch(result))) { - zabbix_log(LOG_LEVEL_WARNING, "cannot process web scenario \"%s\" on host \"%s\": " - "cannot load web scenario data", httptest.httptest.name, host.name); - THIS_SHOULD_NEVER_HAPPEN; - continue; - } - - httptest.httptest.agent = zbx_strdup(NULL, row[5]); - zbx_substitute_simple_macros(NULL, NULL, NULL, NULL, &host.hostid, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, &httptest.httptest.agent, MACRO_TYPE_COMMON, NULL, 0); + ZBX_STR2UINT64(host.hostid, row[0]); + zbx_strscpy(host.host, row[1]); + zbx_strlcpy_utf8(host.name, row[2], sizeof(host.name)); - if (HTTPTEST_AUTH_NONE != (httptest.httptest.authentication = atoi(row[6]))) - { - httptest.httptest.http_user = zbx_strdup(NULL, row[7]); - zbx_substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, &host.hostid, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, &httptest.httptest.http_user, MACRO_TYPE_COMMON, NULL, 0); + ZBX_STR2UINT64(httptest.httptest.httptestid, row[3]); + httptest.httptest.name = row[4]; - httptest.httptest.http_password = zbx_strdup(NULL, row[8]); - zbx_substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, &host.hostid, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, &httptest.httptest.http_password, MACRO_TYPE_COMMON, NULL, 0); - } + if (SUCCEED != httptest_load_pairs(&host, &httptest)) + { + zabbix_log(LOG_LEVEL_WARNING, "cannot process web scenario \"%s\" on host \"%s\": " + "cannot load web scenario data", httptest.httptest.name, host.name); + DBfree_result(result); + THIS_SHOULD_NEVER_HAPPEN; + continue; + } - if ('\0' != *row[9]) - { - httptest.httptest.http_proxy = zbx_strdup(NULL, row[9]); + httptest.httptest.agent = zbx_strdup(NULL, row[5]); zbx_substitute_simple_macros(NULL, NULL, NULL, NULL, &host.hostid, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, &httptest.httptest.http_proxy, MACRO_TYPE_COMMON, NULL, 0); - } - else - httptest.httptest.http_proxy = NULL; + NULL, NULL, &httptest.httptest.agent, MACRO_TYPE_COMMON, NULL, 0); - httptest.httptest.retries = atoi(row[10]); + if (HTTPTEST_AUTH_NONE != (httptest.httptest.authentication = atoi(row[6]))) + { + httptest.httptest.http_user = zbx_strdup(NULL, row[7]); + zbx_substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, &host.hostid, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, &httptest.httptest.http_user, + MACRO_TYPE_COMMON, NULL, 0); + + httptest.httptest.http_password = zbx_strdup(NULL, row[8]); + zbx_substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, &host.hostid, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, &httptest.httptest.http_password, + MACRO_TYPE_COMMON, NULL, 0); + } - httptest.httptest.ssl_cert_file = zbx_strdup(NULL, row[11]); - zbx_substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, &host, NULL, NULL, NULL, NULL, NULL, NULL, - &httptest.httptest.ssl_cert_file, MACRO_TYPE_HTTPTEST_FIELD, NULL, 0); + if ('\0' != *row[9]) + { + httptest.httptest.http_proxy = zbx_strdup(NULL, row[9]); + zbx_substitute_simple_macros(NULL, NULL, NULL, NULL, &host.hostid, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, &httptest.httptest.http_proxy, + MACRO_TYPE_COMMON, NULL, 0); + } + else + httptest.httptest.http_proxy = NULL; - httptest.httptest.ssl_key_file = zbx_strdup(NULL, row[12]); - zbx_substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, &host, NULL, NULL, NULL, NULL, NULL, NULL, - &httptest.httptest.ssl_key_file, MACRO_TYPE_HTTPTEST_FIELD, NULL, 0); + httptest.httptest.retries = atoi(row[10]); - httptest.httptest.ssl_key_password = zbx_strdup(NULL, row[13]); - zbx_substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, &host.hostid, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, &httptest.httptest.ssl_key_password, MACRO_TYPE_COMMON, NULL, 0); + httptest.httptest.ssl_cert_file = zbx_strdup(NULL, row[11]); + zbx_substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, &host, NULL, NULL, NULL, NULL, NULL, + NULL, &httptest.httptest.ssl_cert_file, MACRO_TYPE_HTTPTEST_FIELD, NULL, 0); - httptest.httptest.verify_peer = atoi(row[14]); - httptest.httptest.verify_host = atoi(row[15]); + httptest.httptest.ssl_key_file = zbx_strdup(NULL, row[12]); + zbx_substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, &host, NULL, NULL, NULL, NULL, NULL, + NULL, &httptest.httptest.ssl_key_file, MACRO_TYPE_HTTPTEST_FIELD, NULL, 0); - httptest.httptest.delay = row[16]; + httptest.httptest.ssl_key_password = zbx_strdup(NULL, row[13]); + zbx_substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, &host.hostid, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, &httptest.httptest.ssl_key_password, MACRO_TYPE_COMMON, + NULL, 0); - /* add httptest variables to the current test macro cache */ - http_process_variables(&httptest, &httptest.variables, NULL, NULL); + httptest.httptest.verify_peer = atoi(row[14]); + httptest.httptest.verify_host = atoi(row[15]); - process_httptest(&host, &httptest); + httptest.httptest.delay = row[16]; - zbx_free(httptest.httptest.ssl_key_password); - zbx_free(httptest.httptest.ssl_key_file); - zbx_free(httptest.httptest.ssl_cert_file); - zbx_free(httptest.httptest.http_proxy); + /* add httptest variables to the current test macro cache */ + http_process_variables(&httptest, &httptest.variables, NULL, NULL); - if (HTTPTEST_AUTH_NONE != httptest.httptest.authentication) - { - zbx_free(httptest.httptest.http_password); - zbx_free(httptest.httptest.http_user); - } - zbx_free(httptest.httptest.agent); - zbx_free(httptest.headers); - httppairs_free(&httptest.variables); + process_httptest(&host, &httptest, &delay); + zbx_dc_httptest_queue(now, httptestid, delay); + + zbx_free(httptest.httptest.ssl_key_password); + zbx_free(httptest.httptest.ssl_key_file); + zbx_free(httptest.httptest.ssl_cert_file); + zbx_free(httptest.httptest.http_proxy); + + if (HTTPTEST_AUTH_NONE != httptest.httptest.authentication) + { + zbx_free(httptest.httptest.http_password); + zbx_free(httptest.httptest.http_user); + } + zbx_free(httptest.httptest.agent); + zbx_free(httptest.headers); + httppairs_free(&httptest.variables); - /* clear the macro cache used in this http test */ - httptest_remove_macros(&httptest); + /* clear the macro cache used in this http test */ + httptest_remove_macros(&httptest); - httptests_count++; /* performance metric */ + httptests_count++; /* performance metric */ + } + DBfree_result(result); } + while (ZBX_IS_RUNNING() && SUCCEED == zbx_dc_httptest_next(now, &httptestid, nextcheck)); + /* destroy the macro cache used in http tests */ zbx_vector_ptr_pair_destroy(&httptest.macros); - DBfree_result(result); - zbx_dc_close_user_macros(um_handle); - +out: zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); return httptests_count; diff --git a/src/zabbix_server/httppoller/httptest.h b/src/zabbix_server/httppoller/httptest.h index 8ab9fbd208f..617ceefe029 100644 --- a/src/zabbix_server/httppoller/httptest.h +++ b/src/zabbix_server/httppoller/httptest.h @@ -20,6 +20,8 @@ #ifndef ZABBIX_HTTPTEST_H #define ZABBIX_HTTPTEST_H -int process_httptests(int httppoller_num, int now); +#include "zbxcommon.h" + +int process_httptests(int now, time_t *nextcheck); #endif diff --git a/src/zabbix_server/ipmi/ipmi_manager.c b/src/zabbix_server/ipmi/ipmi_manager.c index ae42db55f9d..66ac2e9f5ff 100644 --- a/src/zabbix_server/ipmi/ipmi_manager.c +++ b/src/zabbix_server/ipmi/ipmi_manager.c @@ -909,12 +909,12 @@ static void ipmi_manager_process_value_result(zbx_ipmi_manager_t *manager, zbx_i state = ITEM_STATE_NORMAL; if (NULL != value) { - init_result(&result); + zbx_init_agent_result(&result); SET_TEXT_RESULT(&result, value); value = NULL; zbx_preprocess_item_value(itemid, poller->request->hostid, ITEM_VALUE_TYPE_TEXT, flags, &result, &ts, state, NULL); - free_result(&result); + zbx_free_agent_result(&result); } break; @@ -963,7 +963,7 @@ ZBX_THREAD_ENTRY(ipmi_manager_thread, args) zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(program_type), server_num, get_process_type_string(process_type), process_num); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); if (FAIL == zbx_ipc_service_start(&ipmi_service, ZBX_IPC_SERVICE_IPMI, &error)) { @@ -1010,9 +1010,9 @@ ZBX_THREAD_ENTRY(ipmi_manager_thread, args) if (ZBX_IPMI_MANAGER_DELAY < timeout.sec) timeout.sec = ZBX_IPMI_MANAGER_DELAY; - update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); ret = zbx_ipc_service_recv(&ipmi_service, &timeout, &client, &message); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); sec = zbx_time(); zbx_update_env(sec); diff --git a/src/zabbix_server/ipmi/ipmi_poller.c b/src/zabbix_server/ipmi/ipmi_poller.c index d16d0df07f1..b0121409a09 100644 --- a/src/zabbix_server/ipmi/ipmi_poller.c +++ b/src/zabbix_server/ipmi/ipmi_poller.c @@ -187,7 +187,7 @@ ZBX_THREAD_ENTRY(ipmi_poller_thread, args) zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(program_type), server_num, get_process_type_string(process_type), process_num); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); if (FAIL == zbx_ipc_async_socket_open(&ipmi_socket, ZBX_IPC_SERVICE_IPMI, SEC_PER_MIN, &error)) { @@ -221,7 +221,7 @@ ZBX_THREAD_ENTRY(ipmi_poller_thread, args) polled_num = 0; } - update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); while (ZBX_IS_RUNNING()) { @@ -240,7 +240,7 @@ ZBX_THREAD_ENTRY(ipmi_poller_thread, args) zbx_perform_all_openipmi_ops(ipmi_timeout); } - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); if (NULL == message) break; diff --git a/src/zabbix_server/lld/lld.c b/src/zabbix_server/lld/lld.c index 9d178816006..1d6f22aa7ed 100644 --- a/src/zabbix_server/lld/lld.c +++ b/src/zabbix_server/lld/lld.c @@ -116,7 +116,7 @@ static void lld_filter_init(lld_filter_t *filter) { zbx_vector_ptr_create(&filter->conditions); filter->expression = NULL; - filter->evaltype = CONDITION_EVAL_TYPE_AND_OR; + filter->evaltype = ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR; } /****************************************************************************** @@ -195,7 +195,7 @@ static int lld_filter_load(lld_filter_t *filter, zbx_uint64_t lld_ruleid, const ; DBfree_result(result); - if (CONDITION_EVAL_TYPE_AND_OR == filter->evaltype) + if (ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR == filter->evaltype) zbx_vector_ptr_sort(&filter->conditions, lld_condition_compare_by_macro); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); @@ -225,11 +225,11 @@ static int filter_condition_match(const struct zbx_json_parse *jp_row, const zbx if (SUCCEED == zbx_lld_macro_value_by_name(jp_row, lld_macro_paths, condition->macro, &value)) { - if (CONDITION_OPERATOR_NOT_EXIST == condition->op) + if (ZBX_CONDITION_OPERATOR_NOT_EXIST == condition->op) { *result = 0; } - if (CONDITION_OPERATOR_EXIST == condition->op) + else if (ZBX_CONDITION_OPERATOR_EXIST == condition->op) { *result = 1; } @@ -238,10 +238,11 @@ static int filter_condition_match(const struct zbx_json_parse *jp_row, const zbx switch (regexp_match_ex(&condition->regexps, value, condition->regexp, ZBX_CASE_SENSITIVE)) { case ZBX_REGEXP_MATCH: - *result = (CONDITION_OPERATOR_REGEXP == condition->op ? 1 : 0); + *result = (ZBX_CONDITION_OPERATOR_REGEXP == condition->op ? 1 : 0); break; case ZBX_REGEXP_NO_MATCH: - *result = (CONDITION_OPERATOR_NOT_REGEXP == condition->op ? 1 : 0); + *result = (ZBX_CONDITION_OPERATOR_NOT_REGEXP == condition->op ? 1 : 0); + break; break; default: *info = zbx_strdcatf(*info, "Cannot accurately apply filter: invalid regular " @@ -254,10 +255,10 @@ static int filter_condition_match(const struct zbx_json_parse *jp_row, const zbx { switch (condition->op) { - case CONDITION_OPERATOR_NOT_EXIST: + case ZBX_CONDITION_OPERATOR_NOT_EXIST: *result = 1; break; - case CONDITION_OPERATOR_EXIST: + case ZBX_CONDITION_OPERATOR_EXIST: *result = 0; break; default: @@ -306,7 +307,7 @@ static int filter_evaluate_and_or_andor(const lld_filter_t *filter, const struct switch (filter->evaltype) { - case CONDITION_EVAL_TYPE_AND_OR: + case ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR: if (NULL == lastmacro) { zbx_chrcpy_alloc(&expression, &expression_alloc, &expression_offset, '('); @@ -320,8 +321,8 @@ static int filter_evaluate_and_or_andor(const lld_filter_t *filter, const struct lastmacro = condition->macro; break; - case CONDITION_EVAL_TYPE_AND: - case CONDITION_EVAL_TYPE_OR: + case ZBX_ACTION_CONDITION_EVAL_TYPE_AND: + case ZBX_ACTION_CONDITION_EVAL_TYPE_OR: if (0 != i) { zbx_chrcpy_alloc(&expression, &expression_alloc, &expression_offset, ' '); @@ -350,7 +351,7 @@ static int filter_evaluate_and_or_andor(const lld_filter_t *filter, const struct if (filter->conditions.values_num == i + 1) { - if (CONDITION_EVAL_TYPE_AND_OR == filter->evaltype) + if (ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR == filter->evaltype) zbx_chrcpy_alloc(&expression, &expression_alloc, &expression_offset, ')'); expression_offset++; @@ -484,13 +485,13 @@ static int filter_evaluate(const lld_filter_t *filter, const struct zbx_json_par switch (filter->evaltype) { - case CONDITION_EVAL_TYPE_AND_OR: + case ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR: ZBX_FALLTHROUGH; - case CONDITION_EVAL_TYPE_AND: + case ZBX_ACTION_CONDITION_EVAL_TYPE_AND: ZBX_FALLTHROUGH; - case CONDITION_EVAL_TYPE_OR: + case ZBX_ACTION_CONDITION_EVAL_TYPE_OR: return filter_evaluate_and_or_andor(filter, jp_row, lld_macro_paths, info); - case CONDITION_EVAL_TYPE_EXPRESSION: + case ZBX_ACTION_CONDITION_EVAL_TYPE_EXPRESSION: return filter_evaluate_expression(filter, jp_row, lld_macro_paths, info); } @@ -541,7 +542,7 @@ static int lld_override_conditions_load(zbx_vector_ptr_t *overrides, const zbx_v { override = (lld_override_t *)overrides->values[i]; - if (CONDITION_EVAL_TYPE_AND_OR == override->filter.evaltype) + if (ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR == override->filter.evaltype) zbx_vector_ptr_sort(&override->filter.conditions, lld_condition_compare_by_macro); } @@ -715,11 +716,11 @@ static int regexp_strmatch_condition(const char *value, const char *pattern, uns { switch (op) { - case CONDITION_OPERATOR_REGEXP: + case ZBX_CONDITION_OPERATOR_REGEXP: if (NULL != zbx_regexp_match(value, pattern, NULL)) return SUCCEED; break; - case CONDITION_OPERATOR_NOT_REGEXP: + case ZBX_CONDITION_OPERATOR_NOT_REGEXP: if (NULL == zbx_regexp_match(value, pattern, NULL)) return SUCCEED; break; diff --git a/src/zabbix_server/lld/lld_item.c b/src/zabbix_server/lld/lld_item.c index 7db84c0b3ae..d1cf75e32b7 100644 --- a/src/zabbix_server/lld/lld_item.c +++ b/src/zabbix_server/lld/lld_item.c @@ -3654,7 +3654,7 @@ static int lld_items_param_save(zbx_uint64_t hostid, zbx_vector_ptr_t *items, in for (j = 0; j < item->item_params.values_num; j++) { - item_param = (zbx_item_param_t *)item->item_params.values[j]; + item_param = item->item_params.values[j]; if (0 != (item_param->flags & ZBX_FLAG_ITEM_PARAM_DELETE)) { @@ -3715,7 +3715,7 @@ static int lld_items_param_save(zbx_uint64_t hostid, zbx_vector_ptr_t *items, in { char delim = ' '; - item_param = (zbx_item_param_t *)item->item_params.values[j]; + item_param = item->item_params.values[j]; if (0 == item_param->item_parameterid) { diff --git a/src/zabbix_server/lld/lld_manager.c b/src/zabbix_server/lld/lld_manager.c index 312dcb9a9cf..845b6dbc596 100644 --- a/src/zabbix_server/lld/lld_manager.c +++ b/src/zabbix_server/lld/lld_manager.c @@ -591,7 +591,7 @@ ZBX_THREAD_ENTRY(lld_manager_thread, args) zbx_setproctitle("%s #%d started", get_process_type_string(process_type), process_num); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); while (ZBX_IS_RUNNING()) { @@ -609,9 +609,9 @@ ZBX_THREAD_ENTRY(lld_manager_thread, args) processed_num = 0; } - update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); ret = zbx_ipc_service_recv(&lld_service, &timeout, &client, &message); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); sec = zbx_time(); zbx_update_env(sec); diff --git a/src/zabbix_server/lld/lld_worker.c b/src/zabbix_server/lld/lld_worker.c index 74038b6b5c7..72ec4c6b059 100644 --- a/src/zabbix_server/lld/lld_worker.c +++ b/src/zabbix_server/lld/lld_worker.c @@ -202,7 +202,7 @@ ZBX_THREAD_ENTRY(lld_worker_thread, args) zbx_setproctitle("%s #%d started", get_process_type_string(process_type), process_num); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); while (ZBX_IS_RUNNING()) { @@ -219,13 +219,13 @@ ZBX_THREAD_ENTRY(lld_worker_thread, args) processed_num = 0; } - update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); if (SUCCEED != zbx_ipc_socket_read(&lld_socket, &message)) { zabbix_log(LOG_LEVEL_CRIT, "cannot read LLD manager service request"); exit(EXIT_FAILURE); } - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); time_read = zbx_time(); time_idle += time_read - time_now; diff --git a/src/zabbix_server/odbc/odbc.c b/src/zabbix_server/odbc/odbc.c index b6010192a5d..ff2a45897cb 100644 --- a/src/zabbix_server/odbc/odbc.c +++ b/src/zabbix_server/odbc/odbc.c @@ -23,13 +23,14 @@ #include "odbc.h" -#include <sql.h> -#include <sqlext.h> - #include "log.h" #include "zbxjson.h" #include "zbxalgo.h" #include "zbxstr.h" +#include "zbxexpr.h" + +#include <sql.h> +#include <sqlext.h> struct zbx_odbc_data_source { @@ -628,7 +629,7 @@ static int odbc_query_result_to_json(zbx_odbc_query_result_t *query_result, int if (0 != isalpha((unsigned char)*p)) *p = toupper((unsigned char)*p); - if (SUCCEED != is_macro_char(*p)) + if (SUCCEED != zbx_is_macro_char(*p)) { *error = zbx_dsprintf(*error, "Cannot convert column #%d name to macro.", i + 1); goto out; diff --git a/src/zabbix_server/operations.c b/src/zabbix_server/operations.c index a45881b1524..be44b3055a6 100644 --- a/src/zabbix_server/operations.c +++ b/src/zabbix_server/operations.c @@ -368,7 +368,7 @@ static zbx_uint64_t add_discovered_host(const ZBX_DB_EVENT *event, int *status, DBfree_result(result3); /* for host uniqueness purposes */ - make_hostname(host); /* replace not-allowed symbols */ + zbx_make_hostname(host); /* replace not-allowed symbols */ host_unique = DBget_unique_hostname_by_sample(host, "host"); zbx_free(host); @@ -422,7 +422,7 @@ static zbx_uint64_t add_discovered_host(const ZBX_DB_EVENT *event, int *status, DBfree_result(result3); zbx_free(sql); - make_hostname(host_visible); /* replace not-allowed symbols */ + zbx_make_hostname(host_visible); /* replace not-allowed symbols */ zbx_free(hostname); hostname = DBget_unique_hostname_by_sample(host_visible, "name"); zbx_free(host_visible); diff --git a/src/zabbix_server/pinger/pinger.c b/src/zabbix_server/pinger/pinger.c index 00df813928a..a79a86b6caf 100644 --- a/src/zabbix_server/pinger/pinger.c +++ b/src/zabbix_server/pinger/pinger.c @@ -74,7 +74,7 @@ static void process_value(zbx_uint64_t itemid, zbx_uint64_t *value_ui64, double } else { - init_result(&value); + zbx_init_agent_result(&value); if (NULL != value_ui64) SET_UI64_RESULT(&value, *value_ui64); @@ -85,7 +85,7 @@ static void process_value(zbx_uint64_t itemid, zbx_uint64_t *value_ui64, double zbx_preprocess_item_value(item.itemid, item.host.hostid, item.value_type, item.flags, &value, ts, item.state, NULL); - free_result(&value); + zbx_free_agent_result(&value); } clean: DCrequeue_items(&item.itemid, &ts->sec, &errcode, 1); @@ -182,30 +182,31 @@ static void process_values(icmpitem_t *items, int first_index, int last_index, Z zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); } -static int parse_key_params(const char *key, const char *host_addr, icmpping_t *icmpping, char **addr, int *count, - int *interval, int *size, int *timeout, icmppingsec_type_t *type, char *error, int max_error_len) +static int zbx_parse_key_params(const char *key, const char *host_addr, icmpping_t *icmpping, char **addr, + int *count, int *interval, int *size, int *timeout, icmppingsec_type_t *type, char *error, + int max_error_len) { const char *tmp; int ret = NOTSUPPORTED; AGENT_REQUEST request; - init_request(&request); + zbx_init_agent_request(&request); - if (SUCCEED != parse_item_key(key, &request)) + if (SUCCEED != zbx_parse_item_key(key, &request)) { zbx_snprintf(error, max_error_len, "Invalid item key format."); goto out; } - if (0 == strcmp(get_rkey(&request), SERVER_ICMPPING_KEY)) + if (0 == strcmp(get_rkey(&request), ZBX_SERVER_ICMPPING_KEY)) { *icmpping = ICMPPING; } - else if (0 == strcmp(get_rkey(&request), SERVER_ICMPPINGLOSS_KEY)) + else if (0 == strcmp(get_rkey(&request), ZBX_SERVER_ICMPPINGLOSS_KEY)) { *icmpping = ICMPPINGLOSS; } - else if (0 == strcmp(get_rkey(&request), SERVER_ICMPPINGSEC_KEY)) + else if (0 == strcmp(get_rkey(&request), ZBX_SERVER_ICMPPINGSEC_KEY)) { *icmpping = ICMPPINGSEC; } @@ -303,7 +304,7 @@ static int parse_key_params(const char *key, const char *host_addr, icmpping_t * ret = SUCCEED; out: - free_request(&request); + zbx_free_agent_request(&request); return ret; } @@ -412,7 +413,7 @@ static void get_pinger_hosts(icmpitem_t **icmp_items, int *icmp_items_alloc, int if (SUCCEED == rc) { - rc = parse_key_params(items[i].key, items[i].interface.addr, &icmpping, &addr, &count, + rc = zbx_parse_key_params(items[i].key, items[i].interface.addr, &icmpping, &addr, &count, &interval, &size, &timeout, &type, error, sizeof(error)); } @@ -550,7 +551,7 @@ ZBX_THREAD_ENTRY(pinger_thread, args) zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(program_type), server_num, get_process_type_string(process_type), process_num); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); if (NULL == items) items = (icmpitem_t *)zbx_malloc(items, sizeof(icmpitem_t) * items_alloc); diff --git a/src/zabbix_server/poller/checks_agent.c b/src/zabbix_server/poller/checks_agent.c index f5b282f9734..edcbcf120ac 100644 --- a/src/zabbix_server/poller/checks_agent.c +++ b/src/zabbix_server/poller/checks_agent.c @@ -127,7 +127,7 @@ int get_value_agent(const DC_ITEM *item, AGENT_RESULT *result) ret = NETWORK_ERROR; } else - set_result_type(result, ITEM_VALUE_TYPE_TEXT, s.buffer); + zbx_set_agent_result_type(result, ITEM_VALUE_TYPE_TEXT, s.buffer); } else SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Get value from agent failed: %s", zbx_socket_strerror())); diff --git a/src/zabbix_server/poller/checks_db.c b/src/zabbix_server/poller/checks_db.c index 3a51e5ea107..51136df1de2 100644 --- a/src/zabbix_server/poller/checks_db.c +++ b/src/zabbix_server/poller/checks_db.c @@ -49,9 +49,9 @@ int get_value_db(const DC_ITEM *item, AGENT_RESULT *result) zabbix_log(LOG_LEVEL_DEBUG, "In %s() key_orig:'%s' query:'%s'", __func__, item->key_orig, item->params); - init_request(&request); + zbx_init_agent_request(&request); - if (SUCCEED != parse_item_key(item->key, &request)) + if (SUCCEED != zbx_parse_item_key(item->key, &request)) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid item key format.")); goto out; @@ -116,7 +116,7 @@ int get_value_db(const DC_ITEM *item, AGENT_RESULT *result) if (SUCCEED != ret) SET_MSG_RESULT(result, error); out: - free_request(&request); + zbx_free_agent_request(&request); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); diff --git a/src/zabbix_server/poller/checks_external.c b/src/zabbix_server/poller/checks_external.c index a851d661eca..ecba2012e22 100644 --- a/src/zabbix_server/poller/checks_external.c +++ b/src/zabbix_server/poller/checks_external.c @@ -45,9 +45,9 @@ int get_value_external(const DC_ITEM *item, AGENT_RESULT *result) zabbix_log(LOG_LEVEL_DEBUG, "In %s() key:'%s'", __func__, item->key); - init_request(&request); + zbx_init_agent_request(&request); - if (SUCCEED != parse_item_key(item->key, &request)) + if (SUCCEED != zbx_parse_item_key(item->key, &request)) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid item key format.")); goto out; @@ -79,7 +79,7 @@ int get_value_external(const DC_ITEM *item, AGENT_RESULT *result) { zbx_rtrim(buf, ZBX_WHITESPACE); - set_result_type(result, ITEM_VALUE_TYPE_TEXT, buf); + zbx_set_agent_result_type(result, ITEM_VALUE_TYPE_TEXT, buf); zbx_free(buf); } else @@ -92,7 +92,7 @@ int get_value_external(const DC_ITEM *item, AGENT_RESULT *result) out: zbx_free(cmd); - free_request(&request); + zbx_free_agent_request(&request); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); diff --git a/src/zabbix_server/poller/checks_internal.c b/src/zabbix_server/poller/checks_internal.c index 833b49e7a79..9d1b5feeb20 100644 --- a/src/zabbix_server/poller/checks_internal.c +++ b/src/zabbix_server/poller/checks_internal.c @@ -18,7 +18,7 @@ **/ #include "checks_internal.h" -#include "zbxserver.h" +#include "zbxstats.h" #include "checks_java.h" #include "zbxself.h" @@ -173,21 +173,23 @@ static int zbx_host_interfaces_discovery(zbx_uint64_t hostid, struct zbx_json *j * * * Purpose: retrieve data from Zabbix server (internally supported items) * * * - * Parameters: item - item we are interested in * + * Parameters: item - [IN] item we are interested in * + * result - [OUT] value of the requested item * + * zbx_config - [IN] Zabbix server/proxy config * * * * Return value: SUCCEED - data successfully retrieved and stored in result * * NOTSUPPORTED - requested item is not supported * * * ******************************************************************************/ -int get_value_internal(const DC_ITEM *item, AGENT_RESULT *result) +int get_value_internal(const DC_ITEM *item, AGENT_RESULT *result, const zbx_config_comms_args_t *zbx_config) { AGENT_REQUEST request; int ret = NOTSUPPORTED, nparams; const char *tmp, *tmp1; - init_request(&request); + zbx_init_agent_request(&request); - if (SUCCEED != parse_item_key(item->key, &request)) + if (SUCCEED != zbx_parse_item_key(item->key, &request)) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid item key format.")); goto out; @@ -463,7 +465,6 @@ int get_value_internal(const DC_ITEM *item, AGENT_RESULT *result) process_type = ZBX_PROCESS_TYPE_UNKNOWN; break; case ZBX_PROCESS_TYPE_DATASENDER: - case ZBX_PROCESS_TYPE_HEARTBEAT: if (0 == (program_type & ZBX_PROGRAM_TYPE_PROXY)) process_type = ZBX_PROCESS_TYPE_UNKNOWN; break; @@ -532,7 +533,7 @@ int get_value_internal(const DC_ITEM *item, AGENT_RESULT *result) goto out; } - get_selfmon_stats(process_type, aggr_func, process_num, state, &value); + zbx_get_selfmon_stats(process_type, aggr_func, process_num, state, &value); SET_DBL_RESULT(result, value); } @@ -764,11 +765,11 @@ int get_value_internal(const DC_ITEM *item, AGENT_RESULT *result) /* work for both data received from internal and external source. */ zbx_json_addobject(&json, ZBX_PROTO_TAG_DATA); - zbx_get_zabbix_stats(&json); + zbx_zabbix_stats_get(&json, zbx_config); zbx_json_close(&json); - set_result_type(result, ITEM_VALUE_TYPE_TEXT, json.buffer); + zbx_set_agent_result_type(result, ITEM_VALUE_TYPE_TEXT, json.buffer); zbx_json_free(&json); } @@ -814,7 +815,7 @@ int get_value_internal(const DC_ITEM *item, AGENT_RESULT *result) zbx_json_adduint64(&json, ZBX_PROTO_VALUE_ZABBIX_STATS_QUEUE, DCget_item_queue(NULL, from, to)); - set_result_type(result, ITEM_VALUE_TYPE_TEXT, json.buffer); + zbx_set_agent_result_type(result, ITEM_VALUE_TYPE_TEXT, json.buffer); zbx_json_free(&json); } @@ -929,7 +930,7 @@ out: if (NOTSUPPORTED == ret && !ZBX_ISSET_MSG(result)) SET_MSG_RESULT(result, zbx_strdup(NULL, "Internal check is not supported.")); - free_request(&request); + zbx_free_agent_request(&request); return ret; } diff --git a/src/zabbix_server/poller/checks_internal.h b/src/zabbix_server/poller/checks_internal.h index b9a84b058af..b381f8c4ee3 100644 --- a/src/zabbix_server/poller/checks_internal.h +++ b/src/zabbix_server/poller/checks_internal.h @@ -21,10 +21,11 @@ #define ZABBIX_CHECKS_INTERNAL_H #include "dbcache.h" +#include "zbxcomms.h" extern int CONFIG_SERVER_STARTUP_TIME; -int get_value_internal(const DC_ITEM *item, AGENT_RESULT *result); +int get_value_internal(const DC_ITEM *item, AGENT_RESULT *result, const zbx_config_comms_args_t *zbx_config); int zbx_get_value_internal_ext(const char *param1, const AGENT_REQUEST *request, AGENT_RESULT *result); diff --git a/src/zabbix_server/poller/checks_internal_server.c b/src/zabbix_server/poller/checks_internal_server.c index f5abdfcd63f..7dd548db690 100644 --- a/src/zabbix_server/poller/checks_internal_server.c +++ b/src/zabbix_server/poller/checks_internal_server.c @@ -22,6 +22,8 @@ #include "zbxlld.h" #include "dbcache.h" #include "zbxha.h" +#include "zbxjson.h" +#include "zbxtime.h" #include "checks_internal.h" @@ -59,48 +61,75 @@ int zbx_get_value_internal_ext(const char *param1, const AGENT_REQUEST *request, SET_UI64_RESULT(result, DCget_trigger_count()); } else if (0 == strcmp(param1, "proxy")) /* zabbix["proxy",<hostname>,"lastaccess" OR "delay"] */ - { + { /* zabbix["proxy","discovery"] */ int value, res; char *error = NULL; /* this item is always processed by server */ - if (3 != nparams) + if (2 > nparams || 3 < nparams) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters.")); goto out; } - param2 = get_rparam(request, 2); - - if (0 == strcmp(param2, "lastaccess")) + if (2 == nparams) { - res = DCget_proxy_lastaccess_by_name(get_rparam(request, 1), &value, &error); - } - else if (0 == strcmp(param2, "delay")) - { - int lastaccess; + param2 = get_rparam(request, 1); + + if (0 == strcmp(param2, "discovery")) + { + char *data; + + if (SUCCEED == (res = zbx_proxy_discovery_get(&data, &error))) + SET_STR_RESULT(result, data); + else + SET_MSG_RESULT(result, error); - if (SUCCEED == (res = DCget_proxy_delay_by_name(get_rparam(request, 1), &value, &error)) && - SUCCEED == (res = DCget_proxy_lastaccess_by_name(get_rparam(request, 1), - &lastaccess, &error))) + if (SUCCEED != res) + goto out; + } + else { - value += (int)time(NULL) - lastaccess; + SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter.")); + goto out; } } else { - SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter.")); - goto out; - } + const char *param3 = get_rparam(request, 2); - if (SUCCEED != res) - { - SET_MSG_RESULT(result, error); - goto out; - } + if (0 == strcmp(param3, "lastaccess")) + { + res = DCget_proxy_lastaccess_by_name(get_rparam(request, 1), &value, &error); + } + else if (0 == strcmp(param3, "delay")) + { + int lastaccess; - SET_UI64_RESULT(result, value); + param2 = get_rparam(request, 1); + + if (SUCCEED == (res = DCget_proxy_delay_by_name(param2, &value, &error)) && + SUCCEED == (res = DCget_proxy_lastaccess_by_name(param2, &lastaccess, + &error))) + { + value += zbx_time() - lastaccess; + } + } + else + { + SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter.")); + goto out; + } + + if (SUCCEED != res) + { + SET_MSG_RESULT(result, error); + goto out; + } + + SET_UI64_RESULT(result, value); + } } else if (0 == strcmp(param1, "vcache")) { diff --git a/src/zabbix_server/poller/checks_java.c b/src/zabbix_server/poller/checks_java.c index eaf1a453a94..deb84ada900 100644 --- a/src/zabbix_server/poller/checks_java.c +++ b/src/zabbix_server/poller/checks_java.c @@ -70,7 +70,7 @@ static int parse_response(AGENT_RESULT *results, int *errcodes, int num, char *r if (SUCCEED == zbx_json_value_by_name_dyn(&jp_row, ZBX_PROTO_TAG_VALUE, &value, &value_alloc, NULL)) { - set_result_type(&results[i], ITEM_VALUE_TYPE_TEXT, value); + zbx_set_agent_result_type(&results[i], ITEM_VALUE_TYPE_TEXT, value); errcodes[i] = SUCCEED; } else if (SUCCEED == zbx_json_value_by_name_dyn(&jp_row, ZBX_PROTO_TAG_ERROR, &value, diff --git a/src/zabbix_server/poller/checks_simple.c b/src/zabbix_server/poller/checks_simple.c index d0eeb30a464..10ea6280a43 100644 --- a/src/zabbix_server/poller/checks_simple.c +++ b/src/zabbix_server/poller/checks_simple.c @@ -205,9 +205,9 @@ int get_value_simple(const DC_ITEM *item, AGENT_RESULT *result, zbx_vector_ptr_t zabbix_log(LOG_LEVEL_DEBUG, "In %s() key_orig:'%s' addr:'%s'", __func__, item->key_orig, item->interface.addr); - init_request(&request); + zbx_init_agent_request(&request); - if (SUCCEED != parse_item_key(item->key, &request)) + if (SUCCEED != zbx_parse_item_key(item->key, &request)) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid item key format.")); goto out; @@ -254,7 +254,7 @@ int get_value_simple(const DC_ITEM *item, AGENT_RESULT *result, zbx_vector_ptr_t else { /* it will execute item from a loadable module if any */ - if (SUCCEED == process(item->key, ZBX_PROCESS_MODULE_COMMAND, result)) + if (SUCCEED == zbx_execute_agent_check(item->key, ZBX_PROCESS_MODULE_COMMAND, result)) ret = SUCCEED; } @@ -262,7 +262,7 @@ int get_value_simple(const DC_ITEM *item, AGENT_RESULT *result, zbx_vector_ptr_t SET_MSG_RESULT(result, zbx_strdup(NULL, "Simple check is not supported.")); out: - free_request(&request); + zbx_free_agent_request(&request); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); diff --git a/src/zabbix_server/poller/checks_simple_vmware.c b/src/zabbix_server/poller/checks_simple_vmware.c index 7af91418100..03eb3548802 100644 --- a/src/zabbix_server/poller/checks_simple_vmware.c +++ b/src/zabbix_server/poller/checks_simple_vmware.c @@ -1012,11 +1012,11 @@ static void vmware_get_events(const zbx_vector_ptr_t *events, zbx_uint64_t event continue; add_result = (AGENT_RESULT *)zbx_malloc(add_result, sizeof(AGENT_RESULT)); - init_result(add_result); + zbx_init_agent_result(add_result); - if (SUCCEED == set_result_type(add_result, item->value_type, event->message)) + if (SUCCEED == zbx_set_agent_result_type(add_result, item->value_type, event->message)) { - set_result_meta(add_result, event->key, 0); + zbx_set_agent_result_meta(add_result, event->key, 0); if (ITEM_VALUE_TYPE_LOG == item->value_type) { diff --git a/src/zabbix_server/poller/checks_snmp.c b/src/zabbix_server/poller/checks_snmp.c index 319dc472de0..c9691969525 100644 --- a/src/zabbix_server/poller/checks_snmp.c +++ b/src/zabbix_server/poller/checks_snmp.c @@ -355,6 +355,14 @@ end: static int zbx_snmpv3_set_auth_protocol(const DC_ITEM *item, struct snmp_session *session) { +/* item snmpv3 authentication protocol */ +/* SYNC WITH PHP! */ +#define ITEM_SNMPV3_AUTHPROTOCOL_MD5 0 +#define ITEM_SNMPV3_AUTHPROTOCOL_SHA1 1 +#define ITEM_SNMPV3_AUTHPROTOCOL_SHA224 2 +#define ITEM_SNMPV3_AUTHPROTOCOL_SHA256 3 +#define ITEM_SNMPV3_AUTHPROTOCOL_SHA384 4 +#define ITEM_SNMPV3_AUTHPROTOCOL_SHA512 5 int ret = SUCCEED; switch (item->snmpv3_authprotocol) @@ -390,6 +398,12 @@ static int zbx_snmpv3_set_auth_protocol(const DC_ITEM *item, struct snmp_session } return ret; +#undef ITEM_SNMPV3_AUTHPROTOCOL_MD5 +#undef ITEM_SNMPV3_AUTHPROTOCOL_SHA1 +#undef ITEM_SNMPV3_AUTHPROTOCOL_SHA224 +#undef ITEM_SNMPV3_AUTHPROTOCOL_SHA256 +#undef ITEM_SNMPV3_AUTHPROTOCOL_SHA384 +#undef ITEM_SNMPV3_AUTHPROTOCOL_SHA512 } static char *zbx_get_snmp_type_error(u_char type) @@ -451,6 +465,14 @@ static int zbx_get_snmp_response_error(const struct snmp_session *ss, const DC_I static struct snmp_session *zbx_snmp_open_session(const DC_ITEM *item, char *error, size_t max_error_len) { +/* item snmpv3 privacy protocol */ +/* SYNC WITH PHP! */ +#define ITEM_SNMPV3_PRIVPROTOCOL_DES 0 +#define ITEM_SNMPV3_PRIVPROTOCOL_AES128 1 +#define ITEM_SNMPV3_PRIVPROTOCOL_AES192 2 +#define ITEM_SNMPV3_PRIVPROTOCOL_AES256 3 +#define ITEM_SNMPV3_PRIVPROTOCOL_AES192C 4 +#define ITEM_SNMPV3_PRIVPROTOCOL_AES256C 5 struct snmp_session session, *ss = NULL; char addr[128]; #ifdef HAVE_IPV6 @@ -531,10 +553,10 @@ static struct snmp_session *zbx_snmp_open_session(const DC_ITEM *item, char *err /* set the security level to authenticated, but not encrypted */ switch (item->snmpv3_securitylevel) { - case ITEM_SNMPV3_SECURITYLEVEL_NOAUTHNOPRIV: + case ZBX_ITEM_SNMPV3_SECURITYLEVEL_NOAUTHNOPRIV: session.securityLevel = SNMP_SEC_LEVEL_NOAUTH; break; - case ITEM_SNMPV3_SECURITYLEVEL_AUTHNOPRIV: + case ZBX_ITEM_SNMPV3_SECURITYLEVEL_AUTHNOPRIV: session.securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV; if (FAIL == zbx_snmpv3_set_auth_protocol(item, &session)) @@ -556,7 +578,7 @@ static struct snmp_session *zbx_snmp_open_session(const DC_ITEM *item, char *err goto end; } break; - case ITEM_SNMPV3_SECURITYLEVEL_AUTHPRIV: + case ZBX_ITEM_SNMPV3_SECURITYLEVEL_AUTHPRIV: session.securityLevel = SNMP_SEC_LEVEL_AUTHPRIV; if (FAIL == zbx_snmpv3_set_auth_protocol(item, &session)) @@ -664,6 +686,12 @@ end: zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); return ss; +#undef ITEM_SNMPV3_PRIVPROTOCOL_DES +#undef ITEM_SNMPV3_PRIVPROTOCOL_AES128 +#undef ITEM_SNMPV3_PRIVPROTOCOL_AES192 +#undef ITEM_SNMPV3_PRIVPROTOCOL_AES256 +#undef ITEM_SNMPV3_PRIVPROTOCOL_AES192C +#undef ITEM_SNMPV3_PRIVPROTOCOL_AES256C } static void zbx_snmp_close_session(struct snmp_session *session) @@ -753,7 +781,7 @@ static int zbx_snmp_set_result(const struct variable_list *var, AGENT_RESULT *re } else { - set_result_type(result, ITEM_VALUE_TYPE_TEXT, strval_dyn); + zbx_set_agent_result_type(result, ITEM_VALUE_TYPE_TEXT, strval_dyn); zbx_free(strval_dyn); } } @@ -786,7 +814,7 @@ static int zbx_snmp_set_result(const struct variable_list *var, AGENT_RESULT *re zbx_snprintf(buffer, sizeof(buffer), "%ld", *var->val.integer); - set_result_type(result, ITEM_VALUE_TYPE_TEXT, buffer); + zbx_set_agent_result_type(result, ITEM_VALUE_TYPE_TEXT, buffer); } #ifdef OPAQUE_SPECIAL_TYPES else if (ASN_OPAQUE_FLOAT == var->type) @@ -1229,7 +1257,7 @@ static int zbx_snmp_walk(struct snmp_session *ss, const DC_ITEM *item, const cha } str_res = NULL; - init_result(&snmp_result); + zbx_init_agent_result(&snmp_result); if (SUCCEED == zbx_snmp_set_result(var, &snmp_result, &val_type)) { @@ -1251,7 +1279,7 @@ static int zbx_snmp_walk(struct snmp_session *ss, const DC_ITEM *item, const cha else walk_cb_func(walk_cb_arg, snmp_oid, oid_index, snmp_result.str); - free_result(&snmp_result); + zbx_free_agent_result(&snmp_result); /* go to next variable */ memcpy((char *)anOID, (char *)var->name, var->name_length * sizeof(oid)); @@ -1680,9 +1708,9 @@ static int zbx_snmp_ddata_init(zbx_snmp_ddata_t *data, const char *key, char *er { int i, j, ret = CONFIG_ERROR; - init_request(&data->request); + zbx_init_agent_request(&data->request); - if (SUCCEED != parse_item_key(key, &data->request)) + if (SUCCEED != zbx_parse_item_key(key, &data->request)) { zbx_strlcpy(error, "Invalid SNMP OID: cannot parse expression.", max_error_len); goto out; @@ -1696,7 +1724,7 @@ static int zbx_snmp_ddata_init(zbx_snmp_ddata_t *data, const char *key, char *er for (i = 0; i < data->request.nparam; i += 2) { - if (SUCCEED != is_discovery_macro(data->request.params[i])) + if (SUCCEED != zbx_is_discovery_macro(data->request.params[i])) { zbx_snprintf(error, max_error_len, "Invalid SNMP OID: macro \"%s\" is invalid", data->request.params[i]); @@ -1728,7 +1756,7 @@ static int zbx_snmp_ddata_init(zbx_snmp_ddata_t *data, const char *key, char *er ret = SUCCEED; out: if (SUCCEED != ret) - free_request(&data->request); + zbx_free_agent_request(&data->request); return ret; } @@ -1760,7 +1788,7 @@ static void zbx_snmp_ddata_clean(zbx_snmp_ddata_t *data) zbx_hashset_destroy(&data->objects); - free_request(&data->request); + zbx_free_agent_request(&data->request); } static void zbx_snmp_walk_discovery_cb(void *arg, const char *snmp_oid, const char *index, const char *value) @@ -1953,7 +1981,7 @@ static int zbx_snmp_process_dynamic(struct snmp_session *ss, const DC_ITEM *item zbx_strlcat(oids_translated[j], to_verify_oids[j] + len, sizeof(oids_translated[j])); } - free_result(&results[j]); + zbx_free_agent_result(&results[j]); } } diff --git a/src/zabbix_server/poller/checks_ssh.c b/src/zabbix_server/poller/checks_ssh.c index 32ad5c78723..e53f9f0b414 100644 --- a/src/zabbix_server/poller/checks_ssh.c +++ b/src/zabbix_server/poller/checks_ssh.c @@ -30,9 +30,9 @@ int get_value_ssh(DC_ITEM *item, AGENT_RESULT *result) int ret = NOTSUPPORTED; const char *port, *encoding, *dns; - init_request(&request); + zbx_init_agent_request(&request); - if (SUCCEED != parse_item_key(item->key, &request)) + if (SUCCEED != zbx_parse_item_key(item->key, &request)) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid item key format.")); goto out; @@ -80,7 +80,7 @@ int get_value_ssh(DC_ITEM *item, AGENT_RESULT *result) ret = ssh_run(item, result, ZBX_NULL2EMPTY_STR(encoding)); out: - free_request(&request); + zbx_free_agent_request(&request); return ret; } diff --git a/src/zabbix_server/poller/checks_telnet.c b/src/zabbix_server/poller/checks_telnet.c index 4121d9b56d5..87279a24c55 100644 --- a/src/zabbix_server/poller/checks_telnet.c +++ b/src/zabbix_server/poller/checks_telnet.c @@ -28,9 +28,9 @@ int get_value_telnet(DC_ITEM *item, AGENT_RESULT *result) int ret = NOTSUPPORTED; const char *port, *encoding, *dns; - init_request(&request); + zbx_init_agent_request(&request); - if (SUCCEED != parse_item_key(item->key, &request)) + if (SUCCEED != zbx_parse_item_key(item->key, &request)) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid item key format.")); goto out; @@ -78,7 +78,7 @@ int get_value_telnet(DC_ITEM *item, AGENT_RESULT *result) ret = telnet_run(item, result, ZBX_NULL2EMPTY_STR(encoding)); out: - free_request(&request); + zbx_free_agent_request(&request); return ret; } diff --git a/src/zabbix_server/poller/poller.c b/src/zabbix_server/poller/poller.c index 09a7f3993c9..3feed6f1dbd 100644 --- a/src/zabbix_server/poller/poller.c +++ b/src/zabbix_server/poller/poller.c @@ -279,13 +279,14 @@ out: zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); } -void zbx_free_result_ptr(AGENT_RESULT *result) +void zbx_free_agent_result_ptr(AGENT_RESULT *result) { - free_result(result); + zbx_free_agent_result(result); zbx_free(result); } -static int get_value(DC_ITEM *item, AGENT_RESULT *result, zbx_vector_ptr_t *add_results) +static int get_value(DC_ITEM *item, AGENT_RESULT *result, zbx_vector_ptr_t *add_results, + const zbx_config_comms_args_t *zbx_config) { int res = FAIL; @@ -303,7 +304,7 @@ static int get_value(DC_ITEM *item, AGENT_RESULT *result, zbx_vector_ptr_t *add_ res = get_value_simple(item, result, add_results); break; case ITEM_TYPE_INTERNAL: - res = get_value_internal(item, result); + res = get_value_internal(item, result, zbx_config); break; case ITEM_TYPE_DB_MONITOR: #ifdef HAVE_UNIXODBC @@ -446,7 +447,7 @@ void zbx_prepare_items(DC_ITEM *items, int *errcodes, int num, AGENT_RESULT *res for (i = 0; i < num; i++) { - init_result(&results[i]); + zbx_init_agent_result(&results[i]); errcodes[i] = SUCCEED; if (MACRO_EXPAND_YES == expand_macros) @@ -697,7 +698,7 @@ void zbx_prepare_items(DC_ITEM *items, int *errcodes, int num, AGENT_RESULT *res } void zbx_check_items(DC_ITEM *items, int *errcodes, int num, AGENT_RESULT *results, zbx_vector_ptr_t *add_results, - unsigned char poller_type) + unsigned char poller_type, const zbx_config_comms_args_t *zbx_config) { if (ITEM_TYPE_SNMP == items[0].type) { @@ -728,7 +729,7 @@ void zbx_check_items(DC_ITEM *items, int *errcodes, int num, AGENT_RESULT *resul else if (1 == num) { if (SUCCEED == errcodes[0]) - errcodes[0] = get_value(&items[0], &results[0], add_results); + errcodes[0] = get_value(&items[0], &results[0], add_results, zbx_config); } else THIS_SHOULD_NEVER_HAPPEN; @@ -788,7 +789,7 @@ void zbx_clean_items(DC_ITEM *items, int num, AGENT_RESULT *results) break; } - free_result(&results[i]); + zbx_free_agent_result(&results[i]); } } @@ -798,6 +799,7 @@ void zbx_clean_items(DC_ITEM *items, int num, AGENT_RESULT *results) * * * Parameters: poller_type - [IN] poller type (ZBX_POLLER_TYPE_...) * * nextcheck - [OUT] item nextcheck * + * zbx_config - [IN] server/proxy config * * * * Return value: number of items processed * * * @@ -805,7 +807,7 @@ void zbx_clean_items(DC_ITEM *items, int num, AGENT_RESULT *results) * see DCconfig_get_poller_items() * * * ******************************************************************************/ -static int get_values(unsigned char poller_type, int *nextcheck) +static int get_values(unsigned char poller_type, int *nextcheck, const zbx_config_comms_args_t *zbx_config) { DC_ITEM item, *items; AGENT_RESULT results[MAX_POLLER_ITEMS]; @@ -830,7 +832,7 @@ static int get_values(unsigned char poller_type, int *nextcheck) zbx_vector_ptr_create(&add_results); zbx_prepare_items(items, errcodes, num, results, MACRO_EXPAND_YES); - zbx_check_items(items, errcodes, num, results, &add_results, poller_type); + zbx_check_items(items, errcodes, num, results, &add_results, poller_type, zbx_config); zbx_timespec(×pec); @@ -927,7 +929,7 @@ static int get_values(unsigned char poller_type, int *nextcheck) zbx_preprocessor_flush(); zbx_clean_items(items, num, results); DCconfig_clean_items(items, NULL, num); - zbx_vector_ptr_clear_ext(&add_results, (zbx_mem_free_func_t)zbx_free_result_ptr); + zbx_vector_ptr_clear_ext(&add_results, (zbx_mem_free_func_t)zbx_free_agent_result_ptr); zbx_vector_ptr_destroy(&add_results); if (NULL != data) @@ -966,12 +968,12 @@ ZBX_THREAD_ENTRY(poller_thread, args) get_program_type_string(poller_args_in->zbx_get_program_type_cb_arg()), server_num, get_process_type_string(process_type), process_num); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); scriptitem_es_engine_init(); #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) - zbx_tls_init_child(poller_args_in->zbx_config_tls, poller_args_in->zbx_get_program_type_cb_arg); + zbx_tls_init_child(poller_args_in->zbx_config->zbx_config_tls, poller_args_in->zbx_get_program_type_cb_arg); #endif if (ZBX_POLLER_TYPE_HISTORY == poller_type) { @@ -999,7 +1001,7 @@ ZBX_THREAD_ENTRY(poller_thread, args) old_total_sec); } - processed += get_values(poller_type, &nextcheck); + processed += get_values(poller_type, &nextcheck, poller_args_in->zbx_config); total_sec += zbx_time() - sec; sleeptime = zbx_calculate_sleeptime(nextcheck, POLLER_DELAY); diff --git a/src/zabbix_server/poller/poller.h b/src/zabbix_server/poller/poller.h index bacc7afeae6..3d71f519bc9 100644 --- a/src/zabbix_server/poller/poller.h +++ b/src/zabbix_server/poller/poller.h @@ -22,10 +22,11 @@ #include "zbxthreads.h" #include "dbcache.h" +#include "zbxcomms.h" typedef struct { - zbx_config_tls_t *zbx_config_tls; + zbx_config_comms_args_t *zbx_config; zbx_get_program_type_f zbx_get_program_type_cb_arg; unsigned char poller_type; } @@ -44,8 +45,8 @@ void zbx_deactivate_item_interface(zbx_timespec_t *ts, DC_ITEM *item, unsigned size_t *data_offset, const char *error); void zbx_prepare_items(DC_ITEM *items, int *errcodes, int num, AGENT_RESULT *results, unsigned char expand_macros); void zbx_check_items(DC_ITEM *items, int *errcodes, int num, AGENT_RESULT *results, zbx_vector_ptr_t *add_results, - unsigned char poller_type); + unsigned char poller_type, const zbx_config_comms_args_t *zbx_config); void zbx_clean_items(DC_ITEM *items, int num, AGENT_RESULT *results); -void zbx_free_result_ptr(AGENT_RESULT *result); +void zbx_free_agent_result_ptr(AGENT_RESULT *result); #endif diff --git a/src/zabbix_server/postinit.c b/src/zabbix_server/postinit.c index 54779694589..c18a917214f 100644 --- a/src/zabbix_server/postinit.c +++ b/src/zabbix_server/postinit.c @@ -24,6 +24,7 @@ #include "zbxtasks.h" #include "log.h" #include "zbxnum.h" +#include "valuecache.h" #define ZBX_HIST_MACRO_NONE (-1) #define ZBX_HIST_MACRO_ITEM_VALUE 0 @@ -442,6 +443,9 @@ int zbx_check_postinit_tasks(char **error) DB_ROW row; int ret = SUCCEED; + /* avoid filling value cache with unnecessary data during event name update */ + zbx_vc_disable(); + result = DBselect("select taskid from task where type=%d and status=%d", ZBX_TM_TASK_UPDATE_EVENTNAMES, ZBX_TM_STATUS_NEW); @@ -463,5 +467,7 @@ int zbx_check_postinit_tasks(char **error) if (SUCCEED != ret) *error = zbx_strdup(*error, "cannot update event names"); + zbx_vc_enable(); + return ret; } diff --git a/src/zabbix_server/preprocessor/preproc_manager.c b/src/zabbix_server/preprocessor/preproc_manager.c index 262e79a41e8..fe77732b603 100644 --- a/src/zabbix_server/preprocessor/preproc_manager.c +++ b/src/zabbix_server/preprocessor/preproc_manager.c @@ -136,7 +136,7 @@ typedef struct zbx_hashset_t item_config; /* item configuration L2 cache */ zbx_hashset_t history_cache; /* item value history cache */ zbx_hashset_t linked_items; /* linked items placed in queue */ - int cache_ts; /* cache timestamp */ + zbx_uint64_t revision; /* the configuration revision */ zbx_uint64_t processed_num; /* processed value counter */ zbx_uint64_t queued_num; /* queued value counter */ zbx_uint64_t preproc_num; /* queued values with preprocessing steps */ @@ -192,16 +192,16 @@ static void request_free_steps(zbx_preprocessing_request_t *request) static void preprocessor_sync_configuration(zbx_preprocessing_manager_t *manager) { zbx_hashset_iter_t iter; - int ts; + zbx_uint64_t old_revision; zbx_preproc_history_t *vault; zbx_preproc_item_t *item; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); - ts = manager->cache_ts; - DCconfig_get_preprocessable_items(&manager->item_config, &manager->cache_ts); + old_revision = manager->revision; + DCconfig_get_preprocessable_items(&manager->item_config, &manager->revision); - if (ts != manager->cache_ts) + if (old_revision != manager->revision) { /* drop items with removed preprocessing steps from preprocessing history cache */ zbx_hashset_iter_reset(&manager->history_cache, &iter); @@ -219,11 +219,9 @@ static void preprocessor_sync_configuration(zbx_preprocessing_manager_t *manager zbx_hashset_iter_reset(&manager->item_config, &iter); while (NULL != (item = (zbx_preproc_item_t *)zbx_hashset_iter_next(&iter))) { - if (ts >= item->update_time && ZBX_PREPROC_MACRO_UPDATE_FALSE == item->macro_update) + if (item->preproc_revision < manager->revision) continue; - item->macro_update = ZBX_PREPROC_MACRO_UPDATE_FALSE; - if (NULL == (vault = (zbx_preproc_history_t *)zbx_hashset_search(&manager->history_cache, &item->itemid))) { @@ -641,7 +639,7 @@ static void preproc_item_value_clear(zbx_preproc_item_value_t *value) if (NULL != value->result) { - free_result(value->result); + zbx_free_agent_result(value->result); zbx_free(value->result); } } @@ -1173,7 +1171,7 @@ static int preprocessor_set_variant_result(zbx_preprocessing_request_t *request, if (ZBX_VARIANT_NONE == value->type) { if (NULL != request->value.result) - free_result(request->value.result); + zbx_free_agent_result(request->value.result); zbx_free(request->value.error); @@ -1203,13 +1201,13 @@ static int preprocessor_set_variant_result(zbx_preprocessing_request_t *request, if (NULL == request->value.result) { request->value.result = (AGENT_RESULT *)zbx_malloc(NULL, sizeof(AGENT_RESULT)); - init_result(request->value.result); + zbx_init_agent_result(request->value.result); } else { /* preserve eventlog related information */ if (ITEM_VALUE_TYPE_LOG != request->value_type) - free_result(request->value.result); + zbx_free_agent_result(request->value.result); } if (ITEM_STATE_NOTSUPPORTED == request->value.state) @@ -1974,7 +1972,7 @@ ZBX_THREAD_ENTRY(preprocessing_manager_thread, args) zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(program_type), server_num, get_process_type_string(process_type), process_num); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); if (FAIL == zbx_ipc_service_start(&service, ZBX_IPC_SERVICE_PREPROCESSING, &error)) { @@ -2007,9 +2005,9 @@ ZBX_THREAD_ENTRY(preprocessing_manager_thread, args) manager.processed_num = 0; } - update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); ret = zbx_ipc_service_recv(&service, &timeout, &client, &message); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); sec = zbx_time(); zbx_update_env(sec); diff --git a/src/zabbix_server/preprocessor/preproc_worker.c b/src/zabbix_server/preprocessor/preproc_worker.c index 983bf0ce25a..c33a85c509e 100644 --- a/src/zabbix_server/preprocessor/preproc_worker.c +++ b/src/zabbix_server/preprocessor/preproc_worker.c @@ -607,7 +607,7 @@ ZBX_THREAD_ENTRY(preprocessing_worker_thread, args) zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(program_type), server_num, get_process_type_string(process_type), process_num); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); memset(&dep_request, 0, sizeof(dep_request)); zbx_variant_set_none(&dep_request.value); @@ -616,7 +616,7 @@ ZBX_THREAD_ENTRY(preprocessing_worker_thread, args) while (ZBX_IS_RUNNING()) { - update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); if (SUCCEED != zbx_ipc_socket_read(&socket, &message)) { @@ -624,7 +624,7 @@ ZBX_THREAD_ENTRY(preprocessing_worker_thread, args) exit(EXIT_FAILURE); } - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); zbx_update_env(zbx_time()); switch (message.code) diff --git a/src/zabbix_server/preprocessor/preprocessing.c b/src/zabbix_server/preprocessor/preprocessing.c index 73d028ba909..b026d83248e 100644 --- a/src/zabbix_server/preprocessor/preprocessing.c +++ b/src/zabbix_server/preprocessor/preprocessing.c @@ -683,7 +683,7 @@ void zbx_preprocessor_free_dep_results(zbx_preproc_dep_result_t *results, int re for (i = 0; i < results_num; i++) { - free_result(&results[i].value); + zbx_free_agent_result(&results[i].value); zbx_free(results[i].error); zbx_vector_ptr_clear_ext(&results[i].history, (zbx_clean_func_t)zbx_preproc_op_history_free); zbx_vector_ptr_destroy(&results[i].history); @@ -1220,7 +1220,7 @@ static void agent_result_set_value(zbx_variant_t *value, zbx_item_value_type_t v unsigned char type; zbx_log_t *log; - init_result(result); + zbx_init_agent_result(result); if (NULL != *error) return; diff --git a/src/zabbix_server/proxyconfigread/Makefile.am b/src/zabbix_server/proxyconfigread/Makefile.am new file mode 100644 index 00000000000..729575b5f3b --- /dev/null +++ b/src/zabbix_server/proxyconfigread/Makefile.am @@ -0,0 +1,9 @@ +## Process this file with automake to produce Makefile.in + +noinst_LIBRARIES = libzbxproxyconfigread.a + +libzbxproxyconfigread_a_SOURCES = \ + proxyconfig_read.c \ + proxyconfig_read.h + +libzbxproxyconfigread_a_CFLAGS = -I$(top_srcdir)/src diff --git a/src/zabbix_server/proxyconfigread/proxyconfig_read.c b/src/zabbix_server/proxyconfigread/proxyconfig_read.c new file mode 100644 index 00000000000..4948ad076e4 --- /dev/null +++ b/src/zabbix_server/proxyconfigread/proxyconfig_read.c @@ -0,0 +1,1201 @@ +/* +** Zabbix +** Copyright (C) 2001-2022 Zabbix SIA +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +**/ + +#include "proxyconfig_read.h" + +#include "proxy.h" +#include "zbxdbhigh.h" +#include "libs/zbxkvs/kvs.h" +#include "libs/zbxvault/vault.h" +#include "log.h" +#include "zbxcommshigh.h" +#include "zbxcompress.h" +#include "zbxcrypto.h" + +extern char *CONFIG_VAULTDBPATH; +extern int CONFIG_TRAPPER_TIMEOUT; + +typedef struct +{ + char *path; + zbx_hashset_t keys; +} +zbx_keys_path_t; + + +static int keys_path_compare(const void *d1, const void *d2) +{ + const zbx_keys_path_t *ptr1 = *((const zbx_keys_path_t * const *)d1); + const zbx_keys_path_t *ptr2 = *((const zbx_keys_path_t * const *)d2); + + return strcmp(ptr1->path, ptr2->path); +} + +static zbx_hash_t keys_hash(const void *data) +{ + return ZBX_DEFAULT_STRING_HASH_ALGO(*(const char * const *)data, strlen(*(const char * const *)data), + ZBX_DEFAULT_HASH_SEED); +} + +static int keys_compare(const void *d1, const void *d2) +{ + return strcmp(*(const char * const *)d1, *(const char * const *)d2); +} + +static void key_path_free(void *data) +{ + zbx_hashset_iter_t iter; + char **ptr; + zbx_keys_path_t *keys_path = (zbx_keys_path_t *)data; + + zbx_hashset_iter_reset(&keys_path->keys, &iter); + while (NULL != (ptr = (char **)zbx_hashset_iter_next(&iter))) + zbx_free(*ptr); + zbx_hashset_destroy(&keys_path->keys); + + zbx_free(keys_path->path); + zbx_free(keys_path); +} + +static void get_macro_secrets(const zbx_vector_ptr_t *keys_paths, struct zbx_json *j) +{ + int i; + zbx_kvs_t kvs; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + + zbx_kvs_create(&kvs, 100); + + zbx_json_addobject(j, ZBX_PROTO_TAG_MACRO_SECRETS); + + for (i = 0; i < keys_paths->values_num; i++) + { + zbx_keys_path_t *keys_path; + char *error = NULL, **ptr; + zbx_hashset_iter_t iter; + + keys_path = (zbx_keys_path_t *)keys_paths->values[i]; + if (FAIL == zbx_vault_kvs_get(keys_path->path, &kvs, &error)) + { + zabbix_log(LOG_LEVEL_WARNING, "cannot get secrets for path \"%s\": %s", keys_path->path, error); + zbx_free(error); + continue; + } + + zbx_json_addobject(j, keys_path->path); + + zbx_hashset_iter_reset(&keys_path->keys, &iter); + while (NULL != (ptr = (char **)zbx_hashset_iter_next(&iter))) + { + zbx_kv_t *kv, kv_local; + + kv_local.key = *ptr; + + if (NULL != (kv = zbx_kvs_search(&kvs, &kv_local))) + zbx_json_addstring(j, kv->key, kv->value, ZBX_JSON_TYPE_STRING); + } + zbx_json_close(j); + + zbx_kvs_clear(&kvs); + } + + zbx_json_close(j); + zbx_kvs_destroy(&kvs); + + zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); +} + +/****************************************************************************** + * * + * Purpose: add database row to the proxy config json data * + * * + * Parameters: j - [OUT] the output json * + * row - [IN] the database row to add * + * table - [IN] the table configuration * + * recids - [OUT] the record identifiers (optional) * + * * + ******************************************************************************/ +static void proxyconfig_add_row(struct zbx_json *j, const DB_ROW row, const ZBX_TABLE *table, + zbx_vector_uint64_t *recids) +{ + int fld = 0, i; + + zbx_json_addstring(j, NULL, row[fld++], ZBX_JSON_TYPE_INT); + + if (NULL != recids) + { + zbx_uint64_t recid; + + ZBX_STR2UINT64(recid, row[0]); + zbx_vector_uint64_append(recids, recid); + } + + for (i = 0; 0 != table->fields[i].name; i++) + { + if (0 == (table->fields[i].flags & ZBX_PROXY)) + continue; + + switch (table->fields[i].type) + { + case ZBX_TYPE_INT: + case ZBX_TYPE_UINT: + case ZBX_TYPE_ID: + if (SUCCEED != DBis_null(row[fld])) + zbx_json_addstring(j, NULL, row[fld], ZBX_JSON_TYPE_INT); + else + zbx_json_addstring(j, NULL, NULL, ZBX_JSON_TYPE_NULL); + break; + default: + zbx_json_addstring(j, NULL, row[fld], ZBX_JSON_TYPE_STRING); + break; + } + fld++; + } +} + +/****************************************************************************** + * * + * Purpose: get table fields, add them to output json and sql select * + * * + * Parameters: sql - [IN/OUT] the sql select string * + * sql_alloc - [IN/OUT] * + * sql_offset - [IN/OUT] * + * table - [IN] the table * + * j - [OUT] the output json * + * * + ******************************************************************************/ +static void proxyconfig_get_fields(char **sql, size_t *sql_alloc, size_t *sql_offset, const ZBX_TABLE *table, + struct zbx_json *j) +{ + int i; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + + zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "select %s", table->recid); + + zbx_json_addarray(j, "fields"); + zbx_json_addstring(j, NULL, table->recid, ZBX_JSON_TYPE_STRING); + + for (i = 0; 0 != table->fields[i].name; i++) + { + if (0 == (table->fields[i].flags & ZBX_PROXY)) + continue; + + zbx_chrcpy_alloc(sql, sql_alloc, sql_offset, ','); + zbx_strcpy_alloc(sql, sql_alloc, sql_offset, table->fields[i].name); + + zbx_json_addstring(j, NULL, table->fields[i].name, ZBX_JSON_TYPE_STRING); + } + + zbx_json_close(j); + + zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); +} + +/****************************************************************************** + * * + * Purpose: get global/host macro data of the specified hosts from database * + * * + * Parameters: table_name - [IN] table name - globalmacro/hostmacro * + * hostids - [IN] the target hostids for hostmacro table and * + * NULL for globalmacro table * + * keys_paths - [OUT] the vault macro path/key * + * j - [OUT] the output json * + * error - [OUT] the error message * + * * + * Return value: SUCCEED - the data was read successfully * + * FAIL - otherwise * + * * + ******************************************************************************/ +static int proxyconfig_get_macro_updates(const char *table_name, const zbx_vector_uint64_t *hostids, + zbx_vector_ptr_t *keys_paths, struct zbx_json *j, char **error) +{ + DB_RESULT result; + DB_ROW row; + const ZBX_TABLE *table; + char *sql; + size_t sql_alloc = 4 * ZBX_KIBIBYTE, sql_offset = 0; + int i, ret = FAIL, offset; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + + table = DBget_table(table_name); + zbx_json_addobject(j, table->table); + + sql = (char *)zbx_malloc(NULL, sql_alloc); + + proxyconfig_get_fields(&sql, &sql_alloc, &sql_offset, table, j); + zbx_json_addarray(j, "data"); + + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " from %s", table->table); + + if (NULL != hostids) + { + /* no hosts to get macros from, send empty data */ + if (0 == hostids->values_num) + goto end; + + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " where"); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid", hostids->values, hostids->values_num); + offset = 1; + } + else + offset = 0; + + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " order by "); + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, table->recid); + + if (NULL == (result = DBselect("%s", sql))) + { + *error = zbx_dsprintf(*error, "failed to get data from table \"%s\"", table->table); + goto out; + } + + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " from %s", table->table); + + while (NULL != (row = DBfetch(result))) + { + zbx_keys_path_t *keys_path, keys_path_local; + unsigned char type; + char *path, *key; + + zbx_json_addarray(j, NULL); + proxyconfig_add_row(j, row, table, NULL); + zbx_json_close(j); + + ZBX_STR2UCHAR(type, row[3 + offset]); + + if (ZBX_MACRO_VALUE_VAULT != type) + continue; + + zbx_strsplit_last(row[2 + offset], ':', &path, &key); + + if (NULL == key) + { + zabbix_log(LOG_LEVEL_WARNING, "cannot parse macro \"%s\" value \"%s\"", + row[1 + offset], row[2 + offset]); + goto next; + } + + if (NULL != CONFIG_VAULTDBPATH && 0 == strcasecmp(CONFIG_VAULTDBPATH, path) && + (0 == strcasecmp(key, ZBX_PROTO_TAG_PASSWORD) + || 0 == strcasecmp(key, ZBX_PROTO_TAG_USERNAME))) + { + zabbix_log(LOG_LEVEL_WARNING, "cannot parse macro \"%s\" value \"%s\":" + " database credentials should not be used with Vault macros", + row[1 + offset], row[2 + offset]); + goto next; + } + + keys_path_local.path = path; + + if (FAIL == (i = zbx_vector_ptr_search(keys_paths, &keys_path_local, keys_path_compare))) + { + keys_path = zbx_malloc(NULL, sizeof(zbx_keys_path_t)); + keys_path->path = path; + + zbx_hashset_create(&keys_path->keys, 0, keys_hash, keys_compare); + zbx_hashset_insert(&keys_path->keys, &key, sizeof(char *)); + + zbx_vector_ptr_append(keys_paths, keys_path); + path = key = NULL; + } + else + { + keys_path = (zbx_keys_path_t *)keys_paths->values[i]; + if (NULL == zbx_hashset_search(&keys_path->keys, &key)) + { + zbx_hashset_insert(&keys_path->keys, &key, sizeof(char **)); + key = NULL; + } + } +next: + zbx_free(key); + zbx_free(path); + } + DBfree_result(result); +end: + zbx_json_close(j); + zbx_json_close(j); + + ret = SUCCEED; +out: + zbx_free(sql); + + zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); + + return ret; +} + +/****************************************************************************** + * * + * Purpose: get table data from database * + * * + * Parameters: table_name - [IN] table name - * + * key_name - [IN] the key field name used to select rows * + * (all rows selected when NULL) * + * key_ids - [IN] the key values used to select rows (optional)* + * filter - [IN] custom filter to apply when selecting rows * + * (optional) * + * recids - [OUT] the selected record identifiers, sorted * + * (optional) * + * j - [OUT] the output json * + * error - [OUT] the error message * + * * + * Return value: SUCCEED - the data was read successfully * + * FAIL - otherwise * + * * + ******************************************************************************/ +static int proxyconfig_get_table_data(const char *table_name, const char *key_name, + const zbx_vector_uint64_t *key_ids, const char *filter, zbx_vector_uint64_t *recids, struct zbx_json *j, + char **error) +{ + DB_RESULT result; + DB_ROW row; + const ZBX_TABLE *table; + char *sql = NULL; + size_t sql_alloc = 4 * ZBX_KIBIBYTE, sql_offset = 0; + int ret = FAIL; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + + table = DBget_table(table_name); + zbx_json_addobject(j, table->table); + + sql = (char *)zbx_malloc(NULL, sql_alloc); + proxyconfig_get_fields(&sql, &sql_alloc, &sql_offset, table, j); + + zbx_json_addarray(j, ZBX_PROTO_TAG_DATA); + + if (NULL == key_ids || 0 != key_ids->values_num) + { + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " from %s", table->table); + + if (NULL != key_ids || NULL != filter) + { + const char *keyword = " where"; + + if (NULL != key_ids) + { + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, keyword); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, key_name, key_ids->values, + key_ids->values_num); + keyword = " and"; + } + + if (NULL != filter) + { + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, keyword); + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, filter); + } + } + + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " order by "); + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, table->recid); + + if (NULL == (result = DBselect("%s", sql))) + { + *error = zbx_dsprintf(*error, "failed to get data from table \"%s\"", table->table); + goto out; + } + + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " from %s", table->table); + + while (NULL != (row = DBfetch(result))) + { + zbx_json_addarray(j, NULL); + proxyconfig_add_row(j, row, table, recids); + zbx_json_close(j); + } + DBfree_result(result); + } + + zbx_json_close(j); + zbx_json_close(j); + + if (NULL != recids) + zbx_vector_uint64_sort(recids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); + + ret = SUCCEED; +out: + zbx_free(sql); + + zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); + + return ret; +} + +typedef struct +{ + zbx_uint64_t itemid; + zbx_uint64_t master_itemid; + DB_ROW row; + int cols_num; +} +zbx_proxyconfig_dep_item_t; + +ZBX_PTR_VECTOR_DECL(proxyconfig_dep_item_ptr, zbx_proxyconfig_dep_item_t *) +ZBX_PTR_VECTOR_IMPL(proxyconfig_dep_item_ptr, zbx_proxyconfig_dep_item_t *) + +static void proxyconfig_dep_item_free(zbx_proxyconfig_dep_item_t *item) +{ + int i; + + for (i = 0; i < item->cols_num; i++) + zbx_free(item->row[i]); + + zbx_free(item->row); + zbx_free(item); +} + +static zbx_proxyconfig_dep_item_t *proxyconfig_dep_item_create(zbx_uint64_t itemid, zbx_uint64_t master_itemid, + const DB_ROW row, int cols_num) +{ + zbx_proxyconfig_dep_item_t *item; + int i; + + item = (zbx_proxyconfig_dep_item_t *)zbx_malloc(NULL, sizeof(zbx_proxyconfig_dep_item_t)); + item->itemid = itemid; + item->master_itemid = master_itemid; + item->cols_num = cols_num; + item->row = (DB_ROW)zbx_malloc(NULL, sizeof(char *) * (size_t)cols_num); + + for (i = 0; i < cols_num; i++) + { + if (NULL == row[i]) + item->row[i] = NULL; + else + item->row[i] = zbx_strdup(NULL, row[i]); + } + + return item; +} + +/****************************************************************************** + * * + * Purpose: get item data from items table * + * * + * Parameters: hostids - [IN] the target host identifiers * + * itemids - [IN] the selected item identifiers, sorted * + * j - [OUT] the output json * + * error - [OUT] the error message * + * * + * Return value: SUCCEED - the data was read successfully * + * FAIL - otherwise * + * * + ******************************************************************************/ +static int proxyconfig_get_item_data(const zbx_vector_uint64_t *hostids, zbx_vector_uint64_t *itemids, + struct zbx_json *j, char **error) +{ + DB_RESULT result; + DB_ROW row; + const ZBX_TABLE *table; + char *sql; + size_t sql_alloc = 4 * ZBX_KIBIBYTE, sql_offset = 0; + int ret = FAIL, fld_key = -1, fld_type = -1, fld_master_itemid = -1, i, fld, dep_items_num; + zbx_uint64_t itemid, master_itemid; + + zbx_vector_proxyconfig_dep_item_ptr_t dep_items; + zbx_hashset_t items; + zbx_proxyconfig_dep_item_t *dep_item; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + + zbx_hashset_create(&items, 1000, ZBX_DEFAULT_UINT64_HASH_FUNC, ZBX_DEFAULT_UINT64_COMPARE_FUNC); + zbx_vector_proxyconfig_dep_item_ptr_create(&dep_items); + + table = DBget_table("items"); + + /* get type, key_ field indexes used to check if item is processed by server */ + for (i = 0, fld = 1; 0 != table->fields[i].name; i++) + { + if (0 == (table->fields[i].flags & ZBX_PROXY)) + continue; + + if (0 == strcmp(table->fields[i].name, "type")) + fld_type = fld; + else if (0 == strcmp(table->fields[i].name, "key_")) + fld_key = fld; + else if (0 == strcmp(table->fields[i].name, "master_itemid")) + fld_master_itemid = fld; + fld++; + } + + if (-1 == fld_type || -1 == fld_key || -1 == fld_master_itemid) + { + THIS_SHOULD_NEVER_HAPPEN; + exit(EXIT_FAILURE); + } + + zbx_json_addobject(j, table->table); + + sql = (char *)zbx_malloc(NULL, sql_alloc); + proxyconfig_get_fields(&sql, &sql_alloc, &sql_offset, table, j); + + zbx_json_addarray(j, ZBX_PROTO_TAG_DATA); + + if (0 != hostids->values_num) + { + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " from %s where", table->table); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid", hostids->values, hostids->values_num); + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " and flags<>%d and type<>%d", + ZBX_FLAG_DISCOVERY_PROTOTYPE, ITEM_TYPE_CALCULATED); + + if (NULL == (result = DBselect("%s", sql))) + { + *error = zbx_dsprintf(*error, "failed to get data from table \"%s\"", table->table); + goto out; + } + + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " from %s", table->table); + + while (NULL != (row = DBfetch(result))) + { + unsigned char type; + + ZBX_STR2UCHAR(type, row[fld_type]); + if (SUCCEED == is_item_processed_by_server(type, row[fld_key])) + continue; + + ZBX_DBROW2UINT64(itemid, row[0]); + + if (ITEM_TYPE_DEPENDENT != atoi(row[fld_type])) + { + zbx_json_addarray(j, NULL); + proxyconfig_add_row(j, row, table, itemids); + zbx_json_close(j); + + zbx_hashset_insert(&items, &itemid, sizeof(itemid)); + } + else + { + ZBX_DBROW2UINT64(master_itemid, row[fld_master_itemid]); + dep_item = proxyconfig_dep_item_create(itemid, master_itemid, row, fld); + zbx_vector_proxyconfig_dep_item_ptr_append(&dep_items, dep_item); + } + } + DBfree_result(result); + + /* add dependent items processed by proxy */ + if (0 != dep_items.values_num) + { + do + { + dep_items_num = dep_items.values_num; + + for (i = 0; i < dep_items.values_num; ) + { + dep_item = dep_items.values[i]; + + if (NULL != zbx_hashset_search(&items, &dep_item->master_itemid)) + { + zbx_json_addarray(j, NULL); + proxyconfig_add_row(j, dep_item->row, table, itemids); + zbx_json_close(j); + + zbx_hashset_insert(&items, &dep_item->itemid, sizeof(zbx_uint64_t)); + proxyconfig_dep_item_free(dep_item); + zbx_vector_proxyconfig_dep_item_ptr_remove_noorder(&dep_items, i); + } + else + i++; + } + } + while (dep_items_num != dep_items.values_num); + } + } + + zbx_json_close(j); + zbx_json_close(j); + + zbx_vector_uint64_sort(itemids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); + + ret = SUCCEED; +out: + zbx_free(sql); + + zbx_vector_proxyconfig_dep_item_ptr_clear_ext(&dep_items, proxyconfig_dep_item_free); + zbx_vector_proxyconfig_dep_item_ptr_destroy(&dep_items); + zbx_hashset_destroy(&items); + + zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); + + return ret; +} + +/****************************************************************************** + * * + * Purpose: get host and related table data from database * + * * + * Parameters: hostids - [IN] the target host identifiers * + * j - [OUT] the output json * + * error - [OUT] the error message * + * * + * Return value: SUCCEED - the data was read successfully * + * FAIL - otherwise * + * * + ******************************************************************************/ +static int proxyconfig_get_host_data(const zbx_vector_uint64_t *hostids, struct zbx_json *j, char **error) +{ + zbx_vector_uint64_t interfaceids, itemids; + int ret = FAIL; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + + zbx_vector_uint64_create(&interfaceids); + zbx_vector_uint64_create(&itemids); + + if (SUCCEED != proxyconfig_get_table_data("hosts", "hostid", hostids, NULL, NULL, j, error)) + goto out; + + if (SUCCEED != proxyconfig_get_table_data("interface", "hostid", hostids, NULL, &interfaceids, j, error)) + goto out; + + if (SUCCEED != proxyconfig_get_table_data("interface_snmp", "interfaceid", &interfaceids, NULL, NULL, + j, error)) + { + goto out; + } + + if (SUCCEED != proxyconfig_get_table_data("host_inventory", "hostid", hostids, NULL, NULL, j, error)) + goto out; + + if (SUCCEED != proxyconfig_get_item_data(hostids, &itemids, j, error)) + goto out; + + if (SUCCEED != proxyconfig_get_table_data("item_rtdata", "itemid", &itemids, NULL, NULL, j, error)) + goto out; + + if (SUCCEED != proxyconfig_get_table_data("item_preproc", "itemid", &itemids, NULL, NULL, j, error)) + goto out; + + if (SUCCEED != proxyconfig_get_table_data("item_parameter", "itemid", &itemids, NULL, NULL, j, error)) + goto out; + + ret = SUCCEED; +out: + zbx_vector_uint64_destroy(&itemids); + zbx_vector_uint64_destroy(&interfaceids); + + zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); + + return ret; +} + +/****************************************************************************** + * * + * Purpose: get discovery rule and checks data from database * + * * + * Parameters: proxy - [IN] the target proxy * + * j - [OUT] the output json * + * error - [OUT] the error message * + * * + * Return value: SUCCEED - the data was read successfully * + * FAIL - otherwise * + * * + ******************************************************************************/ +static int proxyconfig_get_drules_data(const DC_PROXY *proxy, struct zbx_json *j, char **error) +{ + zbx_vector_uint64_t druleids; + zbx_vector_uint64_t proxy_hostids; + int ret = FAIL; + char *filter = NULL; + size_t filter_alloc = 0, filter_offset = 0; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + + zbx_vector_uint64_create(&druleids); + zbx_vector_uint64_create(&proxy_hostids); + + zbx_vector_uint64_append(&proxy_hostids, proxy->hostid); + + zbx_snprintf_alloc(&filter, &filter_alloc, &filter_offset, " status=%d", DRULE_STATUS_MONITORED); + + if (SUCCEED != proxyconfig_get_table_data("drules", "proxy_hostid", &proxy_hostids, filter, &druleids, j, + error)) + { + goto out; + } + + if (SUCCEED != proxyconfig_get_table_data("dchecks", "druleid", &druleids, NULL, NULL, j, error)) + goto out; + + ret = SUCCEED; +out: + zbx_free(filter); + zbx_vector_uint64_destroy(&proxy_hostids); + zbx_vector_uint64_destroy(&druleids); + + zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); + + return ret; +} + +/****************************************************************************** + * * + * Purpose: get global regular expression (regexps/expressions) data from * + * database * + * * + * Parameters: j - [OUT] the output json * + * error - [OUT] the error message * + * * + * Return value: SUCCEED - the data was read successfully * + * FAIL - otherwise * + * * + ******************************************************************************/ +static int proxyconfig_get_expression_data(struct zbx_json *j, char **error) +{ + zbx_vector_uint64_t regexpids; + int ret = FAIL; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + + zbx_vector_uint64_create(®expids); + + if (SUCCEED != proxyconfig_get_table_data("regexps", NULL, NULL, NULL, ®expids, j, error)) + goto out; + + if (SUCCEED != proxyconfig_get_table_data("expressions", "regexpid", ®expids, NULL, NULL, j, error)) + goto out; + + ret = SUCCEED; +out: + zbx_vector_uint64_destroy(®expids); + + zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); + + return ret; +} + +/****************************************************************************** + * * + * Purpose: get httptest and related data from database * + * * + * Parameters: httptestids - [IN] the httptest identifiers * + * j - [OUT] the output json * + * error - [OUT] the error message * + * * + * Return value: SUCCEED - the data was read successfully * + * FAIL - otherwise * + * * + ******************************************************************************/ +static int proxyconfig_get_httptest_data(const zbx_vector_uint64_t *httptestids, struct zbx_json *j, char **error) +{ + zbx_vector_uint64_t httpstepids; + int ret = FAIL; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + + zbx_vector_uint64_create(&httpstepids); + + if (SUCCEED != proxyconfig_get_table_data("httptest", "httptestid", httptestids, NULL, NULL, j, error)) + goto out; + + if (SUCCEED != proxyconfig_get_table_data("httptestitem", "httptestid", httptestids, NULL, NULL, j, error)) + goto out; + + if (SUCCEED != proxyconfig_get_table_data("httptest_field", "httptestid", httptestids, NULL, NULL, j, error)) + goto out; + + if (SUCCEED != proxyconfig_get_table_data("httpstep", "httptestid", httptestids, NULL, &httpstepids, j, error)) + goto out; + + if (SUCCEED != proxyconfig_get_table_data("httpstepitem", "httpstepid", &httpstepids, NULL, NULL, j, error)) + goto out; + + if (SUCCEED != proxyconfig_get_table_data("httpstep_field", "httpstepid", &httpstepids, NULL, NULL, j, error)) + goto out; + + ret = SUCCEED; +out: + zbx_vector_uint64_destroy(&httpstepids); + + zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); + + return ret; +} + +static int proxyconfig_get_tables(const DC_PROXY *proxy, zbx_uint64_t proxy_config_revision, + const zbx_dc_revision_t *dc_revision, struct zbx_json *j, zbx_proxyconfig_status_t *status, + char **error) +{ +#define ZBX_PROXYCONFIG_SYNC_HOSTS 0x0001 +#define ZBX_PROXYCONFIG_SYNC_GMACROS 0x0002 +#define ZBX_PROXYCONFIG_SYNC_HMACROS 0x0004 +#define ZBX_PROXYCONFIG_SYNC_DRULES 0x0008 +#define ZBX_PROXYCONFIG_SYNC_EXPRESSIONS 0x0010 +#define ZBX_PROXYCONFIG_SYNC_CONFIG 0x0020 +#define ZBX_PROXYCONFIG_SYNC_HTTPTESTS 0x0040 +#define ZBX_PROXYCONFIG_SYNC_AUTOREG 0x0080 + +#define ZBX_PROXYCONFIG_SYNC_ALL (ZBX_PROXYCONFIG_SYNC_HOSTS | ZBX_PROXYCONFIG_SYNC_GMACROS | \ + ZBX_PROXYCONFIG_SYNC_HMACROS |ZBX_PROXYCONFIG_SYNC_DRULES | \ + ZBX_PROXYCONFIG_SYNC_EXPRESSIONS | ZBX_PROXYCONFIG_SYNC_CONFIG | \ + ZBX_PROXYCONFIG_SYNC_HTTPTESTS | ZBX_PROXYCONFIG_SYNC_AUTOREG) + + zbx_vector_uint64_t hostids, httptestids, updated_hostids, removed_hostids, del_macro_hostids, + macro_hostids; + zbx_vector_ptr_t keys_paths; + int global_macros = FAIL, ret = FAIL, i; + zbx_uint64_t flags = 0; + + zbx_vector_uint64_create(&hostids); + zbx_vector_uint64_create(&updated_hostids); + zbx_vector_uint64_create(&removed_hostids); + zbx_vector_uint64_create(&httptestids); + zbx_vector_uint64_create(¯o_hostids); + zbx_vector_uint64_create(&del_macro_hostids); + zbx_vector_ptr_create(&keys_paths); + + if (proxy_config_revision < proxy->revision || proxy_config_revision < proxy->macro_revision) + { + zbx_vector_uint64_reserve(&hostids, 1000); + zbx_vector_uint64_reserve(&updated_hostids, 1000); + zbx_vector_uint64_reserve(&removed_hostids, 100); + zbx_vector_uint64_reserve(&httptestids, 100); + zbx_vector_uint64_reserve(¯o_hostids, 1000); + zbx_vector_uint64_reserve(&del_macro_hostids, 100); + + zbx_dc_get_proxy_config_updates(proxy->hostid, proxy_config_revision, &hostids, &updated_hostids, + &removed_hostids, &httptestids); + + zbx_dc_get_macro_updates(&hostids, &updated_hostids, proxy_config_revision, ¯o_hostids, + &global_macros, &del_macro_hostids); + } + + if (0 != proxy_config_revision) + { + if (0 != updated_hostids.values_num) + flags |= ZBX_PROXYCONFIG_SYNC_HOSTS; + + if (SUCCEED == global_macros) + flags |= ZBX_PROXYCONFIG_SYNC_GMACROS; + + if(0 != macro_hostids.values_num) + flags |= ZBX_PROXYCONFIG_SYNC_HMACROS; + + if (proxy_config_revision < proxy->revision) + flags |= ZBX_PROXYCONFIG_SYNC_DRULES; + + if (proxy_config_revision < dc_revision->expression) + flags |= ZBX_PROXYCONFIG_SYNC_EXPRESSIONS; + + if (proxy_config_revision < dc_revision->config_table) + flags |= ZBX_PROXYCONFIG_SYNC_CONFIG; + + if (0 != httptestids.values_num) + flags |= ZBX_PROXYCONFIG_SYNC_HTTPTESTS; + + if (proxy_config_revision < dc_revision->autoreg_tls) + flags |= ZBX_PROXYCONFIG_SYNC_AUTOREG; + } + else + flags = ZBX_PROXYCONFIG_SYNC_ALL; + + zbx_json_addobject(j, ZBX_PROTO_TAG_DATA); + + if (0 != flags) + { + DBbegin(); + + if (0 != (flags & ZBX_PROXYCONFIG_SYNC_HOSTS) && + SUCCEED != proxyconfig_get_host_data(&updated_hostids, j, error)) + { + goto out; + } + + if (0 != (flags & ZBX_PROXYCONFIG_SYNC_GMACROS) && + SUCCEED != proxyconfig_get_macro_updates("globalmacro", NULL, &keys_paths, j, error)) + { + goto out; + } + + if (0 != (flags & ZBX_PROXYCONFIG_SYNC_HMACROS)) + { + if (SUCCEED != proxyconfig_get_table_data("hosts_templates", "hostid", ¯o_hostids, NULL, + NULL, j, error)) + { + goto out; + } + + if (SUCCEED != proxyconfig_get_macro_updates("hostmacro", ¯o_hostids, &keys_paths, j, error)) + goto out; + } + + if (0 != (flags & ZBX_PROXYCONFIG_SYNC_DRULES) && + SUCCEED != proxyconfig_get_drules_data(proxy, j, error)) + { + goto out; + } + + if (0 != (flags & ZBX_PROXYCONFIG_SYNC_EXPRESSIONS) && + SUCCEED != proxyconfig_get_expression_data(j, error)) + { + goto out; + } + + if (0 != (flags & ZBX_PROXYCONFIG_SYNC_CONFIG) && + SUCCEED != proxyconfig_get_table_data("config", NULL, NULL, NULL, NULL, j, error)) + { + goto out; + } + + if (0 != (flags & ZBX_PROXYCONFIG_SYNC_HTTPTESTS) && + SUCCEED != proxyconfig_get_httptest_data(&httptestids, j, error)) + { + goto out; + } + + if (0 != (flags & ZBX_PROXYCONFIG_SYNC_AUTOREG) && + SUCCEED != proxyconfig_get_table_data("config_autoreg_tls", NULL, NULL, NULL, NULL, j, + error)) + { + goto out; + } + } + + zbx_json_close(j); + + if (0 != removed_hostids.values_num) + { + zbx_json_addarray(j, ZBX_PROTO_TAG_REMOVED_HOSTIDS); + + for (i = 0; i < removed_hostids.values_num; i++) + zbx_json_adduint64(j, NULL, removed_hostids.values[i]); + + zbx_json_close(j); + } + + if (0 != del_macro_hostids.values_num) + { + zbx_json_addarray(j, ZBX_PROTO_TAG_REMOVED_MACRO_HOSTIDS); + + for (i = 0; i < del_macro_hostids.values_num; i++) + zbx_json_adduint64(j, NULL, del_macro_hostids.values[i]); + + zbx_json_close(j); + } + + if (0 != keys_paths.values_num) + get_macro_secrets(&keys_paths, j); + + if (0 == flags && 0 == removed_hostids.values_num && 0 == del_macro_hostids.values_num) + *status = ZBX_PROXYCONFIG_STATUS_EMPTY; + else + *status = ZBX_PROXYCONFIG_STATUS_DATA; + + ret = SUCCEED; +out: + if (0 != flags) + DBcommit(); + + zbx_vector_ptr_clear_ext(&keys_paths, key_path_free); + zbx_vector_ptr_destroy(&keys_paths); + zbx_vector_uint64_destroy(&httptestids); + zbx_vector_uint64_destroy(¯o_hostids); + zbx_vector_uint64_destroy(&del_macro_hostids); + zbx_vector_uint64_destroy(&removed_hostids); + zbx_vector_uint64_destroy(&updated_hostids); + zbx_vector_uint64_destroy(&hostids); + + return ret; + +#undef ZBX_PROXYCONFIG_SYNC_HOSTS +#undef ZBX_PROXYCONFIG_SYNC_GMACROS +#undef ZBX_PROXYCONFIG_SYNC_HMACROS +#undef ZBX_PROXYCONFIG_SYNC_DRULES +#undef ZBX_PROXYCONFIG_SYNC_EXPRESSIONS +#undef ZBX_PROXYCONFIG_SYNC_CONFIG +#undef ZBX_PROXYCONFIG_SYNC_HTTPTESTS +#undef ZBX_PROXYCONFIG_SYNC_AUTOREG +} + +/****************************************************************************** + * * + * Purpose: prepare proxy configuration data * + * * + ******************************************************************************/ +int zbx_proxyconfig_get_data(DC_PROXY *proxy, const struct zbx_json_parse *jp_request, struct zbx_json *j, + zbx_proxyconfig_status_t *status, char **error) +{ + int ret = FAIL; + char token[ZBX_SESSION_TOKEN_SIZE + 1], tmp[ZBX_MAX_UINT64_LEN + 1]; + zbx_uint64_t proxy_config_revision; + zbx_dc_revision_t dc_revision; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s() proxy_hostid:" ZBX_FS_UI64, __func__, proxy->hostid); + + if (SUCCEED != zbx_json_value_by_name(jp_request, ZBX_PROTO_TAG_SESSION, token, sizeof(token), NULL)) + { + *error = zbx_strdup(NULL, "cannot get session from proxy configuration request"); + goto out; + } + + if (SUCCEED != zbx_json_value_by_name(jp_request, ZBX_PROTO_TAG_CONFIG_REVISION, tmp, sizeof(tmp), NULL)) + { + *error = zbx_strdup(NULL, "cannot get revision from proxy configuration request"); + goto out; + } + + if (SUCCEED != zbx_is_uint64(tmp, &proxy_config_revision)) + { + *error = zbx_dsprintf(NULL, "invalid proxy configuration revision: %s", tmp); + goto out; + } + + if (0 != zbx_dc_register_config_session(proxy->hostid, token, proxy_config_revision, &dc_revision) || + 0 == proxy_config_revision) + { + zabbix_log(LOG_LEVEL_DEBUG, "%s() forcing full proxy configuration sync", __func__); + proxy_config_revision = 0; + zbx_json_addint64(j, ZBX_PROTO_TAG_FULL_SYNC, 1); + } + else + { + zabbix_log(LOG_LEVEL_DEBUG, "%s() updating proxy configuration " ZBX_FS_UI64 "->" ZBX_FS_UI64, + __func__, proxy_config_revision, dc_revision.config); + } + + if (proxy_config_revision != dc_revision.config) + { + if (SUCCEED != (ret = proxyconfig_get_tables(proxy, proxy_config_revision, &dc_revision, j, status, + error))) + { + goto out; + } + + zbx_json_adduint64(j, ZBX_PROTO_TAG_CONFIG_REVISION, dc_revision.config); + + zabbix_log(LOG_LEVEL_TRACE, "%s() configuration: %s", __func__, j->buffer); + } + else + { + *status = ZBX_PROXYCONFIG_STATUS_EMPTY; + ret = SUCCEED; + } +out: + zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); + + return ret; +} + +/****************************************************************************** + * * + * Purpose: send configuration tables to the proxy from server * + * (for active proxies) * + * * + ******************************************************************************/ +void zbx_send_proxyconfig(zbx_socket_t *sock, const struct zbx_json_parse *jp) +{ + char *error = NULL, *buffer = NULL, *version_str = NULL; + struct zbx_json j; + DC_PROXY proxy; + int ret, flags = ZBX_TCP_PROTOCOL, loglevel, version_int; + size_t buffer_size, reserved = 0; + zbx_proxyconfig_status_t status; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + + if (SUCCEED != get_active_proxy_from_request(jp, &proxy, &error)) + { + zabbix_log(LOG_LEVEL_WARNING, "cannot parse proxy configuration data request from active proxy at" + " \"%s\": %s", sock->peer, error); + goto out; + } + + if (SUCCEED != zbx_proxy_check_permissions(&proxy, sock, &error)) + { + zabbix_log(LOG_LEVEL_WARNING, "cannot accept connection from proxy \"%s\" at \"%s\", allowed address:" + " \"%s\": %s", proxy.host, sock->peer, proxy.proxy_address, error); + goto out; + } + + version_str = zbx_get_proxy_protocol_version_str(jp); + version_int = zbx_get_proxy_protocol_version_int(version_str); + + zbx_update_proxy_data(&proxy, version_str, version_int, (int)time(NULL), + (0 != (sock->protocol & ZBX_TCP_COMPRESS) ? 1 : 0), ZBX_FLAGS_PROXY_DIFF_UPDATE_CONFIG); + + if (0 != proxy.auto_compress) + flags |= ZBX_TCP_COMPRESS; + + if (ZBX_PROXY_VERSION_CURRENT != proxy.compatibility) + { + error = zbx_strdup(error, "proxy and server major versions do not match"); + (void)zbx_send_response_ext(sock, NOTSUPPORTED, error, ZABBIX_VERSION, flags, CONFIG_TIMEOUT); + zabbix_log(LOG_LEVEL_WARNING, "configuration update is disabled for this version of proxy \"%s\" at" + " \"%s\": %s", proxy.host, sock->peer, error); + goto out; + } + + zbx_json_init(&j, ZBX_JSON_STAT_BUF_LEN); + + if (SUCCEED != zbx_proxyconfig_get_data(&proxy, jp, &j, &status, &error)) + { + (void)zbx_send_response_ext(sock, FAIL, error, NULL, flags, CONFIG_TIMEOUT); + zabbix_log(LOG_LEVEL_WARNING, "cannot collect configuration data for proxy \"%s\" at \"%s\": %s", + proxy.host, sock->peer, error); + goto clean; + } + + loglevel = (ZBX_PROXYCONFIG_STATUS_DATA == status ? LOG_LEVEL_WARNING : LOG_LEVEL_DEBUG); + + if (0 != proxy.auto_compress) + { + if (SUCCEED != zbx_compress(j.buffer, j.buffer_size, &buffer, &buffer_size)) + { + zabbix_log(LOG_LEVEL_ERR,"cannot compress data: %s", zbx_compress_strerror()); + goto clean; + } + + reserved = j.buffer_size; + + zbx_json_free(&j); /* json buffer can be large, free as fast as possible */ + + zabbix_log(loglevel, "sending configuration data to proxy \"%s\" at \"%s\", datalen " + ZBX_FS_SIZE_T ", bytes " ZBX_FS_SIZE_T " with compression ratio %.1f", proxy.host, + sock->peer, (zbx_fs_size_t)reserved, (zbx_fs_size_t)buffer_size, + (double)reserved / (double)buffer_size); + + ret = zbx_tcp_send_ext(sock, buffer, buffer_size, reserved, (unsigned char)flags, + CONFIG_TRAPPER_TIMEOUT); + } + else + { + zabbix_log(loglevel, "sending configuration data to proxy \"%s\" at \"%s\", datalen " + ZBX_FS_SIZE_T, proxy.host, sock->peer, (zbx_fs_size_t)j.buffer_size); + + ret = zbx_tcp_send_ext(sock, j.buffer, strlen(j.buffer), 0, (unsigned char)flags, + CONFIG_TRAPPER_TIMEOUT); + } + + if (SUCCEED != ret) + { + zabbix_log(LOG_LEVEL_WARNING, "cannot send configuration data to proxy \"%s\" at \"%s\": %s", + proxy.host, sock->peer, zbx_socket_strerror()); + } +clean: + zbx_json_free(&j); +out: + zbx_free(error); + zbx_free(buffer); + zbx_free(version_str); + + zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); +} diff --git a/src/zabbix_server/proxyconfigread/proxyconfig_read.h b/src/zabbix_server/proxyconfigread/proxyconfig_read.h new file mode 100644 index 00000000000..e77b7de6980 --- /dev/null +++ b/src/zabbix_server/proxyconfigread/proxyconfig_read.h @@ -0,0 +1,36 @@ +/* +** Zabbix +** Copyright (C) 2001-2022 Zabbix SIA +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +**/ + +#ifndef ZABBIX_PROXYCONFIG_READ_H +#define ZABBIX_PROXYCONFIG_READ_H + +#include "dbcache.h" + +typedef enum { + ZBX_PROXYCONFIG_STATUS_EMPTY, + ZBX_PROXYCONFIG_STATUS_DATA +} +zbx_proxyconfig_status_t; + +int zbx_proxyconfig_get_data(DC_PROXY *proxy, const struct zbx_json_parse *jp_request, struct zbx_json *j, + zbx_proxyconfig_status_t *status, char **error); + +void zbx_send_proxyconfig(zbx_socket_t *sock, const struct zbx_json_parse *jp); + +#endif diff --git a/src/zabbix_server/proxypoller/Makefile.am b/src/zabbix_server/proxypoller/Makefile.am index c988506594f..a2dfa58e1d1 100644 --- a/src/zabbix_server/proxypoller/Makefile.am +++ b/src/zabbix_server/proxypoller/Makefile.am @@ -6,3 +6,4 @@ libzbxproxypoller_a_SOURCES = \ proxypoller.c \ proxypoller.h +libzbxproxypoller_a_CFLAGS = -I$(top_srcdir)/src/zabbix_server diff --git a/src/zabbix_server/proxypoller/proxypoller.c b/src/zabbix_server/proxypoller/proxypoller.c index 5096e44007e..f9fce0b1faf 100644 --- a/src/zabbix_server/proxypoller/proxypoller.c +++ b/src/zabbix_server/proxypoller/proxypoller.c @@ -32,6 +32,8 @@ #include "zbxcommshigh.h" #include "zbxnum.h" #include "zbxtime.h" +#include "proxyconfigread/proxyconfig_read.h" +#include "zbxversion.h" static zbx_get_program_type_f zbx_get_program_type_cb = NULL; extern ZBX_THREAD_LOCAL unsigned char process_type; @@ -91,7 +93,7 @@ static int send_data_to_proxy(const DC_PROXY *proxy, zbx_socket_t *sock, const c { int ret; - zabbix_log(LOG_LEVEL_DEBUG, "In %s() data:'%s'", __func__, data); + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); if (FAIL == (ret = zbx_tcp_send_ext(sock, data, size, reserved, flags, 0))) { @@ -254,22 +256,45 @@ out: ******************************************************************************/ static int proxy_send_configuration(DC_PROXY *proxy) { - char *error = NULL, *buffer = NULL; - int ret, flags = ZBX_TCP_PROTOCOL; - zbx_socket_t s; - struct zbx_json j; - size_t buffer_size, reserved = 0; + char *error = NULL, *buffer = NULL; + int ret, flags = ZBX_TCP_PROTOCOL, loglevel; + zbx_socket_t s; + struct zbx_json j; + struct zbx_json_parse jp; + size_t buffer_size, reserved = 0; + zbx_proxyconfig_status_t status; - zbx_json_init(&j, 512 * ZBX_KIBIBYTE); + zbx_json_init(&j, 512 * ZBX_KIBIBYTE); zbx_json_addstring(&j, ZBX_PROTO_TAG_REQUEST, ZBX_PROTO_VALUE_PROXY_CONFIG, ZBX_JSON_TYPE_STRING); - zbx_json_addobject(&j, ZBX_PROTO_TAG_DATA); - if (SUCCEED != (ret = get_proxyconfig_data(proxy->hostid, &j, &error))) + if (SUCCEED != (ret = connect_to_proxy(proxy, &s, CONFIG_TRAPPER_TIMEOUT))) + goto out; + + if (SUCCEED != (ret = send_data_to_proxy(proxy, &s, j.buffer, j.buffer_size, reserved, ZBX_TCP_PROTOCOL))) + goto clean; + + if (FAIL == (ret = zbx_tcp_recv_ext(&s, 0, 0))) + { + zabbix_log(LOG_LEVEL_WARNING, "cannot receive configuration information from proxy \"%s\": %s", + proxy->host, zbx_socket_strerror()); + goto clean; + } + + if (SUCCEED != (ret = zbx_json_open(s.buffer, &jp))) + { + zabbix_log(LOG_LEVEL_WARNING, "cannot parse configuration information from proxy \"%s\": %s", + proxy->host, zbx_socket_strerror()); + goto clean; + } + + zbx_json_clean(&j); + + if (SUCCEED != (ret = zbx_proxyconfig_get_data(proxy, &jp, &j, &status, &error))) { zabbix_log(LOG_LEVEL_ERR, "cannot collect configuration data for proxy \"%s\": %s", proxy->host, error); - goto out; + goto clean; } if (0 != proxy->auto_compress) @@ -278,7 +303,7 @@ static int proxy_send_configuration(DC_PROXY *proxy) { zabbix_log(LOG_LEVEL_ERR,"cannot compress data: %s", zbx_compress_strerror()); ret = FAIL; - goto out; + goto clean; } flags |= ZBX_TCP_COMPRESS; @@ -286,12 +311,11 @@ static int proxy_send_configuration(DC_PROXY *proxy) zbx_json_free(&j); /* json buffer can be large, free as fast as possible */ } - if (SUCCEED != (ret = connect_to_proxy(proxy, &s, CONFIG_TRAPPER_TIMEOUT))) - goto out; + loglevel = (ZBX_PROXYCONFIG_STATUS_DATA == status ? LOG_LEVEL_WARNING : LOG_LEVEL_DEBUG); if (0 != proxy->auto_compress) { - zabbix_log(LOG_LEVEL_WARNING, "sending configuration data to proxy \"%s\" at \"%s\", datalen " + zabbix_log(loglevel, "sending configuration data to proxy \"%s\" at \"%s\", datalen " ZBX_FS_SIZE_T ", bytes " ZBX_FS_SIZE_T " with compression ratio %.1f", proxy->host, s.peer, (zbx_fs_size_t)reserved, (zbx_fs_size_t)buffer_size, (double)reserved / buffer_size); @@ -301,7 +325,7 @@ static int proxy_send_configuration(DC_PROXY *proxy) } else { - zabbix_log(LOG_LEVEL_WARNING, "sending configuration data to proxy \"%s\" at \"%s\", datalen " + zabbix_log(loglevel, "sending configuration data to proxy \"%s\" at \"%s\", datalen " ZBX_FS_SIZE_T, proxy->host, s.peer, (zbx_fs_size_t)j.buffer_size); ret = send_data_to_proxy(proxy, &s, j.buffer, j.buffer_size, reserved, flags); @@ -317,8 +341,6 @@ static int proxy_send_configuration(DC_PROXY *proxy) } else { - struct zbx_json_parse jp; - if (SUCCEED != zbx_json_open(s.buffer, &jp)) { zabbix_log(LOG_LEVEL_WARNING, "invalid configuration data response received from proxy" @@ -326,13 +348,18 @@ static int proxy_send_configuration(DC_PROXY *proxy) } else { - proxy->version = zbx_get_proxy_protocol_version(&jp); + char *version_str; + + version_str = zbx_get_proxy_protocol_version_str(&jp); + zbx_strlcpy(proxy->version_str, version_str, sizeof(proxy->version_str)); + proxy->version_int = zbx_get_proxy_protocol_version_int(version_str); proxy->auto_compress = (0 != (s.protocol & ZBX_TCP_COMPRESS) ? 1 : 0); proxy->lastaccess = time(NULL); + zbx_free(version_str); } } } - +clean: disconnect_proxy(&s); out: zbx_free(buffer); @@ -362,8 +389,8 @@ out: static int proxy_process_proxy_data(DC_PROXY *proxy, const char *answer, zbx_timespec_t *ts, int *more) { struct zbx_json_parse jp; - char *error = NULL; - int ret = FAIL, version; + char *error = NULL, *version_str = NULL; + int version_int, ret = FAIL; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); @@ -383,15 +410,17 @@ static int proxy_process_proxy_data(DC_PROXY *proxy, const char *answer, zbx_tim goto out; } - version = zbx_get_proxy_protocol_version(&jp); + version_str = zbx_get_proxy_protocol_version_str(&jp); + version_int = zbx_get_proxy_protocol_version_int(version_str); - if (SUCCEED != zbx_check_protocol_version(proxy, version)) + zbx_strlcpy(proxy->version_str, version_str, sizeof(proxy->version_str)); + proxy->version_int = version_int; + + if (SUCCEED != zbx_check_protocol_version(proxy, version_int)) { goto out; } - proxy->version = version; - if (SUCCEED != (ret = process_proxy_data(proxy, &jp, ts, HOST_STATUS_PROXY_PASSIVE, more, &error))) { zabbix_log(LOG_LEVEL_WARNING, "proxy \"%s\" at \"%s\" returned invalid proxy data: %s", @@ -400,6 +429,7 @@ static int proxy_process_proxy_data(DC_PROXY *proxy, const char *answer, zbx_tim out: zbx_free(error); + zbx_free(version_str); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); @@ -431,10 +461,11 @@ static int proxy_get_data(DC_PROXY *proxy, int *more) if (SUCCEED != (ret = get_data_from_proxy(proxy, ZBX_PROTO_VALUE_PROXY_DATA, &answer, &ts))) goto out; - /* handle pre 3.4 proxies that did not support proxy data request */ + /* handle pre 3.4 proxies that did not support proxy data request and active/passive configuration mismatch */ if ('\0' == *answer) { - proxy->version = ZBX_COMPONENT_VERSION(3, 2); + zbx_strlcpy(proxy->version_str, ZBX_VERSION_UNDEFINED_STR, sizeof(proxy->version_str)); + proxy->version_int = ZBX_COMPONENT_VERSION_UNDEFINED; zbx_free(answer); ret = FAIL; goto out; @@ -473,11 +504,18 @@ static int proxy_get_tasks(DC_PROXY *proxy) zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); - if (ZBX_COMPONENT_VERSION(3, 2) >= proxy->version) + if (SUCCEED != (ret = get_data_from_proxy(proxy, ZBX_PROTO_VALUE_PROXY_TASKS, &answer, &ts))) goto out; - if (SUCCEED != (ret = get_data_from_proxy(proxy, ZBX_PROTO_VALUE_PROXY_TASKS, &answer, &ts))) + /* handle pre 3.4 proxies that did not support proxy data request and active/passive configuration mismatch */ + if ('\0' == *answer) + { + zbx_strlcpy(proxy->version_str, ZBX_VERSION_UNDEFINED_STR, sizeof(proxy->version_str)); + proxy->version_int = ZBX_COMPONENT_VERSION_UNDEFINED; + zbx_free(answer); + ret = FAIL; goto out; + } proxy->lastaccess = time(NULL); @@ -547,7 +585,7 @@ static int process_proxy(void) } zbx_free(port); - if (proxy.proxy_config_nextcheck <= now) + if (proxy.proxy_config_nextcheck <= now && proxy.compatibility == ZBX_PROXY_VERSION_CURRENT) { if (SUCCEED != (ret = proxy_send_configuration(&proxy))) goto error; @@ -556,7 +594,8 @@ static int process_proxy(void) if (proxy.proxy_tasks_nextcheck <= now) check_tasks = 1; - if (proxy.proxy_data_nextcheck <= now) + if (proxy.proxy_data_nextcheck <= now && (proxy.compatibility == ZBX_PROXY_VERSION_CURRENT || + proxy.compatibility == ZBX_PROXY_VERSION_OUTDATED)) { int more; @@ -580,11 +619,11 @@ static int process_proxy(void) } } error: - - if (proxy_old.version != proxy.version || proxy_old.auto_compress != proxy.auto_compress || + if (0 != strcmp(proxy_old.version_str, proxy.version_str) || + proxy_old.auto_compress != proxy.auto_compress || proxy_old.lastaccess != proxy.lastaccess) { - zbx_update_proxy_data(&proxy_old, proxy.version, proxy.lastaccess, proxy.auto_compress, 0); + zbx_update_proxy_data(&proxy_old, proxy.version_str, proxy.version_int, proxy.lastaccess, proxy.auto_compress, 0); } DCrequeue_proxy(proxy.hostid, update_nextcheck, ret); @@ -615,7 +654,7 @@ ZBX_THREAD_ENTRY(proxypoller_thread, args) get_program_type_string(zbx_get_program_type_cb()), server_num, get_process_type_string(process_type), process_num); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); #define STAT_INTERVAL 5 /* if a process is busy and does not sleep then update status not faster than */ /* once in STAT_INTERVAL seconds */ diff --git a/src/zabbix_server/reporter/report_manager.c b/src/zabbix_server/reporter/report_manager.c index 045aff35198..4bb016ec032 100644 --- a/src/zabbix_server/reporter/report_manager.c +++ b/src/zabbix_server/reporter/report_manager.c @@ -25,7 +25,6 @@ #include "zbxnix.h" #include "base64.h" #include "../zbxreport.h" -#include "zbxhash.h" #include "zbxcrypto.h" #include "zbxalert.h" #include "report_protocol.h" @@ -2312,7 +2311,7 @@ ZBX_THREAD_ENTRY(report_manager_thread, args) zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(program_type), server_num, get_process_type_string(process_type), process_num); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); if (FAIL == rm_init(&manager, &error)) { @@ -2385,9 +2384,9 @@ ZBX_THREAD_ENTRY(report_manager_thread, args) time_now = sec; - update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); ret = zbx_ipc_service_recv(&manager.ipc, &timeout, &client, &message); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); sec = zbx_time(); zbx_update_env(sec); diff --git a/src/zabbix_server/reporter/report_writer.c b/src/zabbix_server/reporter/report_writer.c index a569c47962b..671349b906f 100644 --- a/src/zabbix_server/reporter/report_writer.c +++ b/src/zabbix_server/reporter/report_writer.c @@ -438,7 +438,7 @@ ZBX_THREAD_ENTRY(report_writer_thread, args) get_program_type_string(poller_args_in->zbx_get_program_type_cb_arg()), server_num, get_process_type_string(process_type), process_num); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); zbx_setproctitle("%s #%d started", get_process_type_string(process_type), process_num); @@ -462,7 +462,7 @@ ZBX_THREAD_ENTRY(report_writer_thread, args) finished_num = 0; } - update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); if (SUCCEED != zbx_ipc_socket_read(&socket, &message)) { @@ -470,7 +470,7 @@ ZBX_THREAD_ENTRY(report_writer_thread, args) exit(EXIT_FAILURE); } - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); time_wake = zbx_time(); zbx_update_env(time_wake); diff --git a/src/zabbix_server/scripts/scripts.c b/src/zabbix_server/scripts/scripts.c index 18fc14d3072..412230a80b7 100644 --- a/src/zabbix_server/scripts/scripts.c +++ b/src/zabbix_server/scripts/scripts.c @@ -66,7 +66,7 @@ static int zbx_execute_script_on_agent(const DC_HOST *host, const char *command, } param = zbx_strdup(param, command); - if (SUCCEED != (ret = quote_key_param(¶m, 0))) + if (SUCCEED != (ret = zbx_quote_key_param(¶m, 0))) { zbx_snprintf(error, max_error_len, "Invalid param [%s]", param); goto fail; @@ -75,7 +75,7 @@ static int zbx_execute_script_on_agent(const DC_HOST *host, const char *command, item.key = zbx_dsprintf(item.key, "system.run[%s%s]", param, NULL == result ? ",nowait" : ""); item.value_type = ITEM_VALUE_TYPE_TEXT; - init_result(&agent_result); + zbx_init_agent_result(&agent_result); zbx_alarm_on(CONFIG_TIMEOUT); @@ -90,7 +90,7 @@ static int zbx_execute_script_on_agent(const DC_HOST *host, const char *command, zbx_alarm_off(); - free_result(&agent_result); + zbx_free_agent_result(&agent_result); zbx_free(item.key); fail: @@ -167,7 +167,7 @@ static int zbx_execute_script_on_terminal(const DC_HOST *host, const zbx_script_ item.value_type = ITEM_VALUE_TYPE_TEXT; item.params = zbx_strdup(item.params, script->command); - init_result(&agent_result); + zbx_init_agent_result(&agent_result); zbx_alarm_on(CONFIG_TIMEOUT); @@ -182,7 +182,7 @@ static int zbx_execute_script_on_terminal(const DC_HOST *host, const zbx_script_ zbx_alarm_off(); - free_result(&agent_result); + zbx_free_agent_result(&agent_result); zbx_free(item.params); zbx_free(item.key); diff --git a/src/zabbix_server/selfmon/selfmon.c b/src/zabbix_server/selfmon/selfmon.c index 27aaa716d9c..a2f845394e5 100644 --- a/src/zabbix_server/selfmon/selfmon.c +++ b/src/zabbix_server/selfmon/selfmon.c @@ -39,7 +39,7 @@ ZBX_THREAD_ENTRY(selfmon_thread, args) zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(program_type), server_num, get_process_type_string(process_type), process_num); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); while (ZBX_IS_RUNNING()) { @@ -48,7 +48,7 @@ ZBX_THREAD_ENTRY(selfmon_thread, args) zbx_setproctitle("%s [processing data]", get_process_type_string(process_type)); - collect_selfmon_stats(); + zbx_collect_selfmon_stats(); sec = zbx_time() - sec; zbx_setproctitle("%s [processed data in " ZBX_FS_DBL " sec, idle 1 sec]", diff --git a/src/zabbix_server/server.c b/src/zabbix_server/server.c index 1fa9bb786d5..cad237df3fa 100644 --- a/src/zabbix_server/server.c +++ b/src/zabbix_server/server.c @@ -19,8 +19,6 @@ #include "config.h" -#include "zbxserver.h" - #ifdef HAVE_SQLITE3 # error SQLite is not supported as a main Zabbix database backend. #endif @@ -75,6 +73,7 @@ #include "ha/ha.h" #include "zbxrtc.h" #include "zbxha.h" +#include "zbxstats.h" #include "stats/zabbix_stats.h" #include "zbxdiag.h" #include "diag/diag_server.h" @@ -209,7 +208,6 @@ int CONFIG_JAVAPOLLER_FORKS = 0; int CONFIG_ESCALATOR_FORKS = 1; int CONFIG_SELFMON_FORKS = 1; int CONFIG_DATASENDER_FORKS = 0; -int CONFIG_HEARTBEAT_FORKS = 0; int CONFIG_COLLECTOR_FORKS = 0; int CONFIG_PASSIVE_FORKS = 0; int CONFIG_ACTIVE_FORKS = 0; @@ -240,7 +238,7 @@ int CONFIG_MAX_HOUSEKEEPER_DELETE = 5000; /* applies for every separate field v int CONFIG_HISTSYNCER_FORKS = 4; int CONFIG_HISTSYNCER_FREQUENCY = 1; int CONFIG_CONFSYNCER_FORKS = 1; -int CONFIG_CONFSYNCER_FREQUENCY = 60; +int CONFIG_CONFSYNCER_FREQUENCY = 10; int CONFIG_PROBLEMHOUSEKEEPING_FREQUENCY = 60; @@ -307,7 +305,7 @@ int CONFIG_SERVER_STARTUP_TIME = 0; /* zabbix server startup time */ int CONFIG_PROXYPOLLER_FORKS = 1; /* parameters for passive proxies */ /* how often Zabbix server sends configuration data to passive proxy, in seconds */ -int CONFIG_PROXYCONFIG_FREQUENCY = SEC_PER_MIN * 5; +int CONFIG_PROXYCONFIG_FREQUENCY = 10; int CONFIG_PROXYDATA_FREQUENCY = 1; /* 1s */ char *CONFIG_LOAD_MODULE_PATH = NULL; @@ -1031,7 +1029,7 @@ static void zbx_on_exit(int ret) if (ZBX_NODE_STATUS_ACTIVE == ha_status) { - free_metrics(); + zbx_free_metrics(); zbx_ipc_service_free_env(); free_configuration_cache(); @@ -1041,7 +1039,7 @@ static void zbx_on_exit(int ret) /* free vmware support */ zbx_vmware_destroy(); - free_selfmon_collector(); + zbx_free_selfmon_collector(); } zbx_uninitialize_events(); @@ -1152,7 +1150,7 @@ int main(int argc, char **argv) CONFIG_FILE = zbx_strdup(NULL, DEFAULT_CONFIG_FILE); /* required for simple checks */ - init_metrics(); + zbx_init_metrics(); zbx_load_config(&t); if (ZBX_TASK_RUNTIME_CONTROL == t.task) @@ -1241,6 +1239,31 @@ static void zbx_check_db(void) /****************************************************************************** * * + * Purpose: save Zabbix server status to database * + * * + ******************************************************************************/ +static void zbx_db_save_server_status(void) +{ + struct zbx_json json; + + zbx_json_init(&json, ZBX_JSON_STAT_BUF_LEN); + + zbx_json_addstring(&json, "version", ZABBIX_VERSION, ZBX_JSON_TYPE_STRING); + + zbx_json_close(&json); + + DBconnect(ZBX_DB_CONNECT_NORMAL); + + if (ZBX_DB_OK > DBexecute("update config set server_status='%s'", json.buffer)) + zabbix_log(LOG_LEVEL_WARNING, "Failed to save server status to database"); + + DBclose(); + + zbx_json_free(&json); +} + +/****************************************************************************** + * * * Purpose: initialize shared resources and start processes * * * ******************************************************************************/ @@ -1249,9 +1272,11 @@ static int server_startup(zbx_socket_t *listen_sock, int *ha_stat, int *ha_failo int i, ret = SUCCEED; char *error = NULL; + zbx_config_comms_args_t zbx_config = {zbx_config_tls, NULL, 0}; + zbx_thread_args_t thread_args; - zbx_thread_poller_args poller_args = {zbx_config_tls, get_program_type, ZBX_NO_POLLER}; - zbx_thread_trapper_args trapper_args = {zbx_config_tls, get_program_type, listen_sock}; + zbx_thread_poller_args poller_args = {&zbx_config, get_program_type, ZBX_NO_POLLER}; + zbx_thread_trapper_args trapper_args = {&zbx_config, get_program_type, listen_sock}; zbx_thread_escalator_args escalator_args = {zbx_config_tls, get_program_type}; zbx_thread_proxy_poller_args proxy_poller_args = {zbx_config_tls, get_program_type}; zbx_thread_discoverer_args discoverer_args = {zbx_config_tls, get_program_type}; @@ -1272,7 +1297,7 @@ static int server_startup(zbx_socket_t *listen_sock, int *ha_stat, int *ha_failo return FAIL; } - if (SUCCEED != init_selfmon_collector(&error)) + if (SUCCEED != zbx_init_selfmon_collector(&error)) { zabbix_log(LOG_LEVEL_CRIT, "cannot initialize self-monitoring: %s", error); zbx_free(error); @@ -1346,11 +1371,13 @@ static int server_startup(zbx_socket_t *listen_sock, int *ha_stat, int *ha_failo zbx_thread_start(service_manager_thread, &thread_args, &threads[i]); break; case ZBX_PROCESS_TYPE_CONFSYNCER: + zbx_vc_enable(); zbx_thread_start(dbconfig_thread, &thread_args, &threads[i]); if (FAIL == (ret = zbx_rtc_wait_config_sync(rtc))) goto out; - if (SUCCEED != (ret = zbx_ha_get_status(ha_stat, ha_failover, &error))) + if (SUCCEED != (ret = zbx_ha_get_status(CONFIG_HA_NODE_NAME, ha_stat, ha_failover, + &error))) { zabbix_log(LOG_LEVEL_CRIT, "cannot obtain HA status: %s", error); zbx_free(error); @@ -1377,8 +1404,6 @@ static int server_startup(zbx_socket_t *listen_sock, int *ha_stat, int *ha_failo zbx_dc_update_maintenances(); DBclose(); - - zbx_vc_enable(); break; case ZBX_PROCESS_TYPE_POLLER: poller_args.poller_type = ZBX_POLLER_TYPE_NORMAL; @@ -1496,7 +1521,7 @@ static int server_startup(zbx_socket_t *listen_sock, int *ha_stat, int *ha_failo } /* startup/postinit tasks can take a long time, update status */ - if (SUCCEED != (ret = zbx_ha_get_status(ha_stat, ha_failover, &error))) + if (SUCCEED != (ret = zbx_ha_get_status(CONFIG_HA_NODE_NAME, ha_stat, ha_failover, &error))) { zabbix_log(LOG_LEVEL_CRIT, "cannot obtain HA status: %s", error); zbx_free(error); @@ -1528,8 +1553,9 @@ static int server_restart_logger(char **error) ******************************************************************************/ static void server_teardown(zbx_rtc_t *rtc, zbx_socket_t *listen_sock) { - int i; - char *error = NULL; + int i; + char *error = NULL; + zbx_ha_config_t *ha_config = NULL; /* hard kill all zabbix processes, no logging or other */ @@ -1580,7 +1606,7 @@ static void server_teardown(zbx_rtc_t *rtc, zbx_socket_t *listen_sock) zbx_tfc_destroy(); zbx_vc_destroy(); zbx_vmware_destroy(); - free_selfmon_collector(); + zbx_free_selfmon_collector(); free_configuration_cache(); free_database_cache(ZBX_SYNC_NONE); @@ -1588,7 +1614,14 @@ static void server_teardown(zbx_rtc_t *rtc, zbx_socket_t *listen_sock) zbx_locks_enable(); #endif - if (SUCCEED != zbx_ha_start(rtc, ZBX_NODE_STATUS_STANDBY, &error)) + ha_config = zbx_malloc(NULL, sizeof(zbx_ha_config_t)); + ha_config->ha_node_name = CONFIG_HA_NODE_NAME; + ha_config->ha_node_address = CONFIG_NODE_ADDRESS; + ha_config->default_node_ip = CONFIG_LISTEN_IP; + ha_config->default_node_port = CONFIG_LISTEN_PORT; + ha_config->ha_status = ZBX_NODE_STATUS_STANDBY; + + if (SUCCEED != zbx_ha_start(rtc, ha_config, &error)) { zabbix_log(LOG_LEVEL_CRIT, "cannot start HA manager: %s", error); zbx_free(error); @@ -1605,6 +1638,7 @@ int MAIN_ZABBIX_ENTRY(int flags) time_t standby_warning_time; zbx_rtc_t rtc; zbx_timespec_t rtc_timeout = {1, 0}; + zbx_ha_config_t *ha_config = NULL; if (0 != (flags & ZBX_TASK_FLAG_FOREGROUND)) { @@ -1765,6 +1799,7 @@ int MAIN_ZABBIX_ENTRY(int flags) DBcheck_character_set(); zbx_check_db(); + zbx_db_save_server_status(); if (SUCCEED != DBcheck_double_type()) { @@ -1792,7 +1827,14 @@ int MAIN_ZABBIX_ENTRY(int flags) zbx_unset_exit_on_terminate(); - if (SUCCEED != zbx_ha_start(&rtc, ZBX_NODE_STATUS_UNKNOWN, &error)) + ha_config = zbx_malloc(NULL, sizeof(zbx_ha_config_t)); + ha_config->ha_node_name = CONFIG_HA_NODE_NAME; + ha_config->ha_node_address = CONFIG_NODE_ADDRESS; + ha_config->default_node_ip = CONFIG_LISTEN_IP; + ha_config->default_node_port = CONFIG_LISTEN_PORT; + ha_config->ha_status = ZBX_NODE_STATUS_UNKNOWN; + + if (SUCCEED != zbx_ha_start(&rtc, ha_config, &error)) { zabbix_log(LOG_LEVEL_CRIT, "cannot start HA manager: %s", error); zbx_free(error); @@ -1808,14 +1850,14 @@ int MAIN_ZABBIX_ENTRY(int flags) if (SUCCEED == zbx_is_export_enabled(ZBX_FLAG_EXPTYPE_TRENDS)) zbx_trends_export_init("main-process", 0); - if (SUCCEED != zbx_ha_get_status(&ha_status, &ha_failover_delay, &error)) + if (SUCCEED != zbx_ha_get_status(CONFIG_HA_NODE_NAME, &ha_status, &ha_failover_delay, &error)) { zabbix_log(LOG_LEVEL_CRIT, "cannot start server: %s", error); zbx_free(error); zbx_set_exiting_with_fail(); } - zbx_zabbix_stats_init(zbx_get_zabbix_stats_ext); + zbx_zabbix_stats_init(zbx_zabbix_stats_ext_get); zbx_diag_init(diag_add_section_info); if (ZBX_NODE_STATUS_ACTIVE == ha_status) @@ -1835,7 +1877,7 @@ int MAIN_ZABBIX_ENTRY(int flags) if (ZBX_NODE_STATUS_ERROR != ha_status) { - if (ZBX_HA_IS_CLUSTER()) + if (NULL != CONFIG_HA_NODE_NAME && '\0' != *CONFIG_HA_NODE_NAME) { zabbix_log(LOG_LEVEL_INFORMATION, "\"%s\" node started in \"%s\" mode", CONFIG_HA_NODE_NAME, zbx_ha_status_str(ha_status)); @@ -1858,7 +1900,8 @@ int MAIN_ZABBIX_ENTRY(int flags) if (NULL == message || ZBX_IPC_SERVICE_HA_RTC_FIRST <= message->code) { - if (SUCCEED != zbx_ha_dispatch_message(message, &ha_status, &ha_failover_delay, &error)) + if (SUCCEED != zbx_ha_dispatch_message(CONFIG_HA_NODE_NAME, message, &ha_status, + &ha_failover_delay, &error)) { zabbix_log(LOG_LEVEL_CRIT, "HA manager error: %s", error); zbx_set_exiting_with_fail(); diff --git a/src/zabbix_server/service/service_actions.c b/src/zabbix_server/service/service_actions.c index 5edb14734be..fcd8ab56a55 100644 --- a/src/zabbix_server/service/service_actions.c +++ b/src/zabbix_server/service/service_actions.c @@ -58,7 +58,7 @@ static int condition_match_service_name(const zbx_service_action_condition_t *co * name - [IN] the target tag name * * value - [IN] the target tag value (NULL if only tag name are * * being matched * - * op - [IN] the matching operator (CONDITION_OPERATOR_*) * + * op - [IN] the matching operator (ZBX_CONDITION_OPERATOR_*) * * * * Return value: SUCCEED - the tags matches * * FAIL - otherwise * @@ -71,7 +71,7 @@ static int match_tags(const zbx_vector_ptr_t *tags, const char *name, const char { int i, ret, expected_ret; - if (CONDITION_OPERATOR_EQUAL == op || CONDITION_OPERATOR_LIKE == op) + if (ZBX_CONDITION_OPERATOR_EQUAL == op || ZBX_CONDITION_OPERATOR_LIKE == op) { expected_ret = SUCCEED; ret = FAIL; @@ -137,16 +137,16 @@ static const char *service_update_match_condition(const zbx_service_update_t *up switch (condition->conditiontype) { - case CONDITION_TYPE_SERVICE: + case ZBX_CONDITION_TYPE_SERVICE: ret = condition_match_service(condition, update); break; - case CONDITION_TYPE_SERVICE_NAME: + case ZBX_CONDITION_TYPE_SERVICE_NAME: ret = condition_match_service_name(condition, update); break; - case CONDITION_TYPE_EVENT_TAG: + case ZBX_CONDITION_TYPE_EVENT_TAG: ret = condition_match_service_tag(condition, update); break; - case CONDITION_TYPE_EVENT_TAG_VALUE: + case ZBX_CONDITION_TYPE_EVENT_TAG_VALUE: ret = condition_match_service_tag_value(condition, update); break; default: diff --git a/src/zabbix_server/service/service_manager.c b/src/zabbix_server/service/service_manager.c index 0d4fd9210b2..1176eb38b01 100644 --- a/src/zabbix_server/service/service_manager.c +++ b/src/zabbix_server/service/service_manager.c @@ -352,6 +352,8 @@ static void values_eq_clean(void *data) static void add_service_problem_tag_index(zbx_hashset_t *service_problem_tags_index, zbx_service_problem_tag_t *service_problem_tag) { +/* service problem tag operators */ +#define ZBX_SERVICE_TAG_OPERATOR_LIKE 2 zbx_tag_services_t tag_services_local, *tag_services; zbx_values_eq_t value_eq_local, *value_eq; @@ -441,6 +443,7 @@ static void remove_service_problem_tag_index(zbx_hashset_t *service_problem_tags if (0 == tag_services->values.num_data && 0 == tag_services->service_problem_tags_like.values_num) zbx_hashset_remove_direct(service_problem_tags_index, tag_services); } +#undef ZBX_SERVICE_TAG_OPERATOR_LIKE } static void sync_service_problem_tags(zbx_service_manager_t *service_manager, int *updated, int revision) @@ -954,29 +957,29 @@ static int condition_type_compare(const void *d1, const void *d2) static void update_action_formula(zbx_service_action_t *action) { -#define CONDITION_TYPE_NONE 255 +#define ZBX_CONDITION_TYPE_NONE 255 char *formula = NULL; size_t formula_alloc = 0, formula_offset = 0; int i; zbx_service_action_condition_t *condition; - unsigned char last_type = CONDITION_TYPE_NONE; + unsigned char last_type = ZBX_CONDITION_TYPE_NONE; char *ops[] = {NULL, "and", "or"}; zabbix_log(LOG_LEVEL_DEBUG, "In %s() actionid:" ZBX_FS_UI64, __func__, action->actionid); - if (0 == action->conditions.values_num || CONDITION_EVAL_TYPE_EXPRESSION == action->evaltype) + if (0 == action->conditions.values_num || ZBX_ACTION_CONDITION_EVAL_TYPE_EXPRESSION == action->evaltype) goto out; for (i = 0; i < action->conditions.values_num; i++) { condition = (zbx_service_action_condition_t *)action->conditions.values[i]; - if (CONDITION_EVAL_TYPE_AND_OR == action->evaltype) + if (ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR == action->evaltype) { if (last_type != condition->conditiontype) { - if (CONDITION_TYPE_NONE != last_type) + if (ZBX_CONDITION_TYPE_NONE != last_type) zbx_strcpy_alloc(&formula, &formula_alloc, &formula_offset, ") and "); zbx_chrcpy_alloc(&formula, &formula_alloc, &formula_offset, '('); @@ -986,7 +989,7 @@ static void update_action_formula(zbx_service_action_t *action) } else { - if (CONDITION_TYPE_NONE != last_type) + if (ZBX_CONDITION_TYPE_NONE != last_type) { zbx_chrcpy_alloc(&formula, &formula_alloc, &formula_offset, ' '); zbx_strcpy_alloc(&formula, &formula_alloc, &formula_offset, ops[action->evaltype]); @@ -999,7 +1002,7 @@ static void update_action_formula(zbx_service_action_t *action) last_type = condition->conditiontype; } - if (CONDITION_EVAL_TYPE_AND_OR == action->evaltype) + if (ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR == action->evaltype) zbx_chrcpy_alloc(&formula, &formula_alloc, &formula_offset, ')'); zbx_free(action->formula); @@ -1007,7 +1010,7 @@ static void update_action_formula(zbx_service_action_t *action) out: zabbix_log(LOG_LEVEL_DEBUG, "End of %s() formula:%s", __func__, action->formula); -#undef CONDITION_TYPE_NONE +#undef ZBX_CONDITION_TYPE_NONE } static void sync_action_conditions(zbx_service_manager_t *service_manager, int revision) @@ -3275,7 +3278,7 @@ ZBX_THREAD_ENTRY(service_manager_thread, args) zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(program_type), server_num, get_process_type_string(process_type), process_num); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); zbx_setproctitle("%s #%d [connecting to the database]", get_process_type_string(process_type), process_num); @@ -3325,10 +3328,7 @@ ZBX_THREAD_ENTRY(service_manager_thread, args) int updated = 0, revision; if (1 == service_cache_reload_requested) - { zabbix_log(LOG_LEVEL_WARNING, "forced reloading of the service manager cache"); - service_cache_reload_requested = 0; - } do { @@ -3355,6 +3355,13 @@ ZBX_THREAD_ENTRY(service_manager_thread, args) if (0 != updated) recalculate_services(&service_manager); + if (1 == service_cache_reload_requested) + { + zabbix_log(LOG_LEVEL_WARNING, "finished forced reloading of the service manager cache"); + service_cache_reload_requested = 0; + } + + service_update_num += updated; time_flush = time_now; time_now = zbx_time(); @@ -3368,9 +3375,9 @@ ZBX_THREAD_ENTRY(service_manager_thread, args) time_now = zbx_time(); } - update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); ret = zbx_ipc_service_recv(&service, &timeout, &client, &message); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); sec = zbx_time(); zbx_update_env(sec); diff --git a/src/zabbix_server/snmptrapper/snmptrapper.c b/src/zabbix_server/snmptrapper/snmptrapper.c index 7dd3da84ec3..efe668a4f51 100644 --- a/src/zabbix_server/snmptrapper/snmptrapper.c +++ b/src/zabbix_server/snmptrapper/snmptrapper.c @@ -104,7 +104,7 @@ static int process_trap_for_interface(zbx_uint64_t interfaceid, char *trap, zbx_ for (i = 0; i < num; i++) { - init_result(&results[i]); + zbx_init_agent_result(&results[i]); errcodes[i] = FAIL; items[i].key = zbx_strdup(items[i].key, items[i].key_orig); @@ -122,9 +122,9 @@ static int process_trap_for_interface(zbx_uint64_t interfaceid, char *trap, zbx_ continue; } - init_request(&request); + zbx_init_agent_request(&request); - if (SUCCEED != parse_item_key(items[i].key, &request)) + if (SUCCEED != zbx_parse_item_key(items[i].key, &request)) goto next; if (0 != strcmp(get_rkey(&request), "snmptrap")) @@ -163,17 +163,17 @@ static int process_trap_for_interface(zbx_uint64_t interfaceid, char *trap, zbx_ } value_type = (ITEM_VALUE_TYPE_LOG == items[i].value_type ? ITEM_VALUE_TYPE_LOG : ITEM_VALUE_TYPE_TEXT); - set_result_type(&results[i], value_type, trap); + zbx_set_agent_result_type(&results[i], value_type, trap); errcodes[i] = SUCCEED; ret = SUCCEED; next: - free_request(&request); + zbx_free_agent_request(&request); } if (FAIL == ret && -1 != fb) { value_type = (ITEM_VALUE_TYPE_LOG == items[fb].value_type ? ITEM_VALUE_TYPE_LOG : ITEM_VALUE_TYPE_TEXT); - set_result_type(&results[fb], value_type, trap); + zbx_set_agent_result_type(&results[fb], value_type, trap); errcodes[fb] = SUCCEED; ret = SUCCEED; } @@ -207,7 +207,7 @@ next: } zbx_free(items[i].key); - free_result(&results[i]); + zbx_free_agent_result(&results[i]); } zbx_free(results); @@ -600,7 +600,7 @@ ZBX_THREAD_ENTRY(snmptrapper_thread, args) zabbix_log(LOG_LEVEL_DEBUG, "In %s() trapfile:'%s'", __func__, CONFIG_SNMPTRAP_FILE); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); zbx_setproctitle("%s [connecting to the database]", get_process_type_string(process_type)); diff --git a/src/zabbix_server/stats/zabbix_stats.h b/src/zabbix_server/stats/zabbix_stats.h index 10b610ef9f0..608d63ad1f5 100644 --- a/src/zabbix_server/stats/zabbix_stats.h +++ b/src/zabbix_server/stats/zabbix_stats.h @@ -21,7 +21,8 @@ #define ZABBIX_ZABBIX_STATS_H_ #include "zbxjson.h" +#include "zbxstats.h" -void zbx_get_zabbix_stats_ext(struct zbx_json *json); +void zbx_zabbix_stats_ext_get(struct zbx_json *json, const zbx_config_comms_args_t *zbx_config); #endif /* ZABBIX_ZABBIX_STATS_H_ */ diff --git a/src/zabbix_server/stats/zabbix_stats_server.c b/src/zabbix_server/stats/zabbix_stats_server.c index 9efcd61a7b4..566c6405279 100644 --- a/src/zabbix_server/stats/zabbix_stats_server.c +++ b/src/zabbix_server/stats/zabbix_stats_server.c @@ -26,24 +26,28 @@ #include "log.h" #include "zbxtrends.h" #include "zbxha.h" +#include "zbxcomms.h" /****************************************************************************** * * * Purpose: get program type (server) specific internal statistics * * * - * Parameters: json - [IN/OUT] the json data * + * Parameters: json - [IN/OUT] the json data * + * zbx_config - [IN] server config * * * * Comments: This function is used to gather server specific internal * * statistics. * * * ******************************************************************************/ -void zbx_get_zabbix_stats_ext(struct zbx_json *json) +void zbx_zabbix_stats_ext_get(struct zbx_json *json, const zbx_config_comms_args_t *zbx_config) { zbx_vc_stats_t vc_stats; zbx_uint64_t queue_size; char *value, *error = NULL; zbx_tfc_stats_t tcache_stats; + ZBX_UNUSED(zbx_config); + /* zabbix[lld_queue] */ if (SUCCEED == zbx_lld_get_queue_size(&queue_size, &error)) { @@ -111,7 +115,20 @@ void zbx_get_zabbix_stats_ext(struct zbx_json *json) } else { - zabbix_log(LOG_LEVEL_DEBUG, "cannot get HA node data: %s", error); + zabbix_log(LOG_LEVEL_WARNING, "cannot get HA node data: %s", error); + zbx_free(error); + } + + if (SUCCEED == zbx_proxy_discovery_get(&value, &error)) + { + zbx_json_addraw(json, "proxy", value); + zbx_free(value); + } + else + { + zabbix_log(LOG_LEVEL_WARNING, "cannot get proxy data: %s", error); zbx_free(error); } + + zbx_json_close(json); } diff --git a/src/zabbix_server/taskmanager/proxy_tasks.c b/src/zabbix_server/taskmanager/proxy_tasks.c index 8e6a75880bf..7cc65089b59 100644 --- a/src/zabbix_server/taskmanager/proxy_tasks.c +++ b/src/zabbix_server/taskmanager/proxy_tasks.c @@ -20,24 +20,32 @@ #include "zbxdbhigh.h" #include "zbxnum.h" #include "zbxtasks.h" +#include "zbxversion.h" /****************************************************************************** * * * Purpose: get tasks scheduled to be executed on a proxy * * * - * Parameters: tasks - [OUT] the tasks to execute * - * proxy_hostid - [IN] the target proxy * + * Parameters: tasks - [OUT] the tasks to execute * + * proxy_hostid - [IN] the target proxy * + * compatibility - [IN] proxy version compatibility with server * * * * Comments: This function is used by server to get tasks to be sent to the * * specified proxy. Expired tasks are ignored and handled by the * * server task manager. * + * All tasks are disabled on unsupported proxies. Only remote * + * command and check now are supported by outdated proxies. * * * ******************************************************************************/ -void zbx_tm_get_remote_tasks(zbx_vector_ptr_t *tasks, zbx_uint64_t proxy_hostid) +void zbx_tm_get_remote_tasks(zbx_vector_ptr_t *tasks, zbx_uint64_t proxy_hostid, + zbx_proxy_compatibility_t compatibility) { DB_RESULT result; DB_ROW row; + if (ZBX_PROXY_VERSION_UNDEFINED == compatibility || ZBX_PROXY_VERSION_UNSUPPORTED == compatibility) + return; + /* skip tasks past expiry data - task manager will handle them */ result = DBselect( "select t.taskid,t.type,t.clock,t.ttl," @@ -94,7 +102,7 @@ void zbx_tm_get_remote_tasks(zbx_vector_ptr_t *tasks, zbx_uint64_t proxy_hostid) task->data = (void *)zbx_tm_check_now_create(itemid); break; case ZBX_TM_TASK_DATA: - if (SUCCEED == DBis_null(row[17])) + if (ZBX_PROXY_VERSION_OUTDATED == compatibility || SUCCEED == DBis_null(row[17])) { zbx_free(task); continue; diff --git a/src/zabbix_server/taskmanager/taskmanager.c b/src/zabbix_server/taskmanager/taskmanager.c index acf14696ee5..ac1a5d5e845 100644 --- a/src/zabbix_server/taskmanager/taskmanager.c +++ b/src/zabbix_server/taskmanager/taskmanager.c @@ -37,6 +37,7 @@ #include "dbcache.h" #include "zbxnum.h" #include "zbxtime.h" +#include "zbxversion.h" #define ZBX_TM_PROCESS_PERIOD 5 #define ZBX_TM_CLEANUP_PERIOD SEC_PER_HOUR @@ -1010,6 +1011,34 @@ static int tm_expire_generic_tasks(zbx_vector_uint64_t *taskids) /****************************************************************************** * * + * Purpose: get proxy version compatibility with server version * + * * + ******************************************************************************/ +static zbx_proxy_compatibility_t tm_get_proxy_compatibility(zbx_uint64_t proxy_hostid) +{ + zbx_proxy_compatibility_t compatibility = ZBX_PROXY_VERSION_UNDEFINED; + + if (0 < proxy_hostid) + { + DB_ROW row; + DB_RESULT result; + + result = DBselect( + "select compatibility" + " from host_rtdata" + " where hostid=" ZBX_FS_UI64, proxy_hostid); + + if (NULL != (row = DBfetch(result))) + compatibility = (zbx_proxy_compatibility_t)atoi(row[0]); + + DBfree_result(result); + } + + return compatibility; +} + +/****************************************************************************** + * * * Purpose: process task manager tasks depending on task type * * * * Return value: The number of successfully processed tasks * @@ -1020,7 +1049,7 @@ static int tm_process_tasks(zbx_ipc_async_socket_t *rtc, int now) DB_ROW row; DB_RESULT result; int type, processed_num = 0, expired_num = 0, clock, ttl; - zbx_uint64_t taskid; + zbx_uint64_t taskid, proxy_hostid; zbx_vector_uint64_t ack_taskids, check_now_taskids, expire_taskids, data_taskids; zbx_vector_uint64_create(&ack_taskids); @@ -1028,7 +1057,7 @@ static int tm_process_tasks(zbx_ipc_async_socket_t *rtc, int now) zbx_vector_uint64_create(&expire_taskids); zbx_vector_uint64_create(&data_taskids); - result = DBselect("select taskid,type,clock,ttl" + result = DBselect("select taskid,type,clock,ttl,proxy_hostid" " from task" " where status in (%d,%d)" " order by taskid", @@ -1036,10 +1065,13 @@ static int tm_process_tasks(zbx_ipc_async_socket_t *rtc, int now) while (NULL != (row = DBfetch(result))) { + zbx_proxy_compatibility_t compatibility; + ZBX_STR2UINT64(taskid, row[0]); ZBX_STR2UCHAR(type, row[1]); clock = atoi(row[2]); ttl = atoi(row[3]); + ZBX_DBROW2UINT64(proxy_hostid, row[4]); switch (type) { @@ -1049,8 +1081,23 @@ static int tm_process_tasks(zbx_ipc_async_socket_t *rtc, int now) processed_num++; break; case ZBX_TM_TASK_REMOTE_COMMAND: + compatibility = tm_get_proxy_compatibility(proxy_hostid); + + if (ZBX_PROXY_VERSION_UNSUPPORTED == compatibility) + { + zbx_tm_task_t *task; + const char *error = "Remote commands are disabled on unsupported proxies."; + + zabbix_log(LOG_LEVEL_WARNING, "%s", error); + task = zbx_tm_task_create(0, ZBX_TM_TASK_REMOTE_COMMAND_RESULT, + ZBX_TM_STATUS_NEW, zbx_time(), 0, 0); + task->data = zbx_tm_remote_command_result_create(taskid, FAIL, error); + zbx_tm_save_task(task); + zbx_tm_task_free(task); + } + /* both - 'new' and 'in progress' remote tasks should expire */ - if (0 != ttl && clock + ttl < now) + if ((0 != ttl && clock + ttl < now) || (ZBX_PROXY_VERSION_UNSUPPORTED == compatibility)) { tm_expire_remote_command(taskid); expired_num++; @@ -1065,13 +1112,44 @@ static int tm_process_tasks(zbx_ipc_async_socket_t *rtc, int now) zbx_vector_uint64_append(&ack_taskids, taskid); break; case ZBX_TM_TASK_CHECK_NOW: - if (0 != ttl && clock + ttl < now) + compatibility = tm_get_proxy_compatibility(proxy_hostid); + + if (ZBX_PROXY_VERSION_UNSUPPORTED == compatibility) + { + zabbix_log(LOG_LEVEL_WARNING, "Execute now task is disabled on unsupported" + " proxies."); + } + + if ((0 != ttl && clock + ttl < now) || (ZBX_PROXY_VERSION_UNSUPPORTED == compatibility)) zbx_vector_uint64_append(&expire_taskids, taskid); else zbx_vector_uint64_append(&check_now_taskids, taskid); break; case ZBX_TM_TASK_DATA: case ZBX_TM_PROXYDATA: + if (ZBX_TM_TASK_DATA == type) + { + compatibility = tm_get_proxy_compatibility(proxy_hostid); + + if (ZBX_PROXY_VERSION_OUTDATED == compatibility || + ZBX_PROXY_VERSION_UNSUPPORTED == compatibility) + { + zbx_tm_task_t *task; + const char *error = "The requested task is disabled. Proxy major" + " version does not match server major version."; + + zabbix_log(LOG_LEVEL_WARNING, "%s", error); + task = zbx_tm_task_create(0, ZBX_TM_TASK_DATA_RESULT, ZBX_TM_STATUS_NEW, + zbx_time(), 0, 0); + task->data = zbx_tm_data_result_create(taskid, FAIL, error); + zbx_tm_save_task(task); + zbx_tm_task_free(task); + + zbx_vector_uint64_append(&expire_taskids, taskid); + break; + } + } + /* both - 'new' and 'in progress' tasks should expire */ if (0 != ttl && clock + ttl < now) zbx_vector_uint64_append(&expire_taskids, taskid); @@ -1110,12 +1188,6 @@ static int tm_process_tasks(zbx_ipc_async_socket_t *rtc, int now) return processed_num + expired_num; } -static void zbx_cached_proxy_free(zbx_cached_proxy_t *proxy) -{ - zbx_free(proxy->name); - zbx_free(proxy); -} - /****************************************************************************** * * * Purpose: remove old done/expired tasks * @@ -1132,10 +1204,10 @@ static void tm_remove_old_tasks(int now) static void tm_reload_each_proxy_cache(zbx_ipc_async_socket_t *rtc) { int i, notify_proxypollers = 0; - zbx_vector_cached_proxy_t proxies; + zbx_vector_cached_proxy_ptr_t proxies; zbx_vector_ptr_t tasks_active; - zbx_vector_cached_proxy_create(&proxies); + zbx_vector_cached_proxy_ptr_create(&proxies); zbx_vector_ptr_create(&tasks_active); @@ -1187,8 +1259,8 @@ static void tm_reload_each_proxy_cache(zbx_ipc_async_socket_t *rtc) zbx_vector_ptr_destroy(&tasks_active); - zbx_vector_cached_proxy_clear_ext(&proxies, zbx_cached_proxy_free); - zbx_vector_cached_proxy_destroy(&proxies); + zbx_vector_cached_proxy_ptr_clear_ext(&proxies, zbx_cached_proxy_free); + zbx_vector_cached_proxy_ptr_destroy(&proxies); } /****************************************************************************** @@ -1321,7 +1393,7 @@ ZBX_THREAD_ENTRY(taskmanager_thread, args) zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(program_type), server_num, get_process_type_string(process_type), process_num); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); zbx_setproctitle("%s [connecting to the database]", get_process_type_string(process_type)); DBconnect(ZBX_DB_CONNECT_NORMAL); diff --git a/src/zabbix_server/timer/timer.c b/src/zabbix_server/timer/timer.c index bc783a70a10..345a387236a 100644 --- a/src/zabbix_server/timer/timer.c +++ b/src/zabbix_server/timer/timer.c @@ -572,7 +572,7 @@ ZBX_THREAD_ENTRY(timer_thread, args) zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(program_type), server_num, get_process_type_string(process_type), process_num); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); zbx_setproctitle("%s #%d [connecting to the database]", get_process_type_string(process_type), process_num); zbx_strcpy_alloc(&info, &info_alloc, &info_offset, "started"); diff --git a/src/zabbix_server/trapper/Makefile.am b/src/zabbix_server/trapper/Makefile.am index 05947d08f9e..1b5a820967a 100644 --- a/src/zabbix_server/trapper/Makefile.am +++ b/src/zabbix_server/trapper/Makefile.am @@ -5,8 +5,6 @@ noinst_LIBRARIES = libzbxtrapper.a libzbxtrapper_server.a libzbxtrapper_proxy.a libzbxtrapper_a_SOURCES = \ active.c \ active.h \ - proxyconfig.c \ - proxyconfig.h \ trapper_auth.c \ trapper_auth.h \ nodecommand.c \ @@ -33,3 +31,7 @@ libzbxtrapper_proxy_a_SOURCES = \ libzbxtrapper_a_CFLAGS = \ $(LIBXML2_CFLAGS) + +libzbxtrapper_server_a_CFLAGS = -I$(top_srcdir)/src/zabbix_server + +libzbxtrapper_proxy_a_CFLAGS = -I$(top_srcdir)/src/zabbix_proxy diff --git a/src/zabbix_server/trapper/active.c b/src/zabbix_server/trapper/active.c index 8c51a26b200..ccb8117ecf6 100644 --- a/src/zabbix_server/trapper/active.c +++ b/src/zabbix_server/trapper/active.c @@ -28,6 +28,7 @@ #include "zbxcomms.h" #include "zbxip.h" #include "zbxsysinfo.h" +#include "zbxversion.h" extern unsigned char program_type; @@ -172,7 +173,7 @@ out: ******************************************************************************/ static int get_hostid_by_host(const zbx_socket_t *sock, const char *host, const char *ip, unsigned short port, const char *host_metadata, zbx_conn_flags_t flag, const char *interface, zbx_uint64_t *hostid, - zbx_uint32_t *revision, char *error) + zbx_uint64_t *revision, char *error) { #define PROXY_AUTO_REGISTRATION_HEARTBEAT 120 char *ch_error; @@ -256,8 +257,7 @@ int send_list_of_active_checks(zbx_socket_t *sock, char *request) char *host = NULL, *p, *buffer = NULL, error[MAX_STRING_LEN]; size_t buffer_alloc = 8 * ZBX_KIBIBYTE, buffer_offset = 0; int ret = FAIL, i, num = 0; - zbx_uint64_t hostid; - zbx_uint32_t revision; + zbx_uint64_t hostid, revision; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); @@ -392,9 +392,9 @@ static void zbx_itemkey_extract_global_regexps(const char *key, zbx_vector_str_t else return; - init_request(&request); + zbx_init_agent_request(&request); - if(SUCCEED != parse_item_key(key, &request)) + if(SUCCEED != zbx_parse_item_key(key, &request)) goto out; /* "params" parameter */ @@ -416,7 +416,7 @@ static void zbx_itemkey_extract_global_regexps(const char *key, zbx_vector_str_t zbx_vector_str_append_uniq(regexps, param + 1); } out: - free_request(&request); + zbx_free_agent_request(&request); } /****************************************************************************** @@ -436,8 +436,7 @@ int send_list_of_active_checks_json(zbx_socket_t *sock, struct zbx_json_parse *j error[MAX_STRING_LEN], *host_metadata = NULL, *interface = NULL, *buffer = NULL; struct zbx_json json; int ret = FAIL, i, version, num = 0; - zbx_uint64_t hostid; - zbx_uint32_t revision, agent_config_revision; + zbx_uint64_t hostid, revision, agent_config_revision; size_t host_metadata_alloc = 1; /* for at least NUL-terminated string */ size_t interface_alloc = 1; /* for at least NUL-terminated string */ size_t buffer_size, reserved = 0; @@ -510,29 +509,26 @@ int send_list_of_active_checks_json(zbx_socket_t *sock, struct zbx_json_parse *j { agent_config_revision = 0; } - else if (FAIL == zbx_is_uint32(tmp, &agent_config_revision)) + else if (FAIL == zbx_is_uint64(tmp, &agent_config_revision)) { zbx_snprintf(error, MAX_STRING_LEN, "\"%s\" is not a valid revision", tmp); goto error; } - if (FAIL == get_hostid_by_host(sock, host, ip, port, host_metadata, flag, interface, &hostid, &revision, - error)) - { + if (FAIL == get_hostid_by_host(sock, host, ip, port, host_metadata, flag, interface, &hostid, &revision, error)) goto error; - } if (SUCCEED != zbx_json_value_by_name(jp, ZBX_PROTO_TAG_VERSION, tmp, sizeof(tmp), NULL) || - FAIL == (version = zbx_get_component_version(tmp))) + FAIL == (version = zbx_get_component_version_without_patch(tmp))) { - version = ZBX_COMPONENT_VERSION(4, 2); + version = ZBX_COMPONENT_VERSION(4, 2, 0); } if (SUCCEED == zbx_json_value_by_name(jp, ZBX_PROTO_TAG_SESSION, tmp, sizeof(tmp), NULL)) { size_t token_len; - if (zbx_get_token_len() != (token_len = strlen(tmp))) + if (ZBX_SESSION_TOKEN_SIZE != (token_len = strlen(tmp))) { zbx_snprintf(error, MAX_STRING_LEN, "invalid session token length %d", (int)token_len); goto error; @@ -593,7 +589,7 @@ int send_list_of_active_checks_json(zbx_socket_t *sock, struct zbx_json_parse *j zbx_json_addobject(&json, NULL); zbx_json_addstring(&json, ZBX_PROTO_TAG_KEY, dc_items[i].key, ZBX_JSON_TYPE_STRING); - if (ZBX_COMPONENT_VERSION(4,4) > version) + if (ZBX_COMPONENT_VERSION(4, 4, 0) > version) { if (0 != strcmp(dc_items[i].key, dc_items[i].key_orig)) { @@ -635,7 +631,7 @@ int send_list_of_active_checks_json(zbx_socket_t *sock, struct zbx_json_parse *j zbx_json_close(&json); - if (ZBX_COMPONENT_VERSION(4,4) == version || ZBX_COMPONENT_VERSION(5,0) == version) + if (ZBX_COMPONENT_VERSION(4, 4, 0) == version || ZBX_COMPONENT_VERSION(5, 0, 0) == version) zbx_json_adduint64(&json, ZBX_PROTO_TAG_REFRESH_UNSUPPORTED, 600); DCget_expressions_by_names(®exps, (const char * const *)names.values, names.values_num); diff --git a/src/zabbix_server/trapper/proxyconfig.c b/src/zabbix_server/trapper/proxyconfig.c deleted file mode 100644 index 618d976453a..00000000000 --- a/src/zabbix_server/trapper/proxyconfig.c +++ /dev/null @@ -1,165 +0,0 @@ -/* -** Zabbix -** Copyright (C) 2001-2022 Zabbix SIA -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -**/ - -#include "proxyconfig.h" - -#include "zbxdbhigh.h" -#include "log.h" -#include "proxy.h" -#include "zbxrtc.h" -#include "zbxcommshigh.h" - -#include "zbxcompress.h" - -/****************************************************************************** - * * - * Purpose: send configuration tables to the proxy from server * - * (for active proxies) * - * * - ******************************************************************************/ -void send_proxyconfig(zbx_socket_t *sock, struct zbx_json_parse *jp) -{ - char *error = NULL, *buffer = NULL; - struct zbx_json j; - DC_PROXY proxy; - int ret, flags = ZBX_TCP_PROTOCOL; - size_t buffer_size, reserved = 0; - - zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); - - if (SUCCEED != get_active_proxy_from_request(jp, &proxy, &error)) - { - zabbix_log(LOG_LEVEL_WARNING, "cannot parse proxy configuration data request from active proxy at" - " \"%s\": %s", sock->peer, error); - goto out; - } - - if (SUCCEED != zbx_proxy_check_permissions(&proxy, sock, &error)) - { - zabbix_log(LOG_LEVEL_WARNING, "cannot accept connection from proxy \"%s\" at \"%s\", allowed address:" - " \"%s\": %s", proxy.host, sock->peer, proxy.proxy_address, error); - goto out; - } - - zbx_update_proxy_data(&proxy, zbx_get_proxy_protocol_version(jp), (int)time(NULL), - (0 != (sock->protocol & ZBX_TCP_COMPRESS) ? 1 : 0), ZBX_FLAGS_PROXY_DIFF_UPDATE_CONFIG); - - if (0 != proxy.auto_compress) - flags |= ZBX_TCP_COMPRESS; - - zbx_json_init(&j, ZBX_JSON_STAT_BUF_LEN); - - if (SUCCEED != get_proxyconfig_data(proxy.hostid, &j, &error)) - { - zbx_send_response_ext(sock, FAIL, error, NULL, flags, CONFIG_TIMEOUT); - zabbix_log(LOG_LEVEL_WARNING, "cannot collect configuration data for proxy \"%s\" at \"%s\": %s", - proxy.host, sock->peer, error); - goto clean; - } - - zabbix_log(LOG_LEVEL_DEBUG, "%s", j.buffer); - - if (0 != proxy.auto_compress) - { - if (SUCCEED != zbx_compress(j.buffer, j.buffer_size, &buffer, &buffer_size)) - { - zabbix_log(LOG_LEVEL_ERR,"cannot compress data: %s", zbx_compress_strerror()); - goto clean; - } - - reserved = j.buffer_size; - - zbx_json_free(&j); /* json buffer can be large, free as fast as possible */ - - zabbix_log(LOG_LEVEL_WARNING, "sending configuration data to proxy \"%s\" at \"%s\", datalen " - ZBX_FS_SIZE_T ", bytes " ZBX_FS_SIZE_T " with compression ratio %.1f", proxy.host, - sock->peer, (zbx_fs_size_t)reserved, (zbx_fs_size_t)buffer_size, - (double)reserved / (double)buffer_size); - - ret = zbx_tcp_send_ext(sock, buffer, buffer_size, reserved, (unsigned char)flags, - CONFIG_TRAPPER_TIMEOUT); - } - else - { - zabbix_log(LOG_LEVEL_WARNING, "sending configuration data to proxy \"%s\" at \"%s\", datalen " - ZBX_FS_SIZE_T, proxy.host, sock->peer, (zbx_fs_size_t)j.buffer_size); - - ret = zbx_tcp_send_ext(sock, j.buffer, strlen(j.buffer), 0, (unsigned char)flags, - CONFIG_TRAPPER_TIMEOUT); - } - - if (SUCCEED != ret) - { - zabbix_log(LOG_LEVEL_WARNING, "cannot send configuration data to proxy \"%s\" at \"%s\": %s", - proxy.host, sock->peer, zbx_socket_strerror()); - } -clean: - zbx_json_free(&j); -out: - zbx_free(error); - zbx_free(buffer); - - zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); -} - -/****************************************************************************** - * * - * Purpose: receive configuration tables from server (passive proxies) * - * * - ******************************************************************************/ -void recv_proxyconfig(zbx_socket_t *sock, struct zbx_json_parse *jp, const zbx_config_tls_t *zbx_config_tls) -{ - struct zbx_json_parse jp_data, jp_kvs_paths = {0}; - int ret; - - zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); - - if (SUCCEED != (ret = zbx_json_brackets_by_name(jp, ZBX_PROTO_TAG_DATA, &jp_data))) - { - zabbix_log(LOG_LEVEL_WARNING, "cannot parse proxy configuration data received from server at" - " \"%s\": %s", sock->peer, zbx_json_strerror()); - zbx_send_proxy_response(sock, ret, zbx_json_strerror(), CONFIG_TIMEOUT); - goto out; - } - - if (SUCCEED != check_access_passive_proxy(sock, ZBX_SEND_RESPONSE, "configuration update", zbx_config_tls)) - { - goto out; - } - - if (SUCCEED == process_proxyconfig(&jp_data, &jp_kvs_paths)) - { - char *error = NULL; - - if (SUCCEED == zbx_rtc_reload_config_cache(&error)) - { - if (NULL != jp_kvs_paths.start) - DCsync_kvs_paths(&jp_kvs_paths); - } - else - { - THIS_SHOULD_NEVER_HAPPEN; - zabbix_log(LOG_LEVEL_WARNING, "cannot send message to configuration syncer: %s", error); - zbx_free(error); - } - } - zbx_send_proxy_response(sock, ret, NULL, CONFIG_TIMEOUT); -out: - zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); -} diff --git a/src/zabbix_server/trapper/proxydata.c b/src/zabbix_server/trapper/proxydata.c index 99a3cceded6..e964a3ff40b 100644 --- a/src/zabbix_server/trapper/proxydata.c +++ b/src/zabbix_server/trapper/proxydata.c @@ -62,7 +62,7 @@ int zbx_send_proxy_data_response(const DC_PROXY *proxy, zbx_socket_t *sock, cons if (SUCCEED == status) { zbx_json_addstring(&json, ZBX_PROTO_TAG_RESPONSE, ZBX_PROTO_VALUE_SUCCESS, ZBX_JSON_TYPE_STRING); - zbx_tm_get_remote_tasks(&tasks, proxy->hostid); + zbx_tm_get_remote_tasks(&tasks, proxy->hostid, proxy->compatibility); } else zbx_json_addstring(&json, ZBX_PROTO_TAG_RESPONSE, ZBX_PROTO_VALUE_FAILED, ZBX_JSON_TYPE_STRING); @@ -128,8 +128,8 @@ static int proxy_data_no_history(const struct zbx_json_parse *jp) ******************************************************************************/ void zbx_recv_proxy_data(zbx_socket_t *sock, struct zbx_json_parse *jp, zbx_timespec_t *ts) { - int ret = FAIL, upload_status = 0, status, version, responded = 0; - char *error = NULL; + int ret = FAIL, upload_status = 0, status, version_int, responded = 0; + char *error = NULL, *version_str = NULL; DC_PROXY proxy; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); @@ -148,11 +148,14 @@ void zbx_recv_proxy_data(zbx_socket_t *sock, struct zbx_json_parse *jp, zbx_time goto out; } - version = zbx_get_proxy_protocol_version(jp); + version_str = zbx_get_proxy_protocol_version_str(jp); + version_int = zbx_get_proxy_protocol_version_int(version_str); - if (SUCCEED != zbx_check_protocol_version(&proxy, version)) + if (SUCCEED != zbx_check_protocol_version(&proxy, version_int)) { - goto out; + upload_status = ZBX_PROXY_UPLOAD_DISABLED; + error = zbx_strdup(error, "current proxy version is not supported by server"); + goto reply; } if (FAIL == (ret = zbx_hc_check_proxy(proxy.hostid))) @@ -181,10 +184,9 @@ void zbx_recv_proxy_data(zbx_socket_t *sock, struct zbx_json_parse *jp, zbx_time ret = FAIL; goto out; } - +reply: zbx_send_proxy_data_response(&proxy, sock, error, ret, upload_status); responded = 1; - out: if (SUCCEED == status) /* moved the unpredictable long operation to the end */ /* we are trying to save info about lastaccess to detect communication problem */ @@ -196,7 +198,7 @@ out: else lastaccess = ts->sec; - zbx_update_proxy_data(&proxy, version, lastaccess, + zbx_update_proxy_data(&proxy, version_str, version_int, lastaccess, (0 != (sock->protocol & ZBX_TCP_COMPRESS) ? 1 : 0), 0); } @@ -211,6 +213,7 @@ out: } zbx_free(error); + zbx_free(version_str); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); } @@ -248,10 +251,10 @@ static int send_data_to_server(zbx_socket_t *sock, char **buffer, size_t buffer_ * * * Parameters: sock - [IN] the connection socket * * ts - [IN] the connection timestamp * - * zbx_config_tls - [IN] * + * zbx_config - [IN] proxy config * * * ******************************************************************************/ -void zbx_send_proxy_data(zbx_socket_t *sock, zbx_timespec_t *ts, const zbx_config_tls_t *zbx_config_tls) +void zbx_send_proxy_data(zbx_socket_t *sock, zbx_timespec_t *ts, const zbx_config_comms_args_t *zbx_config) { struct zbx_json j; zbx_uint64_t areg_lastid = 0, history_lastid = 0, discovery_lastid = 0; @@ -263,7 +266,8 @@ void zbx_send_proxy_data(zbx_socket_t *sock, zbx_timespec_t *ts, const zbx_confi zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); - if (SUCCEED != check_access_passive_proxy(sock, ZBX_DO_NOT_SEND_RESPONSE, "proxy data request", zbx_config_tls)) + if (SUCCEED != check_access_passive_proxy(sock, ZBX_DO_NOT_SEND_RESPONSE, "proxy data request", + zbx_config->zbx_config_tls)) { /* do not send any reply to server in this case as the server expects proxy data */ goto out; @@ -280,7 +284,7 @@ void zbx_send_proxy_data(zbx_socket_t *sock, zbx_timespec_t *ts, const zbx_confi proxy_get_host_active_availability(&j); zbx_vector_ptr_create(&tasks); - zbx_tm_get_remote_tasks(&tasks, 0); + zbx_tm_get_remote_tasks(&tasks, 0, 0); if (0 != tasks.values_num) zbx_tm_json_serialize_tasks(&j, &tasks); @@ -377,10 +381,10 @@ out: * * * Parameters: sock - [IN] the connection socket * * ts - [IN] the connection timestamp * - * zbx_config_tls - [IN] * + * zbx_config - [IN] proxy config * * * ******************************************************************************/ -void zbx_send_task_data(zbx_socket_t *sock, zbx_timespec_t *ts, const zbx_config_tls_t *zbx_config_tls) +void zbx_send_task_data(zbx_socket_t *sock, zbx_timespec_t *ts, const zbx_config_comms_args_t *zbx_config) { struct zbx_json j; char *error = NULL, *buffer = NULL; @@ -390,7 +394,8 @@ void zbx_send_task_data(zbx_socket_t *sock, zbx_timespec_t *ts, const zbx_config zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); - if (SUCCEED != check_access_passive_proxy(sock, ZBX_DO_NOT_SEND_RESPONSE, "proxy data request", zbx_config_tls)) + if (SUCCEED != check_access_passive_proxy(sock, ZBX_DO_NOT_SEND_RESPONSE, "proxy data request", + zbx_config->zbx_config_tls)) { /* do not send any reply to server in this case as the server expects proxy data */ goto out; @@ -399,7 +404,7 @@ void zbx_send_task_data(zbx_socket_t *sock, zbx_timespec_t *ts, const zbx_config zbx_json_init(&j, ZBX_JSON_STAT_BUF_LEN); zbx_vector_ptr_create(&tasks); - zbx_tm_get_remote_tasks(&tasks, 0); + zbx_tm_get_remote_tasks(&tasks, 0, 0); if (0 != tasks.values_num) zbx_tm_json_serialize_tasks(&j, &tasks); diff --git a/src/zabbix_server/trapper/proxydata.h b/src/zabbix_server/trapper/proxydata.h index af7f0323332..b7ee7f6b3ad 100644 --- a/src/zabbix_server/trapper/proxydata.h +++ b/src/zabbix_server/trapper/proxydata.h @@ -27,8 +27,8 @@ extern int CONFIG_TIMEOUT; extern int CONFIG_TRAPPER_TIMEOUT; void zbx_recv_proxy_data(zbx_socket_t *sock, struct zbx_json_parse *jp, zbx_timespec_t *ts); -void zbx_send_proxy_data(zbx_socket_t *sock, zbx_timespec_t *ts, const zbx_config_tls_t *zbx_config_tls); -void zbx_send_task_data(zbx_socket_t *sock, zbx_timespec_t *ts, const zbx_config_tls_t *zbx_config_tls); +void zbx_send_proxy_data(zbx_socket_t *sock, zbx_timespec_t *ts, const zbx_config_comms_args_t *zbx_config); +void zbx_send_task_data(zbx_socket_t *sock, zbx_timespec_t *ts, const zbx_config_comms_args_t *zbx_config); int zbx_send_proxy_data_response(const DC_PROXY *proxy, zbx_socket_t *sock, const char *info, int status, int upload_status); diff --git a/src/zabbix_server/trapper/trapper.c b/src/zabbix_server/trapper/trapper.c index c747ba8618c..2dcbf7ae59e 100644 --- a/src/zabbix_server/trapper/trapper.c +++ b/src/zabbix_server/trapper/trapper.c @@ -25,7 +25,6 @@ #include "zbxself.h" #include "active.h" #include "nodecommand.h" -#include "proxyconfig.h" #include "proxydata.h" #include "zbxnix.h" #include "zbxcommshigh.h" @@ -39,6 +38,7 @@ #include "zbxxml.h" #include "base64.h" #include "zbxtime.h" +#include "zbxstats.h" #ifdef HAVE_NETSNMP # include "zbxrtc.h" @@ -47,8 +47,9 @@ #define ZBX_MAX_SECTION_ENTRIES 4 #define ZBX_MAX_ENTRY_ATTRIBUTES 3 +static zbx_get_program_type_f zbx_get_program_type_cb = NULL; + extern ZBX_THREAD_LOCAL unsigned char process_type; -extern unsigned char program_type; extern ZBX_THREAD_LOCAL int server_num, process_num; extern size_t (*find_psk_in_cache)(const unsigned char *, unsigned char *, unsigned int *); @@ -164,43 +165,31 @@ static void recv_senderhistory(zbx_socket_t *sock, struct zbx_json_parse *jp, zb * * * Purpose: process heartbeat sent by proxy servers * * * - * Return value: SUCCEED - processed successfully * - * FAIL - an error occurred * - * * ******************************************************************************/ static void recv_proxy_heartbeat(zbx_socket_t *sock, struct zbx_json_parse *jp) { char *error = NULL; - int ret, flags = ZBX_TCP_PROTOCOL; DC_PROXY proxy; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); - if (SUCCEED != (ret = get_active_proxy_from_request(jp, &proxy, &error))) + if (SUCCEED != get_active_proxy_from_request(jp, &proxy, &error)) { zabbix_log(LOG_LEVEL_WARNING, "cannot parse heartbeat from active proxy at \"%s\": %s", sock->peer, error); goto out; } - if (SUCCEED != (ret = zbx_proxy_check_permissions(&proxy, sock, &error))) + if (SUCCEED != zbx_proxy_check_permissions(&proxy, sock, &error)) { zabbix_log(LOG_LEVEL_WARNING, "cannot accept connection from proxy \"%s\" at \"%s\", allowed address:" " \"%s\": %s", proxy.host, sock->peer, proxy.proxy_address, error); goto out; } - zbx_update_proxy_data(&proxy, zbx_get_proxy_protocol_version(jp), time(NULL), - (0 != (sock->protocol & ZBX_TCP_COMPRESS) ? 1 : 0), ZBX_FLAGS_PROXY_DIFF_UPDATE_HEARTBEAT); - - if (0 != proxy.auto_compress) - flags |= ZBX_TCP_COMPRESS; + zabbix_log(LOG_LEVEL_DEBUG, "ignoring heartbeat from active proxy \"%s\" at \"%s\": proxy heartbeats" + " are deprecated", proxy.host, sock->peer); out: - if (FAIL == ret && 0 != (sock->protocol & ZBX_TCP_COMPRESS)) - flags |= ZBX_TCP_COMPRESS; - - zbx_send_response_ext(sock, ret, error, NULL, flags, CONFIG_TIMEOUT); - zbx_free(error); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); @@ -856,14 +845,16 @@ out: * * * Purpose: process Zabbix stats request * * * - * Parameters: sock - [IN] the request socket * - * jp - [IN] the request data * + * Parameters: sock - [IN] the request socket * + * jp - [IN] the request data * +* zbx_config - [IN] server/proxy config * * * * Return value: SUCCEED - processed successfully * * FAIL - an error occurred * * * ******************************************************************************/ -static int send_internal_stats_json(zbx_socket_t *sock, const struct zbx_json_parse *jp) +static int send_internal_stats_json(zbx_socket_t *sock, const struct zbx_json_parse *jp, + const zbx_config_comms_args_t *zbx_config) { struct zbx_json json; char type[MAX_STRING_LEN], error[MAX_STRING_LEN]; @@ -923,7 +914,7 @@ static int send_internal_stats_json(zbx_socket_t *sock, const struct zbx_json_pa zbx_json_addstring(&json, ZBX_PROTO_TAG_RESPONSE, ZBX_PROTO_VALUE_SUCCESS, ZBX_JSON_TYPE_STRING); zbx_json_addobject(&json, ZBX_PROTO_TAG_DATA); - zbx_get_zabbix_stats(&json); + zbx_zabbix_stats_get(&json, zbx_config); zbx_json_close(&json); } @@ -941,18 +932,6 @@ out: return ret; } -static void active_passive_misconfig(zbx_socket_t *sock) -{ - char *msg = NULL; - - msg = zbx_dsprintf(msg, "misconfiguration error: the proxy is running in the active mode but server at \"%s\"" - " sends requests to it as to proxy in passive mode", sock->peer); - - zabbix_log(LOG_LEVEL_WARNING, "%s", msg); - zbx_send_proxy_response(sock, FAIL, msg, CONFIG_TIMEOUT); - zbx_free(msg); -} - static int process_active_check_heartbeat(struct zbx_json_parse *jp) { char host[ZBX_MAX_HOSTNAME_LEN * ZBX_MAX_BYTES_IN_UTF8_CHAR + 1], @@ -1077,7 +1056,7 @@ static int comms_parse_response(char *xml, char *host, size_t host_len, char *ke } static int process_trap(zbx_socket_t *sock, char *s, ssize_t bytes_received, zbx_timespec_t *ts, - const zbx_config_tls_t *zbx_config_tls) + const zbx_config_comms_args_t *zbx_config) { int ret = SUCCEED; @@ -1101,111 +1080,86 @@ static int process_trap(zbx_socket_t *sock, char *s, ssize_t bytes_received, zbx if (SUCCEED != zbx_json_value_by_name(&jp, ZBX_PROTO_TAG_REQUEST, value, sizeof(value), NULL)) return FAIL; - if (0 == strcmp(value, ZBX_PROTO_VALUE_PROXY_CONFIG)) + if (ZBX_GIBIBYTE < bytes_received && 0 != strcmp(value, ZBX_PROTO_VALUE_PROXY_CONFIG)) { - if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER)) - { - send_proxyconfig(sock, &jp); - } - else if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_PASSIVE)) - { - zabbix_log(LOG_LEVEL_WARNING, "received configuration data from server" - " at \"%s\", datalen " ZBX_FS_SIZE_T, - sock->peer, (zbx_fs_size_t)(jp.end - jp.start + 1)); - recv_proxyconfig(sock, &jp, zbx_config_tls); - } - else if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_ACTIVE)) - { - /* This is a misconfiguration: the proxy is configured in active mode */ - /* but server sends requests to it as to a proxy in passive mode. To */ - /* prevent logging of this problem for every request we report it */ - /* only when the server sends configuration to the proxy and ignore */ - /* it for other requests. */ - active_passive_misconfig(sock); - } + zabbix_log(LOG_LEVEL_WARNING, "message size " ZBX_FS_I64 " exceeds the maximum size " + ZBX_FS_UI64 " for request \"%s\" received from \"%s\"", bytes_received, + (zbx_uint64_t)ZBX_GIBIBYTE, value, sock->peer); + return FAIL; } - else - { - if (ZBX_GIBIBYTE < bytes_received) - { - zabbix_log(LOG_LEVEL_WARNING, "message size " ZBX_FS_I64 " exceeds the maximum size " - ZBX_FS_UI64 " for request \"%s\" received from \"%s\"", bytes_received, - (zbx_uint64_t)ZBX_GIBIBYTE, value, sock->peer); - return FAIL; - } - if (0 == strcmp(value, ZBX_PROTO_VALUE_AGENT_DATA)) - { - recv_agenthistory(sock, &jp, ts); - } - else if (0 == strcmp(value, ZBX_PROTO_VALUE_SENDER_DATA)) - { - recv_senderhistory(sock, &jp, ts); - } - else if (0 == strcmp(value, ZBX_PROTO_VALUE_PROXY_TASKS)) - { - if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_PASSIVE)) - zbx_send_task_data(sock, ts, zbx_config_tls); - } - else if (0 == strcmp(value, ZBX_PROTO_VALUE_PROXY_DATA)) - { - if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER)) - zbx_recv_proxy_data(sock, &jp, ts); - else if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_PASSIVE)) - zbx_send_proxy_data(sock, ts, zbx_config_tls); - } - else if (0 == strcmp(value, ZBX_PROTO_VALUE_PROXY_HEARTBEAT)) - { - if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER)) - recv_proxy_heartbeat(sock, &jp); - } - else if (0 == strcmp(value, ZBX_PROTO_VALUE_GET_ACTIVE_CHECKS)) - { - ret = send_list_of_active_checks_json(sock, &jp); - } - else if (0 == strcmp(value, ZBX_PROTO_VALUE_COMMAND)) - { - if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER)) - ret = node_process_command(sock, s, &jp); - } - else if (0 == strcmp(value, ZBX_PROTO_VALUE_GET_QUEUE)) - { - if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER)) - ret = recv_getqueue(sock, &jp); - } - else if (0 == strcmp(value, ZBX_PROTO_VALUE_GET_STATUS)) - { - if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER)) - ret = recv_getstatus(sock, &jp); - } - else if (0 == strcmp(value, ZBX_PROTO_VALUE_ZABBIX_STATS)) - { - ret = send_internal_stats_json(sock, &jp); - } - else if (0 == strcmp(value, ZBX_PROTO_VALUE_PREPROCESSING_TEST)) - { - if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER)) - ret = zbx_trapper_preproc_test(sock, &jp); - } - else if (0 == strcmp(value, ZBX_PROTO_VALUE_EXPRESSIONS_EVALUATE)) - { - if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER)) - ret = zbx_trapper_expressions_evaluate(sock, &jp); - } - else if (0 == strcmp(value, ZBX_PROTO_VALUE_ZABBIX_ITEM_TEST)) - { - if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER)) - zbx_trapper_item_test(sock, &jp); - } - else if (0 == strcmp(value, ZBX_PROTO_VALUE_ACTIVE_CHECK_HEARTBEAT)) - { - ret = process_active_check_heartbeat(&jp); - } - else if (SUCCEED != trapper_process_request(value, sock, &jp)) - { - zabbix_log(LOG_LEVEL_WARNING, "unknown request received from \"%s\": [%s]", sock->peer, - value); - } + if (0 == strcmp(value, ZBX_PROTO_VALUE_AGENT_DATA)) + { + recv_agenthistory(sock, &jp, ts); + } + else if (0 == strcmp(value, ZBX_PROTO_VALUE_SENDER_DATA)) + { + recv_senderhistory(sock, &jp, ts); + } + else if (0 == strcmp(value, ZBX_PROTO_VALUE_PROXY_TASKS)) + { + if (0 != (zbx_get_program_type_cb() & ZBX_PROGRAM_TYPE_PROXY_PASSIVE)) + zbx_send_task_data(sock, ts, zbx_config); + } + else if (0 == strcmp(value, ZBX_PROTO_VALUE_PROXY_DATA)) + { + if (0 != (zbx_get_program_type_cb() & ZBX_PROGRAM_TYPE_SERVER)) + zbx_recv_proxy_data(sock, &jp, ts); + else if (0 != (zbx_get_program_type_cb() & ZBX_PROGRAM_TYPE_PROXY_PASSIVE)) + zbx_send_proxy_data(sock, ts, zbx_config); + } + else if (0 == strcmp(value, ZBX_PROTO_VALUE_PROXY_HEARTBEAT)) + { + if (0 != (zbx_get_program_type_cb() & ZBX_PROGRAM_TYPE_SERVER)) + recv_proxy_heartbeat(sock, &jp); + } + else if (0 == strcmp(value, ZBX_PROTO_VALUE_GET_ACTIVE_CHECKS)) + { + ret = send_list_of_active_checks_json(sock, &jp); + } + else if (0 == strcmp(value, ZBX_PROTO_VALUE_COMMAND)) + { + if (0 != (zbx_get_program_type_cb() & ZBX_PROGRAM_TYPE_SERVER)) + ret = node_process_command(sock, s, &jp); + } + else if (0 == strcmp(value, ZBX_PROTO_VALUE_GET_QUEUE)) + { + if (0 != (zbx_get_program_type_cb() & ZBX_PROGRAM_TYPE_SERVER)) + ret = recv_getqueue(sock, &jp); + } + else if (0 == strcmp(value, ZBX_PROTO_VALUE_GET_STATUS)) + { + if (0 != (zbx_get_program_type_cb() & ZBX_PROGRAM_TYPE_SERVER)) + ret = recv_getstatus(sock, &jp); + } + else if (0 == strcmp(value, ZBX_PROTO_VALUE_ZABBIX_STATS)) + { + ret = send_internal_stats_json(sock, &jp, zbx_config); + } + else if (0 == strcmp(value, ZBX_PROTO_VALUE_PREPROCESSING_TEST)) + { + if (0 != (zbx_get_program_type_cb() & ZBX_PROGRAM_TYPE_SERVER)) + ret = zbx_trapper_preproc_test(sock, &jp); + } + else if (0 == strcmp(value, ZBX_PROTO_VALUE_EXPRESSIONS_EVALUATE)) + { + if (0 != (zbx_get_program_type_cb() & ZBX_PROGRAM_TYPE_SERVER)) + ret = zbx_trapper_expressions_evaluate(sock, &jp); + } + else if (0 == strcmp(value, ZBX_PROTO_VALUE_ZABBIX_ITEM_TEST)) + { + if (0 != (zbx_get_program_type_cb() & ZBX_PROGRAM_TYPE_SERVER)) + zbx_trapper_item_test(sock, &jp, zbx_config); + } + else if (0 == strcmp(value, ZBX_PROTO_VALUE_ACTIVE_CHECK_HEARTBEAT)) + { + ret = process_active_check_heartbeat(&jp); + } + else if (SUCCEED != trapper_process_request(value, sock, &jp, zbx_config->zbx_config_tls, + zbx_get_program_type_cb)) + { + zabbix_log(LOG_LEVEL_WARNING, "unknown request received from \"%s\": [%s]", sock->peer, + value); } } else if (0 == strncmp(s, "ZBX_GET_ACTIVE_CHECKS", 21)) /* request for list of active checks */ @@ -1288,14 +1242,14 @@ static int process_trap(zbx_socket_t *sock, char *s, ssize_t bytes_received, zbx return ret; } -static void process_trapper_child(zbx_socket_t *sock, zbx_timespec_t *ts, const zbx_config_tls_t *zbx_config_tls) +static void process_trapper_child(zbx_socket_t *sock, zbx_timespec_t *ts, const zbx_config_comms_args_t *zbx_config) { ssize_t bytes_received; if (FAIL == (bytes_received = zbx_tcp_recv_ext(sock, CONFIG_TRAPPER_TIMEOUT, ZBX_TCP_LARGE))) return; - process_trap(sock, sock->buffer, bytes_received, ts, zbx_config_tls); + process_trap(sock, sock->buffer, bytes_received, ts, zbx_config); } ZBX_THREAD_ENTRY(trapper_thread, args) @@ -1313,17 +1267,18 @@ ZBX_THREAD_ENTRY(trapper_thread, args) process_type = ((zbx_thread_args_t *)args)->process_type; server_num = ((zbx_thread_args_t *)args)->server_num; process_num = ((zbx_thread_args_t *)args)->process_num; + zbx_get_program_type_cb = trapper_args_in->zbx_get_program_type_cb_arg; zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(trapper_args_in->zbx_get_program_type_cb_arg()), server_num, get_process_type_string(process_type), process_num); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); memcpy(&s, trapper_args_in->listen_sock, sizeof(zbx_socket_t)); #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) - zbx_tls_init_child(trapper_args_in->zbx_config_tls, trapper_args_in->zbx_get_program_type_cb_arg); + zbx_tls_init_child(trapper_args_in->zbx_config->zbx_config_tls, zbx_get_program_type_cb); find_psk_in_cache = DCget_psk_by_identity; #endif zbx_setproctitle("%s #%d [connecting to the database]", get_process_type_string(process_type), process_num); @@ -1345,7 +1300,7 @@ ZBX_THREAD_ENTRY(trapper_thread, args) zbx_setproctitle("%s #%d [processed data in " ZBX_FS_DBL " sec, waiting for connection]", get_process_type_string(process_type), process_num, sec); - update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); /* Trapper has to accept all types of connections it can accept with the specified configuration. */ /* Only after receiving data it is known who has sent them and one can decide to accept or discard */ @@ -1360,7 +1315,7 @@ ZBX_THREAD_ENTRY(trapper_thread, args) /* get connection timestamp */ zbx_timespec(&ts); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); zbx_setproctitle("%s #%d [processing data]", get_process_type_string(process_type), process_num); @@ -1382,7 +1337,7 @@ ZBX_THREAD_ENTRY(trapper_thread, args) } #endif sec = zbx_time(); - process_trapper_child(&s, &ts, trapper_args_in->zbx_config_tls); + process_trapper_child(&s, &ts, trapper_args_in->zbx_config); sec = zbx_time() - sec; zbx_tcp_unaccept(&s); diff --git a/src/zabbix_server/trapper/trapper.h b/src/zabbix_server/trapper/trapper.h index 0b947354ba5..9f7a7548022 100644 --- a/src/zabbix_server/trapper/trapper.h +++ b/src/zabbix_server/trapper/trapper.h @@ -32,7 +32,7 @@ extern char *CONFIG_STATS_ALLOWED_IP; typedef struct { - zbx_config_tls_t *zbx_config_tls; + zbx_config_comms_args_t *zbx_config; zbx_get_program_type_f zbx_get_program_type_cb_arg; zbx_socket_t *listen_sock; } diff --git a/src/zabbix_server/trapper/trapper_auth.c b/src/zabbix_server/trapper/trapper_auth.c index f294906ff2b..ea77965d834 100644 --- a/src/zabbix_server/trapper/trapper_auth.c +++ b/src/zabbix_server/trapper/trapper_auth.c @@ -19,7 +19,6 @@ #include "trapper_auth.h" -#include <string.h> #include "zbxdbhigh.h" #include "log.h" #include "zbxhash.h" diff --git a/src/zabbix_server/trapper/trapper_item_test.c b/src/zabbix_server/trapper/trapper_item_test.c index 555e633d91e..07577414935 100644 --- a/src/zabbix_server/trapper/trapper_item_test.c +++ b/src/zabbix_server/trapper/trapper_item_test.c @@ -126,7 +126,8 @@ static void db_uchar_from_json(const struct zbx_json_parse *jp, const char *name ZBX_STR2UCHAR(*string, DBget_field(table, fieldname)->default_value); } -int zbx_trapper_item_test_run(const struct zbx_json_parse *jp_data, zbx_uint64_t proxy_hostid, char **info) +int zbx_trapper_item_test_run(const struct zbx_json_parse *jp_data, zbx_uint64_t proxy_hostid, char **info, + const zbx_config_comms_args_t *zbx_config) { char tmp[MAX_STRING_LEN + 1], **pvalue; DC_ITEM item; @@ -300,7 +301,7 @@ int zbx_trapper_item_test_run(const struct zbx_json_parse *jp_data, zbx_uint64_t if (ITEM_TYPE_IPMI == item.type) { - init_result(&result); + zbx_init_agent_result(&result); if (FAIL == zbx_is_ushort(item.interface.port_orig, &item.interface.port)) { @@ -350,7 +351,7 @@ int zbx_trapper_item_test_run(const struct zbx_json_parse *jp_data, zbx_uint64_t zbx_eval_clear(&ctx); } - zbx_check_items(&item, &errcode, 1, &result, &add_results, ZBX_NO_POLLER); + zbx_check_items(&item, &errcode, 1, &result, &add_results, ZBX_NO_POLLER, zbx_config); switch (errcode) { @@ -372,7 +373,7 @@ int zbx_trapper_item_test_run(const struct zbx_json_parse *jp_data, zbx_uint64_t *info = zbx_strdup(NULL, *pvalue); } - zbx_vector_ptr_clear_ext(&add_results, (zbx_mem_free_func_t)zbx_free_result_ptr); + zbx_vector_ptr_clear_ext(&add_results, (zbx_mem_free_func_t)zbx_free_agent_result_ptr); zbx_vector_ptr_destroy(&add_results); } @@ -409,7 +410,7 @@ out: return ret; } -void zbx_trapper_item_test(zbx_socket_t *sock, const struct zbx_json_parse *jp) +void zbx_trapper_item_test(zbx_socket_t *sock, const struct zbx_json_parse *jp, const zbx_config_comms_args_t *zbx_config) { zbx_user_t user; struct zbx_json_parse jp_data; @@ -446,7 +447,7 @@ void zbx_trapper_item_test(zbx_socket_t *sock, const struct zbx_json_parse *jp) else proxy_hostid = 0; - ret = zbx_trapper_item_test_run(&jp_data, proxy_hostid, &info); + ret = zbx_trapper_item_test_run(&jp_data, proxy_hostid, &info, zbx_config); zbx_json_addstring(&json, ZBX_PROTO_TAG_RESPONSE, "success", ZBX_JSON_TYPE_STRING); zbx_json_addobject(&json, ZBX_PROTO_TAG_DATA); diff --git a/src/zabbix_server/trapper/trapper_item_test.h b/src/zabbix_server/trapper/trapper_item_test.h index 960425bb01f..d58dd0e3a8c 100644 --- a/src/zabbix_server/trapper/trapper_item_test.h +++ b/src/zabbix_server/trapper/trapper_item_test.h @@ -23,7 +23,9 @@ #include "zbxcomms.h" #include "zbxjson.h" -void zbx_trapper_item_test(zbx_socket_t *sock, const struct zbx_json_parse *jp); -int zbx_trapper_item_test_run(const struct zbx_json_parse *jp_data, zbx_uint64_t proxy_hostid, char **info); +void zbx_trapper_item_test(zbx_socket_t *sock, const struct zbx_json_parse *jp, + const zbx_config_comms_args_t *zbx_config); +int zbx_trapper_item_test_run(const struct zbx_json_parse *jp_data, zbx_uint64_t proxy_hostid, char **info, + const zbx_config_comms_args_t *zbx_config); #endif diff --git a/src/zabbix_server/trapper/trapper_proxy.c b/src/zabbix_server/trapper/trapper_proxy.c index 2f5a0cb3183..0e362c22632 100644 --- a/src/zabbix_server/trapper/trapper_proxy.c +++ b/src/zabbix_server/trapper/trapper_proxy.c @@ -19,8 +19,44 @@ #include "trapper_request.h" -int trapper_process_request(const char *request, zbx_socket_t *sock, const struct zbx_json_parse *jp) +#include "zbxcommshigh.h" +#include "proxyconfigwrite/proxyconfig_write.h" + +extern int CONFIG_TIMEOUT; + +static void active_passive_misconfig(zbx_socket_t *sock) +{ + char *msg = NULL; + + msg = zbx_dsprintf(msg, "misconfiguration error: the proxy is running in the active mode but server at \"%s\"" + " sends requests to it as to proxy in passive mode", sock->peer); + + zabbix_log(LOG_LEVEL_WARNING, "%s", msg); + zbx_send_proxy_response(sock, FAIL, msg, CONFIG_TIMEOUT); + zbx_free(msg); +} + +int trapper_process_request(const char *request, zbx_socket_t *sock, const struct zbx_json_parse *jp, + const zbx_config_tls_t *zbx_config_tls, zbx_get_program_type_f get_program_type_cb) { + if (0 == strcmp(request, ZBX_PROTO_VALUE_PROXY_CONFIG)) + { + if (0 != (get_program_type_cb() & ZBX_PROGRAM_TYPE_PROXY_PASSIVE)) + { + zbx_recv_proxyconfig(sock, zbx_config_tls); + return SUCCEED; + } + else if (0 != (get_program_type_cb() & ZBX_PROGRAM_TYPE_PROXY_ACTIVE)) + { + /* This is a misconfiguration: the proxy is configured in active mode */ + /* but server sends requests to it as to a proxy in passive mode. To */ + /* prevent logging of this problem for every request we report it */ + /* only when the server sends configuration to the proxy and ignore */ + /* it for other requests. */ + active_passive_misconfig(sock); + return SUCCEED; + } + } ZBX_UNUSED(request); ZBX_UNUSED(sock); ZBX_UNUSED(jp); diff --git a/src/zabbix_server/trapper/trapper_request.h b/src/zabbix_server/trapper/trapper_request.h index ffea592e67c..336e6ded36e 100644 --- a/src/zabbix_server/trapper/trapper_request.h +++ b/src/zabbix_server/trapper/trapper_request.h @@ -23,6 +23,7 @@ #include "zbxcomms.h" #include "zbxjson.h" -int trapper_process_request(const char *request, zbx_socket_t *sock, const struct zbx_json_parse *jp); +int trapper_process_request(const char *request, zbx_socket_t *sock, const struct zbx_json_parse *jp, + const zbx_config_tls_t *zbx_config_tls, zbx_get_program_type_f get_program_type_cb); #endif diff --git a/src/zabbix_server/trapper/trapper_server.c b/src/zabbix_server/trapper/trapper_server.c index c963a795898..f91142e02b3 100644 --- a/src/zabbix_server/trapper/trapper_server.c +++ b/src/zabbix_server/trapper/trapper_server.c @@ -28,6 +28,7 @@ #include "zbxipcservice.h" #include "zbxcommshigh.h" #include "zbxnum.h" +#include "proxyconfigread/proxyconfig_read.h" extern int CONFIG_REPORTMANAGER_FORKS; @@ -214,8 +215,12 @@ fail: zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); } -int trapper_process_request(const char *request, zbx_socket_t *sock, const struct zbx_json_parse *jp) +int trapper_process_request(const char *request, zbx_socket_t *sock, const struct zbx_json_parse *jp, + const zbx_config_tls_t *zbx_config_tls, zbx_get_program_type_f get_program_type_cb) { + ZBX_UNUSED(zbx_config_tls); + ZBX_UNUSED(get_program_type_cb); + if (0 == strcmp(request, ZBX_PROTO_VALUE_REPORT_TEST)) { trapper_process_report_test(sock, jp); @@ -226,6 +231,11 @@ int trapper_process_request(const char *request, zbx_socket_t *sock, const struc trapper_process_alert_send(sock, jp); return SUCCEED; } + else if (0 == strcmp(request, ZBX_PROTO_VALUE_PROXY_CONFIG)) + { + zbx_send_proxyconfig(sock, jp); + return SUCCEED; + } return FAIL; } diff --git a/src/zabbix_server/vmware/vmware_manager.c b/src/zabbix_server/vmware/vmware_manager.c index 2c00bca40e0..7b2d5663e19 100644 --- a/src/zabbix_server/vmware/vmware_manager.c +++ b/src/zabbix_server/vmware/vmware_manager.c @@ -200,7 +200,7 @@ ZBX_THREAD_ENTRY(vmware_thread, args) zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(program_type), server_num, get_process_type_string(process_type), process_num); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); #define JOB_TIMEOUT 1 #define STAT_INTERVAL 5 /* if a process is busy and does not sleep then update status not faster than */ @@ -243,9 +243,9 @@ ZBX_THREAD_ENTRY(vmware_thread, args) if (zbx_time() - time_now <= JOB_TIMEOUT) { time_idle += JOB_TIMEOUT; - update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); zbx_sleep_loop(JOB_TIMEOUT); - update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); + zbx_update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); } } |