Skip to content

Commit 0d7fade

Browse files
committed
Upgraded PTRACK to 1.3
1 parent b500d59 commit 0d7fade

File tree

5 files changed

+125
-169
lines changed

5 files changed

+125
-169
lines changed

src/backend/access/gin/ginfast.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,8 @@ shiftList(Relation index, Buffer metabuffer, BlockNumber newHead,
561561
XLogEnsureRecordSpace(data.ndeleted, 0);
562562

563563
ptrack_add_block(index, BufferGetBlockNumber(metabuffer));
564+
for (i = 0; i < data.ndeleted; i++)
565+
ptrack_add_block(index, BufferGetBlockNumber(buffers[i]));
564566
START_CRIT_SECTION();
565567

566568
metadata->head = blknoToDelete;

src/backend/access/heap/ptrack.c

Lines changed: 108 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "access/genam.h"
2121
#include "access/generic_xlog.h"
2222
#include "catalog/pg_depend.h"
23+
#include "catalog/pg_tablespace.h"
2324
#include "access/htup_details.h"
2425
#include "miscadmin.h"
2526
#include "storage/bufmgr.h"
@@ -29,6 +30,7 @@
2930
#include "utils/array.h"
3031
#include "utils/relfilenodemap.h"
3132
#include "utils/builtins.h"
33+
#include "utils/pg_lsn.h"
3234
#include <unistd.h>
3335
#include <sys/stat.h>
3436

@@ -55,6 +57,11 @@ void SetPtrackClearLSN(bool set_invalid);
5557
Datum pg_ptrack_test(PG_FUNCTION_ARGS);
5658
Datum pg_ptrack_clear(PG_FUNCTION_ARGS);
5759
Datum pg_ptrack_get_and_clear(PG_FUNCTION_ARGS);
60+
Datum pg_ptrack_get_and_clear_db(PG_FUNCTION_ARGS);
61+
Datum pg_ptrack_control_lsn(PG_FUNCTION_ARGS);
62+
63+
void create_ptrack_init_file(char *dest_dir);
64+
void drop_ptrack_init_file(char *dest_dir);
5865

5966
/*
6067
* Mark tracked memory block during recovery.
@@ -471,196 +478,100 @@ assign_ptrack_enable(bool newval, void *extra)
471478
SetPtrackClearLSN(true);
472479
}
473480

474-
/* Test ptrack file. */
481+
/* Clear all ptrack files */
475482
Datum
476-
pg_ptrack_test(PG_FUNCTION_ARGS)
483+
pg_ptrack_clear(PG_FUNCTION_ARGS)
477484
{
478-
Oid relation_oid = PG_GETARG_OID(0);
479-
BlockNumber nblock, num_blocks;
480-
Relation rel;
481-
XLogRecPtr ptrack_control_lsn;
482-
Buffer ptrack_buf = InvalidBuffer;
483-
Page page;
484-
char *map;
485-
int fd;
486-
unsigned int excess_data_counter = 0;
487-
unsigned int necessary_data_counter = 0;
488-
ArrayType *result_array;
489-
Datum result_elems[2];
490-
491485
if (!superuser() && !has_rolreplication(GetUserId()))
492486
ereport(ERROR,
493487
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
494488
(errmsg("must be superuser or replication role to clear ptrack files"))));
495489

496-
/* get LSN from ptrack_control file */
497-
fd = BasicOpenFile("global/ptrack_control",
498-
O_RDONLY | PG_BINARY,
499-
0);
500-
501-
if (fd < 0)
502-
ereport(PANIC,
503-
(errcode_for_file_access(),
504-
errmsg("could not open ptrack control file \"%s\": %m",
505-
"global/ptrack_control")));
506-
errno = 0;
507-
if (read(fd, &ptrack_control_lsn, sizeof(XLogRecPtr)) != sizeof(XLogRecPtr))
508-
{
509-
/* if write didn't set errno, assume problem is no disk space */
510-
if (errno == 0)
511-
errno = ENOSPC;
512-
513-
ereport(PANIC,
514-
(errcode_for_file_access(),
515-
errmsg("could not read to ptrack control file: %m")));
516-
}
517-
518-
if (close(fd))
519-
ereport(PANIC,
520-
(errcode_for_file_access(),
521-
errmsg("could not close ptrack control file: %m")));
522-
523-
rel = RelationIdGetRelation(relation_oid);
524-
if (rel == InvalidRelation)
525-
{
526-
elog(WARNING, "Relation not found.");
527-
goto end_return;
528-
}
529-
530-
LockRelationOid(relation_oid, AccessShareLock);
531-
RelationOpenSmgr(rel);
532-
if (rel->rd_smgr == NULL)
533-
goto end_rel;
534-
535-
LockRelationForExtension(rel, ExclusiveLock);
536-
537-
num_blocks = smgrnblocks(rel->rd_smgr, MAIN_FORKNUM);
538-
if (rel->rd_smgr->smgr_ptrack_nblocks == InvalidBlockNumber)
539-
{
540-
if (smgrexists(rel->rd_smgr, PAGESTRACK_FORKNUM))
541-
rel->rd_smgr->smgr_ptrack_nblocks = smgrnblocks(rel->rd_smgr, PAGESTRACK_FORKNUM);
542-
else
543-
rel->rd_smgr->smgr_ptrack_nblocks = 0;
544-
}
545-
546-
for(nblock = 0; nblock < num_blocks; nblock++)
547-
{
548-
Buffer main_buf = ReadBufferExtended(rel,
549-
MAIN_FORKNUM,
550-
nblock,
551-
RBM_ZERO_ON_ERROR,
552-
NULL);
553-
Page main_page;
554-
XLogRecPtr main_page_lsn;
555-
556-
BlockNumber mapBlock = HEAPBLK_TO_MAPBLOCK(nblock);
557-
uint32 mapByte = HEAPBLK_TO_MAPBYTE(nblock);
558-
uint8 mapBit = HEAPBLK_TO_MAPBIT(nblock);
559-
560-
/* Get page lsn */
561-
LockBuffer(main_buf, BUFFER_LOCK_SHARE);
562-
main_page = BufferGetPage(main_buf);
563-
main_page_lsn = PageGetLSN(main_page);
564-
LockBuffer(main_buf, BUFFER_LOCK_UNLOCK);
565-
ReleaseBuffer(main_buf);
566-
567-
/* Reuse the old pinned buffer if possible */
568-
if (BufferIsValid(ptrack_buf))
569-
{
570-
if (BufferGetBlockNumber(ptrack_buf) == mapBlock)
571-
goto read_bit;
572-
else
573-
ReleaseBuffer(ptrack_buf);
574-
}
575-
ptrack_buf = ptrack_readbuf(rel, mapBlock, false);
576-
577-
read_bit:
578-
if (ptrack_buf == InvalidBuffer)
579-
{
580-
/* not tracked data */
581-
if(ptrack_control_lsn < main_page_lsn)
582-
{
583-
necessary_data_counter++;
584-
elog(WARNING, "Block %ud not track. Ptrack lsn:%X/%X page lsn:%X/%X",
585-
nblock,
586-
(uint32) (ptrack_control_lsn >> 32),
587-
(uint32) ptrack_control_lsn,
588-
(uint32) (main_page_lsn >> 32),
589-
(uint32) main_page_lsn);
590-
}
591-
else
592-
continue;
593-
}
594-
595-
page = BufferGetPage(ptrack_buf);
596-
map = PageGetContents(page);
597-
LockBuffer(ptrack_buf, BUFFER_LOCK_SHARE);
598-
if(map[mapByte] & (1 << mapBit))
599-
{
600-
/* excess data */
601-
if (ptrack_control_lsn >= main_page_lsn)
602-
{
603-
excess_data_counter++;
604-
elog(WARNING, "Block %ud not needed. Ptrack lsn:%X/%X page lsn:%X/%X",
605-
nblock,
606-
(uint32) (ptrack_control_lsn >> 32),
607-
(uint32) ptrack_control_lsn,
608-
(uint32) (main_page_lsn >> 32),
609-
(uint32) main_page_lsn);
610-
}
611-
}
612-
/* not tracked data */
613-
else if (ptrack_control_lsn < main_page_lsn)
614-
{
615-
necessary_data_counter++;
616-
elog(WARNING, "Block %ud not tracked. Ptrack lsn:%X/%X page lsn:%X/%X",
617-
nblock,
618-
(uint32) (ptrack_control_lsn >> 32),
619-
(uint32) ptrack_control_lsn,
620-
(uint32) (main_page_lsn >> 32),
621-
(uint32) main_page_lsn);
622-
}
623-
LockBuffer(ptrack_buf, BUFFER_LOCK_UNLOCK);
624-
}
490+
ptrack_clear();
625491

626-
end_rel:
627-
if (ptrack_buf != InvalidBuffer)
628-
ReleaseBuffer(ptrack_buf);
629-
UnlockRelationForExtension(rel, ExclusiveLock);
630-
RelationClose(rel);
631-
UnlockRelationOid(relation_oid, AccessShareLock);
632-
633-
end_return:
634-
result_elems[0] = UInt32GetDatum(excess_data_counter);
635-
result_elems[1] = UInt32GetDatum(necessary_data_counter);
636-
result_array = construct_array(result_elems, 2, 23, 4, true, 'i');
637-
PG_RETURN_ARRAYTYPE_P(result_array);
492+
PG_RETURN_VOID();
638493
}
639494

640-
/* Clear all ptrack files */
495+
/* Read all ptrack files and clear them afterwards */
641496
Datum
642-
pg_ptrack_clear(PG_FUNCTION_ARGS)
497+
pg_ptrack_get_and_clear(PG_FUNCTION_ARGS)
643498
{
644499
if (!superuser() && !has_rolreplication(GetUserId()))
645500
ereport(ERROR,
646501
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
647502
(errmsg("must be superuser or replication role to clear ptrack files"))));
648503

649-
ptrack_clear();
650-
651-
PG_RETURN_VOID();
504+
PG_RETURN_BYTEA_P(ptrack_get_and_clear(PG_GETARG_OID(0), PG_GETARG_OID(1)));
652505
}
653506

654-
/* Read all ptrack files and clear them afterwards */
507+
/*
508+
* Check if PTRACK_INIT_FILE exits in the given database
509+
* and delete it.
510+
* Args: dbOid and tblspcOid
511+
* Return true if file existed.
512+
*/
655513
Datum
656-
pg_ptrack_get_and_clear(PG_FUNCTION_ARGS)
514+
pg_ptrack_get_and_clear_db(PG_FUNCTION_ARGS)
657515
{
516+
char *db_path = GetDatabasePath(PG_GETARG_OID(0), PG_GETARG_OID(1));
517+
struct stat buf;
518+
char ptrack_init_file_path[MAXPGPATH];
519+
658520
if (!superuser() && !has_rolreplication(GetUserId()))
659521
ereport(ERROR,
660522
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
661523
(errmsg("must be superuser or replication role to clear ptrack files"))));
662524

663-
PG_RETURN_BYTEA_P(ptrack_get_and_clear(PG_GETARG_OID(0), PG_GETARG_OID(1)));
525+
snprintf(ptrack_init_file_path, sizeof(ptrack_init_file_path), "%s/%s", db_path, PTRACK_INIT_FILE);
526+
527+
if (stat(ptrack_init_file_path, &buf) == -1 && errno == ENOENT)
528+
PG_RETURN_BOOL(false);
529+
else if (!S_ISREG(buf.st_mode))
530+
PG_RETURN_BOOL(false);
531+
else
532+
{
533+
drop_ptrack_init_file(db_path);
534+
PG_RETURN_BOOL(true);
535+
}
536+
}
537+
538+
/* create empty ptrack_init_file */
539+
void
540+
create_ptrack_init_file(char *dest_dir)
541+
{
542+
int dstfd;
543+
544+
char ptrack_init_file_path[MAXPGPATH];
545+
snprintf(ptrack_init_file_path, sizeof(ptrack_init_file_path), "%s/%s", dest_dir, PTRACK_INIT_FILE);
546+
547+
dstfd = OpenTransientFile(ptrack_init_file_path, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
548+
S_IRUSR | S_IWUSR);
549+
if (dstfd < 0)
550+
{
551+
if (errno != EEXIST)
552+
ereport(ERROR,
553+
(errcode_for_file_access(),
554+
errmsg("could not create file \"%s\": %m", ptrack_init_file_path)));
555+
}
556+
else if (CloseTransientFile(dstfd))
557+
ereport(ERROR,
558+
(errcode_for_file_access(),
559+
errmsg("could not close file \"%s\": %m", ptrack_init_file_path)));
560+
}
561+
562+
void
563+
drop_ptrack_init_file(char *dest_dir)
564+
{
565+
char ptrack_init_file_path[MAXPGPATH];
566+
snprintf(ptrack_init_file_path, sizeof(ptrack_init_file_path), "%s/%s", dest_dir, PTRACK_INIT_FILE);
567+
568+
if (unlink(ptrack_init_file_path) != 0)
569+
{
570+
if (errno != ENOENT)
571+
ereport(WARNING,
572+
(errcode_for_file_access(),
573+
errmsg("could not remove file \"%s\": %m", ptrack_init_file_path)));
574+
}
664575
}
665576

666577
/*
@@ -672,3 +583,36 @@ ptrack_version(PG_FUNCTION_ARGS)
672583
{
673584
PG_RETURN_TEXT_P(cstring_to_text(PTRACK_VERSION));
674585
}
586+
587+
/* Get lsn from ptrack_control file */
588+
Datum
589+
pg_ptrack_control_lsn(PG_FUNCTION_ARGS)
590+
{
591+
int fd;
592+
char file_path[MAXPGPATH];
593+
XLogRecPtr lsn = 0;
594+
595+
if (!superuser() && !has_rolreplication(GetUserId()))
596+
ereport(ERROR,
597+
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
598+
(errmsg("must be superuser or replication role read ptrack files"))));
599+
join_path_components(file_path, DataDir, "global/ptrack_control");
600+
canonicalize_path(file_path);
601+
602+
fd = BasicOpenFile(file_path, O_RDONLY | PG_BINARY, 0);
603+
if (fd < 0)
604+
ereport(ERROR,
605+
(errcode_for_file_access(),
606+
errmsg("could not open file \"%s\" for reading: %m",
607+
file_path)));
608+
609+
if (read(fd, &lsn, sizeof(XLogRecPtr)) != sizeof(XLogRecPtr))
610+
ereport(ERROR,
611+
(errcode_for_file_access(),
612+
errmsg("could not read content of the file \"%s\" %m",
613+
file_path)));
614+
615+
close(fd);
616+
617+
PG_RETURN_LSN(lsn);
618+
}

src/backend/commands/dbcommands.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "access/xact.h"
3131
#include "access/xloginsert.h"
3232
#include "access/xlogutils.h"
33+
#include "access/ptrack.h"
3334
#include "catalog/catalog.h"
3435
#include "catalog/dependency.h"
3536
#include "catalog/indexing.h"
@@ -616,6 +617,7 @@ createdb(const CreatedbStmt *stmt)
616617
* We don't need to copy subdirectories
617618
*/
618619
copydir(srcpath, dstpath, false);
620+
create_ptrack_init_file(dstpath);
619621

620622
/* Record the filesystem change in XLOG */
621623
{
@@ -1222,6 +1224,7 @@ movedb(const char *dbname, const char *tblspcname)
12221224
* Copy files from the old tablespace to the new one
12231225
*/
12241226
copydir(src_dbpath, dst_dbpath, false);
1227+
create_ptrack_init_file(dst_dbpath);
12251228

12261229
/*
12271230
* Record the filesystem change in XLOG
@@ -2085,6 +2088,7 @@ dbase_redo(XLogReaderState *record)
20852088
* We don't need to copy subdirectories
20862089
*/
20872090
copydir(src_path, dst_path, false);
2091+
create_ptrack_init_file(dst_path);
20882092
}
20892093
else if (info == XLOG_DBASE_DROP)
20902094
{

src/include/access/ptrack.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,23 @@
88
#include "utils/relcache.h"
99

1010
/* Ptrack version as a string */
11-
#define PTRACK_VERSION "1.2"
11+
#define PTRACK_VERSION "1.3"
1212
/* Ptrack version as a number */
13-
#define PTRACK_VERSION_NUM 102
13+
#define PTRACK_VERSION_NUM 103
1414

1515
/* Number of bits allocated for each heap block. */
1616
#define PTRACK_BITS_PER_HEAPBLOCK 1
1717

18+
#define PTRACK_INIT_FILE "ptrack_init"
19+
1820
extern PGDLLIMPORT bool ptrack_enable;
1921

2022
extern void ptrack_add_block(Relation rel, BlockNumber heapBlk);
2123
extern void ptrack_add_block_redo(RelFileNode rnode, BlockNumber heapBlk);
2224
extern void ptrack_pin(Relation rel, BlockNumber heapBlk, Buffer *buf);
2325
extern void ptrack_set(BlockNumber heapBlk, Buffer ptrackBuf);
26+
extern void create_ptrack_init_file(char *dest_dir);
27+
extern void drop_ptrack_init_file(char *dest_dir);
2428

2529
extern void ptrack_clear(void);
2630
extern bytea *ptrack_get_and_clear(Oid tablespace_oid, Oid table_oid);

0 commit comments

Comments
 (0)