MINOR peers: data structure simplifications for server names dictionary cache.

We store pointers to server names dictionary entries in a pre-allocated array of
ebpt_node's (->entries member of struct dcache_tx) to cache those sent to remote
peers. Consequently the ID used to identify the server name dictionary entry is
also used as index for this array. There is no need to implement a lookup by key
for this dictionary cache.
diff --git a/src/peers.c b/src/peers.c
index eebf48a..6cb01a9 100644
--- a/src/peers.c
+++ b/src/peers.c
@@ -250,8 +250,8 @@
 struct peers *cfg_peers = NULL;
 static void peer_session_forceshutdown(struct peer *peer);
 
-struct dcache_tx_entry *dcache_tx_insert(struct dcache *dc,
-                                         struct dcache_tx_entry *i);
+static struct ebpt_node *dcache_tx_insert(struct dcache *dc,
+                                          struct dcache_tx_entry *i);
 static inline void flush_dcache(struct peer *peer);
 
 static const char *statuscode_str(int statuscode)
@@ -524,7 +524,7 @@
 				}
 				case STD_T_DICT: {
 					struct dict_entry *de;
-					struct dcache_tx_entry *cached_de;
+					struct ebpt_node *cached_de;
 					struct dcache_tx_entry cde = { };
 					char *beg, *end;
 					size_t value_len, data_len;
@@ -535,16 +535,13 @@
 						break;
 
 					dc = peer->dcache;
-					cde.value.key = de;
+					cde.entry.key = de;
 					cached_de = dcache_tx_insert(dc, &cde);
-					if (!cached_de)
-						break;
-
 					/* Leave enough room to encode the remaining data length. */
 					end = beg = cursor + PEER_MSG_ENC_LENGTH_MAXLEN;
 					/* Encode the dictionary entry key */
-					intencode(cached_de->key.key + 1, &end);
-					if (cached_de != &cde) {
+					intencode(cde.id + 1, &end);
+					if (cached_de != &cde.entry) {
 						/* Encode the length of the dictionary entry data */
 						value_len = strlen(de->value.key);
 						intencode(value_len, &end);
@@ -2833,29 +2830,42 @@
 /*
  * Allocate a cache a dictionary entries used upon transmission.
  */
-struct dcache_tx *new_dcache_tx(size_t max_entries)
+static struct dcache_tx *new_dcache_tx(size_t max_entries)
 {
 	struct dcache_tx *d;
+	struct ebpt_node *entries;
 
 	d = malloc(sizeof *d);
-	if (!d)
-		return NULL;
+	entries = calloc(max_entries, sizeof *entries);
+	if (!d || !entries)
+		goto err;
 
 	d->lru_key = 0;
-	d->keys = EB_ROOT_UNIQUE;
-	d->values = EB_ROOT_UNIQUE;
-	d->max_entries = max_entries;
+	d->cached_entries = EB_ROOT_UNIQUE;
+	d->entries = entries;
 
 	return d;
+
+ err:
+	free(d);
+	free(entries);
+	return NULL;
 }
 
+static void free_dcache_tx(struct dcache_tx *dc)
+{
+	free(dc->entries);
+	dc->entries = NULL;
+	free(dc);
+}
+
 /*
  * Allocate a cache of dictionary entries with <name> as name and <max_entries>
  * as maximum of entries.
  * Return the dictionay cache if succeeded, NULL if not.
  * Must be deallocated calling free_dcache().
  */
-struct dcache *new_dcache(size_t max_entries)
+static struct dcache *new_dcache(size_t max_entries)
 {
 	struct dcache_tx *dc_tx;
 	struct dcache *dc;
@@ -2883,80 +2893,27 @@
 /*
  * Deallocate a cache of dictionary entries.
  */
-void free_dcache(struct dcache *dc)
+static inline void free_dcache(struct dcache *dc)
 {
-	free(dc->tx); dc->tx = NULL;
+	free_dcache_tx(dc->tx);
+	dc->tx = NULL;
 	free(dc->rx); dc->rx = NULL;
 	free(dc);
 }
 
-/*
- * Look for the dictionary entry with <k> as key in <d> cache of dictionary entries
- * used upon transmission.
- * Return the entry if found, NULL if not.
- */
-struct dcache_tx_entry *dcache_tx_lookup_key(struct dcache_tx *d, unsigned int k)
-{
-	struct dcache_tx_entry *de;
-	struct eb32_node *node;
-
-	de = NULL;
-	node = eb32_lookup(&d->keys, k);
-	if (node)
-		de = container_of(node, struct dcache_tx_entry, key);
-
-	return de;
-}
 
 /*
  * Look for the dictionary entry with the value of <i> in <d> cache of dictionary
  * entries used upon transmission.
  * Return the entry if found, NULL if not.
  */
-struct dcache_tx_entry *dcache_tx_lookup_value(struct dcache_tx *d,
-                                               struct dcache_tx_entry *i)
-{
-	struct dcache_tx_entry *de;
-	struct ebpt_node *node;
-
-	de = NULL;
-	node = ebpt_lookup(&d->values, i->value.key);
-	if (node)
-		de = container_of(node, struct dcache_tx_entry, value);
-
-	return de;
-}
-
-/*
- * Release the memory allocated for the cached dictionary entry <dce>.
- */
-
-static inline void free_dcache_tx_entry(struct dcache_tx_entry *dce)
+static struct ebpt_node *dcache_tx_lookup_value(struct dcache_tx *d,
+                                                struct dcache_tx_entry *i)
 {
-	dce->value.key = NULL;
-	dce->key.key = 0;
-	free(dce);
+	return ebpt_lookup(&d->cached_entries, i->entry.key);
 }
 
 /*
- * Allocate a new dictionary entry with <s> as string value which is strdup()'ed.
- * Returns the new allocated entry if succeeded, NULL if not.
- */
-struct dcache_tx_entry *new_dcache_tx_entry(unsigned int k, struct dict_entry *de)
-{
-	struct dcache_tx_entry *dce;
-
-	dce = calloc(1, sizeof *dce);
-	if (!dce)
-		return NULL;
-
-	dce->value.key = de;
-	dce->key.key = k;
-
-	return dce;
-}
-
-/*
  * Flush <dc> cache.
  * Always succeeds.
  */
@@ -2965,68 +2922,41 @@
 	int i;
 	struct dcache *dc = peer->dcache;
 
-	if (!eb_is_empty(&dc->tx->keys)) {
-		struct eb32_node *node, *next;
+	for (i = 0; i < dc->max_entries; i++)
+		ebpt_delete(&dc->tx->entries[i]);
 
-		for (node = eb32_first(&dc->tx->keys); node; node = next) {
-			next = eb32_next(node);
-			eb32_delete(node);
-		}
-	}
-
-	if (!eb_is_empty(&dc->tx->values)) {
-		struct ebpt_node *node, *next;
-
-		for (node = ebpt_first(&dc->tx->values); node; node = next) {
-			struct dcache_tx_entry *de;
-
-			next = ebpt_next(node);
-			ebpt_delete(node);
-			de = container_of(node, struct dcache_tx_entry, value);
-			free_dcache_tx_entry(de);
-		}
-	}
-
-	for (i = 0; i < dc->max_entries; i++) {
-		dc->rx[i].id = 0;
-		dc->rx[i].de = NULL;
-	}
+	memset(dc->rx, 0, dc->max_entries * sizeof *dc->rx);
 }
 
 /*
  * Insert a dictionary entry in <dc> cache part used upon transmission (->tx)
  * with information provided by <i> dictionary cache entry (especially the value
  * to be inserted if not already). Return <i> if already present in the cache
- * or something different of <i> if not already in the cache, or NULL if something
- * failed.
+ * or something different of <i> if not.
  */
-struct dcache_tx_entry *dcache_tx_insert(struct dcache *dc,
-                                         struct dcache_tx_entry *i)
+static struct ebpt_node *dcache_tx_insert(struct dcache *dc, struct dcache_tx_entry *i)
 {
 	struct dcache_tx *dc_tx;
-	struct dcache_tx_entry *o;
+	struct ebpt_node *o;
 
 	dc_tx = dc->tx;
 	o = dcache_tx_lookup_value(dc_tx, i);
 	if (o) {
-		/* Copy the key. */
-		i->key.key = o->key.key;
-		return i;
+		/* Copy the ID. */
+		i->id = o - dc->tx->entries;
+		return &i->entry;
 	}
 
-	o = dcache_tx_lookup_key(dc_tx, dc_tx->lru_key);
-	if (o) {
-		o->value.key = i->value.key;
-		return o;
-	}
+	/* The new entry to put in cache */
+	o = &dc_tx->entries[dc_tx->lru_key];
 
-	o = new_dcache_tx_entry(dc_tx->lru_key, i->value.key);
-	if (!o)
-		return NULL;
+	ebpt_delete(o);
+	o->key = i->entry.key;
+	ebpt_insert(&dc_tx->cached_entries, o);
+	i->id = dc_tx->lru_key;
 
-	dc_tx->lru_key = (dc_tx->lru_key + 1) & (dc_tx->max_entries - 1);
-	eb32_insert(&dc_tx->keys, &o->key);
-	ebpt_insert(&dc_tx->values, &o->value);
+	/* Update the index for the next entry to put in cache */
+	dc_tx->lru_key = (dc_tx->lru_key + 1) & (dc->max_entries - 1);
 
 	return o;
 }
@@ -3238,20 +3168,21 @@
 			chunk_appendf(&trash, "\n              table:%p id=%s update=%u localupdate=%u"
 			              " commitupdate=%u syncing=%u",
 			              t, t->id, t->update, t->localupdate, t->commitupdate, t->syncing);
-			if (!eb_is_empty(&dcache->tx->keys)) {
-				struct eb32_node *node;
-				struct dcache_tx_entry *de;
+			chunk_appendf(&trash, "\n        TX dictionary cache:");
+			count = 0;
+			for (i = 0; i < dcache->max_entries; i++) {
+				struct ebpt_node *node;
+				struct dict_entry *de;
 
-				chunk_appendf(&trash, "\n        TX dictionary cache:");
-				count = 0;
-				for (node = eb32_first(&dcache->tx->keys); node; node = eb32_next(node)) {
-					if (!count++)
-						chunk_appendf(&trash, "\n        ");
-					de = container_of(node, struct dcache_tx_entry, key);
-					chunk_appendf(&trash, "  %3u -> %s", node->key,
-					              (char *)((struct dict_entry *)(de->value.key))->value.key);
-					count &= 0x3;
-				}
+				node = &dcache->tx->entries[i];
+				if (!node->key)
+					break;
+
+				if (!count++)
+					chunk_appendf(&trash, "\n        ");
+				de = node->key;
+				chunk_appendf(&trash, "  %3u -> %s", i, (char *)de->value.key);
+				count &= 0x3;
 			}
 			chunk_appendf(&trash, "\n        RX dictionary cache:");
 			count = 0;