/** * Close DM map, keeping the SDBM file around. * * If the map was held in memory, it is serialized to disk. */ void dbstore_close(dbmw_t *dw, const char *dir, const char *base) { bool ok; char *path; if (NULL == dw) return; path = make_pathname(dir, base); if (dbstore_debug > 1) g_debug("DBSTORE persisting DBMW \"%s\" as %s", dbmw_name(dw), path); ok = dbmw_store(dw, path, TRUE); HFREE_NULL(path); if (dbstore_debug > 0) { size_t count = dbmw_count(dw); g_debug("DBSTORE %ssucessfully persisted DBMW \"%s\" (%u key%s)", ok ? "" : "un", dbmw_name(dw), (unsigned) count, 1 == count ? "" : "s"); } dbmw_destroy(dw, TRUE); }
/** * Attempt to clear / shrink the DBMW database. */ void dbstore_shrink(dbmw_t *dw) { /* * If we retained no entries, issue a dbmw_clear() to restore underlying * SDBM files to their smallest possible value. This is necessary because * the database is persistent and it can grow very large on disk, but still * holding only a few values per page. Being able to get a fresh start * occasionally is a plus. */ if (0 == dbmw_count(dw)) { if (dbstore_debug > 1) { g_debug("DBSTORE clearing database DBMW \"%s\"", dbmw_name(dw)); } if (!dbmw_clear(dw)) { if (dbstore_debug) { g_warning("DBSTORE unable to clear DBMW \"%s\"", dbmw_name(dw)); } } } else { if (dbstore_debug > 1) { g_debug("DBSTORE shrinking database DBMW \"%s\"", dbmw_name(dw)); } if (!dbmw_shrink(dw)) { if (dbstore_debug) { g_warning("DBSTORE unable to shrink DBMW \"%s\"", dbmw_name(dw)); } } } }
/** * Synchronize a DBMW database, flushing its local cache. */ void dbstore_flush(dbmw_t *dw) { ssize_t n; n = dbmw_sync(dw, DBMW_SYNC_CACHE); if (-1 == n) { g_warning("DBSTORE could not flush cache for DBMW \"%s\": %m", dbmw_name(dw)); } else if (n && dbstore_debug > 1) { g_debug("DBSTORE flushed %u dirty value%s in DBMW \"%s\"", (unsigned) n, 1 == n ? "" : "s", dbmw_name(dw)); } }
/** * Synchronize a DBMW database, flushing its SDBM cache. */ void dbstore_sync(dbmw_t *dw) { ssize_t n; n = dbmw_sync(dw, DBMW_SYNC_MAP); if (-1 == n) { g_warning("DBSTORE could not synchronize DBMW \"%s\": %m", dbmw_name(dw)); } else if (n && dbstore_debug > 1) { g_debug("DBSTORE flushed %u SDBM page%s in DBMW \"%s\"", (unsigned) n, 1 == n ? "" : "s", dbmw_name(dw)); } }
/** * Opens or create a disk database with an SDBM back-end. * * If we can't access the SDBM files on disk, we'll transparently use * an in-core version. * * @param name the name of the storage created, for logs * @param dir the directory where SDBM files will be put * @param base the base name of SDBM files * @param flags the sdbm_open() flags * @param kv key/value description * @param packing key/value serialization description * @param cache_size Amount of items to cache (0 = no cache, 1 = default) * @param hash_func Key hash function * @param eq_func Key equality test function * @param incore If TRUE, allow fallback to a RAM-only database * * @return the DBMW wrapping object. */ dbmw_t * dbstore_open(const char *name, const char *dir, const char *base, dbstore_kv_t kv, dbstore_packing_t packing, size_t cache_size, hash_fn_t hash_func, eq_fn_t eq_func, bool incore) { dbmw_t *dw; dw = dbstore_create_internal(name, dir, base, O_CREAT | O_RDWR, kv, packing, cache_size, hash_func, eq_func, FALSE); if (dw != NULL && dbstore_debug > 0) { size_t count = dbmw_count(dw); g_debug("DBSTORE opened DBMW \"%s\" (%u key%s) from %s", dbmw_name(dw), (unsigned) count, 1 == count ? "" : "s", base); } /* * If they want RAM-only storage, create a new RAM DBMW and copy * the persisted one there. */ if (dw != NULL && incore) { dbmw_t *dram; size_t count = dbmw_count(dw); if (dbstore_debug > 0) { g_debug("DBSTORE loading DBMW \"%s\" (%u key%s) from %s", dbmw_name(dw), (unsigned) count, 1 == count ? "" : "s", base); } dram = dbstore_create_internal(name, NULL, NULL, 0, kv, packing, cache_size, hash_func, eq_func, TRUE); if (!dbmw_copy(dw, dram)) { g_warning("DBSTORE could not load DBMW \"%s\" (%u key%s) from %s", dbmw_name(dw), (unsigned) count, 1 == count ? "" : "s", base); } dbmw_destroy(dw, TRUE); dw = dram; } return dw; }
/** * Get keydata from database. */ static struct keydata * get_keydata(const kuid_t *id) { struct keydata *kd; kd = dbmw_read(db_keydata, id, NULL); if (kd == NULL) { if (dbmw_has_ioerr(db_keydata)) { s_warning_once_per(LOG_PERIOD_MINUTE, "DBMW \"%s\" I/O error, bad things could happen...", dbmw_name(db_keydata)); } else { s_warning_once_per(LOG_PERIOD_SECOND, "key %s exists but was not found in DBMW \"%s\"", kuid_to_hex_string(id), dbmw_name(db_keydata)); } return NULL; } return kd; }
/** * Get lifedata from database, returning NULL if not found. */ static struct lifedata * get_lifedata(const kuid_t *id) { struct lifedata *ld; ld = dbmw_read(db_lifedata, id, NULL); if (NULL == ld && dbmw_has_ioerr(db_lifedata)) { g_warning("DBMW \"%s\" I/O error, bad things could happen...", dbmw_name(db_lifedata)); } return ld; }
/** * Get pubdata from database. */ static struct pubdata * get_pubdata(const sha1_t *sha1) { struct pubdata *pd; pd = dbmw_read(db_pubdata, sha1, NULL); if (NULL == pd && dbmw_has_ioerr(db_pubdata)) { s_warning_once_per(LOG_PERIOD_MINUTE, "DBMW \"%s\" I/O error, bad things could happen...", dbmw_name(db_pubdata)); } return pd; }
/** * Get banned GUID data from database, returning NULL if not found. */ static struct guiddata * get_guiddata(const struct guid *guid) { struct guiddata *gd; gd = dbmw_read(db_guid, guid, NULL); if (NULL == gd) { if (dbmw_has_ioerr(db_guid)) { g_warning("DBMW \"%s\" I/O error", dbmw_name(db_guid)); } } return gd; }
/** * Get tokdata from database, returning NULL if not found. */ static struct tokdata * get_tokdata(const kuid_t *id) { struct tokdata *td; td = dbmw_read(db_tokdata, id, NULL); if (NULL == td) { if (dbmw_has_ioerr(db_tokdata)) { g_warning("DBMW \"%s\" I/O error, bad things could happen...", dbmw_name(db_tokdata)); } } return td; }
/** * Get banned GUID data from database, returning NULL if not found. */ static struct guiddata * get_guiddata(const guid_t *guid) { struct guiddata *gd; gd = dbmw_read(db_guid, guid, NULL); if (NULL == gd) { if (dbmw_has_ioerr(db_guid)) { s_warning_once_per(LOG_PERIOD_MINUTE, "DBMW \"%s\" I/O error", dbmw_name(db_guid)); } } return gd; }