1 /* -*-pgsql-c-*- */
2 /*
3 * $Header$
4 *
5 * pgpool: a language independent connection pool server for PostgreSQL
6 * written by Tatsuo Ishii
7 *
8 * Copyright (c) 2003-2019 PgPool Global Development Group
9 *
10 * Permission to use, copy, modify, and distribute this software and
11 * its documentation for any purpose and without fee is hereby
12 * granted, provided that the above copyright notice appear in all
13 * copies and that both that copyright notice and this permission
14 * notice appear in supporting documentation, and that the name of the
15 * author not be used in advertising or publicity pertaining to
16 * distribution of the software without specific, written prior
17 * permission. The author makes no representations about the
18 * suitability of this software for any purpose. It is provided "as
19 * is" without express or implied warranty.
20 *
21 * Process pgPool-II "SHOW" queries.
22 */
23 #include "pool.h"
24 #include "protocol/pool_proto_modules.h"
25 #include "utils/elog.h"
26 #include "utils/pool_stream.h"
27 #include "pool_config.h"
28 #include "query_cache/pool_memqcache.h"
29 #include "version.h"
30
31 #include <stdlib.h>
32 #include <string.h>
33 #include <netinet/in.h>
34
35
36 void
send_row_description(POOL_CONNECTION * frontend,POOL_CONNECTION_POOL * backend,short num_fields,char ** field_names)37 send_row_description(POOL_CONNECTION * frontend, POOL_CONNECTION_POOL * backend,
38 short num_fields, char **field_names)
39 {
40 static char *cursorname = "blank";
41 static int oid = 0;
42 static short fsize = -1;
43 static int mod = 0;
44 short n;
45 int i;
46 short s;
47 int len;
48 short colnum;
49
50 if (MAJOR(backend) == PROTO_MAJOR_V2)
51 {
52 /* cursor response */
53 pool_write(frontend, "P", 1);
54 pool_write(frontend, cursorname, strlen(cursorname) + 1);
55 }
56
57 /* row description */
58 pool_write(frontend, "T", 1);
59
60 if (MAJOR(backend) == PROTO_MAJOR_V3)
61 {
62 /*
63 * information about computed byte in section "RowDescription (B)"
64 * here:
65 * http://www.postgresql.org/docs/current/static/protocol-message-formats.html
66 */
67
68 len = 6; /* int32 + int16 */
69
70 for (i = 0; i < num_fields; i++)
71 {
72 /* String + '\0' + 3* int32 + 3* int16 */
73 len += strlen(field_names[i]) + 1 + 18;
74 }
75
76 len = htonl(len);
77 pool_write(frontend, &len, sizeof(len));
78 }
79
80 n = htons(num_fields);
81 pool_write(frontend, &n, sizeof(short));
82
83 for (i = 0; i < num_fields; i++)
84 {
85 pool_write(frontend, field_names[i], strlen(field_names[i]) + 1); /* field name */
86
87 if (MAJOR(backend) == PROTO_MAJOR_V3)
88 {
89 pool_write(frontend, &oid, sizeof(oid)); /* table oid */
90 colnum = htons(i);
91 pool_write(frontend, &colnum, sizeof(colnum)); /* column number */
92 }
93
94 pool_write(frontend, &oid, sizeof(oid)); /* data type oid */
95 s = htons(fsize);
96 pool_write(frontend, &s, sizeof(fsize)); /* field size */
97 pool_write(frontend, &mod, sizeof(mod)); /* modifier */
98
99 if (MAJOR(backend) == PROTO_MAJOR_V3)
100 {
101 s = htons(0);
102 pool_write(frontend, &s, sizeof(fsize)); /* field format (text) */
103 }
104 }
105 pool_flush(frontend);
106 }
107
108 /*
109 * Send the command complete and ready for query message
110 * to frontend.
111 * If the num_row is lower than 0, it is not included
112 * to the command complete message.
113 */
114 void
send_complete_and_ready(POOL_CONNECTION * frontend,POOL_CONNECTION_POOL * backend,const char * message,const int num_rows)115 send_complete_and_ready(POOL_CONNECTION * frontend, POOL_CONNECTION_POOL * backend, const char *message, const int num_rows)
116 {
117 int len;
118 int msg_len;
119 char msg[64];
120
121 if (num_rows >= 0)
122 msg_len = snprintf(msg, sizeof(msg), "%s %d", message, num_rows);
123 else
124 msg_len = snprintf(msg, sizeof(msg), "%s", message);
125
126 /* complete command response */
127 pool_write(frontend, "C", 1);
128 if (MAJOR(backend) == PROTO_MAJOR_V3)
129 {
130 len = htonl(4 + msg_len + 1);
131 pool_write(frontend, &len, sizeof(len));
132 }
133 pool_write(frontend, msg, msg_len + 1);
134
135 /* ready for query */
136 pool_write(frontend, "Z", 1);
137 if (MAJOR(backend) == PROTO_MAJOR_V3)
138 {
139 len = htonl(5);
140 pool_write(frontend, &len, sizeof(len));
141 pool_write(frontend, "I", 1);
142 }
143
144 pool_flush(frontend);
145 }
146
147 POOL_REPORT_CONFIG *
get_config(int * nrows)148 get_config(int *nrows)
149 {
150 int i,
151 j;
152 int len;
153
154 /*
155 * Report data buffer.
156 * 128 is the max number of configuration items.
157 * In addition, we need MAX_NUM_BACKENDS*4
158 * for backend descriptions.
159 */
160 #define MAXITEMS (256 + MAX_NUM_BACKENDS*4)
161
162 POOL_REPORT_CONFIG *status = palloc0(MAXITEMS * sizeof(POOL_REPORT_CONFIG));
163
164 /*
165 * we initialize the array with NULL values so when looping on it, we can
166 * use it as stop condition
167 */
168
169 i = 0;
170
171 /* CONNECTIONS */
172
173 /* - pgpool Connection Settings - */
174 StrNCpy(status[i].name, "listen_addresses", POOLCONFIG_MAXNAMELEN);
175 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->listen_addresses);
176 StrNCpy(status[i].desc, "host name(s) or IP address(es) to listen on", POOLCONFIG_MAXDESCLEN);
177 i++;
178
179 StrNCpy(status[i].name, "port", POOLCONFIG_MAXNAMELEN);
180 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->port);
181 StrNCpy(status[i].desc, "pgpool accepting port number", POOLCONFIG_MAXDESCLEN);
182 i++;
183
184 /* - pgpool Communication Manager Connection Settings - */
185 StrNCpy(status[i].name, "socket_dir", POOLCONFIG_MAXNAMELEN);
186 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->socket_dir);
187 StrNCpy(status[i].desc, "pgpool socket directory", POOLCONFIG_MAXDESCLEN);
188 i++;
189
190 StrNCpy(status[i].name, "pcp_listen_addresses", POOLCONFIG_MAXNAMELEN);
191 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->pcp_listen_addresses);
192 StrNCpy(status[i].desc, "host name(s) or IP address(es) for pcp process to listen on", POOLCONFIG_MAXDESCLEN);
193 i++;
194
195 StrNCpy(status[i].name, "pcp_port", POOLCONFIG_MAXNAMELEN);
196 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->pcp_port);
197 StrNCpy(status[i].desc, "PCP port # to bind", POOLCONFIG_MAXDESCLEN);
198 i++;
199
200 StrNCpy(status[i].name, "pcp_socket_dir", POOLCONFIG_MAXNAMELEN);
201 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->pcp_socket_dir);
202 StrNCpy(status[i].desc, "PCP socket directory", POOLCONFIG_MAXDESCLEN);
203 i++;
204
205 /* # - Authentication - */
206 StrNCpy(status[i].name, "enable_pool_hba", POOLCONFIG_MAXNAMELEN);
207 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->enable_pool_hba);
208 StrNCpy(status[i].desc, "if true, use pool_hba.conf for client authentication", POOLCONFIG_MAXDESCLEN);
209 i++;
210
211 StrNCpy(status[i].name, "pool_passwd", POOLCONFIG_MAXNAMELEN);
212 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->pool_passwd);
213 StrNCpy(status[i].desc, "file name of pool_passwd for md5 authentication", POOLCONFIG_MAXDESCLEN);
214 i++;
215
216 StrNCpy(status[i].name, "authentication_timeout", POOLCONFIG_MAXNAMELEN);
217 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->authentication_timeout);
218 StrNCpy(status[i].desc, "maximum time in seconds to complete client authentication", POOLCONFIG_MAXNAMELEN);
219 i++;
220
221 StrNCpy(status[i].name, "allow_clear_text_frontend_auth", POOLCONFIG_MAXNAMELEN);
222 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->allow_clear_text_frontend_auth);
223 StrNCpy(status[i].desc, "allow to use clear text password auth when pool_passwd does not contain password", POOLCONFIG_MAXDESCLEN);
224 i++;
225
226 /* - SSL Connections - */
227 StrNCpy(status[i].name, "ssl", POOLCONFIG_MAXNAMELEN);
228 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->ssl);
229 StrNCpy(status[i].desc, "SSL support", POOLCONFIG_MAXDESCLEN);
230 i++;
231
232 StrNCpy(status[i].name, "ssl_key", POOLCONFIG_MAXNAMELEN);
233 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->ssl_key);
234 StrNCpy(status[i].desc, "path to the SSL private key file", POOLCONFIG_MAXDESCLEN);
235 i++;
236
237 StrNCpy(status[i].name, "ssl_cert", POOLCONFIG_MAXNAMELEN);
238 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->ssl_cert);
239 StrNCpy(status[i].desc, "path to the SSL public certificate file", POOLCONFIG_MAXDESCLEN);
240 i++;
241
242 StrNCpy(status[i].name, "ssl_ca_cert", POOLCONFIG_MAXNAMELEN);
243 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->ssl_ca_cert);
244 StrNCpy(status[i].desc, "path to a single PEM format file", POOLCONFIG_MAXDESCLEN);
245 i++;
246
247 StrNCpy(status[i].name, "ssl_ca_cert_dir", POOLCONFIG_MAXNAMELEN);
248 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->ssl_ca_cert_dir);
249 StrNCpy(status[i].desc, "directory containing CA root certificate(s)", POOLCONFIG_MAXDESCLEN);
250 i++;
251
252 StrNCpy(status[i].name, "ssl_ciphers", POOLCONFIG_MAXNAMELEN);
253 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->ssl_ciphers);
254 StrNCpy(status[i].desc, "allowed SSL ciphers", POOLCONFIG_MAXDESCLEN);
255 i++;
256
257 StrNCpy(status[i].name, "ssl_prefer_server_ciphers", POOLCONFIG_MAXNAMELEN);
258 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->ssl_prefer_server_ciphers);
259 StrNCpy(status[i].desc, "Use server's SSL cipher preferences", POOLCONFIG_MAXDESCLEN);
260 i++;
261
262 StrNCpy(status[i].name, "ssl_ecdh_curve", POOLCONFIG_MAXNAMELEN);
263 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->ssl_ecdh_curve);
264 StrNCpy(status[i].desc, "the curve to use in ECDH key exchange", POOLCONFIG_MAXDESCLEN);
265 i++;
266
267 StrNCpy(status[i].name, "ssl_dh_params_file", POOLCONFIG_MAXNAMELEN);
268 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->ssl_dh_params_file);
269 StrNCpy(status[i].desc, "path to the Diffie-Hellman parameters contained file", POOLCONFIG_MAXDESCLEN);
270 i++;
271
272 /* POOLS */
273
274 /* - Pool size - */
275 StrNCpy(status[i].name, "num_init_children", POOLCONFIG_MAXNAMELEN);
276 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->num_init_children);
277 StrNCpy(status[i].desc, "# of children initially pre-forked", POOLCONFIG_MAXDESCLEN);
278 i++;
279
280 StrNCpy(status[i].name, "listen_backlog_multiplier", POOLCONFIG_MAXNAMELEN);
281 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->listen_backlog_multiplier);
282 StrNCpy(status[i].desc, "determines the size of the queue for pending connections", POOLCONFIG_MAXDESCLEN);
283 i++;
284
285 StrNCpy(status[i].name, "serialize_accept", POOLCONFIG_MAXNAMELEN);
286 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->serialize_accept);
287 StrNCpy(status[i].desc, "whether to serialize accept() call", POOLCONFIG_MAXDESCLEN);
288 i++;
289
290 StrNCpy(status[i].name, "reserved_connections", POOLCONFIG_MAXNAMELEN);
291 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->reserved_connections);
292 StrNCpy(status[i].desc, "number of reserved connections", POOLCONFIG_MAXDESCLEN);
293 i++;
294
295 StrNCpy(status[i].name, "max_pool", POOLCONFIG_MAXNAMELEN);
296 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->max_pool);
297 StrNCpy(status[i].desc, "max # of connection pool per child", POOLCONFIG_MAXDESCLEN);
298 i++;
299
300 /* - Life time - */
301 StrNCpy(status[i].name, "child_life_time", POOLCONFIG_MAXNAMELEN);
302 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->child_life_time);
303 StrNCpy(status[i].desc, "if idle for this seconds, child exits", POOLCONFIG_MAXDESCLEN);
304 i++;
305
306 StrNCpy(status[i].name, "child_max_connections", POOLCONFIG_MAXNAMELEN);
307 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->child_max_connections);
308 StrNCpy(status[i].desc, "if max_connections received, child exits", POOLCONFIG_MAXDESCLEN);
309 i++;
310
311 StrNCpy(status[i].name, "connection_life_time", POOLCONFIG_MAXNAMELEN);
312 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->connection_life_time);
313 StrNCpy(status[i].desc, "if idle for this seconds, connection closes", POOLCONFIG_MAXDESCLEN);
314 i++;
315
316 StrNCpy(status[i].name, "client_idle_limit", POOLCONFIG_MAXNAMELEN);
317 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->client_idle_limit);
318 StrNCpy(status[i].desc, "if idle for this seconds, child connection closes", POOLCONFIG_MAXDESCLEN);
319 i++;
320
321 /* LOGS */
322
323 /* - Where to log - */
324 StrNCpy(status[i].name, "log_destination", POOLCONFIG_MAXNAMELEN);
325 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->log_destination_str);
326 StrNCpy(status[i].desc, "logging destination", POOLCONFIG_MAXDESCLEN);
327 i++;
328
329 /* - What to log - */
330 StrNCpy(status[i].name, "log_line_prefix", POOLCONFIG_MAXNAMELEN);
331 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->log_line_prefix);
332 StrNCpy(status[i].desc, "printf-style string to output at beginning of each log line", POOLCONFIG_MAXDESCLEN);
333 i++;
334
335 StrNCpy(status[i].name, "log_error_verbosity", POOLCONFIG_MAXNAMELEN);
336 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->log_error_verbosity);
337 StrNCpy(status[i].desc, "controls how much detail about error should be emitted", POOLCONFIG_MAXDESCLEN);
338 i++;
339
340 StrNCpy(status[i].name, "client_min_messages", POOLCONFIG_MAXNAMELEN);
341 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->client_min_messages);
342 StrNCpy(status[i].desc, "controls which message should be sent to client", POOLCONFIG_MAXDESCLEN);
343 i++;
344
345 StrNCpy(status[i].name, "log_min_messages", POOLCONFIG_MAXNAMELEN);
346 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->log_min_messages);
347 StrNCpy(status[i].desc, "controls which message should be emitted to server log", POOLCONFIG_MAXDESCLEN);
348 i++;
349
350 StrNCpy(status[i].name, "log_connections", POOLCONFIG_MAXNAMELEN);
351 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->log_connections);
352 StrNCpy(status[i].desc, "if true, print incoming connections to the log", POOLCONFIG_MAXDESCLEN);
353 i++;
354
355 StrNCpy(status[i].name, "log_hostname", POOLCONFIG_MAXNAMELEN);
356 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->log_hostname);
357 StrNCpy(status[i].desc, "if true, resolve hostname for ps and log print", POOLCONFIG_MAXDESCLEN);
358 i++;
359
360 StrNCpy(status[i].name, "log_statement", POOLCONFIG_MAXNAMELEN);
361 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->log_statement);
362 StrNCpy(status[i].desc, "if non 0, logs all SQL statements", POOLCONFIG_MAXDESCLEN);
363 i++;
364
365 StrNCpy(status[i].name, "log_per_node_statement", POOLCONFIG_MAXNAMELEN);
366 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->log_per_node_statement);
367 StrNCpy(status[i].desc, "if non 0, logs all SQL statements on each node", POOLCONFIG_MAXDESCLEN);
368 i++;
369
370 StrNCpy(status[i].name, "log_client_messages", POOLCONFIG_MAXNAMELEN);
371 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->log_client_messages);
372 StrNCpy(status[i].desc, "if non 0, logs any client messages", POOLCONFIG_MAXDESCLEN);
373 i++;
374
375 StrNCpy(status[i].name, "log_standby_delay", POOLCONFIG_MAXNAMELEN);
376 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->log_standby_delay);
377 StrNCpy(status[i].desc, "how to log standby delay", POOLCONFIG_MAXDESCLEN);
378 i++;
379
380 /* - Syslog specific - */
381 StrNCpy(status[i].name, "syslog_facility", POOLCONFIG_MAXNAMELEN);
382 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "LOCAL%d", (pool_config->syslog_facility / 8) - 16);
383 StrNCpy(status[i].desc, "syslog local faclity", POOLCONFIG_MAXDESCLEN);
384 i++;
385
386 StrNCpy(status[i].name, "syslog_ident", POOLCONFIG_MAXNAMELEN);
387 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->syslog_ident);
388 StrNCpy(status[i].desc, "syslog program ident string", POOLCONFIG_MAXDESCLEN);
389 i++;
390
391 /* FILE LOCATIONS */
392
393 StrNCpy(status[i].name, "pid_file_name", POOLCONFIG_MAXNAMELEN);
394 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->pid_file_name);
395 StrNCpy(status[i].desc, "path to pid file", POOLCONFIG_MAXDESCLEN);
396 i++;
397
398 StrNCpy(status[i].name, "logdir", POOLCONFIG_MAXNAMELEN);
399 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->logdir);
400 StrNCpy(status[i].desc, "PgPool status file logging directory", POOLCONFIG_MAXDESCLEN);
401 i++;
402
403 /* CONNECTION POOLING */
404
405 StrNCpy(status[i].name, "connection_cache", POOLCONFIG_MAXNAMELEN);
406 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->connection_cache);
407 StrNCpy(status[i].desc, "if true, cache connection pool", POOLCONFIG_MAXDESCLEN);
408 i++;
409
410 StrNCpy(status[i].name, "reset_query_list", POOLCONFIG_MAXNAMELEN);
411 *(status[i].value) = '\0';
412 for (j = 0; j < pool_config->num_reset_queries; j++)
413 {
414 len = POOLCONFIG_MAXVALLEN - strlen(status[i].value);
415 strncat(status[i].value, pool_config->reset_query_list[j], len);
416 len = POOLCONFIG_MAXVALLEN - strlen(status[i].value);
417 if (j != pool_config->num_reset_queries - 1)
418 strncat(status[i].value, ";", len);
419 }
420 StrNCpy(status[i].desc, "queries issued at the end of session", POOLCONFIG_MAXDESCLEN);
421 i++;
422
423 /* REPLICATION MODE */
424
425 StrNCpy(status[i].name, "replication_mode", POOLCONFIG_MAXNAMELEN);
426 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->replication_mode);
427 StrNCpy(status[i].desc, "non 0 if operating in replication mode", POOLCONFIG_MAXDESCLEN);
428 i++;
429
430 StrNCpy(status[i].name, "replicate_select", POOLCONFIG_MAXNAMELEN);
431 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->replicate_select);
432 StrNCpy(status[i].desc, "non 0 if SELECT statement is replicated", POOLCONFIG_MAXDESCLEN);
433 i++;
434
435 StrNCpy(status[i].name, "insert_lock", POOLCONFIG_MAXNAMELEN);
436 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->insert_lock);
437 StrNCpy(status[i].desc, "insert lock", POOLCONFIG_MAXDESCLEN);
438 i++;
439
440 StrNCpy(status[i].name, "lobj_lock_table", POOLCONFIG_MAXNAMELEN);
441 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->lobj_lock_table);
442 StrNCpy(status[i].desc, "table name used for large object replication control", POOLCONFIG_MAXDESCLEN);
443 i++;
444
445 /* - Degenerate handling - */
446 StrNCpy(status[i].name, "replication_stop_on_mismatch", POOLCONFIG_MAXNAMELEN);
447 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->replication_stop_on_mismatch);
448 StrNCpy(status[i].desc, "stop replication mode on fatal error", POOLCONFIG_MAXDESCLEN);
449 i++;
450
451 StrNCpy(status[i].name, "failover_if_affected_tuples_mismatch", POOLCONFIG_MAXNAMELEN);
452 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->failover_if_affected_tuples_mismatch);
453 StrNCpy(status[i].desc, "failover if affected tuples are mismatch", POOLCONFIG_MAXDESCLEN);
454 i++;
455
456 /* LOAD BALANCING MODE */
457
458 StrNCpy(status[i].name, "load_balance_mode", POOLCONFIG_MAXNAMELEN);
459 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->load_balance_mode);
460 StrNCpy(status[i].desc, "non 0 if operating in load balancing mode", POOLCONFIG_MAXDESCLEN);
461 i++;
462
463 StrNCpy(status[i].name, "ignore_leading_white_space", POOLCONFIG_MAXNAMELEN);
464 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->ignore_leading_white_space);
465 StrNCpy(status[i].desc, "ignore leading white spaces", POOLCONFIG_MAXDESCLEN);
466 i++;
467
468 StrNCpy(status[i].name, "white_function_list", POOLCONFIG_MAXNAMELEN);
469 *(status[i].value) = '\0';
470 for (j = 0; j < pool_config->num_white_function_list; j++)
471 {
472 len = POOLCONFIG_MAXVALLEN - strlen(status[i].value);
473 strncat(status[i].value, pool_config->white_function_list[j], len);
474 len = POOLCONFIG_MAXVALLEN - strlen(status[i].value);
475 if (j != pool_config->num_white_function_list - 1)
476 strncat(status[i].value, ",", len);
477 }
478 StrNCpy(status[i].desc, "functions those do not write to database", POOLCONFIG_MAXDESCLEN);
479 i++;
480
481 StrNCpy(status[i].name, "black_function_list", POOLCONFIG_MAXNAMELEN);
482 *(status[i].value) = '\0';
483 for (j = 0; j < pool_config->num_black_function_list; j++)
484 {
485 len = POOLCONFIG_MAXVALLEN - strlen(status[i].value);
486 strncat(status[i].value, pool_config->black_function_list[j], len);
487 len = POOLCONFIG_MAXVALLEN - strlen(status[i].value);
488 if (j != pool_config->num_black_function_list - 1)
489 strncat(status[i].value, ",", len);
490 }
491 StrNCpy(status[i].desc, "functions those write to database", POOLCONFIG_MAXDESCLEN);
492 i++;
493
494 StrNCpy(status[i].name, "black_query_pattern_list", POOLCONFIG_MAXNAMELEN);
495 *(status[i].value) = '\0';
496 for (j = 0; j < pool_config->num_black_query_pattern_list; j++)
497 {
498 len = POOLCONFIG_MAXVALLEN - strlen(status[i].value);
499 strncat(status[i].value, pool_config->black_query_pattern_list[j], len);
500 len = POOLCONFIG_MAXVALLEN - strlen(status[i].value);
501 if (j != pool_config->num_black_query_pattern_list - 1)
502 strncat(status[i].value, ";", len);
503 }
504 StrNCpy(status[i].desc, "query patterns that should be sent to primary node", POOLCONFIG_MAXDESCLEN);
505 i++;
506
507 StrNCpy(status[i].name, "disable_load_balance_on_write", POOLCONFIG_MAXNAMELEN);
508 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->disable_load_balance_on_write);
509 StrNCpy(status[i].desc, "Load balance behavior when write query is received", POOLCONFIG_MAXDESCLEN);
510 i++;
511
512 StrNCpy(status[i].name, "statement_level_load_balance", POOLCONFIG_MAXNAMELEN);
513 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->statement_level_load_balance);
514 StrNCpy(status[i].desc, "statement level load balancing", POOLCONFIG_MAXDESCLEN);
515 i++;
516
517 /* MASTER/SLAVE MODE */
518
519 StrNCpy(status[i].name, "master_slave_mode", POOLCONFIG_MAXNAMELEN);
520 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->master_slave_mode);
521 StrNCpy(status[i].desc, "if true, operate in master/slave mode", POOLCONFIG_MAXDESCLEN);
522 i++;
523
524 StrNCpy(status[i].name, "master_slave_sub_mode", POOLCONFIG_MAXNAMELEN);
525 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->master_slave_sub_mode);
526 StrNCpy(status[i].desc, "master/slave sub mode", POOLCONFIG_MAXDESCLEN);
527 i++;
528
529 /* - Streaming - */
530 StrNCpy(status[i].name, "sr_check_period", POOLCONFIG_MAXNAMELEN);
531 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->sr_check_period);
532 StrNCpy(status[i].desc, "sr check period", POOLCONFIG_MAXDESCLEN);
533 i++;
534
535 StrNCpy(status[i].name, "sr_check_user", POOLCONFIG_MAXNAMELEN);
536 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->sr_check_user);
537 StrNCpy(status[i].desc, "sr check user", POOLCONFIG_MAXDESCLEN);
538 i++;
539 #ifdef NOT_USED /* for security reason */
540 StrNCpy(status[i].name, "sr_check_password", POOLCONFIG_MAXNAMELEN);
541 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->sr_check_password);
542 StrNCpy(status[i].desc, "sr check password", POOLCONFIG_MAXDESCLEN);
543 i++;
544 #endif
545 StrNCpy(status[i].name, "sr_check_database", POOLCONFIG_MAXNAMELEN);
546 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->sr_check_database);
547 StrNCpy(status[i].desc, "sr check database", POOLCONFIG_MAXDESCLEN);
548 i++;
549
550 StrNCpy(status[i].name, "delay_threshold", POOLCONFIG_MAXNAMELEN);
551 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, INT64_FORMAT, pool_config->delay_threshold);
552 StrNCpy(status[i].desc, "standby delay threshold", POOLCONFIG_MAXDESCLEN);
553 i++;
554
555 /* - Special commands - */
556 StrNCpy(status[i].name, "follow_master_command", POOLCONFIG_MAXNAMELEN);
557 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->follow_master_command);
558 StrNCpy(status[i].desc, "follow master command", POOLCONFIG_MAXDESCLEN);
559 i++;
560
561 StrNCpy(status[i].name, "database_redirect_preference_list", POOLCONFIG_MAXNAMELEN);
562 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->database_redirect_preference_list);
563 StrNCpy(status[i].desc, "redirect by database name", POOLCONFIG_MAXDESCLEN);
564 i++;
565
566 StrNCpy(status[i].name, "app_name_redirect_preference_list", POOLCONFIG_MAXNAMELEN);
567 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->app_name_redirect_preference_list);
568 StrNCpy(status[i].desc, "redirect by application name", POOLCONFIG_MAXDESCLEN);
569 i++;
570
571 StrNCpy(status[i].name, "allow_sql_comments", POOLCONFIG_MAXNAMELEN);
572 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->allow_sql_comments);
573 StrNCpy(status[i].desc, "allow SQL comments", POOLCONFIG_MAXDESCLEN);
574 i++;
575
576 /* HEALTH CHECK */
577
578 StrNCpy(status[i].name, "health_check_period", POOLCONFIG_MAXNAMELEN);
579 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->health_check_period);
580 StrNCpy(status[i].desc, "health check period", POOLCONFIG_MAXDESCLEN);
581 i++;
582
583 StrNCpy(status[i].name, "health_check_timeout", POOLCONFIG_MAXNAMELEN);
584 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->health_check_timeout);
585 StrNCpy(status[i].desc, "health check timeout", POOLCONFIG_MAXDESCLEN);
586 i++;
587
588 StrNCpy(status[i].name, "health_check_user", POOLCONFIG_MAXNAMELEN);
589 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->health_check_user);
590 StrNCpy(status[i].desc, "health check user", POOLCONFIG_MAXDESCLEN);
591 i++;
592 #ifdef NOT_USED /* for security reason */
593 StrNCpy(status[i].name, "health_check_password", POOLCONFIG_MAXNAMELEN);
594 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->health_check_password);
595 StrNCpy(status[i].desc, "health check password", POOLCONFIG_MAXDESCLEN);
596 i++;
597 #endif
598 StrNCpy(status[i].name, "health_check_database", POOLCONFIG_MAXNAMELEN);
599 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->health_check_database);
600 StrNCpy(status[i].desc, "health check database", POOLCONFIG_MAXDESCLEN);
601 i++;
602
603 StrNCpy(status[i].name, "health_check_max_retries", POOLCONFIG_MAXNAMELEN);
604 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->health_check_max_retries);
605 StrNCpy(status[i].desc, "health check max retries", POOLCONFIG_MAXDESCLEN);
606 i++;
607
608 StrNCpy(status[i].name, "health_check_retry_delay", POOLCONFIG_MAXNAMELEN);
609 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->health_check_retry_delay);
610 StrNCpy(status[i].desc, "health check retry delay", POOLCONFIG_MAXDESCLEN);
611 i++;
612
613 StrNCpy(status[i].name, "connect_timeout", POOLCONFIG_MAXNAMELEN);
614 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->connect_timeout);
615 StrNCpy(status[i].desc, "connect timeout", POOLCONFIG_MAXDESCLEN);
616 i++;
617
618 /* FAILOVER AND FAILBACK */
619
620 StrNCpy(status[i].name, "failover_command", POOLCONFIG_MAXNAMELEN);
621 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->failover_command);
622 StrNCpy(status[i].desc, "failover command", POOLCONFIG_MAXDESCLEN);
623 i++;
624
625 StrNCpy(status[i].name, "failback_command", POOLCONFIG_MAXNAMELEN);
626 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->failback_command);
627 StrNCpy(status[i].desc, "failback command", POOLCONFIG_MAXDESCLEN);
628 i++;
629
630 StrNCpy(status[i].name, "failover_on_backend_error", POOLCONFIG_MAXNAMELEN);
631 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->failover_on_backend_error);
632 StrNCpy(status[i].desc, "failover on backend error", POOLCONFIG_MAXDESCLEN);
633 i++;
634
635 StrNCpy(status[i].name, "detach_false_primary", POOLCONFIG_MAXNAMELEN);
636 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->detach_false_primary);
637 StrNCpy(status[i].desc, "detach false primary", POOLCONFIG_MAXDESCLEN);
638 i++;
639
640 StrNCpy(status[i].name, "auto_failback", POOLCONFIG_MAXNAMELEN);
641 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->auto_failback);
642 StrNCpy(status[i].desc, "auto_failback", POOLCONFIG_MAXDESCLEN);
643 i++;
644
645 StrNCpy(status[i].name, "auto_failback_interval", POOLCONFIG_MAXNAMELEN);
646 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->auto_failback_interval);
647 StrNCpy(status[i].desc, "auto_failback_interval", POOLCONFIG_MAXDESCLEN);
648 i++;
649
650 /* ONLINE RECOVERY */
651
652 StrNCpy(status[i].name, "recovery_user", POOLCONFIG_MAXNAMELEN);
653 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->recovery_user);
654 StrNCpy(status[i].desc, "online recovery user", POOLCONFIG_MAXDESCLEN);
655 i++;
656
657 StrNCpy(status[i].name, "recovery_1st_stage_command", POOLCONFIG_MAXNAMELEN);
658 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->recovery_1st_stage_command);
659 StrNCpy(status[i].desc, "execute a command in first stage.", POOLCONFIG_MAXDESCLEN);
660 i++;
661
662 StrNCpy(status[i].name, "recovery_2nd_stage_command", POOLCONFIG_MAXNAMELEN);
663 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->recovery_2nd_stage_command);
664 StrNCpy(status[i].desc, "execute a command in second stage.", POOLCONFIG_MAXDESCLEN);
665 i++;
666
667 StrNCpy(status[i].name, "recovery_timeout", POOLCONFIG_MAXNAMELEN);
668 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->recovery_timeout);
669 StrNCpy(status[i].desc, "max time in seconds to wait for the recovering node's postmaster", POOLCONFIG_MAXDESCLEN);
670 i++;
671
672 StrNCpy(status[i].name, "search_primary_node_timeout", POOLCONFIG_MAXNAMELEN);
673 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->search_primary_node_timeout);
674 StrNCpy(status[i].desc, "max time in seconds to search for primary node after failover", POOLCONFIG_MAXDESCLEN);
675 i++;
676
677 StrNCpy(status[i].name, "client_idle_limit_in_recovery", POOLCONFIG_MAXNAMELEN);
678 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->client_idle_limit_in_recovery);
679 StrNCpy(status[i].desc, "if idle for this seconds, child connection closes in recovery 2nd statge", POOLCONFIG_MAXDESCLEN);
680 i++;
681
682 /* OTHERS */
683
684 StrNCpy(status[i].name, "relcache_expire", POOLCONFIG_MAXNAMELEN);
685 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%ld", pool_config->relcache_expire);
686 StrNCpy(status[i].desc, "relation cache expiration time in seconds", POOLCONFIG_MAXDESCLEN);
687 i++;
688
689 StrNCpy(status[i].name, "relcache_size", POOLCONFIG_MAXNAMELEN);
690 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->relcache_size);
691 StrNCpy(status[i].desc, "number of relation cache entry", POOLCONFIG_MAXDESCLEN);
692 i++;
693
694 StrNCpy(status[i].name, "check_temp_table", POOLCONFIG_MAXNAMELEN);
695 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->check_temp_table);
696 StrNCpy(status[i].desc, "enable temporary table check", POOLCONFIG_MAXDESCLEN);
697 i++;
698
699 StrNCpy(status[i].name, "check_unlogged_table", POOLCONFIG_MAXNAMELEN);
700 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->check_unlogged_table);
701 StrNCpy(status[i].desc, "enable unlogged table check", POOLCONFIG_MAXDESCLEN);
702 i++;
703
704 StrNCpy(status[i].name, "enable_shared_relcache", POOLCONFIG_MAXNAMELEN);
705 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->enable_shared_relcache);
706 StrNCpy(status[i].desc, "If true, relation cache stored in memory cache", POOLCONFIG_MAXDESCLEN);
707 i++;
708
709 StrNCpy(status[i].name, "relcache_query_target", POOLCONFIG_MAXNAMELEN);
710 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->relcache_query_target);
711 StrNCpy(status[i].desc, "Target node to send relcache queries", POOLCONFIG_MAXDESCLEN);
712 i++;
713
714 /*
715 * add for watchdog
716 */
717 StrNCpy(status[i].name, "use_watchdog", POOLCONFIG_MAXNAMELEN);
718 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->use_watchdog);
719 StrNCpy(status[i].desc, "non 0 if operating in use_watchdog", POOLCONFIG_MAXDESCLEN);
720 i++;
721
722 StrNCpy(status[i].name, "wd_ipc_socket_dir", POOLCONFIG_MAXNAMELEN);
723 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->wd_ipc_socket_dir);
724 StrNCpy(status[i].desc, "watchdog ipc socket directory", POOLCONFIG_MAXDESCLEN);
725 i++;
726
727 StrNCpy(status[i].name, "wd_lifecheck_method", POOLCONFIG_MAXNAMELEN);
728 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->wd_lifecheck_method);
729 StrNCpy(status[i].desc, "method of watchdog lifecheck", POOLCONFIG_MAXDESCLEN);
730 i++;
731
732 StrNCpy(status[i].name, "clear_memqcache_on_escalation", POOLCONFIG_MAXNAMELEN);
733 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->clear_memqcache_on_escalation);
734 StrNCpy(status[i].desc, "If true, clear all the query caches in shared memory when escalation occurs", POOLCONFIG_MAXDESCLEN);
735 i++;
736
737 StrNCpy(status[i].name, "wd_escalation_command", POOLCONFIG_MAXNAMELEN);
738 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->wd_escalation_command);
739 StrNCpy(status[i].desc, "command executed when escalation occurs", POOLCONFIG_MAXDESCLEN);
740 i++;
741
742 StrNCpy(status[i].name, "wd_de_escalation_command", POOLCONFIG_MAXNAMELEN);
743 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->wd_de_escalation_command);
744 StrNCpy(status[i].desc, "command executed when master pgpool resigns occurs", POOLCONFIG_MAXDESCLEN);
745 i++;
746
747 StrNCpy(status[i].name, "trusted_servers", POOLCONFIG_MAXNAMELEN);
748 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->trusted_servers);
749 StrNCpy(status[i].desc, "upper server list to observe connection", POOLCONFIG_MAXDESCLEN);
750 i++;
751
752 StrNCpy(status[i].name, "delegate_IP", POOLCONFIG_MAXNAMELEN);
753 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->delegate_IP);
754 StrNCpy(status[i].desc, "delegate IP address of master pgpool", POOLCONFIG_MAXDESCLEN);
755 i++;
756
757 StrNCpy(status[i].name, "wd_hostname", POOLCONFIG_MAXNAMELEN);
758 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->wd_hostname);
759 StrNCpy(status[i].desc, "Host name or IP address of this watchdog", POOLCONFIG_MAXDESCLEN);
760 i++;
761
762 StrNCpy(status[i].name, "wd_port", POOLCONFIG_MAXNAMELEN);
763 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->wd_port);
764 StrNCpy(status[i].desc, "watchdog port number", POOLCONFIG_MAXDESCLEN);
765 i++;
766
767 StrNCpy(status[i].name, "wd_priority", POOLCONFIG_MAXNAMELEN);
768 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->wd_priority);
769 StrNCpy(status[i].desc, "watchdog priority", POOLCONFIG_MAXDESCLEN);
770 i++;
771
772 StrNCpy(status[i].name, "wd_interval", POOLCONFIG_MAXNAMELEN);
773 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->wd_interval);
774 StrNCpy(status[i].desc, "life check interval (second)", POOLCONFIG_MAXDESCLEN);
775 i++;
776
777 StrNCpy(status[i].name, "ping_path", POOLCONFIG_MAXNAMELEN);
778 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->ping_path);
779 StrNCpy(status[i].desc, "path to ping command", POOLCONFIG_MAXDESCLEN);
780 i++;
781
782 StrNCpy(status[i].name, "if_cmd_path", POOLCONFIG_MAXNAMELEN);
783 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->if_cmd_path);
784 StrNCpy(status[i].desc, "path to interface up/down command", POOLCONFIG_MAXDESCLEN);
785 i++;
786
787 StrNCpy(status[i].name, "if_up_cmd", POOLCONFIG_MAXNAMELEN);
788 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->if_up_cmd);
789 StrNCpy(status[i].desc, "virtual interface up command with full parameters", POOLCONFIG_MAXDESCLEN);
790 i++;
791
792 StrNCpy(status[i].name, "if_down_cmd", POOLCONFIG_MAXNAMELEN);
793 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->if_down_cmd);
794 StrNCpy(status[i].desc, "virtual interface down command with full parameters", POOLCONFIG_MAXDESCLEN);
795 i++;
796
797 StrNCpy(status[i].name, "arping_path", POOLCONFIG_MAXNAMELEN);
798 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->arping_path);
799 StrNCpy(status[i].desc, "path to arping command", POOLCONFIG_MAXDESCLEN);
800 i++;
801
802 StrNCpy(status[i].name, "arping_cmd", POOLCONFIG_MAXNAMELEN);
803 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->arping_cmd);
804 StrNCpy(status[i].desc, "send ARP REQUESTi to neighbour host", POOLCONFIG_MAXDESCLEN);
805 i++;
806
807 StrNCpy(status[i].name, "wd_heartbeat_port", POOLCONFIG_MAXNAMELEN);
808 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->wd_heartbeat_port);
809 StrNCpy(status[i].desc, "port number for receiving heartbeat signal", POOLCONFIG_MAXDESCLEN);
810 i++;
811
812 StrNCpy(status[i].name, "wd_heartbeat_keepalive", POOLCONFIG_MAXNAMELEN);
813 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->wd_heartbeat_keepalive);
814 StrNCpy(status[i].desc, "interval time of sending heartbeat siganl (sec)", POOLCONFIG_MAXDESCLEN);
815 i++;
816
817 StrNCpy(status[i].name, "wd_heartbeat_deadtime", POOLCONFIG_MAXNAMELEN);
818 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->wd_heartbeat_deadtime);
819 StrNCpy(status[i].desc, "deadtime interval for heartbeat siganl (sec)", POOLCONFIG_MAXDESCLEN);
820 i++;
821
822 StrNCpy(status[i].name, "wd_life_point", POOLCONFIG_MAXNAMELEN);
823 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->wd_life_point);
824 StrNCpy(status[i].desc, "retry times of life check", POOLCONFIG_MAXDESCLEN);
825 i++;
826
827 StrNCpy(status[i].name, "wd_lifecheck_query", POOLCONFIG_MAXNAMELEN);
828 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->wd_lifecheck_query);
829 StrNCpy(status[i].desc, "lifecheck query to pgpool from watchdog", POOLCONFIG_MAXDESCLEN);
830 i++;
831
832 StrNCpy(status[i].name, "wd_lifecheck_dbname", POOLCONFIG_MAXNAMELEN);
833 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->wd_lifecheck_dbname);
834 StrNCpy(status[i].desc, "database name connected for lifecheck", POOLCONFIG_MAXDESCLEN);
835 i++;
836
837 StrNCpy(status[i].name, "wd_lifecheck_user", POOLCONFIG_MAXNAMELEN);
838 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->wd_lifecheck_user);
839 StrNCpy(status[i].desc, "watchdog user monitoring pgpools in lifecheck", POOLCONFIG_MAXDESCLEN);
840 i++;
841
842 StrNCpy(status[i].name, "wd_lifecheck_password", POOLCONFIG_MAXNAMELEN);
843 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->wd_lifecheck_password);
844 StrNCpy(status[i].desc, "password for watchdog user in lifecheck", POOLCONFIG_MAXDESCLEN);
845 i++;
846
847 StrNCpy(status[i].name, "wd_monitoring_interfaces_list", POOLCONFIG_MAXNAMELEN);
848 *(status[i].value) = '\0';
849 for (j = 0; j < pool_config->num_wd_monitoring_interfaces_list; j++)
850 {
851 len = POOLCONFIG_MAXVALLEN - strlen(status[i].value);
852 strncat(status[i].value, pool_config->wd_monitoring_interfaces_list[j], len);
853 len = POOLCONFIG_MAXVALLEN - strlen(status[i].value);
854 if (j != pool_config->num_wd_monitoring_interfaces_list - 1)
855 strncat(status[i].value, ",", len);
856 }
857 StrNCpy(status[i].desc, "interfaces to monitor by watchdog", POOLCONFIG_MAXDESCLEN);
858 i++;
859
860 /*
861 * end of watchdog
862 */
863
864 StrNCpy(status[i].name, "memory_cache_enabled", POOLCONFIG_MAXNAMELEN);
865 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->memory_cache_enabled);
866 StrNCpy(status[i].desc, "If true, use the memory cache functionality, false by default", POOLCONFIG_MAXDESCLEN);
867 i++;
868
869 StrNCpy(status[i].name, "memqcache_method", POOLCONFIG_MAXNAMELEN);
870 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->memqcache_method);
871 StrNCpy(status[i].desc, "Cache store method. either shmem(shared memory) or Memcached. shmem by default", POOLCONFIG_MAXDESCLEN);
872 i++;
873
874 StrNCpy(status[i].name, "memqcache_memcached_host", POOLCONFIG_MAXNAMELEN);
875 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->memqcache_memcached_host);
876 StrNCpy(status[i].desc, "Memcached host name. Mandatory if memqcache_method=memcached", POOLCONFIG_MAXDESCLEN);
877 i++;
878
879 StrNCpy(status[i].name, "memqcache_memcached_port", POOLCONFIG_MAXNAMELEN);
880 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->memqcache_memcached_port);
881 StrNCpy(status[i].desc, "Memcached port number. Mondatory if memqcache_method=memcached", POOLCONFIG_MAXDESCLEN);
882 i++;
883
884 StrNCpy(status[i].name, "memqcache_total_size", POOLCONFIG_MAXNAMELEN);
885 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%ld", pool_config->memqcache_total_size);
886 StrNCpy(status[i].desc, "Total memory size in bytes for storing memory cache. Mandatory if memqcache_method=shmem", POOLCONFIG_MAXDESCLEN);
887 i++;
888
889 StrNCpy(status[i].name, "memqcache_max_num_cache", POOLCONFIG_MAXNAMELEN);
890 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->memqcache_max_num_cache);
891 StrNCpy(status[i].desc, "Total number of cache entries", POOLCONFIG_MAXDESCLEN);
892 i++;
893
894 StrNCpy(status[i].name, "memqcache_expire", POOLCONFIG_MAXNAMELEN);
895 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->memqcache_expire);
896 StrNCpy(status[i].desc, "Memory cache entry life time specified in seconds. 60 by default", POOLCONFIG_MAXDESCLEN);
897 i++;
898
899 StrNCpy(status[i].name, "memqcache_auto_cache_invalidation", POOLCONFIG_MAXNAMELEN);
900 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->memqcache_auto_cache_invalidation);
901 StrNCpy(status[i].desc, "If true, invalidation of query cache is triggered by corresponding DDL/DML/DCL(and memqcache_expire). If false, it is only triggered by memqcache_expire. True by default.", POOLCONFIG_MAXDESCLEN);
902 i++;
903
904 StrNCpy(status[i].name, "memqcache_maxcache", POOLCONFIG_MAXNAMELEN);
905 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->memqcache_maxcache);
906 StrNCpy(status[i].desc, "Maximum SELECT result size in bytes", POOLCONFIG_MAXDESCLEN);
907 i++;
908
909 StrNCpy(status[i].name, "memqcache_cache_block_size", POOLCONFIG_MAXNAMELEN);
910 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", pool_config->memqcache_cache_block_size);
911 StrNCpy(status[i].desc, "Cache block size in bytes. 8192 by default", POOLCONFIG_MAXDESCLEN);
912 i++;
913
914 StrNCpy(status[i].name, "memqcache_cache_oiddir", POOLCONFIG_MAXNAMELEN);
915 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->memqcache_oiddir);
916 StrNCpy(status[i].desc, "Tempory work directory to record table oids", POOLCONFIG_MAXDESCLEN);
917 i++;
918
919 StrNCpy(status[i].name, "memqcache_stats_start_time", POOLCONFIG_MAXNAMELEN);
920 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", ctime(&pool_get_memqcache_stats()->start_time));
921 StrNCpy(status[i].desc, "Start time of query cache stats", POOLCONFIG_MAXDESCLEN);
922 i++;
923
924 StrNCpy(status[i].name, "memqcache_no_cache_hits", POOLCONFIG_MAXNAMELEN);
925 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%lld", pool_get_memqcache_stats()->num_selects);
926 StrNCpy(status[i].desc, "Number of SELECTs not hitting query cache", POOLCONFIG_MAXDESCLEN);
927 i++;
928
929 StrNCpy(status[i].name, "memqcache_cache_hits", POOLCONFIG_MAXNAMELEN);
930 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%lld", pool_get_memqcache_stats()->num_cache_hits);
931 StrNCpy(status[i].desc, "Number of SELECTs hitting query cache", POOLCONFIG_MAXDESCLEN);
932 i++;
933
934 StrNCpy(status[i].name, "white_memqcache_table_list", POOLCONFIG_MAXNAMELEN);
935 *(status[i].value) = '\0';
936 for (j = 0; j < pool_config->num_white_memqcache_table_list; j++)
937 {
938 len = POOLCONFIG_MAXVALLEN - strlen(status[i].value);
939 strncat(status[i].value, pool_config->white_memqcache_table_list[j], len);
940 len = POOLCONFIG_MAXVALLEN - strlen(status[i].value);
941 if (j != pool_config->num_white_memqcache_table_list - 1)
942 strncat(status[i].value, ",", len);
943 }
944 StrNCpy(status[i].desc, "tables to memqcache", POOLCONFIG_MAXDESCLEN);
945 i++;
946
947 StrNCpy(status[i].name, "black_memqcache_table_list", POOLCONFIG_MAXNAMELEN);
948 *(status[i].value) = '\0';
949 for (j = 0; j < pool_config->num_black_memqcache_table_list; j++)
950 {
951 len = POOLCONFIG_MAXVALLEN - strlen(status[i].value);
952 strncat(status[i].value, pool_config->black_memqcache_table_list[j], len);
953 len = POOLCONFIG_MAXVALLEN - strlen(status[i].value);
954 if (j != pool_config->num_black_memqcache_table_list - 1)
955 strncat(status[i].value, ",", len);
956 }
957 StrNCpy(status[i].desc, "tables not to memqcache", POOLCONFIG_MAXDESCLEN);
958 i++;
959
960 /* BACKENDS */
961
962 for (j = 0; j < NUM_BACKENDS; j++)
963 {
964 if (BACKEND_INFO(j).backend_port == 0)
965 continue;
966
967 snprintf(status[i].name, POOLCONFIG_MAXNAMELEN, "backend_hostname%d", j);
968 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", BACKEND_INFO(j).backend_hostname);
969 snprintf(status[i].desc, POOLCONFIG_MAXDESCLEN, "backend #%d hostname", j);
970 i++;
971
972 snprintf(status[i].name, POOLCONFIG_MAXNAMELEN, "backend_port%d", j);
973 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", BACKEND_INFO(j).backend_port);
974 snprintf(status[i].desc, POOLCONFIG_MAXDESCLEN, "backend #%d port number", j);
975 i++;
976
977 snprintf(status[i].name, POOLCONFIG_MAXNAMELEN, "backend_weight%d", j);
978 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%f", BACKEND_INFO(j).backend_weight / RAND_MAX);
979 snprintf(status[i].desc, POOLCONFIG_MAXDESCLEN, "weight of backend #%d", j);
980 i++;
981
982 snprintf(status[i].name, POOLCONFIG_MAXNAMELEN, "backend_data_directory%d", j);
983 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", BACKEND_INFO(j).backend_data_directory);
984 snprintf(status[i].desc, POOLCONFIG_MAXDESCLEN, "data directory for backend #%d", j);
985 i++;
986
987 snprintf(status[i].name, POOLCONFIG_MAXNAMELEN, "backend_status%d", j);
988 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", backend_status_to_str(&BACKEND_INFO(j)));
989 snprintf(status[i].desc, POOLCONFIG_MAXDESCLEN, "status of backend #%d", j);
990 i++;
991
992 snprintf(status[i].name, POOLCONFIG_MAXNAMELEN, "standby_delay%d", j);
993 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, UINT64_FORMAT, BACKEND_INFO(j).standby_delay);
994 snprintf(status[i].desc, POOLCONFIG_MAXDESCLEN, "standby delay of backend #%d", j);
995 i++;
996
997 snprintf(status[i].name, POOLCONFIG_MAXNAMELEN, "backend_flag%d", j);
998 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_flag_to_str(BACKEND_INFO(j).flag));
999 snprintf(status[i].desc, POOLCONFIG_MAXDESCLEN, "backend #%d flag", j);
1000 i++;
1001
1002 snprintf(status[i].name, POOLCONFIG_MAXNAMELEN, "backend_application_name%d", j);
1003 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", BACKEND_INFO(j).backend_application_name);
1004 snprintf(status[i].desc, POOLCONFIG_MAXDESCLEN, "application_name for backend #%d", j);
1005 i++;
1006 }
1007
1008 for (j = 0; j < MAX_WATCHDOG_NUM; j++)
1009 {
1010 if (WD_INFO(j).pgpool_port == 0)
1011 continue;
1012
1013 snprintf(status[i].name, POOLCONFIG_MAXNAMELEN, "other_pgpool_hostname%d", j);
1014 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", WD_INFO(j).hostname);
1015 snprintf(status[i].desc, POOLCONFIG_MAXDESCLEN, "pgpool #%d hostname", j);
1016 i++;
1017
1018 snprintf(status[i].name, POOLCONFIG_MAXNAMELEN, "other_pgpool_port%d", j);
1019 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", WD_INFO(j).pgpool_port);
1020 snprintf(status[i].desc, POOLCONFIG_MAXDESCLEN, "pgpool #%d port number", j);
1021 i++;
1022
1023 snprintf(status[i].name, POOLCONFIG_MAXNAMELEN, "other_pgpool_wd_port%d", j);
1024 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", WD_INFO(j).wd_port);
1025 snprintf(status[i].desc, POOLCONFIG_MAXDESCLEN, "pgpool #%d watchdog port number", j);
1026 i++;
1027
1028 }
1029
1030 for (j = 0; j < pool_config->num_hb_if; j++)
1031 {
1032 snprintf(status[i].name, POOLCONFIG_MAXNAMELEN, "heartbeat_device%d", j);
1033 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", WD_HB_IF(j).if_name);
1034 snprintf(status[i].desc, POOLCONFIG_MAXDESCLEN, "name of NIC device #%d for sending hearbeat", j);
1035 i++;
1036
1037 snprintf(status[i].name, POOLCONFIG_MAXNAMELEN, "heartbeat_destination%d", j);
1038 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", WD_HB_IF(j).addr);
1039 snprintf(status[i].desc, POOLCONFIG_MAXDESCLEN, "destination host for sending heartbeat using NIC device %d", j);
1040 i++;
1041
1042 snprintf(status[i].name, POOLCONFIG_MAXNAMELEN, "heartbeat_destination_port%d", j);
1043 snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%d", WD_HB_IF(j).dest_port);
1044 snprintf(status[i].desc, POOLCONFIG_MAXDESCLEN, "destination port for sending heartbeat using NIC device %d", j);
1045 i++;
1046 }
1047
1048 *nrows = i;
1049 return status;
1050 }
1051
1052 void
send_config_var_detail_row(POOL_CONNECTION * frontend,POOL_CONNECTION_POOL * backend,const char * name,const char * value,const char * description)1053 send_config_var_detail_row(POOL_CONNECTION * frontend, POOL_CONNECTION_POOL * backend, const char *name, const char *value, const char *description)
1054 {
1055 int size;
1056 int hsize;
1057 static short num_fields = 3;
1058
1059 if (MAJOR(backend) == PROTO_MAJOR_V2)
1060 {
1061
1062 int nbytes = (num_fields + 7) / 8;
1063 static unsigned char nullmap[2] = {0xff, 0xff};
1064
1065 /* ascii row */
1066 pool_write(frontend, "D", 1);
1067 pool_write_and_flush(frontend, nullmap, nbytes);
1068
1069 size = strlen(name);
1070 hsize = htonl(size + 4);
1071 pool_write(frontend, &hsize, sizeof(hsize));
1072 pool_write(frontend, (void *) name, size);
1073
1074 size = strlen(value);
1075 hsize = htonl(size + 4);
1076 pool_write(frontend, &hsize, sizeof(hsize));
1077 pool_write(frontend, (void *) value, size);
1078
1079 size = strlen(description);
1080 hsize = htonl(size + 4);
1081 pool_write(frontend, &hsize, sizeof(hsize));
1082 pool_write(frontend, (void *) description, size);
1083 }
1084 else
1085 {
1086 short s;
1087
1088 pool_write(frontend, "D", 1);
1089 size = 6; /* int32 + int16; */
1090 size += 4 + strlen(name); /* int32 + data; */
1091 size += 4 + strlen(value); /* int32 + data; */
1092 size += 4 + strlen(description); /* int32 + data; */
1093 hsize = htonl(size);
1094 pool_write(frontend, &hsize, sizeof(hsize));
1095 s = htons(num_fields);
1096 pool_write(frontend, &s, sizeof(s));
1097
1098 size = strlen(name);
1099 hsize = htonl(size);
1100 pool_write(frontend, &hsize, sizeof(hsize));
1101 pool_write(frontend, (void *) name, size);
1102
1103 size = strlen(value);
1104 hsize = htonl(size);
1105 pool_write(frontend, &hsize, sizeof(hsize));
1106 pool_write(frontend, (void *) value, size);
1107
1108 size = strlen(description);
1109 hsize = htonl(size);
1110 pool_write(frontend, &hsize, sizeof(hsize));
1111 pool_write(frontend, (void *) description, size);
1112 }
1113 }
1114
1115 void
send_config_var_value_only_row(POOL_CONNECTION * frontend,POOL_CONNECTION_POOL * backend,const char * value)1116 send_config_var_value_only_row(POOL_CONNECTION * frontend, POOL_CONNECTION_POOL * backend, const char *value)
1117 {
1118 int size;
1119 int hsize;
1120 static short num_fields = 1;
1121
1122 if (MAJOR(backend) == PROTO_MAJOR_V2)
1123 {
1124
1125 int nbytes = (num_fields + 7) / 8;
1126 static unsigned char nullmap[2] = {0xff, 0xff};
1127
1128 /* ascii row */
1129 pool_write(frontend, "D", 1);
1130 pool_write_and_flush(frontend, nullmap, nbytes);
1131
1132 size = strlen(value);
1133 hsize = htonl(size + 4);
1134 pool_write(frontend, &hsize, sizeof(hsize));
1135 pool_write(frontend, (void *) value, size);
1136
1137 }
1138 else
1139 {
1140 short s;
1141
1142 pool_write(frontend, "D", 1);
1143 size = 6; /* int32 + int16; */
1144 size += 4 + strlen(value); /* int32 + data; */
1145 hsize = htonl(size);
1146 pool_write(frontend, &hsize, sizeof(hsize));
1147 s = htons(num_fields);
1148 pool_write(frontend, &s, sizeof(s));
1149
1150 size = strlen(value);
1151 hsize = htonl(size);
1152 pool_write(frontend, &hsize, sizeof(hsize));
1153 pool_write(frontend, (void *) value, size);
1154 }
1155 }
1156
1157 void
config_reporting(POOL_CONNECTION * frontend,POOL_CONNECTION_POOL * backend)1158 config_reporting(POOL_CONNECTION * frontend, POOL_CONNECTION_POOL * backend)
1159 {
1160 static char *field_names[] = {"item", "value", "description"};
1161 static unsigned char nullmap[2] = {0xff, 0xff};
1162 static short num_fields = 3;
1163 short s;
1164 int nbytes = (num_fields + 7) / 8;
1165 int len;
1166 int nrows;
1167 int size;
1168 int hsize;
1169 int i;
1170
1171 POOL_REPORT_CONFIG *status = get_config(&nrows);
1172
1173 send_row_description(frontend, backend, num_fields, field_names);
1174
1175 if (MAJOR(backend) == PROTO_MAJOR_V2)
1176 {
1177 /* ascii row */
1178 for (i = 0; i < nrows; i++)
1179 {
1180 pool_write(frontend, "D", 1);
1181 pool_write_and_flush(frontend, nullmap, nbytes);
1182
1183 size = strlen(status[i].name);
1184 hsize = htonl(size + 4);
1185 pool_write(frontend, &hsize, sizeof(hsize));
1186 pool_write(frontend, status[i].name, size);
1187
1188 size = strlen(status[i].value);
1189 hsize = htonl(size + 4);
1190 pool_write(frontend, &hsize, sizeof(hsize));
1191 pool_write(frontend, status[i].value, size);
1192
1193 size = strlen(status[i].desc);
1194 hsize = htonl(size + 4);
1195 pool_write(frontend, &hsize, sizeof(hsize));
1196 pool_write(frontend, status[i].desc, size);
1197 }
1198 }
1199 else
1200 {
1201 /* data row */
1202 for (i = 0; i < nrows; i++)
1203 {
1204 pool_write(frontend, "D", 1);
1205 len = 6; /* int32 + int16; */
1206 len += 4 + strlen(status[i].name); /* int32 + data; */
1207 len += 4 + strlen(status[i].value); /* int32 + data; */
1208 len += 4 + strlen(status[i].desc); /* int32 + data; */
1209 len = htonl(len);
1210 pool_write(frontend, &len, sizeof(len));
1211 s = htons(num_fields);
1212 pool_write(frontend, &s, sizeof(s));
1213
1214 len = htonl(strlen(status[i].name));
1215 pool_write(frontend, &len, sizeof(len));
1216 pool_write(frontend, status[i].name, strlen(status[i].name));
1217
1218 len = htonl(strlen(status[i].value));
1219 pool_write(frontend, &len, sizeof(len));
1220 pool_write(frontend, status[i].value, strlen(status[i].value));
1221
1222 len = htonl(strlen(status[i].desc));
1223 pool_write(frontend, &len, sizeof(len));
1224 pool_write(frontend, status[i].desc, strlen(status[i].desc));
1225 }
1226 }
1227
1228 send_complete_and_ready(frontend, backend, "SELECT", nrows);
1229
1230 pfree(status);
1231 }
1232
1233 /*
1234 * for SHOW pool_nodes
1235 */
1236 POOL_REPORT_NODES *
get_nodes(int * nrows)1237 get_nodes(int *nrows)
1238 {
1239 int i;
1240 POOL_REPORT_NODES *nodes = palloc(NUM_BACKENDS * sizeof(POOL_REPORT_NODES));
1241 BackendInfo *bi = NULL;
1242 POOL_SESSION_CONTEXT *session_context = pool_get_session_context(false);
1243 struct tm tm;
1244
1245 for (i = 0; i < NUM_BACKENDS; i++)
1246 {
1247 bi = pool_get_node_info(i);
1248
1249 snprintf(nodes[i].node_id, POOLCONFIG_MAXIDLEN, "%d", i);
1250 StrNCpy(nodes[i].hostname, bi->backend_hostname, strlen(bi->backend_hostname) + 1);
1251 snprintf(nodes[i].port, POOLCONFIG_MAXPORTLEN, "%d", bi->backend_port);
1252 snprintf(nodes[i].status, POOLCONFIG_MAXSTATLEN, "%s", backend_status_to_str(bi));
1253 snprintf(nodes[i].lb_weight, POOLCONFIG_MAXWEIGHTLEN, "%f", bi->backend_weight / RAND_MAX);
1254 snprintf(nodes[i].select, POOLCONFIG_MAXWEIGHTLEN, UINT64_FORMAT, stat_get_select_count(i));
1255 snprintf(nodes[i].load_balance_node, POOLCONFIG_MAXWEIGHTLEN, "%s",
1256 (session_context->load_balance_node_id == i) ? "true" : "false");
1257
1258 snprintf(nodes[i].delay, POOLCONFIG_MAXWEIGHTLEN, "%d", 0);
1259
1260 if (STREAM)
1261 {
1262 if (i == REAL_PRIMARY_NODE_ID)
1263 {
1264 snprintf(nodes[i].role, POOLCONFIG_MAXWEIGHTLEN, "%s", "primary");
1265 }
1266 else
1267 {
1268 snprintf(nodes[i].role, POOLCONFIG_MAXWEIGHTLEN, "%s", "standby");
1269 snprintf(nodes[i].delay, POOLCONFIG_MAXWEIGHTLEN, UINT64_FORMAT, bi->standby_delay);
1270 }
1271 }
1272 else
1273 {
1274 if (i == REAL_MASTER_NODE_ID)
1275 snprintf(nodes[i].role, POOLCONFIG_MAXWEIGHTLEN, "%s", "master");
1276 else
1277 snprintf(nodes[i].role, POOLCONFIG_MAXWEIGHTLEN, "%s", "slave");
1278 }
1279
1280 /* status last changed */
1281 localtime_r(&bi->status_changed_time, &tm);
1282 strftime(nodes[i].last_status_change, POOLCONFIG_MAXDATELEN, "%F %T", &tm);
1283
1284 /* from pg_stat_replication */
1285 snprintf(nodes[i].rep_state, POOLCONFIG_MAXWEIGHTLEN, "%s", bi->replication_state);
1286 snprintf(nodes[i].rep_sync_state, POOLCONFIG_MAXWEIGHTLEN, "%s", bi->replication_sync_state);
1287 }
1288
1289 *nrows = i;
1290
1291 return nodes;
1292 }
1293
1294 /*
1295 * SHOW pool_nodes;
1296 */
1297 void
nodes_reporting(POOL_CONNECTION * frontend,POOL_CONNECTION_POOL * backend)1298 nodes_reporting(POOL_CONNECTION * frontend, POOL_CONNECTION_POOL * backend)
1299 {
1300 static char *field_names[] = {"node_id", "hostname", "port", "status", "lb_weight", "role", "select_cnt", "load_balance_node", "replication_delay", "replication_state", "replication_sync_state", "last_status_change"};
1301 short num_fields = sizeof(field_names) / sizeof(char *);
1302 int i;
1303 short s;
1304 int len;
1305 int nrows;
1306 int size;
1307 int hsize;
1308 static unsigned char nullmap[2] = {0xff, 0xff};
1309 int nbytes = (num_fields + 7) / 8;
1310
1311 POOL_REPORT_NODES *nodes = get_nodes(&nrows);
1312
1313 send_row_description(frontend, backend, num_fields, field_names);
1314
1315 if (MAJOR(backend) == PROTO_MAJOR_V2)
1316 {
1317 /* ascii row */
1318 for (i = 0; i < nrows; i++)
1319 {
1320 pool_write(frontend, "D", 1);
1321 pool_write_and_flush(frontend, nullmap, nbytes);
1322
1323 size = strlen(nodes[i].node_id);
1324 hsize = htonl(size + 4);
1325 pool_write(frontend, &hsize, sizeof(hsize));
1326 pool_write(frontend, nodes[i].node_id, size);
1327
1328 size = strlen(nodes[i].hostname);
1329 hsize = htonl(size + 4);
1330 pool_write(frontend, &hsize, sizeof(hsize));
1331 pool_write(frontend, nodes[i].hostname, size);
1332
1333 size = strlen(nodes[i].port);
1334 hsize = htonl(size + 4);
1335 pool_write(frontend, &hsize, sizeof(hsize));
1336 pool_write(frontend, nodes[i].port, size);
1337
1338 size = strlen(nodes[i].status);
1339 hsize = htonl(size + 4);
1340 pool_write(frontend, &hsize, sizeof(hsize));
1341 pool_write(frontend, nodes[i].status, size);
1342
1343 size = strlen(nodes[i].lb_weight);
1344 hsize = htonl(size + 4);
1345 pool_write(frontend, &hsize, sizeof(hsize));
1346 pool_write(frontend, nodes[i].lb_weight, size);
1347
1348 size = strlen(nodes[i].role);
1349 hsize = htonl(size + 4);
1350 pool_write(frontend, &hsize, sizeof(hsize));
1351 pool_write(frontend, nodes[i].role, size);
1352
1353 size = strlen(nodes[i].select);
1354 hsize = htonl(size + 4);
1355 pool_write(frontend, &hsize, sizeof(hsize));
1356 pool_write(frontend, nodes[i].select, size);
1357
1358 size = strlen(nodes[i].load_balance_node);
1359 hsize = htonl(size + 4);
1360 pool_write(frontend, &hsize, sizeof(hsize));
1361 pool_write(frontend, nodes[i].load_balance_node, size);
1362
1363 size = strlen(nodes[i].delay);
1364 hsize = htonl(size + 4);
1365 pool_write(frontend, &hsize, sizeof(hsize));
1366 pool_write(frontend, nodes[i].delay, size);
1367
1368 size = strlen(nodes[i].rep_state);
1369 hsize = htonl(size + 4);
1370 pool_write(frontend, &hsize, sizeof(hsize));
1371 pool_write(frontend, nodes[i].rep_state, size);
1372
1373 size = strlen(nodes[i].rep_sync_state);
1374 hsize = htonl(size + 4);
1375 pool_write(frontend, &hsize, sizeof(hsize));
1376 pool_write(frontend, nodes[i].rep_sync_state, size);
1377
1378 size = strlen(nodes[i].last_status_change);
1379 hsize = htonl(size + 4);
1380 pool_write(frontend, &hsize, sizeof(hsize));
1381 pool_write(frontend, nodes[i].last_status_change, size);
1382 }
1383 }
1384 else
1385 {
1386 /* data row */
1387 for (i = 0; i < nrows; i++)
1388 {
1389 pool_write(frontend, "D", 1);
1390 len = 6; /* int32 + int16; */
1391 len += 4 + strlen(nodes[i].node_id); /* int32 + data; */
1392 len += 4 + strlen(nodes[i].hostname); /* int32 + data; */
1393 len += 4 + strlen(nodes[i].port); /* int32 + data; */
1394 len += 4 + strlen(nodes[i].status); /* int32 + data; */
1395 len += 4 + strlen(nodes[i].lb_weight); /* int32 + data; */
1396 len += 4 + strlen(nodes[i].role); /* int32 + data; */
1397 len += 4 + strlen(nodes[i].select); /* int32 + data; */
1398 len += 4 + strlen(nodes[i].load_balance_node); /* int32 + data; */
1399 len += 4 + strlen(nodes[i].delay); /* int32 + data; */
1400 len += 4 + strlen(nodes[i].rep_state); /* int32 + data; */
1401 len += 4 + strlen(nodes[i].rep_sync_state); /* int32 + data; */
1402 len += 4 + strlen(nodes[i].last_status_change); /* int32 + data; */
1403 len = htonl(len);
1404 pool_write(frontend, &len, sizeof(len));
1405 s = htons(num_fields);
1406 pool_write(frontend, &s, sizeof(s));
1407
1408 len = htonl(strlen(nodes[i].node_id));
1409 pool_write(frontend, &len, sizeof(len));
1410 pool_write(frontend, nodes[i].node_id, strlen(nodes[i].node_id));
1411
1412 len = htonl(strlen(nodes[i].hostname));
1413 pool_write(frontend, &len, sizeof(len));
1414 pool_write(frontend, nodes[i].hostname, strlen(nodes[i].hostname));
1415
1416 len = htonl(strlen(nodes[i].port));
1417 pool_write(frontend, &len, sizeof(len));
1418 pool_write(frontend, nodes[i].port, strlen(nodes[i].port));
1419
1420 len = htonl(strlen(nodes[i].status));
1421 pool_write(frontend, &len, sizeof(len));
1422 pool_write(frontend, nodes[i].status, strlen(nodes[i].status));
1423
1424 len = htonl(strlen(nodes[i].lb_weight));
1425 pool_write(frontend, &len, sizeof(len));
1426 pool_write(frontend, nodes[i].lb_weight, strlen(nodes[i].lb_weight));
1427
1428 len = htonl(strlen(nodes[i].role));
1429 pool_write(frontend, &len, sizeof(len));
1430 pool_write(frontend, nodes[i].role, strlen(nodes[i].role));
1431
1432 len = htonl(strlen(nodes[i].select));
1433 pool_write(frontend, &len, sizeof(len));
1434 pool_write(frontend, nodes[i].select, strlen(nodes[i].select));
1435
1436 len = htonl(strlen(nodes[i].load_balance_node));
1437 pool_write(frontend, &len, sizeof(len));
1438 pool_write(frontend, nodes[i].load_balance_node, strlen(nodes[i].load_balance_node));
1439
1440 len = htonl(strlen(nodes[i].delay));
1441 pool_write(frontend, &len, sizeof(len));
1442 pool_write(frontend, nodes[i].delay, strlen(nodes[i].delay));
1443
1444 len = htonl(strlen(nodes[i].rep_state));
1445 pool_write(frontend, &len, sizeof(len));
1446 pool_write(frontend, nodes[i].rep_state, strlen(nodes[i].rep_state));
1447
1448 len = htonl(strlen(nodes[i].rep_sync_state));
1449 pool_write(frontend, &len, sizeof(len));
1450 pool_write(frontend, nodes[i].rep_sync_state, strlen(nodes[i].rep_sync_state));
1451
1452 len = htonl(strlen(nodes[i].last_status_change));
1453 pool_write(frontend, &len, sizeof(len));
1454 pool_write(frontend, nodes[i].last_status_change, strlen(nodes[i].last_status_change));
1455 }
1456 }
1457
1458 send_complete_and_ready(frontend, backend, "SELECT", nrows);
1459
1460 pfree(nodes);
1461 }
1462
1463
1464 POOL_REPORT_POOLS *
get_pools(int * nrows)1465 get_pools(int *nrows)
1466 {
1467 int child,
1468 pool,
1469 poolBE,
1470 backend_id;
1471
1472 ProcessInfo *pi = NULL;
1473 int proc_id;
1474
1475 int lines = 0;
1476
1477 POOL_REPORT_POOLS *pools = palloc(
1478 pool_config->num_init_children * pool_config->max_pool * NUM_BACKENDS * sizeof(POOL_REPORT_POOLS)
1479 );
1480
1481 for (child = 0; child < pool_config->num_init_children; child++)
1482 {
1483 proc_id = process_info[child].pid;
1484 pi = pool_get_process_info(proc_id);
1485
1486 for (pool = 0; pool < pool_config->max_pool; pool++)
1487 {
1488 for (backend_id = 0; backend_id < NUM_BACKENDS; backend_id++)
1489 {
1490 poolBE = pool * MAX_NUM_BACKENDS + backend_id;
1491 pools[lines].pool_pid = proc_id;
1492 pools[lines].start_time = pi->start_time;
1493 pools[lines].pool_id = pool;
1494 pools[lines].backend_id = backend_id;
1495 if (strlen(pi->connection_info[poolBE].database) == 0)
1496 {
1497 StrNCpy(pools[lines].database, "", POOLCONFIG_MAXIDENTLEN);
1498 StrNCpy(pools[lines].username, "", POOLCONFIG_MAXIDENTLEN);
1499 pools[lines].create_time = 0;
1500 pools[lines].pool_majorversion = 0;
1501 pools[lines].pool_minorversion = 0;
1502 }
1503 else
1504 {
1505 StrNCpy(pools[lines].database, pi->connection_info[poolBE].database, POOLCONFIG_MAXIDENTLEN);
1506 StrNCpy(pools[lines].username, pi->connection_info[poolBE].user, POOLCONFIG_MAXIDENTLEN);
1507 pools[lines].create_time = pi->connection_info[poolBE].create_time;
1508 pools[lines].pool_majorversion = pi->connection_info[poolBE].major;
1509 pools[lines].pool_minorversion = pi->connection_info[poolBE].minor;
1510 }
1511 pools[lines].pool_counter = pi->connection_info[poolBE].counter;
1512 pools[lines].pool_backendpid = ntohl(pi->connection_info[poolBE].pid);
1513 pools[lines].pool_connected = pi->connection_info[poolBE].connected;
1514 lines++;
1515 }
1516 }
1517 }
1518
1519 *nrows = lines;
1520 return pools;
1521 }
1522
1523 void
pools_reporting(POOL_CONNECTION * frontend,POOL_CONNECTION_POOL * backend)1524 pools_reporting(POOL_CONNECTION * frontend, POOL_CONNECTION_POOL * backend)
1525 {
1526 static short num_fields = 12;
1527 static char *field_names[] = {"pool_pid", "start_time", "pool_id", "backend_id", "database", "username", "create_time",
1528 "majorversion", "minorversion", "pool_counter", "pool_backendpid", "pool_connected"};
1529 short s;
1530 int len;
1531 int i;
1532 static unsigned char nullmap[2] = {0xff, 0xff};
1533 int nbytes = (num_fields + 7) / 8;
1534 int nrows;
1535 int size;
1536 int hsize;
1537 char proc_pid[16];
1538 char pool_id[16];
1539 char proc_start_time[20];
1540 char proc_create_time[20];
1541 char majorversion[5];
1542 char minorversion[5];
1543 char pool_counter[16];
1544 char backend_id[16];
1545 char backend_pid[16];
1546 char connected[2];
1547
1548 POOL_REPORT_POOLS *pools = get_pools(&nrows);
1549
1550 send_row_description(frontend, backend, num_fields, field_names);
1551
1552 if (MAJOR(backend) == PROTO_MAJOR_V2)
1553 hsize = 4;
1554 else
1555 hsize = 0;
1556
1557 /* ascii row */
1558 for (i = 0; i < nrows; i++)
1559 {
1560 snprintf(proc_pid, sizeof(proc_pid), "%d", pools[i].pool_pid);
1561 snprintf(pool_id, sizeof(pool_id), "%d", pools[i].pool_id);
1562 if (pools[i].start_time)
1563 strftime(proc_start_time, sizeof(proc_start_time), "%Y-%m-%d %H:%M:%S", localtime(&pools[i].start_time));
1564 else
1565 *proc_start_time = '\0';
1566 if (pools[i].create_time)
1567 strftime(proc_create_time, sizeof(proc_create_time), "%Y-%m-%d %H:%M:%S", localtime(&pools[i].create_time));
1568 else
1569 *proc_create_time = '\0';
1570 snprintf(majorversion, sizeof(majorversion), "%d", pools[i].pool_majorversion);
1571 snprintf(minorversion, sizeof(minorversion), "%d", pools[i].pool_minorversion);
1572 snprintf(pool_counter, sizeof(pool_counter), "%d", pools[i].pool_counter);
1573 snprintf(backend_id, sizeof(backend_pid), "%d", pools[i].backend_id);
1574 snprintf(backend_pid, sizeof(backend_pid), "%d", pools[i].pool_backendpid);
1575 snprintf(connected, sizeof(connected), "%d", pools[i].pool_connected);
1576
1577 if (MAJOR(backend) == PROTO_MAJOR_V2)
1578 {
1579 pool_write(frontend, "D", 1);
1580 pool_write_and_flush(frontend, nullmap, nbytes);
1581 }
1582 else
1583 {
1584 pool_write(frontend, "D", 1);
1585 len = 6; /* int32 + int16; */
1586 len += 4 + strlen(proc_pid); /* int32 + data */
1587 len += 4 + strlen(proc_start_time); /* int32 + data */
1588 len += 4 + strlen(pool_id); /* int32 + data */
1589 len += 4 + strlen(backend_id); /* int32 + data */
1590 len += 4 + strlen(pools[i].database); /* int32 + data */
1591 len += 4 + strlen(pools[i].username); /* int32 + data */
1592 len += 4 + strlen(proc_create_time); /* int32 + data */
1593 len += 4 + strlen(majorversion); /* int32 + data */
1594 len += 4 + strlen(minorversion); /* int32 + data */
1595 len += 4 + strlen(pool_counter); /* int32 + data */
1596 len += 4 + strlen(backend_pid); /* int32 + data */
1597 len += 4 + strlen(connected); /* int32 + data */
1598
1599 len = htonl(len);
1600 pool_write(frontend, &len, sizeof(len));
1601 s = htons(num_fields);
1602 pool_write(frontend, &s, sizeof(s));
1603 }
1604
1605 len = strlen(proc_pid);
1606 size = htonl(len + hsize);
1607 pool_write(frontend, &size, sizeof(size));
1608 pool_write(frontend, proc_pid, len);
1609
1610 len = strlen(proc_start_time);
1611 size = htonl(len + hsize);
1612 pool_write(frontend, &size, sizeof(size));
1613 pool_write(frontend, proc_start_time, len);
1614
1615 len = strlen(pool_id);
1616 size = htonl(len + hsize);
1617 pool_write(frontend, &size, sizeof(size));
1618 pool_write(frontend, pool_id, len);
1619
1620 len = strlen(backend_id);
1621 size = htonl(len + hsize);
1622 pool_write(frontend, &size, sizeof(size));
1623 pool_write(frontend, backend_id, len);
1624
1625 len = strlen(pools[i].database);
1626 size = htonl(len + hsize);
1627 pool_write(frontend, &size, sizeof(size));
1628 pool_write(frontend, pools[i].database, len);
1629
1630 len = strlen(pools[i].username);
1631 size = htonl(len + hsize);
1632 pool_write(frontend, &size, sizeof(size));
1633 pool_write(frontend, pools[i].username, len);
1634
1635 len = strlen(proc_create_time);
1636 size = htonl(len + hsize);
1637 pool_write(frontend, &size, sizeof(size));
1638 pool_write(frontend, proc_create_time, len);
1639
1640 len = strlen(majorversion);
1641 size = htonl(len + hsize);
1642 pool_write(frontend, &size, sizeof(size));
1643 pool_write(frontend, majorversion, len);
1644
1645 len = strlen(minorversion);
1646 size = htonl(len + hsize);
1647 pool_write(frontend, &size, sizeof(size));
1648 pool_write(frontend, minorversion, len);
1649
1650 len = strlen(pool_counter);
1651 size = htonl(len + hsize);
1652 pool_write(frontend, &size, sizeof(size));
1653 pool_write(frontend, pool_counter, len);
1654
1655 len = strlen(backend_pid);
1656 size = htonl(len + hsize);
1657 pool_write(frontend, &size, sizeof(size));
1658 pool_write(frontend, backend_pid, len);
1659
1660 len = strlen(connected);
1661 size = htonl(len + hsize);
1662 pool_write(frontend, &size, sizeof(size));
1663 pool_write(frontend, connected, len);
1664 }
1665
1666 send_complete_and_ready(frontend, backend, "SELECT", nrows);
1667
1668 pfree(pools);
1669 }
1670
1671 POOL_REPORT_PROCESSES *
get_processes(int * nrows)1672 get_processes(int *nrows)
1673 {
1674 int child;
1675 int pool;
1676 int poolBE;
1677 ProcessInfo *pi = NULL;
1678 int proc_id;
1679
1680 POOL_REPORT_PROCESSES *processes = palloc(pool_config->num_init_children * sizeof(POOL_REPORT_PROCESSES));
1681
1682 for (child = 0; child < pool_config->num_init_children; child++)
1683 {
1684 proc_id = process_info[child].pid;
1685 pi = pool_get_process_info(proc_id);
1686
1687 snprintf(processes[child].pool_pid, POOLCONFIG_MAXCOUNTLEN, "%d", proc_id);
1688 strftime(processes[child].start_time, POOLCONFIG_MAXDATELEN, "%Y-%m-%d %H:%M:%S", localtime(&pi->start_time));
1689 StrNCpy(processes[child].database, "", POOLCONFIG_MAXIDENTLEN);
1690 StrNCpy(processes[child].username, "", POOLCONFIG_MAXIDENTLEN);
1691 StrNCpy(processes[child].create_time, "", POOLCONFIG_MAXDATELEN);
1692 StrNCpy(processes[child].pool_counter, "", POOLCONFIG_MAXCOUNTLEN);
1693
1694 for (pool = 0; pool < pool_config->max_pool; pool++)
1695 {
1696 poolBE = pool * MAX_NUM_BACKENDS;
1697 if (pi->connection_info[poolBE].connected && strlen(pi->connection_info[poolBE].database) > 0 && strlen(pi->connection_info[poolBE].user) > 0)
1698 {
1699 StrNCpy(processes[child].database, pi->connection_info[poolBE].database, POOLCONFIG_MAXIDENTLEN);
1700 StrNCpy(processes[child].username, pi->connection_info[poolBE].user, POOLCONFIG_MAXIDENTLEN);
1701 strftime(processes[child].create_time, POOLCONFIG_MAXDATELEN, "%Y-%m-%d %H:%M:%S", localtime(&pi->connection_info[poolBE].create_time));
1702 snprintf(processes[child].pool_counter, POOLCONFIG_MAXCOUNTLEN, "%d", pi->connection_info[poolBE].counter);
1703 }
1704 }
1705 }
1706
1707 *nrows = child;
1708
1709 return processes;
1710 }
1711
1712 void
processes_reporting(POOL_CONNECTION * frontend,POOL_CONNECTION_POOL * backend)1713 processes_reporting(POOL_CONNECTION * frontend, POOL_CONNECTION_POOL * backend)
1714 {
1715 static short num_fields = 6;
1716 static char *field_names[] = {"pool_pid", "start_time", "database", "username", "create_time", "pool_counter"};
1717 short s;
1718 int len;
1719 int nrows;
1720 int size;
1721 int hsize;
1722 int i;
1723 static unsigned char nullmap[2] = {0xff, 0xff};
1724 int nbytes = (num_fields + 7) / 8;
1725
1726 POOL_REPORT_PROCESSES *processes = get_processes(&nrows);
1727
1728 send_row_description(frontend, backend, num_fields, field_names);
1729
1730 if (MAJOR(backend) == PROTO_MAJOR_V2)
1731 {
1732 /* ascii row */
1733 for (i = 0; i < nrows; i++)
1734 {
1735 pool_write(frontend, "D", 1);
1736 pool_write_and_flush(frontend, nullmap, nbytes);
1737
1738 size = strlen(processes[i].pool_pid);
1739 hsize = htonl(size + 4);
1740 pool_write(frontend, &hsize, sizeof(hsize));
1741 pool_write(frontend, processes[i].pool_pid, size);
1742
1743 size = strlen(processes[i].start_time);
1744 hsize = htonl(size + 4);
1745 pool_write(frontend, &hsize, sizeof(hsize));
1746 pool_write(frontend, processes[i].start_time, size);
1747
1748 size = strlen(processes[i].database);
1749 hsize = htonl(size + 4);
1750 pool_write(frontend, &hsize, sizeof(hsize));
1751 pool_write(frontend, processes[i].database, size);
1752
1753 size = strlen(processes[i].username);
1754 hsize = htonl(size + 4);
1755 pool_write(frontend, &hsize, sizeof(hsize));
1756 pool_write(frontend, processes[i].username, size);
1757
1758 size = strlen(processes[i].create_time);
1759 hsize = htonl(size + 4);
1760 pool_write(frontend, &hsize, sizeof(hsize));
1761 pool_write(frontend, processes[i].create_time, size);
1762
1763 size = strlen(processes[i].pool_counter);
1764 hsize = htonl(size + 4);
1765 pool_write(frontend, &hsize, sizeof(hsize));
1766 pool_write(frontend, processes[i].pool_counter, size);
1767 }
1768 }
1769 else
1770 {
1771 /* data row */
1772 for (i = 0; i < nrows; i++)
1773 {
1774 pool_write(frontend, "D", 1);
1775 len = 6; /* int32 + int16; */
1776 len += 4 + strlen(processes[i].pool_pid); /* int32 + data */
1777 len += 4 + strlen(processes[i].start_time); /* int32 + data */
1778 len += 4 + strlen(processes[i].database); /* int32 + data */
1779 len += 4 + strlen(processes[i].username); /* int32 + data */
1780 len += 4 + strlen(processes[i].create_time); /* int32 + data */
1781 len += 4 + strlen(processes[i].pool_counter); /* int32 + data */
1782 len = htonl(len);
1783 pool_write(frontend, &len, sizeof(len));
1784 s = htons(num_fields);
1785 pool_write(frontend, &s, sizeof(s));
1786
1787 len = htonl(strlen(processes[i].pool_pid));
1788 pool_write(frontend, &len, sizeof(len));
1789 pool_write(frontend, processes[i].pool_pid, strlen(processes[i].pool_pid));
1790
1791 len = htonl(strlen(processes[i].start_time));
1792 pool_write(frontend, &len, sizeof(len));
1793 pool_write(frontend, processes[i].start_time, strlen(processes[i].start_time));
1794
1795 len = htonl(strlen(processes[i].database));
1796 pool_write(frontend, &len, sizeof(len));
1797 pool_write(frontend, processes[i].database, strlen(processes[i].database));
1798
1799 len = htonl(strlen(processes[i].username));
1800 pool_write(frontend, &len, sizeof(len));
1801 pool_write(frontend, processes[i].username, strlen(processes[i].username));
1802
1803 len = htonl(strlen(processes[i].create_time));
1804 pool_write(frontend, &len, sizeof(len));
1805 pool_write(frontend, processes[i].create_time, strlen(processes[i].create_time));
1806
1807 len = htonl(strlen(processes[i].pool_counter));
1808 pool_write(frontend, &len, sizeof(len));
1809 pool_write(frontend, processes[i].pool_counter, strlen(processes[i].pool_counter));
1810 }
1811 }
1812
1813 send_complete_and_ready(frontend, backend, "SELECT", nrows);
1814
1815 pfree(processes);
1816 }
1817
1818 POOL_REPORT_VERSION *
get_version(void)1819 get_version(void)
1820 {
1821 POOL_REPORT_VERSION *version = palloc(sizeof(POOL_REPORT_VERSION));
1822
1823 snprintf(version[0].version, POOLCONFIG_MAXVALLEN, "%s (%s)", VERSION, PGPOOLVERSION);
1824
1825 return version;
1826 }
1827
1828 void
version_reporting(POOL_CONNECTION * frontend,POOL_CONNECTION_POOL * backend)1829 version_reporting(POOL_CONNECTION * frontend, POOL_CONNECTION_POOL * backend)
1830 {
1831 static short num_fields = 1;
1832 static char *field_names[] = {"pool_version"};
1833 short s;
1834 int len;
1835 int size;
1836 int hsize;
1837
1838 static unsigned char nullmap[2] = {0xff, 0xff};
1839 int nbytes = (num_fields + 7) / 8;
1840
1841 POOL_REPORT_VERSION *version = get_version();
1842
1843 send_row_description(frontend, backend, num_fields, field_names);
1844
1845 if (MAJOR(backend) == PROTO_MAJOR_V2)
1846 {
1847 /* ascii row */
1848 pool_write(frontend, "D", 1);
1849 pool_write_and_flush(frontend, nullmap, nbytes);
1850
1851 size = strlen(version[0].version);
1852 hsize = htonl(size + 4);
1853 pool_write(frontend, &hsize, sizeof(hsize));
1854 pool_write(frontend, version[0].version, size);
1855 }
1856 else
1857 {
1858 /* data row */
1859 pool_write(frontend, "D", 1);
1860 len = 6; /* int32 + int16; */
1861 len += 4 + strlen(version[0].version); /* int32 + data */
1862 len = htonl(len);
1863 pool_write(frontend, &len, sizeof(len));
1864 s = htons(num_fields);
1865 pool_write(frontend, &s, sizeof(s));
1866
1867 len = htonl(strlen(version[0].version));
1868 pool_write(frontend, &len, sizeof(len));
1869 pool_write(frontend, version[0].version, strlen(version[0].version));
1870 }
1871
1872 send_complete_and_ready(frontend, backend, "SELECT", 1);
1873
1874 pfree(version);
1875 }
1876
1877 /*
1878 * Show in memory cache reporting
1879 */
1880 void
cache_reporting(POOL_CONNECTION * frontend,POOL_CONNECTION_POOL * backend)1881 cache_reporting(POOL_CONNECTION * frontend, POOL_CONNECTION_POOL * backend)
1882 {
1883 static char *field_names[] = {"num_cache_hits", "num_selects", "cache_hit_ratio", "num_hash_entries", "used_hash_entries", "num_cache_entries", "used_cache_entries_size", "free_cache_entries_size", "fragment_cache_entries_size"};
1884 short num_fields = sizeof(field_names) / sizeof(char *);
1885 int i;
1886 short s;
1887 int len;
1888 int size;
1889 int hsize;
1890 static unsigned char nullmap[2] = {0xff, 0xff};
1891 int nbytes = (num_fields + 7) / 8;
1892 volatile POOL_SHMEM_STATS *mystats;
1893 pool_sigset_t oldmask;
1894 double ratio;
1895
1896 #define POOL_CACHE_STATS_MAX_STRING_LEN 32
1897 typedef struct
1898 {
1899 int len; /* length of string excluding null terminate */
1900 char string[POOL_CACHE_STATS_MAX_STRING_LEN + 1];
1901 } MY_STRING_CACHE_STATS;
1902
1903 MY_STRING_CACHE_STATS *strp;
1904
1905 strp = palloc(num_fields * sizeof(MY_STRING_CACHE_STATS));
1906
1907 /*
1908 * Get raw cache stat data
1909 */
1910 POOL_SETMASK2(&BlockSig, &oldmask);
1911 pool_shmem_lock();
1912
1913 PG_TRY();
1914 {
1915 mystats = pool_get_shmem_storage_stats();
1916 }
1917 PG_CATCH();
1918 {
1919 pool_shmem_unlock();
1920 POOL_SETMASK(&oldmask);
1921 PG_RE_THROW();
1922 }
1923 PG_END_TRY();
1924 pool_shmem_unlock();
1925 POOL_SETMASK(&oldmask);
1926
1927 /*
1928 * Convert to string
1929 */
1930 i = 0;
1931 snprintf(strp[i++].string, POOL_CACHE_STATS_MAX_STRING_LEN + 1, "%lld", mystats->cache_stats.num_cache_hits);
1932 snprintf(strp[i++].string, POOL_CACHE_STATS_MAX_STRING_LEN + 1, "%lld", mystats->cache_stats.num_selects);
1933 if ((mystats->cache_stats.num_cache_hits + mystats->cache_stats.num_selects) == 0)
1934 {
1935 ratio = 0.0;
1936 }
1937 else
1938 {
1939 ratio = (double) mystats->cache_stats.num_cache_hits / (mystats->cache_stats.num_selects + mystats->cache_stats.num_cache_hits);
1940 }
1941 snprintf(strp[i++].string, POOL_CACHE_STATS_MAX_STRING_LEN + 1, "%.2f", ratio);
1942 snprintf(strp[i++].string, POOL_CACHE_STATS_MAX_STRING_LEN + 1, "%d", mystats->num_hash_entries);
1943 snprintf(strp[i++].string, POOL_CACHE_STATS_MAX_STRING_LEN + 1, "%d", mystats->used_hash_entries);
1944 snprintf(strp[i++].string, POOL_CACHE_STATS_MAX_STRING_LEN + 1, "%d", mystats->num_cache_entries);
1945 snprintf(strp[i++].string, POOL_CACHE_STATS_MAX_STRING_LEN + 1, "%ld", mystats->used_cache_entries_size);
1946 snprintf(strp[i++].string, POOL_CACHE_STATS_MAX_STRING_LEN + 1, "%ld", mystats->free_cache_entries_size);
1947 snprintf(strp[i++].string, POOL_CACHE_STATS_MAX_STRING_LEN + 1, "%ld", mystats->fragment_cache_entries_size);
1948
1949 /*
1950 * Calculate total data length
1951 */
1952 len = 2; /* number of fields (int16) */
1953 for (i = 0; i < num_fields; i++)
1954 {
1955 strp[i].len = strlen(strp[i].string);
1956 len += 4 /* length of string (int32) */
1957 + strp[i].len;
1958 }
1959
1960 /* Send row description */
1961 send_row_description(frontend, backend, num_fields, field_names);
1962
1963 /* Send each field */
1964 if (MAJOR(backend) == PROTO_MAJOR_V2)
1965 {
1966 pool_write(frontend, "D", 1);
1967 pool_write(frontend, nullmap, nbytes);
1968
1969 for (i = 0; i < num_fields; i++)
1970 {
1971 size = strp[i].len + 1;
1972 hsize = htonl(size + 4);
1973 pool_write(frontend, &hsize, sizeof(hsize));
1974 pool_write(frontend, strp[i].string, size);
1975 }
1976 }
1977 else
1978 {
1979 /* Kind */
1980 pool_write(frontend, "D", 1);
1981 /* Packet length */
1982 len = htonl(len + sizeof(int32));
1983 pool_write(frontend, &len, sizeof(len));
1984 /* Number of fields */
1985 s = htons(num_fields);
1986 pool_write(frontend, &s, sizeof(s));
1987
1988 for (i = 0; i < num_fields; i++)
1989 {
1990 hsize = htonl(strp[i].len);
1991 pool_write(frontend, &hsize, sizeof(hsize));
1992 pool_write(frontend, strp[i].string, strp[i].len);
1993 }
1994 }
1995
1996 send_complete_and_ready(frontend, backend, "SELECT", 1);
1997
1998 pfree(strp);
1999 }
2000