+/* }}} */
+/* {{{ dircache */
+
+local char *domaintree_cache_get(MDT_CNF *DT, apr_time_t atime, const char *host)
+{
+ char *path = NULL;
+ dircache_entry_t *cache_entry;
+
+ apr_global_mutex_lock(DT->dircache.lock);
+
+ if ((cache_entry = apr_hash_get(DT->dircache.hmap, host, APR_HASH_KEY_STRING))) {
+ cache_entry->lacc = atime;
+ path = cache_entry->path;
+ }
+
+ apr_global_mutex_unlock(DT->dircache.lock);
+
+ if (path) {
+ ap_log_error(DT_LOG_DBG "cache hit = %s for %s", path, host);
+ }
+
+ return path;
+}
+
+local void domaintree_cache_set(MDT_CNF *DT, apr_time_t atime, const char *host, const char *path)
+{
+ apr_pool_t *pool;
+ dircache_entry_t *cache_entry;
+
+ apr_pool_create(&pool, DT->dircache.pool);
+ cache_entry = apr_palloc(pool, sizeof(dircache_entry_t));
+
+ cache_entry->pool = pool;
+ cache_entry->lacc = atime;
+ cache_entry->host = apr_pstrdup(pool, host);
+ cache_entry->path = apr_pstrdup(pool, path);
+
+ apr_global_mutex_lock(DT->dircache.lock);
+
+ if (apr_hash_count(DT->dircache.hmap) >= DT->dircache.clim) {
+ apr_hash_index_t *idx;
+ dircache_entry_t *purge_this = NULL;
+
+ ap_log_error(DT_LOG_WRN "reached cache limit (%ld)", DT->dircache.clim);
+
+ for (idx = apr_hash_first(DT->dircache.pool, DT->dircache.hmap); idx; idx = apr_hash_next(idx)) {
+ dircache_entry_t *current;
+
+ apr_hash_this(idx, NULL, NULL, (void *) ¤t);
+ if ((!purge_this) || (purge_this->lacc > current->lacc)) {
+ purge_this = current;
+ }
+ }
+
+ if (purge_this) {
+ ap_log_error(DT_LOG_DBG "cache del = %s", purge_this->host);
+ apr_hash_set(DT->dircache.hmap, purge_this->host, APR_HASH_KEY_STRING, NULL);
+ apr_pool_destroy(purge_this->pool);
+ }
+ }
+ apr_hash_set(DT->dircache.hmap, cache_entry->host, APR_HASH_KEY_STRING, cache_entry);
+
+ apr_global_mutex_unlock(DT->dircache.lock);
+
+ ap_log_error(DT_LOG_DBG "cache set = %s for %s", path, host);
+}