/** * Turn LRU deferred writes on or off. * @return -1 on error with errno set, 0 if OK. */ int setwdelay(DBM *db, bool on) { struct lru_cache *cache = db->cache; if (NULL == cache) return init_cache(db, LRU_PAGES, on); sdbm_lru_check(cache); if (on == cache->write_deferred) return 0; /* * Value is inverted. */ if (cache->write_deferred) { flush_dirtypag(db); cache->write_deferred = FALSE; } else { cache->write_deferred = TRUE; } return 0; }
/** * Close the LRU page cache. */ void lru_close(DBM *db) { struct lru_cache *cache = db->cache; if (cache) { if (!db->is_volatile) flush_dirtypag(db); if (common_stats) log_lrustats(db); free_cache(cache); WFREE(cache); } db->cache = NULL; }
/** * Close the LRU page cache. */ void lru_close(DBM *db) { struct lru_cache *cache = db->cache; if (cache) { sdbm_lru_check(cache); if (!db->is_volatile && !(db->flags & DBM_BROKEN)) flush_dirtypag(db); if (common_stats) log_lrustats(db); free_cache(cache); cache->magic = 0; WFREE(cache); } db->cache = NULL; }
/** * Set the page cache size. * @return 0 if OK, -1 on failure with errno set. */ int setcache(DBM *db, long pages) { struct lru_cache *cache = db->cache; bool wdelay; sdbm_lru_check(cache); if (pages <= 0) { errno = EINVAL; return -1; } if (NULL == cache) return init_cache(db, pages, FALSE); /* * Easiest case: the size identical. */ if (pages == cache->pages) return 0; /* * Cache size is changed. * * This means the arena will be reallocated, so we must invalidate the * current db->pagbuf pointer, which lies within the old arena. It is * sufficient to reset db->pagbno, forcing a reload from the upper layers. * Note than when the cache size is enlarged, the old page is still cached * so reloading will be just a matter of recomputing db->pagbuf. We could * do so here, but cache size changes should only be infrequent. * * We also reset all the cache statistics, since a different cache size * will imply a different set of hit/miss ratio. */ db->pagbno = -1; /* Current page address will become invalid */ db->pagbuf = NULL; if (common_stats) { s_info("sdbm: \"%s\" LRU cache size %s from %ld page%s to %ld", sdbm_name(db), pages > cache->pages ? "increased" : "decreased", cache->pages, plural(cache->pages), pages); log_lrustats(db); } cache->rhits = cache->rmisses = 0; cache->whits = cache->wmisses = 0; /* * Straightforward: the size is increased. */ if (pages > cache->pages) { char *new_arena = vmm_alloc(pages * DBM_PBLKSIZ); if (NULL == new_arena) return -1; memmove(new_arena, cache->arena, cache->pages * DBM_PBLKSIZ); vmm_free(cache->arena, cache->pages * DBM_PBLKSIZ); cache->arena = new_arena; cache->dirty = wrealloc(cache->dirty, cache->pages, pages); cache->numpag = wrealloc(cache->numpag, cache->pages * sizeof(long), pages * sizeof(long)); cache->pages = pages; return 0; } /* * Difficult: the size is decreased. * * The current page buffer could point in a cache area that is going * to disappear, and the internal data structures must forget about * all the old indices that are greater than the new limit. * * We do not try to optimize anything here, as this call should happen * only infrequently: we flush the current cache (in case there are * deferred writes), destroy the LRU cache data structures, recreate a * new one and invalidate the current DB page. */ wdelay = cache->write_deferred; flush_dirtypag(db); free_cache(cache); return setup_cache(cache, pages, wdelay); }