1 #include "../../uwsgi.h"
2 #include <libpq-fe.h>
3
4 extern struct uwsgi_server uwsgi;
5 extern struct uwsgi_instance *ui;
6
7 void uwsgi_imperial_monitor_pg_init(struct uwsgi_emperor_scanner *);
8 void uwsgi_imperial_monitor_pg(struct uwsgi_emperor_scanner *);
9 void emperor_pg_init(void);
10
emperor_pg_init(void)11 void emperor_pg_init(void) {
12 uwsgi_register_imperial_monitor("pg", uwsgi_imperial_monitor_pg_init, uwsgi_imperial_monitor_pg);
13 }
14
uwsgi_imperial_monitor_pg_init(struct uwsgi_emperor_scanner * ues)15 void uwsgi_imperial_monitor_pg_init(struct uwsgi_emperor_scanner *ues) {
16 uwsgi_log("[emperor] enabled emperor PostgreSQL monitor\n");
17 }
18
uwsgi_imperial_monitor_pg(struct uwsgi_emperor_scanner * ues)19 void uwsgi_imperial_monitor_pg(struct uwsgi_emperor_scanner *ues) {
20
21 PGconn *conn = NULL;
22 PGresult *res = NULL;
23 const char *query = "SELECT name,config,EXTRACT(epoch FROM ts) FROM vassals";
24
25 char *conn_string = uwsgi_str(ues->arg + 5);
26
27 char *semicolon = strchr(conn_string, ';');
28 if (semicolon) {
29 query = semicolon + 1;
30 *semicolon = '\0';
31 }
32 #ifdef UWSGI_DEBUG
33 uwsgi_log("connecting to PgSQL %s\n", conn_string);
34 #endif
35 conn = PQconnectdb(conn_string);
36 if (!conn || PQstatus(conn) != CONNECTION_OK) {
37 uwsgi_log("libpq-error: %s", PQerrorMessage(conn));
38 goto end;
39 }
40
41 res = PQexec(conn, query);
42 if (!res || PQresultStatus(res) != PGRES_TUPLES_OK) {
43 uwsgi_log("libpq-error: %s\n", PQerrorMessage(conn));
44 goto end;
45 }
46
47 int i;
48
49 for (i = 0; i < PQntuples(res); i++) {
50 if (PQnfields(res) >= 3) {
51 char *name = PQgetvalue(res, i, 0);
52 char *config = PQgetvalue(res, i, 1);
53 char *ts = PQgetvalue(res, i, 2);
54 int len = strlen(ts);
55 char *dot = strchr(ts, '.');
56 if (dot) {
57 len = dot - ts;
58 }
59 uid_t vassal_uid = 0;
60 gid_t vassal_gid = 0;
61 if (uwsgi.emperor_tyrant) {
62 if (PQnfields(res) < 5) {
63 uwsgi_log("[emperor-pg] missing uid and gid for vassal %s\n", name);
64 continue;
65 }
66 char *q_uid = PQgetvalue(res, i, 3);
67 char *q_gid = PQgetvalue(res, i, 4);
68 vassal_uid = uwsgi_str_num(q_uid, strlen(q_uid));
69 vassal_gid = uwsgi_str_num(q_gid, strlen(q_gid));
70 }
71 char *socket_name = NULL;
72 if (PQnfields(res) > 5) {
73 socket_name = PQgetvalue(res, i, 5);
74 }
75 uwsgi_emperor_simple_do(ues, name, config, uwsgi_str_num(ts, len), vassal_uid, vassal_gid, socket_name);
76 }
77 }
78
79 // now check for removed instances
80 struct uwsgi_instance *c_ui = ui->ui_next;
81
82 while (c_ui) {
83 if (c_ui->scanner == ues) {
84 int found = 0;
85 for (i = 0; i < PQntuples(res); i++) {
86 if (PQnfields(res) >= 3) {
87 if (!strcmp(PQgetvalue(res, i, 0), c_ui->name)) {
88 found = 1;
89 break;
90 }
91 }
92 }
93 if (!found) {
94 emperor_stop(c_ui);
95 }
96 }
97 c_ui = c_ui->ui_next;
98 }
99
100
101 end:
102 free(conn_string);
103
104 if (res)
105 PQclear(res);
106 if (conn)
107 PQfinish(conn);
108 }
109
110
111 struct uwsgi_plugin emperor_pg_plugin = {
112
113 .name = "emperor_pg",
114 .on_load = emperor_pg_init,
115 };
116