aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMattias Andrée <maandree@operamail.com>2014-07-28 16:53:10 +0200
committerMattias Andrée <maandree@operamail.com>2014-07-28 16:53:10 +0200
commit0cfe3b6ef1fdb4f4934a5752ca6d0d4aa3fcbf18 (patch)
tree4b919d602da3ee225dea15454cc6aacd4211687b /src
parentprepare for handling client closed messages (diff)
downloadmds-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.h11
-rw-r--r--src/libmdsserver/linked-list.h2
-rw-r--r--src/mds-registry.c64
-rw-r--r--src/mds-registry.h10
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(&reg_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(&reg_table, keys[i]);
+ client_list_t* list = (client_list_t*)(void*)(entry->value);
+ char* command = (char*)(void*)(entry->key);
+
+ hash_table_remove(&reg_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