@@ -1723,7 +1723,8 @@ def pgdata_content(self, pgdata, ignore_ptrack=True, exclude_dirs=None):
1723
1723
1724
1724
file_fullpath = os .path .join (root , file )
1725
1725
file_relpath = os .path .relpath (file_fullpath , pgdata )
1726
- directory_dict ['files' ][file_relpath ] = {'is_datafile' : False }
1726
+ cfile = ContentFile (file .isdigit ())
1727
+ directory_dict ['files' ][file_relpath ] = cfile
1727
1728
with open (file_fullpath , 'rb' ) as f :
1728
1729
# truncate cfm's content's zero tail
1729
1730
if file_relpath .endswith ('.cfm' ):
@@ -1743,49 +1744,31 @@ def pgdata_content(self, pgdata, ignore_ptrack=True, exclude_dirs=None):
1743
1744
b = f .read (64 * 1024 )
1744
1745
if not b : break
1745
1746
digest .update (b )
1746
- directory_dict [ 'files' ][ file_relpath ][ ' md5' ] = digest .hexdigest ()
1747
+ cfile . md5 = digest .hexdigest ()
1747
1748
1748
1749
# crappy algorithm
1749
- if file .isdigit ():
1750
- directory_dict ['files' ][file_relpath ]['is_datafile' ] = True
1750
+ if cfile .is_datafile :
1751
1751
size_in_pages = os .path .getsize (file_fullpath )/ 8192
1752
- directory_dict ['files' ][file_relpath ][
1753
- 'md5_per_page' ] = self .get_md5_per_page_for_fork (
1752
+ cfile .md5_per_page = self .get_md5_per_page_for_fork (
1754
1753
file_fullpath , size_in_pages
1755
1754
)
1756
1755
1757
- for root , dirs , files in os .walk (pgdata , topdown = False , followlinks = True ):
1758
- for directory in sorted (dirs ):
1756
+ for directory in dirs :
1759
1757
directory_path = os .path .join (root , directory )
1760
1758
directory_relpath = os .path .relpath (directory_path , pgdata )
1761
-
1762
- found = False
1763
- for d in dirs_to_ignore :
1764
- if d in directory_relpath :
1765
- found = True
1766
- break
1767
-
1768
- # check if directory already here as part of larger directory
1769
- if not found :
1770
- for d in directory_dict ['dirs' ]:
1771
- # print("OLD dir {0}".format(d))
1772
- if directory_relpath in d :
1773
- found = True
1774
- break
1775
-
1776
- if not found :
1777
- directory_dict ['dirs' ][directory_relpath ] = {}
1759
+ parent = os .path .dirname (directory_relpath )
1760
+ if parent in directory_dict ['dirs' ]:
1761
+ del directory_dict ['dirs' ][parent ]
1762
+ directory_dict ['dirs' ][directory_relpath ] = ContentDir ()
1778
1763
1779
1764
# get permissions for every file and directory
1780
- for file in directory_dict ['dirs' ]:
1765
+ for file , cfile in directory_dict ['dirs' ]. items () :
1781
1766
full_path = os .path .join (pgdata , file )
1782
- directory_dict ['dirs' ][file ]['mode' ] = os .stat (
1783
- full_path ).st_mode
1767
+ cfile .mode = os .stat (full_path ).st_mode
1784
1768
1785
- for file in directory_dict ['files' ]:
1769
+ for file , cdir in directory_dict ['files' ]. items () :
1786
1770
full_path = os .path .join (pgdata , file )
1787
- directory_dict ['files' ][file ]['mode' ] = os .stat (
1788
- full_path ).st_mode
1771
+ cdir .mode = os .stat (full_path ).st_mode
1789
1772
1790
1773
return directory_dict
1791
1774
@@ -1817,123 +1800,117 @@ def compare_pgdata(self, original_pgdata, restored_pgdata, exclusion_dict = dict
1817
1800
error_message = 'Restored PGDATA is not equal to original!\n '
1818
1801
1819
1802
# Compare directories
1820
- for directory in restored_pgdata ['dirs' ]:
1821
- if directory not in original_pgdata ['dirs' ]:
1822
- fail = True
1823
- error_message += '\n Directory was not present'
1824
- error_message += ' in original PGDATA: {0}\n ' .format (
1825
- os .path .join (restored_pgdata ['pgdata' ], directory ))
1826
- else :
1827
- if (
1828
- restored_pgdata ['dirs' ][directory ]['mode' ] !=
1829
- original_pgdata ['dirs' ][directory ]['mode' ]
1830
- ):
1831
- fail = True
1832
- error_message += '\n Dir permissions mismatch:\n '
1833
- error_message += ' Dir old: {0} Permissions: {1}\n ' .format (
1834
- os .path .join (original_pgdata ['pgdata' ], directory ),
1835
- original_pgdata ['dirs' ][directory ]['mode' ])
1836
- error_message += ' Dir new: {0} Permissions: {1}\n ' .format (
1837
- os .path .join (restored_pgdata ['pgdata' ], directory ),
1838
- restored_pgdata ['dirs' ][directory ]['mode' ])
1839
-
1840
- for directory in original_pgdata ['dirs' ]:
1841
- if directory not in restored_pgdata ['dirs' ]:
1803
+ restored_dirs = set (restored_pgdata ['dirs' ])
1804
+ original_dirs = set (restored_pgdata ['dirs' ])
1805
+
1806
+ for directory in sorted (restored_dirs - original_dirs ):
1807
+ fail = True
1808
+ error_message += '\n Directory was not present'
1809
+ error_message += ' in original PGDATA: {0}\n ' .format (
1810
+ os .path .join (restored_pgdata ['pgdata' ], directory ))
1811
+
1812
+ for directory in sorted (original_dirs - restored_dirs ):
1813
+ fail = True
1814
+ error_message += '\n Directory dissappeared'
1815
+ error_message += ' in restored PGDATA: {0}\n ' .format (
1816
+ os .path .join (restored_pgdata ['pgdata' ], directory ))
1817
+
1818
+ for directory in sorted (original_dirs & restored_dirs ):
1819
+ original = original_pgdata ['dirs' ][directory ]
1820
+ restored = restored_pgdata ['dirs' ][directory ]
1821
+ if original .mode != restored .mode :
1842
1822
fail = True
1843
- error_message += '\n Directory dissappeared'
1844
- error_message += ' in restored PGDATA: {0}\n ' .format (
1845
- os .path .join (restored_pgdata ['pgdata' ], directory ))
1846
-
1847
- for file in restored_pgdata ['files' ]:
1823
+ error_message += '\n Dir permissions mismatch:\n '
1824
+ error_message += ' Dir old: {0} Permissions: {1}\n ' .format (
1825
+ os .path .join (original_pgdata ['pgdata' ], directory ),
1826
+ original .mode )
1827
+ error_message += ' Dir new: {0} Permissions: {1}\n ' .format (
1828
+ os .path .join (restored_pgdata ['pgdata' ], directory ),
1829
+ restored .mode )
1830
+
1831
+ restored_files = set (restored_pgdata ['files' ])
1832
+ original_files = set (restored_pgdata ['files' ])
1833
+
1834
+ for file in sorted (restored_files - original_files ):
1848
1835
# File is present in RESTORED PGDATA
1849
1836
# but not present in ORIGINAL
1850
1837
# only backup_label is allowed
1851
- if file not in original_pgdata ['files' ]:
1852
- fail = True
1853
- error_message += '\n File is not present'
1854
- error_message += ' in original PGDATA: {0}\n ' .format (
1855
- os .path .join (restored_pgdata ['pgdata' ], file ))
1856
-
1857
- for file in original_pgdata ['files' ]:
1858
- if file in restored_pgdata ['files' ]:
1838
+ fail = True
1839
+ error_message += '\n File is not present'
1840
+ error_message += ' in original PGDATA: {0}\n ' .format (
1841
+ os .path .join (restored_pgdata ['pgdata' ], file ))
1842
+
1843
+ for file in sorted (original_files - restored_files ):
1844
+ error_message += (
1845
+ '\n File disappearance.\n '
1846
+ 'File: {0}\n ' ).format (
1847
+ os .path .join (restored_pgdata ['pgdata' ], file )
1848
+ )
1849
+ fail = True
1859
1850
1860
- if (
1861
- restored_pgdata ['files' ][file ]['mode' ] !=
1862
- original_pgdata ['files' ][file ]['mode' ]
1863
- ):
1851
+ for file in sorted (original_files & restored_files ):
1852
+ original = original_pgdata ['files' ][file ]
1853
+ restored = restored_pgdata ['files' ][file ]
1854
+ if restored .mode != original .mode :
1855
+ fail = True
1856
+ error_message += '\n File permissions mismatch:\n '
1857
+ error_message += ' File_old: {0} Permissions: {1:o}\n ' .format (
1858
+ os .path .join (original_pgdata ['pgdata' ], file ),
1859
+ original .mode )
1860
+ error_message += ' File_new: {0} Permissions: {1:o}\n ' .format (
1861
+ os .path .join (restored_pgdata ['pgdata' ], file ),
1862
+ restored .mode )
1863
+
1864
+ if original .md5 != restored .md5 :
1865
+ if file not in exclusion_dict :
1864
1866
fail = True
1865
- error_message += '\n File permissions mismatch:\n '
1866
- error_message += ' File_old: {0} Permissions: {1:o}\n ' .format (
1867
+ error_message += (
1868
+ '\n File Checksum mismatch.\n '
1869
+ 'File_old: {0}\n Checksum_old: {1}\n '
1870
+ 'File_new: {2}\n Checksum_new: {3}\n ' ).format (
1867
1871
os .path .join (original_pgdata ['pgdata' ], file ),
1868
- original_pgdata ['files' ][file ]['mode' ])
1869
- error_message += ' File_new: {0} Permissions: {1:o}\n ' .format (
1872
+ original .md5 ,
1870
1873
os .path .join (restored_pgdata ['pgdata' ], file ),
1871
- restored_pgdata ['files' ][file ]['mode' ])
1874
+ restored .md5
1875
+ )
1872
1876
1873
- if (
1874
- original_pgdata ['files' ][file ]['md5' ] !=
1875
- restored_pgdata ['files' ][file ]['md5' ]
1876
- ):
1877
- if file not in exclusion_dict :
1878
- fail = True
1879
- error_message += (
1880
- '\n File Checksum mismatch.\n '
1881
- 'File_old: {0}\n Checksum_old: {1}\n '
1882
- 'File_new: {2}\n Checksum_new: {3}\n ' ).format (
1883
- os .path .join (original_pgdata ['pgdata' ], file ),
1884
- original_pgdata ['files' ][file ]['md5' ],
1885
- os .path .join (restored_pgdata ['pgdata' ], file ),
1886
- restored_pgdata ['files' ][file ]['md5' ]
1887
- )
1877
+ if not original .is_datafile :
1878
+ continue
1888
1879
1889
- if original_pgdata ['files' ][file ]['is_datafile' ]:
1890
- for page in original_pgdata ['files' ][file ]['md5_per_page' ]:
1891
- if page not in restored_pgdata ['files' ][file ]['md5_per_page' ]:
1892
- error_message += (
1893
- '\n Page {0} dissappeared.\n '
1894
- 'File: {1}\n ' ).format (
1895
- page ,
1896
- os .path .join (
1897
- restored_pgdata ['pgdata' ],
1898
- file
1899
- )
1900
- )
1901
- continue
1902
-
1903
- if not (file in exclusion_dict and page in exclusion_dict [file ]):
1904
- if (
1905
- original_pgdata ['files' ][file ]['md5_per_page' ][page ] !=
1906
- restored_pgdata ['files' ][file ]['md5_per_page' ][page ]
1907
- ):
1908
- fail = True
1909
- error_message += (
1910
- '\n Page checksum mismatch: {0}\n '
1911
- ' PAGE Checksum_old: {1}\n '
1912
- ' PAGE Checksum_new: {2}\n '
1913
- ' File: {3}\n '
1914
- ).format (
1915
- page ,
1916
- original_pgdata ['files' ][file ][
1917
- 'md5_per_page' ][page ],
1918
- restored_pgdata ['files' ][file ][
1919
- 'md5_per_page' ][page ],
1920
- os .path .join (
1921
- restored_pgdata ['pgdata' ], file )
1922
- )
1923
- for page in restored_pgdata ['files' ][file ]['md5_per_page' ]:
1924
- if page not in original_pgdata ['files' ][file ]['md5_per_page' ]:
1925
- error_message += '\n Extra page {0}\n File: {1}\n ' .format (
1926
- page ,
1927
- os .path .join (
1928
- restored_pgdata ['pgdata' ], file ))
1880
+ original_pages = set (original .md5_per_page )
1881
+ restored_pages = set (restored .md5_per_page )
1929
1882
1930
- else :
1931
- error_message += (
1932
- '\n File disappearance.\n '
1933
- 'File: {0}\n ' ).format (
1934
- os .path .join (restored_pgdata ['pgdata' ], file )
1883
+ for page in sorted (original_pages - restored_pages ):
1884
+ error_message += '\n Page {0} dissappeared.\n File: {1}\n ' .format (
1885
+ page ,
1886
+ os .path .join (restored_pgdata ['pgdata' ], file )
1935
1887
)
1936
- fail = True
1888
+
1889
+
1890
+ for page in sorted (restored_pages - original_pages ):
1891
+ error_message += '\n Extra page {0}\n File: {1}\n ' .format (
1892
+ page ,
1893
+ os .path .join (restored_pgdata ['pgdata' ], file ))
1894
+
1895
+ for page in sorted (original_pages & restored_pages ):
1896
+ if file in exclusion_dict and page in exclusion_dict [file ]:
1897
+ continue
1898
+
1899
+ if original .md5_per_page [page ] != restored .md5_per_page [page ]:
1900
+ fail = True
1901
+ error_message += (
1902
+ '\n Page checksum mismatch: {0}\n '
1903
+ ' PAGE Checksum_old: {1}\n '
1904
+ ' PAGE Checksum_new: {2}\n '
1905
+ ' File: {3}\n '
1906
+ ).format (
1907
+ page ,
1908
+ original .md5_per_page [page ],
1909
+ restored .md5_per_page [page ],
1910
+ os .path .join (
1911
+ restored_pgdata ['pgdata' ], file )
1912
+ )
1913
+
1937
1914
self .assertFalse (fail , error_message )
1938
1915
1939
1916
def gdb_attach (self , pid ):
@@ -2186,3 +2163,10 @@ def _execute(self, cmd, running=True):
2186
2163
# if running and line.startswith('*running'):
2187
2164
break
2188
2165
return output
2166
+ class ContentFile (object ):
2167
+ __slots__ = ('is_datafile' , 'mode' , 'md5' , 'md5_per_page' )
2168
+ def __init__ (self , is_datafile : bool ):
2169
+ self .is_datafile = is_datafile
2170
+
2171
+ class ContentDir (object ):
2172
+ __slots__ = ('mode' )
0 commit comments