logstor: truncate table

implement freeing all segments of a table for table truncate.

first do barrier to flush all active and mixed segments and put all the
table's data in compaction groups, then stop compaction for the table,
then free the table's segments and remove the live entries from the
index.
This commit is contained in:
Michael Litvak
2026-02-21 13:42:25 +01:00
parent 489efca47c
commit bd66edee5c
9 changed files with 150 additions and 0 deletions

View File

@@ -330,3 +330,53 @@ async def test_compaction(manager: ManagerClient):
metrics = await manager.metrics.query(servers[0].ip_addr)
segments_compacted = metrics.get("scylla_logstor_sm_segments_compacted") or 0
assert segments_compacted == 4, f"Expected 4 segments to be compacted, but got {segments_compacted}"
@pytest.mark.asyncio
async def test_drop_table(manager: ManagerClient):
"""
Test log compaction by creating dead data and verifying space reclamation.
"""
cmdline = ['--logger-log-level', 'logstor=trace']
cfg = {'enable_logstor': True, 'experimental_features': ['logstor']}
servers = await manager.servers_add(1, cmdline=cmdline, config=cfg)
cql = manager.get_cql()
async with new_test_keyspace(manager, "WITH tablets={'initial': 4}") as ks:
await cql.run_async(f"CREATE TABLE {ks}.test1 (pk int PRIMARY KEY, v text) WITH storage_engine = 'logstor'")
# create another table that will not be dropped to verify it's not affected
await cql.run_async(f"CREATE TABLE {ks}.test2 (pk int PRIMARY KEY, v text) WITH storage_engine = 'logstor'")
# write data to fill few segments
value_size = 30 * 1024
value = 'x' * value_size
for i in range(20):
await cql.run_async(f"INSERT INTO {ks}.test1 (pk, v) VALUES ({i}, '{value}')")
await cql.run_async(f"INSERT INTO {ks}.test2 (pk, v) VALUES ({i}, '{value}')")
await cql.run_async(f"DROP TABLE {ks}.test1")
# verify test2 is not affected
for i in range(20):
rows = await cql.run_async(f"SELECT pk, v FROM {ks}.test2 WHERE pk = {i}")
assert len(rows) == 1, f"Expected 1 row for key {i} in test2, but got {len(rows)}"
assert rows[0].v == value, f"Expected value of size {value_size} for key {i} in test2, but got {len(rows[0].v)}"
# recreate the table and verify that old data is not visible
await cql.run_async(f"CREATE TABLE {ks}.test1 (pk int PRIMARY KEY, v text) WITH storage_engine = 'logstor'")
for i in range(20):
rows = await cql.run_async(f"SELECT pk, v FROM {ks}.test1 WHERE pk = {i}")
assert len(rows) == 0, f"Expected no rows for key {i} after table drop, but got {len(rows)}"
# write new data to the recreated table and verify
await cql.run_async(f"INSERT INTO {ks}.test1 (pk, v) VALUES (1, 'new_value')")
rows = await cql.run_async(f"SELECT pk, v FROM {ks}.test1 WHERE pk = 1")
assert len(rows) == 1, f"Expected 1 row for key 1 after new insert, but got {len(rows)}"
assert rows[0].v == 'new_value', f"Expected value 'new_value' for key 1 after new insert, but got {rows[0].v}"
# verify test2 again
for i in range(20):
rows = await cql.run_async(f"SELECT pk, v FROM {ks}.test2 WHERE pk = {i}")
assert len(rows) == 1, f"Expected 1 row for key {i} in test2 after all operations, but got {len(rows)}"
assert rows[0].v == value, f"Expected value of size {value_size} for key {i} in test2 after all operations, but got {len(rows[0].v)}"