summaryrefslogtreecommitdiff
path: root/pjlib-util
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2008-07-12 09:50:48 +0000
committerBenny Prijono <bennylp@teluu.com>2008-07-12 09:50:48 +0000
commit4fd717409a3543061f512dda1e3dacda37e02995 (patch)
tree84804ed5f2c388c0e5c38244882c7767b0e216df /pjlib-util
parent132cbda37abce5fd5703f696ee8fb42cfd6fd41f (diff)
Ticket #560: Optimize the memory usage of DNS resolver
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@2124 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjlib-util')
-rw-r--r--pjlib-util/include/pjlib-util/config.h4
-rw-r--r--pjlib-util/src/pjlib-util/resolver.c87
2 files changed, 54 insertions, 37 deletions
diff --git a/pjlib-util/include/pjlib-util/config.h b/pjlib-util/include/pjlib-util/config.h
index 8c1030a7..1554bdbf 100644
--- a/pjlib-util/include/pjlib-util/config.h
+++ b/pjlib-util/include/pjlib-util/config.h
@@ -178,10 +178,10 @@
* size (PJ_DNS_RESOLVER_MAX_UDP_SIZE), since the DNS replicator function
* (#pj_dns_packet_dup()) is also capable of performing name compressions.
*
- * Default: 1000 (as a broad guidance, 400 is good for 4 SRV entries).
+ * Default: 512
*/
#ifndef PJ_DNS_RESOLVER_RES_BUF_SIZE
-# define PJ_DNS_RESOLVER_RES_BUF_SIZE 1000
+# define PJ_DNS_RESOLVER_RES_BUF_SIZE 512
#endif
diff --git a/pjlib-util/src/pjlib-util/resolver.c b/pjlib-util/src/pjlib-util/resolver.c
index 4cbda0be..c41a9895 100644
--- a/pjlib-util/src/pjlib-util/resolver.c
+++ b/pjlib-util/src/pjlib-util/resolver.c
@@ -150,8 +150,8 @@ struct cached_res
{
PJ_DECL_LIST_MEMBER(struct cached_res);
+ pj_pool_t *pool; /**< Cache's pool. */
struct res_key key; /**< Resource key. */
- char buf[RES_BUF_SZ];/**< Resource buffer. */
pj_hash_entry_buf hbuf; /**< Hash buffer */
pj_time_val expiry_time; /**< Expiration time. */
pj_dns_parsed_packet *pkt; /**< The response packet. */
@@ -195,9 +195,6 @@ struct pj_dns_resolver
/* Hash table for cached response */
pj_hash_table_t *hrescache; /**< Cached response in hash table */
- /* Cached response free list */
- struct cached_res res_free_nodes;
-
/* Pending asynchronous query, hashed by transaction ID. */
pj_hash_table_t *hquerybyid;
@@ -295,9 +292,8 @@ PJ_DEF(pj_status_t) pj_dns_resolver_create( pj_pool_factory *pf,
goto on_error;
}
- /* Response cache hash table and item list */
+ /* Response cache hash table */
resv->hrescache = pj_hash_create(pool, RES_HASH_TABLE_SIZE);
- pj_list_init(&resv->res_free_nodes);
/* Query hash table and free list. */
resv->hquerybyid = pj_hash_create(pool, Q_HASH_TABLE_SIZE);
@@ -351,14 +347,13 @@ on_error:
PJ_DEF(pj_status_t) pj_dns_resolver_destroy( pj_dns_resolver *resolver,
pj_bool_t notify)
{
+ pj_hash_iterator_t it_buf, *it;
PJ_ASSERT_RETURN(resolver, PJ_EINVAL);
if (notify) {
/*
* Notify pending queries if requested.
*/
- pj_hash_iterator_t it_buf, *it;
-
it = pj_hash_first(resolver->hquerybyid, &it_buf);
while (it) {
pj_dns_async_query *q = (pj_dns_async_query *)
@@ -377,6 +372,19 @@ PJ_DEF(pj_status_t) pj_dns_resolver_destroy( pj_dns_resolver *resolver,
}
}
+ /* Destroy cached entries */
+ it = pj_hash_first(resolver->hrescache, &it_buf);
+ while (it) {
+ struct cached_res *cache;
+
+ cache = (struct cached_res*) pj_hash_this(resolver->hrescache, it);
+ pj_hash_set(NULL, resolver->hrescache, &cache->key,
+ sizeof(cache->key), 0, NULL);
+ pj_pool_release(cache->pool);
+
+ it = pj_hash_first(resolver->hrescache, &it_buf);
+ }
+
if (resolver->own_timer && resolver->timer) {
pj_timer_heap_destroy(resolver->timer);
resolver->timer = NULL;
@@ -639,6 +647,28 @@ static void init_res_key(struct res_key *key, int type, const pj_str_t *name)
}
+/* Allocate new cache entry */
+static struct cached_res *alloc_entry(pj_dns_resolver *resolver)
+{
+ pj_pool_t *pool;
+ struct cached_res *cache;
+
+ pool = pj_pool_create(resolver->pool->factory, "dnscache",
+ RES_BUF_SZ, 256, NULL);
+ cache = PJ_POOL_ZALLOC_T(pool, struct cached_res);
+ cache->pool = pool;
+
+ return cache;
+}
+
+/* Put unused/expired cached entry to the free list */
+static void free_entry(pj_dns_resolver *resolver, struct cached_res *cache)
+{
+ PJ_UNUSED_ARG(resolver);
+ pj_pool_release(cache->pool);
+}
+
+
/*
* Create and start asynchronous DNS query for a single resource.
*/
@@ -723,7 +753,7 @@ PJ_DEF(pj_status_t) pj_dns_resolver_start_query( pj_dns_resolver *resolver,
pj_hash_set(NULL, resolver->hrescache, &key, sizeof(key), 0, NULL);
/* Store the entry into free nodes */
- pj_list_push_back(&resolver->res_free_nodes, cache);
+ free_entry(resolver, cache);
/* Must continue with creating a query now */
}
@@ -1065,16 +1095,14 @@ static void update_res_cache(pj_dns_resolver *resolver,
const pj_dns_parsed_packet *pkt)
{
struct cached_res *cache;
- pj_pool_t *res_pool;
pj_uint32_t hval=0, ttl;
- PJ_USE_EXCEPTION;
/* If status is unsuccessful, clear the same entry from the cache */
if (status != PJ_SUCCESS) {
cache = (struct cached_res *) pj_hash_get(resolver->hrescache, key,
sizeof(*key), &hval);
if (cache)
- pj_list_push_back(&resolver->res_free_nodes, cache);
+ free_entry(resolver, cache);
pj_hash_set(NULL, resolver->hrescache, key, sizeof(*key), hval, NULL);
}
@@ -1110,7 +1138,7 @@ static void update_res_cache(pj_dns_resolver *resolver,
cache = (struct cached_res *) pj_hash_get(resolver->hrescache, key,
sizeof(*key), &hval);
if (cache)
- pj_list_push_back(&resolver->res_free_nodes, cache);
+ free_entry(resolver, cache);
pj_hash_set(NULL, resolver->hrescache, key, sizeof(*key), hval, NULL);
return;
}
@@ -1119,12 +1147,7 @@ static void update_res_cache(pj_dns_resolver *resolver,
cache = (struct cached_res *) pj_hash_get(resolver->hrescache, key,
sizeof(*key), &hval);
if (cache == NULL) {
- if (!pj_list_empty(&resolver->res_free_nodes)) {
- cache = resolver->res_free_nodes.next;
- pj_list_erase(cache);
- } else {
- cache = PJ_POOL_ZALLOC_T(resolver->pool, struct cached_res);
- }
+ cache = alloc_entry(resolver);
}
/* Duplicate the packet.
@@ -1133,19 +1156,10 @@ static void update_res_cache(pj_dns_resolver *resolver,
* section since DNS A parser needs the query section to know
* the name being requested.
*/
- res_pool = pj_pool_create_on_buf("respool", cache->buf, sizeof(cache->buf));
- PJ_TRY {
- cache->pkt = NULL;
- pj_dns_packet_dup(res_pool, pkt,
- PJ_DNS_NO_NS | PJ_DNS_NO_AR,
- &cache->pkt);
- }
- PJ_CATCH_ANY {
- PJ_LOG(1,(THIS_FILE,
- "Not enough memory to duplicate DNS response. Response was "
- "truncated."));
- }
- PJ_END;
+ cache->pkt = NULL;
+ pj_dns_packet_dup(cache->pool, pkt,
+ PJ_DNS_NO_NS | PJ_DNS_NO_AR,
+ &cache->pkt);
/* Calculate expiration time */
if (set_expiry) {
@@ -1162,6 +1176,7 @@ static void update_res_cache(pj_dns_resolver *resolver,
/* Update the hash table */
pj_hash_set_np(resolver->hrescache, &cache->key, sizeof(*key), hval,
cache->hbuf, cache);
+
}
@@ -1252,7 +1267,7 @@ static void on_read_complete(pj_ioqueue_key_t *key,
pj_ssize_t bytes_read)
{
pj_dns_resolver *resolver;
- pj_pool_t *pool;
+ pj_pool_t *pool = NULL;
pj_dns_parsed_packet *dns_pkt;
pj_dns_async_query *q;
pj_status_t status;
@@ -1382,6 +1397,10 @@ static void on_read_complete(pj_ioqueue_key_t *key,
pj_list_push_back(&resolver->query_free_nodes, q);
read_next_packet:
+ if (pool) {
+ /* needed just in case PJ_HAS_POOL_ALT_API is set */
+ pj_pool_release(pool);
+ }
bytes_read = sizeof(resolver->udp_rx_pkt);
resolver->udp_addr_len = sizeof(resolver->udp_src_addr);
status = pj_ioqueue_recvfrom(resolver->udp_key, op_key,
@@ -1515,8 +1534,6 @@ PJ_DEF(void) pj_dns_resolver_dump(pj_dns_resolver *resolver,
it = pj_hash_next(resolver->hrescache, it);
}
}
- PJ_LOG(3,(resolver->name.ptr, " Nb. of cached response free nodes: %u",
- pj_list_size(&resolver->res_free_nodes)));
PJ_LOG(3,(resolver->name.ptr, " Nb. of pending queries: %u (%u)",
pj_hash_count(resolver->hquerybyid),
pj_hash_count(resolver->hquerybyres)));