aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJordan Augé <jordan.auge+fdio@cisco.com>2020-09-09 11:59:36 +0200
committerJordan Augé <jordan.auge+fdio@cisco.com>2020-09-21 14:49:29 +0200
commit7356408ca1554468c9d7b9840aaaee28b4341c8d (patch)
treef57bfcc87be4cf5b51b86e5c847b4cde24c0d5e0
parentfe310f8b7a54f31b7270107b57b5ffcc00966f45 (diff)
[HICN-563] listener and connection tables
Change-Id: I88b85a61908d97bda1afb08d31c3bf10b4d9c5c5 Signed-off-by: Jordan Augé <jordan.auge+fdio@cisco.com>
-rw-r--r--hicn-light/src/hicn/base/bitmap.h5
-rw-r--r--hicn-light/src/hicn/base/test/test-bitmap.cc4
-rw-r--r--hicn-light/src/hicn/core/connection_table.c25
-rw-r--r--hicn-light/src/hicn/core/connection_table.h234
-rw-r--r--hicn-light/src/hicn/core/content_store.c4
-rw-r--r--hicn-light/src/hicn/core/content_store.h23
-rw-r--r--hicn-light/src/hicn/core/forwarder.c4
-rw-r--r--hicn-light/src/hicn/core/listener_table.c37
-rw-r--r--hicn-light/src/hicn/core/listener_table.h189
9 files changed, 421 insertions, 104 deletions
diff --git a/hicn-light/src/hicn/base/bitmap.h b/hicn-light/src/hicn/base/bitmap.h
index bebbf88..8fd9fcd 100644
--- a/hicn-light/src/hicn/base/bitmap.h
+++ b/hicn-light/src/hicn/base/bitmap.h
@@ -25,6 +25,9 @@
#include <string.h>
#include "common.h"
+#include "vector.h"
+
+typedef uint_fast32_t bitmap_t;
#define BITMAP_WIDTH(bitmap) (sizeof((bitmap)[0]) * 8)
@@ -56,7 +59,7 @@
* @param[in] bitmap The bitmap to access.
* @param[in] i The bit position.
*/
-#define bitmap_get(bitmap, i) ((bitmap)[(i) / BITMAP_WIDTH(bitmap)] & (1 << ((i) % BITMAP_WIDTH(bitmap))))
+#define bitmap_get(bitmap, i) (((bitmap)[(i) / BITMAP_WIDTH(bitmap)] & (1 << ((i) % BITMAP_WIDTH(bitmap)))) >> ((i) % BITMAP_WIDTH(bitmap)))
/*
* @brief Returns whether the i-th bit is set (equal to 1) in a bitmap.
diff --git a/hicn-light/src/hicn/base/test/test-bitmap.cc b/hicn-light/src/hicn/base/test/test-bitmap.cc
index e7ff704..d6ab94f 100644
--- a/hicn-light/src/hicn/base/test/test-bitmap.cc
+++ b/hicn-light/src/hicn/base/test/test-bitmap.cc
@@ -34,7 +34,7 @@ class BitmapTest : public ::testing::Test {
}
virtual ~BitmapTest() {
-
+
// You can do clean-up work that doesn't throw exceptions here.
}
@@ -68,7 +68,7 @@ TEST_F(BitmapTest, BitmapUnSet) {
EXPECT_FALSE(bitmap_is_set(bitmap, 20));
EXPECT_TRUE(bitmap_is_unset(bitmap, 20));
EXPECT_TRUE(bitmap_is_set(bitmap, 19));
- EXPECT_TRUE(bitmap_is_unset(bitmap, 19));
+ EXPECT_FALSE(bitmap_is_unset(bitmap, 19));
}
diff --git a/hicn-light/src/hicn/core/connection_table.c b/hicn-light/src/hicn/core/connection_table.c
index fd8013b..0b7df03 100644
--- a/hicn-light/src/hicn/core/connection_table.c
+++ b/hicn-light/src/hicn/core/connection_table.c
@@ -18,22 +18,35 @@
* \brief Implementation of hICN connection table
*/
-#include <hicn/core/connection.h>
-#include <hicn/core/connection_table.h>
+#include <hicn/util/log.h>
-/* This is only used for first allocation, as the table is resizeable */
+#include "connection.h"
+#include "connection_table.h"
+
+/* This is only used as a hint for first allocation, as the table is resizeable */
#define DEFAULT_CONNECTION_TABLE_SIZE 64
connection_table_t *
-connection_table_create(size_t elt_size, size_t max_elts)
+_connection_table_create(size_t init_size, size_t max_size)
{
+ if (init_size == 0)
+ init_size = DEFAULT_CONNECTION_TABLE_SIZE;
+
connection_table_t * table = malloc(sizeof(connection_table_t));
if (!table)
return NULL;
+ table->max_size = max_size;
+
+ /* Initialize indices */
table->id_by_pair = kh_init_ct_pair();
table->id_by_name = kh_init_ct_name();
- pool_init(table->connections, DEFAULT_CONNECTION_TABLE_SIZE);
+
+ /*
+ * We start by allocating a reasonably-sized pool, as this will eventually
+ * be resized if needed.
+ */
+ pool_init(table->connections, init_size);
return table;
}
@@ -57,7 +70,7 @@ connection_table_get_by_pair(const connection_table_t * table,
return table->connections + kh_val(table->id_by_pair, k);
}
-unsigned
+off_t
connection_table_get_id_by_name(const connection_table_t * table,
const char * name)
{
diff --git a/hicn-light/src/hicn/core/connection_table.h b/hicn-light/src/hicn/core/connection_table.h
index c0406ce..8a9342f 100644
--- a/hicn-light/src/hicn/core/connection_table.h
+++ b/hicn-light/src/hicn/core/connection_table.h
@@ -16,84 +16,172 @@
/**
* \file connection_table.h
* \brief hICN connection_table
+ *
+ * The connection table is composed of :
+ * - a pool of connections allowing access through their id in constant time;
+ * - a set of indices in the form of hash table for efficient index lookups:
+ * . by name
+ * . by address pair
+ *
+ * For efficient index retrieval, the header will be prepended and the
+ * resulting pointer will directly point to the connection pool.
*/
-/* Iterate on connection table : to remove all connections associated to a
- * listener based on listen address */
+#ifndef HICNLIGHT_CONNECTION_TABLE_H
+#define HICNLIGHT_CONNECTION_TABLE_H
-#ifndef HICN_CONNECTION_TABLE_H
-#define HICN_CONNECTION_TABLE_H
-
-//#include <hicn/base/common.h>
#include <hicn/core/address_pair.h>
#include <hicn/core/connection.h>
#include <hicn/base/hash.h>
#include <hicn/base/khash.h>
#include <hicn/base/pool.h>
-#include <hicn/common.h>
+#define _ct_var(x) _ct_var_##x
+/* Hash functions for indices. */
#define address_pair_hash(pair) (hash32(pair, sizeof(address_pair_t)))
#define address_pair_hash_eq(a, b) (address_pair_hash(b) - address_pair_hash(a))
+/* Hash table types for indices. */
KHASH_INIT(ct_pair, const address_pair_t *, unsigned, 0, address_pair_hash, address_pair_hash_eq);
-
KHASH_INIT(ct_name, const char *, unsigned, 0, str_hash, str_hash_eq);
-/*
- * The connection table is composed of :
- * - a connection pool allowing connection access by id in constant time
- * - a hash table allowing to perform lookups based on address pairs, to get a connection id.
- *
- * For fast lookup by ID, the connection table will point to the beginning of
- * the pool / vector, holding all connections.
- * The header will be prepended
- */
-
typedef struct {
+ size_t max_size;
+
kh_ct_pair_t * id_by_pair;
kh_ct_name_t * id_by_name;
connection_t * connections; // pool
} connection_table_t;
-#define connection_table_allocate(table, conn, pair, name) \
+/**
+ * @brief Allocate a connection from the connection table.
+ *
+ * @param[in] table The connection table from which to allocate a connection.
+ * @param[out] connection The pointer that will hold the allocated connection.
+ * @param[in] pair The address pair associated to the connection (to update index).
+ * @param[in] name The name associated to the connection (to update index).
+ *
+ * NOTE:
+ * - This function updates all indices from the connection table if the
+ * allocation is successful.
+ * - You should always check that the returned connection is not NULL, which
+ * would signal that the pool is exhausted and could not be extended.
+ */
+#define connection_table_allocate(TABLE, CONN, PAIR, NAME) \
do { \
- pool_get(table->connections, conn); \
- off_t connection_id = conn - table->connections; \
- int res; \
- khiter_t k = kh_put_ct_pair(table->id_by_pair, pair, &res); \
- kh_value(table->id_by_pair, k) = connection_id; \
- if (name) { \
- k = kh_put_ct_name(table->id_by_name, name, &res); \
- kh_value(table->id_by_name, k) = connection_id; \
+ pool_get((TABLE)->connections, CONN); \
+ if (CONN) { \
+ off_t _ct_var(id) = (CONN) - (TABLE)->connections; \
+ int _ct_var(res); \
+ khiter_t _ct_var(k); \
+ _ct_var(k) = kh_put_ct_pair((TABLE)->id_by_pair, PAIR, &_ct_var(res)); \
+ kh_value((TABLE)->id_by_pair, _ct_var(k)) = _ct_var(id); \
+ if (NAME) { \
+ _ct_var(k) = kh_put_ct_name((TABLE)->id_by_name, (NAME), &_ct_var(res));\
+ kh_value((TABLE)->id_by_name, _ct_var(k)) = _ct_var(id); \
+ } \
} \
} while(0)
-#define connection_table_deallocate(table, conn) \
+/**
+ * @brief Deallocate a connection and return it to the connection table pool.
+ *
+ * @param[in] table The connection table to which the connection is returned.
+ * @param[in] conn The connection that is returned to the pool.
+ *
+ * NOTE:
+ * - Upon returning a connection to the pool, all indices pointing to that
+ * connection are also cleared.
+ */
+#define connection_table_deallocate(TABLE, CONN) \
do { \
- const address_pair_t * pair = connection_get_pair(connection); \
- khiter_t k = kh_get_ct_pair(table->id_by_pair, pair); \
- if (k != kh_end(table->id_by_pair)) \
- kh_del_ct_pair(table->id_by_pair, k); \
+ const address_pair_t * _ct_var(pair) = connection_get_pair(CONN); \
+ khiter_t _ct_var(k); \
+ _ct_var(k) = kh_get_ct_pair((TABLE)->id_by_pair, _ct_var(pair)); \
+ if (_ct_var(k) != kh_end((TABLE)->id_by_pair)) \
+ kh_del_ct_pair((TABLE)->id_by_pair, _ct_var(k)); \
\
- const char * name = connection_get_name(connection); \
- if (name) { \
- k = kh_get_ct_name(table->id_by_name, name); \
- if (k != kh_end(table->id_by_name)) \
- kh_del_ct_name(table->id_by_name, k); \
+ const char * _ct_var(name) = connection_get_name(CONN); \
+ if (_ct_var(name)) { \
+ _ct_var(k) = kh_get_ct_name((TABLE)->id_by_name, _ct_var(name)); \
+ if (_ct_var(k) != kh_end((TABLE)->id_by_name)) \
+ kh_del_ct_name((TABLE)->id_by_name, _ct_var(k)); \
} \
\
- pool_put(table->connections, conn); \
+ pool_put((TABLE)->connections, CONN); \
} while(0) \
-#define connection_table_len(table) (pool_elts(table->connections))
+/**
+ * @brief Returns the length of the connection table, the number of active
+ * connections.
+ *
+ * @param[in] table The connection table for which we retrieve the length.
+ *
+ * @return size_t The length of the connection table.
+ *
+ * NOTE:
+ * - The length of the connection table, that is the number of currently active
+ * connections.
+ */
+#define connection_table_len(table) (pool_len(table->connections))
+/**
+ * @brief Validate an index in the connection table.
+ *
+ * @param[in] table The connection table in which to validate an index.
+ * @param[in] id The index of the connection to validate.
+ *
+ * @return bool A flag indicating whether the connection index is valid or not.
+ */
#define connection_table_validate_id(table, id) \
pool_validate_id((table)->connections, (id))
+/**
+ * @brief Return the connection corresponding to the specified index in the
+ * connection table.
+ *
+ * @param[in] table The connection table for which to retrieve the connection.
+ * @param[in] id The index for which to retrieve the connection.
+ *
+ * @return connection_t * The connection correponding to the specified index in
+ * the connection table.
+ *
+ * @see connection_table_get_by_id
+ *
+ * NOTE:
+ * - In this function, the index is not validated.
+ */
#define connection_table_at(table, id) ((table)->connections + id)
+/**
+ * @brief Return the connection corresponding to the specified and validated
+ * index in the connection table.
+ *
+ * @param[in] table The connection table for which to retrieve the connection.
+ * @param[in] id The index for which to retrieve the connection.
+ *
+ * @return connection_t * The connection correponding to the specified index in
+ * the connection table.
+ *
+ * @see connection_table_get_by_id
+ *
+ * NOTE:
+ * - In this function, the index is validated.
+ */
+#define connection_table_get_by_id(table, id) \
+ connection_table_validate_id(table, id) \
+ ? connection_table_at(table, id) : NULL
+
+/**
+ * @brief Returns the index of a given connection in the connection table.
+ *
+ * @param[in] table The connection table from which to retrieve the index.
+ * @param[in] conn The connection for which to retrieve the index.
+ *
+ * @return off_t The index of the specified connection in the connection table.
+ */
#define connection_table_get_connection_id(table, conn) \
(conn - table->connections)
@@ -101,26 +189,74 @@ do {
pool_foreach(table->connections, (conn), BODY)
#define connection_table_enumerate(table, i, conn, BODY) \
- pool_foreach(table->connections, (i), (conn), BODY)
+ pool_enumerate(table->connections, (i), (conn), BODY)
-connection_table_t * connection_table_create();
-void connection_table_free(connection_table_t * table);
+/**
+ * @brief Create a new connection table (extended parameters).
+ *
+ * @param[in] init_size Initially allocated size (hint, 0 = use default value).
+ * @param[in] max_size Maximum size (0 = unlimited).
+ *
+ * @return connection_table_t* The newly created connection table.
+ */
+connection_table_t * _connection_table_create(size_t init_size, size_t max_size);
-#define connection_table_get_by_id(table, id) \
- connection_table_validate_id((table), (id)) \
- ? connection_table_at((table), (id)) : NULL;
+/**
+ * @brief Create a new connection table (minimal parameters).
+ *
+ * @return connection_table_t* The newly created connection table.
+ */
+#define connection_table_create() _connection_table_create(0, 0)
+/**
+ * @brief Free a connection table
+ *
+ * @param[in] table Connection table to free
+ */
+void connection_table_free(connection_table_t * table);
+
+/**
+ * @brief Retrieve a connection from the connection table by address pair.
+ *
+ * @param[in] table The connection table in which to search.
+ * @param[in] pair The address pair to search for.
+ *
+ * @return connection_t * The connection matching the specified address pair, or
+ * NULL if not found.
+ */
connection_t * connection_table_get_by_pair(const connection_table_t * table,
const address_pair_t * pair);
-unsigned connection_table_get_id_by_name(const connection_table_t * table,
+/**
+ * @brief Return a connection index from the connection table by name.
+ *
+ * @param[in] table The connection table in which to search.
+ * @param[in] name The name to search for.
+ *
+ * @return off_t The index of the connection matching the name, or
+ * CONNECTION_ID_UNDEFINED if not found.
+ */
+off_t connection_table_get_id_by_name(const connection_table_t * table,
const char * name);
+/**
+ * @brief Return a connection from the connection table by name.
+ *
+ * @param[in] table The connection table in which to search.
+ * @param[in] name The name to search for.
+ *
+ * @return connection_t * The connection matching the name, or NULL if not
+ * found.
+ */
connection_t * connection_table_get_by_name(const connection_table_t * table,
const char * name);
+/**
+ * @brief Remove a connection from the connection table by its index.
+ *
+ * @param[in] table The connection table from which to delete the connection.
+ * @param[in] id The index of the connection to remove.
+ */
void connection_table_remove_by_id(connection_table_t * table, off_t id);
-//unsigned connection_table_add(connection_table_t * table, Connection * connection);
-
-#endif /* HICN_CONNECTION_TABLE_H */
+#endif /* HICNLIGHT_CONNECTION_TABLE_H */
diff --git a/hicn-light/src/hicn/core/content_store.c b/hicn-light/src/hicn/core/content_store.c
index 7ed2bd8..77d40ac 100644
--- a/hicn-light/src/hicn/core/content_store.c
+++ b/hicn-light/src/hicn/core/content_store.c
@@ -46,7 +46,7 @@ do {
content_store_t *
-content_store_create(content_store_type_t type, size_t max_elts)
+_content_store_create(content_store_type_t type, size_t init_size, size_t max_size)
{
content_store_t * cs = malloc(sizeof(content_store_t));
if (!cs)
@@ -56,7 +56,7 @@ content_store_create(content_store_type_t type, size_t max_elts)
cs->type = type;
// XXX TODO an entry = data + metadata specific to each policy
- pool_init(cs->entries, max_elts);
+ pool_init(cs->entries, init_size);
// data
// options
diff --git a/hicn-light/src/hicn/core/content_store.h b/hicn-light/src/hicn/core/content_store.h
index 1a339f4..5cddeaa 100644
--- a/hicn-light/src/hicn/core/content_store.h
+++ b/hicn-light/src/hicn/core/content_store.h
@@ -45,6 +45,7 @@ KHASH_INIT(cs_name, const Name *, unsigned, 0, name_hash, name_hash_eq);
typedef struct {
content_store_type_t type;
+ size_t max_size;
// XXX TODO api to dynamically set max size
content_store_entry_t * entries; // pool
@@ -60,7 +61,25 @@ typedef struct {
content_store_stats_t stats;
} content_store_t;
-content_store_t * content_store_create(content_store_type_t type, size_t max_elts);
+/**
+ * @brief Create a new content store (extended parameters)
+ *
+ * @param[in] type Content store type
+ * @param[in] init_size Initially allocated size (hint, 0 = use default value)
+ * @param[in] max_size Maximum size (0 = unlimited)
+ *
+ * @return content_store_t* - The newly created content store
+ */
+content_store_t * _content_store_create(content_store_type_t type, size_t init_size, size_t max_size);
+
+/**
+ * @brief Create a new content store
+ *
+ * @param[in] type Content store type
+ *
+ * @return content_store_t* - The newly created content store
+ */
+#define content_store_create( TYPE) _content_store_create((TYPE), 0, 0)
void content_store_free(content_store_t * cs);
@@ -74,7 +93,7 @@ void content_store_remove_entry(content_store_t * cs, content_store_entry_t * en
bool content_store_remove(content_store_t * cs, msgbuf_t * msgbuf);
-#define content_store_size(content_store) (pool_elts(cs->entries))
+#define content_store_size(content_store) (pool_len(cs->entries))
void content_store_purge_entry(content_store_t * cs, content_store_entry_t * entry);
diff --git a/hicn-light/src/hicn/core/forwarder.c b/hicn-light/src/hicn/core/forwarder.c
index 94baade..9c3df90 100644
--- a/hicn-light/src/hicn/core/forwarder.c
+++ b/hicn-light/src/hicn/core/forwarder.c
@@ -224,8 +224,8 @@ forwarder_create()
size_t objectStoreSize =
configuration_content_store_get_size(forwarder_get_configuration(forwarder));
- forwarder->content_store = content_store_create(CONTENT_STORE_TYPE_LRU,
- objectStoreSize);
+ forwarder->content_store = _content_store_create(CONTENT_STORE_TYPE_LRU,
+ objectStoreSize, 0);
if (!forwarder->content_store)
goto ERR_CONTENT_STORE;
diff --git a/hicn-light/src/hicn/core/listener_table.c b/hicn-light/src/hicn/core/listener_table.c
index e3cbb31..f69ad75 100644
--- a/hicn-light/src/hicn/core/listener_table.c
+++ b/hicn-light/src/hicn/core/listener_table.c
@@ -18,22 +18,35 @@
* \brief Implementation of hICN listener table
*/
-#include <hicn/core/listener_table.h>
-#include <hicn/core/listener.h>
+#include <hicn/util/log.h>
-/* This is only used for first allocation, as the table is resizeable */
+#include "listener_table.h"
+#include "listener.h"
+
+/* This is only used as a hint for first allocation, as the table is resizeable */
#define DEFAULT_LISTENER_TABLE_SIZE 64
listener_table_t *
-listener_table_create(size_t elt_size, size_t max_elts)
+_listener_table_create(size_t init_size, size_t max_size)
{
+ if (init_size == 0)
+ init_size = DEFAULT_LISTENER_TABLE_SIZE;
+
listener_table_t * table = malloc(sizeof(listener_table_t));
if (!table)
return NULL;
+ table->max_size = max_size;
+
+ /* Initialize indices */
table->id_by_name = kh_init_lt_name();
table->id_by_key = kh_init_lt_key();
- pool_init(table->listeners, DEFAULT_LISTENER_TABLE_SIZE);
+
+ /*
+ * We start by allocating a reasonably-sized pool, as this will eventually
+ * be resized if needed.
+ */
+ pool_init(table->listeners, init_size);
return table;
}
@@ -91,17 +104,3 @@ listener_table_get_by_name(listener_table_t * table, const char * name)
return NULL;
return listener_table_at(table, kh_val(table->id_by_name, k));
}
-
-#if 0
-unsigned
-listener_table_add(listener_table_t * table, listener_t * listener)
-{
- // XXX missing hash and key storage
- listener_t * lst;
- pool_get(table->listeners, lst);
- lst = listener;
- unsigned listener_id = lst - table,
- Listener_SetId(listener, listener_id);
- return listener_id;
-}
-#endif
diff --git a/hicn-light/src/hicn/core/listener_table.h b/hicn-light/src/hicn/core/listener_table.h
index 66959de..70cd8bb 100644
--- a/hicn-light/src/hicn/core/listener_table.h
+++ b/hicn-light/src/hicn/core/listener_table.h
@@ -16,10 +16,19 @@
/**
* \file listener_table.h
* \brief hICN listener table
+ *
+ * The listener table is composed of:
+ * - a pool of listeners allowing access through their index in constant time;
+ * - a set of indices in the form of hash table for efficient index lookups:
+ * . by name
+ * . by key (listener_type, address)
+ *
+ * For efficient index retrieval, the header will be prepended and the
+ * resulting pointer will directly point to the listener pool.
*/
-#ifndef HICN_LISTENER_TABLE_H
-#define HICN_LISTENER_TABLE_H
+#ifndef HICNLIGHT_LISTENER_TABLE_H
+#define HICNLIGHT_LISTENER_TABLE_H
#include <hicn/core/address.h>
#include <hicn/base/common.h>
@@ -30,34 +39,65 @@
#define _lt_var(x) _lt_var_##x
+/* Hash functions for indices */
#define key_hash(key) (hash(key, sizeof(listener_key_t)))
#define key_hash_eq(a, b) (key_hash(b) - key_hash(a))
+/* Hash table types for indices */
KHASH_INIT(lt_name, const char *, unsigned, 0, str_hash, str_hash_eq);
KHASH_INIT(lt_key, listener_key_t *, unsigned, 0, key_hash, key_hash_eq);
typedef struct {
- kh_lt_key_t * id_by_key;
- kh_lt_name_t * id_by_name;
- listener_t * listeners; // pool
+ size_t max_size;
+
+ kh_lt_key_t * id_by_key;
+ kh_lt_name_t * id_by_name;
+
+ listener_t * listeners; // pool
} listener_table_t;
+/**
+ * @brief Allocate a listener from the listener table.
+ *
+ * @param[in] table The listener table from which to allocate a listener.
+ * @param[out] listener The pointer that will hold the allocated listener.
+ * @param[in] pair The address pair associated to the listener (to update index)
+ * @param[in] name The name associated to the listener (to update index)
+ *
+ * NOTE:
+ * - This function updates all indices from the listener table if the
+ * allocation is successful.
+ * - You should always check that the returned listener is not NULL, which
+ * would signal that the pool is exhausted and could not be extended.
+ */
#define listener_table_allocate(TABLE, LISTENER, KEY, NAME) \
do { \
pool_get(table->listeners, (LISTENER)); \
- off_t _lt_var(id) = (LISTENER) - (TABLE)->listeners; \
- int _lt_var(res); \
- khiter_t _lt_var(k); \
- _lt_var(k) = kh_put_lt_name((TABLE)->id_by_name, (NAME), &_lt_var(res)); \
- kh_value((TABLE)->id_by_name, _lt_var(k)) = _lt_var(id); \
- \
- listener->type = (KEY)->type; \
- listener->address = (KEY)->address; \
- listener_key_t * _lt_var(key) = listener_get_key(LISTENER); \
- _lt_var(k) = kh_put_lt_key((TABLE)->id_by_key, _lt_var(key), &_lt_var(res));\
- kh_value((TABLE)->id_by_key, _lt_var(k)) = _lt_var(id); \
+ if (LISTENER) { \
+ off_t _lt_var(id) = (LISTENER) - (TABLE)->listeners; \
+ int _lt_var(res); \
+ khiter_t _lt_var(k); \
+ _lt_var(k) = kh_put_lt_name((TABLE)->id_by_name, (NAME), &_lt_var(res));\
+ kh_value((TABLE)->id_by_name, _lt_var(k)) = _lt_var(id); \
+ \
+ listener->type = (KEY)->type; \
+ listener->address = (KEY)->address; \
+ listener_key_t * _lt_var(key) = listener_get_key(LISTENER); \
+ _lt_var(k) = kh_put_lt_key((TABLE)->id_by_key, _lt_var(key), &_lt_var(res));\
+ kh_value((TABLE)->id_by_key, _lt_var(k)) = _lt_var(id); \
+ } \
} while(0)
+/**
+ * @brief Deallocate a listener and return it to the listener table pool.
+ *
+ * @param[in] table The listener table to which the listener is returned.
+ * @param[in] conn The listener that is returned to the pool.
+ *
+ * NOTE:
+ * - Upon returning a listener to the pool, all indices pointing to that
+ * listener are also cleared.
+ */
#define listener_table_deallocate(TABLE, LISTENER) \
do { \
const address_key_t * _lt_var(key) = listener_get_key(LISTENER); \
@@ -74,33 +114,140 @@ do {
pool_put((TABLE)->listeners, LISTENER); \
} while(0) \
+/**
+ * @brief Returns the length of the connection table, the number of active
+ * connections.
+ *
+ * @param[in] table The connection table for which we retrieve the length.
+ *
+ * @return size_t The length of the connection table.
+ *
+ * NOTE:
+ * - The length of the connection table, that is the number of currently active
+ * connections.
+ */
+#define listener_table_len(table) (pool_len(table->listeners))
-#define listener_table_len(table) (pool_elts(table->listeners))
-
-#define listener_table_validate_id(table, id) pool_validate_id(table->listeners, id)
+/**
+ * @brief Validate an index in the listener table.
+ *
+ * @param[in] table The listener table in which to validate an index.
+ * @param[in] id The index of the listener to validate.
+ *
+ * @return bool A flag indicating whether the listener index is valid or not.
+ */
+#define listener_table_validate_id(table, id) \
+ pool_validate_id(table->listeners, id)
+/**
+ * @brief Return the connection corresponding to the specified index in the
+ * connection table.
+ *
+ * @param[in] table The connection table for which to retrieve the connection.
+ * @param[in] id The index for which to retrieve the connection.
+ *
+ * @return connection_t * The connection correponding to the specified index in
+ * the connection table.
+ *
+ * @see listener_table_get_by_id
+ *
+ * NOTE:
+ * - In this function, the index is not validated.
+ */
#define listener_table_at(table, id) ((table)->listeners + id)
+/**
+ * @brief Return the listener corresponding to the specified and validated
+ * index in the listener table.
+ *
+ * @param[in] table The listener table for which to retrieve the listener.
+ * @param[in] id The index for which to retrieve the listener.
+ *
+ * @return listener_t * The listener correponding to the specified index in
+ * the listener table.
+ *
+ * @see listener_table_get_by_id
+ *
+ * NOTE:
+ * - In this function, the index is validated.
+ */
#define listener_table_get_by_id(table, id) \
listener_table_validate_id(table, id) \
? listener_table_at(table, id) : NULL
+/**
+ * @brief Returns the index of a given listener in the listener table.
+ *
+ * @param[in] table The listener table from which to retrieve the index.
+ * @param[in] conn The listener for which to retrieve the index.
+ *
+ * @return off_t The index of the specified listener in the listener table.
+ */
#define listener_table_get_listener_id(table, listener) (listener - table->listeners)
#define listener_table_foreach(table, listener, BODY) \
pool_foreach(table->listeners, listener, do { BODY } while(0) )
-listener_table_t * listener_table_create();
+#define listener_table_enumerate(table, i, conn, BODY) \
+ pool_enumerate(table->listeners, (i), (conn), BODY)
+
+/**
+ * @brief Create a new listener table (extended parameters)
+ *
+ * @param[in] init_size Initially allocated size (hint, 0 = use default value)
+ * @param[in] max_size Maximum size (0 = unlimited)
+ *
+ * @return listener_table_t* - The newly created listener table
+ */
+listener_table_t * _listener_table_create(size_t init_size, size_t max_size);
+
+/**
+ * @brief Create a new listener table (minimal parameters)
+ *
+ * @return listener_table_t* - The newly created listener table
+ */
+#define listener_table_create() _listener_table_create(0, 0)
+
+/**
+ * @brief Free a listener table
+ *
+ * @param[in] table Listener table to free
+ */
void listener_table_free(listener_table_t * table);
+/**
+ * @brief Retrieve a listener from the listener table by address.
+ *
+ * @param[in] table The listener table in which to search.
+ * @param[in] type The face type characterizing the listener to search for.
+ * @param[in] address The address to search for.
+ *
+ * @return listener_t * The listener matching the specified address, or
+ * NULL if not found.
+ */
listener_t * listener_table_get_by_address(listener_table_t * table,
face_type_t type, const address_t * address);
+/**
+ * @brief Return a listener from the listener table by name.
+ *
+ * @param[in] table The listener table in which to search.
+ * @param[in] name The name to search for.
+ *
+ * @return listener_t * The listener matching the name, or NULL if not
+ * found.
+ */
listener_t * listener_table_get_by_name(listener_table_t * table,
const char *name);
+/**
+ * @brief Remove a listener from the listener table by its index.
+ *
+ * @param[in] table The listener table from which to delete the listener.
+ * @param[in] id The index of the listener to remove.
+ */
void listener_table_remove_by_id(listener_table_t * table, off_t id);
unsigned listener_table_add(listener_table_t * table, listener_t * listener);
-#endif /* HICN_LISTENER_TABLE_H */
+#endif /* HICNLIGHT_LISTENER_TABLE_H */