11import os
22import unittest
33from .helpers .ptrack_helpers import ProbackupTest , idx_ptrack
4+ import time
45
56
67module_name = 'ptrack_vacuum_full'
@@ -12,10 +13,15 @@ class SimpleTest(ProbackupTest, unittest.TestCase):
1213 # @unittest.expectedFailure
1314 def test_ptrack_vacuum_full (self ):
1415 fname = self .id ().split ('.' )[3 ]
15- node = self .make_simple_node (base_dir = "{0}/{1}/node" .format (module_name , fname ),
16+ node = self .make_simple_node (
17+ base_dir = "{0}/{1}/node" .format (module_name , fname ),
1618 set_replication = True ,
1719 initdb_params = ['--data-checksums' ],
18- pg_options = {'ptrack_enable' : 'on' , 'wal_level' : 'replica' , 'max_wal_senders' : '2' })
20+ pg_options = {
21+ 'ptrack_enable' : 'on' ,
22+ 'wal_level' : 'replica' ,
23+ 'max_wal_senders' : '2' })
24+
1925 backup_dir = os .path .join (self .tmp_path , module_name , fname , 'backup' )
2026 self .init_pb (backup_dir )
2127 self .add_instance (backup_dir , 'node' , node )
@@ -26,11 +32,17 @@ def test_ptrack_vacuum_full(self):
2632 # Create table and indexes
2733 res = node .safe_psql (
2834 "postgres" ,
29- "create sequence t_seq; create table t_heap tablespace somedata as select i as id, md5(i::text) as text, md5(repeat(i::text,10))::tsvector as tsvector from generate_series(0,127) i" )
35+ "create sequence t_seq; create table t_heap tablespace somedata "
36+ "as select i as id, md5(i::text) as text, "
37+ "md5(repeat(i::text,10))::tsvector as tsvector "
38+ "from generate_series(0,127) i" )
3039 for i in idx_ptrack :
3140 if idx_ptrack [i ]['type' ] != 'heap' and idx_ptrack [i ]['type' ] != 'seq' :
32- node .safe_psql ("postgres" , "create index {0} on {1} using {2}({3}) tablespace somedata" .format (
33- i , idx_ptrack [i ]['relation' ], idx_ptrack [i ]['type' ], idx_ptrack [i ]['column' ]))
41+ node .safe_psql (
42+ "postgres" , "create index {0} on {1} "
43+ "using {2}({3}) tablespace somedata" .format (
44+ i , idx_ptrack [i ]['relation' ],
45+ idx_ptrack [i ]['type' ], idx_ptrack [i ]['column' ]))
3446
3547 node .safe_psql ('postgres' , 'vacuum t_heap' )
3648 node .safe_psql ('postgres' , 'checkpoint' )
@@ -44,7 +56,8 @@ def test_ptrack_vacuum_full(self):
4456 idx_ptrack [i ]['old_pages' ] = self .get_md5_per_page_for_fork (
4557 idx_ptrack [i ]['path' ], idx_ptrack [i ]['old_size' ])
4658
47- self .backup_node (backup_dir , 'node' , node , options = ['-j10' , '--stream' ])
59+ self .backup_node (
60+ backup_dir , 'node' , node , options = ['-j10' , '--stream' ])
4861
4962 node .safe_psql ('postgres' , 'delete from t_heap where id%2 = 1' )
5063 node .safe_psql ('postgres' , 'vacuum full t_heap' )
@@ -60,7 +73,8 @@ def test_ptrack_vacuum_full(self):
6073 idx_ptrack [i ]['path' ], idx_ptrack [i ]['new_size' ])
6174 # get ptrack for every idx
6275 idx_ptrack [i ]['ptrack' ] = self .get_ptrack_bits_per_page_for_fork (
63- node , idx_ptrack [i ]['path' ], [idx_ptrack [i ]['old_size' ], idx_ptrack [i ]['new_size' ]])
76+ node , idx_ptrack [i ]['path' ],
77+ [idx_ptrack [i ]['old_size' ], idx_ptrack [i ]['new_size' ]])
6478
6579 # compare pages and check ptrack sanity, the most important part
6680 self .check_ptrack_sanity (idx_ptrack [i ])
@@ -72,17 +86,23 @@ def test_ptrack_vacuum_full(self):
7286 # @unittest.expectedFailure
7387 def test_ptrack_vacuum_full_replica (self ):
7488 fname = self .id ().split ('.' )[3 ]
75- master = self .make_simple_node (base_dir = "{0}/{1}/master" .format (module_name , fname ),
89+ master = self .make_simple_node (
90+ base_dir = "{0}/{1}/master" .format (module_name , fname ),
7691 set_replication = True ,
7792 initdb_params = ['--data-checksums' ],
78- pg_options = {'ptrack_enable' : 'on' , 'wal_level' : 'replica' , 'max_wal_senders' : '2' })
93+ pg_options = {
94+ 'ptrack_enable' : 'on' , 'wal_level' : 'replica' ,
95+ 'max_wal_senders' : '2' , 'autovacuum' : 'off' ,
96+ 'checkpoint_timeout' : '30s' }
97+ )
7998 backup_dir = os .path .join (self .tmp_path , module_name , fname , 'backup' )
8099 self .init_pb (backup_dir )
81100 self .add_instance (backup_dir , 'master' , master )
82101 master .start ()
83102
84103 self .backup_node (backup_dir , 'master' , master , options = ['--stream' ])
85- replica = self .make_simple_node (base_dir = "{0}/{1}/replica" .format (module_name , fname ))
104+ replica = self .make_simple_node (
105+ base_dir = "{0}/{1}/replica" .format (module_name , fname ))
86106 replica .cleanup ()
87107
88108 self .restore_node (backup_dir , 'master' , replica )
@@ -95,15 +115,32 @@ def test_ptrack_vacuum_full_replica(self):
95115 # Create table and indexes
96116 master .safe_psql (
97117 "postgres" ,
98- "create sequence t_seq; create table t_heap as select i as id, md5(i::text) as text, md5(repeat(i::text,10))::tsvector as tsvector from generate_series(0,127) i" )
118+ "create sequence t_seq; create table t_heap as select i as id, "
119+ "md5(i::text) as text, md5(repeat(i::text,10))::tsvector as "
120+ "tsvector from generate_series(0,127) i" )
99121 for i in idx_ptrack :
100122 if idx_ptrack [i ]['type' ] != 'heap' and idx_ptrack [i ]['type' ] != 'seq' :
101- master .safe_psql ("postgres" , "create index {0} on {1} using {2}({3})" .format (
102- i , idx_ptrack [i ]['relation' ], idx_ptrack [i ]['type' ], idx_ptrack [i ]['column' ]))
123+ master .safe_psql (
124+ "postgres" ,
125+ "create index {0} on {1} using {2}({3})" .format (
126+ i , idx_ptrack [i ]['relation' ],
127+ idx_ptrack [i ]['type' ],
128+ idx_ptrack [i ]['column' ]))
103129
104130 master .safe_psql ('postgres' , 'vacuum t_heap' )
105131 master .safe_psql ('postgres' , 'checkpoint' )
106132
133+ # Sync master and replica
134+ lsn = master .safe_psql (
135+ 'postgres' , 'SELECT pg_catalog.pg_current_wal_lsn()' ).rstrip ()
136+ # print(lsn)
137+
138+ replica .poll_query_until (
139+ "postgres" ,
140+ "SELECT '{0}'::pg_lsn <= pg_last_wal_replay_lsn()" .format (
141+ lsn ))
142+ replica .safe_psql ('postgres' , 'checkpoint' )
143+
107144 for i in idx_ptrack :
108145 # get size of heap and indexes. size calculated in pages
109146 idx_ptrack [i ]['old_size' ] = self .get_fork_size (replica , i )
@@ -114,12 +151,34 @@ def test_ptrack_vacuum_full_replica(self):
114151 idx_ptrack [i ]['path' ], idx_ptrack [i ]['old_size' ])
115152
116153 # Take FULL backup to clean every ptrack
117- self .backup_node (backup_dir , 'replica' , replica , options = ['-j10' ,
118- '--master-host=localhost' , '--master-db=postgres' , '--master-port={0}' .format (master .port )])
154+ self .backup_node (
155+ backup_dir , 'replica' , replica ,
156+ options = [
157+ '-j10' ,
158+ '--master-host=localhost' ,
159+ '--master-db=postgres' ,
160+ '--master-port={0}' .format (master .port )
161+ ]
162+ )
163+ # TODO: check that all ptrack are nullified
119164
120165 master .safe_psql ('postgres' , 'delete from t_heap where id%2 = 1' )
121166 master .safe_psql ('postgres' , 'vacuum full t_heap' )
122- master .safe_psql ('postgres' , 'checkpoint' )
167+
168+ # Sync master and replica
169+ lsn = master .safe_psql (
170+ 'postgres' , 'SELECT pg_catalog.pg_current_wal_lsn()' ).rstrip ()
171+ # print(lsn)
172+
173+ replica .poll_query_until (
174+ "postgres" ,
175+ "SELECT '{0}'::pg_lsn <= pg_last_wal_replay_lsn()" .format (
176+ lsn ))
177+
178+ replica .safe_psql ('postgres' , 'checkpoint' )
179+
180+ # print(replica.safe_psql(
181+ # 'postgres', 'SELECT pg_catalog.pg_last_wal_replay_lsn()'))
123182
124183 for i in idx_ptrack :
125184 # get new size of heap and indexes. size calculated in pages
@@ -131,7 +190,8 @@ def test_ptrack_vacuum_full_replica(self):
131190 idx_ptrack [i ]['path' ], idx_ptrack [i ]['new_size' ])
132191 # get ptrack for every idx
133192 idx_ptrack [i ]['ptrack' ] = self .get_ptrack_bits_per_page_for_fork (
134- replica , idx_ptrack [i ]['path' ], [idx_ptrack [i ]['old_size' ], idx_ptrack [i ]['new_size' ]])
193+ replica , idx_ptrack [i ]['path' ],
194+ [idx_ptrack [i ]['old_size' ], idx_ptrack [i ]['new_size' ]])
135195
136196 # compare pages and check ptrack sanity, the most important part
137197 self .check_ptrack_sanity (idx_ptrack [i ])
0 commit comments