78 #define BLOCKS_PER_CHUNK (1 << 16)
79 #define BLOCKS_PER_ENTRY (BITS_PER_BYTE * sizeof(uint16))
80 #define MAX_ENTRIES_PER_CHUNK (BLOCKS_PER_CHUNK / BLOCKS_PER_ENTRY)
81 #define INITIAL_ENTRIES_PER_CHUNK 16
122 #define SH_PREFIX blockreftable
123 #define SH_ELEMENT_TYPE BlockRefTableEntry
124 #define SH_KEY_TYPE BlockRefTableKey
126 #define SH_HASH_KEY(tb, key) \
127 hash_bytes((const unsigned char *) &key, sizeof(BlockRefTableKey))
128 #define SH_EQUAL(tb, a, b) (memcmp(&a, &b, sizeof(BlockRefTableKey)) == 0)
129 #define SH_SCOPE static inline
131 #define SH_RAW_ALLOCATOR pg_malloc0
166 #define BUFSIZE 65536
245 brtab->
hash = blockreftable_create(4096, NULL);
248 brtab->
hash = blockreftable_create(brtab->
mcxt, 4096, NULL);
272 key.forknum = forknum;
273 brtentry = blockreftable_insert(brtab->
hash,
key, &found);
310 key.forknum = forknum;
311 brtentry = blockreftable_insert(brtab->
hash,
key, &found);
346 Assert(limit_block != NULL);
349 key.forknum = forknum;
350 entry = blockreftable_lookup(brtab->
hash,
key);
392 if (stop_chunkno > entry->
nchunks)
398 for (chunkno = start_chunkno; chunkno < stop_chunkno; ++chunkno)
402 unsigned start_offset = 0;
410 if (chunkno == start_chunkno)
412 if (chunkno == stop_chunkno - 1)
428 for (
i = start_offset;
i < stop_offset; ++
i)
436 blocks[nresults++] = blkno;
439 if (nresults == nblocks)
449 for (
i = 0;
i < chunk_usage; ++
i)
453 if (offset >= start_offset && offset < stop_offset)
457 blocks[nresults++] = blkno;
460 if (nresults == nblocks)
476 void *write_callback_arg)
492 if (brtab->
hash->members > 0)
495 blockreftable_iterator it;
501 blockreftable_start_iterate(brtab->
hash, &it);
502 while ((brtentry = blockreftable_iterate(brtab->
hash, &it)) != NULL)
521 for (
i = 0;
i < brtab->
hash->members; ++
i)
534 brtentry = blockreftable_lookup(brtab->
hash,
key);
578 void *read_callback_arg,
579 char *error_filename,
581 void *error_callback_arg)
598 error_callback(error_callback_arg,
599 "file \"%s\" has wrong magic number: expected %u, found %u",
652 if (!
EQ_CRC32C(expected_crc, actual_crc))
654 "file \"%s\" has wrong checksum: expected %08X, found %08X",
693 unsigned blocks_found = 0;
716 blocks_found < nblocks)
723 blocks[blocks_found++] =
732 blocks_found < nblocks)
742 if (blocks_found >= nblocks)
759 if (next_chunk_size > 0)
761 next_chunk_size *
sizeof(
uint16));
791 void *write_callback_arg)
898 unsigned limit_chunkno;
899 unsigned limit_chunkoffset;
920 if (limit_chunkno >= entry->
nchunks)
924 for (chunkno = limit_chunkno + 1; chunkno < entry->
nchunks; ++chunkno)
933 limit_chunk = entry->
chunk_data[limit_chunkno];
936 unsigned chunkoffset;
953 if (limit_chunk[
i] < limit_chunkoffset)
954 limit_chunk[
j++] = limit_chunk[
i];
956 Assert(j <= entry->chunk_usage[limit_chunkno]);
970 unsigned chunkoffset;
987 unsigned extra_chunks;
994 while (max_chunks < chunkno + 1)
996 extra_chunks = max_chunks - entry->
nchunks;
1008 sizeof(
uint16) * max_chunks);
1010 extra_chunks *
sizeof(
uint16));
1012 sizeof(
uint16) * max_chunks);
1014 extra_chunks *
sizeof(
uint16));
1103 unsigned newsize = entry->
chunk_size[chunkno] * 2;
1107 newsize *
sizeof(
uint16));
1209 int bytes_to_copy =
Min(length, buffer->
used - buffer->
cursor);
1214 buffer->
cursor += bytes_to_copy;
1215 data = ((
char *)
data) + bytes_to_copy;
1216 length -= bytes_to_copy;
1229 data = ((
char *)
data) + bytes_read;
1230 length -= bytes_read;
1233 if (bytes_read == 0)
1235 "file \"%s\" ends unexpectedly",
1248 if (buffer->
used == 0)
1250 "file \"%s\" ends unexpectedly",
1283 buffer->
used += length;
void BlockRefTableFreeEntry(BlockRefTableEntry *entry)
struct BlockRefTableSerializedEntry BlockRefTableSerializedEntry
BlockRefTableWriter * CreateBlockRefTableWriter(io_callback_fn write_callback, void *write_callback_arg)
BlockRefTable * CreateEmptyBlockRefTable(void)
BlockRefTableReader * CreateBlockRefTableReader(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)
int BlockRefTableEntryGetBlocks(BlockRefTableEntry *entry, BlockNumber start_blkno, BlockNumber stop_blkno, BlockNumber *blocks, int nblocks)
void BlockRefTableMarkBlockModified(BlockRefTable *brtab, const RelFileLocator *rlocator, ForkNumber forknum, BlockNumber blknum)
void BlockRefTableWriteEntry(BlockRefTableWriter *writer, BlockRefTableEntry *entry)
static void BlockRefTableRead(BlockRefTableReader *reader, void *data, int length)
BlockRefTableEntry * BlockRefTableGetEntry(BlockRefTable *brtab, const RelFileLocator *rlocator, ForkNumber forknum, BlockNumber *limit_block)
void BlockRefTableEntryMarkBlockModified(BlockRefTableEntry *entry, ForkNumber forknum, BlockNumber blknum)
BlockRefTableEntry * CreateBlockRefTableEntry(RelFileLocator rlocator, ForkNumber forknum)
unsigned BlockRefTableReaderGetBlocks(BlockRefTableReader *reader, BlockNumber *blocks, int nblocks)
void BlockRefTableSetLimitBlock(BlockRefTable *brtab, const RelFileLocator *rlocator, ForkNumber forknum, BlockNumber limit_block)
void BlockRefTableEntrySetLimitBlock(BlockRefTableEntry *entry, BlockNumber limit_block)
struct BlockRefTableBuffer BlockRefTableBuffer
void WriteBlockRefTable(BlockRefTable *brtab, io_callback_fn write_callback, void *write_callback_arg)
static void BlockRefTableFileTerminate(BlockRefTableBuffer *buffer)
void DestroyBlockRefTableReader(BlockRefTableReader *reader)
#define MAX_ENTRIES_PER_CHUNK
void DestroyBlockRefTableWriter(BlockRefTableWriter *writer)
#define INITIAL_ENTRIES_PER_CHUNK
uint16 * BlockRefTableChunk
static void BlockRefTableWrite(BlockRefTableBuffer *buffer, void *data, int length)
static void BlockRefTableFlush(BlockRefTableBuffer *buffer)
struct BlockRefTableKey BlockRefTableKey
static int BlockRefTableComparator(const void *a, const void *b)
void(* report_error_fn)(void *callback_arg, char *msg,...) pg_attribute_printf(2
int(* io_callback_fn)(void *callback_arg, void *data, int length)
#define BLOCKREFTABLE_MAGIC
#define InvalidBlockNumber
#define Assert(condition)
if(TABLE==NULL||TABLE_index==NULL)
void pfree(void *pointer)
void * palloc0(Size size)
MemoryContext CurrentMemoryContext
void * repalloc(void *pointer, Size size)
#define COMP_CRC32C(crc, data, len)
#define EQ_CRC32C(c1, c2)
#define qsort(a, b, c, d)
MemoryContextSwitchTo(old_ctx)
io_callback_fn io_callback
BlockRefTableChunk * chunk_data
BlockRefTableBuffer buffer
uint16 chunk_data[MAX_ENTRIES_PER_CHUNK]
void * error_callback_arg
report_error_fn error_callback
BlockRefTableBuffer buffer
blockreftable_hash * hash