1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "apr_general.h"
19 #include "mod_cache.h"
20 #include "cache_hash.h"
21 #include "cache_pqueue.h"
22 #include "cache_cache.h"
31 struct cache_cache_t
{
34 apr_size_t current_size
;
39 cache_pqueue_set_priority set_pri
;
40 cache_pqueue_get_priority get_pri
;
41 cache_cache_inc_frequency
*inc_entry
;
42 cache_cache_get_size
*size_entry
;
43 cache_cache_get_key
*key_entry
;
44 cache_cache_free
*free_entry
;
47 cache_cache_t
* cache_init(int max_entries
,
49 cache_pqueue_get_priority get_pri
,
50 cache_pqueue_set_priority set_pri
,
51 cache_pqueue_getpos get_pos
,
52 cache_pqueue_setpos set_pos
,
53 cache_cache_inc_frequency
*inc_entry
,
54 cache_cache_get_size
*size_entry
,
55 cache_cache_get_key
* key_entry
,
56 cache_cache_free
*free_entry
)
59 tmp
= malloc(sizeof(cache_cache_t
));
60 tmp
->max_entries
= max_entries
;
61 tmp
->max_size
= max_size
;
62 tmp
->current_size
= 0;
63 tmp
->total_purges
= 0;
65 tmp
->get_pri
= get_pri
;
66 tmp
->set_pri
= set_pri
;
67 tmp
->inc_entry
= inc_entry
;
68 tmp
->size_entry
= size_entry
;
69 tmp
->key_entry
= key_entry
;
70 tmp
->free_entry
= free_entry
;
72 tmp
->ht
= cache_hash_make(max_entries
);
73 tmp
->pq
= cache_pq_init(max_entries
, get_pri
, get_pos
, set_pos
);
78 void cache_free(cache_cache_t
*c
)
81 cache_hash_free(c
->ht
);
86 void* cache_find(cache_cache_t
* c
, const char *key
)
88 return cache_hash_get(c
->ht
, key
, CACHE_HASH_KEY_STRING
);
91 void cache_update(cache_cache_t
* c
, void *entry
)
96 old_priority
= c
->set_pri(c
->queue_clock
, entry
);
98 new_priority
= c
->set_pri(c
->queue_clock
, entry
);
99 cache_pq_change_priority(c
->pq
, old_priority
, new_priority
, entry
);
102 void cache_insert(cache_cache_t
* c
, void *entry
)
104 void *ejected
= NULL
;
107 c
->set_pri(c
->queue_clock
, entry
);
108 /* FIX: check if priority of bottom item is greater than inserted one */
109 while ((cache_pq_size(c
->pq
) >= c
->max_entries
) ||
110 ((c
->current_size
+ c
->size_entry(entry
)) > c
->max_size
)) {
112 ejected
= cache_pq_pop(c
->pq
);
113 /* FIX: If ejected is NULL, we'll segfault here */
114 priority
= c
->get_pri(ejected
);
116 if (c
->queue_clock
> priority
)
117 c
->queue_clock
= priority
;
119 cache_hash_set(c
->ht
,
120 c
->key_entry(ejected
),
121 CACHE_HASH_KEY_STRING
,
124 ap_log_error(APLOG_MARK
, APLOG_DEBUG
, 0, NULL
, "Cache Purge of %s",c
->key_entry(ejected
));
125 c
->current_size
-= c
->size_entry(ejected
);
126 c
->free_entry(ejected
);
129 c
->current_size
+= c
->size_entry(entry
);
131 cache_pq_insert(c
->pq
, entry
);
132 cache_hash_set(c
->ht
, c
->key_entry(entry
), CACHE_HASH_KEY_STRING
, entry
);
135 void* cache_pop(cache_cache_t
*c
)
142 entry
= cache_pq_pop(c
->pq
);
147 c
->current_size
-= c
->size_entry(entry
);
148 cache_hash_set(c
->ht
, c
->key_entry(entry
), CACHE_HASH_KEY_STRING
, NULL
);
153 apr_status_t
cache_remove(cache_cache_t
*c
, void *entry
)
155 apr_size_t entry_size
= c
->size_entry(entry
);
157 rc
= cache_pq_remove(c
->pq
, entry
);
158 if (rc
!= APR_SUCCESS
)
161 cache_hash_set(c
->ht
, c
->key_entry(entry
), CACHE_HASH_KEY_STRING
, NULL
);
162 c
->current_size
-= entry_size
;