Skip to content

Commit 5851068

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 4ecb11f commit 5851068

File tree

3 files changed

+72
-35
lines changed

3 files changed

+72
-35
lines changed

src/catalog.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1139,7 +1139,18 @@ get_backup_filelist(pgBackup *backup, bool strict)
11391139
file->hdr_size = (int) hdr_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

Lines changed: 60 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -688,20 +688,6 @@ dir_check_file(pgFile *file, bool backup_logs)
688688

689689
if (file->forkName == ptrack) /* Compatibility with left-overs from ptrack1 */
690690
return CHECK_FALSE;
691-
else if (file->forkName != none)
692-
return CHECK_TRUE;
693-
694-
/* Set is_datafile flag */
695-
{
696-
char suffix[MAXFNAMELEN];
697-
698-
/* check if file is datafile */
699-
sscanf_res = sscanf(file->name, "%u.%d.%s", &(file->relOid),
700-
&(file->segno), suffix);
701-
Assert(sscanf_res > 0); /* since first char is digit */
702-
if (sscanf_res == 1 || sscanf_res == 2)
703-
file->is_datafile = true;
704-
}
705691
}
706692
}
707693

@@ -1927,34 +1913,74 @@ pfilearray_clear_locks(parray *file_list)
19271913
}
19281914
}
19291915

1916+
static inline bool
1917+
is_forkname(char *name, size_t *pos, const char *forkname)
1918+
{
1919+
size_t fnlen = strlen(forkname);
1920+
if (strncmp(name + *pos, forkname, fnlen) != 0)
1921+
return false;
1922+
*pos += fnlen;
1923+
return true;
1924+
}
1925+
1926+
#define OIDCHARS 10
1927+
19301928
/* Set forkName if possible */
1931-
void
1929+
bool
19321930
set_forkname(pgFile *file)
19331931
{
1934-
int name_len = strlen(file->name);
1935-
1936-
/* Auxiliary fork of the relfile */
1937-
if (name_len > 3 && strcmp(file->name + name_len - 3, "_vm") == 0)
1938-
file->forkName = vm;
1932+
size_t i = 0;
1933+
uint64_t oid = 0; /* use 64bit to not check for overflow in a loop */
19391934

1940-
else if (name_len > 4 && strcmp(file->name + name_len - 4, "_fsm") == 0)
1941-
file->forkName = fsm;
1935+
/* pretend it is not relation file */
1936+
file->relOid = 0;
1937+
file->forkName = none;
1938+
file->is_datafile = false;
19421939

1943-
else if (name_len > 4 && strcmp(file->name + name_len - 4, ".cfm") == 0)
1944-
file->forkName = cfm;
1940+
for (i = 0; isdigit(file->name[i]); i++)
1941+
{
1942+
if (i == 0 && file->name[i] == '0')
1943+
return false;
1944+
oid = oid * 10 + file->name[i] - '0';
1945+
}
1946+
if (i == 0 || i > OIDCHARS || oid > UINT32_MAX)
1947+
return false;
19451948

1946-
else if (name_len > 5 && strcmp(file->name + name_len - 5, "_init") == 0)
1949+
/* usual fork name */
1950+
/* /^\d+_(vm|fsm|init|ptrack)$/ */
1951+
if (is_forkname(file->name, &i, "_vm"))
1952+
file->forkName = vm;
1953+
else if (is_forkname(file->name, &i, "_fsm"))
1954+
file->forkName = fsm;
1955+
else if (is_forkname(file->name, &i, "_init"))
19471956
file->forkName = init;
1948-
1949-
else if (name_len > 7 && strcmp(file->name + name_len - 7, "_ptrack") == 0)
1957+
else if (is_forkname(file->name, &i, "_ptrack"))
19501958
file->forkName = ptrack;
19511959

1952-
// extract relOid for certain forks
1960+
/* segment number */
1961+
/* /^\d+(_(vm|fsm|init|ptrack))?\.\d+$/ */
1962+
if (file->name[i] == '.' && isdigit(file->name[i+1]))
1963+
{
1964+
for (i++; isdigit(file->name[i]); i++)
1965+
;
1966+
}
1967+
1968+
/* CFS "fork name" */
1969+
if (file->forkName == none &&
1970+
is_forkname(file->name, &i, ".cfm"))
1971+
{
1972+
/* /^\d+(\.\d+)?.cfm$/ */
1973+
file->forkName = cfm;
1974+
}
1975+
1976+
/* If there are excess characters, it is not relation file */
1977+
if (file->name[i] != 0)
1978+
{
1979+
file->forkName = none;
1980+
return false;
1981+
}
19531982

1954-
if ((file->forkName == vm ||
1955-
file->forkName == fsm ||
1956-
file->forkName == init ||
1957-
file->forkName == cfm) &&
1958-
(sscanf(file->name, "%u*", &(file->relOid)) != 1))
1959-
file->relOid = 0;
1983+
file->relOid = oid;
1984+
file->is_datafile = file->forkName == none;
1985+
return true;
19601986
}

src/pg_probackup.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1041,7 +1041,7 @@ extern int pgCompareString(const void *str1, const void *str2);
10411041
extern int pgPrefixCompareString(const void *str1, const void *str2);
10421042
extern int pgCompareOid(const void *f1, const void *f2);
10431043
extern void pfilearray_clear_locks(parray *file_list);
1044-
extern void set_forkname(pgFile *file);
1044+
extern bool set_forkname(pgFile *file);
10451045
extern void exclude_files(parray *files, bool backup_logs);
10461046

10471047
/* in data.c */

0 commit comments

Comments
 (0)