PostgreSQL Source Code git master
Macros | Typedefs | Functions
blkreftable.h File Reference
#include "storage/block.h"
#include "storage/relfilelocator.h"
Include dependency graph for blkreftable.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define  BLOCKREFTABLE_MAGIC   0x652b137b
 

Typedefs

typedef struct BlockRefTable  BlockRefTable
 
 
 
 
typedef int(*  io_callback_fn) (void *callback_arg, void *data, int length)
 
typedef void(*  report_error_fn) (void *callback_arg, char *msg,...) pg_attribute_printf(2
 
typedef void(*) BlockRefTable  CreateEmptyBlockRefTable) (void)
 

Functions

void  BlockRefTableSetLimitBlock (BlockRefTable *brtab, const RelFileLocator *rlocator, ForkNumber forknum, BlockNumber limit_block)
 
void  BlockRefTableMarkBlockModified (BlockRefTable *brtab, const RelFileLocator *rlocator, ForkNumber forknum, BlockNumber blknum)
 
void  WriteBlockRefTable (BlockRefTable *brtab, io_callback_fn write_callback, void *write_callback_arg)
 
BlockRefTableEntryBlockRefTableGetEntry (BlockRefTable *brtab, const RelFileLocator *rlocator, ForkNumber forknum, BlockNumber *limit_block)
 
int  BlockRefTableEntryGetBlocks (BlockRefTableEntry *entry, BlockNumber start_blkno, BlockNumber stop_blkno, BlockNumber *blocks, int nblocks)
 
BlockRefTableReaderCreateBlockRefTableReader (io_callback_fn read_callback, void *read_callback_arg, char *error_filename, report_error_fn error_callback, void *error_callback_arg)
 
bool  BlockRefTableReaderNextRelation (BlockRefTableReader *reader, RelFileLocator *rlocator, ForkNumber *forknum, BlockNumber *limit_block)
 
unsigned  BlockRefTableReaderGetBlocks (BlockRefTableReader *reader, BlockNumber *blocks, int nblocks)
 
 
BlockRefTableWriterCreateBlockRefTableWriter (io_callback_fn write_callback, void *write_callback_arg)
 
 
 
 
 
 
 

Macro Definition Documentation

BLOCKREFTABLE_MAGIC

#define BLOCKREFTABLE_MAGIC   0x652b137b

Definition at line 30 of file blkreftable.h.

Typedef Documentation

BlockRefTable

typedef struct BlockRefTable BlockRefTable

Definition at line 32 of file blkreftable.h.

BlockRefTableEntry

Definition at line 33 of file blkreftable.h.

BlockRefTableReader

Definition at line 34 of file blkreftable.h.

BlockRefTableWriter

Definition at line 35 of file blkreftable.h.

CreateEmptyBlockRefTable

typedef void(*) BlockRefTable CreateEmptyBlockRefTable) (void)
extern

io_callback_fn

typedef int(* io_callback_fn) (void *callback_arg, void *data, int length)

Definition at line 46 of file blkreftable.h.

report_error_fn

typedef void(* report_error_fn) (void *callback_arg, char *msg,...) pg_attribute_printf(2

Definition at line 47 of file blkreftable.h.

Function Documentation

BlockRefTableEntryGetBlocks()

int BlockRefTableEntryGetBlocks ( BlockRefTableEntryentry,
BlockNumber  start_blkno,
BlockNumber  stop_blkno,
BlockNumberblocks,
int  nblocks 
)

Definition at line 369 of file blkreftable.c.

374{
375 uint32 start_chunkno;
376 uint32 stop_chunkno;
377 uint32 chunkno;
378 int nresults = 0;
379
380 Assert(entry != NULL);
381
382 /*
383 * Figure out which chunks could potentially contain blocks of interest.
384 *
385 * We need to be careful about overflow here, because stop_blkno could be
386 * InvalidBlockNumber or something very close to it.
387 */
388 start_chunkno = start_blkno / BLOCKS_PER_CHUNK;
389 stop_chunkno = stop_blkno / BLOCKS_PER_CHUNK;
390 if ((stop_blkno % BLOCKS_PER_CHUNK) != 0)
391 ++stop_chunkno;
392 if (stop_chunkno > entry->nchunks)
393 stop_chunkno = entry->nchunks;
394
395 /*
396 * Loop over chunks.
397 */
398 for (chunkno = start_chunkno; chunkno < stop_chunkno; ++chunkno)
399 {
400 uint16 chunk_usage = entry->chunk_usage[chunkno];
401 BlockRefTableChunk chunk_data = entry->chunk_data[chunkno];
402 unsigned start_offset = 0;
403 unsigned stop_offset = BLOCKS_PER_CHUNK;
404
405 /*
406 * If the start and/or stop block number falls within this chunk, the
407 * whole chunk may not be of interest. Figure out which portion we
408 * care about, if it's not the whole thing.
409 */
410 if (chunkno == start_chunkno)
411 start_offset = start_blkno % BLOCKS_PER_CHUNK;
412 if (chunkno == stop_chunkno - 1)
413 {
414 Assert(stop_blkno > chunkno * BLOCKS_PER_CHUNK);
415 stop_offset = stop_blkno - (chunkno * BLOCKS_PER_CHUNK);
416 Assert(stop_offset <= BLOCKS_PER_CHUNK);
417 }
418
419 /*
420 * Handling differs depending on whether this is an array of offsets
421 * or a bitmap.
422 */
423 if (chunk_usage == MAX_ENTRIES_PER_CHUNK)
424 {
425 unsigned i;
426
427 /* It's a bitmap, so test every relevant bit. */
428 for (i = start_offset; i < stop_offset; ++i)
429 {
430 uint16 w = chunk_data[i / BLOCKS_PER_ENTRY];
431
432 if ((w & (1 << (i % BLOCKS_PER_ENTRY))) != 0)
433 {
434 BlockNumber blkno = chunkno * BLOCKS_PER_CHUNK + i;
435
436 blocks[nresults++] = blkno;
437
438 /* Early exit if we run out of output space. */
439 if (nresults == nblocks)
440 return nresults;
441 }
442 }
443 }
444 else
445 {
446 unsigned i;
447
448 /* It's an array of offsets, so check each one. */
449 for (i = 0; i < chunk_usage; ++i)
450 {
451 uint16 offset = chunk_data[i];
452
453 if (offset >= start_offset && offset < stop_offset)
454 {
455 BlockNumber blkno = chunkno * BLOCKS_PER_CHUNK + offset;
456
457 blocks[nresults++] = blkno;
458
459 /* Early exit if we run out of output space. */
460 if (nresults == nblocks)
461 return nresults;
462 }
463 }
464 }
465 }
466
467 return nresults;
468}
#define BLOCKS_PER_CHUNK
Definition: blkreftable.c:78
#define BLOCKS_PER_ENTRY
Definition: blkreftable.c:79
#define MAX_ENTRIES_PER_CHUNK
Definition: blkreftable.c:80
uint16 * BlockRefTableChunk
Definition: blkreftable.c:82
uint32 BlockNumber
Definition: block.h:31
uint16_t uint16
Definition: c.h:537
uint32_t uint32
Definition: c.h:538
Assert(PointerIsAligned(start, uint64))
i
int i
Definition: isn.c:77
uint16 * chunk_usage
Definition: blkreftable.c:117
BlockRefTableChunk * chunk_data
Definition: blkreftable.c:118

References Assert(), BLOCKS_PER_CHUNK, BLOCKS_PER_ENTRY, BlockRefTableEntry::chunk_data, BlockRefTableEntry::chunk_usage, i, MAX_ENTRIES_PER_CHUNK, and BlockRefTableEntry::nchunks.

Referenced by GetFileBackupMethod().

BlockRefTableEntryMarkBlockModified()

void BlockRefTableEntryMarkBlockModified ( BlockRefTableEntryentry,
ForkNumber  forknum,
BlockNumber  blknum 
)

Definition at line 965 of file blkreftable.c.

968{
969 unsigned chunkno;
970 unsigned chunkoffset;
971 unsigned i;
972
973 /*
974 * Which chunk should store the state of this block? And what is the
975 * offset of this block relative to the start of that chunk?
976 */
977 chunkno = blknum / BLOCKS_PER_CHUNK;
978 chunkoffset = blknum % BLOCKS_PER_CHUNK;
979
980 /*
981 * If 'nchunks' isn't big enough for us to be able to represent the state
982 * of this block, we need to enlarge our arrays.
983 */
984 if (chunkno >= entry->nchunks)
985 {
986 unsigned max_chunks;
987 unsigned extra_chunks;
988
989 /*
990 * New array size is a power of 2, at least 16, big enough so that
991 * chunkno will be a valid array index.
992 */
993 max_chunks = Max(16, entry->nchunks);
994 while (max_chunks < chunkno + 1)
995 max_chunks *= 2;
996 extra_chunks = max_chunks - entry->nchunks;
997
998 if (entry->nchunks == 0)
999 {
1000 entry->chunk_size = palloc0(sizeof(uint16) * max_chunks);
1001 entry->chunk_usage = palloc0(sizeof(uint16) * max_chunks);
1002 entry->chunk_data =
1003 palloc0(sizeof(BlockRefTableChunk) * max_chunks);
1004 }
1005 else
1006 {
1007 entry->chunk_size = repalloc(entry->chunk_size,
1008 sizeof(uint16) * max_chunks);
1009 memset(&entry->chunk_size[entry->nchunks], 0,
1010 extra_chunks * sizeof(uint16));
1011 entry->chunk_usage = repalloc(entry->chunk_usage,
1012 sizeof(uint16) * max_chunks);
1013 memset(&entry->chunk_usage[entry->nchunks], 0,
1014 extra_chunks * sizeof(uint16));
1015 entry->chunk_data = repalloc(entry->chunk_data,
1016 sizeof(BlockRefTableChunk) * max_chunks);
1017 memset(&entry->chunk_data[entry->nchunks], 0,
1018 extra_chunks * sizeof(BlockRefTableChunk));
1019 }
1020 entry->nchunks = max_chunks;
1021 }
1022
1023 /*
1024 * If the chunk that covers this block number doesn't exist yet, create it
1025 * as an array and add the appropriate offset to it. We make it pretty
1026 * small initially, because there might only be 1 or a few block
1027 * references in this chunk and we don't want to use up too much memory.
1028 */
1029 if (entry->chunk_size[chunkno] == 0)
1030 {
1031 entry->chunk_data[chunkno] =
1033 entry->chunk_size[chunkno] = INITIAL_ENTRIES_PER_CHUNK;
1034 entry->chunk_data[chunkno][0] = chunkoffset;
1035 entry->chunk_usage[chunkno] = 1;
1036 return;
1037 }
1038
1039 /*
1040 * If the number of entries in this chunk is already maximum, it must be a
1041 * bitmap. Just set the appropriate bit.
1042 */
1043 if (entry->chunk_usage[chunkno] == MAX_ENTRIES_PER_CHUNK)
1044 {
1045 BlockRefTableChunk chunk = entry->chunk_data[chunkno];
1046
1047 chunk[chunkoffset / BLOCKS_PER_ENTRY] |=
1048 1 << (chunkoffset % BLOCKS_PER_ENTRY);
1049 return;
1050 }
1051
1052 /*
1053 * There is an existing chunk and it's in array format. Let's find out
1054 * whether it already has an entry for this block. If so, we do not need
1055 * to do anything.
1056 */
1057 for (i = 0; i < entry->chunk_usage[chunkno]; ++i)
1058 {
1059 if (entry->chunk_data[chunkno][i] == chunkoffset)
1060 return;
1061 }
1062
1063 /*
1064 * If the number of entries currently used is one less than the maximum,
1065 * it's time to convert to bitmap format.
1066 */
1067 if (entry->chunk_usage[chunkno] == MAX_ENTRIES_PER_CHUNK - 1)
1068 {
1069 BlockRefTableChunk newchunk;
1070 unsigned j;
1071
1072 /* Allocate a new chunk. */
1073 newchunk = palloc0(MAX_ENTRIES_PER_CHUNK * sizeof(uint16));
1074
1075 /* Set the bit for each existing entry. */
1076 for (j = 0; j < entry->chunk_usage[chunkno]; ++j)
1077 {
1078 unsigned coff = entry->chunk_data[chunkno][j];
1079
1080 newchunk[coff / BLOCKS_PER_ENTRY] |=
1081 1 << (coff % BLOCKS_PER_ENTRY);
1082 }
1083
1084 /* Set the bit for the new entry. */
1085 newchunk[chunkoffset / BLOCKS_PER_ENTRY] |=
1086 1 << (chunkoffset % BLOCKS_PER_ENTRY);
1087
1088 /* Swap the new chunk into place and update metadata. */
1089 pfree(entry->chunk_data[chunkno]);
1090 entry->chunk_data[chunkno] = newchunk;
1091 entry->chunk_size[chunkno] = MAX_ENTRIES_PER_CHUNK;
1092 entry->chunk_usage[chunkno] = MAX_ENTRIES_PER_CHUNK;
1093 return;
1094 }
1095
1096 /*
1097 * OK, we currently have an array, and we don't need to convert to a
1098 * bitmap, but we do need to add a new element. If there's not enough
1099 * room, we'll have to expand the array.
1100 */
1101 if (entry->chunk_usage[chunkno] == entry->chunk_size[chunkno])
1102 {
1103 unsigned newsize = entry->chunk_size[chunkno] * 2;
1104
1105 Assert(newsize <= MAX_ENTRIES_PER_CHUNK);
1106 entry->chunk_data[chunkno] = repalloc(entry->chunk_data[chunkno],
1107 newsize * sizeof(uint16));
1108 entry->chunk_size[chunkno] = newsize;
1109 }
1110
1111 /* Now we can add the new entry. */
1112 entry->chunk_data[chunkno][entry->chunk_usage[chunkno]] =
1113 chunkoffset;
1114 entry->chunk_usage[chunkno]++;
1115}
#define INITIAL_ENTRIES_PER_CHUNK
Definition: blkreftable.c:81
#define Max(x, y)
Definition: c.h:997
j
int j
Definition: isn.c:78
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1610
void pfree(void *pointer)
Definition: mcxt.c:1594
void * palloc0(Size size)
Definition: mcxt.c:1395
void * palloc(Size size)
Definition: mcxt.c:1365
uint16 * chunk_size
Definition: blkreftable.c:116

References Assert(), BLOCKS_PER_CHUNK, BLOCKS_PER_ENTRY, BlockRefTableEntry::chunk_data, BlockRefTableEntry::chunk_size, BlockRefTableEntry::chunk_usage, i, INITIAL_ENTRIES_PER_CHUNK, j, Max, MAX_ENTRIES_PER_CHUNK, BlockRefTableEntry::nchunks, palloc(), palloc0(), pfree(), and repalloc().

Referenced by BlockRefTableMarkBlockModified().

BlockRefTableEntrySetLimitBlock()

void BlockRefTableEntrySetLimitBlock ( BlockRefTableEntryentry,
BlockNumber  limit_block 
)

Definition at line 894 of file blkreftable.c.

896{
897 unsigned chunkno;
898 unsigned limit_chunkno;
899 unsigned limit_chunkoffset;
900 BlockRefTableChunk limit_chunk;
901
902 /* If we already have an equal or lower limit block, do nothing. */
903 if (limit_block >= entry->limit_block)
904 return;
905
906 /* Record the new limit block value. */
907 entry->limit_block = limit_block;
908
909 /*
910 * Figure out which chunk would store the state of the new limit block,
911 * and which offset within that chunk.
912 */
913 limit_chunkno = limit_block / BLOCKS_PER_CHUNK;
914 limit_chunkoffset = limit_block % BLOCKS_PER_CHUNK;
915
916 /*
917 * If the number of chunks is not large enough for any blocks with equal
918 * or higher block numbers to exist, then there is nothing further to do.
919 */
920 if (limit_chunkno >= entry->nchunks)
921 return;
922
923 /* Discard entire contents of any higher-numbered chunks. */
924 for (chunkno = limit_chunkno + 1; chunkno < entry->nchunks; ++chunkno)
925 entry->chunk_usage[chunkno] = 0;
926
927 /*
928 * Next, we need to discard any offsets within the chunk that would
929 * contain the limit_block. We must handle this differently depending on
930 * whether the chunk that would contain limit_block is a bitmap or an
931 * array of offsets.
932 */
933 limit_chunk = entry->chunk_data[limit_chunkno];
934 if (entry->chunk_usage[limit_chunkno] == MAX_ENTRIES_PER_CHUNK)
935 {
936 unsigned chunkoffset;
937
938 /* It's a bitmap. Unset bits. */
939 for (chunkoffset = limit_chunkoffset; chunkoffset < BLOCKS_PER_CHUNK;
940 ++chunkoffset)
941 limit_chunk[chunkoffset / BLOCKS_PER_ENTRY] &=
942 ~(1 << (chunkoffset % BLOCKS_PER_ENTRY));
943 }
944 else
945 {
946 unsigned i,
947 j = 0;
948
949 /* It's an offset array. Filter out large offsets. */
950 for (i = 0; i < entry->chunk_usage[limit_chunkno]; ++i)
951 {
952 Assert(j <= i);
953 if (limit_chunk[i] < limit_chunkoffset)
954 limit_chunk[j++] = limit_chunk[i];
955 }
956 Assert(j <= entry->chunk_usage[limit_chunkno]);
957 entry->chunk_usage[limit_chunkno] = j;
958 }
959}
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:81
BlockNumber limit_block
Definition: blkreftable.c:113

References Assert(), BLOCKS_PER_CHUNK, BLOCKS_PER_ENTRY, BlockRefTableEntry::chunk_data, BlockRefTableEntry::chunk_usage, i, if(), j, BlockRefTableEntry::limit_block, MAX_ENTRIES_PER_CHUNK, and BlockRefTableEntry::nchunks.

Referenced by BlockRefTableSetLimitBlock().

BlockRefTableFreeEntry()

void BlockRefTableFreeEntry ( BlockRefTableEntryentry )

Definition at line 1122 of file blkreftable.c.

1123{
1124 if (entry->chunk_size != NULL)
1125 {
1126 pfree(entry->chunk_size);
1127 entry->chunk_size = NULL;
1128 }
1129
1130 if (entry->chunk_usage != NULL)
1131 {
1132 pfree(entry->chunk_usage);
1133 entry->chunk_usage = NULL;
1134 }
1135
1136 if (entry->chunk_data != NULL)
1137 {
1138 pfree(entry->chunk_data);
1139 entry->chunk_data = NULL;
1140 }
1141
1142 pfree(entry);
1143}

References BlockRefTableEntry::chunk_data, BlockRefTableEntry::chunk_size, BlockRefTableEntry::chunk_usage, and pfree().

BlockRefTableGetEntry()

BlockRefTableEntry * BlockRefTableGetEntry ( BlockRefTablebrtab,
const RelFileLocatorrlocator,
ForkNumber  forknum,
BlockNumberlimit_block 
)

Definition at line 340 of file blkreftable.c.

342{
343 BlockRefTableKey key = {0}; /* make sure any padding is zero */
344 BlockRefTableEntry *entry;
345
346 Assert(limit_block != NULL);
347
348 memcpy(&key.rlocator, rlocator, sizeof(RelFileLocator));
349 key.forknum = forknum;
350 entry = blockreftable_lookup(brtab->hash, key);
351
352 if (entry != NULL)
353 *limit_block = entry->limit_block;
354
355 return entry;
356}
blockreftable_hash * hash
Definition: blkreftable.c:146

References Assert(), BlockRefTable::hash, sort-test::key, and BlockRefTableEntry::limit_block.

Referenced by GetFileBackupMethod().

BlockRefTableMarkBlockModified()

void BlockRefTableMarkBlockModified ( BlockRefTablebrtab,
const RelFileLocatorrlocator,
ForkNumber  forknum,
BlockNumber  blknum 
)

Definition at line 297 of file blkreftable.c.

301{
302 BlockRefTableEntry *brtentry;
303 BlockRefTableKey key = {0}; /* make sure any padding is zero */
304 bool found;
305#ifndef FRONTEND
306 MemoryContext oldcontext = MemoryContextSwitchTo(brtab->mcxt);
307#endif
308
309 memcpy(&key.rlocator, rlocator, sizeof(RelFileLocator));
310 key.forknum = forknum;
311 brtentry = blockreftable_insert(brtab->hash, key, &found);
312
313 if (!found)
314 {
315 /*
316 * We want to set the initial limit block value to something higher
317 * than any legal block number. InvalidBlockNumber fits the bill.
318 */
320 brtentry->nchunks = 0;
321 brtentry->chunk_size = NULL;
322 brtentry->chunk_usage = NULL;
323 brtentry->chunk_data = NULL;
324 }
325
326 BlockRefTableEntryMarkBlockModified(brtentry, forknum, blknum);
327
328#ifndef FRONTEND
329 MemoryContextSwitchTo(oldcontext);
330#endif
331}
void BlockRefTableEntryMarkBlockModified(BlockRefTableEntry *entry, ForkNumber forknum, BlockNumber blknum)
Definition: blkreftable.c:965
#define InvalidBlockNumber
Definition: block.h:33
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
MemoryContext mcxt
Definition: blkreftable.c:148

References BlockRefTableEntryMarkBlockModified(), BlockRefTableEntry::chunk_data, BlockRefTableEntry::chunk_size, BlockRefTableEntry::chunk_usage, BlockRefTable::hash, InvalidBlockNumber, sort-test::key, BlockRefTableEntry::limit_block, BlockRefTable::mcxt, MemoryContextSwitchTo(), and BlockRefTableEntry::nchunks.

Referenced by PrepareForIncrementalBackup(), and SummarizeWAL().

BlockRefTableReaderGetBlocks()

unsigned BlockRefTableReaderGetBlocks ( BlockRefTableReaderreader,
BlockNumberblocks,
int  nblocks 
)

Definition at line 689 of file blkreftable.c.

692{
693 unsigned blocks_found = 0;
694
695 /* Must provide space for at least one block number to be returned. */
696 Assert(nblocks > 0);
697
698 /* Loop collecting blocks to return to caller. */
699 for (;;)
700 {
701 uint16 next_chunk_size;
702
703 /*
704 * If we've read at least one chunk, maybe it contains some block
705 * numbers that could satisfy caller's request.
706 */
707 if (reader->consumed_chunks > 0)
708 {
709 uint32 chunkno = reader->consumed_chunks - 1;
710 uint16 chunk_size = reader->chunk_size[chunkno];
711
712 if (chunk_size == MAX_ENTRIES_PER_CHUNK)
713 {
714 /* Bitmap format, so search for bits that are set. */
715 while (reader->chunk_position < BLOCKS_PER_CHUNK &&
716 blocks_found < nblocks)
717 {
718 uint16 chunkoffset = reader->chunk_position;
719 uint16 w;
720
721 w = reader->chunk_data[chunkoffset / BLOCKS_PER_ENTRY];
722 if ((w & (1u << (chunkoffset % BLOCKS_PER_ENTRY))) != 0)
723 blocks[blocks_found++] =
724 chunkno * BLOCKS_PER_CHUNK + chunkoffset;
725 ++reader->chunk_position;
726 }
727 }
728 else
729 {
730 /* Not in bitmap format, so each entry is a 2-byte offset. */
731 while (reader->chunk_position < chunk_size &&
732 blocks_found < nblocks)
733 {
734 blocks[blocks_found++] = chunkno * BLOCKS_PER_CHUNK
735 + reader->chunk_data[reader->chunk_position];
736 ++reader->chunk_position;
737 }
738 }
739 }
740
741 /* We found enough blocks, so we're done. */
742 if (blocks_found >= nblocks)
743 break;
744
745 /*
746 * We didn't find enough blocks, so we must need the next chunk. If
747 * there are none left, though, then we're done anyway.
748 */
749 if (reader->consumed_chunks == reader->total_chunks)
750 break;
751
752 /*
753 * Read data for next chunk and reset scan position to beginning of
754 * chunk. Note that the next chunk might be empty, in which case we
755 * consume the chunk without actually consuming any bytes from the
756 * underlying file.
757 */
758 next_chunk_size = reader->chunk_size[reader->consumed_chunks];
759 if (next_chunk_size > 0)
760 BlockRefTableRead(reader, reader->chunk_data,
761 next_chunk_size * sizeof(uint16));
762 ++reader->consumed_chunks;
763 reader->chunk_position = 0;
764 }
765
766 return blocks_found;
767}
static void BlockRefTableRead(BlockRefTableReader *reader, void *data, int length)
Definition: blkreftable.c:1196
uint16 chunk_data[MAX_ENTRIES_PER_CHUNK]
Definition: blkreftable.c:209
uint32 consumed_chunks
Definition: blkreftable.c:207
uint16 * chunk_size
Definition: blkreftable.c:208
uint32 chunk_position
Definition: blkreftable.c:210

References Assert(), BlockRefTableRead(), BLOCKS_PER_CHUNK, BLOCKS_PER_ENTRY, BlockRefTableReader::chunk_data, BlockRefTableReader::chunk_position, BlockRefTableReader::chunk_size, BlockRefTableReader::consumed_chunks, MAX_ENTRIES_PER_CHUNK, and BlockRefTableReader::total_chunks.

Referenced by dump_one_relation(), pg_wal_summary_contents(), and PrepareForIncrementalBackup().

BlockRefTableReaderNextRelation()

bool BlockRefTableReaderNextRelation ( BlockRefTableReaderreader,
RelFileLocatorrlocator,
ForkNumberforknum,
BlockNumberlimit_block 
)

Definition at line 613 of file blkreftable.c.

617{
619 BlockRefTableSerializedEntry zentry = {0};
620
621 /*
622 * Sanity check: caller must read all blocks from all chunks before moving
623 * on to the next relation.
624 */
625 Assert(reader->total_chunks == reader->consumed_chunks);
626
627 /* Read serialized entry. */
628 BlockRefTableRead(reader, &sentry,
630
631 /*
632 * If we just read the sentinel entry indicating that we've reached the
633 * end, read and check the CRC.
634 */
635 if (memcmp(&sentry, &zentry, sizeof(BlockRefTableSerializedEntry)) == 0)
636 {
637 pg_crc32c expected_crc;
638 pg_crc32c actual_crc;
639
640 /*
641 * We want to know the CRC of the file excluding the 4-byte CRC
642 * itself, so copy the current value of the CRC accumulator before
643 * reading those bytes, and use the copy to finalize the calculation.
644 */
645 expected_crc = reader->buffer.crc;
646 FIN_CRC32C(expected_crc);
647
648 /* Now we can read the actual value. */
649 BlockRefTableRead(reader, &actual_crc, sizeof(pg_crc32c));
650
651 /* Throw an error if there is a mismatch. */
652 if (!EQ_CRC32C(expected_crc, actual_crc))
653 reader->error_callback(reader->error_callback_arg,
654 "file \"%s\" has wrong checksum: expected %08X, found %08X",
655 reader->error_filename, expected_crc, actual_crc);
656
657 return false;
658 }
659
660 /* Read chunk size array. */
661 if (reader->chunk_size != NULL)
662 pfree(reader->chunk_size);
663 reader->chunk_size = palloc(sentry.nchunks * sizeof(uint16));
664 BlockRefTableRead(reader, reader->chunk_size,
665 sentry.nchunks * sizeof(uint16));
666
667 /* Set up for chunk scan. */
668 reader->total_chunks = sentry.nchunks;
669 reader->consumed_chunks = 0;
670
671 /* Return data to caller. */
672 memcpy(rlocator, &sentry.rlocator, sizeof(RelFileLocator));
673 *forknum = sentry.forknum;
674 *limit_block = sentry.limit_block;
675 return true;
676}
uint32 pg_crc32c
Definition: pg_crc32c.h:38
#define EQ_CRC32C(c1, c2)
Definition: pg_crc32c.h:42
#define FIN_CRC32C(crc)
Definition: pg_crc32c.h:158
BlockRefTableBuffer buffer
Definition: blkreftable.c:202
void * error_callback_arg
Definition: blkreftable.c:205
char * error_filename
Definition: blkreftable.c:203
report_error_fn error_callback
Definition: blkreftable.c:204
RelFileLocator rlocator
Definition: blkreftable.c:157

References Assert(), BlockRefTableRead(), BlockRefTableReader::buffer, BlockRefTableReader::chunk_size, BlockRefTableReader::consumed_chunks, BlockRefTableBuffer::crc, EQ_CRC32C, BlockRefTableReader::error_callback, BlockRefTableReader::error_callback_arg, BlockRefTableReader::error_filename, FIN_CRC32C, BlockRefTableSerializedEntry::forknum, BlockRefTableSerializedEntry::limit_block, BlockRefTableSerializedEntry::nchunks, palloc(), pfree(), BlockRefTableSerializedEntry::rlocator, and BlockRefTableReader::total_chunks.

Referenced by main(), pg_wal_summary_contents(), and PrepareForIncrementalBackup().

BlockRefTableSetLimitBlock()

void BlockRefTableSetLimitBlock ( BlockRefTablebrtab,
const RelFileLocatorrlocator,
ForkNumber  forknum,
BlockNumber  limit_block 
)

Definition at line 262 of file blkreftable.c.

266{
267 BlockRefTableEntry *brtentry;
268 BlockRefTableKey key = {0}; /* make sure any padding is zero */
269 bool found;
270
271 memcpy(&key.rlocator, rlocator, sizeof(RelFileLocator));
272 key.forknum = forknum;
273 brtentry = blockreftable_insert(brtab->hash, key, &found);
274
275 if (!found)
276 {
277 /*
278 * We have no existing data about this relation fork, so just record
279 * the limit_block value supplied by the caller, and make sure other
280 * parts of the entry are properly initialized.
281 */
282 brtentry->limit_block = limit_block;
283 brtentry->nchunks = 0;
284 brtentry->chunk_size = NULL;
285 brtentry->chunk_usage = NULL;
286 brtentry->chunk_data = NULL;
287 return;
288 }
289
290 BlockRefTableEntrySetLimitBlock(brtentry, limit_block);
291}
void BlockRefTableEntrySetLimitBlock(BlockRefTableEntry *entry, BlockNumber limit_block)
Definition: blkreftable.c:894

References BlockRefTableEntrySetLimitBlock(), BlockRefTableEntry::chunk_data, BlockRefTableEntry::chunk_size, BlockRefTableEntry::chunk_usage, BlockRefTable::hash, sort-test::key, BlockRefTableEntry::limit_block, and BlockRefTableEntry::nchunks.

Referenced by PrepareForIncrementalBackup(), SummarizeDbaseRecord(), SummarizeSmgrRecord(), and SummarizeXactRecord().

BlockRefTableWriteEntry()

void BlockRefTableWriteEntry ( BlockRefTableWriterwriter,
BlockRefTableEntryentry 
)

Definition at line 817 of file blkreftable.c.

818{
820 unsigned j;
821
822 /* Convert to serialized entry format. */
823 sentry.rlocator = entry->key.rlocator;
824 sentry.forknum = entry->key.forknum;
825 sentry.limit_block = entry->limit_block;
826 sentry.nchunks = entry->nchunks;
827
828 /* Trim trailing zero entries. */
829 while (sentry.nchunks > 0 && entry->chunk_usage[sentry.nchunks - 1] == 0)
830 sentry.nchunks--;
831
832 /* Write the serialized entry itself. */
833 BlockRefTableWrite(&writer->buffer, &sentry,
835
836 /* Write the untruncated portion of the chunk length array. */
837 if (sentry.nchunks != 0)
838 BlockRefTableWrite(&writer->buffer, entry->chunk_usage,
839 sentry.nchunks * sizeof(uint16));
840
841 /* Write the contents of each chunk. */
842 for (j = 0; j < entry->nchunks; ++j)
843 {
844 if (entry->chunk_usage[j] == 0)
845 continue;
846 BlockRefTableWrite(&writer->buffer, entry->chunk_data[j],
847 entry->chunk_usage[j] * sizeof(uint16));
848 }
849}
static void BlockRefTableWrite(BlockRefTableBuffer *buffer, void *data, int length)
Definition: blkreftable.c:1261
BlockRefTableKey key
Definition: blkreftable.c:112
RelFileLocator rlocator
Definition: blkreftable.c:49
ForkNumber forknum
Definition: blkreftable.c:50
BlockRefTableBuffer buffer
Definition: blkreftable.c:219

References BlockRefTableWrite(), BlockRefTableWriter::buffer, BlockRefTableEntry::chunk_data, BlockRefTableEntry::chunk_usage, BlockRefTableKey::forknum, BlockRefTableSerializedEntry::forknum, j, BlockRefTableEntry::key, BlockRefTableEntry::limit_block, BlockRefTableSerializedEntry::limit_block, BlockRefTableEntry::nchunks, BlockRefTableSerializedEntry::nchunks, BlockRefTableKey::rlocator, and BlockRefTableSerializedEntry::rlocator.

CreateBlockRefTableEntry()

BlockRefTableEntry * CreateBlockRefTableEntry ( RelFileLocator  rlocator,
ForkNumber  forknum 
)

Definition at line 875 of file blkreftable.c.

876{
878
879 memcpy(&entry->key.rlocator, &rlocator, sizeof(RelFileLocator));
880 entry->key.forknum = forknum;
882
883 return entry;
884}

References BlockRefTableKey::forknum, InvalidBlockNumber, BlockRefTableEntry::key, BlockRefTableEntry::limit_block, palloc0(), and BlockRefTableKey::rlocator.

CreateBlockRefTableReader()

BlockRefTableReader * CreateBlockRefTableReader ( io_callback_fn  read_callback,
void *  read_callback_arg,
char *  error_filename,
report_error_fn  error_callback,
void *  error_callback_arg 
)

Definition at line 577 of file blkreftable.c.

582{
583 BlockRefTableReader *reader;
584 uint32 magic;
585
586 /* Initialize data structure. */
587 reader = palloc0(sizeof(BlockRefTableReader));
588 reader->buffer.io_callback = read_callback;
589 reader->buffer.io_callback_arg = read_callback_arg;
590 reader->error_filename = error_filename;
591 reader->error_callback = error_callback;
592 reader->error_callback_arg = error_callback_arg;
593 INIT_CRC32C(reader->buffer.crc);
594
595 /* Verify magic number. */
596 BlockRefTableRead(reader, &magic, sizeof(uint32));
597 if (magic != BLOCKREFTABLE_MAGIC)
598 error_callback(error_callback_arg,
599 "file \"%s\" has wrong magic number: expected %u, found %u",
600 error_filename,
601 BLOCKREFTABLE_MAGIC, magic);
602
603 return reader;
604}
#define BLOCKREFTABLE_MAGIC
Definition: blkreftable.h:30
#define INIT_CRC32C(crc)
Definition: pg_crc32c.h:41
void * io_callback_arg
Definition: blkreftable.c:174
io_callback_fn io_callback
Definition: blkreftable.c:173

References BLOCKREFTABLE_MAGIC, BlockRefTableRead(), BlockRefTableReader::buffer, BlockRefTableBuffer::crc, BlockRefTableReader::error_callback, BlockRefTableReader::error_callback_arg, BlockRefTableReader::error_filename, INIT_CRC32C, BlockRefTableBuffer::io_callback, BlockRefTableBuffer::io_callback_arg, and palloc0().

Referenced by main(), pg_wal_summary_contents(), and PrepareForIncrementalBackup().

CreateBlockRefTableWriter()

BlockRefTableWriter * CreateBlockRefTableWriter ( io_callback_fn  write_callback,
void *  write_callback_arg 
)

Definition at line 790 of file blkreftable.c.

792{
793 BlockRefTableWriter *writer;
795
796 /* Prepare buffer and CRC check and save callbacks. */
797 writer = palloc0(sizeof(BlockRefTableWriter));
798 writer->buffer.io_callback = write_callback;
799 writer->buffer.io_callback_arg = write_callback_arg;
800 INIT_CRC32C(writer->buffer.crc);
801
802 /* Write magic number. */
803 BlockRefTableWrite(&writer->buffer, &magic, sizeof(uint32));
804
805 return writer;
806}

References BLOCKREFTABLE_MAGIC, BlockRefTableWrite(), BlockRefTableWriter::buffer, BlockRefTableBuffer::crc, INIT_CRC32C, BlockRefTableBuffer::io_callback, BlockRefTableBuffer::io_callback_arg, and palloc0().

DestroyBlockRefTableReader()

void DestroyBlockRefTableReader ( BlockRefTableReaderreader )

Definition at line 773 of file blkreftable.c.

774{
775 if (reader->chunk_size != NULL)
776 {
777 pfree(reader->chunk_size);
778 reader->chunk_size = NULL;
779 }
780 pfree(reader);
781}

References BlockRefTableReader::chunk_size, and pfree().

Referenced by main(), pg_wal_summary_contents(), and PrepareForIncrementalBackup().

DestroyBlockRefTableWriter()

void DestroyBlockRefTableWriter ( BlockRefTableWriterwriter )

Definition at line 855 of file blkreftable.c.

856{
858 pfree(writer);
859}
static void BlockRefTableFileTerminate(BlockRefTableBuffer *buffer)
Definition: blkreftable.c:1292

References BlockRefTableFileTerminate(), BlockRefTableWriter::buffer, and pfree().

WriteBlockRefTable()

void WriteBlockRefTable ( BlockRefTablebrtab,
io_callback_fn  write_callback,
void *  write_callback_arg 
)

Definition at line 474 of file blkreftable.c.

477{
478 BlockRefTableSerializedEntry *sdata = NULL;
479 BlockRefTableBuffer buffer;
481
482 /* Prepare buffer. */
483 memset(&buffer, 0, sizeof(BlockRefTableBuffer));
484 buffer.io_callback = write_callback;
485 buffer.io_callback_arg = write_callback_arg;
486 INIT_CRC32C(buffer.crc);
487
488 /* Write magic number. */
489 BlockRefTableWrite(&buffer, &magic, sizeof(uint32));
490
491 /* Write the entries, assuming there are some. */
492 if (brtab->hash->members > 0)
493 {
494 unsigned i = 0;
495 blockreftable_iterator it;
496 BlockRefTableEntry *brtentry;
497
498 /* Extract entries into serializable format and sort them. */
499 sdata =
500 palloc(brtab->hash->members * sizeof(BlockRefTableSerializedEntry));
501 blockreftable_start_iterate(brtab->hash, &it);
502 while ((brtentry = blockreftable_iterate(brtab->hash, &it)) != NULL)
503 {
504 BlockRefTableSerializedEntry *sentry = &sdata[i++];
505
506 sentry->rlocator = brtentry->key.rlocator;
507 sentry->forknum = brtentry->key.forknum;
508 sentry->limit_block = brtentry->limit_block;
509 sentry->nchunks = brtentry->nchunks;
510
511 /* trim trailing zero entries */
512 while (sentry->nchunks > 0 &&
513 brtentry->chunk_usage[sentry->nchunks - 1] == 0)
514 sentry->nchunks--;
515 }
516 Assert(i == brtab->hash->members);
517 qsort(sdata, i, sizeof(BlockRefTableSerializedEntry),
519
520 /* Loop over entries in sorted order and serialize each one. */
521 for (i = 0; i < brtab->hash->members; ++i)
522 {
523 BlockRefTableSerializedEntry *sentry = &sdata[i];
524 BlockRefTableKey key = {0}; /* make sure any padding is zero */
525 unsigned j;
526
527 /* Write the serialized entry itself. */
528 BlockRefTableWrite(&buffer, sentry,
530
531 /* Look up the original entry so we can access the chunks. */
532 memcpy(&key.rlocator, &sentry->rlocator, sizeof(RelFileLocator));
533 key.forknum = sentry->forknum;
534 brtentry = blockreftable_lookup(brtab->hash, key);
535 Assert(brtentry != NULL);
536
537 /* Write the untruncated portion of the chunk length array. */
538 if (sentry->nchunks != 0)
539 BlockRefTableWrite(&buffer, brtentry->chunk_usage,
540 sentry->nchunks * sizeof(uint16));
541
542 /* Write the contents of each chunk. */
543 for (j = 0; j < brtentry->nchunks; ++j)
544 {
545 if (brtentry->chunk_usage[j] == 0)
546 continue;
547 BlockRefTableWrite(&buffer, brtentry->chunk_data[j],
548 brtentry->chunk_usage[j] * sizeof(uint16));
549 }
550 }
551 }
552
553 /* Write out appropriate terminator and CRC and flush buffer. */
555}
static int BlockRefTableComparator(const void *a, const void *b)
Definition: blkreftable.c:1152
#define qsort(a, b, c, d)
Definition: port.h:479

References Assert(), BLOCKREFTABLE_MAGIC, BlockRefTableComparator(), BlockRefTableFileTerminate(), BlockRefTableWrite(), BlockRefTableEntry::chunk_data, BlockRefTableEntry::chunk_usage, BlockRefTableBuffer::crc, BlockRefTableKey::forknum, BlockRefTableSerializedEntry::forknum, BlockRefTable::hash, i, INIT_CRC32C, BlockRefTableBuffer::io_callback, BlockRefTableBuffer::io_callback_arg, j, BlockRefTableEntry::key, sort-test::key, BlockRefTableEntry::limit_block, BlockRefTableSerializedEntry::limit_block, BlockRefTableEntry::nchunks, BlockRefTableSerializedEntry::nchunks, palloc(), qsort, BlockRefTableKey::rlocator, and BlockRefTableSerializedEntry::rlocator.

Referenced by SummarizeWAL().

AltStyle によって変換されたページ (->オリジナル) /