From 2ac1a6105da3c60d304a55bb85a1d96c2a943a4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C4=81ris=20Narti=C5=A1s?= Date: Thu, 12 Oct 2023 10:10:44 +0300 Subject: [PATCH] LMDB: minimize transaction duration (#323) * LMDB: minimize transaction duration Readers do not block anything but tie-up resources; Writers block other writers and thus it's good idea to keep them short. * LMDB: do not pass data variable when deleting tiles As MapCache LMDB uses single entry per key, there is no need to pass data to mdb_del call. --- lib/cache_lmdb.c | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/lib/cache_lmdb.c b/lib/cache_lmdb.c index 181c2b26..7b8f514a 100644 --- a/lib/cache_lmdb.c +++ b/lib/cache_lmdb.c @@ -69,23 +69,24 @@ static int _mapcache_cache_lmdb_has_tile(mapcache_context *ctx, mapcache_cache * MDB_val key, data; MDB_txn *txn; mapcache_cache_lmdb *cache = (mapcache_cache_lmdb*)pcache; - char *skey = mapcache_util_get_tile_key(ctx,tile,cache->key_template,NULL,NULL); + char *skey; if (lmdb_env->is_open == 0) { ctx->set_error(ctx,500,"lmdb is not open %s",cache->basedir); return MAPCACHE_FALSE; } + + skey = mapcache_util_get_tile_key(ctx,tile,cache->key_template,NULL,NULL); + key.mv_size = strlen(skey)+1; + key.mv_data = skey; + rc = mdb_txn_begin(lmdb_env->env, NULL, MDB_RDONLY, &txn); if (rc) { ctx->set_error(ctx,500,"lmdb failed to begin transaction for has_tile in %s:%s",cache->basedir,mdb_strerror(rc)); return MAPCACHE_FALSE; } - key.mv_size = strlen(skey)+1; - key.mv_data = skey; - rc = mdb_get(txn, lmdb_env->dbi, &key, &data); - if(rc == 0) { ret = MAPCACHE_TRUE; } else if(rc == MDB_NOTFOUND) { @@ -107,24 +108,27 @@ static int _mapcache_cache_lmdb_has_tile(mapcache_context *ctx, mapcache_cache * static void _mapcache_cache_lmdb_delete(mapcache_context *ctx, mapcache_cache *pcache, mapcache_tile *tile) { int rc; - MDB_val key, data; + MDB_val key; MDB_txn *txn; mapcache_cache_lmdb *cache = (mapcache_cache_lmdb*)pcache; - char *skey = mapcache_util_get_tile_key(ctx,tile,cache->key_template,NULL,NULL); + char *skey; if (lmdb_env->is_open == 0) { ctx->set_error(ctx,500,"lmdb is not open %s",cache->basedir); return; } + + skey = mapcache_util_get_tile_key(ctx,tile,cache->key_template,NULL,NULL); + key.mv_size = strlen(skey)+1; + key.mv_data = skey; + rc = mdb_txn_begin(lmdb_env->env, NULL, 0, &txn); if (rc) { ctx->set_error(ctx,500,"lmdb failed to begin transaction for delete in %s:%s",cache->basedir,mdb_strerror(rc)); return; } - key.mv_size = strlen(skey)+1; - key.mv_data = skey; - rc = mdb_del(txn, lmdb_env->dbi, &key, &data); + rc = mdb_del(txn, lmdb_env->dbi, &key, NULL); if (rc) { if (rc == MDB_NOTFOUND) { ctx->log(ctx,MAPCACHE_DEBUG,"attempt to delete tile %s absent in the db %s",skey,cache->basedir); @@ -152,18 +156,18 @@ static int _mapcache_cache_lmdb_get(mapcache_context *ctx, mapcache_cache *pcach ctx->set_error(ctx,500,"lmdb is not open %s",cache->basedir); return MAPCACHE_FALSE; } + + skey = mapcache_util_get_tile_key(ctx,tile,cache->key_template,NULL,NULL); + key.mv_size = strlen(skey)+1; + key.mv_data = skey; + rc = mdb_txn_begin(lmdb_env->env, NULL, MDB_RDONLY, &txn); if (rc) { ctx->set_error(ctx,500,"lmdb failed to begin transaction for get in %s:%s",cache->basedir,mdb_strerror(rc)); return MAPCACHE_FALSE; } - skey = mapcache_util_get_tile_key(ctx,tile,cache->key_template,NULL,NULL); - key.mv_size = strlen(skey)+1; - key.mv_data = skey; - rc = mdb_get(txn, lmdb_env->dbi, &key, &data); - if(rc == 0) { if(((char*)(data.mv_data))[0] == '#') { tile->encoded_data = mapcache_empty_png_decode(ctx,tile->grid_link->grid->tile_sx, tile->grid_link->grid->tile_sy, (unsigned char*)data.mv_data,&tile->nodata); @@ -232,6 +236,7 @@ static void _mapcache_cache_lmdb_set(mapcache_context *ctx, mapcache_cache *pcac ctx->set_error(ctx,500,"lmdb is not open %s",cache->basedir); return; } + rc = mdb_txn_begin(lmdb_env->env, NULL, 0, &txn); if (rc) { ctx->set_error(ctx,500,"lmdb failed to begin transaction for set in %s:%s",cache->basedir,mdb_strerror(rc)); @@ -264,6 +269,7 @@ static void _mapcache_cache_lmdb_multiset(mapcache_context *ctx, mapcache_cache ctx->set_error(ctx,500,"lmdb is not open %s",cache->basedir); return; } + rc = mdb_txn_begin(lmdb_env->env, NULL, 0, &txn); if (rc) { ctx->set_error(ctx,500,"lmdb failed to begin transaction for multiset in %s:%s",cache->basedir,mdb_strerror(rc));