Skip to content

Commit 7993488

Browse files
committed
fix ptrack_get_and_clear() for files in pg_global tablespace
1 parent 1befa47 commit 7993488

File tree

2 files changed

+80
-29
lines changed

2 files changed

+80
-29
lines changed

src/backup.c

Lines changed: 79 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -807,54 +807,91 @@ pg_ptrack_clear(void)
807807

808808
/* Read and clear ptrack files of the target relation.
809809
* Result is a bytea ptrack map of all segments of the target relation.
810+
* case 1: we know a tablespace_oid, db_oid, and rel_filenode
811+
* case 2: we know db_oid and rel_filenode (no tablespace_oid, because file in pg_default)
812+
* case 3: we know only rel_filenode (because file in pg_global)
810813
*/
811814
static char *
812-
pg_ptrack_get_and_clear(Oid tablespace_oid, Oid db_oid, Oid rel_oid,
815+
pg_ptrack_get_and_clear(Oid tablespace_oid, Oid db_oid, Oid rel_filenode,
813816
size_t *result_size)
814817
{
815818
PGconn *tmp_conn;
816819
PGresult *res_db,
820+
*res_pg_global,
817821
*res;
818822
char *dbname;
819823
char *params[2];
820824
char *result;
825+
Oid pg_global_oid;
821826

822827
params[0] = palloc(64);
823828
params[1] = palloc(64);
824-
sprintf(params[0], "%i", db_oid);
825829

826-
res_db = pgut_execute(backup_conn,
827-
"SELECT datname FROM pg_database WHERE oid=$1",
828-
1, (const char **) params);
830+
/* regular file (not in directory 'global') */
831+
if (db_oid != 0)
832+
{
833+
sprintf(params[0], "%i", db_oid);
834+
res_db = pgut_execute(backup_conn,
835+
"SELECT datname FROM pg_database WHERE oid=$1",
836+
1, (const char **) params);
837+
/*
838+
* If database is not found, it's not an error.
839+
* It could have been deleted since previous backup.
840+
*/
841+
if (PQntuples(res_db) != 1 || PQnfields(res_db) != 1)
842+
return NULL;
829843

830-
/*
831-
* If database is not found, it's not an error.
832-
* It could have been deleted since previous backup.
833-
*/
834-
if (PQntuples(res_db) != 1 || PQnfields(res_db) != 1)
835-
return NULL;
844+
dbname = pstrdup(PQgetvalue(res_db, 0, 0));
845+
PQclear(res_db);
836846

837-
dbname = pstrdup(PQgetvalue(res_db, 0, 0));
838-
PQclear(res_db);
847+
tmp_conn = pgut_connect(dbname);
848+
sprintf(params[0], "%i", tablespace_oid);
849+
sprintf(params[1], "%i", rel_filenode);
850+
res = pgut_execute(tmp_conn, "SELECT pg_ptrack_get_and_clear($1, $2)",
851+
2, (const char **)params);
852+
853+
if (PQnfields(res) != 1)
854+
elog(ERROR, "cannot get ptrack file from database \"%s\" by tablespace oid %u and relation oid %u",
855+
dbname, tablespace_oid, rel_filenode);
856+
pfree(dbname);
857+
pgut_disconnect(tmp_conn);
839858

840-
tmp_conn = pgut_connect(dbname);
841-
sprintf(params[0], "%i", tablespace_oid);
842-
sprintf(params[1], "%i", rel_oid);
859+
}
860+
/* file in directory 'global' */
861+
else
862+
{
863+
/* get oid of pg_global */
864+
res_pg_global = pgut_execute(backup_conn,
865+
"SELECT oid FROM pg_tablespace WHERE spcname = 'pg_global'",
866+
0, NULL);
867+
/*
868+
* something is very wrong, i.e. ptrack file are present in pg_global directory
869+
* but pg_global tablespace is missing in PostgreSQL catalogue
870+
*/
871+
if (PQntuples(res_pg_global) != 1 || PQnfields(res_pg_global) != 1)
872+
elog(ERROR, "cannot get oid of pg_global tablespace, which was needed"
873+
"for getting ptrack file content of filenode %u",
874+
rel_filenode);
875+
876+
pg_global_oid = atoi(pstrdup(PQgetvalue(res_pg_global, 0, 0)));
877+
PQclear(res_pg_global);
878+
879+
/* execute ptrack_get_and_clear for relation in pg_global */
880+
sprintf(params[0], "%i", pg_global_oid);
881+
sprintf(params[1], "%i", rel_filenode);
882+
res = pgut_execute(backup_conn, "SELECT pg_ptrack_get_and_clear($1, $2)",
883+
2, (const char **)params);
884+
885+
if (PQnfields(res) != 1)
886+
elog(ERROR, "cannot get ptrack file from pg_global tablespace and relation oid %u",
887+
rel_filenode);
888+
}
843889

844-
res = pgut_execute(tmp_conn, "SELECT pg_ptrack_get_and_clear($1, $2)",
845-
2, (const char **)params);
846-
if (PQnfields(res) != 1)
847-
elog(ERROR, "cannot get ptrack file from database \"%s\" by tablespace oid %u and relation oid %u",
848-
dbname, tablespace_oid, rel_oid);
849890
result = (char *) PQunescapeBytea((unsigned char *) PQgetvalue(res, 0, 0),
850891
result_size);
851892
PQclear(res);
852-
853-
pgut_disconnect(tmp_conn);
854-
855893
pfree(params[0]);
856894
pfree(params[1]);
857-
pfree(dbname);
858895

859896
return result;
860897
}
@@ -1843,6 +1880,7 @@ make_pagemap_from_ptrack(parray *files)
18431880
if (p->ptrack_path != NULL)
18441881
{
18451882
char *tablespace;
1883+
char *global;
18461884
Oid db_oid,
18471885
rel_oid,
18481886
tablespace_oid = 0;
@@ -1861,8 +1899,9 @@ make_pagemap_from_ptrack(parray *files)
18611899

18621900
/*
18631901
* Path has format:
1864-
* pg_tblspc/tablespace_oid/tablespace_version_subdir/db_oid/rel_oid
1865-
* base/db_oid/rel_oid
1902+
* pg_tblspc/tablespace_oid/tablespace_version_subdir/db_oid/rel_filenode
1903+
* base/db_oid/rel_filenode
1904+
* global/rel_filenode
18661905
*/
18671906
sep_iter = strlen(p->path);
18681907
while (sep_iter >= 0)
@@ -1878,9 +1917,20 @@ make_pagemap_from_ptrack(parray *files)
18781917
elog(ERROR, "path of the file \"%s\" has wrong format",
18791918
p->path);
18801919

1881-
sscanf(p->path + sep_iter + 1, "%u/%u", &db_oid, &rel_oid);
1920+
/*
1921+
* If file lies in directory 'global' we cannot get its db_oid from file path
1922+
* In this case we set db_oid to 0
1923+
*/
1924+
global = strstr(p->path + sep_iter + 1, PG_GLOBAL_DIR);
1925+
if (global)
1926+
{
1927+
sscanf(global+strlen(PG_GLOBAL_DIR)+1, "%u", &rel_oid);
1928+
db_oid = 0;
1929+
}
1930+
else
1931+
sscanf(p->path + sep_iter + 1, "%u/%u", &db_oid, &rel_oid);
18821932

1883-
/* get ptrack map for all segments of the relation in a raw format */
1933+
/* get ptrack map for all segments of the relation in a raw format*/
18841934
ptrack_nonparsed = pg_ptrack_get_and_clear(tablespace_oid, db_oid,
18851935
rel_oid, &ptrack_nonparsed_size);
18861936
if (ptrack_nonparsed != NULL)

src/pg_probackup.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#define PG_XLOG_DIR "pg_xlog"
5151
#endif
5252
#define PG_TBLSPC_DIR "pg_tblspc"
53+
#define PG_GLOBAL_DIR "global"
5354
#define BACKUP_CONTROL_FILE "backup.control"
5455
#define BACKUP_CATALOG_CONF_FILE "pg_probackup.conf"
5556
#define BACKUP_CATALOG_PID "pg_probackup.pid"

0 commit comments

Comments
 (0)