@@ -118,7 +118,7 @@ bool launch_agent(void)
118
118
int errfd [2 ];
119
119
int agent_version ;
120
120
//TODO REVIEW XXX review buf_size
121
- size_t payload_buf_size = 1024 * 8 ;
121
+ int payload_buf_size = 1024 * 8 ;
122
122
char payload_buf [payload_buf_size ];
123
123
124
124
ssh_argc = 0 ;
@@ -244,29 +244,83 @@ bool launch_agent(void)
244
244
/* Make sure that remote agent has the same version, fork and other features to be binary compatible
245
245
*/
246
246
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 );
248
248
249
249
return true;
250
250
}
251
251
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 )
255
279
{
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 )
262
290
{
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 );
264
313
}
265
- return payload_size + 1 ;
314
+ return result_size ;
266
315
}
267
316
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 )
269
321
{
322
+ elog (LOG , "Agent version=%d" , agent_version );
323
+
270
324
if (agent_version != AGENT_PROTOCOL_VERSION )
271
325
{
272
326
char agent_version_str [1024 ];
@@ -279,6 +333,23 @@ void check_remote_agent_compatibility(int agent_version, char *compatibility_str
279
333
"consider to upgrade pg_probackup binary" ,
280
334
agent_version_str , AGENT_PROTOCOL_VERSION_STR );
281
335
}
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
+
284
355
}
0 commit comments