diff options
author | Mattias Andrée <maandree@operamail.com> | 2014-07-28 16:53:10 +0200 |
---|---|---|
committer | Mattias Andrée <maandree@operamail.com> | 2014-07-28 16:53:10 +0200 |
commit | 0cfe3b6ef1fdb4f4934a5752ca6d0d4aa3fcbf18 (patch) | |
tree | 4b919d602da3ee225dea15454cc6aacd4211687b /src | |
parent | prepare for handling client closed messages (diff) | |
download | mds-0cfe3b6ef1fdb4f4934a5752ca6d0d4aa3fcbf18.tar.gz mds-0cfe3b6ef1fdb4f4934a5752ca6d0d4aa3fcbf18.tar.bz2 mds-0cfe3b6ef1fdb4f4934a5752ca6d0d4aa3fcbf18.tar.xz |
unregister protocols for closing servers
Signed-off-by: Mattias Andrée <maandree@operamail.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/libmdsserver/hash-table.h | 11 | ||||
-rw-r--r-- | src/libmdsserver/linked-list.h | 2 | ||||
-rw-r--r-- | src/mds-registry.c | 64 | ||||
-rw-r--r-- | src/mds-registry.h | 10 |
4 files changed, 80 insertions, 7 deletions
diff --git a/src/libmdsserver/hash-table.h b/src/libmdsserver/hash-table.h index edf8d3a..2f4d03b 100644 --- a/src/libmdsserver/hash-table.h +++ b/src/libmdsserver/hash-table.h @@ -220,6 +220,17 @@ size_t hash_table_remove(hash_table_t* restrict this, size_t key); void hash_table_clear(hash_table_t* restrict this); /** + * Wrapper for `for` keyword that iterates over entry element in a hash table + * + * @param table:hash_table_t The hans table + * @param i:size_t The variable to store the buckey index in at each iteration + * @param entry:hash_entry_t* The variable to store the entry in at each iteration + */ +#define foreach_hash_table_entry(table, i, entry) \ + for (i = 0; i < (table).capacity; i++) \ + for (entry = (table).buckets[i]; entry != NULL; entry = entry->next) + +/** * Calculate the buffer size need to marshal a hash table * * @param this The hash table diff --git a/src/libmdsserver/linked-list.h b/src/libmdsserver/linked-list.h index e2ec884..6ed7076 100644 --- a/src/libmdsserver/linked-list.h +++ b/src/libmdsserver/linked-list.h @@ -274,7 +274,7 @@ int linked_list_unmarshal(linked_list_t* restrict this, char* restrict data); * @param node:ssize_t The variable to store the node in at each iteration */ #define foreach_linked_list_node(list, node) \ - for (node = list.edge; node = list.next[node], node != list.edge;) + for (node = (list).edge; node = (list).next[node], node != (list).edge;) /** diff --git a/src/mds-registry.c b/src/mds-registry.c index ec1e186..d7d7b63 100644 --- a/src/mds-registry.c +++ b/src/mds-registry.c @@ -145,6 +145,15 @@ int initialise_server(void) "Message ID: 1\n" "\n"; + /* We are asking all servers to reregister their + protocols for two reasons: + + 1) The server would otherwise not get registrations + from servers started before this server. + 2) If this server crashes we may miss registrations + that happen between the crash and the recovery. + */ + if (full_send(message, strlen(message))) return 1; if (hash_table_create_tuned(®_table, 32)) @@ -474,8 +483,53 @@ static int handle_register_message(void) */ static int handle_close_message(void) { - /* FIXME */ + /* Servers do not close too often, there is no need to + optimise this with another hash table. */ + + size_t i, j, ptr = 0, size = 1; + size_t* keys = NULL; + size_t* old_keys; + + for (i = 0; i < received.header_count; i++) + if (startswith(received.headers[i], "Client closed: ")) + { + uint64_t client = parse_client_id(received.headers[i] + strlen("Client closed: ")); + hash_entry_t* entry; + + foreach_hash_table_entry (reg_table, j, entry) + { + client_list_t* list = (client_list_t*)(void*)(entry->value); + client_list_remove(list, client); + if (list->size) + continue; + + fail_if ((keys == NULL) && xmalloc(keys, size, size_t)); + if (ptr == size ? growalloc(old_keys, keys, size, size_t) : 0) + goto fail; + keys[ptr++] = entry->key; + } + } + + for (i = 0; i < ptr; i++) + { + hash_entry_t* entry = hash_table_get_entry(®_table, keys[i]); + client_list_t* list = (client_list_t*)(void*)(entry->value); + char* command = (char*)(void*)(entry->key); + + hash_table_remove(®_table, entry->key); + + client_list_destroy(list); + free(list); + free(command); + } + + free(keys); return 0; + pfail: + perror(*argv); + fail: + free(keys); + return -1; } @@ -489,10 +543,8 @@ int handle_message(void) { size_t i; for (i = 0; i < received.header_count; i++) - { - if (strequals(received.headers[i], "Command: register")) - return handle_register_message(); - } + if (strequals(received.headers[i], "Command: register")) + return handle_register_message(); return handle_close_message(); } @@ -503,7 +555,7 @@ int handle_message(void) * @param str The client ID string * @return The client ID integer */ -static uint64_t parse_client_id(const char* str) +uint64_t parse_client_id(const char* str) { char client_words[22]; char* client_high; diff --git a/src/mds-registry.h b/src/mds-registry.h index 6eb09b4..2f40f31 100644 --- a/src/mds-registry.h +++ b/src/mds-registry.h @@ -21,6 +21,8 @@ #include "mds-base.h" +#include <stdint.h> + /** * Handle the received message @@ -31,6 +33,14 @@ int handle_message(void); /** + * Convert a client ID string into a client ID integer + * + * @param str The client ID string + * @return The client ID integer + */ +uint64_t parse_client_id(const char* str); + +/** * Perform an action over the registry * * @param length The length of the received message |