@@ -118,7 +118,7 @@ bool launch_agent(void)
118118 int errfd [2 ];
119119 int agent_version ;
120120 //TODO REVIEW XXX review buf_size
121- size_t payload_buf_size = 1024 * 8 ;
121+ int payload_buf_size = 1024 * 8 ;
122122 char payload_buf [payload_buf_size ];
123123
124124 ssh_argc = 0 ;
@@ -244,29 +244,83 @@ bool launch_agent(void)
244244 /* Make sure that remote agent has the same version, fork and other features to be binary compatible
245245 */
246246 fio_get_agent_version (& agent_version , payload_buf , payload_buf_size );
247- check_remote_agent_compatibility (0 , payload_buf );
247+ check_remote_agent_compatibility (agent_version , payload_buf , payload_buf_size );
248248
249249 return true;
250250}
251251
252- //TODO REVIEW XXX review macro
253- #define STR (macro ) #macro
254- size_t prepare_remote_agent_compatibility_str (char * compatibility_buf , size_t buf_size )
252+ #define COMPATIBILITY_VAL (macro ) #macro, macro
253+ #define COMPATIBILITY_STR (macro ) #macro
254+ #define COMPATIBILITY_VAL_STR (macro ) #macro, COMPATIBILITY_STR(macro)
255+
256+ #define COMPATIBILITY_VAL_SEPARATOR "="
257+ #define COMPATIBILITY_LINE_SEPARATOR "\n"
258+
259+ static char * compatibility_params [] = {
260+ COMPATIBILITY_VAL (PG_MAJORVERSION ),
261+ //TODO remove?
262+ //TODO doesn't work macro name check for ints!!!!
263+ COMPATIBILITY_VAL_STR (SIZEOF_VOID_P ),
264+ //TODO REVIEW XXX can use edition.h/extract_pgpro_edition()
265+ #ifdef PGPRO_EDN
266+ //TODO add vanilla
267+ //TODO make "1c" -> "vanilla"
268+ COMPATIBILITY_VAL (PGPRO_EDN ),
269+ #endif
270+ };
271+
272+ /*
273+ * Compose compatibility string to be sent by pg_probackup agent
274+ * through ssh and to be verified by pg_probackup peer.
275+ * Compatibility string contains postgres essential vars as strings
276+ * in format "var_name" + COMPATIBILITY_VAL_SEPARATOR + "var_value" + COMPATIBILITY_LINE_SEPARATOR
277+ */
278+ size_t prepare_compatibility_str (char * compatibility_buf , size_t compatibility_buf_size )
255279{
256- size_t payload_size = snprintf (compatibility_buf , buf_size ,
257- // "%s\n%s\n%s\n%s\n",
258- "%s\n%s\n" ,
259- STR (PG_MAJORVERSION ), PG_MAJORVERSION );
260- // STR(PGPRO_EDN), PGPRO_EDN);
261- if (payload_size >= buf_size )
280+ char tmp_buf [1024 ];
281+ int size_inc = 0 ;
282+ size_t result_size = 1 ;
283+ size_t compatibility_params_array_size = sizeof compatibility_params / sizeof compatibility_params [0 ];;
284+
285+ * compatibility_buf = '\0' ;
286+ Assert (compatibility_params_array_size % 2 == 0 );
287+
288+ //TODO !!!!
289+ for (int i = 0 ; i < compatibility_params_array_size ; i += 2 )
262290 {
263- elog (ERROR , "TODO REVIEW XXX too bad message buffer exhaust" );
291+ size_inc = snprintf (compatibility_buf + size_inc , compatibility_buf_size ,
292+ "%s" COMPATIBILITY_VAL_SEPARATOR "%s" COMPATIBILITY_LINE_SEPARATOR ,
293+ compatibility_params [i ], compatibility_params [i + 1 ]);
294+
295+ // size_inc = snprintf(tmp_buf, sizeof tmp_buf,
296+ // "%s" COMPATIBILITY_VAL_SEPARATOR "%s" COMPATIBILITY_LINE_SEPARATOR,
297+ // compatibility_params[i], compatibility_params[i+1]);
298+ if (size_inc >= sizeof tmp_buf )
299+ {
300+ //TODO make Assert
301+ elog (ERROR , "Compatibility params from agent doesn't fit to %zu chars, %s=%s" ,
302+ sizeof tmp_buf - 1 , compatibility_params [i ], compatibility_params [i + 1 ] );
303+ }
304+
305+ result_size += size_inc ;
306+ if (result_size > compatibility_buf_size )
307+ {
308+ //TODO make Assert
309+ elog (ERROR , "Can't fit compatibility string size %zu to buffer size %zu:\n%s\n%s" ,
310+ result_size , compatibility_buf_size , compatibility_buf , tmp_buf );
311+ }
312+ strcat (compatibility_buf , tmp_buf );
264313 }
265- return payload_size + 1 ;
314+ return result_size ;
266315}
267316
268- void check_remote_agent_compatibility (int agent_version , char * compatibility_str )
317+ /*
318+ * Check incoming remote agent's compatibility params for equality to local ones.
319+ */
320+ void check_remote_agent_compatibility (int agent_version , char * compatibility_str , size_t compatibility_str_max_size )
269321{
322+ elog (LOG , "Agent version=%d" , agent_version );
323+
270324 if (agent_version != AGENT_PROTOCOL_VERSION )
271325 {
272326 char agent_version_str [1024 ];
@@ -279,6 +333,23 @@ void check_remote_agent_compatibility(int agent_version, char *compatibility_str
279333 "consider to upgrade pg_probackup binary" ,
280334 agent_version_str , AGENT_PROTOCOL_VERSION_STR );
281335 }
282- assert (false);
283- elog (ERROR , " check_remote_agent_compatibility() not implemented" );
336+
337+ if (strnlen (compatibility_str , compatibility_str_max_size ) == compatibility_str_max_size )
338+ {
339+ elog (ERROR , "Corrupted remote compatibility protocol: compatibility string has no terminating \\0" );
340+ }
341+
342+ elog (LOG , "Agent compatibility params: '%s'" , compatibility_str );
343+
344+ /* checking compatibility params */
345+ {
346+ char * buf [compatibility_str_max_size ];
347+
348+ prepare_compatibility_str (buf , sizeof buf );
349+ if (!strcmp (compatibility_str , buf ))
350+ {
351+ elog (ERROR , "Incompatible agent params, expected %s" , buf );
352+ }
353+ }
354+
284355}
0 commit comments