diff options
author | Martin Schwenke <martin@meltin.net> | 2017-09-04 17:01:05 +1000 |
---|---|---|
committer | Martin Schwenke <martins@samba.org> | 2017-09-19 13:30:27 +0200 |
commit | 6d9fef467cf91e543c2b0084d8a41e213f40c365 (patch) | |
tree | 609ef6d2d639e2c96db46637df453f122c38228e /ctdb | |
parent | e50cb8cb5213cf1f876a70638f37b2f8b3d36baa (diff) | |
download | samba-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.c | 144 | ||||
-rw-r--r-- | ctdb/protocol/protocol_util.h | 9 | ||||
-rw-r--r-- | ctdb/tests/src/protocol_util_test.c | 152 |
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; } |