You've already forked pgbackrest
							
							
				mirror of
				https://github.com/pgbackrest/pgbackrest.git
				synced 2025-10-30 23:37:45 +02:00 
			
		
		
		
	Much improved param protocol.
This commit is contained in:
		| @@ -74,22 +74,34 @@ my $oRemote = pg_backrest_remote->new(); | ||||
| # Write the greeting so remote process knows who we are | ||||
| $oRemote->greeting_write(); | ||||
|  | ||||
| # Get the first command | ||||
| my ($strCommand, $strOptions) = $oRemote->command_read(); | ||||
| # Command string | ||||
| my $strCommand = ''; | ||||
|  | ||||
| # Loop until the exit command is received | ||||
| while ($strCommand ne 'exit') | ||||
| { | ||||
|     my %oParamHash; | ||||
|  | ||||
|     $strCommand = $oRemote->command_read(\%oParamHash); | ||||
|  | ||||
|     eval | ||||
|     { | ||||
|         # File->exists | ||||
|         if ($strCommand eq OP_EXISTS) | ||||
|         { | ||||
|             $oRemote->output_write($oFile->exists(PATH_ABSOLUTE, $strOptions) ? "Y" : "N"); | ||||
|             if (!defined($oParamHash{path})) | ||||
|             { | ||||
|                 confess "path must be defined"; | ||||
|             } | ||||
|              | ||||
|             $oRemote->output_write($oFile->exists(PATH_ABSOLUTE, $oParamHash{path}) ? "Y" : "N"); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             confess "invalid command: ${strCommand}"; | ||||
|             if ($strCommand ne 'noop') | ||||
|             { | ||||
|                 confess "invalid command: ${strCommand}"; | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
|      | ||||
| @@ -97,9 +109,6 @@ while ($strCommand ne 'exit') | ||||
|     { | ||||
|         $oRemote->error_write($@); | ||||
|     } | ||||
|  | ||||
|     # Get the next command | ||||
|     ($strCommand, $strOptions) = $oRemote->command_read(); | ||||
| } | ||||
|  | ||||
| # # Get the operation | ||||
|   | ||||
| @@ -1129,21 +1129,25 @@ sub exists | ||||
|  | ||||
|     # Set error prefix, remote, and path | ||||
|     my $bExists = true; | ||||
|     my $bRemote = $self->is_remote($strPathType); | ||||
|     my $strPathOp = $self->path_get($strPathType, $strPath); | ||||
|  | ||||
|     my $strErrorPrefix = "File->exists"; | ||||
|     my $strTrace = "${strPathType}:${strPathOp}"; | ||||
|  | ||||
|     # Run remotely | ||||
|     if ($bRemote) | ||||
|     if ($self->is_remote($strPathType)) | ||||
|     { | ||||
|         my $strCommandOptions = "${strPathOp}"; | ||||
|         $strTrace = "${strErrorPrefix}: remote ($strCommandOptions): " . $strTrace; | ||||
|  | ||||
|         # Build param hash | ||||
|         my %oParamHash; | ||||
|          | ||||
|         $oParamHash{path} = ${strPathOp}; | ||||
|          | ||||
|         # Build trace string | ||||
|         $strTrace = "${strErrorPrefix}: remote (" . $self->{oRemote}->command_param_string(\%oParamHash) . "): " . $strTrace; | ||||
|         &log(TRACE, $strTrace); | ||||
|  | ||||
|         $bExists = $self->{oRemote}->command_execute("EXISTS", $strCommandOptions, $strTrace) eq "Y"; | ||||
|         # Execute the command | ||||
|         $bExists = $self->{oRemote}->command_execute("exists", \%oParamHash, $strTrace) eq "Y"; | ||||
|     } | ||||
|     # Run locally | ||||
|     else | ||||
|   | ||||
| @@ -64,7 +64,7 @@ sub BUILD | ||||
|         #     $strOptionSSHCompression = "Compression=yes"; | ||||
|         # } | ||||
|  | ||||
|         &log(TRACE, "connecting to remote ssh host " . $self->{strHost}); | ||||
| #        &log(TRACE, "connecting to remote ssh host " . $self->{strHost}); | ||||
|  | ||||
|         # Make SSH connection | ||||
|         $self->{oSSH} = Net::OpenSSH->new($self->{strHost}, timeout => 300, user => $self->{strUser}, | ||||
| @@ -74,6 +74,8 @@ sub BUILD | ||||
|  | ||||
|         # Execute remote command | ||||
|         ($self->{hIn}, $self->{hOut}, $self->{hErr}, $self->{pId}) = $self->{oSSH}->open3($self->{strCommand}); | ||||
|          | ||||
|         $self->greeting_read(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -100,7 +102,7 @@ sub greeting_read | ||||
|     my $self = shift; | ||||
|  | ||||
|     # Make sure that the remote is running the right version | ||||
|     if (trim(readline($self->{hOut})) ne $self->{strGreeting}) | ||||
|     if (readline($self->{hOut}) ne $self->{strGreeting} . "\n") | ||||
|     { | ||||
|         confess &log(ERROR, "remote version mismatch"); | ||||
|     } | ||||
| @@ -182,7 +184,7 @@ sub output_read | ||||
| { | ||||
|     my $self = shift; | ||||
|  | ||||
|     &log(TRACE, "Remote->output_read"); | ||||
| #    &log(TRACE, "Remote->output_read"); | ||||
|  | ||||
|     my $strLine; | ||||
|     my $strOutput; | ||||
| @@ -205,7 +207,7 @@ sub output_read | ||||
|             last; | ||||
|         } | ||||
|  | ||||
|         $strOutput .= trim(substr($strLine, 1)); | ||||
|         $strOutput .= (defined($strOutput) ? "\n" : "") . trim(substr($strLine, 1)); | ||||
|     } | ||||
|  | ||||
|     return ($strOutput, $bError, $iErrorCode); | ||||
| @@ -227,32 +229,80 @@ sub output_write | ||||
|     } | ||||
| } | ||||
|  | ||||
| #################################################################################################################################### | ||||
| # COMMAND_PARAM_STRING | ||||
| #################################################################################################################################### | ||||
| sub command_param_string | ||||
| { | ||||
|     my $self = shift; | ||||
|     my $oParamHashRef = shift; | ||||
|      | ||||
|     my $strParamList; | ||||
|      | ||||
|     foreach my $strParam (sort(keys $oParamHashRef)) | ||||
|     { | ||||
|         $strParamList .= (defined($strParamList) ? "," : "") . "${strParam}=" . | ||||
|                          (defined(${$oParamHashRef}{"${strParam}"}) ? ${$oParamHashRef}{"${strParam}"} : "[undef]"); | ||||
|     } | ||||
|  | ||||
|     return $strParamList; | ||||
| } | ||||
|  | ||||
| #################################################################################################################################### | ||||
| # COMMAND_READ | ||||
| #################################################################################################################################### | ||||
| sub command_read | ||||
| { | ||||
|     my $self = shift; | ||||
|     my $oParamHashRef = shift; | ||||
|  | ||||
|     my $strOut = readline(*STDIN); | ||||
|     my $iPos = index($strOut, ':'); | ||||
|      | ||||
| #    &log(TRACE, "Remote->command_read"); | ||||
|  | ||||
|     my $strLine; | ||||
|     my $strCommand; | ||||
|     my $strOptions; | ||||
|      | ||||
|     # If no colon then there are no options | ||||
|     if ($iPos == -1) | ||||
|  | ||||
|     while ($strLine = readline(*STDIN)) | ||||
|     { | ||||
|         $strCommand = lc(trim($strOut)); | ||||
|     } | ||||
|     # Else parse options | ||||
|     else | ||||
|     { | ||||
|         $strCommand = lc(substr($strOut, 0, $iPos)); | ||||
|         $strOptions = trim(substr($strOut, $iPos + 1)); | ||||
|         $strLine = trim($strLine); | ||||
|          | ||||
|         if (!defined($strCommand)) | ||||
|         { | ||||
|             if ($strLine =~ /:$/) | ||||
|             { | ||||
|                 $strCommand = substr($strLine, 0, length($strLine) - 1); | ||||
| #                print "command ${strCommand} continues\n"; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 $strCommand = $strLine; | ||||
| #                print "command ${strCommand}\n"; | ||||
|                 last; | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             if ($strLine eq 'end') | ||||
|             { | ||||
|                 last; | ||||
|             } | ||||
|              | ||||
|             my $iPos = index($strLine, "="); | ||||
|              | ||||
|             if ($iPos == -1) | ||||
|             { | ||||
|                 confess "param \"${strLine}\" is missing = character"; | ||||
|             } | ||||
|              | ||||
|             my $strParam = substr($strLine, 0, $iPos); | ||||
|             my $strValue = substr($strLine, $iPos + 1); | ||||
|              | ||||
|             ${$oParamHashRef}{"${strParam}"} = ${strValue}; | ||||
|              | ||||
| #            print "${strParam}=${strValue}\n"; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return $strCommand, $strOptions; | ||||
|     return $strCommand; | ||||
| } | ||||
|  | ||||
| #################################################################################################################################### | ||||
| @@ -262,11 +312,40 @@ sub command_write | ||||
| { | ||||
|     my $self = shift; | ||||
|     my $strCommand = shift; | ||||
|     my $strOptions = shift; | ||||
|     my $oParamRef = shift; | ||||
|  | ||||
|     &log(TRACE, "Remote->command_write: $strCommand" . (defined($strOptions) ? ":$strOptions" : "")); | ||||
|     my $strOutput = $strCommand; | ||||
|  | ||||
|     if (!syswrite($self->{hIn}, "$strCommand" . (defined($strOptions) ? ":${strOptions}" : "") . "\n")) | ||||
|     if (defined($oParamRef)) | ||||
|     { | ||||
|         $strOutput = "${strCommand}:\n"; | ||||
|          | ||||
|         foreach my $strParam (sort(keys $oParamRef)) | ||||
|         { | ||||
|             if ($strParam =~ /=/) | ||||
|             { | ||||
|                 confess &log(ASSERT, "param \"${strParam}\" cannot contain = character"); | ||||
|             } | ||||
|  | ||||
|             my $strValue = ${$oParamRef}{"${strParam}"}; | ||||
|  | ||||
|             if ($strParam =~ /\n\$/) | ||||
|             { | ||||
|                 confess &log(ASSERT, "param \"${strParam}\" value cannot end with LF"); | ||||
|             } | ||||
|              | ||||
|             if (defined(${strValue})) | ||||
|             { | ||||
|                 $strOutput .= "${strParam}=${strValue}\n"; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $strOutput .= "end"; | ||||
|     } | ||||
|  | ||||
| #    &log(TRACE, "Remote->command_write:\n" . trim($strOutput)); | ||||
|  | ||||
|     if (!syswrite($self->{hIn}, "${strOutput}\n")) | ||||
|     { | ||||
|         confess "unable to write command"; | ||||
|     } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user