You've already forked pgbackrest
							
							
				mirror of
				https://github.com/pgbackrest/pgbackrest.git
				synced 2025-10-30 23:37:45 +02:00 
			
		
		
		
	Improvements in C codebase:
* Update C naming conventions. * Use int datatype wherever possible. * Better separation of C source from Perl interface.
This commit is contained in:
		| @@ -22,6 +22,11 @@ use pgBackRestBuild::CodeGen::Common; | ||||
| use pgBackRestBuild::CodeGen::Truth; | ||||
| use pgBackRestBuild::Config::Build; | ||||
|  | ||||
| #################################################################################################################################### | ||||
| # Define generator used for auto generated warning messages | ||||
| #################################################################################################################################### | ||||
| use constant GENERATOR                                              => 'Build.pm'; | ||||
|  | ||||
| #################################################################################################################################### | ||||
| # buildAll - execute all build functions and generate C source code | ||||
| #################################################################################################################################### | ||||
| @@ -112,7 +117,7 @@ sub buildAll | ||||
|  | ||||
|             # Build general banner | ||||
|             #------------------------------------------------------------------------------------------------------------------------------- | ||||
|             my $strBanner = cgenBanner($rhFile->{&BLD_SUMMARY}); | ||||
|             my $strBanner = cgenBanner($rhFile->{&BLD_SUMMARY}, GENERATOR); | ||||
|  | ||||
|             # Build header file | ||||
|             #------------------------------------------------------------------------------------------------------------------------------- | ||||
| @@ -130,7 +135,7 @@ sub buildAll | ||||
|                 { | ||||
|                     my $rhConstantGroup = $rhFileConstant->{$strConstantGroup}; | ||||
|  | ||||
|                     $strHeader .= "\n" . cgenBanner($rhConstantGroup->{&BLD_SUMMARY} . ' constants'); | ||||
|                     $strHeader .= "\n" . cgenBanner($rhConstantGroup->{&BLD_SUMMARY} . ' constants', GENERATOR); | ||||
|  | ||||
|                     # Iterate constants | ||||
|                     foreach my $strConstant (sort(keys(%{$rhConstantGroup->{&BLD_CONSTANT}}))) | ||||
|   | ||||
| @@ -21,8 +21,8 @@ use constant CGEN_DATATYPE_BOOL                                     => 'bool'; | ||||
|     push @EXPORT, qw(CGEN_DATATYPE_BOOL); | ||||
| use constant CGEN_DATATYPE_DOUBLE                                   => 'double'; | ||||
|     push @EXPORT, qw(CGEN_DATATYPE_DOUBLE); | ||||
| use constant CGEN_DATATYPE_INT32                                    => 'int32'; | ||||
|     push @EXPORT, qw(CGEN_DATATYPE_INT32); | ||||
| use constant CGEN_DATATYPE_INT                                      => 'int'; | ||||
|     push @EXPORT, qw(CGEN_DATATYPE_INT); | ||||
| use constant CGEN_DATATYPE_INT64                                    => 'int64'; | ||||
|     push @EXPORT, qw(CGEN_DATATYPE_INT64); | ||||
| use constant CGEN_DATATYPE_CONSTCHAR                                => 'const char *'; | ||||
| @@ -31,16 +31,38 @@ use constant CGEN_DATATYPE_CONSTCHAR                                => 'const ch | ||||
| use constant CGEN_DATAVAL_NULL                                      => '^^{{[[NULL]]}}^^'; | ||||
|     push @EXPORT, qw(CGEN_DATAVAL_NULL); | ||||
|  | ||||
| #################################################################################################################################### | ||||
| # cgenAutoWarning - warning not to modify automatically generated files directly | ||||
| #################################################################################################################################### | ||||
| sub cgenAutoWarning | ||||
| { | ||||
|     my $strGenerator = shift; | ||||
|  | ||||
|     return "Automatically generated by ${strGenerator} -- do not modify directly."; | ||||
| } | ||||
|  | ||||
| push @EXPORT, qw(cgenAutoWarning); | ||||
|  | ||||
| #################################################################################################################################### | ||||
| # cgenBanner - build general banner | ||||
| #################################################################################################################################### | ||||
| sub cgenBanner | ||||
| { | ||||
|     my $strContent = shift; | ||||
|     my $strGenerator = shift; | ||||
|  | ||||
|     my $strBanner = | ||||
|         qw{/} . (qw{*} x 131) . "\n" . | ||||
|         trim($strContent) . "\n" . | ||||
|         trim($strContent) . "\n"; | ||||
|  | ||||
|     if (defined($strGenerator)) | ||||
|     { | ||||
|         $strBanner .= | ||||
|             "# \n" . | ||||
|             '# ' . cgenAutoWarning($strGenerator)  . "\n"; | ||||
|     } | ||||
|  | ||||
|     $strBanner .= | ||||
|         (qw{*} x 131) . qw{/} . "\n"; | ||||
|  | ||||
|     return $strBanner; | ||||
| @@ -93,7 +115,7 @@ sub cgenTypeFormat | ||||
|     { | ||||
|         return ($strValue == 1 ? 'true' : 'false'); | ||||
|     } | ||||
|     elsif ($strType eq CGEN_DATATYPE_INT32 || $strType eq CGEN_DATATYPE_INT64 || $strType eq CGEN_DATATYPE_DOUBLE) | ||||
|     elsif ($strType eq CGEN_DATATYPE_INT || $strType eq CGEN_DATATYPE_INT64 || $strType eq CGEN_DATATYPE_DOUBLE) | ||||
|     { | ||||
|         return $strValue; | ||||
|     } | ||||
| @@ -118,9 +140,9 @@ sub cgenTypeName | ||||
|     { | ||||
|         return 'bool'; | ||||
|     } | ||||
|     elsif ($strType eq CGEN_DATATYPE_INT32) | ||||
|     elsif ($strType eq CGEN_DATATYPE_INT) | ||||
|     { | ||||
|         return 'int32'; | ||||
|         return 'int'; | ||||
|     } | ||||
|     elsif ($strType eq CGEN_DATATYPE_INT64) | ||||
|     { | ||||
|   | ||||
| @@ -26,9 +26,11 @@ sub cgenLookupString | ||||
|     my $rhValue = shift; | ||||
|     my $strFilter = shift; | ||||
|  | ||||
|     my $strLowerName = lc($strName); | ||||
|  | ||||
|     # Generate list of command strings | ||||
|     my $strFunction = | ||||
|         "const char *szy${strName}Name[${strTotal}] = \n" . | ||||
|         "const char *${strLowerName}NameList[${strTotal}] = \n" . | ||||
|         "{\n"; | ||||
|  | ||||
|     my $bFirst = true; | ||||
| @@ -46,12 +48,12 @@ sub cgenLookupString | ||||
|  | ||||
|     $strFunction .= | ||||
|         "const char *\n" . | ||||
|         "cfg${strName}Name(uint32 ui${strName}Id)\n" . | ||||
|         "cfg${strName}Name(int ${strLowerName}Id)\n" . | ||||
|         "{\n" . | ||||
|         "    if (ui${strName}Id >= ${strTotal})\n" . | ||||
|         "    if (${strLowerName}Id < 0 || ${strLowerName}Id >= ${strTotal})\n" . | ||||
|         "        return NULL;\n" . | ||||
|         "\n" . | ||||
|         "    return szy${strName}Name[ui${strName}Id];\n" . | ||||
|         "    return ${strLowerName}NameList[${strLowerName}Id];\n" . | ||||
|         "}\n"; | ||||
|  | ||||
|     return $strFunction; | ||||
| @@ -67,13 +69,15 @@ sub cgenLookupId | ||||
|     my $strName = shift; | ||||
|     my $strTotal = shift; | ||||
|  | ||||
|     my $strLowerName = lc($strName); | ||||
|  | ||||
|     my $strFunction = | ||||
|         "int32\n" . | ||||
|         "cfg${strName}Id(const char *sz${strName}Name)\n" . | ||||
|         "int\n" . | ||||
|         "cfg${strName}Id(const char *${strLowerName}Name)\n" . | ||||
|         "{\n" . | ||||
|         "    for (uint32 uiIndex = 0; uiIndex < ${strTotal}; uiIndex++)\n" . | ||||
|         "        if (strcmp(sz${strName}Name, cfg${strName}Name(uiIndex)) == 0)\n" . | ||||
|         "            return uiIndex;\n" . | ||||
|         "    for (int nameIdx = 0; nameIdx < ${strTotal}; nameIdx++)\n" . | ||||
|         "        if (strcmp(${strLowerName}Name, cfg${strName}Name(nameIdx)) == 0)\n" . | ||||
|         "            return nameIdx;\n" . | ||||
|         "\n" . | ||||
|         "    return -1;\n" . | ||||
|         "}\n"; | ||||
|   | ||||
| @@ -95,7 +95,7 @@ sub cgenSwitchBuild | ||||
|     # Construct the function based on the best switch statement | ||||
|     return | ||||
|         cgenTypeName($strType) . "\n" . | ||||
|         "${strName}(uint32 " . join(', uint32 ', @{$rstryParam}) . ")\n" . | ||||
|         "${strName}(int " . join(', int ', @{$rstryParam}) . ")\n" . | ||||
|         "{\n" . | ||||
|         "${strBestSwitch}\n" . | ||||
|         "}\n"; | ||||
|   | ||||
| @@ -32,10 +32,10 @@ use pgBackRestBuild::Config::Rule; | ||||
| use constant BLDLCL_FILE_CONFIG                                     => 'config'; | ||||
| use constant BLDLCL_FILE_CONFIG_RULE                                => BLDLCL_FILE_CONFIG . 'Rule'; | ||||
|  | ||||
| use constant BLDLCL_PARAM_OPTIONID                                  => 'uiOptionId'; | ||||
| use constant BLDLCL_PARAM_COMMANDID                                 => 'uiCommandId'; | ||||
| use constant BLDLCL_PARAM_OPTIONID                                  => 'optionId'; | ||||
| use constant BLDLCL_PARAM_COMMANDID                                 => 'commandId'; | ||||
|     push @EXPORT, qw(BLDLCL_PARAM_COMMANDID); | ||||
| use constant BLDLCL_PARAM_VALUEID                                   => 'uiValueId'; | ||||
| use constant BLDLCL_PARAM_VALUEID                                   => 'valueId'; | ||||
|  | ||||
| use constant BLDLCL_CONSTANT_COMMAND                                => 'CFGCMDDEF'; | ||||
| use constant BLDLCL_CONSTANT_COMMAND_TOTAL                          => BLDLCL_CONSTANT_COMMAND . '_TOTAL'; | ||||
| @@ -181,7 +181,7 @@ my $rhBuild = | ||||
|         #--------------------------------------------------------------------------------------------------------------------------- | ||||
|         &BLDLCL_FILE_CONFIG => | ||||
|         { | ||||
|             &BLD_SUMMARY => 'Query Configuration Settings', | ||||
|             &BLD_SUMMARY => 'Command and Option Configuration', | ||||
|  | ||||
|             &BLD_CONSTANT_GROUP => | ||||
|             { | ||||
| @@ -228,7 +228,7 @@ my $rhBuild = | ||||
|                 &BLDLCL_FUNCTION_INDEX_TOTAL => | ||||
|                 { | ||||
|                     &BLD_SUMMARY => 'total index values allowed', | ||||
|                     &BLD_RETURN_TYPE => CGEN_DATATYPE_INT32, | ||||
|                     &BLD_RETURN_TYPE => CGEN_DATATYPE_INT, | ||||
|                     &BLD_PARAM => [BLDLCL_PARAM_OPTIONID], | ||||
|                     &BLD_TRUTH_DEFAULT => 1, | ||||
|                     &BLD_FUNCTION_DEPEND => BLDLCL_FUNCTION_VALID, | ||||
| @@ -245,7 +245,7 @@ my $rhBuild = | ||||
|         #--------------------------------------------------------------------------------------------------------------------------- | ||||
|         &BLDLCL_FILE_CONFIG_RULE => | ||||
|         { | ||||
|             &BLD_SUMMARY => 'Parse Configuration Settings', | ||||
|             &BLD_SUMMARY => 'Command and Option Configuration Rules', | ||||
|  | ||||
|             &BLD_FUNCTION => | ||||
|             { | ||||
| @@ -276,7 +276,7 @@ my $rhBuild = | ||||
|                 &BLDLCL_FUNCTION_ALLOW_LIST_VALUE_TOTAL => | ||||
|                 { | ||||
|                     &BLD_SUMMARY => 'total number of values allowed', | ||||
|                     &BLD_RETURN_TYPE => CGEN_DATATYPE_INT32, | ||||
|                     &BLD_RETURN_TYPE => CGEN_DATATYPE_INT, | ||||
|                     &BLD_PARAM => [BLDLCL_PARAM_COMMANDID, BLDLCL_PARAM_OPTIONID], | ||||
|                     &BLD_FUNCTION_DEPEND => BLDLCL_FUNCTION_ALLOW_LIST, | ||||
|                     &BLD_FUNCTION_DEPEND_RESULT => true, | ||||
| @@ -333,7 +333,7 @@ my $rhBuild = | ||||
|                 &BLDLCL_FUNCTION_DEPEND_OPTION => | ||||
|                 { | ||||
|                     &BLD_SUMMARY => 'name of the option that this option depends in order to be set', | ||||
|                     &BLD_RETURN_TYPE => CGEN_DATATYPE_INT32, | ||||
|                     &BLD_RETURN_TYPE => CGEN_DATATYPE_INT, | ||||
|                     &BLD_PARAM => [BLDLCL_PARAM_COMMANDID, BLDLCL_PARAM_OPTIONID], | ||||
|                     &BLD_RETURN_VALUE_MAP => $rhOptionIdConstantMap, | ||||
|                     &BLD_FUNCTION_DEPEND => BLDLCL_FUNCTION_DEPEND, | ||||
| @@ -352,7 +352,7 @@ my $rhBuild = | ||||
|                 &BLDLCL_FUNCTION_DEPEND_VALUE_TOTAL => | ||||
|                 { | ||||
|                     &BLD_SUMMARY => 'total depend values for this option', | ||||
|                     &BLD_RETURN_TYPE => CGEN_DATATYPE_INT32, | ||||
|                     &BLD_RETURN_TYPE => CGEN_DATATYPE_INT, | ||||
|                     &BLD_PARAM => [BLDLCL_PARAM_COMMANDID, BLDLCL_PARAM_OPTIONID], | ||||
|                     &BLD_FUNCTION_DEPEND => BLDLCL_FUNCTION_DEPEND, | ||||
|                     &BLD_FUNCTION_DEPEND_RESULT => true, | ||||
| @@ -428,7 +428,7 @@ my $rhBuild = | ||||
|                 &BLDLCL_FUNCTION_TYPE => | ||||
|                 { | ||||
|                     &BLD_SUMMARY => 'secure options can never be passed on the commmand-line', | ||||
|                     &BLD_RETURN_TYPE => CGEN_DATATYPE_INT32, | ||||
|                     &BLD_RETURN_TYPE => CGEN_DATATYPE_INT, | ||||
|                     &BLD_PARAM => [BLDLCL_PARAM_OPTIONID], | ||||
|                     &BLD_RETURN_VALUE_MAP => $rhOptionTypeIdConstantMap, | ||||
|                 }, | ||||
|   | ||||
| @@ -10,6 +10,24 @@ | ||||
|     </intro> | ||||
|  | ||||
|     <release-list> | ||||
|         <release date="XXXX-XX-XX" version="1.25dev" title="UNDER DEVELOPMENT"> | ||||
|             <release-core-list> | ||||
|                 <release-refactor-list> | ||||
|                     <release-item> | ||||
|                         <p>Update C naming conventions.</p> | ||||
|                     </release-item> | ||||
|  | ||||
|                     <release-item> | ||||
|                         <p>Use <id>int</id> datatype wherever possible.</p> | ||||
|                     </release-item> | ||||
|  | ||||
|                     <release-item> | ||||
|                         <p>Better separation of C source from Perl interface.</p> | ||||
|                     </release-item> | ||||
|                 </release-refactor-list> | ||||
|             </release-core-list> | ||||
|         </release> | ||||
|  | ||||
|         <release date="2017-09-28" version="1.24" title="New Backup Exclusions"> | ||||
|             <release-core-list> | ||||
|                 <release-bug-list> | ||||
|   | ||||
| @@ -35,7 +35,7 @@ use constant BACKREST_BIN                                           => abs_path( | ||||
| # Defines the current version of the BackRest executable.  The version number is used to track features but does not affect what | ||||
| # repositories or manifests can be read - that's the job of the format number. | ||||
| #----------------------------------------------------------------------------------------------------------------------------------- | ||||
| use constant BACKREST_VERSION                                       => '1.24'; | ||||
| use constant BACKREST_VERSION                                       => '1.25dev'; | ||||
|     push @EXPORT, qw(BACKREST_VERSION); | ||||
|  | ||||
| # Format Format Number | ||||
|   | ||||
| @@ -1,9 +0,0 @@ | ||||
| #ifndef LIBC_H | ||||
| #define LIBC_H | ||||
|  | ||||
| #include "common/type.h" | ||||
| #include "config/config.h" | ||||
| #include "config/configRule.h" | ||||
| #include "postgres/pageChecksum.h" | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										53
									
								
								libc/LibC.xs
									
									
									
									
									
								
							
							
						
						
									
										53
									
								
								libc/LibC.xs
									
									
									
									
									
								
							| @@ -1,26 +1,57 @@ | ||||
| /*********************************************************************************************************************************** | ||||
| C to Perl Interface | ||||
|  | ||||
| The following C types are mapped by the current typemap: | ||||
|  | ||||
| 'AV *', 'Boolean', 'CV *', 'FILE *', 'FileHandle', 'HV *', 'I16', 'I32', 'I8', 'IV', 'InOutStream', 'InputStream', 'NV', | ||||
| 'OutputStream', 'PerlIO *', 'Result', 'STRLEN', 'SV *', 'SVREF', 'SysRet', 'SysRetLong', 'Time_t *', 'U16', 'U32', 'U8', 'UV', | ||||
| 'bool', 'bool_t', 'caddr_t', 'char', 'char *', 'char **', 'const char *', 'double', 'float', 'int', 'long', 'short', 'size_t', | ||||
| 'ssize_t', 'time_t', 'unsigned', 'unsigned char', 'unsigned char *', 'unsigned int', 'unsigned long', 'unsigned long *', | ||||
| 'unsigned short', 'void *', 'wchar_t', 'wchar_t *' | ||||
| ***********************************************************************************************************************************/ | ||||
| #define PERL_NO_GET_CONTEXT | ||||
|  | ||||
| #include "LibC.h" | ||||
| #include "XSUB.h" | ||||
| /*********************************************************************************************************************************** | ||||
| Perl includes | ||||
|  | ||||
| Order is critical here so don't change it. | ||||
| ***********************************************************************************************************************************/ | ||||
| #include <XSUB.h> | ||||
| #include <EXTERN.h> | ||||
| #include <perl.h> | ||||
|  | ||||
| /*********************************************************************************************************************************** | ||||
| C includes | ||||
|  | ||||
| These includes are from the src directory.  There is no Perl-specific code in them. | ||||
| ***********************************************************************************************************************************/ | ||||
| #include "common/type.h" | ||||
| #include "config/config.h" | ||||
| #include "config/configRule.h" | ||||
| #include "postgres/pageChecksum.h" | ||||
|  | ||||
| /*********************************************************************************************************************************** | ||||
| Constant include | ||||
|  | ||||
| Auto generated code that handles exporting C constants to Perl. | ||||
| ***********************************************************************************************************************************/ | ||||
| #include "const-c.inc" | ||||
|  | ||||
| /* | ||||
|  * The following C types are mapped by the current typemap: | ||||
|  * 'AV *', 'Boolean', 'CV *', 'FILE *', 'FileHandle', 'HV *', 'I16', 'I32', 'I8', 'IV', 'InOutStream', 'InputStream', 'NV', | ||||
|  * 'OutputStream', 'PerlIO *', 'Result', 'STRLEN', 'SV *', 'SVREF', 'SysRet', 'SysRetLong', 'Time_t *', 'U16', 'U32', 'U8', 'UV', | ||||
|  * 'bool', 'bool_t', 'caddr_t', 'char', 'char *', 'char **', 'const char *', 'double', 'float', 'int', 'long', 'short', 'size_t', | ||||
|  * 'ssize_t', 'time_t', 'unsigned', 'unsigned char', 'unsigned char *', 'unsigned int', 'unsigned long', 'unsigned long *', | ||||
|  * 'unsigned short', 'void *', 'wchar_t', 'wchar_t *' | ||||
|  */ | ||||
|  | ||||
| /*********************************************************************************************************************************** | ||||
| Module definition | ||||
| ***********************************************************************************************************************************/ | ||||
| MODULE = pgBackRest::LibC PACKAGE = pgBackRest::LibC | ||||
| PROTOTYPES: DISABLE | ||||
|  | ||||
| # Exported constants | ||||
| # | ||||
| # The XS portion of the code that handles exporting C constants to Perl. | ||||
| # ---------------------------------------------------------------------------------------------------------------------------------- | ||||
| INCLUDE: const-xs.inc | ||||
|  | ||||
| # Exported functions and modules | ||||
| # | ||||
| # These modules should map 1-1 with C modules in src directory. | ||||
| # ---------------------------------------------------------------------------------------------------------------------------------- | ||||
| INCLUDE: xs/config/config.xs | ||||
| INCLUDE: xs/config/configRule.xs | ||||
|   | ||||
| @@ -28,6 +28,7 @@ my $oStorage = new pgBackRest::Storage::Local( | ||||
| #################################################################################################################################### | ||||
| # Build C files required for the library | ||||
| #################################################################################################################################### | ||||
| use pgBackRestBuild::CodeGen::Common; | ||||
| use pgBackRestBuild::Build; | ||||
|  | ||||
| my $rhBuild = buildAll($strBuildPath); | ||||
| @@ -150,6 +151,11 @@ sub formatText | ||||
|     } | ||||
|  | ||||
|     my $strLibC = | ||||
|         ('#' x 132) . "\n" . | ||||
|         "# C to Perl Interface\n" . | ||||
|         "# \n" . | ||||
|         '# ' . cgenAutoWarning('Makefile.PL') . "\n" . | ||||
|         ('#' x 132) . "\n" . | ||||
|         'package ' . BACKREST_NAME . '::' . LIB_NAME . ";\n" . | ||||
|         "\n" . | ||||
|         "use 5.010001;\n" . | ||||
|   | ||||
| @@ -11,7 +11,7 @@ use Fcntl qw(O_RDONLY); | ||||
| # Set number of tests | ||||
| use Test::More tests => 56; | ||||
|  | ||||
| # Load the module dynamically so it does not interfere with the test above | ||||
| # Load the module | ||||
| use pgBackRest::LibC qw(:config :configRule); | ||||
|  | ||||
| # Config rule functions | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| #################################################################################################################################### | ||||
| # pgBackRest-LibC.t - Unit tests for the LibC module | ||||
| # Page Checksum Tests | ||||
| #################################################################################################################################### | ||||
| use strict; | ||||
| use warnings; | ||||
| @@ -9,17 +9,10 @@ use English '-no_match_vars'; | ||||
| use Fcntl qw(O_RDONLY); | ||||
| 
 | ||||
| # Set number of tests | ||||
| use Test::More tests => 11; | ||||
| use Test::More tests => 9; | ||||
| 
 | ||||
| # Make sure the module loads without errors | ||||
| BEGIN {use_ok('pgBackRest::LibC')}; | ||||
| 
 | ||||
| # Load the module dynamically so it does not interfere with the test above | ||||
| require pgBackRest::LibC; | ||||
| pgBackRest::LibC->import(qw(:debug :checksum)); | ||||
| 
 | ||||
| # UVSIZE determines the pointer and long long int size.  This needs to be 8 to indicate 64-bit types are available. | ||||
| ok (&UVSIZE == 8, 'UVSIZE == 8'); | ||||
| # Load the module | ||||
| use pgBackRest::LibC qw(:checksum); | ||||
| 
 | ||||
| sub pageBuild | ||||
| { | ||||
| @@ -88,7 +81,7 @@ sub pageBuild | ||||
| 
 | ||||
|     ok (pageChecksumBufferTest($tBufferMulti, length($tBufferMulti), 0, $iPageSize, 0xFFFF, 0xFFFF), 'pass valid page buffer'); | ||||
| 
 | ||||
|     # Make sure that an invalid buffer size throws an exception | ||||
|     # Make sure that an invalid buffer size throws an error | ||||
|     eval | ||||
|     { | ||||
|         pageChecksumBufferTest($tBufferMulti, length($tBufferMulti) - 1, 0, $iPageSize, 0xFFFF, 0xFFFF); | ||||
							
								
								
									
										22
									
								
								libc/t/sanity.t
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								libc/t/sanity.t
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| #################################################################################################################################### | ||||
| # Sanity Tests for C Library | ||||
| # | ||||
| # Basic test to ensure the C library loads and has been compiled correctly. | ||||
| #################################################################################################################################### | ||||
| use strict; | ||||
| use warnings; | ||||
| use Carp; | ||||
| use English '-no_match_vars'; | ||||
|  | ||||
| # Set number of tests | ||||
| use Test::More tests => 2; | ||||
|  | ||||
| # Make sure the module loads without errors | ||||
| BEGIN {use_ok('pgBackRest::LibC')}; | ||||
|  | ||||
| # Load the module dynamically so it does not interfere with the test above | ||||
| require pgBackRest::LibC; | ||||
| pgBackRest::LibC->import(qw(:debug)); | ||||
|  | ||||
| # UVSIZE determines the pointer and long long int size.  This needs to be 8 to indicate 64-bit types are available. | ||||
| ok (&UVSIZE == 8, 'UVSIZE == 8'); | ||||
| @@ -5,13 +5,13 @@ | ||||
| MODULE = pgBackRest::LibC PACKAGE = pgBackRest::LibC | ||||
|  | ||||
| const char * | ||||
| cfgCommandName(uiCommandId) | ||||
|     U32 uiCommandId | ||||
| cfgCommandName(commandId) | ||||
|     U32 commandId | ||||
|  | ||||
| I32 | ||||
| cfgOptionIndexTotal(uiOptionId) | ||||
|     U32 uiOptionId | ||||
| cfgOptionIndexTotal(optionId) | ||||
|     U32 optionId | ||||
|  | ||||
| const char * | ||||
| cfgOptionName(uiOptionId) | ||||
|     U32 uiOptionId | ||||
| cfgOptionName(optionId) | ||||
|     U32 optionId | ||||
|   | ||||
| @@ -5,123 +5,123 @@ | ||||
| MODULE = pgBackRest::LibC PACKAGE = pgBackRest::LibC | ||||
|  | ||||
| I32 | ||||
| cfgCommandId(szCommandName) | ||||
|     const char *szCommandName | ||||
| cfgCommandId(commandName) | ||||
|     const char *commandName | ||||
|  | ||||
| I32 | ||||
| cfgOptionId(szOptionName) | ||||
|     const char *szOptionName | ||||
| cfgOptionId(optionName) | ||||
|     const char *optionName | ||||
|  | ||||
| bool | ||||
| cfgRuleOptionAllowList(uiCommandId, uiOptionId) | ||||
|     U32 uiCommandId | ||||
|     U32 uiOptionId | ||||
| cfgRuleOptionAllowList(commandId, optionId) | ||||
|     U32 commandId | ||||
|     U32 optionId | ||||
|  | ||||
| const char * | ||||
| cfgRuleOptionAllowListValue(uiCommandId, uiOptionId, uiValueId) | ||||
|     U32 uiCommandId | ||||
|     U32 uiOptionId | ||||
|     U32 uiValueId | ||||
| cfgRuleOptionAllowListValue(commandId, optionId, valueId) | ||||
|     U32 commandId | ||||
|     U32 optionId | ||||
|     U32 valueId | ||||
|  | ||||
| I32 | ||||
| cfgRuleOptionAllowListValueTotal(uiCommandId, uiOptionId) | ||||
|     U32 uiCommandId | ||||
|     U32 uiOptionId | ||||
| cfgRuleOptionAllowListValueTotal(commandId, optionId) | ||||
|     U32 commandId | ||||
|     U32 optionId | ||||
|  | ||||
| bool | ||||
| cfgRuleOptionAllowListValueValid(uiCommandId, uiOptionId, szValue); | ||||
|     U32 uiCommandId | ||||
|     U32 uiOptionId | ||||
|     const char *szValue | ||||
| cfgRuleOptionAllowListValueValid(commandId, optionId, value); | ||||
|     U32 commandId | ||||
|     U32 optionId | ||||
|     const char *value | ||||
|  | ||||
| bool | ||||
| cfgRuleOptionAllowRange(uiCommandId, uiOptionId) | ||||
|     U32 uiCommandId | ||||
|     U32 uiOptionId | ||||
| cfgRuleOptionAllowRange(commandId, optionId) | ||||
|     U32 commandId | ||||
|     U32 optionId | ||||
|  | ||||
| double | ||||
| cfgRuleOptionAllowRangeMax(uiCommandId, uiOptionId) | ||||
|     U32 uiCommandId | ||||
|     U32 uiOptionId | ||||
| cfgRuleOptionAllowRangeMax(commandId, optionId) | ||||
|     U32 commandId | ||||
|     U32 optionId | ||||
|  | ||||
| double | ||||
| cfgRuleOptionAllowRangeMin(uiCommandId, uiOptionId) | ||||
|     U32 uiCommandId | ||||
|     U32 uiOptionId | ||||
| cfgRuleOptionAllowRangeMin(commandId, optionId) | ||||
|     U32 commandId | ||||
|     U32 optionId | ||||
|  | ||||
| const char * | ||||
| cfgRuleOptionDefault(uiCommandId, uiOptionId) | ||||
|     U32 uiCommandId | ||||
|     U32 uiOptionId | ||||
| cfgRuleOptionDefault(commandId, optionId) | ||||
|     U32 commandId | ||||
|     U32 optionId | ||||
|  | ||||
| bool | ||||
| cfgRuleOptionDepend(uiCommandId, uiOptionId); | ||||
|     U32 uiCommandId | ||||
|     U32 uiOptionId | ||||
| cfgRuleOptionDepend(commandId, optionId); | ||||
|     U32 commandId | ||||
|     U32 optionId | ||||
|  | ||||
| I32 | ||||
| cfgRuleOptionDependOption(uiCommandId, uiOptionId) | ||||
|     U32 uiCommandId | ||||
|     U32 uiOptionId | ||||
| cfgRuleOptionDependOption(commandId, optionId) | ||||
|     U32 commandId | ||||
|     U32 optionId | ||||
|  | ||||
| const char * | ||||
| cfgRuleOptionDependValue(uiCommandId, uiOptionId, uiValueId) | ||||
|     U32 uiCommandId | ||||
|     U32 uiOptionId | ||||
|     U32 uiValueId | ||||
| cfgRuleOptionDependValue(commandId, optionId, valueId) | ||||
|     U32 commandId | ||||
|     U32 optionId | ||||
|     U32 valueId | ||||
|  | ||||
| I32 | ||||
| cfgRuleOptionDependValueTotal(uiCommandId, uiOptionId) | ||||
|     U32 uiCommandId | ||||
|     U32 uiOptionId | ||||
| cfgRuleOptionDependValueTotal(commandId, optionId) | ||||
|     U32 commandId | ||||
|     U32 optionId | ||||
|  | ||||
| bool | ||||
| cfgRuleOptionDependValueValid(uiCommandId, uiOptionId, szValue) | ||||
|     U32 uiCommandId | ||||
|     U32 uiOptionId | ||||
|     const char *szValue | ||||
| cfgRuleOptionDependValueValid(commandId, optionId, value) | ||||
|     U32 commandId | ||||
|     U32 optionId | ||||
|     const char *value | ||||
|  | ||||
| const char * | ||||
| cfgRuleOptionHint(uiCommandId, uiOptionId) | ||||
|     U32 uiCommandId | ||||
|     U32 uiOptionId | ||||
| cfgRuleOptionHint(commandId, optionId) | ||||
|     U32 commandId | ||||
|     U32 optionId | ||||
|  | ||||
| const char * | ||||
| cfgRuleOptionNameAlt(uiOptionId) | ||||
|     U32 uiOptionId | ||||
| cfgRuleOptionNameAlt(optionId) | ||||
|     U32 optionId | ||||
|  | ||||
| bool cfgRuleOptionNegate(uiOptionId) | ||||
|     U32 uiOptionId | ||||
| bool cfgRuleOptionNegate(optionId) | ||||
|     U32 optionId | ||||
|  | ||||
| const char * | ||||
| cfgRuleOptionPrefix(uiOptionId) | ||||
|     U32 uiOptionId | ||||
| cfgRuleOptionPrefix(optionId) | ||||
|     U32 optionId | ||||
|  | ||||
| bool | ||||
| cfgRuleOptionRequired(uiCommandId, uiOptionId) | ||||
|     U32 uiCommandId | ||||
|     U32 uiOptionId | ||||
| cfgRuleOptionRequired(commandId, optionId) | ||||
|     U32 commandId | ||||
|     U32 optionId | ||||
|  | ||||
| const char * | ||||
| cfgRuleOptionSection(uiOptionId) | ||||
|     U32 uiOptionId | ||||
| cfgRuleOptionSection(optionId) | ||||
|     U32 optionId | ||||
|  | ||||
| bool | ||||
| cfgRuleOptionSecure(uiOptionId) | ||||
|     U32 uiOptionId | ||||
| cfgRuleOptionSecure(optionId) | ||||
|     U32 optionId | ||||
|  | ||||
| I32 | ||||
| cfgRuleOptionType(uiOptionId); | ||||
|     U32 uiOptionId | ||||
| cfgRuleOptionType(optionId); | ||||
|     U32 optionId | ||||
|  | ||||
| bool | ||||
| cfgRuleOptionValid(uiCommandId, uiOptionId) | ||||
|     U32 uiCommandId | ||||
|     U32 uiOptionId | ||||
| cfgRuleOptionValid(commandId, optionId) | ||||
|     U32 commandId | ||||
|     U32 optionId | ||||
|  | ||||
| U32 | ||||
| cfgOptionTotal() | ||||
|  | ||||
| bool | ||||
| cfgRuleOptionValueHash(uiOptionId) | ||||
|     U32 uiOptionId | ||||
| cfgRuleOptionValueHash(optionId) | ||||
|     U32 optionId | ||||
|   | ||||
| @@ -5,24 +5,39 @@ | ||||
| MODULE = pgBackRest::LibC PACKAGE = pgBackRest::LibC | ||||
|  | ||||
| U16 | ||||
| pageChecksum(page, blkno, pageSize) | ||||
| pageChecksum(page, blockNo, pageSize) | ||||
|     const char *page | ||||
|     U32 blkno | ||||
|     U32 blockNo | ||||
|     U32 pageSize | ||||
| CODE: | ||||
|     RETVAL = pageChecksum( | ||||
|         (const unsigned char *)page, blockNo, pageSize); | ||||
| OUTPUT: | ||||
|     RETVAL | ||||
|  | ||||
| bool | ||||
| pageChecksumTest(szPage, uiBlockNo, uiPageSize, uiIgnoreWalId, uiIgnoreWalOffset) | ||||
|     const char *szPage | ||||
|     U32 uiBlockNo | ||||
|     U32 uiPageSize | ||||
|     U32 uiIgnoreWalId | ||||
|     U32 uiIgnoreWalOffset | ||||
| pageChecksumTest(page, blockNo, pageSize, ignoreWalId, ignoreWalOffset) | ||||
|     const char *page | ||||
|     U32 blockNo | ||||
|     U32 pageSize | ||||
|     U32 ignoreWalId | ||||
|     U32 ignoreWalOffset | ||||
| CODE: | ||||
|     RETVAL = pageChecksumTest( | ||||
|         (const unsigned char *)page, blockNo, pageSize, ignoreWalId, ignoreWalOffset); | ||||
| OUTPUT: | ||||
|     RETVAL | ||||
|  | ||||
| bool | ||||
| pageChecksumBufferTest(szPageBuffer, uiBufferSize, uiBlockNoStart, uiPageSize, uiIgnoreWalId, uiIgnoreWalOffset) | ||||
|     const char *szPageBuffer | ||||
|     U32 uiBufferSize | ||||
|     U32 uiBlockNoStart | ||||
|     U32 uiPageSize | ||||
|     U32 uiIgnoreWalId | ||||
|     U32 uiIgnoreWalOffset | ||||
| pageChecksumBufferTest(pageBuffer, pageBufferSize, blockNoBegin, pageSize, ignoreWalId, ignoreWalOffset) | ||||
|     const char *pageBuffer | ||||
|     U32 pageBufferSize | ||||
|     U32 blockNoBegin | ||||
|     U32 pageSize | ||||
|     U32 ignoreWalId | ||||
|     U32 ignoreWalOffset | ||||
| CODE: | ||||
|     RETVAL = pageChecksumBufferTest( | ||||
|         (const unsigned char *)pageBuffer, pageBufferSize, blockNoBegin, pageSize, ignoreWalId, ignoreWalOffset); | ||||
| OUTPUT: | ||||
|     RETVAL | ||||
|   | ||||
| @@ -1,31 +1,30 @@ | ||||
| /*********************************************************************************************************************************** | ||||
| Common Types | ||||
| ***********************************************************************************************************************************/ | ||||
| #ifndef TYPE_H | ||||
| #define TYPE_H | ||||
|  | ||||
| #include "EXTERN.h" | ||||
| #include "perl.h" | ||||
| /*********************************************************************************************************************************** | ||||
| Include true/false | ||||
| ***********************************************************************************************************************************/ | ||||
| #include <stdbool.h> | ||||
|  | ||||
| /*********************************************************************************************************************************** | ||||
| Older compilers do not define true/false | ||||
| Include NULL | ||||
| ***********************************************************************************************************************************/ | ||||
| #ifndef false | ||||
|     #define false 0 | ||||
| #endif | ||||
|  | ||||
| #ifndef true | ||||
|     #define true 1 | ||||
| #endif | ||||
| #include <stdio.h> | ||||
|  | ||||
| /*********************************************************************************************************************************** | ||||
| Define integer types based on Perl portability | ||||
| Define standard integer types for portability | ||||
| ***********************************************************************************************************************************/ | ||||
| typedef U8 uint8;       /* ==  8 bits */ | ||||
| typedef U16 uint16;     /* == 16 bits */ | ||||
| typedef U32 uint32;     /* == 32 bits */ | ||||
| typedef UV uint64;      /* == 64 bits */ | ||||
| #include <stdint.h> | ||||
|  | ||||
| typedef I8 int8;        /* ==  8 bits */ | ||||
| typedef I16 int16;      /* == 16 bits */ | ||||
| typedef I32 int32;      /* == 32 bits */ | ||||
| typedef IV int64;       /* == 64 bits */ | ||||
| typedef uint16_t uint16; | ||||
| typedef uint32_t uint32; | ||||
| typedef uint64_t uint64; | ||||
|  | ||||
| typedef int16_t int16; | ||||
| typedef int32_t int32; | ||||
| typedef int64_t int64; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| # Query Configuration Settings | ||||
| # Command and Option Configuration | ||||
|  | ||||
| ## cfgOptionIndexTotal | ||||
|  | ||||
| @@ -8,8 +8,8 @@ Total index values allowed. | ||||
|  | ||||
| This function is valid when `cfgRuleOptionValid()` = `true`. Permutations that return `1` are excluded for brevity. | ||||
|  | ||||
| | Function | uiOptionId | Result | | ||||
| | -------- | ---------- | ------ | | ||||
| | Function | optionId | Result | | ||||
| | -------- | -------- | ------ | | ||||
| | cfgOptionIndexTotal | `CFGOPT_DB1_CMD` | `8` | | ||||
| | cfgOptionIndexTotal | `CFGOPT_DB1_CONFIG` | `8` | | ||||
| | cfgOptionIndexTotal | `CFGOPT_DB1_HOST` | `8` | | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| /*********************************************************************************************************************************** | ||||
| Command and Option Rules | ||||
| Command and Option Configuration | ||||
| ***********************************************************************************************************************************/ | ||||
| #include "LibC.h" | ||||
| #include "config/config.h" | ||||
|  | ||||
| #include "config.auto.c" | ||||
|   | ||||
| @@ -1,3 +1,6 @@ | ||||
| /*********************************************************************************************************************************** | ||||
| Command and Option Configuration | ||||
| ***********************************************************************************************************************************/ | ||||
| #ifndef CONFIG_H | ||||
| #define CONFIG_H | ||||
|  | ||||
| @@ -7,8 +10,8 @@ | ||||
| /*********************************************************************************************************************************** | ||||
| Functions | ||||
| ***********************************************************************************************************************************/ | ||||
| const char *cfgCommandName(uint32 uiCommandId); | ||||
| int32 cfgOptionIndexTotal(uint32 uiOptionId); | ||||
| const char *cfgOptionName(uint32 uiCommandId); | ||||
| const char *cfgCommandName(int commandId); | ||||
| int cfgOptionIndexTotal(int optionId); | ||||
| const char *cfgOptionName(int commandId); | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| # Parse Configuration Settings | ||||
| # Command and Option Configuration Rules | ||||
|  | ||||
| ## cfgRuleOptionAllowList | ||||
|  | ||||
| @@ -8,8 +8,8 @@ Is there an allow list for this option? | ||||
|  | ||||
| This function is valid when `cfgRuleOptionValid()` = `true`. Permutations that return `false` are excluded for brevity. | ||||
|  | ||||
| | Function | uiCommandId | uiOptionId | Result | | ||||
| | -------- | ----------- | ---------- | ------ | | ||||
| | Function | commandId | optionId | Result | | ||||
| | -------- | --------- | -------- | ------ | | ||||
| | cfgRuleOptionAllowList | _\<ANY\>_ | `CFGOPT_BUFFER_SIZE` | `true` | | ||||
| | cfgRuleOptionAllowList | _\<ANY\>_ | `CFGOPT_LOG_LEVEL_CONSOLE` | `true` | | ||||
| | cfgRuleOptionAllowList | _\<ANY\>_ | `CFGOPT_LOG_LEVEL_FILE` | `true` | | ||||
| @@ -28,8 +28,8 @@ Get value from allowed list. | ||||
|  | ||||
| This function is valid when `cfgRuleOptionAllowList()` = `true`. | ||||
|  | ||||
| | Function | uiCommandId | uiOptionId | uiValueId | Result | | ||||
| | -------- | ----------- | ---------- | --------- | ------ | | ||||
| | Function | commandId | optionId | valueId | Result | | ||||
| | -------- | --------- | -------- | ------- | ------ | | ||||
| | cfgRuleOptionAllowListValue | `CFGCMD_BACKUP` | `CFGOPT_TYPE` | `0` | `"full"` | | ||||
| | cfgRuleOptionAllowListValue | `CFGCMD_BACKUP` | `CFGOPT_TYPE` | `1` | `"diff"` | | ||||
| | cfgRuleOptionAllowListValue | `CFGCMD_BACKUP` | `CFGOPT_TYPE` | `2` | `"incr"` | | ||||
| @@ -96,8 +96,8 @@ Total number of values allowed. | ||||
|  | ||||
| This function is valid when `cfgRuleOptionAllowList()` = `true`. | ||||
|  | ||||
| | Function | uiCommandId | uiOptionId | Result | | ||||
| | -------- | ----------- | ---------- | ------ | | ||||
| | Function | commandId | optionId | Result | | ||||
| | -------- | --------- | -------- | ------ | | ||||
| | cfgRuleOptionAllowListValueTotal | `CFGCMD_BACKUP` | `CFGOPT_TYPE` | `3` | | ||||
| | cfgRuleOptionAllowListValueTotal | `CFGCMD_LOCAL` | `CFGOPT_TYPE` | `2` | | ||||
| | cfgRuleOptionAllowListValueTotal | `CFGCMD_REMOTE` | `CFGOPT_TYPE` | `2` | | ||||
| @@ -119,8 +119,8 @@ Is the option constrained to a range? | ||||
|  | ||||
| This function is valid when `cfgRuleOptionValid()` = `true`. Permutations that return `false` are excluded for brevity. | ||||
|  | ||||
| | Function | uiCommandId | uiOptionId | Result | | ||||
| | -------- | ----------- | ---------- | ------ | | ||||
| | Function | commandId | optionId | Result | | ||||
| | -------- | --------- | -------- | ------ | | ||||
| | cfgRuleOptionAllowRange | _\<ANY\>_ | `CFGOPT_ARCHIVE_TIMEOUT` | `true` | | ||||
| | cfgRuleOptionAllowRange | _\<ANY\>_ | `CFGOPT_COMPRESS_LEVEL` | `true` | | ||||
| | cfgRuleOptionAllowRange | _\<ANY\>_ | `CFGOPT_COMPRESS_LEVEL_NETWORK` | `true` | | ||||
| @@ -139,8 +139,8 @@ Maximum value allowed (if the option is constrained to a range). | ||||
|  | ||||
| This function is valid when `cfgRuleOptionAllowRange()` = `true`. | ||||
|  | ||||
| | Function | uiCommandId | uiOptionId | Result | | ||||
| | -------- | ----------- | ---------- | ------ | | ||||
| | Function | commandId | optionId | Result | | ||||
| | -------- | --------- | -------- | ------ | | ||||
| | cfgRuleOptionAllowRangeMax | _\<ANY\>_ | `CFGOPT_ARCHIVE_TIMEOUT` | `86400` | | ||||
| | cfgRuleOptionAllowRangeMax | _\<ANY\>_ | `CFGOPT_COMPRESS_LEVEL` | `9` | | ||||
| | cfgRuleOptionAllowRangeMax | _\<ANY\>_ | `CFGOPT_COMPRESS_LEVEL_NETWORK` | `9` | | ||||
| @@ -159,8 +159,8 @@ Minimum value allowed (if the option is constrained to a range). | ||||
|  | ||||
| This function is valid when `cfgRuleOptionAllowRange()` = `true`. | ||||
|  | ||||
| | Function | uiCommandId | uiOptionId | Result | | ||||
| | -------- | ----------- | ---------- | ------ | | ||||
| | Function | commandId | optionId | Result | | ||||
| | -------- | --------- | -------- | ------ | | ||||
| | cfgRuleOptionAllowRangeMin | _\<ANY\>_ | `CFGOPT_ARCHIVE_TIMEOUT` | `0.1` | | ||||
| | cfgRuleOptionAllowRangeMin | _\<ANY\>_ | `CFGOPT_COMPRESS_LEVEL` | `0` | | ||||
| | cfgRuleOptionAllowRangeMin | _\<ANY\>_ | `CFGOPT_COMPRESS_LEVEL_NETWORK` | `0` | | ||||
| @@ -179,8 +179,8 @@ Default value. | ||||
|  | ||||
| This function is valid when `cfgRuleOptionValid()` = `true`. Permutations that return `NULL` are excluded for brevity. | ||||
|  | ||||
| | Function | uiCommandId | uiOptionId | Result | | ||||
| | -------- | ----------- | ---------- | ------ | | ||||
| | Function | commandId | optionId | Result | | ||||
| | -------- | --------- | -------- | ------ | | ||||
| | cfgRuleOptionDefault | `CFGCMD_BACKUP` | `CFGOPT_TYPE` | `"incr"` | | ||||
| | cfgRuleOptionDefault | `CFGCMD_RESTORE` | `CFGOPT_TYPE` | `"default"` | | ||||
| | cfgRuleOptionDefault | _\<ANY\>_ | `CFGOPT_ARCHIVE_ASYNC` | `"0"` | | ||||
| @@ -259,8 +259,8 @@ Does the option have a dependency on another option? | ||||
|  | ||||
| This function is valid when `cfgRuleOptionValid()` = `true`. Permutations that return `false` are excluded for brevity. | ||||
|  | ||||
| | Function | uiCommandId | uiOptionId | Result | | ||||
| | -------- | ----------- | ---------- | ------ | | ||||
| | Function | commandId | optionId | Result | | ||||
| | -------- | --------- | -------- | ------ | | ||||
| | cfgRuleOptionDepend | `CFGCMD_BACKUP` | `CFGOPT_FORCE` | `true` | | ||||
| | cfgRuleOptionDepend | _\<ANY\>_ | `CFGOPT_ARCHIVE_CHECK` | `true` | | ||||
| | cfgRuleOptionDepend | _\<ANY\>_ | `CFGOPT_ARCHIVE_COPY` | `true` | | ||||
| @@ -326,8 +326,8 @@ Name of the option that this option depends in order to be set. | ||||
|  | ||||
| This function is valid when `cfgRuleOptionDepend()` = `true`. | ||||
|  | ||||
| | Function | uiCommandId | uiOptionId | Result | | ||||
| | -------- | ----------- | ---------- | ------ | | ||||
| | Function | commandId | optionId | Result | | ||||
| | -------- | --------- | -------- | ------ | | ||||
| | cfgRuleOptionDependOption | _\<ANY\>_ | `CFGOPT_ARCHIVE_CHECK` | `CFGOPT_ONLINE` | | ||||
| | cfgRuleOptionDependOption | _\<ANY\>_ | `CFGOPT_ARCHIVE_COPY` | `CFGOPT_ARCHIVE_CHECK` | | ||||
| | cfgRuleOptionDependOption | _\<ANY\>_ | `CFGOPT_BACKUP_CMD` | `CFGOPT_BACKUP_HOST` | | ||||
| @@ -393,8 +393,8 @@ The depend option must have one of these values before this option is set. | ||||
|  | ||||
| This function is valid when `cfgRuleOptionDepend()` = `true`. | ||||
|  | ||||
| | Function | uiCommandId | uiOptionId | uiValueId | Result | | ||||
| | -------- | ----------- | ---------- | --------- | ------ | | ||||
| | Function | commandId | optionId | valueId | Result | | ||||
| | -------- | --------- | -------- | ------- | ------ | | ||||
| | cfgRuleOptionDependValue | _\<ANY\>_ | `CFGOPT_ARCHIVE_CHECK` | `0` | `"1"` | | ||||
| | cfgRuleOptionDependValue | _\<ANY\>_ | `CFGOPT_ARCHIVE_COPY` | `0` | `"1"` | | ||||
| | cfgRuleOptionDependValue | _\<ANY\>_ | `CFGOPT_FORCE` | `0` | `"0"` | | ||||
| @@ -435,8 +435,8 @@ Total depend values for this option. | ||||
|  | ||||
| This function is valid when `cfgRuleOptionDepend()` = `true`. | ||||
|  | ||||
| | Function | uiCommandId | uiOptionId | Result | | ||||
| | -------- | ----------- | ---------- | ------ | | ||||
| | Function | commandId | optionId | Result | | ||||
| | -------- | --------- | -------- | ------ | | ||||
| | cfgRuleOptionDependValueTotal | _\<ANY\>_ | `CFGOPT_ARCHIVE_CHECK` | `1` | | ||||
| | cfgRuleOptionDependValueTotal | _\<ANY\>_ | `CFGOPT_ARCHIVE_COPY` | `1` | | ||||
| | cfgRuleOptionDependValueTotal | _\<ANY\>_ | `CFGOPT_BACKUP_CMD` | `0` | | ||||
| @@ -502,8 +502,8 @@ Some clue as to what value the user should provide when the option is missing bu | ||||
|  | ||||
| This function is valid when `cfgRuleOptionValid()` = `true`. Permutations that return `NULL` are excluded for brevity. | ||||
|  | ||||
| | Function | uiCommandId | uiOptionId | Result | | ||||
| | -------- | ----------- | ---------- | ------ | | ||||
| | Function | commandId | optionId | Result | | ||||
| | -------- | --------- | -------- | ------ | | ||||
| | cfgRuleOptionHint | _\<ANY\>_ | `CFGOPT_DB1_PATH` | `"does this stanza exist?"` | | ||||
| | cfgRuleOptionHint | _\<ANY\>_ | `CFGOPT_DB2_PATH` | `"does this stanza exist?"` | | ||||
| | cfgRuleOptionHint | _\<ANY\>_ | `CFGOPT_DB3_PATH` | `"does this stanza exist?"` | | ||||
| @@ -521,8 +521,8 @@ Alternate name for the option primarily used for deprecated names. | ||||
|  | ||||
| This function is valid when `cfgRuleOptionValid()` = `true`. Permutations that return `NULL` are excluded for brevity. | ||||
|  | ||||
| | Function | uiOptionId | Result | | ||||
| | -------- | ---------- | ------ | | ||||
| | Function | optionId | Result | | ||||
| | -------- | -------- | ------ | | ||||
| | cfgRuleOptionNameAlt | `CFGOPT_DB1_CMD` | `"db-cmd"` | | ||||
| | cfgRuleOptionNameAlt | `CFGOPT_DB1_CONFIG` | `"db-config"` | | ||||
| | cfgRuleOptionNameAlt | `CFGOPT_DB1_HOST` | `"db-host"` | | ||||
| @@ -541,8 +541,8 @@ Can the boolean option be negated? | ||||
|  | ||||
| Permutations that return `false` are excluded for brevity. | ||||
|  | ||||
| | Function | uiOptionId | Result | | ||||
| | -------- | ---------- | ------ | | ||||
| | Function | optionId | Result | | ||||
| | -------- | -------- | ------ | | ||||
| | cfgRuleOptionNegate | `CFGOPT_ARCHIVE_ASYNC` | `true` | | ||||
| | cfgRuleOptionNegate | `CFGOPT_ARCHIVE_CHECK` | `true` | | ||||
| | cfgRuleOptionNegate | `CFGOPT_ARCHIVE_COPY` | `true` | | ||||
| @@ -568,8 +568,8 @@ Prefix when the option has an index > 1 (e.g. "db"). | ||||
|  | ||||
| Permutations that return `NULL` are excluded for brevity. | ||||
|  | ||||
| | Function | uiOptionId | Result | | ||||
| | -------- | ---------- | ------ | | ||||
| | Function | optionId | Result | | ||||
| | -------- | -------- | ------ | | ||||
| | cfgRuleOptionPrefix | `CFGOPT_DB1_CMD` | `"db"` | | ||||
| | cfgRuleOptionPrefix | `CFGOPT_DB1_CONFIG` | `"db"` | | ||||
| | cfgRuleOptionPrefix | `CFGOPT_DB1_HOST` | `"db"` | | ||||
| @@ -643,8 +643,8 @@ Is the option required? | ||||
|  | ||||
| This function is valid when `cfgRuleOptionValid()` = `true`. Permutations that return `false` are excluded for brevity. | ||||
|  | ||||
| | Function | uiCommandId | uiOptionId | Result | | ||||
| | -------- | ----------- | ---------- | ------ | | ||||
| | Function | commandId | optionId | Result | | ||||
| | -------- | --------- | -------- | ------ | | ||||
| | cfgRuleOptionRequired | `CFGCMD_ARCHIVE_GET` | `CFGOPT_STANZA` | `true` | | ||||
| | cfgRuleOptionRequired | `CFGCMD_ARCHIVE_PUSH` | `CFGOPT_STANZA` | `true` | | ||||
| | cfgRuleOptionRequired | `CFGCMD_BACKUP` | `CFGOPT_DB1_PATH` | `true` | | ||||
| @@ -720,8 +720,8 @@ Section that the option belongs in, NULL means command-line only. | ||||
|  | ||||
| Permutations that return `NULL` are excluded for brevity. | ||||
|  | ||||
| | Function | uiOptionId | Result | | ||||
| | -------- | ---------- | ------ | | ||||
| | Function | optionId | Result | | ||||
| | -------- | -------- | ------ | | ||||
| | cfgRuleOptionSection | `CFGOPT_ARCHIVE_ASYNC` | `"global"` | | ||||
| | cfgRuleOptionSection | `CFGOPT_ARCHIVE_CHECK` | `"global"` | | ||||
| | cfgRuleOptionSection | `CFGOPT_ARCHIVE_COPY` | `"global"` | | ||||
| @@ -850,8 +850,8 @@ Secure options can never be passed on the commmand-line. | ||||
|  | ||||
| Permutations that return `false` are excluded for brevity. | ||||
|  | ||||
| | Function | uiOptionId | Result | | ||||
| | -------- | ---------- | ------ | | ||||
| | Function | optionId | Result | | ||||
| | -------- | -------- | ------ | | ||||
| | cfgRuleOptionSecure | `CFGOPT_REPO_S3_KEY` | `true` | | ||||
| | cfgRuleOptionSecure | `CFGOPT_REPO_S3_KEY_SECRET` | `true` | | ||||
|  | ||||
| @@ -861,8 +861,8 @@ Secure options can never be passed on the commmand-line. | ||||
|  | ||||
| ### Truth Table: | ||||
|  | ||||
| | Function | uiOptionId | Result | | ||||
| | -------- | ---------- | ------ | | ||||
| | Function | optionId | Result | | ||||
| | -------- | -------- | ------ | | ||||
| | cfgRuleOptionType | `CFGOPT_ARCHIVE_ASYNC` | `CFGOPTDEF_TYPE_BOOLEAN` | | ||||
| | cfgRuleOptionType | `CFGOPT_ARCHIVE_CHECK` | `CFGOPTDEF_TYPE_BOOLEAN` | | ||||
| | cfgRuleOptionType | `CFGOPT_ARCHIVE_COPY` | `CFGOPTDEF_TYPE_BOOLEAN` | | ||||
| @@ -1009,8 +1009,8 @@ Is the option valid for this command? | ||||
|  | ||||
| Permutations that return `false` are excluded for brevity. | ||||
|  | ||||
| | Function | uiCommandId | uiOptionId | Result | | ||||
| | -------- | ----------- | ---------- | ------ | | ||||
| | Function | commandId | optionId | Result | | ||||
| | -------- | --------- | -------- | ------ | | ||||
| | cfgRuleOptionValid | `CFGCMD_ARCHIVE_GET` | `CFGOPT_BACKUP_CMD` | `true` | | ||||
| | cfgRuleOptionValid | `CFGCMD_ARCHIVE_GET` | `CFGOPT_BACKUP_CONFIG` | `true` | | ||||
| | cfgRuleOptionValid | `CFGCMD_ARCHIVE_GET` | `CFGOPT_BACKUP_HOST` | `true` | | ||||
| @@ -1924,8 +1924,8 @@ Is the option a true hash or just a list of keys? | ||||
|  | ||||
| Permutations that return `false` are excluded for brevity. | ||||
|  | ||||
| | Function | uiOptionId | Result | | ||||
| | -------- | ---------- | ------ | | ||||
| | Function | optionId | Result | | ||||
| | -------- | -------- | ------ | | ||||
| | cfgRuleOptionValueHash | `CFGOPT_LINK_MAP` | `true` | | ||||
| | cfgRuleOptionValueHash | `CFGOPT_RECOVERY_OPTION` | `true` | | ||||
| | cfgRuleOptionValueHash | `CFGOPT_TABLESPACE_MAP` | `true` | | ||||
|   | ||||
| @@ -1,6 +1,8 @@ | ||||
| /*********************************************************************************************************************************** | ||||
| Command and Option Rules | ||||
| Command and Option Configuration Rules | ||||
| ***********************************************************************************************************************************/ | ||||
| #include <string.h> | ||||
|  | ||||
| #include "config.h" | ||||
| #include "configRule.h" | ||||
|  | ||||
| @@ -9,7 +11,7 @@ Command and Option Rules | ||||
| /*********************************************************************************************************************************** | ||||
| cfgCommandTotal - total number of commands | ||||
| ***********************************************************************************************************************************/ | ||||
| uint32 | ||||
| int | ||||
| cfgCommandTotal() | ||||
| { | ||||
|     return CFGCMDDEF_TOTAL; | ||||
| @@ -18,7 +20,7 @@ cfgCommandTotal() | ||||
| /*********************************************************************************************************************************** | ||||
| cfgOptionTotal - total number of configuration options | ||||
| ***********************************************************************************************************************************/ | ||||
| uint32 | ||||
| int | ||||
| cfgOptionTotal() | ||||
| { | ||||
|     return CFGOPTDEF_TOTAL; | ||||
| @@ -28,12 +30,12 @@ cfgOptionTotal() | ||||
| cfgRuleOptionAllowListValueValid - check if the value matches a value in the allow list | ||||
| ***********************************************************************************************************************************/ | ||||
| bool | ||||
| cfgRuleOptionAllowListValueValid(uint32 uiCommandId, uint32 uiOptionId, const char *szValue) | ||||
| cfgRuleOptionAllowListValueValid(int commandId, int optionId, const char *value) | ||||
| { | ||||
|     if (szValue != NULL) | ||||
|     if (value != NULL) | ||||
|     { | ||||
|         for (uint32 uiIndex = 0; uiIndex < cfgRuleOptionAllowListValueTotal(uiCommandId, uiOptionId); uiIndex++) | ||||
|             if (strcmp(szValue, cfgRuleOptionAllowListValue(uiCommandId, uiOptionId, uiIndex)) == 0) | ||||
|         for (int valueIdx = 0; valueIdx < cfgRuleOptionAllowListValueTotal(commandId, optionId); valueIdx++) | ||||
|             if (strcmp(value, cfgRuleOptionAllowListValue(commandId, optionId, valueIdx)) == 0) | ||||
|                 return true; | ||||
|     } | ||||
|  | ||||
| @@ -44,12 +46,12 @@ cfgRuleOptionAllowListValueValid(uint32 uiCommandId, uint32 uiOptionId, const ch | ||||
| cfgRuleOptionDependValueValid - check if the value matches a value in the allow list | ||||
| ***********************************************************************************************************************************/ | ||||
| bool | ||||
| cfgRuleOptionDependValueValid(uint32 uiCommandId, uint32 uiOptionId, const char *szValue) | ||||
| cfgRuleOptionDependValueValid(int commandId, int optionId, const char *value) | ||||
| { | ||||
|     if (szValue != NULL) | ||||
|     if (value != NULL) | ||||
|     { | ||||
|         for (uint32 uiIndex = 0; uiIndex < cfgRuleOptionDependValueTotal(uiCommandId, uiOptionId); uiIndex++) | ||||
|             if (strcmp(szValue, cfgRuleOptionDependValue(uiCommandId, uiOptionId, uiIndex)) == 0) | ||||
|         for (int valueIdx = 0; valueIdx < cfgRuleOptionDependValueTotal(commandId, optionId); valueIdx++) | ||||
|             if (strcmp(value, cfgRuleOptionDependValue(commandId, optionId, valueIdx)) == 0) | ||||
|                 return true; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -1,3 +1,6 @@ | ||||
| /*********************************************************************************************************************************** | ||||
| Command and Option Configuration Rules | ||||
| ***********************************************************************************************************************************/ | ||||
| #ifndef CONFIG_RULE_H | ||||
| #define CONFIG_RULE_H | ||||
|  | ||||
| @@ -6,35 +9,35 @@ | ||||
| /*********************************************************************************************************************************** | ||||
| Functions | ||||
| ***********************************************************************************************************************************/ | ||||
| int32 cfgCommandId(const char *szCommandName); | ||||
| int32 cfgOptionId(const char *szOptionName); | ||||
| bool cfgRuleOptionAllowListValueValid(uint32 uiCommandId, uint32 uiOptionId, const char *szValue); | ||||
| bool cfgRuleOptionDependValueValid(uint32 uiCommandId, uint32 uiOptionId, const char *szValue); | ||||
| uint32 cfgOptionTotal(); | ||||
| int cfgCommandId(const char *commandName); | ||||
| int cfgOptionId(const char *optionName); | ||||
| bool cfgRuleOptionAllowListValueValid(int commandId, int optionId, const char *value); | ||||
| bool cfgRuleOptionDependValueValid(int commandId, int optionId, const char *value); | ||||
| int cfgOptionTotal(); | ||||
|  | ||||
| /*********************************************************************************************************************************** | ||||
| Auto-Generated Functions | ||||
| ***********************************************************************************************************************************/ | ||||
| bool cfgRuleOptionAllowList(uint32 uiCommandId, uint32 uiOptionId); | ||||
| const char * cfgRuleOptionAllowListValue(uint32 uiCommandId, uint32 uiOptionId, uint32 uiValueId); | ||||
| int32 cfgRuleOptionAllowListValueTotal(uint32 uiCommandId, uint32 uiOptionId); | ||||
| bool cfgRuleOptionAllowRange(uint32 uiCommandId, uint32 uiOptionId); | ||||
| double cfgRuleOptionAllowRangeMax(uint32 uiCommandId, uint32 uiOptionId); | ||||
| double cfgRuleOptionAllowRangeMin(uint32 uiCommandId, uint32 uiOptionId); | ||||
| const char * cfgRuleOptionDefault(uint32 uiCommandId, uint32 uiOptionId); | ||||
| bool cfgRuleOptionDepend(uint32 uiCommandId, uint32 uiOptionId); | ||||
| int32 cfgRuleOptionDependOption(uint32 uiCommandId, uint32 uiOptionId); | ||||
| const char *cfgRuleOptionDependValue(uint32 uiCommandId, uint32 uiOptionId, uint32 uiValueId); | ||||
| int32 cfgRuleOptionDependValueTotal(uint32 uiCommandId, uint32 uiOptionId); | ||||
| const char *cfgRuleOptionHint(uint32 uiCommandId, uint32 uiOptionId); | ||||
| const char *cfgRuleOptionNameAlt(uint32 uiOptionId); | ||||
| bool cfgRuleOptionNegate(uint32 uiOptionId); | ||||
| const char *cfgRuleOptionPrefix(uint32 uiOptionId); | ||||
| bool cfgRuleOptionRequired(uint32 uiCommandId, uint32 uiOptionId); | ||||
| const char *cfgRuleOptionSection(uint32 uiOptionId); | ||||
| bool cfgRuleOptionSecure(uint32 uiOptionId); | ||||
| int32 cfgRuleOptionType(uint32 uiOptionId); | ||||
| bool cfgRuleOptionValid(uint32 uiCommandId, uint32 uiOptionId); | ||||
| bool cfgRuleOptionValueHash(uint32 uiOptionId); | ||||
| bool cfgRuleOptionAllowList(int commandId, int optionId); | ||||
| const char * cfgRuleOptionAllowListValue(int commandId, int optionId, int valueId); | ||||
| int cfgRuleOptionAllowListValueTotal(int commandId, int optionId); | ||||
| bool cfgRuleOptionAllowRange(int commandId, int optionId); | ||||
| double cfgRuleOptionAllowRangeMax(int commandId, int optionId); | ||||
| double cfgRuleOptionAllowRangeMin(int commandId, int optionId); | ||||
| const char * cfgRuleOptionDefault(int commandId, int optionId); | ||||
| bool cfgRuleOptionDepend(int commandId, int optionId); | ||||
| int cfgRuleOptionDependOption(int commandId, int optionId); | ||||
| const char *cfgRuleOptionDependValue(int commandId, int optionId, int valueId); | ||||
| int cfgRuleOptionDependValueTotal(int commandId, int optionId); | ||||
| const char *cfgRuleOptionHint(int commandId, int optionId); | ||||
| const char *cfgRuleOptionNameAlt(int optionId); | ||||
| bool cfgRuleOptionNegate(int optionId); | ||||
| const char *cfgRuleOptionPrefix(int optionId); | ||||
| bool cfgRuleOptionRequired(int commandId, int optionId); | ||||
| const char *cfgRuleOptionSection(int optionId); | ||||
| bool cfgRuleOptionSecure(int optionId); | ||||
| int cfgRuleOptionType(int optionId); | ||||
| bool cfgRuleOptionValid(int commandId, int optionId); | ||||
| bool cfgRuleOptionValueHash(int optionId); | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,7 +1,5 @@ | ||||
| /*********************************************************************************************************************************** | ||||
| pageChecksum.c | ||||
|  | ||||
| Checksum implementation for data pages. | ||||
| Checksum Implementation for Data Pages | ||||
|  | ||||
| Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group | ||||
| Portions Copyright (c) 1994, Regents of the University of California | ||||
| @@ -64,15 +62,20 @@ calculate a subset of the columns at a time and perform multiple passes to avoid | ||||
| is not used. Current coding also assumes that the compiler has the ability to unroll the inner loop to avoid loop overhead and | ||||
| minimize register spilling. For less sophisticated compilers it might be beneficial to manually unroll the inner loop. | ||||
| ***********************************************************************************************************************************/ | ||||
| #include "LibC.h" | ||||
| #include "EXTERN.h" | ||||
| #include "perl.h" | ||||
|  | ||||
| #include <string.h> | ||||
|  | ||||
| #include "common/type.h" | ||||
|  | ||||
| /*********************************************************************************************************************************** | ||||
| For historical reasons, the 64-bit LSN value is stored as two 32-bit values. | ||||
| ***********************************************************************************************************************************/ | ||||
| typedef struct | ||||
| { | ||||
|     uint32 walid;      /* high bits */ | ||||
|     uint32 xrecoff;     /* low bits */ | ||||
|     uint32 walid;                                                   // high bits | ||||
|     uint32 xrecoff;                                                 // low bits | ||||
| } PageWalRecPtr; | ||||
|  | ||||
| /*********************************************************************************************************************************** | ||||
| @@ -104,9 +107,9 @@ typedef struct PageHeaderData | ||||
| typedef PageHeaderData *PageHeader; | ||||
|  | ||||
| /*********************************************************************************************************************************** | ||||
| pageChecksumBlock | ||||
| pageChecksumBlock - block checksum algorithm | ||||
|  | ||||
| Block checksum algorithm.  The data argument must be aligned on a 4-byte boundary. | ||||
| The data argument must be aligned on a 4-byte boundary. | ||||
| ***********************************************************************************************************************************/ | ||||
| // number of checksums to calculate in parallel | ||||
| #define N_SUMS 32 | ||||
| @@ -115,7 +118,7 @@ Block checksum algorithm.  The data argument must be aligned on a 4-byte boundar | ||||
| #define FNV_PRIME 16777619 | ||||
|  | ||||
| // Base offsets to initialize each of the parallel FNV hashes into a different initial state. | ||||
| static const uint32 uiyChecksumBaseOffsets[N_SUMS] = | ||||
| static const uint32 checksumBaseOffsets[N_SUMS] = | ||||
| { | ||||
|     0x5B1F36E9, 0xB8525960, 0x02AB50AA, 0x1DE66D2A, 0x79FF467A, 0x9BB9F8A3, 0x217E7CD2, 0x83E13D2C, | ||||
|     0xF8D4474F, 0xE39EB970, 0x42C6AE16, 0x993216FA, 0x7B093B5D, 0x98DAFF3C, 0xF718902A, 0x0B1C9CDB, | ||||
| @@ -124,107 +127,101 @@ static const uint32 uiyChecksumBaseOffsets[N_SUMS] = | ||||
| }; | ||||
|  | ||||
| // Calculate one round of the checksum. | ||||
| #define CHECKSUM_COMP(uiChecksum, uiValue) \ | ||||
| #define CHECKSUM_COMP(checksum, value) \ | ||||
| do { \ | ||||
|     uint32 uiTemp = (uiChecksum) ^ (uiValue); \ | ||||
|     (uiChecksum) = uiTemp * FNV_PRIME ^ (uiTemp >> 17); \ | ||||
|     uint32 temp = (checksum) ^ (value); \ | ||||
|     (checksum) = temp * FNV_PRIME ^ (temp >> 17); \ | ||||
| } while (0) | ||||
|  | ||||
| static uint32 | ||||
| pageChecksumBlock(const char *szData, uint32 uiSize) | ||||
| pageChecksumBlock(const unsigned char *data, uint32 size) | ||||
| { | ||||
|     uint32 uiySums[N_SUMS]; | ||||
|     uint32 (*puiyDataArray)[N_SUMS] = (uint32 (*)[N_SUMS])szData; | ||||
|     uint32 uiResult = 0; | ||||
|     uint32 sums[N_SUMS]; | ||||
|     uint32 (*dataArray)[N_SUMS] = (uint32 (*)[N_SUMS])data; | ||||
|     uint32 result = 0; | ||||
|     uint32 i, j; | ||||
|  | ||||
|     /* initialize partial checksums to their corresponding offsets */ | ||||
|     memcpy(uiySums, uiyChecksumBaseOffsets, sizeof(uiyChecksumBaseOffsets)); | ||||
|     memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets)); | ||||
|  | ||||
|     /* main checksum calculation */ | ||||
|     for (i = 0; i < uiSize / sizeof(uint32) / N_SUMS; i++) | ||||
|     for (i = 0; i < size / sizeof(uint32) / N_SUMS; i++) | ||||
|         for (j = 0; j < N_SUMS; j++) | ||||
|             CHECKSUM_COMP(uiySums[j], puiyDataArray[i][j]); | ||||
|             CHECKSUM_COMP(sums[j], dataArray[i][j]); | ||||
|  | ||||
|     /* finally add in two rounds of zeroes for additional mixing */ | ||||
|     for (i = 0; i < 2; i++) | ||||
|         for (j = 0; j < N_SUMS; j++) | ||||
|             CHECKSUM_COMP(uiySums[j], 0); | ||||
|             CHECKSUM_COMP(sums[j], 0); | ||||
|  | ||||
|     // xor fold partial checksums together | ||||
|     for (i = 0; i < N_SUMS; i++) | ||||
|         uiResult ^= uiySums[i]; | ||||
|         result ^= sums[i]; | ||||
|  | ||||
|     return uiResult; | ||||
|     return result; | ||||
| } | ||||
|  | ||||
| /*********************************************************************************************************************************** | ||||
| pageChecksum | ||||
|  | ||||
| Compute the checksum for a Postgres page.  The page must be aligned on a 4-byte boundary. | ||||
| pageChecksum - compute the checksum for a PostgreSQL page | ||||
|  | ||||
| The checksum includes the block number (to detect the case where a page is somehow moved to a different location), the page header | ||||
| (excluding the checksum itself), and the page data. | ||||
| ***********************************************************************************************************************************/ | ||||
| uint16 | ||||
| pageChecksum(const char *szPage, uint32 uiBlockNo, uint32 uiPageSize) | ||||
| pageChecksum(const unsigned char *page, int blockNo, int pageSize) | ||||
| { | ||||
|     // Save pd_checksum and temporarily set it to zero, so that the checksum calculation isn't affected by the old checksum stored | ||||
|     // on the page. Restore it after, because actually updating the checksum is NOT part of the API of this function. | ||||
|     PageHeader pxPageHeader = (PageHeader)szPage; | ||||
|     PageHeader pageHeader = (PageHeader)page; | ||||
|  | ||||
|     uint usOriginalChecksum = pxPageHeader->pd_checksum; | ||||
|     pxPageHeader->pd_checksum = 0; | ||||
|     uint uiChecksum = pageChecksumBlock(szPage, uiPageSize); | ||||
|     pxPageHeader->pd_checksum = usOriginalChecksum; | ||||
|     uint32 originalChecksum = pageHeader->pd_checksum; | ||||
|     pageHeader->pd_checksum = 0; | ||||
|     uint32 checksum = pageChecksumBlock(page, pageSize); | ||||
|     pageHeader->pd_checksum = originalChecksum; | ||||
|  | ||||
|     // Mix in the block number to detect transposed pages | ||||
|     uiChecksum ^= uiBlockNo; | ||||
|     checksum ^= blockNo; | ||||
|  | ||||
|     // Reduce to a uint16 with an offset of one. That avoids checksums of zero, which seems like a good idea. | ||||
|     return (uiChecksum % 65535) + 1; | ||||
|     return (checksum % 65535) + 1; | ||||
| } | ||||
|  | ||||
| /*********************************************************************************************************************************** | ||||
| pageChecksumTest | ||||
|  | ||||
| Test if checksum is valid for a single page. | ||||
| pageChecksumTest - test if checksum is valid for a single page | ||||
| ***********************************************************************************************************************************/ | ||||
| bool | ||||
| pageChecksumTest(const char *szPage, uint32 uiBlockNo, uint32 uiPageSize, uint32 uiIgnoreWalId, uint32 uiIgnoreWalOffset) | ||||
| pageChecksumTest(const unsigned char *page, int blockNo, int pageSize, uint32 ignoreWalId, uint32 ignoreWalOffset) | ||||
| { | ||||
|     return | ||||
|         // This is a new page so don't test checksum | ||||
|         ((PageHeader)szPage)->pd_upper == 0 || | ||||
|         ((PageHeader)page)->pd_upper == 0 || | ||||
|         // LSN is after the backup started so checksum is not tested because pages may be torn | ||||
|         (((PageHeader)szPage)->pd_lsn.walid >= uiIgnoreWalId && ((PageHeader)szPage)->pd_lsn.xrecoff >= uiIgnoreWalOffset) || | ||||
|         (((PageHeader)page)->pd_lsn.walid >= ignoreWalId && ((PageHeader)page)->pd_lsn.xrecoff >= ignoreWalOffset) || | ||||
|         // Checksum is valid | ||||
|         ((PageHeader)szPage)->pd_checksum == pageChecksum(szPage, uiBlockNo, uiPageSize); | ||||
|         ((PageHeader)page)->pd_checksum == pageChecksum(page, blockNo, pageSize); | ||||
| } | ||||
|  | ||||
| /*********************************************************************************************************************************** | ||||
| pageChecksumBufferTest | ||||
|  | ||||
| Test if checksums are valid for all pages in a buffer. | ||||
| pageChecksumBufferTest - test if checksums are valid for all pages in a buffer | ||||
| ***********************************************************************************************************************************/ | ||||
| bool | ||||
| pageChecksumBufferTest( | ||||
|     const char *szPageBuffer, uint32 uiBufferSize, uint32 uiBlockNoStart, uint32 uiPageSize, uint32 uiIgnoreWalId, | ||||
|     uint32 uiIgnoreWalOffset) | ||||
|     const unsigned char *pageBuffer, int pageBufferSize, int blockNoBegin, int pageSize, uint32 ignoreWalId, | ||||
|     uint32 ignoreWalOffset) | ||||
| { | ||||
|     // If the buffer does not represent an even number of pages then error | ||||
|     if (uiBufferSize % uiPageSize != 0 || uiBufferSize / uiPageSize == 0) | ||||
|     if (pageBufferSize % pageSize != 0 || pageBufferSize / pageSize == 0) | ||||
|     { | ||||
|         croak("buffer size %lu, page size %lu are not divisible", uiBufferSize, uiPageSize); | ||||
|         croak("buffer size %lu, page size %lu are not divisible", pageBufferSize, pageSize); | ||||
|     } | ||||
|  | ||||
|     // Loop through all pages in the buffer | ||||
|     for (uint32 uiIndex = 0; uiIndex < uiBufferSize / uiPageSize; uiIndex++) | ||||
|     for (int pageIdx = 0; pageIdx < pageBufferSize / pageSize; pageIdx++) | ||||
|     { | ||||
|         const char *szPage = szPageBuffer + (uiIndex * uiPageSize); | ||||
|         const unsigned char *page = pageBuffer + (pageIdx * pageSize); | ||||
|  | ||||
|         // Return false if the checksums do not match | ||||
|         if (!pageChecksumTest(szPage, uiBlockNoStart + uiIndex, uiPageSize, uiIgnoreWalId, uiIgnoreWalOffset)) | ||||
|         if (!pageChecksumTest(page, blockNoBegin + pageIdx, pageSize, ignoreWalId, ignoreWalOffset)) | ||||
|             return false; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -1,3 +1,6 @@ | ||||
| /*********************************************************************************************************************************** | ||||
| Checksum Implementation for Data Pages | ||||
| ***********************************************************************************************************************************/ | ||||
| #ifndef PAGE_CHECKSUM_H | ||||
| #define PAGE_CHECKSUM_H | ||||
|  | ||||
| @@ -6,10 +9,10 @@ | ||||
| /*********************************************************************************************************************************** | ||||
| Functions | ||||
| ***********************************************************************************************************************************/ | ||||
| uint16 pageChecksum(const char *szPage, uint32 uiBlockNo, uint32 uiPageSize); | ||||
| bool pageChecksumTest(const char *szPage, uint32 uiBlockNo, uint32 uiPageSize, uint32 uiIgnoreWalId, uint32 uiIgnoreWalOffset); | ||||
| uint16 pageChecksum(const unsigned char *page, int blockNo, int pageSize); | ||||
| bool pageChecksumTest(const unsigned char *page, int blockNo, int pageSize, uint32 ignoreWalId, uint32 ignoreWalOffset); | ||||
| bool pageChecksumBufferTest( | ||||
|     const char *szPageBuffer, uint32 uiBufferSize, uint32 uiBlockNoStart, uint32 uiPageSize, uint32 uiIgnoreWalId, | ||||
|     uint32 uiIgnoreWalOffset); | ||||
|     const unsigned char *pageBuffer, int pageBufferSize, int blockNoBegin, int pageSize, uint32 ignoreWalId, | ||||
|     uint32 ignoreWalOffset); | ||||
|  | ||||
| #endif | ||||
|   | ||||
		Reference in New Issue
	
	Block a user