2 Misc control routines of libctdb
4 Copyright (C) Rusty Russell 2010
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, see <http://www.gnu.org/licenses/>.
19 #include <sys/socket.h>
22 #include <ctdb_protocol.h>
23 #include "libctdb_private.h"
25 /* Remove type-safety macros. */
26 #undef ctdb_getrecmaster_send
27 #undef ctdb_getrecmode_send
28 #undef ctdb_getpnn_send
29 #undef ctdb_getdbstat_send
30 #undef ctdb_check_message_handlers_send
31 #undef ctdb_getnodemap_send
32 #undef ctdb_getpublicips_send
33 #undef ctdb_getdbseqnum_send
34 #undef ctdb_getifaces_send
35 #undef ctdb_getvnnmap_send
37 bool ctdb_getrecmaster_recv(struct ctdb_connection *ctdb,
38 struct ctdb_request *req, uint32_t *recmaster)
40 struct ctdb_reply_control *reply;
42 reply = unpack_reply_control(req, CTDB_CONTROL_GET_RECMASTER);
46 if (reply->status == -1) {
47 DEBUG(ctdb, LOG_ERR, "ctdb_getrecmaster_recv: status -1");
50 *recmaster = reply->status;
54 struct ctdb_request *ctdb_getrecmaster_send(struct ctdb_connection *ctdb,
56 ctdb_callback_t callback,
59 return new_ctdb_control_request(ctdb, CTDB_CONTROL_GET_RECMASTER,
61 callback, private_data);
64 bool ctdb_getrecmode_recv(struct ctdb_connection *ctdb,
65 struct ctdb_request *req, uint32_t *recmode)
67 struct ctdb_reply_control *reply;
69 reply = unpack_reply_control(req, CTDB_CONTROL_GET_RECMODE);
73 if (reply->status == -1) {
74 DEBUG(ctdb, LOG_ERR, "ctdb_getrecmode_recv: status -1");
77 *recmode = reply->status;
81 struct ctdb_request *ctdb_getrecmode_send(struct ctdb_connection *ctdb,
83 ctdb_callback_t callback,
86 return new_ctdb_control_request(ctdb, CTDB_CONTROL_GET_RECMODE,
88 callback, private_data);
91 bool ctdb_getpnn_recv(struct ctdb_connection *ctdb,
92 struct ctdb_request *req, uint32_t *pnn)
94 struct ctdb_reply_control *reply;
96 reply = unpack_reply_control(req, CTDB_CONTROL_GET_PNN);
100 if (reply->status == -1) {
101 DEBUG(ctdb, LOG_ERR, "ctdb_getpnn_recv: status -1");
104 *pnn = reply->status;
108 struct ctdb_request *ctdb_getpnn_send(struct ctdb_connection *ctdb,
110 ctdb_callback_t callback,
113 return new_ctdb_control_request(ctdb, CTDB_CONTROL_GET_PNN, destnode,
114 NULL, 0, callback, private_data);
117 bool ctdb_getdbstat_recv(struct ctdb_connection *ctdb,
118 struct ctdb_request *req,
119 struct ctdb_db_statistics **stat)
121 struct ctdb_reply_control *reply;
122 struct ctdb_db_statistics *s;
123 struct ctdb_db_statistics_wire *wire;
127 reply = unpack_reply_control(req, CTDB_CONTROL_GET_DB_STATISTICS);
131 if (reply->status == -1) {
132 DEBUG(ctdb, LOG_ERR, "ctdb_getpnn_recv: status -1");
135 if (reply->datalen < offsetof(struct ctdb_db_statistics_wire, hot_keys)) {
136 DEBUG(ctdb, LOG_ERR, "ctdb_getdbstat_recv: returned data is %d bytes but should be >= %d", reply->datalen, (int)sizeof(struct ctdb_db_statistics));
142 s = malloc(offsetof(struct ctdb_db_statistics, hot_keys) + sizeof(struct ctdb_db_hot_key) * wire->num_hot_keys);
146 s->db_ro_delegations = wire->db_ro_delegations;
147 s->db_ro_revokes = wire->db_ro_revokes;
148 for (i = 0; i < MAX_COUNT_BUCKETS; i++) {
149 s->hop_count_bucket[i] = wire->hop_count_bucket[i];
151 s->num_hot_keys = wire->num_hot_keys;
152 ptr = &wire->hot_keys[0];
153 for (i = 0; i < wire->num_hot_keys; i++) {
154 s->hot_keys[i].count = *(uint32_t *)ptr;
157 s->hot_keys[i].key.dsize = *(uint32_t *)ptr;
160 s->hot_keys[i].key.dptr = malloc(s->hot_keys[i].key.dsize);
161 memcpy(s->hot_keys[i].key.dptr, ptr, s->hot_keys[i].key.dsize);
162 ptr += s->hot_keys[i].key.dsize;
170 struct ctdb_request *ctdb_getdbstat_send(struct ctdb_connection *ctdb,
173 ctdb_callback_t callback,
176 uint32_t indata = db_id;
178 return new_ctdb_control_request(ctdb, CTDB_CONTROL_GET_DB_STATISTICS, destnode,
179 &indata, sizeof(indata), callback, private_data);
182 void ctdb_free_dbstat(struct ctdb_db_statistics *stat)
190 for (i = 0; i < stat->num_hot_keys; i++) {
191 if (stat->hot_keys[i].key.dptr != NULL) {
192 free(stat->hot_keys[i].key.dptr);
199 bool ctdb_getnodemap_recv(struct ctdb_connection *ctdb,
200 struct ctdb_request *req, struct ctdb_node_map **nodemap)
202 struct ctdb_reply_control *reply;
205 reply = unpack_reply_control(req, CTDB_CONTROL_GET_NODEMAP);
209 if (reply->status == -1) {
210 DEBUG(ctdb, LOG_ERR, "ctdb_getnodemap_recv: status -1");
213 if (reply->datalen == 0) {
214 DEBUG(ctdb, LOG_ERR, "ctdb_getnodemap_recv: returned data is 0 bytes");
218 *nodemap = malloc(reply->datalen);
219 if (*nodemap == NULL) {
220 DEBUG(ctdb, LOG_ERR, "ctdb_getnodemap_recv: failed to malloc buffer");
223 memcpy(*nodemap, reply->data, reply->datalen);
227 struct ctdb_request *ctdb_getnodemap_send(struct ctdb_connection *ctdb,
229 ctdb_callback_t callback,
232 return new_ctdb_control_request(ctdb, CTDB_CONTROL_GET_NODEMAP,
234 NULL, 0, callback, private_data);
237 void ctdb_free_nodemap(struct ctdb_node_map *nodemap)
239 if (nodemap == NULL) {
245 bool ctdb_getpublicips_recv(struct ctdb_connection *ctdb,
246 struct ctdb_request *req,
247 struct ctdb_all_public_ips **ips)
249 struct ctdb_reply_control *reply;
252 reply = unpack_reply_control(req, CTDB_CONTROL_GET_PUBLIC_IPS);
256 if (reply->status == -1) {
257 DEBUG(ctdb, LOG_ERR, "ctdb_getpublicips_recv: status -1");
260 if (reply->datalen == 0) {
261 DEBUG(ctdb, LOG_ERR, "ctdb_getpublicips_recv: returned data is 0 bytes");
265 *ips = malloc(reply->datalen);
267 DEBUG(ctdb, LOG_ERR, "ctdb_getpublicips_recv: failed to malloc buffer");
270 memcpy(*ips, reply->data, reply->datalen);
274 struct ctdb_request *ctdb_getpublicips_send(struct ctdb_connection *ctdb,
276 ctdb_callback_t callback,
279 return new_ctdb_control_request(ctdb, CTDB_CONTROL_GET_PUBLIC_IPS,
281 NULL, 0, callback, private_data);
284 void ctdb_free_publicips(struct ctdb_all_public_ips *ips)
292 bool ctdb_getdbseqnum_recv(struct ctdb_connection *ctdb,
293 struct ctdb_request *req, uint64_t *seqnum)
295 struct ctdb_reply_control *reply;
297 reply = unpack_reply_control(req, CTDB_CONTROL_GET_DB_SEQNUM);
301 if (reply->status == -1) {
302 DEBUG(ctdb, LOG_ERR, "ctdb_getdbseqnum_recv: status -1");
306 if (reply->datalen != sizeof(uint64_t)) {
307 DEBUG(ctdb, LOG_ERR, "ctdb_getdbseqnum wrong size of data was %d but expected %d bytes", reply->datalen, (int)sizeof(uint64_t));
311 *seqnum = *((uint64_t *)reply->data);
316 struct ctdb_request *ctdb_getdbseqnum_send(struct ctdb_connection *ctdb,
319 ctdb_callback_t callback,
324 *((uint32_t *)&indata) = dbid;
326 return new_ctdb_control_request(ctdb, CTDB_CONTROL_GET_DB_SEQNUM,
327 destnode, &indata, sizeof(uint64_t),
328 callback, private_data);
331 bool ctdb_check_message_handlers_recv(struct ctdb_connection *ctdb,
332 struct ctdb_request *req,
333 uint32_t num, uint8_t *result)
335 struct ctdb_reply_control *reply;
338 reply = unpack_reply_control(req, CTDB_CONTROL_CHECK_SRVIDS);
342 if (reply->status == -1) {
343 DEBUG(ctdb, LOG_ERR, "ctdb_check_message_handlers_recv: status -1");
347 count = (num + 7) / 8;
348 if (count != reply->datalen) {
349 DEBUG(ctdb, LOG_ERR, "ctdb_check_message_handlers_recv: wrong amount of data returned, expected %d bytes for %d srvids but received %d bytes", count, num, reply->datalen);
353 for (i = 0; i < num; i++) {
354 result[i] = !!(reply->data[i / 8] & (1 << (i % 8)));
360 struct ctdb_request *
361 ctdb_check_message_handlers_send(struct ctdb_connection *ctdb,
365 ctdb_callback_t callback,
368 return new_ctdb_control_request(ctdb, CTDB_CONTROL_CHECK_SRVIDS,
370 mhs, num * sizeof(uint64_t) ,
371 callback, private_data);
375 bool ctdb_getifaces_recv(struct ctdb_connection *ctdb,
376 struct ctdb_request *req,
377 struct ctdb_ifaces_list **ifaces)
379 struct ctdb_reply_control *reply;
380 struct ctdb_ifaces_list *ifc;
384 reply = unpack_reply_control(req, CTDB_CONTROL_GET_IFACES);
388 if (reply->status == -1) {
389 DEBUG(ctdb, LOG_ERR, "ctdb_getifaces_recv: status -1");
392 if (reply->datalen == 0) {
393 DEBUG(ctdb, LOG_ERR, "ctdb_getifaces_recv: returned data is 0 bytes");
397 len = offsetof(struct ctdb_ifaces_list, ifaces);
398 if (len > reply->datalen) {
399 DEBUG(ctdb, LOG_ERR, "ctdb_getifaces_recv: returned data is %d bytes but %d is minimum", reply->datalen, (int)offsetof(struct ctdb_ifaces_list, ifaces));
403 ifc = (struct ctdb_ifaces_list *)(reply->data);
404 len += ifc->num * sizeof(struct ctdb_iface_info);
406 if (len != reply->datalen) {
407 DEBUG(ctdb, LOG_ERR, "ctdb_getifaces_recv: returned data is %d bytes but should be %d", reply->datalen, len);
411 ifc = malloc(reply->datalen);
413 DEBUG(ctdb, LOG_ERR, "ctdb_getifaces_recv: failed to malloc buffer");
416 memcpy(ifc, reply->data, reply->datalen);
418 /* make sure we null terminate the returned strings */
419 for (i = 0; i < ifc->num; i++) {
420 ifc->ifaces[i].name[CTDB_IFACE_SIZE] = '\0';
428 void ctdb_free_ifaces(struct ctdb_ifaces_list *ifaces)
433 struct ctdb_request *ctdb_getifaces_send(struct ctdb_connection *ctdb,
435 ctdb_callback_t callback,
438 return new_ctdb_control_request(ctdb, CTDB_CONTROL_GET_IFACES,
440 NULL, 0, callback, private_data);
443 bool ctdb_getvnnmap_recv(struct ctdb_connection *ctdb,
444 struct ctdb_request *req,
445 struct ctdb_vnn_map **vnnmap)
447 struct ctdb_reply_control *reply;
448 struct ctdb_vnn_map_wire *map;
449 struct ctdb_vnn_map *tmap;
453 reply = unpack_reply_control(req, CTDB_CONTROL_GETVNNMAP);
457 if (reply->status == -1) {
458 DEBUG(ctdb, LOG_ERR, "ctdb_getvnnmap_recv: status -1");
461 if (reply->datalen == 0) {
462 DEBUG(ctdb, LOG_ERR, "ctdb_getvnnmap_recv: returned data is 0 bytes");
466 len = offsetof(struct ctdb_vnn_map_wire, map);
467 if (len > reply->datalen) {
468 DEBUG(ctdb, LOG_ERR, "ctdb_getvnnmap_recv: returned data is %d bytes but %d is minimum", reply->datalen, (int)offsetof(struct ctdb_vnn_map_wire, map));
472 map = (struct ctdb_vnn_map_wire *)(reply->data);
473 len += map->size * sizeof(uint32_t);
475 if (len != reply->datalen) {
476 DEBUG(ctdb, LOG_ERR, "ctdb_getvnnmap_recv: returned data is %d bytes but should be %d", reply->datalen, len);
480 tmap = malloc(sizeof(struct ctdb_vnn_map));
482 DEBUG(ctdb, LOG_ERR, "ctdb_getvnnmap_recv: failed to malloc buffer");
486 tmap->generation = map->generation;
487 tmap->size = map->size;
488 tmap->map = malloc(sizeof(uint32_t) * map->size);
489 if (tmap->map == NULL) {
490 DEBUG(ctdb, LOG_ERR, "ctdb_getvnnmap_recv: failed to malloc buffer");
495 memcpy(tmap->map, map->map, sizeof(uint32_t)*map->size);
502 void ctdb_free_vnnmap(struct ctdb_vnn_map *vnnmap)
508 struct ctdb_request *ctdb_getvnnmap_send(struct ctdb_connection *ctdb,
510 ctdb_callback_t callback,
513 return new_ctdb_control_request(ctdb, CTDB_CONTROL_GETVNNMAP,
515 NULL, 0, callback, private_data);