PostgreSQL Source Code  git master
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/catalog.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 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

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 }
signed int int32
Definition: c.h:483
#define ERROR
Definition: elog.h:39
int i
Definition: isn.c:73
#define MAX_MAPPINGS
Definition: relmapper.c:82
RelMapping mappings[MAX_MAPPINGS]
Definition: relmapper.c:94
int32 num_mappings
Definition: relmapper.c:93
Oid mapoid
Definition: relmapper.c:86
RelFileNumber mapfilenumber
Definition: relmapper.c:87

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: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:416
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 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 }
Assert(fmt[strlen(fmt) - 1] !='\n')
static void perform_relmap_update(bool shared, const RelMapFile *updates)
Definition: relmapper.c:1028

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 {
594  ereport(ERROR,
595  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
596  errmsg("cannot PREPARE a transaction that modified relation mapping")));
597 }
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#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:1195
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1808
@ LW_SHARED
Definition: lwlock.h:117

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

Referenced by CheckPointGuts().

◆ EstimateRelationMapSpace()

Size EstimateRelationMapSpace ( void  )

Definition at line 711 of file relmapper.c.

712 {
713  return sizeof(SerializedActiveRelMaps);
714 }
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 763 of file relmapper.c.

764 {
765  if (shared)
766  read_relmap_file(&shared_map, "global", lock_held, FATAL);
767  else
769 }
#define FATAL
Definition: elog.h:41
char * DatabasePath
Definition: globals.c:99
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:782
static RelMapFile local_map
Definition: relmapper.c:114

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  {
422  apply_map_update(map,
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 1028 of file relmapper.c.

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

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

783 {
784  char mapfilename[MAXPGPATH];
785  pg_crc32c crc;
786  int fd;
787  int r;
788 
789  Assert(elevel >= ERROR);
790 
791  /*
792  * Grab the lock to prevent the file from being updated while we read it,
793  * unless the caller is already holding the lock. If the file is updated
794  * shortly after we look, the sinval signaling mechanism will make us
795  * re-read it before we are able to access any relation that's affected by
796  * the change.
797  */
798  if (!lock_held)
799  LWLockAcquire(RelationMappingLock, LW_SHARED);
800 
801  /*
802  * Open the target file.
803  *
804  * Because Windows isn't happy about the idea of renaming over a file that
805  * someone has open, we only open this file after acquiring the lock, and
806  * for the same reason, we close it before releasing the lock. That way,
807  * by the time write_relmap_file() acquires an exclusive lock, no one else
808  * will have it open.
809  */
810  snprintf(mapfilename, sizeof(mapfilename), "%s/%s", dbpath,
812  fd = OpenTransientFile(mapfilename, O_RDONLY | PG_BINARY);
813  if (fd < 0)
814  ereport(elevel,
816  errmsg("could not open file \"%s\": %m",
817  mapfilename)));
818 
819  /* Now read the data. */
820  pgstat_report_wait_start(WAIT_EVENT_RELATION_MAP_READ);
821  r = read(fd, map, sizeof(RelMapFile));
822  if (r != sizeof(RelMapFile))
823  {
824  if (r < 0)
825  ereport(elevel,
827  errmsg("could not read file \"%s\": %m", mapfilename)));
828  else
829  ereport(elevel,
831  errmsg("could not read file \"%s\": read %d of %zu",
832  mapfilename, r, sizeof(RelMapFile))));
833  }
835 
836  if (CloseTransientFile(fd) != 0)
837  ereport(elevel,
839  errmsg("could not close file \"%s\": %m",
840  mapfilename)));
841 
842  if (!lock_held)
843  LWLockRelease(RelationMappingLock);
844 
845  /* check for correct magic number, etc */
846  if (map->magic != RELMAPPER_FILEMAGIC ||
847  map->num_mappings < 0 ||
848  map->num_mappings > MAX_MAPPINGS)
849  ereport(elevel,
850  (errmsg("relation mapping file \"%s\" contains invalid data",
851  mapfilename)));
852 
853  /* verify the CRC */
854  INIT_CRC32C(crc);
855  COMP_CRC32C(crc, (char *) map, offsetof(RelMapFile, crc));
856  FIN_CRC32C(crc);
857 
858  if (!EQ_CRC32C(crc, map->crc))
859  ereport(elevel,
860  (errmsg("relation mapping file \"%s\" contains incorrect checksum",
861  mapfilename)));
862 }
#define PG_BINARY
Definition: c.h:1283
int errcode_for_file_access(void)
Definition: elog.c:881
int CloseTransientFile(int fd)
Definition: fd.c:2779
int OpenTransientFile(const char *fileName, int fileFlags)
Definition: fd.c:2603
#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:74
#define RELMAPPER_FILENAME
Definition: relmapper.c:71
int32 magic
Definition: relmapper.c:92
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:88
static void pgstat_report_wait_end(void)
Definition: wait_event.h:104

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 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. For the same reason, there is no need to acquire
307  * RelationMappingLock.
308  *
309  * There's no point in trying to preserve files here. The new database
310  * isn't usable yet anyway, and won't ever be if we can't install a relmap
311  * file.
312  */
313  write_relmap_file(&map, true, false, false, dbid, tsid, dstdbpath);
314 }

References ERROR, 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  {
227  map = &active_shared_updates;
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  {
242  map = &active_local_updates;
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()

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  write_relmap_file(&shared_map, false, false, false,
637  InvalidOid, GLOBALTABLESPACE_OID, "global");
638  write_relmap_file(&local_map, false, false, false,
640 }
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:417

References active_local_updates, active_shared_updates, Assert(), DatabasePath, InvalidOid, IsBootstrapProcessingMode, local_map, 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 649 of file relmapper.c.

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

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

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

References IsBootstrapProcessingMode, and load_relmap_file().

Referenced by RelationCacheInitializePhase2().

◆ RelationMapInitializePhase3()

void RelationMapInitializePhase3 ( void  )

Definition at line 690 of file relmapper.c.

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

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 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  {
174  map = &active_shared_updates;
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  {
189  map = &active_local_updates;
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 
203  return InvalidRelFileNumber;
204 }
#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 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 
281  return InvalidRelFileNumber;
282 }

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)
357  map = &active_shared_updates;
358  else
359  map = &active_local_updates;
360  }
361  else
362  {
363  /* Make it pending */
364  if (shared)
365  map = &pending_shared_updates;
366  else
367  map = &pending_local_updates;
368  }
369  }
370  apply_map_update(map, relationId, fileNumber, true);
371 }
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:914
bool IsInParallelMode(void)
Definition: xact.c:1069

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

1086 {
1087  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
1088 
1089  /* Backup blocks are not used in relmap records */
1090  Assert(!XLogRecHasAnyBlockRefs(record));
1091 
1092  if (info == XLOG_RELMAP_UPDATE)
1093  {
1094  xl_relmap_update *xlrec = (xl_relmap_update *) XLogRecGetData(record);
1095  RelMapFile newmap;
1096  char *dbpath;
1097 
1098  if (xlrec->nbytes != sizeof(RelMapFile))
1099  elog(PANIC, "relmap_redo: wrong size %u in relmap update record",
1100  xlrec->nbytes);
1101  memcpy(&newmap, xlrec->data, sizeof(newmap));
1102 
1103  /* We need to construct the pathname for this database */
1104  dbpath = GetDatabasePath(xlrec->dbid, xlrec->tsid);
1105 
1106  /*
1107  * Write out the new map and send sinval, but of course don't write a
1108  * new WAL entry. There's no surrounding transaction to tell to
1109  * preserve files, either.
1110  *
1111  * There shouldn't be anyone else updating relmaps during WAL replay,
1112  * but grab the lock to interlock against load_relmap_file().
1113  *
1114  * Note that we use the same WAL record for updating the relmap of an
1115  * existing database as we do for creating a new database. In the
1116  * latter case, taking the relmap log and sending sinval messages is
1117  * unnecessary, but harmless. If we wanted to avoid it, we could add a
1118  * flag to the WAL record to indicate which operation is being
1119  * performed.
1120  */
1121  LWLockAcquire(RelationMappingLock, LW_EXCLUSIVE);
1122  write_relmap_file(&newmap, false, true, false,
1123  xlrec->dbid, xlrec->tsid, dbpath);
1124  LWLockRelease(RelationMappingLock);
1125 
1126  pfree(dbpath);
1127  }
1128  else
1129  elog(PANIC, "relmap_redo: unknown op code %u", info);
1130 }
unsigned char uint8
Definition: c.h:493
#define PANIC
Definition: elog.h:42
void pfree(void *pointer)
Definition: mcxt.c:1456
#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
#define XLR_INFO_MASK
Definition: xlogrecord.h:62

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, XLogRecHasAnyBlockRefs, and XLR_INFO_MASK.

◆ RestoreRelationMap()

void RestoreRelationMap ( char *  startAddress)

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

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

References 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, 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