PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
relmapper.c File Reference
#include "postgres.h"
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include "access/xact.h"
#include "access/xlog.h"
#include "access/xloginsert.h"
#include "catalog/pg_tablespace.h"
#include "catalog/storage.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "storage/fd.h"
#include "storage/lwlock.h"
#include "utils/inval.h"
#include "utils/relmapper.h"
Include dependency graph for relmapper.c:

Go to the source code of this file.

Data Structures

struct  RelMapping
 
struct  RelMapFile
 
struct  SerializedActiveRelMaps
 

Macros

#define RELMAPPER_FILENAME   "pg_filenode.map"
 
#define RELMAPPER_TEMP_FILENAME   "pg_filenode.map.tmp"
 
#define RELMAPPER_FILEMAGIC   0x592717 /* version ID value */
 
#define MAX_MAPPINGS   64
 

Typedefs

typedef struct RelMapping RelMapping
 
typedef struct RelMapFile RelMapFile
 
typedef struct SerializedActiveRelMaps SerializedActiveRelMaps
 

Functions

static void apply_map_update (RelMapFile *map, Oid relationId, RelFileNumber fileNumber, bool add_okay)
 
static void merge_map_updates (RelMapFile *map, const RelMapFile *updates, bool add_okay)
 
static void load_relmap_file (bool shared, bool lock_held)
 
static void read_relmap_file (RelMapFile *map, char *dbpath, bool lock_held, int elevel)
 
static void write_relmap_file (RelMapFile *newmap, bool write_wal, bool send_sinval, bool preserve_files, Oid dbid, Oid tsid, const char *dbpath)
 
static void perform_relmap_update (bool shared, const RelMapFile *updates)
 
RelFileNumber RelationMapOidToFilenumber (Oid relationId, bool shared)
 
Oid RelationMapFilenumberToOid (RelFileNumber filenumber, bool shared)
 
RelFileNumber RelationMapOidToFilenumberForDatabase (char *dbpath, Oid relationId)
 
void RelationMapCopy (Oid dbid, Oid tsid, char *srcdbpath, char *dstdbpath)
 
void RelationMapUpdateMap (Oid relationId, RelFileNumber fileNumber, bool shared, bool immediate)
 
void RelationMapRemoveMapping (Oid relationId)
 
void RelationMapInvalidate (bool shared)
 
void RelationMapInvalidateAll (void)
 
void AtCCI_RelationMap (void)
 
void AtEOXact_RelationMap (bool isCommit, bool isParallelWorker)
 
void AtPrepare_RelationMap (void)
 
void CheckPointRelationMap (void)
 
void RelationMapFinishBootstrap (void)
 
void RelationMapInitialize (void)
 
void RelationMapInitializePhase2 (void)
 
void RelationMapInitializePhase3 (void)
 
Size EstimateRelationMapSpace (void)
 
void SerializeRelationMap (Size maxSize, char *startAddress)
 
void RestoreRelationMap (char *startAddress)
 
void relmap_redo (XLogReaderState *record)
 

Variables

static RelMapFile shared_map
 
static RelMapFile local_map
 
static RelMapFile active_shared_updates
 
static RelMapFile active_local_updates
 
static RelMapFile pending_shared_updates
 
static RelMapFile pending_local_updates
 

Macro Definition Documentation

◆ MAX_MAPPINGS

#define MAX_MAPPINGS   64

Definition at line 81 of file relmapper.c.

◆ RELMAPPER_FILEMAGIC

#define RELMAPPER_FILEMAGIC   0x592717 /* version ID value */

Definition at line 73 of file relmapper.c.

◆ RELMAPPER_FILENAME

#define RELMAPPER_FILENAME   "pg_filenode.map"

Definition at line 70 of file relmapper.c.

◆ RELMAPPER_TEMP_FILENAME

#define RELMAPPER_TEMP_FILENAME   "pg_filenode.map.tmp"

Definition at line 71 of file relmapper.c.

Typedef Documentation

◆ RelMapFile

typedef struct RelMapFile RelMapFile

◆ RelMapping

typedef struct RelMapping RelMapping

◆ SerializedActiveRelMaps

Function Documentation

◆ apply_map_update()

static void apply_map_update ( RelMapFile map,
Oid  relationId,
RelFileNumber  fileNumber,
bool  add_okay 
)
static

Definition at line 383 of file relmapper.c.

385{
386 int32 i;
387
388 /* Replace any existing mapping */
389 for (i = 0; i < map->num_mappings; i++)
390 {
391 if (relationId == map->mappings[i].mapoid)
392 {
393 map->mappings[i].mapfilenumber = fileNumber;
394 return;
395 }
396 }
397
398 /* Nope, need to add a new mapping */
399 if (!add_okay)
400 elog(ERROR, "attempt to apply a mapping to unmapped relation %u",
401 relationId);
402 if (map->num_mappings >= MAX_MAPPINGS)
403 elog(ERROR, "ran out of space in relation map");
404 map->mappings[map->num_mappings].mapoid = relationId;
405 map->mappings[map->num_mappings].mapfilenumber = fileNumber;
406 map->num_mappings++;
407}
int32_t int32
Definition: c.h:481
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
int i
Definition: isn.c:72
#define MAX_MAPPINGS
Definition: relmapper.c:81
RelMapping mappings[MAX_MAPPINGS]
Definition: relmapper.c:93
int32 num_mappings
Definition: relmapper.c:92
Oid mapoid
Definition: relmapper.c:85
RelFileNumber mapfilenumber
Definition: relmapper.c:86

References elog, ERROR, i, RelMapping::mapfilenumber, RelMapping::mapoid, RelMapFile::mappings, MAX_MAPPINGS, and RelMapFile::num_mappings.

Referenced by merge_map_updates(), and RelationMapUpdateMap().

◆ AtCCI_RelationMap()

void AtCCI_RelationMap ( void  )

Definition at line 504 of file relmapper.c.

505{
507 {
510 true);
512 }
514 {
517 true);
519 }
520}
static RelMapFile pending_local_updates
Definition: relmapper.c:134
static RelMapFile active_local_updates
Definition: relmapper.c:132
static RelMapFile pending_shared_updates
Definition: relmapper.c:133
static void merge_map_updates(RelMapFile *map, const RelMapFile *updates, bool add_okay)
Definition: relmapper.c:416
static RelMapFile active_shared_updates
Definition: relmapper.c:131

References active_local_updates, active_shared_updates, merge_map_updates(), RelMapFile::num_mappings, pending_local_updates, and pending_shared_updates.

Referenced by AtCCI_LocalCache().

◆ AtEOXact_RelationMap()

void AtEOXact_RelationMap ( bool  isCommit,
bool  isParallelWorker 
)

Definition at line 541 of file relmapper.c.

542{
543 if (isCommit && !isParallelWorker)
544 {
545 /*
546 * We should not get here with any "pending" updates. (We could
547 * logically choose to treat such as committed, but in the current
548 * code this should never happen.)
549 */
552
553 /*
554 * Write any active updates to the actual map files, then reset them.
555 */
557 {
560 }
562 {
565 }
566 }
567 else
568 {
569 /* Abort or parallel worker --- drop all local and pending updates */
570 Assert(!isParallelWorker || pending_shared_updates.num_mappings == 0);
571 Assert(!isParallelWorker || pending_local_updates.num_mappings == 0);
572
577 }
578}
#define Assert(condition)
Definition: c.h:812
static void perform_relmap_update(bool shared, const RelMapFile *updates)
Definition: relmapper.c:1039

References active_local_updates, active_shared_updates, Assert, RelMapFile::num_mappings, pending_local_updates, pending_shared_updates, and perform_relmap_update().

Referenced by AbortTransaction(), and CommitTransaction().

◆ AtPrepare_RelationMap()

void AtPrepare_RelationMap ( void  )

Definition at line 588 of file relmapper.c.

589{
595 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
596 errmsg("cannot PREPARE a transaction that modified relation mapping")));
597}
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ereport(elevel,...)
Definition: elog.h:149

References active_local_updates, active_shared_updates, ereport, errcode(), errmsg(), ERROR, RelMapFile::num_mappings, pending_local_updates, and pending_shared_updates.

Referenced by PrepareTransaction().

◆ CheckPointRelationMap()

void CheckPointRelationMap ( void  )

Definition at line 611 of file relmapper.c.

612{
613 LWLockAcquire(RelationMappingLock, LW_SHARED);
614 LWLockRelease(RelationMappingLock);
615}
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1168
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1781
@ LW_SHARED
Definition: lwlock.h:115

References LW_SHARED, LWLockAcquire(), and LWLockRelease().

Referenced by CheckPointGuts().

◆ EstimateRelationMapSpace()

Size EstimateRelationMapSpace ( void  )

Definition at line 713 of file relmapper.c.

714{
715 return sizeof(SerializedActiveRelMaps);
716}
struct SerializedActiveRelMaps SerializedActiveRelMaps

Referenced by InitializeParallelDSM(), and SerializeRelationMap().

◆ load_relmap_file()

static void load_relmap_file ( bool  shared,
bool  lock_held 
)
static

Definition at line 765 of file relmapper.c.

766{
767 if (shared)
768 read_relmap_file(&shared_map, "global", lock_held, FATAL);
769 else
771}
#define FATAL
Definition: elog.h:41
char * DatabasePath
Definition: globals.c:103
static RelMapFile shared_map
Definition: relmapper.c:112
static void read_relmap_file(RelMapFile *map, char *dbpath, bool lock_held, int elevel)
Definition: relmapper.c:784
static RelMapFile local_map
Definition: relmapper.c:113

References DatabasePath, FATAL, local_map, read_relmap_file(), and shared_map.

Referenced by perform_relmap_update(), RelationMapInitializePhase2(), RelationMapInitializePhase3(), RelationMapInvalidate(), and RelationMapInvalidateAll().

◆ merge_map_updates()

static void merge_map_updates ( RelMapFile map,
const RelMapFile updates,
bool  add_okay 
)
static

Definition at line 416 of file relmapper.c.

417{
418 int32 i;
419
420 for (i = 0; i < updates->num_mappings; i++)
421 {
423 updates->mappings[i].mapoid,
424 updates->mappings[i].mapfilenumber,
425 add_okay);
426 }
427}
static void apply_map_update(RelMapFile *map, Oid relationId, RelFileNumber fileNumber, bool add_okay)
Definition: relmapper.c:383

References apply_map_update(), i, RelMapping::mapfilenumber, RelMapping::mapoid, RelMapFile::mappings, and RelMapFile::num_mappings.

Referenced by AtCCI_RelationMap(), and perform_relmap_update().

◆ perform_relmap_update()

static void perform_relmap_update ( bool  shared,
const RelMapFile updates 
)
static

Definition at line 1039 of file relmapper.c.

1040{
1041 RelMapFile newmap;
1042
1043 /*
1044 * Anyone updating a relation's mapping info should take exclusive lock on
1045 * that rel and hold it until commit. This ensures that there will not be
1046 * concurrent updates on the same mapping value; but there could easily be
1047 * concurrent updates on different values in the same file. We cover that
1048 * by acquiring the RelationMappingLock, re-reading the target file to
1049 * ensure it's up to date, applying the updates, and writing the data
1050 * before releasing RelationMappingLock.
1051 *
1052 * There is only one RelationMappingLock. In principle we could try to
1053 * have one per mapping file, but it seems unlikely to be worth the
1054 * trouble.
1055 */
1056 LWLockAcquire(RelationMappingLock, LW_EXCLUSIVE);
1057
1058 /* Be certain we see any other updates just made */
1059 load_relmap_file(shared, true);
1060
1061 /* Prepare updated data in a local variable */
1062 if (shared)
1063 memcpy(&newmap, &shared_map, sizeof(RelMapFile));
1064 else
1065 memcpy(&newmap, &local_map, sizeof(RelMapFile));
1066
1067 /*
1068 * Apply the updates to newmap. No new mappings should appear, unless
1069 * somebody is adding indexes to system catalogs.
1070 */
1071 merge_map_updates(&newmap, updates, allowSystemTableMods);
1072
1073 /* Write out the updated map and do other necessary tasks */
1074 write_relmap_file(&newmap, true, true, true,
1075 (shared ? InvalidOid : MyDatabaseId),
1076 (shared ? GLOBALTABLESPACE_OID : MyDatabaseTableSpace),
1077 (shared ? "global" : DatabasePath));
1078
1079 /*
1080 * We successfully wrote the updated file, so it's now safe to rely on the
1081 * new values in this process, too.
1082 */
1083 if (shared)
1084 memcpy(&shared_map, &newmap, sizeof(RelMapFile));
1085 else
1086 memcpy(&local_map, &newmap, sizeof(RelMapFile));
1087
1088 /* Now we can release the lock */
1089 LWLockRelease(RelationMappingLock);
1090}
bool allowSystemTableMods
Definition: globals.c:129
Oid MyDatabaseTableSpace
Definition: globals.c:95
Oid MyDatabaseId
Definition: globals.c:93
@ LW_EXCLUSIVE
Definition: lwlock.h:114
#define InvalidOid
Definition: postgres_ext.h:36
static void write_relmap_file(RelMapFile *newmap, bool write_wal, bool send_sinval, bool preserve_files, Oid dbid, Oid tsid, const char *dbpath)
Definition: relmapper.c:889
static void load_relmap_file(bool shared, bool lock_held)
Definition: relmapper.c:765

References allowSystemTableMods, DatabasePath, InvalidOid, load_relmap_file(), local_map, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), merge_map_updates(), MyDatabaseId, MyDatabaseTableSpace, shared_map, and write_relmap_file().

Referenced by AtEOXact_RelationMap().

◆ read_relmap_file()

static void read_relmap_file ( RelMapFile map,
char *  dbpath,
bool  lock_held,
int  elevel 
)
static

Definition at line 784 of file relmapper.c.

785{
786 char mapfilename[MAXPGPATH];
788 int fd;
789 int r;
790
791 Assert(elevel >= ERROR);
792
793 /*
794 * Grab the lock to prevent the file from being updated while we read it,
795 * unless the caller is already holding the lock. If the file is updated
796 * shortly after we look, the sinval signaling mechanism will make us
797 * re-read it before we are able to access any relation that's affected by
798 * the change.
799 */
800 if (!lock_held)
801 LWLockAcquire(RelationMappingLock, LW_SHARED);
802
803 /*
804 * Open the target file.
805 *
806 * Because Windows isn't happy about the idea of renaming over a file that
807 * someone has open, we only open this file after acquiring the lock, and
808 * for the same reason, we close it before releasing the lock. That way,
809 * by the time write_relmap_file() acquires an exclusive lock, no one else
810 * will have it open.
811 */
812 snprintf(mapfilename, sizeof(mapfilename), "%s/%s", dbpath,
814 fd = OpenTransientFile(mapfilename, O_RDONLY | PG_BINARY);
815 if (fd < 0)
816 ereport(elevel,
818 errmsg("could not open file \"%s\": %m",
819 mapfilename)));
820
821 /* Now read the data. */
822 pgstat_report_wait_start(WAIT_EVENT_RELATION_MAP_READ);
823 r = read(fd, map, sizeof(RelMapFile));
824 if (r != sizeof(RelMapFile))
825 {
826 if (r < 0)
827 ereport(elevel,
829 errmsg("could not read file \"%s\": %m", mapfilename)));
830 else
831 ereport(elevel,
833 errmsg("could not read file \"%s\": read %d of %zu",
834 mapfilename, r, sizeof(RelMapFile))));
835 }
837
838 if (CloseTransientFile(fd) != 0)
839 ereport(elevel,
841 errmsg("could not close file \"%s\": %m",
842 mapfilename)));
843
844 if (!lock_held)
845 LWLockRelease(RelationMappingLock);
846
847 /* check for correct magic number, etc */
848 if (map->magic != RELMAPPER_FILEMAGIC ||
849 map->num_mappings < 0 ||
851 ereport(elevel,
852 (errmsg("relation mapping file \"%s\" contains invalid data",
853 mapfilename)));
854
855 /* verify the CRC */
857 COMP_CRC32C(crc, (char *) map, offsetof(RelMapFile, crc));
859
860 if (!EQ_CRC32C(crc, map->crc))
861 ereport(elevel,
862 (errmsg("relation mapping file \"%s\" contains incorrect checksum",
863 mapfilename)));
864}
#define PG_BINARY
Definition: c.h:1227
int errcode_for_file_access(void)
Definition: elog.c:876
int CloseTransientFile(int fd)
Definition: fd.c:2831
int OpenTransientFile(const char *fileName, int fileFlags)
Definition: fd.c:2655
#define read(a, b, c)
Definition: win32.h:13
#define ERRCODE_DATA_CORRUPTED
Definition: pg_basebackup.c:41
#define MAXPGPATH
uint32 pg_crc32c
Definition: pg_crc32c.h:38
#define COMP_CRC32C(crc, data, len)
Definition: pg_crc32c.h:98
#define EQ_CRC32C(c1, c2)
Definition: pg_crc32c.h:42
#define INIT_CRC32C(crc)
Definition: pg_crc32c.h:41
#define FIN_CRC32C(crc)
Definition: pg_crc32c.h:103
return crc
#define snprintf
Definition: port.h:238
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define RELMAPPER_FILEMAGIC
Definition: relmapper.c:73
#define RELMAPPER_FILENAME
Definition: relmapper.c:70
int32 magic
Definition: relmapper.c:91
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:85
static void pgstat_report_wait_end(void)
Definition: wait_event.h:101

References Assert, CloseTransientFile(), COMP_CRC32C, RelMapFile::crc, crc, EQ_CRC32C, ereport, errcode(), ERRCODE_DATA_CORRUPTED, errcode_for_file_access(), errmsg(), ERROR, fd(), FIN_CRC32C, INIT_CRC32C, LW_SHARED, LWLockAcquire(), LWLockRelease(), RelMapFile::magic, MAX_MAPPINGS, MAXPGPATH, RelMapFile::num_mappings, OpenTransientFile(), PG_BINARY, pgstat_report_wait_end(), pgstat_report_wait_start(), read, RELMAPPER_FILEMAGIC, RELMAPPER_FILENAME, and snprintf.

Referenced by load_relmap_file(), RelationMapCopy(), and RelationMapOidToFilenumberForDatabase().

◆ RelationMapCopy()

void RelationMapCopy ( Oid  dbid,
Oid  tsid,
char *  srcdbpath,
char *  dstdbpath 
)

Definition at line 292 of file relmapper.c.

293{
294 RelMapFile map;
295
296 /*
297 * Read the relmap file from the source database.
298 */
299 read_relmap_file(&map, srcdbpath, false, ERROR);
300
301 /*
302 * Write the same data into the destination database's relmap file.
303 *
304 * No sinval is needed because no one can be connected to the destination
305 * database yet.
306 *
307 * There's no point in trying to preserve files here. The new database
308 * isn't usable yet anyway, and won't ever be if we can't install a relmap
309 * file.
310 */
311 LWLockAcquire(RelationMappingLock, LW_EXCLUSIVE);
312 write_relmap_file(&map, true, false, false, dbid, tsid, dstdbpath);
313 LWLockRelease(RelationMappingLock);
314}

References ERROR, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), read_relmap_file(), and write_relmap_file().

Referenced by CreateDatabaseUsingWalLog().

◆ RelationMapFilenumberToOid()

Oid RelationMapFilenumberToOid ( RelFileNumber  filenumber,
bool  shared 
)

Definition at line 218 of file relmapper.c.

219{
220 const RelMapFile *map;
221 int32 i;
222
223 /* If there are active updates, believe those over the main maps */
224 if (shared)
225 {
227 for (i = 0; i < map->num_mappings; i++)
228 {
229 if (filenumber == map->mappings[i].mapfilenumber)
230 return map->mappings[i].mapoid;
231 }
232 map = &shared_map;
233 for (i = 0; i < map->num_mappings; i++)
234 {
235 if (filenumber == map->mappings[i].mapfilenumber)
236 return map->mappings[i].mapoid;
237 }
238 }
239 else
240 {
242 for (i = 0; i < map->num_mappings; i++)
243 {
244 if (filenumber == map->mappings[i].mapfilenumber)
245 return map->mappings[i].mapoid;
246 }
247 map = &local_map;
248 for (i = 0; i < map->num_mappings; i++)
249 {
250 if (filenumber == map->mappings[i].mapfilenumber)
251 return map->mappings[i].mapoid;
252 }
253 }
254
255 return InvalidOid;
256}

References active_local_updates, active_shared_updates, i, InvalidOid, local_map, RelMapping::mapfilenumber, RelMapping::mapoid, RelMapFile::mappings, RelMapFile::num_mappings, and shared_map.

Referenced by RelidByRelfilenumber().

◆ RelationMapFinishBootstrap()

void RelationMapFinishBootstrap ( void  )

Definition at line 625 of file relmapper.c.

626{
628
629 /* Shouldn't be anything "pending" ... */
634
635 /* Write the files; no WAL or sinval needed */
636 LWLockAcquire(RelationMappingLock, LW_EXCLUSIVE);
637 write_relmap_file(&shared_map, false, false, false,
638 InvalidOid, GLOBALTABLESPACE_OID, "global");
639 write_relmap_file(&local_map, false, false, false,
641 LWLockRelease(RelationMappingLock);
642}
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:466

References active_local_updates, active_shared_updates, Assert, DatabasePath, InvalidOid, IsBootstrapProcessingMode, local_map, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MyDatabaseId, MyDatabaseTableSpace, RelMapFile::num_mappings, pending_local_updates, pending_shared_updates, shared_map, and write_relmap_file().

Referenced by BootstrapModeMain().

◆ RelationMapInitialize()

void RelationMapInitialize ( void  )

Definition at line 651 of file relmapper.c.

652{
653 /* The static variables should initialize to zeroes, but let's be sure */
654 shared_map.magic = 0; /* mark it not loaded */
655 local_map.magic = 0;
662}

References active_local_updates, active_shared_updates, local_map, RelMapFile::magic, RelMapFile::num_mappings, pending_local_updates, pending_shared_updates, and shared_map.

Referenced by RelationCacheInitialize().

◆ RelationMapInitializePhase2()

void RelationMapInitializePhase2 ( void  )

Definition at line 671 of file relmapper.c.

672{
673 /*
674 * In bootstrap mode, the map file isn't there yet, so do nothing.
675 */
677 return;
678
679 /*
680 * Load the shared map file, die on error.
681 */
682 load_relmap_file(true, false);
683}

References IsBootstrapProcessingMode, and load_relmap_file().

Referenced by RelationCacheInitializePhase2().

◆ RelationMapInitializePhase3()

void RelationMapInitializePhase3 ( void  )

Definition at line 692 of file relmapper.c.

693{
694 /*
695 * In bootstrap mode, the map file isn't there yet, so do nothing.
696 */
698 return;
699
700 /*
701 * Load the local map file, die on error.
702 */
703 load_relmap_file(false, false);
704}

References IsBootstrapProcessingMode, and load_relmap_file().

Referenced by RelationCacheInitializePhase3().

◆ RelationMapInvalidate()

void RelationMapInvalidate ( bool  shared)

Definition at line 468 of file relmapper.c.

469{
470 if (shared)
471 {
473 load_relmap_file(true, false);
474 }
475 else
476 {
478 load_relmap_file(false, false);
479 }
480}

References load_relmap_file(), local_map, RelMapFile::magic, RELMAPPER_FILEMAGIC, and shared_map.

Referenced by LocalExecuteInvalidationMessage().

◆ RelationMapInvalidateAll()

void RelationMapInvalidateAll ( void  )

Definition at line 490 of file relmapper.c.

491{
493 load_relmap_file(true, false);
495 load_relmap_file(false, false);
496}

References load_relmap_file(), local_map, RelMapFile::magic, RELMAPPER_FILEMAGIC, and shared_map.

Referenced by RelationCacheInvalidate().

◆ RelationMapOidToFilenumber()

RelFileNumber RelationMapOidToFilenumber ( Oid  relationId,
bool  shared 
)

Definition at line 165 of file relmapper.c.

166{
167 const RelMapFile *map;
168 int32 i;
169
170 /* If there are active updates, believe those over the main maps */
171 if (shared)
172 {
174 for (i = 0; i < map->num_mappings; i++)
175 {
176 if (relationId == map->mappings[i].mapoid)
177 return map->mappings[i].mapfilenumber;
178 }
179 map = &shared_map;
180 for (i = 0; i < map->num_mappings; i++)
181 {
182 if (relationId == map->mappings[i].mapoid)
183 return map->mappings[i].mapfilenumber;
184 }
185 }
186 else
187 {
189 for (i = 0; i < map->num_mappings; i++)
190 {
191 if (relationId == map->mappings[i].mapoid)
192 return map->mappings[i].mapfilenumber;
193 }
194 map = &local_map;
195 for (i = 0; i < map->num_mappings; i++)
196 {
197 if (relationId == map->mappings[i].mapoid)
198 return map->mappings[i].mapfilenumber;
199 }
200 }
201
203}
#define InvalidRelFileNumber
Definition: relpath.h:26

References active_local_updates, active_shared_updates, i, InvalidRelFileNumber, local_map, RelMapping::mapfilenumber, RelMapping::mapoid, RelMapFile::mappings, RelMapFile::num_mappings, and shared_map.

Referenced by pg_relation_filenode(), pg_relation_filepath(), RelationInitPhysicalAddr(), and swap_relation_files().

◆ RelationMapOidToFilenumberForDatabase()

RelFileNumber RelationMapOidToFilenumberForDatabase ( char *  dbpath,
Oid  relationId 
)

Definition at line 265 of file relmapper.c.

266{
267 RelMapFile map;
268 int i;
269
270 /* Read the relmap file from the source database. */
271 read_relmap_file(&map, dbpath, false, ERROR);
272
273 /* Iterate over the relmap entries to find the input relation OID. */
274 for (i = 0; i < map.num_mappings; i++)
275 {
276 if (relationId == map.mappings[i].mapoid)
277 return map.mappings[i].mapfilenumber;
278 }
279
281}

References ERROR, i, InvalidRelFileNumber, RelMapping::mapfilenumber, RelMapping::mapoid, RelMapFile::mappings, RelMapFile::num_mappings, and read_relmap_file().

Referenced by ScanSourceDatabasePgClass(), and ScanSourceDatabasePgClassTuple().

◆ RelationMapRemoveMapping()

void RelationMapRemoveMapping ( Oid  relationId)

Definition at line 438 of file relmapper.c.

439{
441 int32 i;
442
443 for (i = 0; i < map->num_mappings; i++)
444 {
445 if (relationId == map->mappings[i].mapoid)
446 {
447 /* Found it, collapse it out */
448 map->mappings[i] = map->mappings[map->num_mappings - 1];
449 map->num_mappings--;
450 return;
451 }
452 }
453 elog(ERROR, "could not find temporary mapping for relation %u",
454 relationId);
455}

References active_local_updates, elog, ERROR, i, RelMapping::mapoid, RelMapFile::mappings, and RelMapFile::num_mappings.

Referenced by finish_heap_swap().

◆ RelationMapUpdateMap()

void RelationMapUpdateMap ( Oid  relationId,
RelFileNumber  fileNumber,
bool  shared,
bool  immediate 
)

Definition at line 325 of file relmapper.c.

327{
328 RelMapFile *map;
329
331 {
332 /*
333 * In bootstrap mode, the mapping gets installed in permanent map.
334 */
335 if (shared)
336 map = &shared_map;
337 else
338 map = &local_map;
339 }
340 else
341 {
342 /*
343 * We don't currently support map changes within subtransactions, or
344 * when in parallel mode. This could be done with more bookkeeping
345 * infrastructure, but it doesn't presently seem worth it.
346 */
348 elog(ERROR, "cannot change relation mapping within subtransaction");
349
350 if (IsInParallelMode())
351 elog(ERROR, "cannot change relation mapping in parallel mode");
352
353 if (immediate)
354 {
355 /* Make it active, but only locally */
356 if (shared)
358 else
360 }
361 else
362 {
363 /* Make it pending */
364 if (shared)
366 else
368 }
369 }
370 apply_map_update(map, relationId, fileNumber, true);
371}
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:928
bool IsInParallelMode(void)
Definition: xact.c:1088

References active_local_updates, active_shared_updates, apply_map_update(), elog, ERROR, GetCurrentTransactionNestLevel(), IsBootstrapProcessingMode, IsInParallelMode(), local_map, pending_local_updates, pending_shared_updates, and shared_map.

Referenced by formrdesc(), RelationBuildLocalRelation(), RelationSetNewRelfilenumber(), and swap_relation_files().

◆ relmap_redo()

void relmap_redo ( XLogReaderState record)

Definition at line 1096 of file relmapper.c.

1097{
1098 uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
1099
1100 /* Backup blocks are not used in relmap records */
1102
1103 if (info == XLOG_RELMAP_UPDATE)
1104 {
1106 RelMapFile newmap;
1107 char *dbpath;
1108
1109 if (xlrec->nbytes != sizeof(RelMapFile))
1110 elog(PANIC, "relmap_redo: wrong size %u in relmap update record",
1111 xlrec->nbytes);
1112 memcpy(&newmap, xlrec->data, sizeof(newmap));
1113
1114 /* We need to construct the pathname for this database */
1115 dbpath = GetDatabasePath(xlrec->dbid, xlrec->tsid);
1116
1117 /*
1118 * Write out the new map and send sinval, but of course don't write a
1119 * new WAL entry. There's no surrounding transaction to tell to
1120 * preserve files, either.
1121 *
1122 * There shouldn't be anyone else updating relmaps during WAL replay,
1123 * but grab the lock to interlock against load_relmap_file().
1124 *
1125 * Note that we use the same WAL record for updating the relmap of an
1126 * existing database as we do for creating a new database. In the
1127 * latter case, taking the relmap log and sending sinval messages is
1128 * unnecessary, but harmless. If we wanted to avoid it, we could add a
1129 * flag to the WAL record to indicate which operation is being
1130 * performed.
1131 */
1132 LWLockAcquire(RelationMappingLock, LW_EXCLUSIVE);
1133 write_relmap_file(&newmap, false, true, false,
1134 xlrec->dbid, xlrec->tsid, dbpath);
1135 LWLockRelease(RelationMappingLock);
1136
1137 pfree(dbpath);
1138 }
1139 else
1140 elog(PANIC, "relmap_redo: unknown op code %u", info);
1141}
uint8_t uint8
Definition: c.h:483
#define PANIC
Definition: elog.h:42
void pfree(void *pointer)
Definition: mcxt.c:1521
#define XLOG_RELMAP_UPDATE
Definition: relmapper.h:25
char * GetDatabasePath(Oid dbOid, Oid spcOid)
Definition: relpath.c:110
char data[FLEXIBLE_ARRAY_MEMBER]
Definition: relmapper.h:32
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:410
#define XLogRecGetData(decoder)
Definition: xlogreader.h:415
#define XLogRecHasAnyBlockRefs(decoder)
Definition: xlogreader.h:417

References Assert, xl_relmap_update::data, xl_relmap_update::dbid, elog, GetDatabasePath(), LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), xl_relmap_update::nbytes, PANIC, pfree(), xl_relmap_update::tsid, write_relmap_file(), XLOG_RELMAP_UPDATE, XLogRecGetData, XLogRecGetInfo, and XLogRecHasAnyBlockRefs.

◆ RestoreRelationMap()

◆ SerializeRelationMap()

void SerializeRelationMap ( Size  maxSize,
char *  startAddress 
)

◆ write_relmap_file()

static void write_relmap_file ( RelMapFile newmap,
bool  write_wal,
bool  send_sinval,
bool  preserve_files,
Oid  dbid,
Oid  tsid,
const char *  dbpath 
)
static

Definition at line 889 of file relmapper.c.

891{
892 int fd;
893 char mapfilename[MAXPGPATH];
894 char maptempfilename[MAXPGPATH];
895
896 /*
897 * Even without concurrent use of this map, CheckPointRelationMap() relies
898 * on this locking. Without it, a restore of a base backup taken after
899 * this function's XLogInsert() and before its durable_rename() would not
900 * have the changes. wal_level=minimal doesn't need the lock, but this
901 * isn't performance-critical enough for such a micro-optimization.
902 */
903 Assert(LWLockHeldByMeInMode(RelationMappingLock, LW_EXCLUSIVE));
904
905 /*
906 * Fill in the overhead fields and update CRC.
907 */
908 newmap->magic = RELMAPPER_FILEMAGIC;
909 if (newmap->num_mappings < 0 || newmap->num_mappings > MAX_MAPPINGS)
910 elog(ERROR, "attempt to write bogus relation mapping");
911
912 INIT_CRC32C(newmap->crc);
913 COMP_CRC32C(newmap->crc, (char *) newmap, offsetof(RelMapFile, crc));
914 FIN_CRC32C(newmap->crc);
915
916 /*
917 * Construct filenames -- a temporary file that we'll create to write the
918 * data initially, and then the permanent name to which we will rename it.
919 */
920 snprintf(mapfilename, sizeof(mapfilename), "%s/%s",
921 dbpath, RELMAPPER_FILENAME);
922 snprintf(maptempfilename, sizeof(maptempfilename), "%s/%s",
924
925 /*
926 * Open a temporary file. If a file already exists with this name, it must
927 * be left over from a previous crash, so we can overwrite it. Concurrent
928 * calls to this function are not allowed.
929 */
930 fd = OpenTransientFile(maptempfilename,
931 O_WRONLY | O_CREAT | O_TRUNC | PG_BINARY);
932 if (fd < 0)
935 errmsg("could not open file \"%s\": %m",
936 maptempfilename)));
937
938 /* Write new data to the file. */
939 pgstat_report_wait_start(WAIT_EVENT_RELATION_MAP_WRITE);
940 if (write(fd, newmap, sizeof(RelMapFile)) != sizeof(RelMapFile))
941 {
942 /* if write didn't set errno, assume problem is no disk space */
943 if (errno == 0)
944 errno = ENOSPC;
947 errmsg("could not write file \"%s\": %m",
948 maptempfilename)));
949 }
951
952 /* And close the file. */
953 if (CloseTransientFile(fd) != 0)
956 errmsg("could not close file \"%s\": %m",
957 maptempfilename)));
958
959 if (write_wal)
960 {
961 xl_relmap_update xlrec;
962 XLogRecPtr lsn;
963
964 /* now errors are fatal ... */
966
967 xlrec.dbid = dbid;
968 xlrec.tsid = tsid;
969 xlrec.nbytes = sizeof(RelMapFile);
970
972 XLogRegisterData((char *) (&xlrec), MinSizeOfRelmapUpdate);
973 XLogRegisterData((char *) newmap, sizeof(RelMapFile));
974
975 lsn = XLogInsert(RM_RELMAP_ID, XLOG_RELMAP_UPDATE);
976
977 /* As always, WAL must hit the disk before the data update does */
978 XLogFlush(lsn);
979 }
980
981 /*
982 * durable_rename() does all the hard work of making sure that we rename
983 * the temporary file into place in a crash-safe manner.
984 *
985 * NB: Although we instruct durable_rename() to use ERROR, we will often
986 * be in a critical section at this point; if so, ERROR will become PANIC.
987 */
988 pgstat_report_wait_start(WAIT_EVENT_RELATION_MAP_REPLACE);
989 durable_rename(maptempfilename, mapfilename, ERROR);
991
992 /*
993 * Now that the file is safely on disk, send sinval message to let other
994 * backends know to re-read it. We must do this inside the critical
995 * section: if for some reason we fail to send the message, we have to
996 * force a database-wide PANIC. Otherwise other backends might continue
997 * execution with stale mapping information, which would be catastrophic
998 * as soon as others began to use the now-committed data.
999 */
1000 if (send_sinval)
1002
1003 /*
1004 * Make sure that the files listed in the map are not deleted if the outer
1005 * transaction aborts. This had better be within the critical section
1006 * too: it's not likely to fail, but if it did, we'd arrive at transaction
1007 * abort with the files still vulnerable. PANICing will leave things in a
1008 * good state on-disk.
1009 *
1010 * Note: we're cheating a little bit here by assuming that mapped files
1011 * are either in pg_global or the database's default tablespace.
1012 */
1013 if (preserve_files)
1014 {
1015 int32 i;
1016
1017 for (i = 0; i < newmap->num_mappings; i++)
1018 {
1019 RelFileLocator rlocator;
1020
1021 rlocator.spcOid = tsid;
1022 rlocator.dbOid = dbid;
1023 rlocator.relNumber = newmap->mappings[i].mapfilenumber;
1024 RelationPreserveStorage(rlocator, false);
1025 }
1026 }
1027
1028 /* Critical section done */
1029 if (write_wal)
1031}
int durable_rename(const char *oldfile, const char *newfile, int elevel)
Definition: fd.c:781
#define write(a, b, c)
Definition: win32.h:14
void CacheInvalidateRelmap(Oid databaseId)
Definition: inval.c:1677
bool LWLockHeldByMeInMode(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1937
#define START_CRIT_SECTION()
Definition: miscadmin.h:149
#define END_CRIT_SECTION()
Definition: miscadmin.h:151
#define RELMAPPER_TEMP_FILENAME
Definition: relmapper.c:71
struct RelMapFile RelMapFile
#define MinSizeOfRelmapUpdate
Definition: relmapper.h:35
void RelationPreserveStorage(RelFileLocator rlocator, bool atCommit)
Definition: storage.c:251
RelFileNumber relNumber
pg_crc32c crc
Definition: relmapper.c:94
void XLogFlush(XLogRecPtr record)
Definition: xlog.c:2802
uint64 XLogRecPtr
Definition: xlogdefs.h:21
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:474
void XLogRegisterData(const char *data, uint32 len)
Definition: xloginsert.c:364
void XLogBeginInsert(void)
Definition: xloginsert.c:149

References Assert, CacheInvalidateRelmap(), CloseTransientFile(), COMP_CRC32C, RelMapFile::crc, crc, xl_relmap_update::dbid, RelFileLocator::dbOid, durable_rename(), elog, END_CRIT_SECTION, ereport, errcode_for_file_access(), errmsg(), ERROR, fd(), FIN_CRC32C, i, INIT_CRC32C, LW_EXCLUSIVE, LWLockHeldByMeInMode(), RelMapFile::magic, RelMapping::mapfilenumber, RelMapFile::mappings, MAX_MAPPINGS, MAXPGPATH, MinSizeOfRelmapUpdate, xl_relmap_update::nbytes, RelMapFile::num_mappings, OpenTransientFile(), PG_BINARY, pgstat_report_wait_end(), pgstat_report_wait_start(), RelationPreserveStorage(), RELMAPPER_FILEMAGIC, RELMAPPER_FILENAME, RELMAPPER_TEMP_FILENAME, RelFileLocator::relNumber, snprintf, RelFileLocator::spcOid, START_CRIT_SECTION, xl_relmap_update::tsid, write, XLOG_RELMAP_UPDATE, XLogBeginInsert(), XLogFlush(), XLogInsert(), and XLogRegisterData().

Referenced by perform_relmap_update(), RelationMapCopy(), RelationMapFinishBootstrap(), and relmap_redo().

Variable Documentation

◆ active_local_updates

◆ active_shared_updates

◆ local_map

◆ pending_local_updates

◆ pending_shared_updates

◆ shared_map