1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-21 01:59:07 +03:00
samba-mirror/ctdb/ib/ibw_ctdb.c
Peter Somogyi 1714c1ed0c ib: added external send queue to workaround downtime
Workaround is because I couldn't find a correct way in ib to reconnect cleanly (with queue kept) when destination is unreachable.
When connection is broken, all internal queue contents are being destroyed and reconnects automatically.
An "external" send queue is kept until the connection is up again for a dest node.

(This used to be ctdb commit 49cac6eafb9d9c80ef1c7f0388aa7786c8be6f24)
2007-02-26 11:59:20 +01:00

158 lines
4.9 KiB
C

/*
* Unix SMB/CIFS implementation.
* Join infiniband wrapper and ctdb.
*
* Copyright (C) Sven Oehme <oehmes@de.ibm.com> 2006
*
* Major code contributions by Peter Somogyi <psomogyi@gamax.hu>
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
#include "lib/events/events.h"
#include <system/network.h>
#include <assert.h>
#include "ctdb_private.h"
#include "ibwrapper.h"
#include "ibw_ctdb.h"
int ctdb_ibw_node_connect(struct ctdb_node *node)
{
struct ctdb_ibw_node *cn = talloc_get_type(node->private, struct ctdb_ibw_node);
int rc;
assert(cn!=NULL);
assert(cn->conn!=NULL);
struct sockaddr_in sock_out;
memset(&sock_out, 0, sizeof(struct sockaddr_in));
inet_pton(AF_INET, node->address.address, &sock_out.sin_addr);
sock_out.sin_port = htons(node->address.port);
sock_out.sin_family = PF_INET;
rc = ibw_connect(cn->conn, &sock_out, node);
if (rc) {
DEBUG(0, ("ctdb_ibw_node_connect/ibw_connect failed - retrying...\n"));
/* try again once a second */
event_add_timed(node->ctdb->ev, node, timeval_current_ofs(1, 0),
ctdb_ibw_node_connect_event, node);
}
/* continues at ibw_ctdb.c/IBWC_CONNECTED in good case */
return 0;
}
void ctdb_ibw_node_connect_event(struct event_context *ev, struct timed_event *te,
struct timeval t, void *private)
{
struct ctdb_node *node = talloc_get_type(private, struct ctdb_node);
ctdb_ibw_node_connect(node);
}
int ctdb_ibw_connstate_handler(struct ibw_ctx *ctx, struct ibw_conn *conn)
{
if (ctx!=NULL) {
/* ctx->state changed */
switch(ctx->state) {
case IBWS_INIT: /* ctx start - after ibw_init */
break;
case IBWS_READY: /* after ibw_bind & ibw_listen */
break;
case IBWS_CONNECT_REQUEST: /* after [IBWS_READY + incoming request] */
/* => [(ibw_accept)IBWS_READY | (ibw_disconnect)STOPPED | ERROR] */
if (ibw_accept(ctx, conn, NULL)) {
DEBUG(0, ("connstate_handler/ibw_accept failed\n"));
return -1;
} /* else continue in IBWC_CONNECTED */
break;
case IBWS_STOPPED: /* normal stop <= ibw_disconnect+(IBWS_READY | IBWS_CONNECT_REQUEST) */
/* TODO: have a CTDB upcall for which CTDB should wait in a (final) loop */
break;
case IBWS_ERROR: /* abnormal state; ibw_stop must be called after this */
break;
default:
assert(0);
break;
}
}
if (conn!=NULL) {
/* conn->state changed */
switch(conn->state) {
case IBWC_INIT: /* conn start - internal state */
break;
case IBWC_CONNECTED: { /* after ibw_accept or ibw_connect */
struct ctdb_node *node = talloc_get_type(conn->conn_userdata, struct ctdb_node);
if (node!=NULL) { /* after ibw_connect */
struct ctdb_ibw_node *cn = talloc_get_type(node->private, struct ctdb_ibw_node);
node->ctdb->upcalls->node_connected(node);
ctdb_flush_cn_queue(cn);
} else { /* after ibw_accept */
/* NOP in CTDB case */
}
} break;
case IBWC_DISCONNECTED: { /* after ibw_disconnect */
struct ctdb_node *node = talloc_get_type(conn->conn_userdata, struct ctdb_node);
if (node!=NULL)
node->ctdb->upcalls->node_dead(node);
talloc_free(conn);
/* normal + intended disconnect => not reconnecting in this layer */
} break;
case IBWC_ERROR: {
struct ctdb_node *node = talloc_get_type(conn->conn_userdata, struct ctdb_node);
if (node!=NULL) {
struct ctdb_ibw_node *cn = talloc_get_type(node->private, struct ctdb_ibw_node);
struct ibw_ctx *ictx = cn->conn->ctx;
DEBUG(10, ("IBWC_ERROR, reconnecting...\n"));
talloc_free(cn->conn); /* internal queue content is destroyed */
cn->conn = (void *)ibw_conn_new(ictx, node);
event_add_timed(node->ctdb->ev, node, timeval_current_ofs(1, 0),
ctdb_ibw_node_connect_event, node);
}
} break;
default:
assert(0);
break;
}
}
return 0;
}
int ctdb_ibw_receive_handler(struct ibw_conn *conn, void *buf, int n)
{
struct ctdb_context *ctdb = talloc_get_type(conn->ctx->ctx_userdata, struct ctdb_context);
void *buf2; /* future TODO: a solution for removal of this */
assert(ctdb!=NULL);
assert(buf!=NULL);
assert(conn!=NULL);
assert(conn->state==IBWC_CONNECTED);
/* so far "buf" is an ib-registered memory area
* and being reused for next receive
* noticed that HL requires talloc-ed memory to be stolen */
buf2 = talloc_zero_size(conn, n);
memcpy(buf2, buf, n);
ctdb->upcalls->recv_pkt(ctdb, (uint8_t *)buf2, (uint32_t)n);
return 0;
}