/** * em_cache_add: * @emc: * @n: * * Add a cache node to the cache, once added the memory is owned by * the cache. If there are conflicts and the old node is still in * use, then the new node is not added, otherwise it is added and any * nodes older than the expire time are flushed. **/ void em_cache_add(EMCache *emc, EMCacheNode *n) { EMCacheNode *old, *prev; EDList old_nodes; e_dlist_init(&old_nodes); g_mutex_lock(emc->lock); old = g_hash_table_lookup(emc->key_table, n->key); if (old != NULL) { if (old->ref_count == 0) { g_hash_table_remove(emc->key_table, old->key); e_dlist_remove((EDListNode *)old); e_dlist_addtail(&old_nodes, (EDListNode *)old); goto insert; } else { e_dlist_addtail(&old_nodes, (EDListNode *)n); } } else { time_t now; insert: now = time(0); g_hash_table_insert(emc->key_table, n->key, n); e_dlist_addhead(&emc->lru_list, (EDListNode *)n); n->stamp = now; emc->node_count++; c(printf("inserting node %s\n", n->key)); old = (EMCacheNode *)emc->lru_list.tailpred; prev = old->prev; while (prev && old->stamp < now - emc->timeout) { if (old->ref_count == 0) { c(printf("expiring node %s\n", old->key)); g_hash_table_remove(emc->key_table, old->key); e_dlist_remove((EDListNode *)old); e_dlist_addtail(&old_nodes, (EDListNode *)old); } old = prev; prev = prev->prev; } } g_mutex_unlock(emc->lock); while ((old = (EMCacheNode *)e_dlist_remhead(&old_nodes))) { emc->node_free(old); g_free(old->key); g_free(old); } }
/** * camel_operation_unref: * @cc: operation context * * Unref and potentially free @cc. **/ void camel_operation_unref (CamelOperation *cc) { GSList *n; g_assert(cc->refcount > 0); LOCK(); if (cc->refcount == 1) { CamelOperationMsg *msg; e_dlist_remove((EDListNode *)cc); while ((msg = (CamelOperationMsg *)e_msgport_get(cc->cancel_port))) g_free(msg); e_msgport_destroy(cc->cancel_port); n = cc->status_stack; while (n) { g_warning("Camel operation status stack non empty: %s", (char *)n->data); g_free(n->data); n = n->next; } g_slist_free(cc->status_stack); g_free(cc); } else { cc->refcount--; } UNLOCK(); }
/** * camel_offline_journal_replay: * @journal: a #CamelOfflineJournal object * @ex: a #CamelException * * Replay all entries in the journal. * * Returns %0 on success (no entry failed to replay) or %-1 on fail **/ int camel_offline_journal_replay (CamelOfflineJournal *journal, CamelException *ex) { EDListNode *entry, *next; CamelException lex; int failed = 0; camel_exception_init (&lex); entry = journal->queue.head; while (entry->next) { next = entry->next; if (CAMEL_OFFLINE_JOURNAL_GET_CLASS (journal)->entry_play (journal, entry, &lex) == -1) { if (failed == 0) camel_exception_xfer (ex, &lex); camel_exception_clear (&lex); failed++; } else { e_dlist_remove (entry); } entry = next; } if (failed > 0) return -1; return 0; }
/** * e_event_remove_items: * @emp: * @handle: * * Remove items previously added. They MUST have been previously * added, and may only be removed once. **/ void e_event_remove_items(EEvent *emp, void *handle) { struct _event_node *node = handle; e_dlist_remove((EDListNode *)node); if (node->freefunc) node->freefunc(emp, node->events, node->data); g_free(node); if (emp->priv->sorted) { g_slist_foreach(emp->priv->sorted, (GFunc)g_free, NULL); g_slist_free(emp->priv->sorted); emp->priv->sorted = NULL; } }
void e_import_class_remove_importer(EImportClass *klass, EImportImporter *f) { struct _EImportImporters *ei, *en; ei = (struct _EImportImporters *)klass->importers.head; en = ei->next; while (en) { if (ei->importer == f) { e_dlist_remove((EDListNode *)ei); if (ei->free) ei->free(f, ei->data); g_free(ei); } ei = en; en = en->next; } }
/** * em_cache_lookup: * @emc: * @key: * * Lookup a cache node. once you're finished with it, you need to * unref it. * * Return value: **/ EMCacheNode * em_cache_lookup(EMCache *emc, const char *key) { EMCacheNode *n; g_mutex_lock(emc->lock); n = g_hash_table_lookup(emc->key_table, key); if (n) { e_dlist_remove((EDListNode *)n); e_dlist_addhead(&emc->lru_list, (EDListNode *)n); n->stamp = time(0); n->ref_count++; } g_mutex_unlock(emc->lock); c(printf("looking up '%s' %s\n", key, n?"found":"not found")); return n; }
void e_iconv_close(iconv_t ip) { struct _iconv_cache_node *in; if (ip == (iconv_t)-1) return; LOCK(); in = g_hash_table_lookup(iconv_cache_open, ip); if (in) { cd(printf("closing iconv converter '%s'\n", in->parent->conv)); e_dlist_remove((EDListNode *)in); in->busy = FALSE; e_dlist_addtail(&in->parent->open, (EDListNode *)in); } else { g_warning("trying to close iconv i dont know about: %p", ip); iconv_close(ip); } UNLOCK(); }
/* This should run pretty quick, its called a lot */ iconv_t e_iconv_open(const char *oto, const char *ofrom) { const char *to, *from; char *tofrom; struct _iconv_cache *ic; struct _iconv_cache_node *in; int errnosav; iconv_t ip; to = e_iconv_charset_name (oto); from = e_iconv_charset_name (ofrom); /* e_iconv_charset_name() could return NULL in case of invalid charset. So, we need to check them here. */ if (to == NULL || from == NULL) { errno = EINVAL; return (iconv_t) -1; } tofrom = g_alloca (strlen (to) + strlen (from) + 2); sprintf(tofrom, "%s%%%s", to, from); LOCK(); ic = g_hash_table_lookup(iconv_cache, tofrom); if (ic) { e_dlist_remove((EDListNode *)ic); } else { struct _iconv_cache *last = (struct _iconv_cache *)iconv_cache_list.tailpred; struct _iconv_cache *prev; prev = last->prev; while (prev && iconv_cache_size > E_ICONV_CACHE_SIZE) { in = (struct _iconv_cache_node *)last->open.head; if (in->next && !in->busy) { cd(printf("Flushing iconv converter '%s'\n", last->conv)); e_dlist_remove((EDListNode *)last); g_hash_table_remove(iconv_cache, last->conv); flush_entry(last); iconv_cache_size--; } last = prev; prev = last->prev; } iconv_cache_size++; ic = g_malloc(sizeof(*ic)); e_dlist_init(&ic->open); ic->conv = g_strdup(tofrom); g_hash_table_insert(iconv_cache, ic->conv, ic); cd(printf("Creating iconv converter '%s'\n", ic->conv)); } e_dlist_addhead(&iconv_cache_list, (EDListNode *)ic); /* If we have a free iconv, use it */ in = (struct _iconv_cache_node *)ic->open.tailpred; if (in->prev && !in->busy) { cd(printf("using existing iconv converter '%s'\n", ic->conv)); ip = in->ip; if (ip != (iconv_t)-1) { /* work around some broken iconv implementations * that die if the length arguments are NULL */ size_t buggy_iconv_len = 0; char *buggy_iconv_buf = NULL; /* resets the converter */ iconv(ip, &buggy_iconv_buf, &buggy_iconv_len, &buggy_iconv_buf, &buggy_iconv_len); in->busy = TRUE; e_dlist_remove((EDListNode *)in); e_dlist_addhead(&ic->open, (EDListNode *)in); } } else { cd(printf("creating new iconv converter '%s'\n", ic->conv)); ip = iconv_open(to, from); in = g_malloc(sizeof(*in)); in->ip = ip; in->parent = ic; e_dlist_addhead(&ic->open, (EDListNode *)in); if (ip != (iconv_t)-1) { g_hash_table_insert(iconv_cache_open, ip, in); in->busy = TRUE; } else { errnosav = errno; /* g_warning("Could not open converter for '%s' to '%s' charset", from, to); */ in->busy = FALSE; errno = errnosav; } } UNLOCK(); return ip; }