refactor(test): unify how we clear shared buffers (#8634)

so that we can easily plug in LFC clearing as well.

Private discussion reference:
<https://neondb.slack.com/archives/C033A2WE6BZ/p1722942856987979>
This commit is contained in:
Joonas Koivunen
2024-08-13 20:14:42 +03:00
committed by GitHub
parent 8f170c5105
commit ae6e27274c
8 changed files with 21 additions and 15 deletions

View File

@@ -4100,6 +4100,17 @@ class Endpoint(PgProtocol, LogUtils):
assert self.pgdata_dir is not None # please mypy
return get_dir_size(os.path.join(self.pgdata_dir, "pg_wal")) / 1024 / 1024
def clear_shared_buffers(self, cursor: Optional[Any] = None):
"""
Best-effort way to clear postgres buffers. Pinned buffers will not be 'cleared.'
Might also clear LFC.
"""
if cursor is not None:
cursor.execute("select clear_buffer_cache()")
else:
self.safe_psql("select clear_buffer_cache()")
class EndpointFactory:
"""An object representing multiple compute endpoints."""

View File

@@ -182,14 +182,8 @@ class Workload:
def validate(self, pageserver_id: Optional[int] = None):
endpoint = self.endpoint(pageserver_id)
result = endpoint.safe_psql_many(
[
"select clear_buffer_cache()",
f"""
SELECT COUNT(*) FROM {self.table}
""",
]
)
endpoint.clear_shared_buffers()
result = endpoint.safe_psql(f"SELECT COUNT(*) FROM {self.table}")
log.info(f"validate({self.expect_rows}): {result}")
assert result == [[("",)], [(self.expect_rows,)]]
assert result == [(self.expect_rows,)]

View File

@@ -168,7 +168,7 @@ def test_hot_standby_gc(neon_env_builder: NeonEnvBuilder, pause_apply: bool):
# re-execute the query, it will make GetPage
# requests. This does not clear the last-written LSN cache
# so we still remember the LSNs of the pages.
s_cur.execute("SELECT clear_buffer_cache()")
secondary.clear_shared_buffers(cursor=s_cur)
if pause_apply:
s_cur.execute("SELECT pg_wal_replay_pause()")
@@ -332,6 +332,7 @@ def test_replica_query_race(neon_simple_env: NeonEnv):
log.info(f"read {reads}: counter {readcounter}, last update {writecounter}")
reads += 1
# FIXME: what about LFC clearing?
await conn.execute("SELECT clear_buffer_cache()")
async def both():

View File

@@ -37,7 +37,7 @@ def test_oid_overflow(neon_env_builder: NeonEnvBuilder):
oid = cur.fetchall()[0][0]
log.info(f"t2.relfilenode={oid}")
cur.execute("SELECT clear_buffer_cache()")
endpoint.clear_shared_buffers(cursor=cur)
cur.execute("SELECT x from t1")
assert cur.fetchone() == (1,)

View File

@@ -61,7 +61,7 @@ def test_read_validation(neon_simple_env: NeonEnv):
log.info("Clear buffer cache to ensure no stale pages are brought into the cache")
c.execute("select clear_buffer_cache()")
endpoint.clear_shared_buffers(cursor=c)
cache_entries = query_scalar(
c, f"select count(*) from pg_buffercache where relfilenode = {relfilenode}"

View File

@@ -411,7 +411,7 @@ def test_detached_receives_flushes_while_being_detached(neon_env_builder: NeonEn
assert client.timeline_detail(env.initial_tenant, timeline_id)["ancestor_timeline_id"] is None
assert ep.safe_psql("SELECT clear_buffer_cache();")
ep.clear_shared_buffers()
assert ep.safe_psql("SELECT count(*) FROM foo;")[0][0] == rows
assert ep.safe_psql("SELECT SUM(LENGTH(aux)) FROM foo")[0][0] != 0
ep.stop()

View File

@@ -62,7 +62,7 @@ def test_vm_bit_clear(neon_simple_env: NeonEnv):
# Clear the buffer cache, to force the VM page to be re-fetched from
# the page server
cur.execute("SELECT clear_buffer_cache()")
endpoint.clear_shared_buffers(cursor=cur)
# Check that an index-only scan doesn't see the deleted row. If the
# clearing of the VM bit was not replayed correctly, this would incorrectly

View File

@@ -2159,7 +2159,7 @@ def test_broker_discovery(neon_env_builder: NeonEnvBuilder):
# generate some data to commit WAL on safekeepers
endpoint.safe_psql("insert into t select generate_series(1,100), 'action'")
# clear the buffers
endpoint.safe_psql("select clear_buffer_cache()")
endpoint.clear_shared_buffers()
# read data to fetch pages from pageserver
endpoint.safe_psql("select sum(i) from t")