1
0
mirror of https://github.com/postgrespro/pg_probackup.git synced 2026-06-21 01:34:15 +02:00

fix set_forkname

Fork detection were broken before set_forkname extraction, and its bug
were copied into.

Lets reimplement it to be like `parse_filename_for_nonetemp_relation` in
PostgreSQL code.
This commit is contained in:
Yura Sokolov
2022-11-03 02:37:29 +03:00
parent 0c7c78b8e8
commit eaf3b14c22
3 changed files with 72 additions and 35 deletions
+11
View File
@@ -1139,7 +1139,18 @@ get_backup_filelist(pgBackup *backup, bool strict)
file->uncompressed_size = write_size;
if (file->external_dir_num == 0)
{
bool is_datafile = file->is_datafile;
set_forkname(file);
if (is_datafile != file->is_datafile)
{
elog(WARNING, "File '%s' was stored as datafile, but looks like it is not",
file->rel_path);
/* Lets fail in tests */
Assert(file->is_datafile == file->is_datafile);
file->is_datafile = is_datafile;
}
}
parray_append(files, file);
}
+60 -34
View File
@@ -631,20 +631,6 @@ dir_check_file(pgFile *file, bool backup_logs)
if (file->forkName == ptrack) /* Compatibility with left-overs from ptrack1 */
return CHECK_FALSE;
else if (file->forkName != none)
return CHECK_TRUE;
/* Set is_datafile flag */
{
char suffix[MAXFNAMELEN];
/* check if file is datafile */
sscanf_res = sscanf(file->name, "%u.%d.%s", &(file->relOid),
&(file->segno), suffix);
Assert(sscanf_res > 0); /* since first char is digit */
if (sscanf_res == 1 || sscanf_res == 2)
file->is_datafile = true;
}
}
}
@@ -1789,34 +1775,74 @@ pfilearray_clear_locks(parray *file_list)
}
}
static inline bool
is_forkname(char *name, size_t *pos, const char *forkname)
{
size_t fnlen = strlen(forkname);
if (strncmp(name + *pos, forkname, fnlen) != 0)
return false;
*pos += fnlen;
return true;
}
#define OIDCHARS 10
/* Set forkName if possible */
void
bool
set_forkname(pgFile *file)
{
int name_len = strlen(file->name);
size_t i = 0;
uint64_t oid = 0; /* use 64bit to not check for overflow in a loop */
/* Auxiliary fork of the relfile */
if (name_len > 3 && strcmp(file->name + name_len - 3, "_vm") == 0)
/* pretend it is not relation file */
file->relOid = 0;
file->forkName = none;
file->is_datafile = false;
for (i = 0; isdigit(file->name[i]); i++)
{
if (i == 0 && file->name[i] == '0')
return false;
oid = oid * 10 + file->name[i] - '0';
}
if (i == 0 || i > OIDCHARS || oid > UINT32_MAX)
return false;
/* usual fork name */
/* /^\d+_(vm|fsm|init|ptrack)$/ */
if (is_forkname(file->name, &i, "_vm"))
file->forkName = vm;
else if (name_len > 4 && strcmp(file->name + name_len - 4, "_fsm") == 0)
else if (is_forkname(file->name, &i, "_fsm"))
file->forkName = fsm;
else if (name_len > 4 && strcmp(file->name + name_len - 4, ".cfm") == 0)
file->forkName = cfm;
else if (name_len > 5 && strcmp(file->name + name_len - 5, "_init") == 0)
else if (is_forkname(file->name, &i, "_init"))
file->forkName = init;
else if (name_len > 7 && strcmp(file->name + name_len - 7, "_ptrack") == 0)
else if (is_forkname(file->name, &i, "_ptrack"))
file->forkName = ptrack;
// extract relOid for certain forks
/* segment number */
/* /^\d+(_(vm|fsm|init|ptrack))?\.\d+$/ */
if (file->name[i] == '.' && isdigit(file->name[i+1]))
{
for (i++; isdigit(file->name[i]); i++)
;
}
if ((file->forkName == vm ||
file->forkName == fsm ||
file->forkName == init ||
file->forkName == cfm) &&
(sscanf(file->name, "%u*", &(file->relOid)) != 1))
file->relOid = 0;
/* CFS "fork name" */
if (file->forkName == none &&
is_forkname(file->name, &i, ".cfm"))
{
/* /^\d+(\.\d+)?.cfm$/ */
file->forkName = cfm;
}
/* If there are excess characters, it is not relation file */
if (file->name[i] != 0)
{
file->forkName = none;
return false;
}
file->relOid = oid;
file->is_datafile = file->forkName == none;
return true;
}
+1 -1
View File
@@ -1098,7 +1098,7 @@ extern int pgCompareString(const void *str1, const void *str2);
extern int pgPrefixCompareString(const void *str1, const void *str2);
extern int pgCompareOid(const void *f1, const void *f2);
extern void pfilearray_clear_locks(parray *file_list);
extern void set_forkname(pgFile *file);
extern bool set_forkname(pgFile *file);
/* in data.c */
extern bool check_data_file(ConnectionArgs *arguments, pgFile *file,