Fix stat-cache ref counting

personal/stbuehler/wip
Stefan Bühler 14 years ago
parent 70e1bd247d
commit 4653900eca

@ -44,6 +44,9 @@ LI_API void li_waitqueue_push(liWaitQueue *queue, liWaitQueueElem *elem);
/* pops the first ready! element from the queue or NULL if none ready yet. this should be called in your callback */
LI_API liWaitQueueElem *li_waitqueue_pop(liWaitQueue *queue);
/* pops the first element from the queue or NULL if empty. use it to clean your queue */
LI_API liWaitQueueElem *li_waitqueue_pop_force(liWaitQueue *queue);
/* pops all elements from the queue that are ready or NULL of none ready yet. returns number of elements pop()ed and saves old head in '*head' */
LI_API guint li_waitqueue_pop_ready(liWaitQueue *queue, liWaitQueueElem **head);

@ -94,6 +94,25 @@ liWaitQueueElem *li_waitqueue_pop(liWaitQueue *queue) {
return elem;
}
liWaitQueueElem *li_waitqueue_pop_force(liWaitQueue *queue) {
liWaitQueueElem *elem = queue->head;
if (!elem) {
return NULL;
}
if (elem == queue->tail)
queue->tail = NULL;
else
elem->next->prev = NULL;
queue->head = elem->next;
elem->queued = FALSE;
return elem;
}
void li_waitqueue_remove(liWaitQueue *queue, liWaitQueueElem *elem) {
if (!elem->queued)
return;

@ -40,25 +40,30 @@ void stat_cache_new(liWorker *wrk, gdouble ttl) {
}
void stat_cache_free(liStatCache *sc) {
GHashTableIter iter;
gpointer k, v;
liStatCacheEntry *dummy;
liStatCacheEntry *sce;
liWaitQueueElem *wqe;
/* wake up thread */
dummy = g_slice_new0(liStatCacheEntry);
g_async_queue_push(sc->job_queue_out, dummy);
sce = g_slice_new0(liStatCacheEntry);
g_async_queue_push(sc->job_queue_out, sce);
g_thread_join(sc->thread);
g_slice_free(liStatCacheEntry, dummy);
li_ev_safe_ref_and_stop(ev_async_stop, sc->delete_queue.loop, &sc->job_watcher);
g_slice_free(liStatCacheEntry, sce);
/* clear cache */
g_hash_table_iter_init(&iter, sc->entries);
while (g_hash_table_iter_next(&iter, &k, &v)) {
stat_cache_entry_free(v);
li_waitqueue_stop(&sc->delete_queue);
while (NULL != (wqe = li_waitqueue_pop_force(&sc->delete_queue))) {
sce = wqe->data;
if (sce->cached) {
if (sce->type == STAT_CACHE_ENTRY_SINGLE)
g_hash_table_remove(sc->entries, sce->data.path);
else
g_hash_table_remove(sc->dirlists, sce->data.path);
sce->cached = FALSE;
}
stat_cache_entry_free(sce);
}
li_waitqueue_stop(&sc->delete_queue);
li_ev_safe_ref_and_stop(ev_async_stop, sc->delete_queue.loop, &sc->job_watcher);
g_async_queue_unref(sc->job_queue_in);
g_async_queue_unref(sc->job_queue_out);
g_hash_table_destroy(sc->entries);
@ -117,10 +122,6 @@ static void stat_cache_job_cb(struct ev_loop *loop, ev_async *w, int revents) {
for (i = 0; i < sce->vrequests->len; i++) {
vr = g_ptr_array_index(sce->vrequests, i);
li_vrequest_joblist_append(vr);
if (sce->type == STAT_CACHE_ENTRY_SINGLE) {
sce->refcount--;
g_ptr_array_remove_fast(vr->stat_cache_entries, sce);
}
}
g_ptr_array_set_size(sce->vrequests, 0);
@ -267,10 +268,13 @@ liHandlerResult li_stat_cache_get_dirlist(liVRequest *vr, GString *path, liStatC
return LI_HANDLER_WAIT_FOR_EVENT;
}
sce->refcount++;
g_ptr_array_add(vr->stat_cache_entries, sce);
sc->hits++;
*result = sce;
for (i = 0; i < vr->stat_cache_entries->len; i++) {
if (g_ptr_array_index(vr->stat_cache_entries, i) == sce)
return LI_HANDLER_GO_ON;
}
li_stat_cache_entry_acquire(vr, sce);
return LI_HANDLER_GO_ON;
} else {
/* cache miss, allocate new entry */

@ -172,8 +172,6 @@ liVRequest* li_vrequest_new(liConnection *con, liVRequestHandlerCB handle_respon
}
void li_vrequest_free(liVRequest* vr) {
guint i;
li_action_stack_clear(vr, &vr->action_stack);
li_plugins_handle_vrclose(vr);
g_ptr_array_free(vr->plugin_ctx, TRUE);
@ -194,8 +192,8 @@ void li_vrequest_free(liVRequest* vr) {
g_slice_free1(vr->wrk->srv->option_def_values->len * sizeof(liOptionValue), vr->options);
for (i = 0; i < vr->stat_cache_entries->len; i++) {
liStatCacheEntry *sce = g_ptr_array_index(vr->stat_cache_entries, i);
while (vr->stat_cache_entries->len > 0 ) {
liStatCacheEntry *sce = g_ptr_array_index(vr->stat_cache_entries, 0);
li_stat_cache_entry_release(vr, sce);
}
g_ptr_array_free(vr->stat_cache_entries, TRUE);
@ -209,8 +207,6 @@ void li_vrequest_free(liVRequest* vr) {
}
void li_vrequest_reset(liVRequest *vr) {
guint i;
li_action_stack_reset(vr, &vr->action_stack);
li_plugins_handle_vrclose(vr);
{
@ -236,8 +232,8 @@ void li_vrequest_reset(liVRequest *vr) {
g_atomic_int_set(&vr->queued, 0);
}
for (i = 0; i < vr->stat_cache_entries->len; i++) {
liStatCacheEntry *sce = g_ptr_array_index(vr->stat_cache_entries, i);
while (vr->stat_cache_entries->len > 0 ) {
liStatCacheEntry *sce = g_ptr_array_index(vr->stat_cache_entries, 0);
li_stat_cache_entry_release(vr, sce);
}

Loading…
Cancel
Save