1
0
mirror of https://github.com/samba-team/samba.git synced 2025-03-10 12:58:35 +03:00
Amitay Isaacs 6635092a76 libctdb: Do not include sys/time.h to support build on AIX
Signed-off-by: Amitay Isaacs <amitay@gmail.com>

(This used to be ctdb commit 2c19fa78ce0b25c3615b23664df32233bdbdea42)
2013-05-29 15:16:54 +10:00

550 lines
14 KiB
C

/*
Misc control routines of libctdb
Copyright (C) Rusty Russell 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <sys/time.h>
#include <sys/socket.h>
#include <string.h>
#include <ctdb.h>
#include <ctdb_protocol.h>
#include "libctdb_private.h"
/* Remove type-safety macros. */
#undef ctdb_getrecmaster_send
#undef ctdb_getrecmode_send
#undef ctdb_getpnn_send
#undef ctdb_getdbstat_send
#undef ctdb_check_message_handlers_send
#undef ctdb_getnodemap_send
#undef ctdb_getpublicips_send
#undef ctdb_getdbseqnum_send
#undef ctdb_getifaces_send
#undef ctdb_getvnnmap_send
#undef ctdb_getcapabilities_send
bool ctdb_getrecmaster_recv(struct ctdb_connection *ctdb,
struct ctdb_request *req, uint32_t *recmaster)
{
struct ctdb_reply_control *reply;
reply = unpack_reply_control(req, CTDB_CONTROL_GET_RECMASTER);
if (!reply) {
return false;
}
if (reply->status == -1) {
DEBUG(ctdb, LOG_ERR, "ctdb_getrecmaster_recv: status -1");
return false;
}
/* Note: data is stashed in status - see ctdb_control_dispatch() */
*recmaster = reply->status;
return true;
}
struct ctdb_request *ctdb_getrecmaster_send(struct ctdb_connection *ctdb,
uint32_t destnode,
ctdb_callback_t callback,
void *private_data)
{
return new_ctdb_control_request(ctdb, CTDB_CONTROL_GET_RECMASTER,
destnode, NULL, 0,
callback, private_data);
}
bool ctdb_getrecmode_recv(struct ctdb_connection *ctdb,
struct ctdb_request *req, uint32_t *recmode)
{
struct ctdb_reply_control *reply;
reply = unpack_reply_control(req, CTDB_CONTROL_GET_RECMODE);
if (!reply) {
return false;
}
if (reply->status == -1) {
DEBUG(ctdb, LOG_ERR, "ctdb_getrecmode_recv: status -1");
return false;
}
/* Note: data is stashed in status - see ctdb_control_dispatch() */
*recmode = reply->status;
return true;
}
struct ctdb_request *ctdb_getrecmode_send(struct ctdb_connection *ctdb,
uint32_t destnode,
ctdb_callback_t callback,
void *private_data)
{
return new_ctdb_control_request(ctdb, CTDB_CONTROL_GET_RECMODE,
destnode, NULL, 0,
callback, private_data);
}
bool ctdb_getpnn_recv(struct ctdb_connection *ctdb,
struct ctdb_request *req, uint32_t *pnn)
{
struct ctdb_reply_control *reply;
reply = unpack_reply_control(req, CTDB_CONTROL_GET_PNN);
if (!reply) {
return false;
}
if (reply->status == -1) {
DEBUG(ctdb, LOG_ERR, "ctdb_getpnn_recv: status -1");
return false;
}
/* Note: data is stashed in status - see ctdb_control_dispatch() */
*pnn = reply->status;
return true;
}
struct ctdb_request *ctdb_getpnn_send(struct ctdb_connection *ctdb,
uint32_t destnode,
ctdb_callback_t callback,
void *private_data)
{
return new_ctdb_control_request(ctdb, CTDB_CONTROL_GET_PNN, destnode,
NULL, 0, callback, private_data);
}
bool ctdb_getdbstat_recv(struct ctdb_connection *ctdb,
struct ctdb_request *req,
struct ctdb_db_statistics **stat)
{
struct ctdb_reply_control *reply;
struct ctdb_db_statistics *s;
struct ctdb_db_statistics_wire *wire;
int i;
char *ptr;
reply = unpack_reply_control(req, CTDB_CONTROL_GET_DB_STATISTICS);
if (!reply) {
return false;
}
if (reply->status == -1) {
DEBUG(ctdb, LOG_ERR, "ctdb_getpnn_recv: status -1");
return false;
}
if (reply->datalen < offsetof(struct ctdb_db_statistics_wire, hot_keys)) {
DEBUG(ctdb, LOG_ERR, "ctdb_getdbstat_recv: returned data is %d bytes but should be >= %d", reply->datalen, (int)sizeof(struct ctdb_db_statistics));
return false;
}
wire = (struct ctdb_db_statistics_wire *)reply->data;
s = malloc(offsetof(struct ctdb_db_statistics, hot_keys) + sizeof(struct ctdb_db_hot_key) * wire->num_hot_keys);
if (!s) {
return false;
}
s->db_ro_delegations = wire->db_ro_delegations;
s->db_ro_revokes = wire->db_ro_revokes;
for (i = 0; i < MAX_COUNT_BUCKETS; i++) {
s->hop_count_bucket[i] = wire->hop_count_bucket[i];
}
s->num_hot_keys = wire->num_hot_keys;
ptr = &wire->hot_keys[0];
for (i = 0; i < wire->num_hot_keys; i++) {
s->hot_keys[i].count = *(uint32_t *)ptr;
ptr += 4;
s->hot_keys[i].key.dsize = *(uint32_t *)ptr;
ptr += 4;
s->hot_keys[i].key.dptr = malloc(s->hot_keys[i].key.dsize);
memcpy(s->hot_keys[i].key.dptr, ptr, s->hot_keys[i].key.dsize);
ptr += s->hot_keys[i].key.dsize;
}
*stat = s;
return true;
}
struct ctdb_request *ctdb_getdbstat_send(struct ctdb_connection *ctdb,
uint32_t destnode,
uint32_t db_id,
ctdb_callback_t callback,
void *private_data)
{
uint32_t indata = db_id;
return new_ctdb_control_request(ctdb, CTDB_CONTROL_GET_DB_STATISTICS, destnode,
&indata, sizeof(indata), callback, private_data);
}
void ctdb_free_dbstat(struct ctdb_db_statistics *stat)
{
int i;
if (stat == NULL) {
return;
}
for (i = 0; i < stat->num_hot_keys; i++) {
if (stat->hot_keys[i].key.dptr != NULL) {
free(stat->hot_keys[i].key.dptr);
}
}
free(stat);
}
bool ctdb_getnodemap_recv(struct ctdb_connection *ctdb,
struct ctdb_request *req, struct ctdb_node_map **nodemap)
{
struct ctdb_reply_control *reply;
*nodemap = NULL;
reply = unpack_reply_control(req, CTDB_CONTROL_GET_NODEMAP);
if (!reply) {
return false;
}
if (reply->status == -1) {
DEBUG(ctdb, LOG_ERR, "ctdb_getnodemap_recv: status -1");
return false;
}
if (reply->datalen == 0) {
DEBUG(ctdb, LOG_ERR, "ctdb_getnodemap_recv: returned data is 0 bytes");
return false;
}
*nodemap = malloc(reply->datalen);
if (*nodemap == NULL) {
DEBUG(ctdb, LOG_ERR, "ctdb_getnodemap_recv: failed to malloc buffer");
return false;
}
memcpy(*nodemap, reply->data, reply->datalen);
return true;
}
struct ctdb_request *ctdb_getnodemap_send(struct ctdb_connection *ctdb,
uint32_t destnode,
ctdb_callback_t callback,
void *private_data)
{
return new_ctdb_control_request(ctdb, CTDB_CONTROL_GET_NODEMAP,
destnode,
NULL, 0, callback, private_data);
}
void ctdb_free_nodemap(struct ctdb_node_map *nodemap)
{
if (nodemap == NULL) {
return;
}
free(nodemap);
}
bool ctdb_getpublicips_recv(struct ctdb_connection *ctdb,
struct ctdb_request *req,
struct ctdb_all_public_ips **ips)
{
struct ctdb_reply_control *reply;
*ips = NULL;
reply = unpack_reply_control(req, CTDB_CONTROL_GET_PUBLIC_IPS);
if (!reply) {
return false;
}
if (reply->status == -1) {
DEBUG(ctdb, LOG_ERR, "ctdb_getpublicips_recv: status -1");
return false;
}
if (reply->datalen == 0) {
DEBUG(ctdb, LOG_ERR, "ctdb_getpublicips_recv: returned data is 0 bytes");
return false;
}
*ips = malloc(reply->datalen);
if (*ips == NULL) {
DEBUG(ctdb, LOG_ERR, "ctdb_getpublicips_recv: failed to malloc buffer");
return false;
}
memcpy(*ips, reply->data, reply->datalen);
return true;
}
struct ctdb_request *ctdb_getpublicips_send(struct ctdb_connection *ctdb,
uint32_t destnode,
ctdb_callback_t callback,
void *private_data)
{
return new_ctdb_control_request(ctdb, CTDB_CONTROL_GET_PUBLIC_IPS,
destnode,
NULL, 0, callback, private_data);
}
void ctdb_free_publicips(struct ctdb_all_public_ips *ips)
{
if (ips == NULL) {
return;
}
free(ips);
}
bool ctdb_getdbseqnum_recv(struct ctdb_connection *ctdb,
struct ctdb_request *req, uint64_t *seqnum)
{
struct ctdb_reply_control *reply;
reply = unpack_reply_control(req, CTDB_CONTROL_GET_DB_SEQNUM);
if (!reply) {
return false;
}
if (reply->status == -1) {
DEBUG(ctdb, LOG_ERR, "ctdb_getdbseqnum_recv: status -1");
return false;
}
if (reply->datalen != sizeof(uint64_t)) {
DEBUG(ctdb, LOG_ERR, "ctdb_getdbseqnum wrong size of data was %d but expected %d bytes", reply->datalen, (int)sizeof(uint64_t));
return false;
}
*seqnum = *((uint64_t *)reply->data);
return true;
}
struct ctdb_request *ctdb_getdbseqnum_send(struct ctdb_connection *ctdb,
uint32_t destnode,
uint32_t dbid,
ctdb_callback_t callback,
void *private_data)
{
uint64_t indata;
*((uint32_t *)&indata) = dbid;
return new_ctdb_control_request(ctdb, CTDB_CONTROL_GET_DB_SEQNUM,
destnode, &indata, sizeof(uint64_t),
callback, private_data);
}
bool ctdb_check_message_handlers_recv(struct ctdb_connection *ctdb,
struct ctdb_request *req,
uint32_t num, uint8_t *result)
{
struct ctdb_reply_control *reply;
int i, count;
reply = unpack_reply_control(req, CTDB_CONTROL_CHECK_SRVIDS);
if (!reply) {
return false;
}
if (reply->status == -1) {
DEBUG(ctdb, LOG_ERR, "ctdb_check_message_handlers_recv: status -1");
return false;
}
count = (num + 7) / 8;
if (count != reply->datalen) {
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);
return false;
}
for (i = 0; i < num; i++) {
result[i] = !!(reply->data[i / 8] & (1 << (i % 8)));
}
return true;
}
struct ctdb_request *
ctdb_check_message_handlers_send(struct ctdb_connection *ctdb,
uint32_t destnode,
uint32_t num,
uint64_t *mhs,
ctdb_callback_t callback,
void *private_data)
{
return new_ctdb_control_request(ctdb, CTDB_CONTROL_CHECK_SRVIDS,
destnode,
mhs, num * sizeof(uint64_t) ,
callback, private_data);
}
bool ctdb_getifaces_recv(struct ctdb_connection *ctdb,
struct ctdb_request *req,
struct ctdb_ifaces_list **ifaces)
{
struct ctdb_reply_control *reply;
struct ctdb_ifaces_list *ifc;
int i, len;
*ifaces = NULL;
reply = unpack_reply_control(req, CTDB_CONTROL_GET_IFACES);
if (!reply) {
return false;
}
if (reply->status == -1) {
DEBUG(ctdb, LOG_ERR, "ctdb_getifaces_recv: status -1");
return false;
}
if (reply->datalen == 0) {
DEBUG(ctdb, LOG_ERR, "ctdb_getifaces_recv: returned data is 0 bytes");
return false;
}
len = offsetof(struct ctdb_ifaces_list, ifaces);
if (len > reply->datalen) {
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));
return false;
}
ifc = (struct ctdb_ifaces_list *)(reply->data);
len += ifc->num * sizeof(struct ctdb_iface_info);
if (len != reply->datalen) {
DEBUG(ctdb, LOG_ERR, "ctdb_getifaces_recv: returned data is %d bytes but should be %d", reply->datalen, len);
return false;
}
ifc = malloc(reply->datalen);
if (ifc == NULL) {
DEBUG(ctdb, LOG_ERR, "ctdb_getifaces_recv: failed to malloc buffer");
return false;
}
memcpy(ifc, reply->data, reply->datalen);
/* make sure we null terminate the returned strings */
for (i = 0; i < ifc->num; i++) {
ifc->ifaces[i].name[CTDB_IFACE_SIZE] = '\0';
}
*ifaces = ifc;
return true;
}
void ctdb_free_ifaces(struct ctdb_ifaces_list *ifaces)
{
free(ifaces);
}
struct ctdb_request *ctdb_getifaces_send(struct ctdb_connection *ctdb,
uint32_t destnode,
ctdb_callback_t callback,
void *private_data)
{
return new_ctdb_control_request(ctdb, CTDB_CONTROL_GET_IFACES,
destnode,
NULL, 0, callback, private_data);
}
bool ctdb_getvnnmap_recv(struct ctdb_connection *ctdb,
struct ctdb_request *req,
struct ctdb_vnn_map **vnnmap)
{
struct ctdb_reply_control *reply;
struct ctdb_vnn_map_wire *map;
struct ctdb_vnn_map *tmap;
int len;
*vnnmap = NULL;
reply = unpack_reply_control(req, CTDB_CONTROL_GETVNNMAP);
if (!reply) {
return false;
}
if (reply->status == -1) {
DEBUG(ctdb, LOG_ERR, "ctdb_getvnnmap_recv: status -1");
return false;
}
if (reply->datalen == 0) {
DEBUG(ctdb, LOG_ERR, "ctdb_getvnnmap_recv: returned data is 0 bytes");
return false;
}
len = offsetof(struct ctdb_vnn_map_wire, map);
if (len > reply->datalen) {
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));
return false;
}
map = (struct ctdb_vnn_map_wire *)(reply->data);
len += map->size * sizeof(uint32_t);
if (len != reply->datalen) {
DEBUG(ctdb, LOG_ERR, "ctdb_getvnnmap_recv: returned data is %d bytes but should be %d", reply->datalen, len);
return false;
}
tmap = malloc(sizeof(struct ctdb_vnn_map));
if (tmap == NULL) {
DEBUG(ctdb, LOG_ERR, "ctdb_getvnnmap_recv: failed to malloc buffer");
return false;
}
tmap->generation = map->generation;
tmap->size = map->size;
tmap->map = malloc(sizeof(uint32_t) * map->size);
if (tmap->map == NULL) {
DEBUG(ctdb, LOG_ERR, "ctdb_getvnnmap_recv: failed to malloc buffer");
free(tmap);
return false;
}
memcpy(tmap->map, map->map, sizeof(uint32_t)*map->size);
*vnnmap = tmap;
return true;
}
void ctdb_free_vnnmap(struct ctdb_vnn_map *vnnmap)
{
free(vnnmap->map);
free(vnnmap);
}
struct ctdb_request *ctdb_getvnnmap_send(struct ctdb_connection *ctdb,
uint32_t destnode,
ctdb_callback_t callback,
void *private_data)
{
return new_ctdb_control_request(ctdb, CTDB_CONTROL_GETVNNMAP,
destnode,
NULL, 0, callback, private_data);
}
bool ctdb_getcapabilities_recv(struct ctdb_connection *ctdb,
struct ctdb_request *req, uint32_t *capabilities)
{
struct ctdb_reply_control *reply;
reply = unpack_reply_control(req, CTDB_CONTROL_GET_CAPABILITIES);
if (!reply) {
return false;
}
if (reply->status == -1) {
DEBUG(ctdb, LOG_ERR, "ctdb_getcapabilities_recv: status -1");
return false;
}
*capabilities = *((uint32_t *)reply->data);
return true;
}
struct ctdb_request *ctdb_getcapabilities_send(struct ctdb_connection *ctdb,
uint32_t destnode,
ctdb_callback_t callback,
void *private_data)
{
return new_ctdb_control_request(ctdb, CTDB_CONTROL_GET_CAPABILITIES,
destnode,
NULL, 0, callback, private_data);
}