summaryrefslogtreecommitdiff
path: root/ctdb
diff options
context:
space:
mode:
authorMartin Schwenke <martin@meltin.net>2017-09-04 17:01:05 +1000
committerMartin Schwenke <martins@samba.org>2017-09-19 13:30:27 +0200
commit6d9fef467cf91e543c2b0084d8a41e213f40c365 (patch)
tree609ef6d2d639e2c96db46637df453f122c38228e /ctdb
parente50cb8cb5213cf1f876a70638f37b2f8b3d36baa (diff)
downloadsamba-6d9fef467cf91e543c2b0084d8a41e213f40c365.tar.gz
ctdb-protocol: Add ctdb_connection_list utilities
Signed-off-by: Martin Schwenke <martin@meltin.net> Reviewed-by: Amitay Isaacs <amitay@gmail.com>
Diffstat (limited to 'ctdb')
-rw-r--r--ctdb/protocol/protocol_util.c144
-rw-r--r--ctdb/protocol/protocol_util.h9
-rw-r--r--ctdb/tests/src/protocol_util_test.c152
3 files changed, 305 insertions, 0 deletions
diff --git a/ctdb/protocol/protocol_util.c b/ctdb/protocol/protocol_util.c
index 2b6585b1958..68a470fc316 100644
--- a/ctdb/protocol/protocol_util.c
+++ b/ctdb/protocol/protocol_util.c
@@ -512,3 +512,147 @@ int ctdb_connection_from_string(const char *str, bool client_first,
return 0;
}
+
+int ctdb_connection_list_add(struct ctdb_connection_list *conn_list,
+ struct ctdb_connection *conn)
+{
+ uint32_t len;
+
+ if (conn_list == NULL) {
+ return EINVAL;
+ }
+
+ /* Ensure array is big enough */
+ len = talloc_array_length(conn_list->conn);
+ if (conn_list->num == len) {
+ conn_list->conn = talloc_realloc(conn_list, conn_list->conn,
+ struct ctdb_connection,
+ len+128);
+ if (conn_list->conn == NULL) {
+ return ENOMEM;
+ }
+ }
+
+ conn_list->conn[conn_list->num] = *conn;
+ conn_list->num++;
+
+ return 0;
+}
+
+static int connection_cmp(const void *a, const void *b)
+{
+ const struct ctdb_connection *conn_a = a;
+ const struct ctdb_connection *conn_b = b;
+ int ret;
+
+ ret = ctdb_sock_addr_cmp(&conn_a->server, &conn_b->server);
+ if (ret == 0) {
+ ret = ctdb_sock_addr_cmp(&conn_a->client, &conn_b->client);
+ }
+
+ return ret;
+}
+
+int ctdb_connection_list_sort(struct ctdb_connection_list *conn_list)
+{
+ if (conn_list == NULL) {
+ return EINVAL;
+ }
+
+ if (conn_list->num > 0) {
+ qsort(conn_list->conn, conn_list->num,
+ sizeof(struct ctdb_connection), connection_cmp);
+ }
+
+ return 0;
+}
+
+const char *ctdb_connection_list_to_string(
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_connection_list *conn_list, bool client_first)
+{
+ uint32_t i;
+ char *out;
+
+ out = talloc_strdup(mem_ctx, "");
+ if (out == NULL) {
+ return NULL;
+ }
+
+ if (conn_list == NULL || conn_list->num == 0) {
+ return out;
+ }
+
+ for (i = 0; i < conn_list->num; i++) {
+ char buf[128];
+ int ret;
+
+ ret = ctdb_connection_to_buf(buf, sizeof(buf),
+ &conn_list->conn[i], client_first);
+ if (ret != 0) {
+ talloc_free(out);
+ return NULL;
+ }
+
+ out = talloc_asprintf_append(out, "%s\n", buf);
+ if (out == NULL) {
+ return NULL;
+ }
+ }
+
+ return out;
+}
+
+int ctdb_connection_list_read(TALLOC_CTX *mem_ctx, bool client_first,
+ struct ctdb_connection_list **conn_list)
+{
+ struct ctdb_connection_list *list;
+ char line[128]; /* long enough for IPv6 */
+ int ret;
+
+ if (conn_list == NULL) {
+ return EINVAL;
+ }
+
+ list = talloc_zero(mem_ctx, struct ctdb_connection_list);
+ if (list == NULL) {
+ return ENOMEM;
+ }
+
+ while (fgets(line, sizeof(line), stdin) != NULL) {
+ char *t;
+ struct ctdb_connection conn;
+
+ /* Skip empty lines */
+ if (line[0] == '\n') {
+ continue;
+ }
+
+ /* Comment */
+ if (line[0] == '#') {
+ continue;
+ }
+
+ t = strtok(line, "\n");
+ if (t == NULL) {
+ goto fail;
+ }
+
+ ret = ctdb_connection_from_string(t, client_first, &conn);
+ if (ret != 0) {
+ goto fail;
+ }
+
+ ret = ctdb_connection_list_add(list, &conn);
+ if (ret != 0) {
+ goto fail;
+ }
+ }
+
+ *conn_list = list;
+ return 0;
+
+fail:
+ talloc_free(list);
+ return EINVAL;
+}
diff --git a/ctdb/protocol/protocol_util.h b/ctdb/protocol/protocol_util.h
index ab2a20b4631..66a49136576 100644
--- a/ctdb/protocol/protocol_util.h
+++ b/ctdb/protocol/protocol_util.h
@@ -60,4 +60,13 @@ const char *ctdb_connection_to_string(TALLOC_CTX *mem_ctx,
int ctdb_connection_from_string(const char *str, bool client_first,
struct ctdb_connection *conn);
+int ctdb_connection_list_add(struct ctdb_connection_list *conn_list,
+ struct ctdb_connection *conn);
+int ctdb_connection_list_sort(struct ctdb_connection_list *conn_list);
+const char *ctdb_connection_list_to_string(
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_connection_list *conn_list, bool client_first);
+int ctdb_connection_list_read(TALLOC_CTX *mem_ctx, bool client_first,
+ struct ctdb_connection_list **conn_list);
+
#endif /* __CTDB_PROTOCOL_UTIL_H__ */
diff --git a/ctdb/tests/src/protocol_util_test.c b/ctdb/tests/src/protocol_util_test.c
index 4ca70aef108..fd1b0679414 100644
--- a/ctdb/tests/src/protocol_util_test.c
+++ b/ctdb/tests/src/protocol_util_test.c
@@ -144,6 +144,147 @@ static void test_connection_from_string_bad(const char *conn_str)
assert(ret != 0);
}
+/*
+ * Test connection list utilities
+ */
+
+static void test_connection_list_read(const char *s1, const char *s2)
+{
+ TALLOC_CTX *tmp_ctx;
+ int pipefd[2];
+ pid_t pid;
+ struct ctdb_connection_list *conn_list;
+ const char *t;
+ int ret;
+
+ tmp_ctx = talloc_new(NULL);
+ assert(tmp_ctx != NULL);
+
+ ret = pipe(pipefd);
+ assert(ret == 0);
+
+ pid = fork();
+ assert(pid != -1);
+
+ if (pid == 0) {
+ close(pipefd[0]);
+
+ ret = dup2(pipefd[1], STDOUT_FILENO);
+ assert(ret != -1);
+
+ close(pipefd[1]);
+
+ printf("%s", s1);
+ fflush(stdout);
+
+ exit(0);
+ }
+
+ close(pipefd[1]);
+
+ ret = dup2(pipefd[0], STDIN_FILENO);
+ assert(ret != -1);
+
+ close(pipefd[0]);
+
+ ret = ctdb_connection_list_read(tmp_ctx, false, &conn_list);
+ assert(ret == 0);
+
+ ret = ctdb_connection_list_sort(conn_list);
+ assert(ret == 0);
+
+ t = ctdb_connection_list_to_string(tmp_ctx, conn_list, false);
+ assert(t != NULL);
+ ret = strcmp(t, s2);
+ assert(ret == 0);
+
+ talloc_free(tmp_ctx);
+}
+
+static void test_connection_list_read_bad(const char *s1)
+{
+ TALLOC_CTX *tmp_ctx;
+ int pipefd[2];
+ pid_t pid;
+ struct ctdb_connection_list *conn_list;
+ int ret;
+
+ tmp_ctx = talloc_new(NULL);
+ assert(tmp_ctx != NULL);
+
+ ret = pipe(pipefd);
+ assert(ret == 0);
+
+ pid = fork();
+ assert(pid != -1);
+
+ if (pid == 0) {
+ close(pipefd[0]);
+
+ ret = dup2(pipefd[1], STDOUT_FILENO);
+ assert(ret != -1);
+
+ close(pipefd[1]);
+
+ printf("%s", s1);
+ fflush(stdout);
+
+ exit(0);
+ }
+
+ close(pipefd[1]);
+
+ ret = dup2(pipefd[0], STDIN_FILENO);
+ assert(ret != -1);
+
+ close(pipefd[0]);
+
+ ret = ctdb_connection_list_read(tmp_ctx, false, &conn_list);
+ assert(ret != 0);
+
+ talloc_free(tmp_ctx);
+}
+
+/*
+ * Use macros for these to make them easy to concatenate
+ */
+
+#define CONN4 \
+"\
+127.0.0.1:12345 127.0.0.2:54321\n\
+127.0.0.2:12345 127.0.0.1:54322\n\
+127.0.0.1:12346 127.0.0.2:54323\n\
+127.0.0.2:12345 127.0.0.1:54324\n\
+127.0.0.1:12345 127.0.0.2:54325\n\
+"
+
+#define CONN4_SORT \
+"\
+127.0.0.1:12345 127.0.0.2:54321\n\
+127.0.0.1:12345 127.0.0.2:54325\n\
+127.0.0.1:12346 127.0.0.2:54323\n\
+127.0.0.2:12345 127.0.0.1:54322\n\
+127.0.0.2:12345 127.0.0.1:54324\n\
+"
+
+#define CONN6 \
+"\
+fe80::6af7:28ff:fefa:d136:12345 fe80::6af7:28ff:fefa:d137:54321\n\
+fe80::6af7:28ff:fefa:d138:12345 fe80::6af7:28ff:fefa:d137:54322\n\
+fe80::6af7:28ff:fefa:d136:12346 fe80::6af7:28ff:fefa:d137:54323\n\
+fe80::6af7:28ff:fefa:d132:12345 fe80::6af7:28ff:fefa:d137:54324\n\
+fe80::6af7:28ff:fefa:d136:12345 fe80::6af7:28ff:fefa:d137:54325\n\
+"
+
+#define CONN6_SORT \
+"\
+fe80::6af7:28ff:fefa:d132:12345 fe80::6af7:28ff:fefa:d137:54324\n\
+fe80::6af7:28ff:fefa:d136:12345 fe80::6af7:28ff:fefa:d137:54321\n\
+fe80::6af7:28ff:fefa:d136:12345 fe80::6af7:28ff:fefa:d137:54325\n\
+fe80::6af7:28ff:fefa:d136:12346 fe80::6af7:28ff:fefa:d137:54323\n\
+fe80::6af7:28ff:fefa:d138:12345 fe80::6af7:28ff:fefa:d137:54322\n\
+"
+
int main(int argc, char *argv[])
{
test_sock_addr_to_string("0.0.0.0", false);
@@ -194,5 +335,16 @@ int main(int argc, char *argv[])
test_connection_from_string_bad("Junk!");
test_connection_from_string_bad("More junk");
+ test_connection_list_read(CONN4, CONN4_SORT);
+ test_connection_list_read(CONN6, CONN6_SORT);
+ test_connection_list_read(CONN4 CONN6, CONN4_SORT CONN6_SORT);
+ test_connection_list_read(CONN4 "# Comment\n\n# Comment\n" CONN6,
+ CONN4_SORT CONN6_SORT);
+
+ test_connection_list_read_bad(CONN4 "# Comment\n\nJunk!!!\n" CONN6);
+ test_connection_list_read_bad(CONN4
+ "# Comment\n\n127.0.0.1: 127.0.0.1:124\n"
+ CONN6);
+
return 0;
}