From 2245ef06a82f8eb0aee092af177ab90195a52658 Mon Sep 17 00:00:00 2001
From: Andrey Saranchin <Andrey22102001@gmail.com>
Date: Tue, 15 Mar 2022 15:01:01 +0300
Subject: [PATCH] txm: relax conditions for memtx_story delete

Since a transaction has been prepared its garbage (produced stories
and replaced tuples) cannot be deleted because they are recognized
as used in read-view even if there are no transactions in read-view.
This problem makes it difficult to test the memory monitoring system,
so this patch solves the problem.

Close #6635
Part of #6150

NO_DOC=no visible changes
NO_CHANGELOG=no visible changes
---
 src/box/memtx_tx.c                            |  9 +++-
 .../gh_6635_garbage_of_last_prep_txn_test.lua | 41 +++++++++++++++++++
 2 files changed, 48 insertions(+), 2 deletions(-)
 create mode 100644 test/box-luatest/gh_6635_garbage_of_last_prep_txn_test.lua

diff --git a/src/box/memtx_tx.c b/src/box/memtx_tx.c
index 42d8917660..dd7a9b6d24 100644
--- a/src/box/memtx_tx.c
+++ b/src/box/memtx_tx.c
@@ -924,8 +924,13 @@ memtx_tx_story_gc_step()
 		return;
 	}
 
-	/* Lowest read view PSN */
-	int64_t lowest_rv_psn = txn_last_psn;
+	/*
+	 * Lowest read view PSN.
+	 * Default value is more than txn_last_psn because if it is not so some
+	 * stories (stories produced by last txn at least) will be marked as
+	 * potentially in read view even though there are no txns in read view.
+	 */
+	int64_t lowest_rv_psn = txn_last_psn + 1;
 	if (!rlist_empty(&txm.read_view_txs)) {
 		struct txn *txn =
 			rlist_first_entry(&txm.read_view_txs, struct txn,
diff --git a/test/box-luatest/gh_6635_garbage_of_last_prep_txn_test.lua b/test/box-luatest/gh_6635_garbage_of_last_prep_txn_test.lua
new file mode 100644
index 0000000000..e0e225069d
--- /dev/null
+++ b/test/box-luatest/gh_6635_garbage_of_last_prep_txn_test.lua
@@ -0,0 +1,41 @@
+local server = require('test.luatest_helpers.server')
+local t = require('luatest')
+
+local g = t.group()
+
+g.before_all = function()
+    g.server = server:new{
+        alias   = 'default',
+        box_cfg = {memtx_use_mvcc_engine = true}
+    }
+    g.server:start()
+end
+
+g.after_all = function()
+    g.server:drop()
+end
+
+g.test_garbage_of_last_prepared_txn_cannot_be_deleted = function()
+    g.server:exec(function()
+        local t = require('luatest')
+
+        local s = box.schema.create_space('test')
+        s:create_index('pk')
+
+        -- Collect garbage before replacing tuples
+        box.internal.memtx_tx_gc(10)
+        collectgarbage('collect')
+
+        s:replace{0, string.rep('a', 1100)}
+        box.internal.memtx_tx_gc(10)
+        collectgarbage('collect')
+        local items_used_with_huge_tuple = box.slab.info()['items_used']
+
+        s:replace{0, 1}
+        box.internal.memtx_tx_gc(10)
+        collectgarbage('collect')
+        local items_used_without_huge_tuple = box.slab.info()['items_used']
+        t.assert_lt(items_used_without_huge_tuple, items_used_with_huge_tuple)
+        t.assert_ge(items_used_with_huge_tuple - items_used_without_huge_tuple, 1000)
+    end)
+end
-- 
GitLab