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

Skip to content

Commit eaf3b14

Browse files
committed
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.
1 parent 0c7c78b commit eaf3b14

File tree

3 files changed

+72
-35
lines changed

3 files changed

+72
-35
lines changed

src/catalog.c

+11
Original file line numberDiff line numberDiff line change
@@ -1139,7 +1139,18 @@ get_backup_filelist(pgBackup *backup, bool strict)
11391139
file->uncompressed_size = write_size;
11401140

11411141
if (file->external_dir_num == 0)
1142+
{
1143+
bool is_datafile = file->is_datafile;
11421144
set_forkname(file);
1145+
if (is_datafile != file->is_datafile)
1146+
{
1147+
elog(WARNING, "File '%s' was stored as datafile, but looks like it is not",
1148+
file->rel_path);
1149+
/* Lets fail in tests */
1150+
Assert(file->is_datafile == file->is_datafile);
1151+
file->is_datafile = is_datafile;
1152+
}
1153+
}
11431154

11441155
parray_append(files, file);
11451156
}

src/dir.c

+60-34
Original file line numberDiff line numberDiff line change
@@ -631,20 +631,6 @@ dir_check_file(pgFile *file, bool backup_logs)
631631

632632
if (file->forkName == ptrack) /* Compatibility with left-overs from ptrack1 */
633633
return CHECK_FALSE;
634-
else if (file->forkName != none)
635-
return CHECK_TRUE;
636-
637-
/* Set is_datafile flag */
638-
{
639-
char suffix[MAXFNAMELEN];
640-
641-
/* check if file is datafile */
642-
sscanf_res = sscanf(file->name, "%u.%d.%s", &(file->relOid),
643-
&(file->segno), suffix);
644-
Assert(sscanf_res > 0); /* since first char is digit */
645-
if (sscanf_res == 1 || sscanf_res == 2)
646-
file->is_datafile = true;
647-
}
648634
}
649635
}
650636

@@ -1789,34 +1775,74 @@ pfilearray_clear_locks(parray *file_list)
17891775
}
17901776
}
17911777

1778+
static inline bool
1779+
is_forkname(char *name, size_t *pos, const char *forkname)
1780+
{
1781+
size_t fnlen = strlen(forkname);
1782+
if (strncmp(name + *pos, forkname, fnlen) != 0)
1783+
return false;
1784+
*pos += fnlen;
1785+
return true;
1786+
}
1787+
1788+
#define OIDCHARS 10
1789+
17921790
/* Set forkName if possible */
1793-
void
1791+
bool
17941792
set_forkname(pgFile *file)
17951793
{
1796-
int name_len = strlen(file->name);
1797-
1798-
/* Auxiliary fork of the relfile */
1799-
if (name_len > 3 && strcmp(file->name + name_len - 3, "_vm") == 0)
1800-
file->forkName = vm;
1794+
size_t i = 0;
1795+
uint64_t oid = 0; /* use 64bit to not check for overflow in a loop */
18011796

1802-
else if (name_len > 4 && strcmp(file->name + name_len - 4, "_fsm") == 0)
1803-
file->forkName = fsm;
1797+
/* pretend it is not relation file */
1798+
file->relOid = 0;
1799+
file->forkName = none;
1800+
file->is_datafile = false;
18041801

1805-
else if (name_len > 4 && strcmp(file->name + name_len - 4, ".cfm") == 0)
1806-
file->forkName = cfm;
1802+
for (i = 0; isdigit(file->name[i]); i++)
1803+
{
1804+
if (i == 0 && file->name[i] == '0')
1805+
return false;
1806+
oid = oid * 10 + file->name[i] - '0';
1807+
}
1808+
if (i == 0 || i > OIDCHARS || oid > UINT32_MAX)
1809+
return false;
18071810

1808-
else if (name_len > 5 && strcmp(file->name + name_len - 5, "_init") == 0)
1811+
/* usual fork name */
1812+
/* /^\d+_(vm|fsm|init|ptrack)$/ */
1813+
if (is_forkname(file->name, &i, "_vm"))
1814+
file->forkName = vm;
1815+
else if (is_forkname(file->name, &i, "_fsm"))
1816+
file->forkName = fsm;
1817+
else if (is_forkname(file->name, &i, "_init"))
18091818
file->forkName = init;
1810-
1811-
else if (name_len > 7 && strcmp(file->name + name_len - 7, "_ptrack") == 0)
1819+
else if (is_forkname(file->name, &i, "_ptrack"))
18121820
file->forkName = ptrack;
18131821

1814-
// extract relOid for certain forks
1822+
/* segment number */
1823+
/* /^\d+(_(vm|fsm|init|ptrack))?\.\d+$/ */
1824+
if (file->name[i] == '.' && isdigit(file->name[i+1]))
1825+
{
1826+
for (i++; isdigit(file->name[i]); i++)
1827+
;
1828+
}
1829+
1830+
/* CFS "fork name" */
1831+
if (file->forkName == none &&
1832+
is_forkname(file->name, &i, ".cfm"))
1833+
{
1834+
/* /^\d+(\.\d+)?.cfm$/ */
1835+
file->forkName = cfm;
1836+
}
1837+
1838+
/* If there are excess characters, it is not relation file */
1839+
if (file->name[i] != 0)
1840+
{
1841+
file->forkName = none;
1842+
return false;
1843+
}
18151844

1816-
if ((file->forkName == vm ||
1817-
file->forkName == fsm ||
1818-
file->forkName == init ||
1819-
file->forkName == cfm) &&
1820-
(sscanf(file->name, "%u*", &(file->relOid)) != 1))
1821-
file->relOid = 0;
1845+
file->relOid = oid;
1846+
file->is_datafile = file->forkName == none;
1847+
return true;
18221848
}

src/pg_probackup.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1098,7 +1098,7 @@ extern int pgCompareString(const void *str1, const void *str2);
10981098
extern int pgPrefixCompareString(const void *str1, const void *str2);
10991099
extern int pgCompareOid(const void *f1, const void *f2);
11001100
extern void pfilearray_clear_locks(parray *file_list);
1101-
extern void set_forkname(pgFile *file);
1101+
extern bool set_forkname(pgFile *file);
11021102

11031103
/* in data.c */
11041104
extern bool check_data_file(ConnectionArgs *arguments, pgFile *file,

0 commit comments

Comments
 (0)