From: Andrew Tridgell Date: Tue, 28 Nov 2006 06:56:10 +0000 (+1100) Subject: - added simple (fake) vnn system X-Git-Tag: tevent-0.9.20~348^2~3013 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=fdb317facfdb60c87695b557a4680401c210031a;p=thirdparty%2Fsamba.git - added simple (fake) vnn system - split up ctdb layer code into 3 modules - added a simple test suite - added packet structures for ctdb_call - switched to an array for ctdb_node to make vnn lookup easy and fast (This used to be ctdb commit 8a17460a816a5970f2df8244a06aec55d814f186) --- diff --git a/ctdb/Makefile.in b/ctdb/Makefile.in index a818a2ce273..66369ae03c5 100644 --- a/ctdb/Makefile.in +++ b/ctdb/Makefile.in @@ -20,7 +20,8 @@ LIB_FLAGS=@LDFLAGS@ -Llib @LIBS@ -lpopt EVENTS_OBJ = lib/events/events.o lib/events/events_standard.o -CTDB_COMMON_OBJ = common/ctdb.o common/util.o +CTDB_COMMON_OBJ = common/ctdb.o common/util.o common/ctdb_util.o \ + common/ctdb_call.o common/ctdb_ltdb.o CTDB_TCP_OBJ = tcp/tcp_connect.o tcp/tcp_io.o tcp/tcp_init.o diff --git a/ctdb/common/ctdb.c b/ctdb/common/ctdb.c index 588bff2f7f0..0277135f361 100644 --- a/ctdb/common/ctdb.c +++ b/ctdb/common/ctdb.c @@ -1,5 +1,5 @@ /* - ctdb over TCP + ctdb main protocol code Copyright (C) Andrew Tridgell 2006 @@ -24,24 +24,6 @@ #include "system/filesys.h" #include "ctdb_private.h" -const char *ctdb_errstr(struct ctdb_context *ctdb) -{ - return ctdb->err_msg; -} - - -/* - remember an error message -*/ -void ctdb_set_error(struct ctdb_context *ctdb, const char *fmt, ...) -{ - va_list ap; - talloc_free(ctdb->err_msg); - va_start(ap, fmt); - ctdb->err_msg = talloc_vasprintf(ctdb, fmt, ap); - va_end(ap); -} - /* choose the transport we will use */ @@ -57,34 +39,22 @@ int ctdb_set_transport(struct ctdb_context *ctdb, const char *transport) } -/* - parse a IP:port pair -*/ -static int ctdb_parse_address(struct ctdb_context *ctdb, - TALLOC_CTX *mem_ctx, const char *str, - struct ctdb_address *address) -{ - char *p; - p = strchr(str, ':'); - if (p == NULL) { - ctdb_set_error(ctdb, "Badly formed node '%s'\n", str); - return -1; - } - - address->address = talloc_strndup(mem_ctx, str, p-str); - address->port = strtoul(p+1, NULL, 0); - return 0; -} - - /* add a node to the list of active nodes */ static int ctdb_add_node(struct ctdb_context *ctdb, char *nstr) { - struct ctdb_node *node; + struct ctdb_node *node, **nodep; + + nodep = talloc_realloc(ctdb, ctdb->nodes, struct ctdb_node *, ctdb->num_nodes+1); + CTDB_NO_MEMORY(ctdb, nodep); + + ctdb->nodes = nodep; + nodep = &ctdb->nodes[ctdb->num_nodes]; + (*nodep) = talloc_zero(ctdb->nodes, struct ctdb_node); + CTDB_NO_MEMORY(ctdb, *nodep); + node = *nodep; - node = talloc(ctdb, struct ctdb_node); if (ctdb_parse_address(ctdb, node, nstr, &node->address) != 0) { return -1; } @@ -92,13 +62,21 @@ static int ctdb_add_node(struct ctdb_context *ctdb, char *nstr) node->name = talloc_asprintf(node, "%s:%u", node->address.address, node->address.port); + /* for now we just set the vnn to the line in the file - this + will change! */ + node->vnn = ctdb->num_nodes; if (ctdb->methods->add_node(node) != 0) { talloc_free(node); return -1; } - DLIST_ADD(ctdb->nodes, node); + if (ctdb_same_address(&ctdb->address, &node->address)) { + ctdb->vnn = node->vnn; + } + + ctdb->num_nodes++; + return 0; } @@ -133,7 +111,14 @@ int ctdb_set_nlist(struct ctdb_context *ctdb, const char *nlist) */ int ctdb_set_address(struct ctdb_context *ctdb, const char *address) { - return ctdb_parse_address(ctdb, ctdb, address, &ctdb->address); + if (ctdb_parse_address(ctdb, ctdb, address, &ctdb->address) != 0) { + return -1; + } + + ctdb->name = talloc_asprintf(ctdb, "%s:%u", + ctdb->address.address, + ctdb->address.port); + return 0; } /* @@ -151,23 +136,6 @@ int ctdb_set_call(struct ctdb_context *ctdb, ctdb_fn_t fn, int id) return 0; } -/* - attach to a specific database -*/ -int ctdb_attach(struct ctdb_context *ctdb, const char *name, int tdb_flags, - int open_flags, mode_t mode) -{ - /* when we have a separate daemon this will need to be a real - file, not a TDB_INTERNAL, so the parent can access it to - for ltdb bypass */ - ctdb->ltdb = tdb_open(name, 0, TDB_INTERNAL, 0, 0); - if (ctdb->ltdb == NULL) { - ctdb_set_error(ctdb, "Failed to open tdb %s\n", name); - return -1; - } - return 0; -} - /* start the protocol going */ @@ -177,42 +145,33 @@ int ctdb_start(struct ctdb_context *ctdb) } /* - make a remote ctdb call -*/ -int ctdb_call(struct ctdb_context *ctdb, TDB_DATA key, int call_id, - TDB_DATA *call_data, TDB_DATA *reply_data) -{ - printf("ctdb_call not implemented\n"); - return -1; -} - -/* - check if two addresses are the same + called by the transport layer when a packet comes in */ -bool ctdb_same_address(struct ctdb_address *a1, struct ctdb_address *a2) +static void ctdb_recv_pkt(struct ctdb_context *ctdb, uint8_t *data, uint32_t length) { - return strcmp(a1->address, a2->address) == 0 && a1->port == a2->port; + printf("received pkt of length %d\n", length); } /* - called by the transport layer when a packet comes in + called by the transport layer when a node is dead */ -static void ctdb_recv_pkt(struct ctdb_context *ctdb, uint8_t *data, uint32_t length) +static void ctdb_node_dead(struct ctdb_node *node) { - printf("received pkt of length %d\n", length); + printf("%s: node %s is dead\n", node->ctdb->name, node->name); } /* called by the transport layer when a node is dead */ -static void ctdb_node_dead(struct ctdb_node *node) +static void ctdb_node_connected(struct ctdb_node *node) { - printf("node %s is dead\n", node->name); + printf("%s: connected to %s\n", node->ctdb->name, node->name); } static const struct ctdb_upcalls ctdb_upcalls = { - .recv_pkt = ctdb_recv_pkt, - .node_dead = ctdb_node_dead + .recv_pkt = ctdb_recv_pkt, + .node_dead = ctdb_node_dead, + .node_connected = ctdb_node_connected }; /* diff --git a/ctdb/common/ctdb_call.c b/ctdb/common/ctdb_call.c new file mode 100644 index 00000000000..9688ffda739 --- /dev/null +++ b/ctdb/common/ctdb_call.c @@ -0,0 +1,53 @@ +/* + ctdb_call protocol code + + Copyright (C) Andrew Tridgell 2006 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "includes.h" +#include "lib/events/events.h" +#include "system/network.h" +#include "system/filesys.h" +#include "ctdb_private.h" + + +/* + local version of ctdb_call +*/ +static int ctdb_call_local(struct ctdb_context *ctdb, TDB_DATA key, int call_id, + TDB_DATA *call_data, TDB_DATA *reply_data) +{ + return -1; +} + +/* + make a remote ctdb call +*/ +int ctdb_call(struct ctdb_context *ctdb, TDB_DATA key, int call_id, + TDB_DATA *call_data, TDB_DATA *reply_data) +{ + uint32_t dest; + + dest = ctdb_hash(&key) % ctdb->num_nodes; + if (dest == ctdb->vnn) { + return ctdb_call_local(ctdb, key, call_id, call_data, reply_data); + } + + + return -1; +} + diff --git a/ctdb/common/ctdb_ltdb.c b/ctdb/common/ctdb_ltdb.c new file mode 100644 index 00000000000..7238a436b49 --- /dev/null +++ b/ctdb/common/ctdb_ltdb.c @@ -0,0 +1,42 @@ +/* + ctdb ltdb code + + Copyright (C) Andrew Tridgell 2006 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "includes.h" +#include "lib/events/events.h" +#include "system/network.h" +#include "system/filesys.h" +#include "ctdb_private.h" + +/* + attach to a specific database +*/ +int ctdb_attach(struct ctdb_context *ctdb, const char *name, int tdb_flags, + int open_flags, mode_t mode) +{ + /* when we have a separate daemon this will need to be a real + file, not a TDB_INTERNAL, so the parent can access it to + for ltdb bypass */ + ctdb->ltdb = tdb_open(name, 0, TDB_INTERNAL, 0, 0); + if (ctdb->ltdb == NULL) { + ctdb_set_error(ctdb, "Failed to open tdb %s\n", name); + return -1; + } + return 0; +} diff --git a/ctdb/common/ctdb_util.c b/ctdb/common/ctdb_util.c new file mode 100644 index 00000000000..64053a5d995 --- /dev/null +++ b/ctdb/common/ctdb_util.c @@ -0,0 +1,91 @@ +/* + ctdb utility code + + Copyright (C) Andrew Tridgell 2006 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "includes.h" +#include "lib/events/events.h" +#include "system/network.h" +#include "system/filesys.h" +#include "ctdb_private.h" + +/* + return error string for last error +*/ +const char *ctdb_errstr(struct ctdb_context *ctdb) +{ + return ctdb->err_msg; +} + + +/* + remember an error message +*/ +void ctdb_set_error(struct ctdb_context *ctdb, const char *fmt, ...) +{ + va_list ap; + talloc_free(ctdb->err_msg); + va_start(ap, fmt); + ctdb->err_msg = talloc_vasprintf(ctdb, fmt, ap); + va_end(ap); +} + + +/* + parse a IP:port pair +*/ +int ctdb_parse_address(struct ctdb_context *ctdb, + TALLOC_CTX *mem_ctx, const char *str, + struct ctdb_address *address) +{ + char *p; + p = strchr(str, ':'); + if (p == NULL) { + ctdb_set_error(ctdb, "Badly formed node '%s'\n", str); + return -1; + } + + address->address = talloc_strndup(mem_ctx, str, p-str); + address->port = strtoul(p+1, NULL, 0); + return 0; +} + + +/* + check if two addresses are the same +*/ +bool ctdb_same_address(struct ctdb_address *a1, struct ctdb_address *a2) +{ + return strcmp(a1->address, a2->address) == 0 && a1->port == a2->port; +} + + +/* + hash function for mapping data to a VNN - taken from tdb +*/ +uint32_t ctdb_hash(TDB_DATA *key) +{ + uint32_t value; /* Used to compute the hash value. */ + uint32_t i; /* Used to cycle through random values. */ + + /* Set the initial value from the key size. */ + for (value = 0x238F13AF * key->dsize, i=0; i < key->dsize; i++) + value = (value + (key->dptr[i] << (i*5 % 24))); + + return (1103515243 * value + 12345); +} diff --git a/ctdb/include/ctdb_private.h b/ctdb/include/ctdb_private.h index 41d51a17734..d4e7350bd70 100644 --- a/ctdb/include/ctdb_private.h +++ b/ctdb/include/ctdb_private.h @@ -42,10 +42,10 @@ struct ctdb_address { */ struct ctdb_node { struct ctdb_context *ctdb; - struct ctdb_node *next, *prev; struct ctdb_address address; const char *name; /* for debug messages */ void *private; /* private to transport */ + uint32_t vnn; }; /* @@ -61,15 +61,24 @@ struct ctdb_methods { transport calls up to the ctdb layer */ struct ctdb_upcalls { + /* recv_pkt is called when a packet comes in */ void (*recv_pkt)(struct ctdb_context *, uint8_t *data, uint32_t length); + + /* node_dead is called when an attempt to send to a node fails */ void (*node_dead)(struct ctdb_node *); + + /* node_connected is called when a connection to a node is established */ + void (*node_connected)(struct ctdb_node *); }; /* main state of the ctdb daemon */ struct ctdb_context { struct event_context *ev; struct ctdb_address address; - struct ctdb_node *nodes; /* list of nodes in the cluster */ + const char *name; + uint32_t vnn; /* our own vnn */ + uint32_t num_nodes; + struct ctdb_node **nodes; /* array of nodes in the cluster - indexed by vnn */ struct ctdb_registered_call *calls; /* list of registered calls */ char *err_msg; struct tdb_context *ltdb; @@ -82,9 +91,52 @@ struct ctdb_context { ctdb_set_error(ctdb, "Out of memory at %s:%d", __FILE__, __LINE__); \ return -1; }} while (0) +/* + operation IDs +*/ +enum ctdb_operation { + CTDB_OP_CALL = 0 +}; + +/* + packet structures +*/ +struct ctdb_req_header { + uint32_t _length; /* ignored by datagram transports */ + uint32_t operation; + uint32_t destnode; + uint32_t srcnode; + uint32_t reqid; + uint32_t reqtimeout; +}; + +struct ctdb_reply_header { + uint32_t _length; /* ignored by datagram transports */ + uint32_t operation; + uint32_t destnode; + uint32_t srcnode; + uint32_t reqid; +}; + +struct ctdb_req_call { + struct ctdb_req_header hdr; + uint32_t callid; + uint32_t keylen; + uint32_t calldatalen; + uint8_t data[0]; /* key[] followed by calldata[] */ +}; + +struct ctdb_reply_call { + struct ctdb_reply_header hdr; + uint32_t datalen; + uint8_t data[0]; +}; /* internal prototypes */ void ctdb_set_error(struct ctdb_context *ctdb, const char *fmt, ...); bool ctdb_same_address(struct ctdb_address *a1, struct ctdb_address *a2); - +int ctdb_parse_address(struct ctdb_context *ctdb, + TALLOC_CTX *mem_ctx, const char *str, + struct ctdb_address *address); +uint32_t ctdb_hash(TDB_DATA *key); diff --git a/ctdb/tcp/tcp_connect.c b/ctdb/tcp/tcp_connect.c index fff6938e561..c7e361f9ca9 100644 --- a/ctdb/tcp/tcp_connect.c +++ b/ctdb/tcp/tcp_connect.c @@ -43,16 +43,12 @@ static void ctdb_node_connect_write(struct event_context *ev, struct fd_event *f struct ctdb_tcp_node *tnode = talloc_get_type(node->private, struct ctdb_tcp_node); struct ctdb_context *ctdb = node->ctdb; - int error; + int error = 0; socklen_t len; if (getsockopt(tnode->fd, SOL_SOCKET, SO_ERROR, &error, &len) != 0 || error != 0) { - if (error == EINPROGRESS) { - printf("connect in progress\n"); - return; - } - printf("getsockopt errno=%s\n", strerror(errno)); + printf("getsockopt error=%s\n", strerror(error)); talloc_free(fde); close(tnode->fd); tnode->fd = -1; @@ -61,10 +57,12 @@ static void ctdb_node_connect_write(struct event_context *ev, struct fd_event *f return; } - printf("Established connection to %s\n", node->name); talloc_free(fde); tnode->fde = event_add_fd(node->ctdb->ev, node, tnode->fd, EVENT_FD_READ, ctdb_tcp_node_write, node); + + /* tell the ctdb layer we are connected */ + node->ctdb->upcalls->node_connected(node); } /* @@ -97,7 +95,7 @@ void ctdb_tcp_node_connect(struct event_context *ev, struct timed_event *te, } /* non-blocking connect - wait for write event */ - event_add_fd(node->ctdb->ev, node, tnode->fd, EVENT_FD_WRITE, + event_add_fd(node->ctdb->ev, node, tnode->fd, EVENT_FD_WRITE|EVENT_FD_READ, ctdb_node_connect_write, node); } @@ -143,8 +141,6 @@ static void ctdb_listen_event(struct event_context *ev, struct fd_event *fde, ctdb_tcp_incoming_read, in); talloc_set_destructor(in, ctdb_incoming_destructor); - - printf("New incoming socket %d\n", in->fd); } diff --git a/ctdb/tcp/tcp_init.c b/ctdb/tcp/tcp_init.c index b98a92818d9..39ecec4dbdd 100644 --- a/ctdb/tcp/tcp_init.c +++ b/ctdb/tcp/tcp_init.c @@ -30,14 +30,15 @@ */ int ctdb_tcp_start(struct ctdb_context *ctdb) { - struct ctdb_node *node; + int i; /* listen on our own address */ if (ctdb_tcp_listen(ctdb) != 0) return -1; /* startup connections to the other servers - will happen on next event loop */ - for (node=ctdb->nodes;node;node=node->next) { + for (i=0;inum_nodes;i++) { + struct ctdb_node *node = *(ctdb->nodes + i); if (ctdb_same_address(&ctdb->address, &node->address)) continue; event_add_timed(ctdb->ev, node, timeval_zero(), ctdb_tcp_node_connect, node); diff --git a/ctdb/tests/test.sh b/ctdb/tests/test.sh new file mode 100755 index 00000000000..0aa93fbdbdb --- /dev/null +++ b/ctdb/tests/test.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +killall -q ctdb_test + +bin/ctdb_test --nlist nodes.txt --listen 127.0.0.1:9001 & +bin/ctdb_test --nlist nodes.txt --listen 127.0.0.2:9001 & + +sleep 3 +killall ctdb_test