/** * Iterate over the DB, invoking the callback on each item along with the * supplied argument and removing the item when the callback returns TRUE. */ void dbmw_foreach_remove(dbmw_t *dw, dbmw_cbr_t cbr, gpointer arg) { struct foreach_ctx ctx; struct cache_foreach_ctx fctx; dbmw_check(dw); /* * Before iterating we flush the deleted keys we know about in the cache * and whose deletion was deferred, so that the underlying map will * not have to iterate on them. */ dbmw_sync(dw, DBMW_SYNC_CACHE | DBMW_DELETED_ONLY); /* * Some values may be present only in the cache. Hence we clear all * marks in the cache and each traversed value that happens to be * present in the cache will be marked as "traversed". * * We flushed deleted keys above, but that does not remove them from * the cache structure. We don't need to traverse these after iterating * on the map, so we make sure they are artifically set to "traversed". */ ctx.u.cbr = cbr; ctx.arg = arg; ctx.dw = dw; map_foreach(dw->values, cache_reset_before_traversal, NULL); dbmap_foreach_remove(dw->dm, dbmw_foreach_remove_trampoline, &ctx); fctx.removing = TRUE; fctx.foreach = &ctx; fctx.u.cbr = dbmw_foreach_remove_trampoline; /* * Continue traversal with all the cached entries that were not traversed * already because they do not exist in the underlying map. * * Any cached entry that needs to be removed will be marked as such * and we'll complete processing by discarding from the cache all * the entries that have been marked as "removable" during the traversal. */ map_foreach(dw->values, cache_finish_traversal, &fctx); map_foreach_remove(dw->values, cache_free_removable, dw); }
/** * Iterate over the DB, invoking the callback on each item along with the * supplied argument and removing the item when the callback returns TRUE. * * @return the amount of removed entries. */ size_t dbmw_foreach_remove(dbmw_t *dw, dbmw_cbr_t cbr, void *arg) { struct foreach_ctx ctx; struct cache_foreach_ctx fctx; size_t pruned; dbmw_check(dw); if (dbg_ds_debugging(dw->dbg, 1, DBG_DSF_ITERATOR)) { dbg_ds_log(dw->dbg, dw, "%s: starting with %s(%p)", G_STRFUNC, stacktrace_function_name(cbr), arg); } /* * Before iterating we flush the deleted keys we know about in the cache * and whose deletion was deferred, so that the underlying map will * not have to iterate on them. */ dbmw_sync(dw, DBMW_SYNC_CACHE | DBMW_DELETED_ONLY); /* * Some values may be present only in the cache. Hence we clear all * marks in the cache and each traversed value that happens to be * present in the cache will be marked as "traversed". * * We flushed deleted keys above, but that does not remove them from * the cache structure. We don't need to traverse these after iterating * on the map, so we make sure they are artifically set to "traversed". */ ctx.u.cbr = cbr; ctx.arg = arg; ctx.dw = dw; map_foreach(dw->values, cache_reset_before_traversal, NULL); pruned = dbmap_foreach_remove(dw->dm, dbmw_foreach_remove_trampoline, &ctx); ZERO(&fctx); fctx.removing = TRUE; fctx.foreach = &ctx; fctx.u.cbr = dbmw_foreach_remove_trampoline; /* * Continue traversal with all the cached entries that were not traversed * already because they do not exist in the underlying map. * * We count these and remember how many there are so that we can determine * the correct overall item count after an iteration without having to * flush all the dirty values! * * Any cached entry that needs to be removed will be marked as such * and we'll complete processing by discarding from the cache all * the entries that have been marked as "removable" during the traversal. */ map_foreach(dw->values, cache_finish_traversal, &fctx); map_foreach_remove(dw->values, cache_free_removable, dw); dw->cached = fctx.cached; dw->count_needs_sync = FALSE; /* We just counted items the slow way! */ if (dbg_ds_debugging(dw->dbg, 1, DBG_DSF_ITERATOR)) { dbg_ds_log(dw->dbg, dw, "%s: done with %s(%p): " "pruned %zu from dbmap, %zu from cache (%zu total), " "has %zu unflushed entr%s in cache", G_STRFUNC, stacktrace_function_name(cbr), arg, pruned, fctx.removed, pruned + fctx.removed, dw->cached, plural_y(dw->cached)); } return pruned + fctx.removed; }