~ubuntu-branches/ubuntu/vivid/ctdb/vivid-proposed

« back to all changes in this revision

Viewing changes to utils/pmda/pmda_ctdb.c

  • Committer: Package Import Robot
  • Author(s): Mathieu Parent
  • Date: 2011-11-06 15:18:59 UTC
  • mfrom: (1.2.14)
  • Revision ID: package-import@ubuntu.com-20111106151859-41lblk8ml4es7ra3
Tags: 1.11+git20111102-1
* New upstream release
  - removed 92-apache-service-enable.diff: integrated 
  - removed 99-fix-broken-readdir-test.diff: integrated
* d/rules, d/control, d/compat:
  - converted to dh (% target and dh_auto_*)
  - moved to compat level 9 (buildeps upgraded)
  - dh9 enabled hardening build flags
  - added hardening=+bindnow
  - dh9 enabled multiarch
    + Don't use /use/lib64 on ppc64 (Closes: #644907)
    + libctdb-dev is Multi-Arch: same
    + removed 10_no-lib64.diff: not needed with multiarch
* ctdb.init:
  - removed gettext support
  - synced with upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * CTDB Performance Metrics Domain Agent (PMDA) for Performance Co-Pilot (PCP)
 
3
 *
 
4
 * Copyright (c) 1995,2004 Silicon Graphics, Inc.  All Rights Reserved.
 
5
 * Copyright (c) 2011 David Disseldorp
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or modify it
 
8
 * under the terms of the GNU General Public License as published by the
 
9
 * Free Software Foundation; either version 2 of the License, or (at your
 
10
 * option) any later version.
 
11
 *
 
12
 * This program is distributed in the hope that it will be useful, but
 
13
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 
14
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 
15
 * for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License along
 
18
 * with this program; if not, write to the Free Software Foundation, Inc.,
 
19
 * 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 
20
 */
 
21
 
 
22
#include <pcp/pmapi.h>
 
23
#include <pcp/impl.h>
 
24
#include <pcp/pmda.h>
 
25
#include "../../include/includes.h"
 
26
#include "../../lib/tevent/tevent.h"
 
27
#include "../../include/ctdb.h"
 
28
#include "../../include/ctdb_private.h"
 
29
#include "../../include/ctdb_protocol.h"
 
30
#include "domain.h"
 
31
 
 
32
/*
 
33
 * CTDB PMDA
 
34
 *
 
35
 * This PMDA connects to the locally running ctdbd daemon and pulls
 
36
 * statistics for export via PCP. The ctdbd Unix domain socket path can be
 
37
 * specified with the CTDB_SOCKET environment variable, otherwise the default
 
38
 * path is used.
 
39
 */
 
40
 
 
41
/*
 
42
 * All metrics supported in this PMDA - one table entry for each.
 
43
 * The 4th field specifies the serial number of the instance domain
 
44
 * for the metric, and must be either PM_INDOM_NULL (denoting a
 
45
 * metric that only ever has a single value), or the serial number
 
46
 * of one of the instance domains declared in the instance domain table
 
47
 * (i.e. in indomtab, above).
 
48
 */
 
49
static pmdaMetric metrictab[] = {
 
50
        /* num_clients */
 
51
        { NULL, { PMDA_PMID(0,0), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT,
 
52
                PMDA_PMUNITS(0,0,0,0,0,0) }, },
 
53
        /* frozen */
 
54
        { NULL, { PMDA_PMID(1,2), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT,
 
55
                PMDA_PMUNITS(0,0,0,0,0,0) }, },
 
56
        /* recovering */
 
57
        { NULL, { PMDA_PMID(3,3), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT,
 
58
                PMDA_PMUNITS(0,0,0,0,0,0) }, },
 
59
        /* client_packets_sent */
 
60
        { NULL, { PMDA_PMID(4,4), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER,
 
61
                PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
 
62
        /* client_packets_recv */
 
63
        { NULL, { PMDA_PMID(5,5), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER,
 
64
                PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
 
65
        /* node_packets_sent */
 
66
        { NULL, { PMDA_PMID(6,6), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER,
 
67
                PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
 
68
        /* node_packets_recv */
 
69
        { NULL, { PMDA_PMID(7,7), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER,
 
70
                PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
 
71
        /* keepalive_packets_sent */
 
72
        { NULL, { PMDA_PMID(8,8), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER,
 
73
                PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
 
74
        /* keepalive_packets_recv */
 
75
        { NULL, { PMDA_PMID(9,9), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER,
 
76
                PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
 
77
        /* req_call */
 
78
        { NULL, { PMDA_PMID(10,10), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER,
 
79
                PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
 
80
        /* reply_call */
 
81
        { NULL, { PMDA_PMID(10,11), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER,
 
82
                PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
 
83
        /* req_dmaster */
 
84
        { NULL, { PMDA_PMID(10,12), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER,
 
85
                PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
 
86
        /* reply_dmaster */
 
87
        { NULL, { PMDA_PMID(10,13), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER,
 
88
                PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
 
89
        /* reply_error */
 
90
        { NULL, { PMDA_PMID(10,14), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER,
 
91
                PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
 
92
        /* req_message */
 
93
        { NULL, { PMDA_PMID(10,15), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER,
 
94
                PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
 
95
        /* req_control */
 
96
        { NULL, { PMDA_PMID(10,16), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER,
 
97
                PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
 
98
        /* reply_control */
 
99
        { NULL, { PMDA_PMID(10,17), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER,
 
100
                PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
 
101
        /* req_call */
 
102
        { NULL, { PMDA_PMID(11,18), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER,
 
103
                PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
 
104
        /* req_message */
 
105
        { NULL, { PMDA_PMID(11,19), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER,
 
106
                PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
 
107
        /* req_control */
 
108
        { NULL, { PMDA_PMID(11,20), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER,
 
109
                PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
 
110
        /* call */
 
111
        { NULL, { PMDA_PMID(12,21), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER,
 
112
                PMDA_PMUNITS(0,0,1,0,0,0) }, },
 
113
        /* control */
 
114
        { NULL, { PMDA_PMID(12,22), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER,
 
115
                PMDA_PMUNITS(0,0,1,0,0,0) }, },
 
116
        /* traverse */
 
117
        { NULL, { PMDA_PMID(12,23), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER,
 
118
                PMDA_PMUNITS(0,0,1,0,0,0) }, },
 
119
        /* total_calls */
 
120
        { NULL, { PMDA_PMID(13,24), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER,
 
121
                PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
 
122
        /* pending_calls */
 
123
        { NULL, { PMDA_PMID(14,25), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT,
 
124
                PMDA_PMUNITS(0,0,0,0,0,0) }, },
 
125
        /* lockwait_calls */
 
126
        { NULL, { PMDA_PMID(15,27), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER,
 
127
                PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
 
128
        /* pending_lockwait_calls */
 
129
        { NULL, { PMDA_PMID(16,27), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT,
 
130
                PMDA_PMUNITS(0,0,0,0,0,0) }, },
 
131
        /* childwrite_calls */
 
132
        { NULL, { PMDA_PMID(17,28), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER,
 
133
                PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
 
134
        /* pending_childwrite_calls */
 
135
        { NULL, { PMDA_PMID(18,29), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT,
 
136
                PMDA_PMUNITS(0,0,0,0,0,0) }, },
 
137
        /* memory_used */
 
138
        { NULL, { PMDA_PMID(19,30), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT,
 
139
                PMDA_PMUNITS(1,0,0,PM_SPACE_BYTE,0,0) }, },
 
140
        /* max_hop_count */
 
141
        { NULL, { PMDA_PMID(20,31), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT,
 
142
                PMDA_PMUNITS(0,0,0,0,0,0) }, },
 
143
        /* max_reclock_ctdbd */
 
144
        { NULL, { PMDA_PMID(21,32), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_INSTANT,
 
145
                PMDA_PMUNITS(0,1,0,0,PM_TIME_SEC,0) }, },
 
146
        /* max_reclock_recd */
 
147
        { NULL, { PMDA_PMID(22,33), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_INSTANT,
 
148
                PMDA_PMUNITS(0,1,0,0,PM_TIME_SEC,0) }, },
 
149
        /* max_call_latency */
 
150
        { NULL, { PMDA_PMID(23,34), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_INSTANT,
 
151
                PMDA_PMUNITS(0,1,0,0,PM_TIME_SEC,0) }, },
 
152
        /* max_lockwait_latency */
 
153
        { NULL, { PMDA_PMID(24,35), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_INSTANT,
 
154
                PMDA_PMUNITS(0,1,0,0,PM_TIME_SEC,0) }, },
 
155
        /* max_childwrite_latency */
 
156
        { NULL, { PMDA_PMID(25,36), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_INSTANT,
 
157
                PMDA_PMUNITS(0,1,0,0,PM_TIME_SEC,0) }, },
 
158
        /* num_recoveries */
 
159
        { NULL, { PMDA_PMID(26,37), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT,
 
160
                PMDA_PMUNITS(0,0,0,0,0,0) }, },
 
161
};
 
162
 
 
163
static struct event_context *ev;
 
164
static struct ctdb_context *ctdb;
 
165
static struct ctdb_statistics *stats;
 
166
 
 
167
static void
 
168
pmda_ctdb_q_read_cb(uint8_t *data, size_t cnt, void *args)
 
169
{
 
170
        if (cnt == 0) {
 
171
                fprintf(stderr, "ctdbd unreachable\n");
 
172
                /* cleanup on request timeout */
 
173
                return;
 
174
        }
 
175
 
 
176
        ctdb_client_read_cb(data, cnt, args);
 
177
}
 
178
 
 
179
 
 
180
static int
 
181
pmda_ctdb_daemon_connect(void)
 
182
{
 
183
        const char *socket_name;
 
184
        int ret;
 
185
        struct sockaddr_un addr;
 
186
 
 
187
        ev = event_context_init(NULL);
 
188
        if (ev == NULL) {
 
189
                fprintf(stderr, "Failed to init event ctx\n");
 
190
                return -1;
 
191
        }
 
192
 
 
193
        ctdb = ctdb_init(ev);
 
194
        if (ctdb == NULL) {
 
195
                fprintf(stderr, "Failed to init ctdb\n");
 
196
                goto err_ev;
 
197
        }
 
198
 
 
199
        socket_name = getenv("CTDB_SOCKET");
 
200
        if (socket_name == NULL) {
 
201
                socket_name = CTDB_PATH;
 
202
        }
 
203
 
 
204
        ret = ctdb_set_socketname(ctdb, socket_name);
 
205
        if (ret == -1) {
 
206
                fprintf(stderr, "ctdb_set_socketname failed - %s\n",
 
207
                                ctdb_errstr(ctdb));
 
208
                goto err_ctdb;
 
209
        }
 
210
 
 
211
        /*
 
212
         * ctdb_socket_connect() sets a default queue callback handler that
 
213
         * calls exit() if ctdbd is unavailable on recv, use our own wrapper to
 
214
         * work around this
 
215
         */
 
216
 
 
217
        memset(&addr, 0, sizeof(addr));
 
218
        addr.sun_family = AF_UNIX;
 
219
        strncpy(addr.sun_path, ctdb->daemon.name, sizeof(addr.sun_path));
 
220
 
 
221
        ctdb->daemon.sd = socket(AF_UNIX, SOCK_STREAM, 0);
 
222
        if (ctdb->daemon.sd == -1) {
 
223
                fprintf(stderr, "Failed to open client socket\n");
 
224
                goto err_ctdb;
 
225
        }
 
226
 
 
227
        set_nonblocking(ctdb->daemon.sd);
 
228
        set_close_on_exec(ctdb->daemon.sd);
 
229
 
 
230
        if (connect(ctdb->daemon.sd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
 
231
                fprintf(stderr, "Failed to connect to ctdb daemon via %s\n",
 
232
                        ctdb->daemon.name);
 
233
                goto err_sd;
 
234
        }
 
235
 
 
236
        ctdb->daemon.queue = ctdb_queue_setup(ctdb, ctdb, ctdb->daemon.sd,
 
237
                                              CTDB_DS_ALIGNMENT,
 
238
                                              pmda_ctdb_q_read_cb, ctdb,
 
239
                                              "to-ctdbd");
 
240
        if (ctdb->daemon.queue == NULL) {
 
241
                fprintf(stderr, "Failed to setup queue\n");
 
242
                goto err_sd;
 
243
        }
 
244
 
 
245
        ctdb->pnn = ctdb_ctrl_getpnn(ctdb, timeval_current_ofs(3, 0),
 
246
                                     CTDB_CURRENT_NODE);
 
247
        if (ctdb->pnn == (uint32_t)-1) {
 
248
                fprintf(stderr, "Failed to get ctdb pnn\n");
 
249
                goto err_sd;
 
250
        }
 
251
 
 
252
        return 0;
 
253
err_sd:
 
254
        close(ctdb->daemon.sd);
 
255
err_ctdb:
 
256
        talloc_free(ctdb);
 
257
err_ev:
 
258
        talloc_free(ev);
 
259
        ctdb = NULL;
 
260
        return -1;
 
261
}
 
262
 
 
263
static void
 
264
pmda_ctdb_daemon_disconnect(void)
 
265
{
 
266
        if (ctdb->methods) {
 
267
                ctdb->methods->shutdown(ctdb);
 
268
        }
 
269
 
 
270
        if (ctdb->daemon.sd != -1) {
 
271
                close(ctdb->daemon.sd);
 
272
        }
 
273
 
 
274
        talloc_free(ctdb);
 
275
        talloc_free(ev);
 
276
        ctdb = NULL;
 
277
}
 
278
 
 
279
static int
 
280
fill_node(unsigned int item, pmAtomValue *atom)
 
281
{
 
282
        switch (item) {
 
283
        case 10:
 
284
                atom->ul = stats->node.req_call;
 
285
                break;
 
286
        case 11:
 
287
                atom->ul = stats->node.reply_call;
 
288
                break;
 
289
        case 12:
 
290
                atom->ul = stats->node.req_dmaster;
 
291
                break;
 
292
        case 13:
 
293
                atom->ul = stats->node.reply_dmaster;
 
294
                break;
 
295
        case 14:
 
296
                atom->ul = stats->node.reply_error;
 
297
                break;
 
298
        case 15:
 
299
                atom->ul = stats->node.req_message;
 
300
                break;
 
301
        case 16:
 
302
                atom->ul = stats->node.req_control;
 
303
                break;
 
304
        case 17:
 
305
                atom->ul = stats->node.reply_control;
 
306
                break;
 
307
        default:
 
308
                return PM_ERR_PMID;
 
309
        }
 
310
 
 
311
        return 0;
 
312
}
 
313
 
 
314
static int
 
315
fill_client(unsigned int item, pmAtomValue *atom)
 
316
{
 
317
        switch (item) {
 
318
        case 18:
 
319
                atom->ul = stats->client.req_call;
 
320
                break;
 
321
        case 19:
 
322
                atom->ul = stats->client.req_message;
 
323
                break;
 
324
        case 20:
 
325
                atom->ul = stats->client.req_control;
 
326
                break;
 
327
        default:
 
328
                return PM_ERR_PMID;
 
329
        }
 
330
 
 
331
        return 0;
 
332
}
 
333
 
 
334
static int
 
335
fill_timeout(unsigned int item, pmAtomValue *atom)
 
336
{
 
337
        switch (item) {
 
338
        case 21:
 
339
                atom->ul = stats->timeouts.call;
 
340
                break;
 
341
        case 22:
 
342
                atom->ul = stats->timeouts.control;
 
343
                break;
 
344
        case 23:
 
345
                atom->ul = stats->timeouts.traverse;
 
346
                break;
 
347
        default:
 
348
                return PM_ERR_PMID;
 
349
        }
 
350
 
 
351
        return 0;
 
352
}
 
353
 
 
354
/*
 
355
 * callback provided to pmdaFetch
 
356
 */
 
357
static int
 
358
pmda_ctdb_fetch_cb(pmdaMetric *mdesc, unsigned int inst, pmAtomValue *atom)
 
359
{
 
360
        int ret;
 
361
        __pmID_int *id = (__pmID_int *)&(mdesc->m_desc.pmid);
 
362
 
 
363
        if (inst != PM_IN_NULL) {
 
364
                return PM_ERR_INST;
 
365
        }
 
366
 
 
367
        if (stats == NULL) {
 
368
                fprintf(stderr, "stats not available\n");
 
369
                ret = PM_ERR_VALUE;
 
370
                goto err_out;
 
371
        }
 
372
 
 
373
 
 
374
        switch (id->cluster) {
 
375
        case 0:
 
376
                atom->ul = stats->num_clients;
 
377
                break;
 
378
        case 1:
 
379
                atom->ul = stats->frozen;
 
380
                break;
 
381
        case 3:
 
382
                atom->ul = stats->recovering;
 
383
                break;
 
384
        case 4:
 
385
                atom->ul = stats->client_packets_sent;
 
386
                break;
 
387
        case 5:
 
388
                atom->ul = stats->client_packets_recv;
 
389
                break;
 
390
        case 6:
 
391
                atom->ul = stats->node_packets_sent;
 
392
                break;
 
393
        case 7:
 
394
                atom->ul = stats->node_packets_recv;
 
395
                break;
 
396
        case 8:
 
397
                atom->ul = stats->keepalive_packets_sent;
 
398
                break;
 
399
        case 9:
 
400
                atom->ul = stats->keepalive_packets_recv;
 
401
                break;
 
402
        case 10:
 
403
                ret = fill_node(id->item, atom);
 
404
                if (ret) {
 
405
                        goto err_out;
 
406
                }
 
407
                break;
 
408
        case 11:
 
409
                ret = fill_client(id->item, atom);
 
410
                if (ret) {
 
411
                        goto err_out;
 
412
                }
 
413
                break;
 
414
        case 12:
 
415
                ret = fill_timeout(id->item, atom);
 
416
                if (ret) {
 
417
                        goto err_out;
 
418
                }
 
419
                break;
 
420
        case 13:
 
421
                atom->ul = stats->total_calls;
 
422
                break;
 
423
        case 14:
 
424
                atom->ul = stats->pending_calls;
 
425
                break;
 
426
        case 15:
 
427
                atom->ul = stats->lockwait_calls;
 
428
                break;
 
429
        case 16:
 
430
                atom->ul = stats->pending_lockwait_calls;
 
431
                break;
 
432
        case 17:
 
433
                atom->ul = stats->childwrite_calls;
 
434
                break;
 
435
        case 18:
 
436
                atom->ul = stats->pending_childwrite_calls;
 
437
                break;
 
438
        case 19:
 
439
                atom->ul = stats->memory_used;
 
440
                break;
 
441
        case 20:
 
442
                atom->ul = stats->max_hop_count;
 
443
                break;
 
444
        case 21:
 
445
                atom->d = stats->reclock.ctdbd.max;
 
446
                break;
 
447
        case 22:
 
448
                atom->d = stats->reclock.recd.max;
 
449
                break;
 
450
        case 23:
 
451
                atom->d = stats->call_latency.max;
 
452
                break;
 
453
        case 24:
 
454
                atom->d = stats->lockwait_latency.max;
 
455
                break;
 
456
        case 25:
 
457
                atom->d = stats->childwrite_latency.max;
 
458
                break;
 
459
        case 26:
 
460
                atom->d = stats->num_recoveries;
 
461
                break;
 
462
        default:
 
463
                return PM_ERR_PMID;
 
464
        }
 
465
 
 
466
        ret = 0;
 
467
err_out:
 
468
        return ret;
 
469
}
 
470
 
 
471
/*
 
472
 * This routine is called once for each pmFetch(3) operation, so is a
 
473
 * good place to do once-per-fetch functions, such as value caching or
 
474
 * instance domain evaluation.
 
475
 */
 
476
static int
 
477
pmda_ctdb_fetch(int numpmid, pmID pmidlist[], pmResult **resp, pmdaExt *pmda)
 
478
{
 
479
        int ret;
 
480
        TDB_DATA data;
 
481
        int32_t res;
 
482
        struct timeval ctdb_timeout;
 
483
 
 
484
        if (ctdb == NULL) {
 
485
                fprintf(stderr, "attempting reconnect to ctdbd\n");
 
486
                ret = pmda_ctdb_daemon_connect();
 
487
                if (ret < 0) {
 
488
                        fprintf(stderr, "reconnect failed\n");
 
489
                        return PM_ERR_VALUE;
 
490
                }
 
491
        }
 
492
 
 
493
        ctdb_timeout = timeval_current_ofs(1, 0);
 
494
        ret = ctdb_control(ctdb, ctdb->pnn, 0,
 
495
                           CTDB_CONTROL_STATISTICS, 0, tdb_null,
 
496
                           ctdb, &data, &res, &ctdb_timeout, NULL);
 
497
 
 
498
        if (ret != 0 || res != 0) {
 
499
                fprintf(stderr, "ctdb control for statistics failed, reconnecting\n");
 
500
                pmda_ctdb_daemon_disconnect();
 
501
                ret = PM_ERR_VALUE;
 
502
                goto err_out;
 
503
        }
 
504
 
 
505
        stats = (struct ctdb_statistics *)data.dptr;
 
506
 
 
507
        if (data.dsize != sizeof(struct ctdb_statistics)) {
 
508
                fprintf(stderr, "incorrect statistics size %zu - not %zu\n",
 
509
                        data.dsize, sizeof(struct ctdb_statistics));
 
510
                ret = PM_ERR_VALUE;
 
511
                goto err_stats;
 
512
        }
 
513
 
 
514
        ret = pmdaFetch(numpmid, pmidlist, resp, pmda);
 
515
 
 
516
err_stats:
 
517
        talloc_free(stats);
 
518
err_out:
 
519
        return ret;
 
520
}
 
521
 
 
522
/*
 
523
 * Initialise the agent
 
524
 */
 
525
void
 
526
pmda_ctdb_init(pmdaInterface *dp)
 
527
{
 
528
        if (dp->status != 0) {
 
529
                return;
 
530
        }
 
531
 
 
532
        dp->version.two.fetch = pmda_ctdb_fetch;
 
533
        pmdaSetFetchCallBack(dp, pmda_ctdb_fetch_cb);
 
534
 
 
535
        pmdaInit(dp, NULL, 0, metrictab,
 
536
                 (sizeof(metrictab) / sizeof(metrictab[0])));
 
537
}
 
538
 
 
539
static char *
 
540
helpfile(void)
 
541
{
 
542
        static char buf[MAXPATHLEN];
 
543
 
 
544
        if (!buf[0]) {
 
545
                snprintf(buf, sizeof(buf), "%s/ctdb/help",
 
546
                         pmGetConfig("PCP_PMDAS_DIR"));
 
547
        }
 
548
        return buf;
 
549
}
 
550
 
 
551
static void
 
552
usage(void)
 
553
{
 
554
        fprintf(stderr, "Usage: %s [options]\n\n", pmProgname);
 
555
        fputs("Options:\n"
 
556
          "  -d domain        use domain (numeric) for metrics domain of PMDA\n"
 
557
          "  -l logfile       write log into logfile rather than using default log name\n"
 
558
          "\nExactly one of the following options may appear:\n"
 
559
          "  -i port          expect PMCD to connect on given inet port (number or name)\n"
 
560
          "  -p               expect PMCD to supply stdin/stdout (pipe)\n"
 
561
          "  -u socket        expect PMCD to connect on given unix domain socket\n",
 
562
          stderr);
 
563
        exit(1);
 
564
}
 
565
 
 
566
/*
 
567
 * Set up the agent if running as a daemon.
 
568
 */
 
569
int
 
570
main(int argc, char **argv)
 
571
{
 
572
        int err = 0;
 
573
        char log_file[] = "pmda_ctdb.log";
 
574
        pmdaInterface dispatch;
 
575
 
 
576
        __pmSetProgname(argv[0]);
 
577
 
 
578
        pmdaDaemon(&dispatch, PMDA_INTERFACE_2, pmProgname, CTDB,
 
579
                   log_file, helpfile());
 
580
 
 
581
        if (pmdaGetOpt(argc, argv, "d:i:l:pu:?", &dispatch, &err) != EOF) {
 
582
                err++;
 
583
        }
 
584
 
 
585
        if (err) {
 
586
                usage();
 
587
        }
 
588
 
 
589
        pmdaOpenLog(&dispatch);
 
590
        pmda_ctdb_init(&dispatch);
 
591
        pmdaConnect(&dispatch);
 
592
        pmdaMain(&dispatch);
 
593
 
 
594
        exit(0);
 
595
}
 
596