Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit eefd887

Browse files
author
Ivan Lazarev
committed
[PBCKP-236] draft, solution without couple of unapplied shortenings
1 parent 497751c commit eefd887

File tree

3 files changed

+99
-25
lines changed

3 files changed

+99
-25
lines changed

src/pg_probackup.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -882,8 +882,9 @@ extern DestDirIncrCompatibility check_incremental_compatibility(const char *pgda
882882
IncrRestoreMode incremental_mode);
883883

884884
/* in remote.c */
885-
extern void check_remote_agent_compatibility(int agent_version, char *compatibility_str);
886-
extern size_t prepare_remote_agent_compatibility_str(char* compatibility_buf, size_t buf_size);
885+
extern void check_remote_agent_compatibility(int agent_version,
886+
char *compatibility_str, size_t compatibility_str_max_size);
887+
extern size_t prepare_compatibility_str(char* compatibility_buf, size_t compatibility_buf_size);
887888

888889
/* in merge.c */
889890
extern void do_merge(InstanceState *instanceState, time_t backup_id, bool no_validate, bool no_sync);

src/utils/file.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,8 @@ fio_get_agent_version(int* protocol, char* payload_buf, size_t payload_buf_size)
281281
IO_CHECK(fio_read_all(fio_stdin, &hdr, sizeof(hdr)), sizeof(hdr));
282282
if (hdr.size > payload_buf_size)
283283
{
284-
elog(ERROR, "Bad protocol, insufficient payload_buf_size=%zu", payload_buf_size);
284+
//TODO REVIEW XXX %zu is C99 but not ANSI S standard, should we cast to unsigned long?
285+
elog(ERROR, "Corrupted remote compatibility protocol: insufficient payload_buf_size=%zu", payload_buf_size);
285286
}
286287

287288
*protocol = hdr.arg;
@@ -3321,17 +3322,18 @@ fio_communicate(int in, int out)
33213322
IO_CHECK(fio_write_all(out, buf, hdr.size), hdr.size);
33223323
break;
33233324
case FIO_AGENT_VERSION:
3324-
hdr.arg = AGENT_PROTOCOL_VERSION;
3325-
IO_CHECK(fio_write_all(out, &hdr, sizeof(hdr)), sizeof(hdr));
3326-
//TODO REVIEW XXX is it allowed by ANSI C to declare new scope inside???
33273325
{
3328-
size_t payload_size = prepare_remote_agent_compatibility_str(buf, buf_size);
3326+
size_t payload_size = prepare_compatibility_str(buf, buf_size);
3327+
3328+
hdr.arg = AGENT_PROTOCOL_VERSION;
3329+
hdr.size = payload_size;
3330+
3331+
IO_CHECK(fio_write_all(out, &hdr, sizeof(hdr)), sizeof(hdr));
33293332
IO_CHECK(fio_write_all(out, buf, payload_size), payload_size);
33303333
//TODO REVIEW XXX make INFO to LOG or VERBOSE
33313334
elog(INFO, "TODO REVIEW XXX sent agent compatibility\n %s", buf);
3335+
break;
33323336
}
3333-
assert(false);
3334-
break;
33353337
case FIO_STAT: /* Get information about file with specified path */
33363338
hdr.size = sizeof(st);
33373339
rc = hdr.arg ? stat(buf, &st) : lstat(buf, &st);

src/utils/remote.c

Lines changed: 87 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)