nutcracker 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +22 -0
- data/Rakefile +55 -0
- data/bin/nutcracker +2 -0
- data/ext/nutcracker/ChangeLog +66 -0
- data/ext/nutcracker/LICENSE +177 -0
- data/ext/nutcracker/Makefile.am +7 -0
- data/ext/nutcracker/Makefile.in +726 -0
- data/ext/nutcracker/NOTICE +124 -0
- data/ext/nutcracker/README.md +240 -0
- data/ext/nutcracker/aclocal.m4 +956 -0
- data/ext/nutcracker/conf/nutcracker.leaf.yml +10 -0
- data/ext/nutcracker/conf/nutcracker.root.yml +8 -0
- data/ext/nutcracker/conf/nutcracker.yml +67 -0
- data/ext/nutcracker/config.h.in +316 -0
- data/ext/nutcracker/config/config.guess +1561 -0
- data/ext/nutcracker/config/config.sub +1686 -0
- data/ext/nutcracker/config/depcomp +630 -0
- data/ext/nutcracker/config/install-sh +520 -0
- data/ext/nutcracker/config/ltmain.sh +8413 -0
- data/ext/nutcracker/config/missing +376 -0
- data/ext/nutcracker/configure +18862 -0
- data/ext/nutcracker/configure.ac +155 -0
- data/ext/nutcracker/contrib/Makefile.am +3 -0
- data/ext/nutcracker/contrib/Makefile.in +560 -0
- data/ext/nutcracker/contrib/yaml-0.1.4.tar.gz +0 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/LICENSE +19 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/Makefile.am +20 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/Makefile.in +736 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/README +27 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/aclocal.m4 +956 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/config.h.in +80 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/config/config.guess +1561 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/config/config.sub +1686 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/config/depcomp +630 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/config/install-sh +520 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/config/ltmain.sh +8406 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/config/missing +376 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/configure +13085 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/configure.ac +75 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/doc/doxygen.cfg +222 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/include/yaml.h +1971 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/m4/libtool.m4 +7357 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/m4/ltoptions.m4 +368 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/m4/ltsugar.m4 +123 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/m4/ltversion.m4 +23 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/m4/lt~obsolete.m4 +92 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/src/Makefile.am +4 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/src/Makefile.in +484 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/src/api.c +1392 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/src/dumper.c +394 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/src/emitter.c +2329 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/src/loader.c +432 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/src/parser.c +1374 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/src/reader.c +465 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/src/scanner.c +3570 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/src/writer.c +141 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/src/yaml_private.h +640 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/Makefile.am +8 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/Makefile.in +675 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/example-deconstructor-alt.c +800 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/example-deconstructor.c +1130 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/example-reformatter-alt.c +217 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/example-reformatter.c +202 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-dumper.c +311 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-emitter.c +327 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-loader.c +63 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-parser.c +63 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-scanner.c +63 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/test-reader.c +354 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/test-version.c +29 -0
- data/ext/nutcracker/extconf.rb +5 -0
- data/ext/nutcracker/m4/libtool.m4 +7376 -0
- data/ext/nutcracker/m4/ltoptions.m4 +368 -0
- data/ext/nutcracker/m4/ltsugar.m4 +123 -0
- data/ext/nutcracker/m4/ltversion.m4 +23 -0
- data/ext/nutcracker/m4/lt~obsolete.m4 +92 -0
- data/ext/nutcracker/notes/c-styleguide.txt +425 -0
- data/ext/nutcracker/notes/debug.txt +96 -0
- data/ext/nutcracker/notes/memcache.txt +123 -0
- data/ext/nutcracker/notes/recommendation.md +118 -0
- data/ext/nutcracker/notes/redis.md +415 -0
- data/ext/nutcracker/notes/socket.txt +131 -0
- data/ext/nutcracker/scripts/multi_get.sh +26 -0
- data/ext/nutcracker/scripts/nutcracker.init +73 -0
- data/ext/nutcracker/scripts/nutcracker.spec +52 -0
- data/ext/nutcracker/scripts/pipelined_read.sh +23 -0
- data/ext/nutcracker/scripts/pipelined_write.sh +29 -0
- data/ext/nutcracker/scripts/populate_memcached.sh +24 -0
- data/ext/nutcracker/scripts/redis-check.py +23 -0
- data/ext/nutcracker/scripts/redis-check.sh +564 -0
- data/ext/nutcracker/src/Makefile.am +46 -0
- data/ext/nutcracker/src/Makefile.in +726 -0
- data/ext/nutcracker/src/hashkit/Makefile.am +22 -0
- data/ext/nutcracker/src/hashkit/Makefile.in +501 -0
- data/ext/nutcracker/src/hashkit/nc_crc32.c +105 -0
- data/ext/nutcracker/src/hashkit/nc_fnv.c +82 -0
- data/ext/nutcracker/src/hashkit/nc_hashkit.h +74 -0
- data/ext/nutcracker/src/hashkit/nc_hsieh.c +93 -0
- data/ext/nutcracker/src/hashkit/nc_jenkins.c +230 -0
- data/ext/nutcracker/src/hashkit/nc_ketama.c +240 -0
- data/ext/nutcracker/src/hashkit/nc_md5.c +379 -0
- data/ext/nutcracker/src/hashkit/nc_modula.c +144 -0
- data/ext/nutcracker/src/hashkit/nc_murmur.c +99 -0
- data/ext/nutcracker/src/hashkit/nc_one_at_a_time.c +51 -0
- data/ext/nutcracker/src/hashkit/nc_random.c +146 -0
- data/ext/nutcracker/src/nc.c +573 -0
- data/ext/nutcracker/src/nc_array.c +204 -0
- data/ext/nutcracker/src/nc_array.h +73 -0
- data/ext/nutcracker/src/nc_client.c +189 -0
- data/ext/nutcracker/src/nc_client.h +28 -0
- data/ext/nutcracker/src/nc_conf.c +1766 -0
- data/ext/nutcracker/src/nc_conf.h +134 -0
- data/ext/nutcracker/src/nc_connection.c +392 -0
- data/ext/nutcracker/src/nc_connection.h +99 -0
- data/ext/nutcracker/src/nc_core.c +334 -0
- data/ext/nutcracker/src/nc_core.h +131 -0
- data/ext/nutcracker/src/nc_event.c +214 -0
- data/ext/nutcracker/src/nc_event.h +39 -0
- data/ext/nutcracker/src/nc_log.c +254 -0
- data/ext/nutcracker/src/nc_log.h +120 -0
- data/ext/nutcracker/src/nc_mbuf.c +285 -0
- data/ext/nutcracker/src/nc_mbuf.h +67 -0
- data/ext/nutcracker/src/nc_message.c +828 -0
- data/ext/nutcracker/src/nc_message.h +253 -0
- data/ext/nutcracker/src/nc_proxy.c +359 -0
- data/ext/nutcracker/src/nc_proxy.h +34 -0
- data/ext/nutcracker/src/nc_queue.h +788 -0
- data/ext/nutcracker/src/nc_rbtree.c +348 -0
- data/ext/nutcracker/src/nc_rbtree.h +47 -0
- data/ext/nutcracker/src/nc_request.c +588 -0
- data/ext/nutcracker/src/nc_response.c +332 -0
- data/ext/nutcracker/src/nc_server.c +841 -0
- data/ext/nutcracker/src/nc_server.h +143 -0
- data/ext/nutcracker/src/nc_signal.c +131 -0
- data/ext/nutcracker/src/nc_signal.h +34 -0
- data/ext/nutcracker/src/nc_stats.c +1188 -0
- data/ext/nutcracker/src/nc_stats.h +206 -0
- data/ext/nutcracker/src/nc_string.c +109 -0
- data/ext/nutcracker/src/nc_string.h +112 -0
- data/ext/nutcracker/src/nc_util.c +619 -0
- data/ext/nutcracker/src/nc_util.h +214 -0
- data/ext/nutcracker/src/proto/Makefile.am +14 -0
- data/ext/nutcracker/src/proto/Makefile.in +482 -0
- data/ext/nutcracker/src/proto/nc_memcache.c +1306 -0
- data/ext/nutcracker/src/proto/nc_proto.h +155 -0
- data/ext/nutcracker/src/proto/nc_redis.c +2102 -0
- data/lib/nutcracker.rb +7 -0
- data/lib/nutcracker/version.rb +3 -0
- metadata +194 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* twemproxy - A fast and lightweight proxy for memcached protocol.
|
|
3
|
+
* Copyright (C) 2011 Twitter, Inc.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#ifndef _NC_SERVER_H_
|
|
19
|
+
#define _NC_SERVER_H_
|
|
20
|
+
|
|
21
|
+
#include <nc_core.h>
|
|
22
|
+
|
|
23
|
+
/*
|
|
24
|
+
* server_pool is a collection of servers and their continuum. Each
|
|
25
|
+
* server_pool is the owner of a single proxy connection and one or
|
|
26
|
+
* more client connections. server_pool itself is owned by the current
|
|
27
|
+
* context.
|
|
28
|
+
*
|
|
29
|
+
* Each server is the owner of one or more server connections. server
|
|
30
|
+
* itself is owned by the server_pool.
|
|
31
|
+
*
|
|
32
|
+
* +-------------+
|
|
33
|
+
* | |<---------------------+
|
|
34
|
+
* | |<------------+ |
|
|
35
|
+
* | | +-------+--+-----+----+--------------+
|
|
36
|
+
* | pool 0 |+--->| | | |
|
|
37
|
+
* | | | server 0 | server 1 | ... ... |
|
|
38
|
+
* | | | | | |--+
|
|
39
|
+
* | | +----------+----------+--------------+ |
|
|
40
|
+
* +-------------+ //
|
|
41
|
+
* | |
|
|
42
|
+
* | |
|
|
43
|
+
* | |
|
|
44
|
+
* | pool 1 |
|
|
45
|
+
* | |
|
|
46
|
+
* | |
|
|
47
|
+
* | |
|
|
48
|
+
* +-------------+
|
|
49
|
+
* | |
|
|
50
|
+
* | |
|
|
51
|
+
* . .
|
|
52
|
+
* . ... .
|
|
53
|
+
* . .
|
|
54
|
+
* | |
|
|
55
|
+
* | |
|
|
56
|
+
* +-------------+
|
|
57
|
+
* |
|
|
58
|
+
* |
|
|
59
|
+
* //
|
|
60
|
+
*/
|
|
61
|
+
|
|
62
|
+
typedef uint32_t (*hash_t)(const char *, size_t);
|
|
63
|
+
|
|
64
|
+
struct continuum {
|
|
65
|
+
uint32_t index; /* server index */
|
|
66
|
+
uint32_t value; /* hash value */
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
struct server {
|
|
70
|
+
uint32_t idx; /* server index */
|
|
71
|
+
struct server_pool *owner; /* owner pool */
|
|
72
|
+
|
|
73
|
+
struct string pname; /* name:port:weight (ref in conf_server) */
|
|
74
|
+
struct string name; /* name (ref in conf_server) */
|
|
75
|
+
uint16_t port; /* port */
|
|
76
|
+
uint32_t weight; /* weight */
|
|
77
|
+
int family; /* socket family */
|
|
78
|
+
socklen_t addrlen; /* socket length */
|
|
79
|
+
struct sockaddr *addr; /* socket address (ref in conf_server) */
|
|
80
|
+
|
|
81
|
+
uint32_t ns_conn_q; /* # server connection */
|
|
82
|
+
struct conn_tqh s_conn_q; /* server connection q */
|
|
83
|
+
|
|
84
|
+
int64_t next_retry; /* next retry time in usec */
|
|
85
|
+
uint32_t failure_count; /* # consecutive failures */
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
struct server_pool {
|
|
89
|
+
uint32_t idx; /* pool index */
|
|
90
|
+
struct context *ctx; /* owner context */
|
|
91
|
+
|
|
92
|
+
struct conn *p_conn; /* proxy connection (listener) */
|
|
93
|
+
uint32_t nc_conn_q; /* # client connection */
|
|
94
|
+
struct conn_tqh c_conn_q; /* client connection q */
|
|
95
|
+
|
|
96
|
+
struct array server; /* server[] */
|
|
97
|
+
uint32_t ncontinuum; /* # continuum points */
|
|
98
|
+
uint32_t nserver_continuum; /* # servers - live and dead on continuum (const) */
|
|
99
|
+
struct continuum *continuum; /* continuum */
|
|
100
|
+
uint32_t nlive_server; /* # live server */
|
|
101
|
+
int64_t next_rebuild; /* next distribution rebuild time in usec */
|
|
102
|
+
|
|
103
|
+
struct string name; /* pool name (ref in conf_pool) */
|
|
104
|
+
struct string addrstr; /* pool address (ref in conf_pool) */
|
|
105
|
+
uint16_t port; /* port */
|
|
106
|
+
int family; /* socket family */
|
|
107
|
+
socklen_t addrlen; /* socket length */
|
|
108
|
+
struct sockaddr *addr; /* socket address (ref in conf_pool) */
|
|
109
|
+
int dist_type; /* distribution type (dist_type_t) */
|
|
110
|
+
int key_hash_type; /* key hash type (hash_type_t) */
|
|
111
|
+
hash_t key_hash; /* key hasher */
|
|
112
|
+
struct string hash_tag; /* key hash tag (ref in conf_pool) */
|
|
113
|
+
int timeout; /* timeout in msec */
|
|
114
|
+
int backlog; /* listen backlog */
|
|
115
|
+
uint32_t client_connections; /* maximum # client connection */
|
|
116
|
+
uint32_t server_connections; /* maximum # server connection */
|
|
117
|
+
int64_t server_retry_timeout; /* server retry timeout in usec */
|
|
118
|
+
uint32_t server_failure_limit; /* server failure limit */
|
|
119
|
+
unsigned auto_eject_hosts:1; /* auto_eject_hosts? */
|
|
120
|
+
unsigned preconnect:1; /* preconnect? */
|
|
121
|
+
unsigned redis:1; /* redis? */
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
void server_ref(struct conn *conn, void *owner);
|
|
125
|
+
void server_unref(struct conn *conn);
|
|
126
|
+
int server_timeout(struct conn *conn);
|
|
127
|
+
bool server_active(struct conn *conn);
|
|
128
|
+
rstatus_t server_init(struct array *server, struct array *conf_server, struct server_pool *sp);
|
|
129
|
+
void server_deinit(struct array *server);
|
|
130
|
+
struct conn *server_conn(struct server *server);
|
|
131
|
+
rstatus_t server_connect(struct context *ctx, struct server *server, struct conn *conn);
|
|
132
|
+
void server_close(struct context *ctx, struct conn *conn);
|
|
133
|
+
void server_connected(struct context *ctx, struct conn *conn);
|
|
134
|
+
void server_ok(struct context *ctx, struct conn *conn);
|
|
135
|
+
|
|
136
|
+
struct conn *server_pool_conn(struct context *ctx, struct server_pool *pool, uint8_t *key, uint32_t keylen);
|
|
137
|
+
rstatus_t server_pool_run(struct server_pool *pool);
|
|
138
|
+
rstatus_t server_pool_preconnect(struct context *ctx);
|
|
139
|
+
void server_pool_disconnect(struct context *ctx);
|
|
140
|
+
rstatus_t server_pool_init(struct array *server_pool, struct array *conf_pool, struct context *ctx);
|
|
141
|
+
void server_pool_deinit(struct array *server_pool);
|
|
142
|
+
|
|
143
|
+
#endif
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* twemproxy - A fast and lightweight proxy for memcached protocol.
|
|
3
|
+
* Copyright (C) 2011 Twitter, Inc.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#include <stdlib.h>
|
|
19
|
+
#include <signal.h>
|
|
20
|
+
|
|
21
|
+
#include <nc_core.h>
|
|
22
|
+
#include <nc_signal.h>
|
|
23
|
+
|
|
24
|
+
static struct signal signals[] = {
|
|
25
|
+
{ SIGUSR1, "SIGUSR1", 0, signal_handler },
|
|
26
|
+
{ SIGUSR2, "SIGUSR2", 0, signal_handler },
|
|
27
|
+
{ SIGTTIN, "SIGTTIN", 0, signal_handler },
|
|
28
|
+
{ SIGTTOU, "SIGTTOU", 0, signal_handler },
|
|
29
|
+
{ SIGHUP, "SIGHUP", 0, signal_handler },
|
|
30
|
+
{ SIGINT, "SIGINT", 0, signal_handler },
|
|
31
|
+
{ SIGSEGV, "SIGSEGV", (int)SA_RESETHAND, signal_handler },
|
|
32
|
+
{ SIGPIPE, "SIGPIPE", 0, SIG_IGN },
|
|
33
|
+
{ 0, NULL, 0, NULL }
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
rstatus_t
|
|
37
|
+
signal_init(void)
|
|
38
|
+
{
|
|
39
|
+
struct signal *sig;
|
|
40
|
+
|
|
41
|
+
for (sig = signals; sig->signo != 0; sig++) {
|
|
42
|
+
rstatus_t status;
|
|
43
|
+
struct sigaction sa;
|
|
44
|
+
|
|
45
|
+
memset(&sa, 0, sizeof(sa));
|
|
46
|
+
sa.sa_handler = sig->handler;
|
|
47
|
+
sa.sa_flags = sig->flags;
|
|
48
|
+
sigemptyset(&sa.sa_mask);
|
|
49
|
+
|
|
50
|
+
status = sigaction(sig->signo, &sa, NULL);
|
|
51
|
+
if (status < 0) {
|
|
52
|
+
log_error("sigaction(%s) failed: %s", sig->signame,
|
|
53
|
+
strerror(errno));
|
|
54
|
+
return NC_ERROR;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return NC_OK;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
void
|
|
62
|
+
signal_deinit(void)
|
|
63
|
+
{
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
void
|
|
67
|
+
signal_handler(int signo)
|
|
68
|
+
{
|
|
69
|
+
struct signal *sig;
|
|
70
|
+
void (*action)(void);
|
|
71
|
+
char *actionstr;
|
|
72
|
+
bool done;
|
|
73
|
+
|
|
74
|
+
for (sig = signals; sig->signo != 0; sig++) {
|
|
75
|
+
if (sig->signo == signo) {
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
ASSERT(sig->signo != 0);
|
|
80
|
+
|
|
81
|
+
actionstr = "";
|
|
82
|
+
action = NULL;
|
|
83
|
+
done = false;
|
|
84
|
+
|
|
85
|
+
switch (signo) {
|
|
86
|
+
case SIGUSR1:
|
|
87
|
+
break;
|
|
88
|
+
|
|
89
|
+
case SIGUSR2:
|
|
90
|
+
break;
|
|
91
|
+
|
|
92
|
+
case SIGTTIN:
|
|
93
|
+
actionstr = ", up logging level";
|
|
94
|
+
action = log_level_up;
|
|
95
|
+
break;
|
|
96
|
+
|
|
97
|
+
case SIGTTOU:
|
|
98
|
+
actionstr = ", down logging level";
|
|
99
|
+
action = log_level_down;
|
|
100
|
+
break;
|
|
101
|
+
|
|
102
|
+
case SIGHUP:
|
|
103
|
+
actionstr = ", reopening log file";
|
|
104
|
+
action = log_reopen;
|
|
105
|
+
break;
|
|
106
|
+
|
|
107
|
+
case SIGINT:
|
|
108
|
+
done = true;
|
|
109
|
+
actionstr = ", exiting";
|
|
110
|
+
break;
|
|
111
|
+
|
|
112
|
+
case SIGSEGV:
|
|
113
|
+
nc_stacktrace(1);
|
|
114
|
+
actionstr = ", core dumping";
|
|
115
|
+
raise(SIGSEGV);
|
|
116
|
+
break;
|
|
117
|
+
|
|
118
|
+
default:
|
|
119
|
+
NOT_REACHED();
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
loga("signal %d (%s) received%s", signo, sig->signame, actionstr);
|
|
123
|
+
|
|
124
|
+
if (action != NULL) {
|
|
125
|
+
action();
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (done) {
|
|
129
|
+
exit(1);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* twemproxy - A fast and lightweight proxy for memcached protocol.
|
|
3
|
+
* Copyright (C) 2011 Twitter, Inc.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#ifndef _NC_SIGNAL_H_
|
|
19
|
+
#define _NC_SIGNAL_H_
|
|
20
|
+
|
|
21
|
+
#include <nc_core.h>
|
|
22
|
+
|
|
23
|
+
struct signal {
|
|
24
|
+
int signo;
|
|
25
|
+
char *signame;
|
|
26
|
+
int flags;
|
|
27
|
+
void (*handler)(int signo);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
rstatus_t signal_init(void);
|
|
31
|
+
void signal_deinit(void);
|
|
32
|
+
void signal_handler(int signo);
|
|
33
|
+
|
|
34
|
+
#endif
|
|
@@ -0,0 +1,1188 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* twemproxy - A fast and lightweight proxy for memcached protocol.
|
|
3
|
+
* Copyright (C) 2011 Twitter, Inc.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#include <stdio.h>
|
|
19
|
+
#include <stdlib.h>
|
|
20
|
+
#include <unistd.h>
|
|
21
|
+
|
|
22
|
+
#include <sys/types.h>
|
|
23
|
+
#include <sys/socket.h>
|
|
24
|
+
#include <sys/epoll.h>
|
|
25
|
+
#include <netinet/in.h>
|
|
26
|
+
|
|
27
|
+
#include <nc_core.h>
|
|
28
|
+
#include <nc_server.h>
|
|
29
|
+
|
|
30
|
+
struct stats_desc {
|
|
31
|
+
char *name; /* stats name */
|
|
32
|
+
char *desc; /* stats description */
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
#define DEFINE_ACTION(_name, _type, _desc) { .type = _type, .name = string(#_name) },
|
|
36
|
+
static struct stats_metric stats_pool_codec[] = {
|
|
37
|
+
STATS_POOL_CODEC( DEFINE_ACTION )
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
static struct stats_metric stats_server_codec[] = {
|
|
41
|
+
STATS_SERVER_CODEC( DEFINE_ACTION )
|
|
42
|
+
};
|
|
43
|
+
#undef DEFINE_ACTION
|
|
44
|
+
|
|
45
|
+
#define DEFINE_ACTION(_name, _type, _desc) { .name = #_name, .desc = _desc },
|
|
46
|
+
static struct stats_desc stats_pool_desc[] = {
|
|
47
|
+
STATS_POOL_CODEC( DEFINE_ACTION )
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
static struct stats_desc stats_server_desc[] = {
|
|
51
|
+
STATS_SERVER_CODEC( DEFINE_ACTION )
|
|
52
|
+
};
|
|
53
|
+
#undef DEFINE_ACTION
|
|
54
|
+
|
|
55
|
+
void
|
|
56
|
+
stats_describe(void)
|
|
57
|
+
{
|
|
58
|
+
uint32_t i;
|
|
59
|
+
|
|
60
|
+
log_stderr("pool stats:");
|
|
61
|
+
for (i = 0; i < NELEMS(stats_pool_desc); i++) {
|
|
62
|
+
log_stderr(" %-20s\"%s\"", stats_pool_desc[i].name,
|
|
63
|
+
stats_pool_desc[i].desc);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
log_stderr("");
|
|
67
|
+
|
|
68
|
+
log_stderr("server stats:");
|
|
69
|
+
for (i = 0; i < NELEMS(stats_server_desc); i++) {
|
|
70
|
+
log_stderr(" %-20s\"%s\"", stats_server_desc[i].name,
|
|
71
|
+
stats_server_desc[i].desc);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
static void
|
|
76
|
+
stats_metric_init(struct stats_metric *stm)
|
|
77
|
+
{
|
|
78
|
+
switch (stm->type) {
|
|
79
|
+
case STATS_COUNTER:
|
|
80
|
+
stm->value.counter = 0LL;
|
|
81
|
+
break;
|
|
82
|
+
|
|
83
|
+
case STATS_GAUGE:
|
|
84
|
+
stm->value.counter = 0LL;
|
|
85
|
+
break;
|
|
86
|
+
|
|
87
|
+
case STATS_TIMESTAMP:
|
|
88
|
+
stm->value.timestamp = 0LL;
|
|
89
|
+
break;
|
|
90
|
+
|
|
91
|
+
default:
|
|
92
|
+
NOT_REACHED();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
static void
|
|
97
|
+
stats_metric_reset(struct array *stats_metric)
|
|
98
|
+
{
|
|
99
|
+
uint32_t i, nmetric;
|
|
100
|
+
|
|
101
|
+
nmetric = array_n(stats_metric);
|
|
102
|
+
ASSERT(nmetric == STATS_POOL_NFIELD || nmetric == STATS_SERVER_NFIELD);
|
|
103
|
+
|
|
104
|
+
for (i = 0; i < nmetric; i++) {
|
|
105
|
+
struct stats_metric *stm = array_get(stats_metric, i);
|
|
106
|
+
|
|
107
|
+
stats_metric_init(stm);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
static rstatus_t
|
|
112
|
+
stats_pool_metric_init(struct array *stats_metric)
|
|
113
|
+
{
|
|
114
|
+
rstatus_t status;
|
|
115
|
+
uint32_t i, nfield = STATS_POOL_NFIELD;
|
|
116
|
+
|
|
117
|
+
status = array_init(stats_metric, nfield, sizeof(struct stats_metric));
|
|
118
|
+
if (status != NC_OK) {
|
|
119
|
+
return status;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
for (i = 0; i < nfield; i++) {
|
|
123
|
+
struct stats_metric *stm = array_push(stats_metric);
|
|
124
|
+
|
|
125
|
+
/* initialize from pool codec first */
|
|
126
|
+
*stm = stats_pool_codec[i];
|
|
127
|
+
|
|
128
|
+
/* initialize individual metric */
|
|
129
|
+
stats_metric_init(stm);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return NC_OK;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
static rstatus_t
|
|
136
|
+
stats_server_metric_init(struct stats_server *sts)
|
|
137
|
+
{
|
|
138
|
+
rstatus_t status;
|
|
139
|
+
uint32_t i, nfield = STATS_SERVER_NFIELD;
|
|
140
|
+
|
|
141
|
+
status = array_init(&sts->metric, nfield, sizeof(struct stats_metric));
|
|
142
|
+
if (status != NC_OK) {
|
|
143
|
+
return status;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
for (i = 0; i < nfield; i++) {
|
|
147
|
+
struct stats_metric *stm = array_push(&sts->metric);
|
|
148
|
+
|
|
149
|
+
/* initialize from server codec first */
|
|
150
|
+
*stm = stats_server_codec[i];
|
|
151
|
+
|
|
152
|
+
/* initialize individual metric */
|
|
153
|
+
stats_metric_init(stm);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return NC_OK;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
static void
|
|
160
|
+
stats_metric_deinit(struct array *metric)
|
|
161
|
+
{
|
|
162
|
+
uint32_t i, nmetric;
|
|
163
|
+
|
|
164
|
+
nmetric = array_n(metric);
|
|
165
|
+
for (i = 0; i < nmetric; i++) {
|
|
166
|
+
array_pop(metric);
|
|
167
|
+
}
|
|
168
|
+
array_deinit(metric);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
static rstatus_t
|
|
172
|
+
stats_server_init(struct stats_server *sts, struct server *s)
|
|
173
|
+
{
|
|
174
|
+
rstatus_t status;
|
|
175
|
+
|
|
176
|
+
sts->name = s->name;
|
|
177
|
+
array_null(&sts->metric);
|
|
178
|
+
|
|
179
|
+
status = stats_server_metric_init(sts);
|
|
180
|
+
if (status != NC_OK) {
|
|
181
|
+
return status;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
log_debug(LOG_VVVERB, "init stats server '%.*s' with %"PRIu32" metric",
|
|
185
|
+
sts->name.len, sts->name.data, array_n(&sts->metric));
|
|
186
|
+
|
|
187
|
+
return NC_OK;
|
|
188
|
+
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
static rstatus_t
|
|
192
|
+
stats_server_map(struct array *stats_server, struct array *server)
|
|
193
|
+
{
|
|
194
|
+
rstatus_t status;
|
|
195
|
+
uint32_t i, nserver;
|
|
196
|
+
|
|
197
|
+
nserver = array_n(server);
|
|
198
|
+
ASSERT(nserver != 0);
|
|
199
|
+
|
|
200
|
+
status = array_init(stats_server, nserver, sizeof(struct stats_server));
|
|
201
|
+
if (status != NC_OK) {
|
|
202
|
+
return status;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
for (i = 0; i < nserver; i++) {
|
|
206
|
+
struct server *s = array_get(server, i);
|
|
207
|
+
struct stats_server *sts = array_push(stats_server);
|
|
208
|
+
|
|
209
|
+
status = stats_server_init(sts, s);
|
|
210
|
+
if (status != NC_OK) {
|
|
211
|
+
return status;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
log_debug(LOG_VVVERB, "map %"PRIu32" stats servers", nserver);
|
|
216
|
+
|
|
217
|
+
return NC_OK;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
static void
|
|
221
|
+
stats_server_unmap(struct array *stats_server)
|
|
222
|
+
{
|
|
223
|
+
uint32_t i, nserver;
|
|
224
|
+
|
|
225
|
+
nserver = array_n(stats_server);
|
|
226
|
+
|
|
227
|
+
for (i = 0; i < nserver; i++) {
|
|
228
|
+
struct stats_server *sts = array_pop(stats_server);
|
|
229
|
+
stats_metric_deinit(&sts->metric);
|
|
230
|
+
}
|
|
231
|
+
array_deinit(stats_server);
|
|
232
|
+
|
|
233
|
+
log_debug(LOG_VVVERB, "unmap %"PRIu32" stats servers", nserver);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
static rstatus_t
|
|
237
|
+
stats_pool_init(struct stats_pool *stp, struct server_pool *sp)
|
|
238
|
+
{
|
|
239
|
+
rstatus_t status;
|
|
240
|
+
|
|
241
|
+
stp->name = sp->name;
|
|
242
|
+
array_null(&stp->metric);
|
|
243
|
+
array_null(&stp->server);
|
|
244
|
+
|
|
245
|
+
status = stats_pool_metric_init(&stp->metric);
|
|
246
|
+
if (status != NC_OK) {
|
|
247
|
+
return status;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
status = stats_server_map(&stp->server, &sp->server);
|
|
251
|
+
if (status != NC_OK) {
|
|
252
|
+
stats_metric_deinit(&stp->metric);
|
|
253
|
+
return status;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
log_debug(LOG_VVVERB, "init stats pool '%.*s' with %"PRIu32" metric and "
|
|
257
|
+
"%"PRIu32" server", stp->name.len, stp->name.data,
|
|
258
|
+
array_n(&stp->metric), array_n(&stp->metric));
|
|
259
|
+
|
|
260
|
+
return NC_OK;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
static void
|
|
264
|
+
stats_pool_reset(struct array *stats_pool)
|
|
265
|
+
{
|
|
266
|
+
uint32_t i, npool;
|
|
267
|
+
|
|
268
|
+
npool = array_n(stats_pool);
|
|
269
|
+
|
|
270
|
+
for (i = 0; i < npool; i++) {
|
|
271
|
+
struct stats_pool *stp = array_get(stats_pool, i);
|
|
272
|
+
uint32_t j, nserver;
|
|
273
|
+
|
|
274
|
+
stats_metric_reset(&stp->metric);
|
|
275
|
+
|
|
276
|
+
nserver = array_n(&stp->server);
|
|
277
|
+
for (j = 0; j < nserver; j++) {
|
|
278
|
+
struct stats_server *sts = array_get(&stp->server, j);
|
|
279
|
+
stats_metric_reset(&sts->metric);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
static rstatus_t
|
|
285
|
+
stats_pool_map(struct array *stats_pool, struct array *server_pool)
|
|
286
|
+
{
|
|
287
|
+
rstatus_t status;
|
|
288
|
+
uint32_t i, npool;
|
|
289
|
+
|
|
290
|
+
npool = array_n(server_pool);
|
|
291
|
+
ASSERT(npool != 0);
|
|
292
|
+
|
|
293
|
+
status = array_init(stats_pool, npool, sizeof(struct stats_pool));
|
|
294
|
+
if (status != NC_OK) {
|
|
295
|
+
return status;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
for (i = 0; i < npool; i++) {
|
|
299
|
+
struct server_pool *sp = array_get(server_pool, i);
|
|
300
|
+
struct stats_pool *stp = array_push(stats_pool);
|
|
301
|
+
|
|
302
|
+
status = stats_pool_init(stp, sp);
|
|
303
|
+
if (status != NC_OK) {
|
|
304
|
+
return status;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
log_debug(LOG_VVVERB, "map %"PRIu32" stats pools", npool);
|
|
309
|
+
|
|
310
|
+
return NC_OK;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
static void
|
|
314
|
+
stats_pool_unmap(struct array *stats_pool)
|
|
315
|
+
{
|
|
316
|
+
uint32_t i, npool;
|
|
317
|
+
|
|
318
|
+
npool = array_n(stats_pool);
|
|
319
|
+
|
|
320
|
+
for (i = 0; i < npool; i++) {
|
|
321
|
+
struct stats_pool *stp = array_pop(stats_pool);
|
|
322
|
+
stats_metric_deinit(&stp->metric);
|
|
323
|
+
stats_server_unmap(&stp->server);
|
|
324
|
+
}
|
|
325
|
+
array_deinit(stats_pool);
|
|
326
|
+
|
|
327
|
+
log_debug(LOG_VVVERB, "unmap %"PRIu32" stats pool", npool);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
static rstatus_t
|
|
331
|
+
stats_create_buf(struct stats *st)
|
|
332
|
+
{
|
|
333
|
+
uint32_t int64_max_digits = 20; /* INT64_MAX = 9223372036854775807 */
|
|
334
|
+
uint32_t key_value_extra = 8; /* "key": "value", */
|
|
335
|
+
uint32_t pool_extra = 8; /* '"pool_name": { ' + ' }' */
|
|
336
|
+
uint32_t server_extra = 8; /* '"server_name": { ' + ' }' */
|
|
337
|
+
size_t size = 0;
|
|
338
|
+
uint32_t i;
|
|
339
|
+
|
|
340
|
+
ASSERT(st->buf.data == NULL && st->buf.size == 0);
|
|
341
|
+
|
|
342
|
+
/* header */
|
|
343
|
+
size += 1;
|
|
344
|
+
|
|
345
|
+
size += st->service_str.len;
|
|
346
|
+
size += st->service.len;
|
|
347
|
+
size += key_value_extra;
|
|
348
|
+
|
|
349
|
+
size += st->source_str.len;
|
|
350
|
+
size += st->source.len;
|
|
351
|
+
size += key_value_extra;
|
|
352
|
+
|
|
353
|
+
size += st->version_str.len;
|
|
354
|
+
size += st->version.len;
|
|
355
|
+
size += key_value_extra;
|
|
356
|
+
|
|
357
|
+
size += st->uptime_str.len;
|
|
358
|
+
size += int64_max_digits;
|
|
359
|
+
size += key_value_extra;
|
|
360
|
+
|
|
361
|
+
size += st->timestamp_str.len;
|
|
362
|
+
size += int64_max_digits;
|
|
363
|
+
size += key_value_extra;
|
|
364
|
+
|
|
365
|
+
/* server pools */
|
|
366
|
+
for (i = 0; i < array_n(&st->sum); i++) {
|
|
367
|
+
struct stats_pool *stp = array_get(&st->sum, i);
|
|
368
|
+
uint32_t j;
|
|
369
|
+
|
|
370
|
+
size += stp->name.len;
|
|
371
|
+
size += pool_extra;
|
|
372
|
+
|
|
373
|
+
for (j = 0; j < array_n(&stp->metric); j++) {
|
|
374
|
+
struct stats_metric *stm = array_get(&stp->metric, j);
|
|
375
|
+
|
|
376
|
+
size += stm->name.len;
|
|
377
|
+
size += int64_max_digits;
|
|
378
|
+
size += key_value_extra;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/* servers per pool */
|
|
382
|
+
for (j = 0; j < array_n(&stp->server); j++) {
|
|
383
|
+
struct stats_server *sts = array_get(&stp->server, j);
|
|
384
|
+
uint32_t k;
|
|
385
|
+
|
|
386
|
+
size += sts->name.len;
|
|
387
|
+
size += server_extra;
|
|
388
|
+
|
|
389
|
+
for (k = 0; k < array_n(&sts->metric); k++) {
|
|
390
|
+
struct stats_metric *stm = array_get(&sts->metric, k);
|
|
391
|
+
|
|
392
|
+
size += stm->name.len;
|
|
393
|
+
size += int64_max_digits;
|
|
394
|
+
size += key_value_extra;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/* footer */
|
|
400
|
+
size += 2;
|
|
401
|
+
|
|
402
|
+
size = NC_ALIGN(size, NC_ALIGNMENT);
|
|
403
|
+
|
|
404
|
+
st->buf.data = nc_alloc(size);
|
|
405
|
+
if (st->buf.data == NULL) {
|
|
406
|
+
log_error("create stats buffer of size %zu failed: %s", size,
|
|
407
|
+
strerror(errno));
|
|
408
|
+
return NC_ENOMEM;
|
|
409
|
+
}
|
|
410
|
+
st->buf.size = size;
|
|
411
|
+
|
|
412
|
+
log_debug(LOG_DEBUG, "stats buffer size %zu", size);
|
|
413
|
+
|
|
414
|
+
return NC_OK;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
static void
|
|
418
|
+
stats_destroy_buf(struct stats *st)
|
|
419
|
+
{
|
|
420
|
+
if (st->buf.size != 0) {
|
|
421
|
+
ASSERT(st->buf.data != NULL);
|
|
422
|
+
nc_free(st->buf.data);
|
|
423
|
+
st->buf.size = 0;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
static rstatus_t
|
|
428
|
+
stats_add_string(struct stats *st, struct string *key, struct string *val)
|
|
429
|
+
{
|
|
430
|
+
struct stats_buffer *buf;
|
|
431
|
+
uint8_t *pos;
|
|
432
|
+
size_t room;
|
|
433
|
+
int n;
|
|
434
|
+
|
|
435
|
+
buf = &st->buf;
|
|
436
|
+
pos = buf->data + buf->len;
|
|
437
|
+
room = buf->size - buf->len - 1;
|
|
438
|
+
|
|
439
|
+
n = nc_snprintf(pos, room, "\"%.*s\":\"%.*s\", ", key->len, key->data,
|
|
440
|
+
val->len, val->data);
|
|
441
|
+
if (n < 0 || n >= (int)room) {
|
|
442
|
+
return NC_ERROR;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
buf->len += (size_t)n;
|
|
446
|
+
|
|
447
|
+
return NC_OK;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
static rstatus_t
|
|
451
|
+
stats_add_num(struct stats *st, struct string *key, int64_t val)
|
|
452
|
+
{
|
|
453
|
+
struct stats_buffer *buf;
|
|
454
|
+
uint8_t *pos;
|
|
455
|
+
size_t room;
|
|
456
|
+
int n;
|
|
457
|
+
|
|
458
|
+
buf = &st->buf;
|
|
459
|
+
pos = buf->data + buf->len;
|
|
460
|
+
room = buf->size - buf->len - 1;
|
|
461
|
+
|
|
462
|
+
n = nc_snprintf(pos, room, "\"%.*s\":%"PRId64", ", key->len, key->data,
|
|
463
|
+
val);
|
|
464
|
+
if (n < 0 || n >= (int)room) {
|
|
465
|
+
return NC_ERROR;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
buf->len += (size_t)n;
|
|
469
|
+
|
|
470
|
+
return NC_OK;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
static rstatus_t
|
|
474
|
+
stats_add_header(struct stats *st)
|
|
475
|
+
{
|
|
476
|
+
rstatus_t status;
|
|
477
|
+
struct stats_buffer *buf;
|
|
478
|
+
int64_t cur_ts, uptime;
|
|
479
|
+
|
|
480
|
+
buf = &st->buf;
|
|
481
|
+
buf->data[0] = '{';
|
|
482
|
+
buf->len = 1;
|
|
483
|
+
|
|
484
|
+
cur_ts = (int64_t)time(NULL);
|
|
485
|
+
uptime = cur_ts - st->start_ts;
|
|
486
|
+
|
|
487
|
+
status = stats_add_string(st, &st->service_str, &st->service);
|
|
488
|
+
if (status != NC_OK) {
|
|
489
|
+
return status;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
status = stats_add_string(st, &st->source_str, &st->source);
|
|
493
|
+
if (status != NC_OK) {
|
|
494
|
+
return status;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
status = stats_add_string(st, &st->version_str, &st->version);
|
|
498
|
+
if (status != NC_OK) {
|
|
499
|
+
return status;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
status = stats_add_num(st, &st->uptime_str, uptime);
|
|
503
|
+
if (status != NC_OK) {
|
|
504
|
+
return status;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
status = stats_add_num(st, &st->timestamp_str, cur_ts);
|
|
508
|
+
if (status != NC_OK) {
|
|
509
|
+
return status;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
return NC_OK;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
static rstatus_t
|
|
516
|
+
stats_add_footer(struct stats *st)
|
|
517
|
+
{
|
|
518
|
+
struct stats_buffer *buf;
|
|
519
|
+
uint8_t *pos;
|
|
520
|
+
|
|
521
|
+
buf = &st->buf;
|
|
522
|
+
|
|
523
|
+
if (buf->len == buf->size) {
|
|
524
|
+
return NC_ERROR;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
/* overwrite the last byte and add a new byte */
|
|
528
|
+
pos = buf->data + buf->len - 1;
|
|
529
|
+
pos[0] = '}';
|
|
530
|
+
pos[1] = '\n';
|
|
531
|
+
buf->len += 1;
|
|
532
|
+
|
|
533
|
+
return NC_OK;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
static rstatus_t
|
|
537
|
+
stats_begin_nesting(struct stats *st, struct string *key)
|
|
538
|
+
{
|
|
539
|
+
struct stats_buffer *buf;
|
|
540
|
+
uint8_t *pos;
|
|
541
|
+
size_t room;
|
|
542
|
+
int n;
|
|
543
|
+
|
|
544
|
+
buf = &st->buf;
|
|
545
|
+
pos = buf->data + buf->len;
|
|
546
|
+
room = buf->size - buf->len - 1;
|
|
547
|
+
|
|
548
|
+
n = nc_snprintf(pos, room, "\"%.*s\": {", key->len, key->data);
|
|
549
|
+
if (n < 0 || n >= (int)room) {
|
|
550
|
+
return NC_ERROR;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
buf->len += (size_t)n;
|
|
554
|
+
|
|
555
|
+
return NC_OK;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
static rstatus_t
|
|
559
|
+
stats_end_nesting(struct stats *st)
|
|
560
|
+
{
|
|
561
|
+
struct stats_buffer *buf;
|
|
562
|
+
uint8_t *pos;
|
|
563
|
+
|
|
564
|
+
buf = &st->buf;
|
|
565
|
+
pos = buf->data + buf->len;
|
|
566
|
+
|
|
567
|
+
pos -= 2; /* go back by 2 bytes */
|
|
568
|
+
|
|
569
|
+
switch (pos[0]) {
|
|
570
|
+
case ',':
|
|
571
|
+
/* overwrite last two bytes; len remains unchanged */
|
|
572
|
+
ASSERT(pos[1] == ' ');
|
|
573
|
+
pos[0] = '}';
|
|
574
|
+
pos[1] = ',';
|
|
575
|
+
break;
|
|
576
|
+
|
|
577
|
+
case '}':
|
|
578
|
+
if (buf->len == buf->size) {
|
|
579
|
+
return NC_ERROR;
|
|
580
|
+
}
|
|
581
|
+
/* overwrite the last byte and add a new byte */
|
|
582
|
+
ASSERT(pos[1] == ',');
|
|
583
|
+
pos[1] = '}';
|
|
584
|
+
pos[2] = ',';
|
|
585
|
+
buf->len += 1;
|
|
586
|
+
break;
|
|
587
|
+
|
|
588
|
+
default:
|
|
589
|
+
NOT_REACHED();
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
return NC_OK;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
static rstatus_t
|
|
596
|
+
stats_copy_metric(struct stats *st, struct array *metric)
|
|
597
|
+
{
|
|
598
|
+
rstatus_t status;
|
|
599
|
+
uint32_t i;
|
|
600
|
+
|
|
601
|
+
for (i = 0; i < array_n(metric); i++) {
|
|
602
|
+
struct stats_metric *stm = array_get(metric, i);
|
|
603
|
+
|
|
604
|
+
status = stats_add_num(st, &stm->name, stm->value.counter);
|
|
605
|
+
if (status != NC_OK) {
|
|
606
|
+
return status;
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
return NC_OK;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
static void
|
|
614
|
+
stats_aggregate_metric(struct array *dst, struct array *src)
|
|
615
|
+
{
|
|
616
|
+
uint32_t i;
|
|
617
|
+
|
|
618
|
+
for (i = 0; i < array_n(src); i++) {
|
|
619
|
+
struct stats_metric *stm1, *stm2;
|
|
620
|
+
|
|
621
|
+
stm1 = array_get(src, i);
|
|
622
|
+
stm2 = array_get(dst, i);
|
|
623
|
+
|
|
624
|
+
ASSERT(stm1->type == stm2->type);
|
|
625
|
+
|
|
626
|
+
switch (stm1->type) {
|
|
627
|
+
case STATS_COUNTER:
|
|
628
|
+
stm2->value.counter += stm1->value.counter;
|
|
629
|
+
break;
|
|
630
|
+
|
|
631
|
+
case STATS_GAUGE:
|
|
632
|
+
stm2->value.counter += stm1->value.counter;
|
|
633
|
+
break;
|
|
634
|
+
|
|
635
|
+
case STATS_TIMESTAMP:
|
|
636
|
+
if (stm1->value.timestamp) {
|
|
637
|
+
stm2->value.timestamp = stm1->value.timestamp;
|
|
638
|
+
}
|
|
639
|
+
break;
|
|
640
|
+
|
|
641
|
+
default:
|
|
642
|
+
NOT_REACHED();
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
static void
|
|
648
|
+
stats_aggregate(struct stats *st)
|
|
649
|
+
{
|
|
650
|
+
uint32_t i;
|
|
651
|
+
|
|
652
|
+
if (st->aggregate == 0) {
|
|
653
|
+
log_debug(LOG_PVERB, "skip aggregate of shadow %p to sum %p as "
|
|
654
|
+
"generator is slow", st->shadow.elem, st->sum.elem);
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
log_debug(LOG_PVERB, "aggregate stats shadow %p to sum %p", st->shadow.elem,
|
|
659
|
+
st->sum.elem);
|
|
660
|
+
|
|
661
|
+
for (i = 0; i < array_n(&st->shadow); i++) {
|
|
662
|
+
struct stats_pool *stp1, *stp2;
|
|
663
|
+
uint32_t j;
|
|
664
|
+
|
|
665
|
+
stp1 = array_get(&st->shadow, i);
|
|
666
|
+
stp2 = array_get(&st->sum, i);
|
|
667
|
+
stats_aggregate_metric(&stp2->metric, &stp1->metric);
|
|
668
|
+
|
|
669
|
+
for (j = 0; j < array_n(&stp1->server); j++) {
|
|
670
|
+
struct stats_server *sts1, *sts2;
|
|
671
|
+
|
|
672
|
+
sts1 = array_get(&stp1->server, j);
|
|
673
|
+
sts2 = array_get(&stp2->server, j);
|
|
674
|
+
stats_aggregate_metric(&sts2->metric, &sts1->metric);
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
st->aggregate = 0;
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
static rstatus_t
|
|
682
|
+
stats_make_rsp(struct stats *st)
|
|
683
|
+
{
|
|
684
|
+
rstatus_t status;
|
|
685
|
+
uint32_t i;
|
|
686
|
+
|
|
687
|
+
status = stats_add_header(st);
|
|
688
|
+
if (status != NC_OK) {
|
|
689
|
+
return status;
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
for (i = 0; i < array_n(&st->sum); i++) {
|
|
693
|
+
struct stats_pool *stp = array_get(&st->sum, i);
|
|
694
|
+
uint32_t j;
|
|
695
|
+
|
|
696
|
+
status = stats_begin_nesting(st, &stp->name);
|
|
697
|
+
if (status != NC_OK) {
|
|
698
|
+
return status;
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
/* copy pool metric from sum(c) to buffer */
|
|
702
|
+
status = stats_copy_metric(st, &stp->metric);
|
|
703
|
+
if (status != NC_OK) {
|
|
704
|
+
return status;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
for (j = 0; j < array_n(&stp->server); j++) {
|
|
708
|
+
struct stats_server *sts = array_get(&stp->server, j);
|
|
709
|
+
|
|
710
|
+
status = stats_begin_nesting(st, &sts->name);
|
|
711
|
+
if (status != NC_OK) {
|
|
712
|
+
return status;
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
/* copy server metric from sum(c) to buffer */
|
|
716
|
+
status = stats_copy_metric(st, &sts->metric);
|
|
717
|
+
if (status != NC_OK) {
|
|
718
|
+
return status;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
status = stats_end_nesting(st);
|
|
722
|
+
if (status != NC_OK) {
|
|
723
|
+
return status;
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
status = stats_end_nesting(st);
|
|
728
|
+
if (status != NC_OK) {
|
|
729
|
+
return status;
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
status = stats_add_footer(st);
|
|
734
|
+
if (status != NC_OK) {
|
|
735
|
+
return status;
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
return NC_OK;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
static rstatus_t
|
|
742
|
+
stats_send_rsp(struct stats *st)
|
|
743
|
+
{
|
|
744
|
+
rstatus_t status;
|
|
745
|
+
ssize_t n;
|
|
746
|
+
int sd;
|
|
747
|
+
|
|
748
|
+
status = stats_make_rsp(st);
|
|
749
|
+
if (status != NC_OK) {
|
|
750
|
+
return status;
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
sd = accept(st->sd, NULL, NULL);
|
|
754
|
+
if (sd < 0) {
|
|
755
|
+
log_error("accept on m %d failed: %s", st->sd, strerror(errno));
|
|
756
|
+
return NC_ERROR;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
log_debug(LOG_VERB, "send stats on sd %d %d bytes", sd, st->buf.len);
|
|
760
|
+
|
|
761
|
+
n = nc_sendn(sd, st->buf.data, st->buf.len);
|
|
762
|
+
if (n < 0) {
|
|
763
|
+
log_error("send stats on sd %d failed: %s", sd, strerror(errno));
|
|
764
|
+
close(sd);
|
|
765
|
+
return NC_ERROR;
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
close(sd);
|
|
769
|
+
|
|
770
|
+
return NC_OK;
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
static void *
|
|
774
|
+
stats_loop(void *arg)
|
|
775
|
+
{
|
|
776
|
+
struct stats *st = arg;
|
|
777
|
+
int n;
|
|
778
|
+
|
|
779
|
+
for (;;) {
|
|
780
|
+
n = epoll_wait(st->ep, &st->event, 1, st->interval);
|
|
781
|
+
if (n < 0) {
|
|
782
|
+
if (errno == EINTR) {
|
|
783
|
+
continue;
|
|
784
|
+
}
|
|
785
|
+
log_error("epoll wait on e %d with event m %d failed: %s",
|
|
786
|
+
st->ep, st->sd, strerror(errno));
|
|
787
|
+
break;
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
/* aggregate stats from shadow (b) -> sum (c) */
|
|
791
|
+
stats_aggregate(st);
|
|
792
|
+
|
|
793
|
+
if (n == 0) {
|
|
794
|
+
continue;
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
/* send aggregate stats sum (c) to collector */
|
|
798
|
+
stats_send_rsp(st);
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
return NULL;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
static rstatus_t
|
|
805
|
+
stats_listen(struct stats *st)
|
|
806
|
+
{
|
|
807
|
+
rstatus_t status;
|
|
808
|
+
struct sockinfo si;
|
|
809
|
+
|
|
810
|
+
status = nc_resolve(&st->addr, st->port, &si);
|
|
811
|
+
if (status < 0) {
|
|
812
|
+
return status;
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
st->sd = socket(si.family, SOCK_STREAM, 0);
|
|
816
|
+
if (st->sd < 0) {
|
|
817
|
+
log_error("socket failed: %s", strerror(errno));
|
|
818
|
+
return NC_ERROR;
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
status = nc_set_reuseaddr(st->sd);
|
|
822
|
+
if (status < 0) {
|
|
823
|
+
log_error("set reuseaddr on m %d failed: %s", st->sd, strerror(errno));
|
|
824
|
+
return NC_ERROR;
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
status = bind(st->sd, (struct sockaddr *)&si.addr, si.addrlen);
|
|
828
|
+
if (status < 0) {
|
|
829
|
+
log_error("bind on m %d to addr '%.*s:%u' failed: %s", st->sd,
|
|
830
|
+
st->addr.len, st->addr.data, st->port, strerror(errno));
|
|
831
|
+
return NC_ERROR;
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
status = listen(st->sd, SOMAXCONN);
|
|
835
|
+
if (status < 0) {
|
|
836
|
+
log_error("listen on m %d failed: %s", st->sd, strerror(errno));
|
|
837
|
+
return NC_ERROR;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
log_debug(LOG_NOTICE, "m %d listening on '%.*s:%u'", st->sd,
|
|
841
|
+
st->addr.len, st->addr.data, st->port);
|
|
842
|
+
|
|
843
|
+
return NC_OK;
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
static rstatus_t
|
|
847
|
+
stats_start_aggregator(struct stats *st)
|
|
848
|
+
{
|
|
849
|
+
rstatus_t status;
|
|
850
|
+
struct epoll_event ev;
|
|
851
|
+
|
|
852
|
+
if (!stats_enabled) {
|
|
853
|
+
return NC_OK;
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
status = stats_listen(st);
|
|
857
|
+
if (status != NC_OK) {
|
|
858
|
+
return status;
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
st->ep = epoll_create(10);
|
|
862
|
+
if (st->ep < 0) {
|
|
863
|
+
log_error("epoll create failed: %s", strerror(errno));
|
|
864
|
+
return NC_ERROR;
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
ev.data.fd = st->sd;
|
|
868
|
+
ev.events = EPOLLIN;
|
|
869
|
+
|
|
870
|
+
status = epoll_ctl(st->ep, EPOLL_CTL_ADD, st->sd, &ev);
|
|
871
|
+
if (status < 0) {
|
|
872
|
+
log_error("epoll ctl on e %d sd %d failed: %s", st->ep, st->sd,
|
|
873
|
+
strerror(errno));
|
|
874
|
+
return NC_ERROR;
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
status = pthread_create(&st->tid, NULL, stats_loop, st);
|
|
878
|
+
if (status < 0) {
|
|
879
|
+
log_error("stats aggregator create failed: %s", strerror(status));
|
|
880
|
+
return NC_ERROR;
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
return NC_OK;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
static void
|
|
887
|
+
stats_stop_aggregator(struct stats *st)
|
|
888
|
+
{
|
|
889
|
+
if (!stats_enabled) {
|
|
890
|
+
return;
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
close(st->sd);
|
|
894
|
+
close(st->ep);
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
struct stats *
|
|
898
|
+
stats_create(uint16_t stats_port, char *stats_ip, int stats_interval,
|
|
899
|
+
char *source, struct array *server_pool)
|
|
900
|
+
{
|
|
901
|
+
rstatus_t status;
|
|
902
|
+
struct stats *st;
|
|
903
|
+
|
|
904
|
+
st = nc_alloc(sizeof(*st));
|
|
905
|
+
if (st == NULL) {
|
|
906
|
+
return NULL;
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
st->port = stats_port;
|
|
910
|
+
st->interval = stats_interval;
|
|
911
|
+
string_set_raw(&st->addr, stats_ip);
|
|
912
|
+
|
|
913
|
+
st->start_ts = (int64_t)time(NULL);
|
|
914
|
+
|
|
915
|
+
st->buf.len = 0;
|
|
916
|
+
st->buf.data = NULL;
|
|
917
|
+
st->buf.size = 0;
|
|
918
|
+
|
|
919
|
+
array_null(&st->current);
|
|
920
|
+
array_null(&st->shadow);
|
|
921
|
+
array_null(&st->sum);
|
|
922
|
+
|
|
923
|
+
st->tid = (pthread_t) -1;
|
|
924
|
+
st->ep = -1;
|
|
925
|
+
st->sd = -1;
|
|
926
|
+
|
|
927
|
+
string_set_text(&st->service_str, "service");
|
|
928
|
+
string_set_text(&st->service, "nutcracker");
|
|
929
|
+
|
|
930
|
+
string_set_text(&st->source_str, "source");
|
|
931
|
+
string_set_raw(&st->source, source);
|
|
932
|
+
|
|
933
|
+
string_set_text(&st->version_str, "version");
|
|
934
|
+
string_set_text(&st->version, NC_VERSION_STRING);
|
|
935
|
+
|
|
936
|
+
string_set_text(&st->uptime_str, "uptime");
|
|
937
|
+
string_set_text(&st->timestamp_str, "timestamp");
|
|
938
|
+
|
|
939
|
+
st->updated = 0;
|
|
940
|
+
st->aggregate = 0;
|
|
941
|
+
|
|
942
|
+
/* map server pool to current (a), shadow (b) and sum (c) */
|
|
943
|
+
|
|
944
|
+
status = stats_pool_map(&st->current, server_pool);
|
|
945
|
+
if (status != NC_OK) {
|
|
946
|
+
goto error;
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
status = stats_pool_map(&st->shadow, server_pool);
|
|
950
|
+
if (status != NC_OK) {
|
|
951
|
+
goto error;
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
status = stats_pool_map(&st->sum, server_pool);
|
|
955
|
+
if (status != NC_OK) {
|
|
956
|
+
goto error;
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
status = stats_create_buf(st);
|
|
960
|
+
if (status != NC_OK) {
|
|
961
|
+
goto error;
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
status = stats_start_aggregator(st);
|
|
965
|
+
if (status != NC_OK) {
|
|
966
|
+
goto error;
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
return st;
|
|
970
|
+
|
|
971
|
+
error:
|
|
972
|
+
stats_destroy(st);
|
|
973
|
+
return NULL;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
void
|
|
977
|
+
stats_destroy(struct stats *st)
|
|
978
|
+
{
|
|
979
|
+
stats_stop_aggregator(st);
|
|
980
|
+
stats_pool_unmap(&st->sum);
|
|
981
|
+
stats_pool_unmap(&st->shadow);
|
|
982
|
+
stats_pool_unmap(&st->current);
|
|
983
|
+
stats_destroy_buf(st);
|
|
984
|
+
nc_free(st);
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
void
|
|
988
|
+
stats_swap(struct stats *st)
|
|
989
|
+
{
|
|
990
|
+
if (!stats_enabled) {
|
|
991
|
+
return;
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
if (st->aggregate == 1) {
|
|
995
|
+
log_debug(LOG_PVERB, "skip swap of current %p shadow %p as aggregator "
|
|
996
|
+
"is busy", st->current.elem, st->shadow.elem);
|
|
997
|
+
return;
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
if (st->updated == 0) {
|
|
1001
|
+
log_debug(LOG_PVERB, "skip swap of current %p shadow %p as there is "
|
|
1002
|
+
"nothing new", st->current.elem, st->shadow.elem);
|
|
1003
|
+
return;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
log_debug(LOG_PVERB, "swap stats current %p shadow %p", st->current.elem,
|
|
1007
|
+
st->shadow.elem);
|
|
1008
|
+
|
|
1009
|
+
array_swap(&st->current, &st->shadow);
|
|
1010
|
+
|
|
1011
|
+
/*
|
|
1012
|
+
* Reset current (a) stats before giving it back to generator to keep
|
|
1013
|
+
* stats addition idempotent
|
|
1014
|
+
*/
|
|
1015
|
+
stats_pool_reset(&st->current);
|
|
1016
|
+
st->updated = 0;
|
|
1017
|
+
|
|
1018
|
+
st->aggregate = 1;
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
static struct stats_metric *
|
|
1022
|
+
stats_pool_to_metric(struct context *ctx, struct server_pool *pool,
|
|
1023
|
+
stats_pool_field_t fidx)
|
|
1024
|
+
{
|
|
1025
|
+
struct stats *st;
|
|
1026
|
+
struct stats_pool *stp;
|
|
1027
|
+
struct stats_metric *stm;
|
|
1028
|
+
uint32_t pidx;
|
|
1029
|
+
|
|
1030
|
+
pidx = pool->idx;
|
|
1031
|
+
|
|
1032
|
+
st = ctx->stats;
|
|
1033
|
+
stp = array_get(&st->current, pidx);
|
|
1034
|
+
stm = array_get(&stp->metric, fidx);
|
|
1035
|
+
|
|
1036
|
+
st->updated = 1;
|
|
1037
|
+
|
|
1038
|
+
log_debug(LOG_VVVERB, "metric '%.*s' in pool %"PRIu32"", stm->name.len,
|
|
1039
|
+
stm->name.data, pidx);
|
|
1040
|
+
|
|
1041
|
+
return stm;
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
void
|
|
1045
|
+
_stats_pool_incr(struct context *ctx, struct server_pool *pool,
|
|
1046
|
+
stats_pool_field_t fidx)
|
|
1047
|
+
{
|
|
1048
|
+
struct stats_metric *stm;
|
|
1049
|
+
|
|
1050
|
+
stm = stats_pool_to_metric(ctx, pool, fidx);
|
|
1051
|
+
|
|
1052
|
+
ASSERT(stm->type == STATS_COUNTER || stm->type == STATS_GAUGE);
|
|
1053
|
+
stm->value.counter++;
|
|
1054
|
+
|
|
1055
|
+
log_debug(LOG_VVVERB, "incr field '%.*s' to %"PRId64"", stm->name.len,
|
|
1056
|
+
stm->name.data, stm->value.counter);
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
void
|
|
1060
|
+
_stats_pool_decr(struct context *ctx, struct server_pool *pool,
|
|
1061
|
+
stats_pool_field_t fidx)
|
|
1062
|
+
{
|
|
1063
|
+
struct stats_metric *stm;
|
|
1064
|
+
|
|
1065
|
+
stm = stats_pool_to_metric(ctx, pool, fidx);
|
|
1066
|
+
|
|
1067
|
+
ASSERT(stm->type == STATS_GAUGE);
|
|
1068
|
+
stm->value.counter--;
|
|
1069
|
+
|
|
1070
|
+
log_debug(LOG_VVVERB, "decr field '%.*s' to %"PRId64"", stm->name.len,
|
|
1071
|
+
stm->name.data, stm->value.counter);
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
void
|
|
1075
|
+
_stats_pool_incr_by(struct context *ctx, struct server_pool *pool,
|
|
1076
|
+
stats_pool_field_t fidx, int64_t val)
|
|
1077
|
+
{
|
|
1078
|
+
struct stats_metric *stm;
|
|
1079
|
+
|
|
1080
|
+
stm = stats_pool_to_metric(ctx, pool, fidx);
|
|
1081
|
+
|
|
1082
|
+
ASSERT(stm->type == STATS_COUNTER || stm->type == STATS_GAUGE);
|
|
1083
|
+
stm->value.counter += val;
|
|
1084
|
+
|
|
1085
|
+
log_debug(LOG_VVVERB, "incr by field '%.*s' to %"PRId64"", stm->name.len,
|
|
1086
|
+
stm->name.data, stm->value.counter);
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
void
|
|
1090
|
+
_stats_pool_decr_by(struct context *ctx, struct server_pool *pool,
|
|
1091
|
+
stats_pool_field_t fidx, int64_t val)
|
|
1092
|
+
{
|
|
1093
|
+
struct stats_metric *stm;
|
|
1094
|
+
|
|
1095
|
+
stm = stats_pool_to_metric(ctx, pool, fidx);
|
|
1096
|
+
|
|
1097
|
+
ASSERT(stm->type == STATS_GAUGE);
|
|
1098
|
+
stm->value.counter -= val;
|
|
1099
|
+
|
|
1100
|
+
log_debug(LOG_VVVERB, "decr by field '%.*s' to %"PRId64"", stm->name.len,
|
|
1101
|
+
stm->name.data, stm->value.counter);
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
static struct stats_metric *
|
|
1105
|
+
stats_server_to_metric(struct context *ctx, struct server *server,
|
|
1106
|
+
stats_server_field_t fidx)
|
|
1107
|
+
{
|
|
1108
|
+
struct stats *st;
|
|
1109
|
+
struct stats_pool *stp;
|
|
1110
|
+
struct stats_server *sts;
|
|
1111
|
+
struct stats_metric *stm;
|
|
1112
|
+
uint32_t pidx, sidx;
|
|
1113
|
+
|
|
1114
|
+
sidx = server->idx;
|
|
1115
|
+
pidx = server->owner->idx;
|
|
1116
|
+
|
|
1117
|
+
st = ctx->stats;
|
|
1118
|
+
stp = array_get(&st->current, pidx);
|
|
1119
|
+
sts = array_get(&stp->server, sidx);
|
|
1120
|
+
stm = array_get(&sts->metric, fidx);
|
|
1121
|
+
|
|
1122
|
+
st->updated = 1;
|
|
1123
|
+
|
|
1124
|
+
log_debug(LOG_VVVERB, "metric '%.*s' in pool %"PRIu32" server %"PRIu32"",
|
|
1125
|
+
stm->name.len, stm->name.data, pidx, sidx);
|
|
1126
|
+
|
|
1127
|
+
return stm;
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
void
|
|
1131
|
+
_stats_server_incr(struct context *ctx, struct server *server,
|
|
1132
|
+
stats_server_field_t fidx)
|
|
1133
|
+
{
|
|
1134
|
+
struct stats_metric *stm;
|
|
1135
|
+
|
|
1136
|
+
stm = stats_server_to_metric(ctx, server, fidx);
|
|
1137
|
+
|
|
1138
|
+
ASSERT(stm->type == STATS_COUNTER || stm->type == STATS_GAUGE);
|
|
1139
|
+
stm->value.counter++;
|
|
1140
|
+
|
|
1141
|
+
log_debug(LOG_VVVERB, "incr field '%.*s' to %"PRId64"", stm->name.len,
|
|
1142
|
+
stm->name.data, stm->value.counter);
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
void
|
|
1146
|
+
_stats_server_decr(struct context *ctx, struct server *server,
|
|
1147
|
+
stats_server_field_t fidx)
|
|
1148
|
+
{
|
|
1149
|
+
struct stats_metric *stm;
|
|
1150
|
+
|
|
1151
|
+
stm = stats_server_to_metric(ctx, server, fidx);
|
|
1152
|
+
|
|
1153
|
+
ASSERT(stm->type == STATS_GAUGE);
|
|
1154
|
+
stm->value.counter--;
|
|
1155
|
+
|
|
1156
|
+
log_debug(LOG_VVVERB, "decr field '%.*s' to %"PRId64"", stm->name.len,
|
|
1157
|
+
stm->name.data, stm->value.counter);
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
void
|
|
1161
|
+
_stats_server_incr_by(struct context *ctx, struct server *server,
|
|
1162
|
+
stats_server_field_t fidx, int64_t val)
|
|
1163
|
+
{
|
|
1164
|
+
struct stats_metric *stm;
|
|
1165
|
+
|
|
1166
|
+
stm = stats_server_to_metric(ctx, server, fidx);
|
|
1167
|
+
|
|
1168
|
+
ASSERT(stm->type == STATS_COUNTER || stm->type == STATS_GAUGE);
|
|
1169
|
+
stm->value.counter += val;
|
|
1170
|
+
|
|
1171
|
+
log_debug(LOG_VVVERB, "incr by field '%.*s' to %"PRId64"", stm->name.len,
|
|
1172
|
+
stm->name.data, stm->value.counter);
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
void
|
|
1176
|
+
_stats_server_decr_by(struct context *ctx, struct server *server,
|
|
1177
|
+
stats_server_field_t fidx, int64_t val)
|
|
1178
|
+
{
|
|
1179
|
+
struct stats_metric *stm;
|
|
1180
|
+
|
|
1181
|
+
stm = stats_server_to_metric(ctx, server, fidx);
|
|
1182
|
+
|
|
1183
|
+
ASSERT(stm->type == STATS_GAUGE);
|
|
1184
|
+
stm->value.counter -= val;
|
|
1185
|
+
|
|
1186
|
+
log_debug(LOG_VVVERB, "decr by field '%.*s' to %"PRId64"", stm->name.len,
|
|
1187
|
+
stm->name.data, stm->value.counter);
|
|
1188
|
+
}
|