PostgreSQL Source Code  git master
relmapper.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * relmapper.c
4  * Catalog-to-filenumber mapping
5  *
6  * For most tables, the physical file underlying the table is specified by
7  * pg_class.relfilenode. However, that obviously won't work for pg_class
8  * itself, nor for the other "nailed" catalogs for which we have to be able
9  * to set up working Relation entries without access to pg_class. It also
10  * does not work for shared catalogs, since there is no practical way to
11  * update other databases' pg_class entries when relocating a shared catalog.
12  * Therefore, for these special catalogs (henceforth referred to as "mapped
13  * catalogs") we rely on a separately maintained file that shows the mapping
14  * from catalog OIDs to filenumbers. Each database has a map file for
15  * its local mapped catalogs, and there is a separate map file for shared
16  * catalogs. Mapped catalogs have zero in their pg_class.relfilenode entries.
17  *
18  * Relocation of a normal table is committed (ie, the new physical file becomes
19  * authoritative) when the pg_class row update commits. For mapped catalogs,
20  * the act of updating the map file is effectively commit of the relocation.
21  * We postpone the file update till just before commit of the transaction
22  * doing the rewrite, but there is necessarily a window between. Therefore
23  * mapped catalogs can only be relocated by operations such as VACUUM FULL
24  * and CLUSTER, which make no transactionally-significant changes: it must be
25  * safe for the new file to replace the old, even if the transaction itself
26  * aborts. An important factor here is that the indexes and toast table of
27  * a mapped catalog must also be mapped, so that the rewrites/relocations of
28  * all these files commit in a single map file update rather than being tied
29  * to transaction commit.
30  *
31  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
32  * Portions Copyright (c) 1994, Regents of the University of California
33  *
34  *
35  * IDENTIFICATION
36  * src/backend/utils/cache/relmapper.c
37  *
38  *-------------------------------------------------------------------------
39  */
40 #include "postgres.h"
41 
42 #include <fcntl.h>
43 #include <sys/stat.h>
44 #include <unistd.h>
45 
46 #include "access/xact.h"
47 #include "access/xlog.h"
48 #include "access/xloginsert.h"
49 #include "catalog/catalog.h"
50 #include "catalog/pg_tablespace.h"
51 #include "catalog/storage.h"
52 #include "miscadmin.h"
53 #include "pgstat.h"
54 #include "storage/fd.h"
55 #include "storage/lwlock.h"
56 #include "utils/inval.h"
57 #include "utils/relmapper.h"
58 
59 
60 /*
61  * The map file is critical data: we have no automatic method for recovering
62  * from loss or corruption of it. We use a CRC so that we can detect
63  * corruption. Since the file might be more than one standard-size disk
64  * sector in size, we cannot rely on overwrite-in-place. Instead, we generate
65  * a new file and rename it into place, atomically replacing the original file.
66  *
67  * Entries in the mappings[] array are in no particular order. We could
68  * speed searching by insisting on OID order, but it really shouldn't be
69  * worth the trouble given the intended size of the mapping sets.
70  */
71 #define RELMAPPER_FILENAME "pg_filenode.map"
72 #define RELMAPPER_TEMP_FILENAME "pg_filenode.map.tmp"
73 
74 #define RELMAPPER_FILEMAGIC 0x592717 /* version ID value */
75 
76 /*
77  * There's no need for this constant to have any particular value, and we
78  * can raise it as necessary if we end up with more mapped relations. For
79  * now, we just pick a round number that is modestly larger than the expected
80  * number of mappings.
81  */
82 #define MAX_MAPPINGS 64
83 
84 typedef struct RelMapping
85 {
86  Oid mapoid; /* OID of a catalog */
87  RelFileNumber mapfilenumber; /* its rel file number */
89 
90 typedef struct RelMapFile
91 {
92  int32 magic; /* always RELMAPPER_FILEMAGIC */
93  int32 num_mappings; /* number of valid RelMapping entries */
95  pg_crc32c crc; /* CRC of all above */
97 
98 /*
99  * State for serializing local and shared relmappings for parallel workers
100  * (active states only). See notes on active_* and pending_* updates state.
101  */
103 {
107 
108 /*
109  * The currently known contents of the shared map file and our database's
110  * local map file are stored here. These can be reloaded from disk
111  * immediately whenever we receive an update sinval message.
112  */
115 
116 /*
117  * We use the same RelMapFile data structure to track uncommitted local
118  * changes in the mappings (but note the magic and crc fields are not made
119  * valid in these variables). Currently, map updates are not allowed within
120  * subtransactions, so one set of transaction-level changes is sufficient.
121  *
122  * The active_xxx variables contain updates that are valid in our transaction
123  * and should be honored by RelationMapOidToFilenumber. The pending_xxx
124  * variables contain updates we have been told about that aren't active yet;
125  * they will become active at the next CommandCounterIncrement. This setup
126  * lets map updates act similarly to updates of pg_class rows, ie, they
127  * become visible only at the next CommandCounterIncrement boundary.
128  *
129  * Active shared and active local updates are serialized by the parallel
130  * infrastructure, and deserialized within parallel workers.
131  */
136 
137 
138 /* non-export function prototypes */
139 static void apply_map_update(RelMapFile *map, Oid relationId,
140  RelFileNumber fileNumber, bool add_okay);
141 static void merge_map_updates(RelMapFile *map, const RelMapFile *updates,
142  bool add_okay);
143 static void load_relmap_file(bool shared, bool lock_held);
144 static void read_relmap_file(RelMapFile *map, char *dbpath, bool lock_held,
145  int elevel);
146 static void write_relmap_file(RelMapFile *newmap, bool write_wal,
147  bool send_sinval, bool preserve_files,
148  Oid dbid, Oid tsid, const char *dbpath);
149 static void perform_relmap_update(bool shared, const RelMapFile *updates);
150 
151 
152 /*
153  * RelationMapOidToFilenumber
154  *
155  * The raison d' etre ... given a relation OID, look up its filenumber.
156  *
157  * Although shared and local relation OIDs should never overlap, the caller
158  * always knows which we need --- so pass that information to avoid useless
159  * searching.
160  *
161  * Returns InvalidRelFileNumber if the OID is not known (which should never
162  * happen, but the caller is in a better position to report a meaningful
163  * error).
164  */
166 RelationMapOidToFilenumber(Oid relationId, bool shared)
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 }
205 
206 /*
207  * RelationMapFilenumberToOid
208  *
209  * Do the reverse of the normal direction of mapping done in
210  * RelationMapOidToFilenumber.
211  *
212  * This is not supposed to be used during normal running but rather for
213  * information purposes when looking at the filesystem or xlog.
214  *
215  * Returns InvalidOid if the OID is not known; this can easily happen if the
216  * relfilenumber doesn't pertain to a mapped relation.
217  */
218 Oid
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 }
258 
259 /*
260  * RelationMapOidToFilenumberForDatabase
261  *
262  * Like RelationMapOidToFilenumber, but reads the mapping from the indicated
263  * path instead of using the one for the current database.
264  */
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 }
283 
284 /*
285  * RelationMapCopy
286  *
287  * Copy relmapfile from source db path to the destination db path and WAL log
288  * the operation. This is intended for use in creating a new relmap file
289  * for a database that doesn't have one yet, not for replacing an existing
290  * relmap file.
291  */
292 void
293 RelationMapCopy(Oid dbid, Oid tsid, char *srcdbpath, char *dstdbpath)
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  */
312  LWLockAcquire(RelationMappingLock, LW_EXCLUSIVE);
313  write_relmap_file(&map, true, false, false, dbid, tsid, dstdbpath);
314  LWLockRelease(RelationMappingLock);
315 }
316 
317 /*
318  * RelationMapUpdateMap
319  *
320  * Install a new relfilenumber mapping for the specified relation.
321  *
322  * If immediate is true (or we're bootstrapping), the mapping is activated
323  * immediately. Otherwise it is made pending until CommandCounterIncrement.
324  */
325 void
326 RelationMapUpdateMap(Oid relationId, RelFileNumber fileNumber, bool shared,
327  bool immediate)
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)
358  map = &active_shared_updates;
359  else
360  map = &active_local_updates;
361  }
362  else
363  {
364  /* Make it pending */
365  if (shared)
366  map = &pending_shared_updates;
367  else
368  map = &pending_local_updates;
369  }
370  }
371  apply_map_update(map, relationId, fileNumber, true);
372 }
373 
374 /*
375  * apply_map_update
376  *
377  * Insert a new mapping into the given map variable, replacing any existing
378  * mapping for the same relation.
379  *
380  * In some cases the caller knows there must be an existing mapping; pass
381  * add_okay = false to draw an error if not.
382  */
383 static void
384 apply_map_update(RelMapFile *map, Oid relationId, RelFileNumber fileNumber,
385  bool add_okay)
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  {
394  map->mappings[i].mapfilenumber = fileNumber;
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");
405  map->mappings[map->num_mappings].mapoid = relationId;
406  map->mappings[map->num_mappings].mapfilenumber = fileNumber;
407  map->num_mappings++;
408 }
409 
410 /*
411  * merge_map_updates
412  *
413  * Merge all the updates in the given pending-update map into the target map.
414  * This is just a bulk form of apply_map_update.
415  */
416 static void
417 merge_map_updates(RelMapFile *map, const RelMapFile *updates, bool add_okay)
418 {
419  int32 i;
420 
421  for (i = 0; i < updates->num_mappings; i++)
422  {
423  apply_map_update(map,
424  updates->mappings[i].mapoid,
425  updates->mappings[i].mapfilenumber,
426  add_okay);
427  }
428 }
429 
430 /*
431  * RelationMapRemoveMapping
432  *
433  * Remove a relation's entry in the map. This is only allowed for "active"
434  * (but not committed) local mappings. We need it so we can back out the
435  * entry for the transient target file when doing VACUUM FULL/CLUSTER on
436  * a mapped relation.
437  */
438 void
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 }
457 
458 /*
459  * RelationMapInvalidate
460  *
461  * This routine is invoked for SI cache flush messages. We must re-read
462  * the indicated map file. However, we might receive a SI message in a
463  * process that hasn't yet, and might never, load the mapping files;
464  * for example the autovacuum launcher, which *must not* try to read
465  * a local map since it is attached to no particular database.
466  * So, re-read only if the map is valid now.
467  */
468 void
470 {
471  if (shared)
472  {
474  load_relmap_file(true, false);
475  }
476  else
477  {
479  load_relmap_file(false, false);
480  }
481 }
482 
483 /*
484  * RelationMapInvalidateAll
485  *
486  * Reload all map files. This is used to recover from SI message buffer
487  * overflow: we can't be sure if we missed an inval message.
488  * Again, reload only currently-valid maps.
489  */
490 void
492 {
494  load_relmap_file(true, false);
496  load_relmap_file(false, false);
497 }
498 
499 /*
500  * AtCCI_RelationMap
501  *
502  * Activate any "pending" relation map updates at CommandCounterIncrement time.
503  */
504 void
506 {
508  {
511  true);
513  }
515  {
518  true);
520  }
521 }
522 
523 /*
524  * AtEOXact_RelationMap
525  *
526  * Handle relation mapping at main-transaction commit or abort.
527  *
528  * During commit, this must be called as late as possible before the actual
529  * transaction commit, so as to minimize the window where the transaction
530  * could still roll back after committing map changes. Although nothing
531  * critically bad happens in such a case, we still would prefer that it
532  * not happen, since we'd possibly be losing useful updates to the relations'
533  * pg_class row(s).
534  *
535  * During abort, we just have to throw away any pending map changes.
536  * Normal post-abort cleanup will take care of fixing relcache entries.
537  * Parallel worker commit/abort is handled by resetting active mappings
538  * that may have been received from the leader process. (There should be
539  * no pending updates in parallel workers.)
540  */
541 void
542 AtEOXact_RelationMap(bool isCommit, bool isParallelWorker)
543 {
544  if (isCommit && !isParallelWorker)
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 */
571  Assert(!isParallelWorker || pending_shared_updates.num_mappings == 0);
572  Assert(!isParallelWorker || pending_local_updates.num_mappings == 0);
573 
578  }
579 }
580 
581 /*
582  * AtPrepare_RelationMap
583  *
584  * Handle relation mapping at PREPARE.
585  *
586  * Currently, we don't support preparing any transaction that changes the map.
587  */
588 void
590 {
595  ereport(ERROR,
596  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
597  errmsg("cannot PREPARE a transaction that modified relation mapping")));
598 }
599 
600 /*
601  * CheckPointRelationMap
602  *
603  * This is called during a checkpoint. It must ensure that any relation map
604  * updates that were WAL-logged before the start of the checkpoint are
605  * securely flushed to disk and will not need to be replayed later. This
606  * seems unlikely to be a performance-critical issue, so we use a simple
607  * method: we just take and release the RelationMappingLock. This ensures
608  * that any already-logged map update is complete, because write_relmap_file
609  * will fsync the map file before the lock is released.
610  */
611 void
613 {
614  LWLockAcquire(RelationMappingLock, LW_SHARED);
615  LWLockRelease(RelationMappingLock);
616 }
617 
618 /*
619  * RelationMapFinishBootstrap
620  *
621  * Write out the initial relation mapping files at the completion of
622  * bootstrap. All the mapped files should have been made known to us
623  * via RelationMapUpdateMap calls.
624  */
625 void
627 {
629 
630  /* Shouldn't be anything "pending" ... */
635 
636  /* Write the files; no WAL or sinval needed */
637  LWLockAcquire(RelationMappingLock, LW_EXCLUSIVE);
638  write_relmap_file(&shared_map, false, false, false,
639  InvalidOid, GLOBALTABLESPACE_OID, "global");
640  write_relmap_file(&local_map, false, false, false,
642  LWLockRelease(RelationMappingLock);
643 }
644 
645 /*
646  * RelationMapInitialize
647  *
648  * This initializes the mapper module at process startup. We can't access the
649  * database yet, so just make sure the maps are empty.
650  */
651 void
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 }
664 
665 /*
666  * RelationMapInitializePhase2
667  *
668  * This is called to prepare for access to pg_database during startup.
669  * We should be able to read the shared map file now.
670  */
671 void
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 }
685 
686 /*
687  * RelationMapInitializePhase3
688  *
689  * This is called as soon as we have determined MyDatabaseId and set up
690  * DatabasePath. At this point we should be able to read the local map file.
691  */
692 void
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 }
706 
707 /*
708  * EstimateRelationMapSpace
709  *
710  * Estimate space needed to pass active shared and local relmaps to parallel
711  * workers.
712  */
713 Size
715 {
716  return sizeof(SerializedActiveRelMaps);
717 }
718 
719 /*
720  * SerializeRelationMap
721  *
722  * Serialize active shared and local relmap state for parallel workers.
723  */
724 void
725 SerializeRelationMap(Size maxSize, char *startAddress)
726 {
727  SerializedActiveRelMaps *relmaps;
728 
729  Assert(maxSize >= EstimateRelationMapSpace());
730 
731  relmaps = (SerializedActiveRelMaps *) startAddress;
734 }
735 
736 /*
737  * RestoreRelationMap
738  *
739  * Restore active shared and local relmap state within a parallel worker.
740  */
741 void
742 RestoreRelationMap(char *startAddress)
743 {
744  SerializedActiveRelMaps *relmaps;
745 
750  elog(ERROR, "parallel worker has existing mappings");
751 
752  relmaps = (SerializedActiveRelMaps *) startAddress;
755 }
756 
757 /*
758  * load_relmap_file -- load the shared or local map file
759  *
760  * Because these files are essential for access to core system catalogs,
761  * failure to load either of them is a fatal error.
762  *
763  * Note that the local case requires DatabasePath to be set up.
764  */
765 static void
766 load_relmap_file(bool shared, bool lock_held)
767 {
768  if (shared)
769  read_relmap_file(&shared_map, "global", lock_held, FATAL);
770  else
772 }
773 
774 /*
775  * read_relmap_file -- load data from any relation mapper file
776  *
777  * dbpath must be the relevant database path, or "global" for shared relations.
778  *
779  * RelationMappingLock will be acquired released unless lock_held = true.
780  *
781  * Errors will be reported at the indicated elevel, which should be at least
782  * ERROR.
783  */
784 static void
785 read_relmap_file(RelMapFile *map, char *dbpath, bool lock_held, int elevel)
786 {
787  char mapfilename[MAXPGPATH];
788  pg_crc32c crc;
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)
802  LWLockAcquire(RelationMappingLock, LW_SHARED);
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,
815  fd = OpenTransientFile(mapfilename, O_RDONLY | PG_BINARY);
816  if (fd < 0)
817  ereport(elevel,
819  errmsg("could not open file \"%s\": %m",
820  mapfilename)));
821 
822  /* Now read the data. */
823  pgstat_report_wait_start(WAIT_EVENT_RELATION_MAP_READ);
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)
846  LWLockRelease(RelationMappingLock);
847 
848  /* check for correct magic number, etc */
849  if (map->magic != RELMAPPER_FILEMAGIC ||
850  map->num_mappings < 0 ||
851  map->num_mappings > MAX_MAPPINGS)
852  ereport(elevel,
853  (errmsg("relation mapping file \"%s\" contains invalid data",
854  mapfilename)));
855 
856  /* verify the CRC */
857  INIT_CRC32C(crc);
858  COMP_CRC32C(crc, (char *) map, offsetof(RelMapFile, crc));
859  FIN_CRC32C(crc);
860 
861  if (!EQ_CRC32C(crc, map->crc))
862  ereport(elevel,
863  (errmsg("relation mapping file \"%s\" contains incorrect checksum",
864  mapfilename)));
865 }
866 
867 /*
868  * Write out a new shared or local map file with the given contents.
869  *
870  * The magic number and CRC are automatically updated in *newmap. On
871  * success, we copy the data to the appropriate permanent static variable.
872  *
873  * If write_wal is true then an appropriate WAL message is emitted.
874  * (It will be false for bootstrap and WAL replay cases.)
875  *
876  * If send_sinval is true then a SI invalidation message is sent.
877  * (This should be true except in bootstrap case.)
878  *
879  * If preserve_files is true then the storage manager is warned not to
880  * delete the files listed in the map.
881  *
882  * Because this may be called during WAL replay when MyDatabaseId,
883  * DatabasePath, etc aren't valid, we require the caller to pass in suitable
884  * values. Pass dbpath as "global" for the shared map.
885  *
886  * The caller is also responsible for being sure no concurrent map update
887  * could be happening.
888  */
889 static void
890 write_relmap_file(RelMapFile *newmap, bool write_wal, bool send_sinval,
891  bool preserve_files, Oid dbid, Oid tsid, const char *dbpath)
892 {
893  int fd;
894  char mapfilename[MAXPGPATH];
895  char maptempfilename[MAXPGPATH];
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  */
904  Assert(LWLockHeldByMeInMode(RelationMappingLock, LW_EXCLUSIVE));
905 
906  /*
907  * Fill in the overhead fields and update CRC.
908  */
909  newmap->magic = RELMAPPER_FILEMAGIC;
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);
914  COMP_CRC32C(newmap->crc, (char *) newmap, offsetof(RelMapFile, 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",
922  dbpath, RELMAPPER_FILENAME);
923  snprintf(maptempfilename, sizeof(maptempfilename), "%s/%s",
924  dbpath, RELMAPPER_TEMP_FILENAME);
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  */
931  fd = OpenTransientFile(maptempfilename,
932  O_WRONLY | O_CREAT | O_TRUNC | PG_BINARY);
933  if (fd < 0)
934  ereport(ERROR,
936  errmsg("could not open file \"%s\": %m",
937  maptempfilename)));
938 
939  /* Write new data to the file. */
940  pgstat_report_wait_start(WAIT_EVENT_RELATION_MAP_WRITE);
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;
946  ereport(ERROR,
948  errmsg("could not write file \"%s\": %m",
949  maptempfilename)));
950  }
952 
953  /* And close the file. */
954  if (CloseTransientFile(fd) != 0)
955  ereport(ERROR,
957  errmsg("could not close file \"%s\": %m",
958  maptempfilename)));
959 
960  if (write_wal)
961  {
962  xl_relmap_update xlrec;
963  XLogRecPtr lsn;
964 
965  /* now errors are fatal ... */
967 
968  xlrec.dbid = dbid;
969  xlrec.tsid = tsid;
970  xlrec.nbytes = sizeof(RelMapFile);
971 
972  XLogBeginInsert();
973  XLogRegisterData((char *) (&xlrec), MinSizeOfRelmapUpdate);
974  XLogRegisterData((char *) newmap, sizeof(RelMapFile));
975 
976  lsn = XLogInsert(RM_RELMAP_ID, XLOG_RELMAP_UPDATE);
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  */
989  pgstat_report_wait_start(WAIT_EVENT_RELATION_MAP_REPLACE);
990  durable_rename(maptempfilename, mapfilename, ERROR);
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)
1002  CacheInvalidateRelmap(dbid);
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)
1031  END_CRIT_SECTION();
1032 }
1033 
1034 /*
1035  * Merge the specified updates into the appropriate "real" map,
1036  * and write out the changes. This function must be used for committing
1037  * updates during normal multiuser operation.
1038  */
1039 static void
1040 perform_relmap_update(bool shared, const RelMapFile *updates)
1041 {
1042  RelMapFile newmap;
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  */
1057  LWLockAcquire(RelationMappingLock, LW_EXCLUSIVE);
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  */
1072  merge_map_updates(&newmap, updates, allowSystemTableMods);
1073 
1074  /* Write out the updated map and do other necessary tasks */
1075  write_relmap_file(&newmap, true, true, true,
1076  (shared ? InvalidOid : MyDatabaseId),
1077  (shared ? GLOBALTABLESPACE_OID : MyDatabaseTableSpace),
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 */
1090  LWLockRelease(RelationMappingLock);
1091 }
1092 
1093 /*
1094  * RELMAP resource manager's routines
1095  */
1096 void
1098 {
1099  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
1100 
1101  /* Backup blocks are not used in relmap records */
1102  Assert(!XLogRecHasAnyBlockRefs(record));
1103 
1104  if (info == XLOG_RELMAP_UPDATE)
1105  {
1106  xl_relmap_update *xlrec = (xl_relmap_update *) XLogRecGetData(record);
1107  RelMapFile newmap;
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  */
1133  LWLockAcquire(RelationMappingLock, LW_EXCLUSIVE);
1134  write_relmap_file(&newmap, false, true, false,
1135  xlrec->dbid, xlrec->tsid, dbpath);
1136  LWLockRelease(RelationMappingLock);
1137 
1138  pfree(dbpath);
1139  }
1140  else
1141  elog(PANIC, "relmap_redo: unknown op code %u", info);
1142 }
signed int int32
Definition: c.h:483
#define PG_BINARY
Definition: c.h:1262
unsigned char uint8
Definition: c.h:493
size_t Size
Definition: c.h:594
int errcode_for_file_access(void)
Definition: elog.c:883
int errcode(int sqlerrcode)
Definition: elog.c:860
int errmsg(const char *fmt,...)
Definition: elog.c:1075
#define FATAL
Definition: elog.h:41
#define PANIC
Definition: elog.h:42
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
int durable_rename(const char *oldfile, const char *newfile, int elevel)
Definition: fd.c:782
int CloseTransientFile(int fd)
Definition: fd.c:2809
int OpenTransientFile(const char *fileName, int fileFlags)
Definition: fd.c:2633
bool allowSystemTableMods
Definition: globals.c:127
Oid MyDatabaseTableSpace
Definition: globals.c:92
char * DatabasePath
Definition: globals.c:100
Oid MyDatabaseId
Definition: globals.c:90
#define write(a, b, c)
Definition: win32.h:14
#define read(a, b, c)
Definition: win32.h:13
void CacheInvalidateRelmap(Oid databaseId)
Definition: inval.c:1490
int i
Definition: isn.c:73
Assert(fmt[strlen(fmt) - 1] !='\n')
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1168
bool LWLockHeldByMeInMode(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1937
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1781
@ LW_SHARED
Definition: lwlock.h:117
@ LW_EXCLUSIVE
Definition: lwlock.h:116
void pfree(void *pointer)
Definition: mcxt.c:1431
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:416
#define START_CRIT_SECTION()
Definition: miscadmin.h:149
#define END_CRIT_SECTION()
Definition: miscadmin.h:151
#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
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
static int fd(const char *x, int i)
Definition: preproc-init.c:105
RelFileNumber RelationMapOidToFilenumberForDatabase(char *dbpath, Oid relationId)
Definition: relmapper.c:266
static RelMapFile pending_local_updates
Definition: relmapper.c:135
Size EstimateRelationMapSpace(void)
Definition: relmapper.c:714
void RelationMapRemoveMapping(Oid relationId)
Definition: relmapper.c:439
struct RelMapping RelMapping
void SerializeRelationMap(Size maxSize, char *startAddress)
Definition: relmapper.c:725
#define RELMAPPER_FILEMAGIC
Definition: relmapper.c:74
void RelationMapCopy(Oid dbid, Oid tsid, char *srcdbpath, char *dstdbpath)
Definition: relmapper.c:293
static void apply_map_update(RelMapFile *map, Oid relationId, RelFileNumber fileNumber, bool add_okay)
Definition: relmapper.c:384
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
Oid RelationMapFilenumberToOid(RelFileNumber filenumber, bool shared)
Definition: relmapper.c:219
void RelationMapInvalidateAll(void)
Definition: relmapper.c:491
void RestoreRelationMap(char *startAddress)
Definition: relmapper.c:742
#define MAX_MAPPINGS
Definition: relmapper.c:82
static RelMapFile shared_map
Definition: relmapper.c:113
static RelMapFile active_local_updates
Definition: relmapper.c:133
static void perform_relmap_update(bool shared, const RelMapFile *updates)
Definition: relmapper.c:1040
static void read_relmap_file(RelMapFile *map, char *dbpath, bool lock_held, int elevel)
Definition: relmapper.c:785
void RelationMapInitialize(void)
Definition: relmapper.c:652
void AtPrepare_RelationMap(void)
Definition: relmapper.c:589
static RelMapFile local_map
Definition: relmapper.c:114
#define RELMAPPER_TEMP_FILENAME
Definition: relmapper.c:72
void relmap_redo(XLogReaderState *record)
Definition: relmapper.c:1097
#define RELMAPPER_FILENAME
Definition: relmapper.c:71
void AtEOXact_RelationMap(bool isCommit, bool isParallelWorker)
Definition: relmapper.c:542
void RelationMapInvalidate(bool shared)
Definition: relmapper.c:469
static RelMapFile pending_shared_updates
Definition: relmapper.c:134
void RelationMapInitializePhase2(void)
Definition: relmapper.c:672
void RelationMapFinishBootstrap(void)
Definition: relmapper.c:626
struct SerializedActiveRelMaps SerializedActiveRelMaps
RelFileNumber RelationMapOidToFilenumber(Oid relationId, bool shared)
Definition: relmapper.c:166
void RelationMapUpdateMap(Oid relationId, RelFileNumber fileNumber, bool shared, bool immediate)
Definition: relmapper.c:326
void RelationMapInitializePhase3(void)
Definition: relmapper.c:693
struct RelMapFile RelMapFile
void AtCCI_RelationMap(void)
Definition: relmapper.c:505
static void merge_map_updates(RelMapFile *map, const RelMapFile *updates, bool add_okay)
Definition: relmapper.c:417
void CheckPointRelationMap(void)
Definition: relmapper.c:612
static RelMapFile active_shared_updates
Definition: relmapper.c:132
static void load_relmap_file(bool shared, bool lock_held)
Definition: relmapper.c:766
#define XLOG_RELMAP_UPDATE
Definition: relmapper.h:25
#define MinSizeOfRelmapUpdate
Definition: relmapper.h:35
char * GetDatabasePath(Oid dbOid, Oid spcOid)
Definition: relpath.c:110
Oid RelFileNumber
Definition: relpath.h:25
#define InvalidRelFileNumber
Definition: relpath.h:26
void RelationPreserveStorage(RelFileLocator rlocator, bool atCommit)
Definition: storage.c:251
RelFileNumber relNumber
RelMapping mappings[MAX_MAPPINGS]
Definition: relmapper.c:94
int32 magic
Definition: relmapper.c:92
pg_crc32c crc
Definition: relmapper.c:95
int32 num_mappings
Definition: relmapper.c:93
Oid mapoid
Definition: relmapper.c:86
RelFileNumber mapfilenumber
Definition: relmapper.c:87
RelMapFile active_local_updates
Definition: relmapper.c:105
RelMapFile active_shared_updates
Definition: relmapper.c:104
char data[FLEXIBLE_ARRAY_MEMBER]
Definition: relmapper.h:32
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
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:914
bool IsInParallelMode(void)
Definition: xact.c:1069
void XLogFlush(XLogRecPtr record)
Definition: xlog.c:2733
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
#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