PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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 "utils/wait_event.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 82 of file relmapper.c.

◆ RELMAPPER_FILEMAGIC

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

Definition at line 74 of file relmapper.c.

◆ RELMAPPER_FILENAME

#define RELMAPPER_FILENAME   "pg_filenode.map"

Definition at line 71 of file relmapper.c.

◆ RELMAPPER_TEMP_FILENAME

#define RELMAPPER_TEMP_FILENAME   "pg_filenode.map.tmp"

Definition at line 72 of file relmapper.c.

Typedef Documentation

◆ RelMapFile

◆ 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 384 of file relmapper.c.

386{
387 int32 i;
388
389 /* Replace any existing mapping */
390 for (i = 0; i < map->num_mappings; i++)
391 {
392 if (relationId == map->mappings[i].mapoid)
393 {
395 return;
396 }
397 }
398
399 /* Nope, need to add a new mapping */
400 if (!add_okay)
401 elog(ERROR, "attempt to apply a mapping to unmapped relation %u",
402 relationId);
403 if (map->num_mappings >= MAX_MAPPINGS)
404 elog(ERROR, "ran out of space in relation map");
407 map->num_mappings++;
408}
int32_t int32
Definition c.h:614
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
int i
Definition isn.c:77
static int fb(int x)
#define MAX_MAPPINGS
Definition relmapper.c:82
RelMapping mappings[MAX_MAPPINGS]
Definition relmapper.c:94
int32 num_mappings
Definition relmapper.c:93
RelFileNumber mapfilenumber
Definition relmapper.c:87

References elog, ERROR, fb(), 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 505 of file relmapper.c.

506{
508 {
511 true);
513 }
515 {
518 true);
520 }
521}
static RelMapFile pending_local_updates
Definition relmapper.c:135
static RelMapFile active_local_updates
Definition relmapper.c:133
static RelMapFile pending_shared_updates
Definition relmapper.c:134
static void merge_map_updates(RelMapFile *map, const RelMapFile *updates, bool add_okay)
Definition relmapper.c:417
static RelMapFile active_shared_updates
Definition relmapper.c:132

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 542 of file relmapper.c.

543{
545 {
546 /*
547 * We should not get here with any "pending" updates. (We could
548 * logically choose to treat such as committed, but in the current
549 * code this should never happen.)
550 */
553
554 /*
555 * Write any active updates to the actual map files, then reset them.
556 */
558 {
561 }
563 {
566 }
567 }
568 else
569 {
570 /* Abort or parallel worker --- drop all local and pending updates */
573
578 }
579}
#define Assert(condition)
Definition c.h:945
static void perform_relmap_update(bool shared, const RelMapFile *updates)
Definition relmapper.c:1040

References active_local_updates, active_shared_updates, Assert, fb(), 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 589 of file relmapper.c.

590{
597 errmsg("cannot PREPARE a transaction that modified relation mapping")));
598}
int errcode(int sqlerrcode)
Definition elog.c:874
#define ereport(elevel,...)
Definition elog.h:150
static char * errmsg

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

Referenced by PrepareTransaction().

◆ CheckPointRelationMap()

void CheckPointRelationMap ( void  )

Definition at line 612 of file relmapper.c.

613{
616}
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1177
void LWLockRelease(LWLock *lock)
Definition lwlock.c:1794
@ LW_SHARED
Definition lwlock.h:113

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

Referenced by CheckPointGuts().

◆ EstimateRelationMapSpace()

Size EstimateRelationMapSpace ( void  )

Definition at line 714 of file relmapper.c.

715{
716 return sizeof(SerializedActiveRelMaps);
717}

Referenced by InitializeParallelDSM(), and SerializeRelationMap().

◆ load_relmap_file()

static void load_relmap_file ( bool  shared,
bool  lock_held 
)
static

Definition at line 766 of file relmapper.c.

767{
768 if (shared)
770 else
772}
#define FATAL
Definition elog.h:41
char * DatabasePath
Definition globals.c:104
static RelMapFile shared_map
Definition relmapper.c:113
static void read_relmap_file(RelMapFile *map, char *dbpath, bool lock_held, int elevel)
Definition relmapper.c:785
static RelMapFile local_map
Definition relmapper.c:114

References DatabasePath, FATAL, fb(), 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 417 of file relmapper.c.

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

References apply_map_update(), fb(), i, RelMapping::mapoid, and RelMapFile::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 1040 of file relmapper.c.

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

References allowSystemTableMods, DatabasePath, fb(), 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 785 of file relmapper.c.

786{
789 int fd;
790 int r;
791
792 Assert(elevel >= ERROR);
793
794 /*
795 * Grab the lock to prevent the file from being updated while we read it,
796 * unless the caller is already holding the lock. If the file is updated
797 * shortly after we look, the sinval signaling mechanism will make us
798 * re-read it before we are able to access any relation that's affected by
799 * the change.
800 */
801 if (!lock_held)
803
804 /*
805 * Open the target file.
806 *
807 * Because Windows isn't happy about the idea of renaming over a file that
808 * someone has open, we only open this file after acquiring the lock, and
809 * for the same reason, we close it before releasing the lock. That way,
810 * by the time write_relmap_file() acquires an exclusive lock, no one else
811 * will have it open.
812 */
813 snprintf(mapfilename, sizeof(mapfilename), "%s/%s", dbpath,
816 if (fd < 0)
817 ereport(elevel,
819 errmsg("could not open file \"%s\": %m",
820 mapfilename)));
821
822 /* Now read the data. */
824 r = read(fd, map, sizeof(RelMapFile));
825 if (r != sizeof(RelMapFile))
826 {
827 if (r < 0)
828 ereport(elevel,
830 errmsg("could not read file \"%s\": %m", mapfilename)));
831 else
832 ereport(elevel,
834 errmsg("could not read file \"%s\": read %d of %zu",
835 mapfilename, r, sizeof(RelMapFile))));
836 }
838
839 if (CloseTransientFile(fd) != 0)
840 ereport(elevel,
842 errmsg("could not close file \"%s\": %m",
843 mapfilename)));
844
845 if (!lock_held)
847
848 /* check for correct magic number, etc */
849 if (map->magic != RELMAPPER_FILEMAGIC ||
850 map->num_mappings < 0 ||
852 ereport(elevel,
853 (errmsg("relation mapping file \"%s\" contains invalid data",
854 mapfilename)));
855
856 /* verify the CRC */
860
861 if (!EQ_CRC32C(crc, map->crc))
862 ereport(elevel,
863 (errmsg("relation mapping file \"%s\" contains incorrect checksum",
864 mapfilename)));
865}
#define PG_BINARY
Definition c.h:1376
int errcode_for_file_access(void)
Definition elog.c:897
int CloseTransientFile(int fd)
Definition fd.c:2855
int OpenTransientFile(const char *fileName, int fileFlags)
Definition fd.c:2678
#define read(a, b, c)
Definition win32.h:13
#define ERRCODE_DATA_CORRUPTED
#define MAXPGPATH
uint32 pg_crc32c
Definition pg_crc32c.h:38
#define COMP_CRC32C(crc, data, len)
Definition pg_crc32c.h:153
#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:158
return crc
#define snprintf
Definition port.h:260
static int fd(const char *x, int i)
#define RELMAPPER_FILEMAGIC
Definition relmapper.c:74
#define RELMAPPER_FILENAME
Definition relmapper.c:71
int32 magic
Definition relmapper.c:92
pg_crc32c crc
Definition relmapper.c:95
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition wait_event.h:69
static void pgstat_report_wait_end(void)
Definition wait_event.h:85

References Assert, CloseTransientFile(), COMP_CRC32C, RelMapFile::crc, crc, EQ_CRC32C, ereport, errcode(), ERRCODE_DATA_CORRUPTED, errcode_for_file_access(), errmsg, ERROR, fb(), 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 293 of file relmapper.c.

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

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

Referenced by CreateDatabaseUsingWalLog().

◆ RelationMapFilenumberToOid()

Oid RelationMapFilenumberToOid ( RelFileNumber  filenumber,
bool  shared 
)

Definition at line 219 of file relmapper.c.

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

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()

◆ RelationMapInitialize()

void RelationMapInitialize ( void  )

Definition at line 652 of file relmapper.c.

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

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 672 of file relmapper.c.

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

References IsBootstrapProcessingMode, and load_relmap_file().

Referenced by RelationCacheInitializePhase2().

◆ RelationMapInitializePhase3()

void RelationMapInitializePhase3 ( void  )

Definition at line 693 of file relmapper.c.

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

References IsBootstrapProcessingMode, and load_relmap_file().

Referenced by RelationCacheInitializePhase3().

◆ RelationMapInvalidate()

void RelationMapInvalidate ( bool  shared)

Definition at line 469 of file relmapper.c.

470{
471 if (shared)
472 {
474 load_relmap_file(true, false);
475 }
476 else
477 {
479 load_relmap_file(false, false);
480 }
481}

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

Referenced by LocalExecuteInvalidationMessage().

◆ RelationMapInvalidateAll()

void RelationMapInvalidateAll ( void  )

Definition at line 491 of file relmapper.c.

492{
494 load_relmap_file(true, false);
496 load_relmap_file(false, false);
497}

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 166 of file relmapper.c.

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

References active_local_updates, active_shared_updates, fb(), 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 266 of file relmapper.c.

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

References ERROR, fb(), 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 439 of file relmapper.c.

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

References active_local_updates, elog, ERROR, fb(), 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 326 of file relmapper.c.

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

References active_local_updates, active_shared_updates, apply_map_update(), elog, ERROR, fb(), 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 1097 of file relmapper.c.

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

References Assert, elog, fb(), GetDatabasePath(), LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), PANIC, pfree(), write_relmap_file(), XLOG_RELMAP_UPDATE, XLogRecGetData, XLogRecGetInfo, and XLogRecHasAnyBlockRefs.

◆ RestoreRelationMap()

void RestoreRelationMap ( char startAddress)

Definition at line 742 of file relmapper.c.

743{
745
750 elog(ERROR, "parallel worker has existing mappings");
751
753 active_shared_updates = relmaps->active_shared_updates;
754 active_local_updates = relmaps->active_local_updates;
755}

References active_local_updates, active_shared_updates, elog, ERROR, fb(), RelMapFile::num_mappings, pending_local_updates, and pending_shared_updates.

Referenced by ParallelWorkerMain().

◆ SerializeRelationMap()

void SerializeRelationMap ( Size  maxSize,
char startAddress 
)

Definition at line 725 of file relmapper.c.

726{
728
730
732 relmaps->active_shared_updates = active_shared_updates;
733 relmaps->active_local_updates = active_local_updates;
734}
Size EstimateRelationMapSpace(void)
Definition relmapper.c:714

References active_local_updates, active_shared_updates, Assert, EstimateRelationMapSpace(), and fb().

Referenced by InitializeParallelDSM().

◆ 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 890 of file relmapper.c.

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

References Assert, CacheInvalidateRelmap(), CloseTransientFile(), COMP_CRC32C, crc, RelFileLocator::dbOid, durable_rename(), elog, END_CRIT_SECTION, ereport, errcode_for_file_access(), errmsg, ERROR, fb(), fd(), FIN_CRC32C, i, INIT_CRC32C, LW_EXCLUSIVE, LWLockHeldByMeInMode(), MAX_MAPPINGS, MAXPGPATH, MinSizeOfRelmapUpdate, 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, 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