/* Remove the one element of the cache based on it's access time. */ static void tags_cache_gc (struct tags_cache *c) { DBC *cur; DBT key; DBT serialized_cache_rec; int ret; char *last_referenced = NULL; time_t last_referenced_atime = time (NULL); int nitems = 0; assert (c != NULL); if (!c->db) return; c->db->cursor (c->db, NULL, &cur, 0); memset (&key, 0, sizeof(key)); memset (&serialized_cache_rec, 0, sizeof(serialized_cache_rec)); key.flags = DB_DBT_MALLOC; serialized_cache_rec.flags = DB_DBT_MALLOC; while ((ret = cur->c_get(cur, &key, &serialized_cache_rec, DB_NEXT)) == 0) { struct cache_record rec; if (cache_record_deserialize(&rec, serialized_cache_rec.data, serialized_cache_rec.size, 1) && rec.atime < last_referenced_atime) { last_referenced_atime = rec.atime; if (last_referenced) free (last_referenced); last_referenced = (char *)xmalloc (key.size + 1); memcpy (last_referenced, key.data, key.size); last_referenced[key.size] = '\0'; } // TODO: remove objects with serialization error. nitems++; free (key.data); free (serialized_cache_rec.data); } if (ret != DB_NOTFOUND) logit ("Searching for element to remove failed (cursor): %s", db_strerror(ret)); cur->c_close (cur); debug ("Elements in cache: %d (limit %d)", nitems, c->max_items); if (last_referenced) { if (nitems > c->max_items) tags_cache_remove_rec (c, last_referenced); free (last_referenced); } else debug ("Cache empty"); }
static void tags_cache_gc (struct tags_cache *c) { DBC *cur; DBT key; DBT serialized_cache_rec; int ret; char *last_referenced = NULL; time_t last_referenced_atime = time (NULL) + 1; int nitems = 0; c->db->cursor (c->db, NULL, &cur, 0); memset (&key, 0, sizeof(key)); memset (&serialized_cache_rec, 0, sizeof(serialized_cache_rec)); key.flags = DB_DBT_MALLOC; serialized_cache_rec.flags = DB_DBT_MALLOC; while (true) { struct cache_record rec; #if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR < 6 ret = cur->c_get (cur, &key, &serialized_cache_rec, DB_NEXT); #else ret = cur->get (cur, &key, &serialized_cache_rec, DB_NEXT); #endif if (ret != 0) break; if (cache_record_deserialize (&rec, serialized_cache_rec.data, serialized_cache_rec.size, 1) && rec.atime < last_referenced_atime) { last_referenced_atime = rec.atime; if (last_referenced) free (last_referenced); last_referenced = (char *)xmalloc (key.size + 1); memcpy (last_referenced, key.data, key.size); last_referenced[key.size] = '\0'; } // TODO: remove objects with serialization error. nitems++; free (key.data); free (serialized_cache_rec.data); } if (ret != DB_NOTFOUND) log_errno ("Searching for element to remove failed (cursor)", ret); #if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR < 6 cur->c_close (cur); #else cur->close (cur); #endif debug ("Elements in cache: %d (limit %d)", nitems, c->max_items); if (last_referenced) { if (nitems >= c->max_items) tags_cache_remove_rec (c, last_referenced); free (last_referenced); } else debug ("Cache empty"); }