Skip to content

Commit 39f0c4b

Browse files
committed
Refactor code for reading and writing relation map files.
Restructure things so that the functions which update the global variables shared_map and local_map are separate from the functions which just read and write relation map files without touching any global variables. In the new structure of things, write_relmap_file() writes a relmap file but no longer performs global variable updates. A symmetric function read_relmap_file() that just reads a file without changing any global variables is added, and load_relmap_file(), which does change the global variables, uses it as a subroutine. Because write_relmap_file() no longer updates shared_map and local_map, that logic is moved to perform_relmap_update(). However, no similar logic is added to relmap_redo() even though it also calls write_relmap_file(). That's because recovery must not rely on the contents of the relation map, and therefore there is no need to initialize it. In fact, doing so seems like a mistake, because we might then manage to rely on the in-memory map where we shouldn't. Patch by me, based on earlier work by Dilip Kumar. Reviewed by Ashutosh Sharma. Discussion: http://postgr.es/m/CA+TgmobQLgrt4AXsc0ru7aFFkzv=9fS-Q_yO69=k9WY67RCctg@mail.gmail.com
1 parent 5a07966 commit 39f0c4b

File tree

1 file changed

+60
-61
lines changed

1 file changed

+60
-61
lines changed

src/backend/utils/cache/relmapper.c

Lines changed: 60 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,10 @@ static void apply_map_update(RelMapFile *map, Oid relationId, Oid fileNode,
137137
static void merge_map_updates(RelMapFile *map, const RelMapFile *updates,
138138
bool add_okay);
139139
static void load_relmap_file(bool shared, bool lock_held);
140-
static void write_relmap_file(bool shared, RelMapFile *newmap,
141-
bool write_wal, bool send_sinval, bool preserve_files,
140+
static void read_relmap_file(RelMapFile *map, char *dbpath, bool lock_held,
141+
int elevel);
142+
static void write_relmap_file(RelMapFile *newmap, bool write_wal,
143+
bool send_sinval, bool preserve_files,
142144
Oid dbid, Oid tsid, const char *dbpath);
143145
static void perform_relmap_update(bool shared, const RelMapFile *updates);
144146

@@ -568,9 +570,9 @@ RelationMapFinishBootstrap(void)
568570
Assert(pending_local_updates.num_mappings == 0);
569571

570572
/* Write the files; no WAL or sinval needed */
571-
write_relmap_file(true, &shared_map, false, false, false,
572-
InvalidOid, GLOBALTABLESPACE_OID, NULL);
573-
write_relmap_file(false, &local_map, false, false, false,
573+
write_relmap_file(&shared_map, false, false, false,
574+
InvalidOid, GLOBALTABLESPACE_OID, "global");
575+
write_relmap_file(&local_map, false, false, false,
574576
MyDatabaseId, MyDatabaseTableSpace, DatabasePath);
575577
}
576578

@@ -687,39 +689,48 @@ RestoreRelationMap(char *startAddress)
687689
}
688690

689691
/*
690-
* load_relmap_file -- load data from the shared or local map file
692+
* load_relmap_file -- load the shared or local map file
691693
*
692-
* Because the map file is essential for access to core system catalogs,
693-
* failure to read it is a fatal error.
694+
* Because these files are essential for access to core system catalogs,
695+
* failure to load either of them is a fatal error.
694696
*
695697
* Note that the local case requires DatabasePath to be set up.
696698
*/
697699
static void
698700
load_relmap_file(bool shared, bool lock_held)
699701
{
700-
RelMapFile *map;
702+
if (shared)
703+
read_relmap_file(&shared_map, "global", lock_held, FATAL);
704+
else
705+
read_relmap_file(&local_map, DatabasePath, lock_held, FATAL);
706+
}
707+
708+
/*
709+
* read_relmap_file -- load data from any relation mapper file
710+
*
711+
* dbpath must be the relevant database path, or "global" for shared relations.
712+
*
713+
* RelationMappingLock will be acquired released unless lock_held = true.
714+
*
715+
* Errors will be reported at the indicated elevel, which should be at least
716+
* ERROR.
717+
*/
718+
static void
719+
read_relmap_file(RelMapFile *map, char *dbpath, bool lock_held, int elevel)
720+
{
701721
char mapfilename[MAXPGPATH];
702722
pg_crc32c crc;
703723
int fd;
704724
int r;
705725

706-
if (shared)
707-
{
708-
snprintf(mapfilename, sizeof(mapfilename), "global/%s",
709-
RELMAPPER_FILENAME);
710-
map = &shared_map;
711-
}
712-
else
713-
{
714-
snprintf(mapfilename, sizeof(mapfilename), "%s/%s",
715-
DatabasePath, RELMAPPER_FILENAME);
716-
map = &local_map;
717-
}
726+
Assert(elevel >= ERROR);
718727

719-
/* Read data ... */
728+
/* Open the target file. */
729+
snprintf(mapfilename, sizeof(mapfilename), "%s/%s", dbpath,
730+
RELMAPPER_FILENAME);
720731
fd = OpenTransientFile(mapfilename, O_RDONLY | PG_BINARY);
721732
if (fd < 0)
722-
ereport(FATAL,
733+
ereport(elevel,
723734
(errcode_for_file_access(),
724735
errmsg("could not open file \"%s\": %m",
725736
mapfilename)));
@@ -734,16 +745,17 @@ load_relmap_file(bool shared, bool lock_held)
734745
if (!lock_held)
735746
LWLockAcquire(RelationMappingLock, LW_SHARED);
736747

748+
/* Now read the data. */
737749
pgstat_report_wait_start(WAIT_EVENT_RELATION_MAP_READ);
738750
r = read(fd, map, sizeof(RelMapFile));
739751
if (r != sizeof(RelMapFile))
740752
{
741753
if (r < 0)
742-
ereport(FATAL,
754+
ereport(elevel,
743755
(errcode_for_file_access(),
744756
errmsg("could not read file \"%s\": %m", mapfilename)));
745757
else
746-
ereport(FATAL,
758+
ereport(elevel,
747759
(errcode(ERRCODE_DATA_CORRUPTED),
748760
errmsg("could not read file \"%s\": read %d of %zu",
749761
mapfilename, r, sizeof(RelMapFile))));
@@ -754,7 +766,7 @@ load_relmap_file(bool shared, bool lock_held)
754766
LWLockRelease(RelationMappingLock);
755767

756768
if (CloseTransientFile(fd) != 0)
757-
ereport(FATAL,
769+
ereport(elevel,
758770
(errcode_for_file_access(),
759771
errmsg("could not close file \"%s\": %m",
760772
mapfilename)));
@@ -763,7 +775,7 @@ load_relmap_file(bool shared, bool lock_held)
763775
if (map->magic != RELMAPPER_FILEMAGIC ||
764776
map->num_mappings < 0 ||
765777
map->num_mappings > MAX_MAPPINGS)
766-
ereport(FATAL,
778+
ereport(elevel,
767779
(errmsg("relation mapping file \"%s\" contains invalid data",
768780
mapfilename)));
769781

@@ -773,7 +785,7 @@ load_relmap_file(bool shared, bool lock_held)
773785
FIN_CRC32C(crc);
774786

775787
if (!EQ_CRC32C(crc, map->crc))
776-
ereport(FATAL,
788+
ereport(elevel,
777789
(errmsg("relation mapping file \"%s\" contains incorrect checksum",
778790
mapfilename)));
779791
}
@@ -795,16 +807,16 @@ load_relmap_file(bool shared, bool lock_held)
795807
*
796808
* Because this may be called during WAL replay when MyDatabaseId,
797809
* DatabasePath, etc aren't valid, we require the caller to pass in suitable
798-
* values. The caller is also responsible for being sure no concurrent
799-
* map update could be happening.
810+
* values. Pass dbpath as "global" for the shared map.
811+
*
812+
* The caller is also responsible for being sure no concurrent map update
813+
* could be happening.
800814
*/
801815
static void
802-
write_relmap_file(bool shared, RelMapFile *newmap,
803-
bool write_wal, bool send_sinval, bool preserve_files,
804-
Oid dbid, Oid tsid, const char *dbpath)
816+
write_relmap_file(RelMapFile *newmap, bool write_wal, bool send_sinval,
817+
bool preserve_files, Oid dbid, Oid tsid, const char *dbpath)
805818
{
806819
int fd;
807-
RelMapFile *realmap;
808820
char mapfilename[MAXPGPATH];
809821

810822
/*
@@ -822,19 +834,8 @@ write_relmap_file(bool shared, RelMapFile *newmap,
822834
* Open the target file. We prefer to do this before entering the
823835
* critical section, so that an open() failure need not force PANIC.
824836
*/
825-
if (shared)
826-
{
827-
snprintf(mapfilename, sizeof(mapfilename), "global/%s",
828-
RELMAPPER_FILENAME);
829-
realmap = &shared_map;
830-
}
831-
else
832-
{
833-
snprintf(mapfilename, sizeof(mapfilename), "%s/%s",
834-
dbpath, RELMAPPER_FILENAME);
835-
realmap = &local_map;
836-
}
837-
837+
snprintf(mapfilename, sizeof(mapfilename), "%s/%s",
838+
dbpath, RELMAPPER_FILENAME);
838839
fd = OpenTransientFile(mapfilename, O_WRONLY | O_CREAT | PG_BINARY);
839840
if (fd < 0)
840841
ereport(ERROR,
@@ -934,16 +935,6 @@ write_relmap_file(bool shared, RelMapFile *newmap,
934935
}
935936
}
936937

937-
/*
938-
* Success, update permanent copy. During bootstrap, we might be working
939-
* on the permanent copy itself, in which case skip the memcpy() to avoid
940-
* invoking nominally-undefined behavior.
941-
*/
942-
if (realmap != newmap)
943-
memcpy(realmap, newmap, sizeof(RelMapFile));
944-
else
945-
Assert(!send_sinval); /* must be bootstrapping */
946-
947938
/* Critical section done */
948939
if (write_wal)
949940
END_CRIT_SECTION();
@@ -990,10 +981,19 @@ perform_relmap_update(bool shared, const RelMapFile *updates)
990981
merge_map_updates(&newmap, updates, allowSystemTableMods);
991982

992983
/* Write out the updated map and do other necessary tasks */
993-
write_relmap_file(shared, &newmap, true, true, true,
984+
write_relmap_file(&newmap, true, true, true,
994985
(shared ? InvalidOid : MyDatabaseId),
995986
(shared ? GLOBALTABLESPACE_OID : MyDatabaseTableSpace),
996-
DatabasePath);
987+
(shared ? "global" : DatabasePath));
988+
989+
/*
990+
* We succesfully wrote the updated file, so it's now safe to rely on the
991+
* new values in this process, too.
992+
*/
993+
if (shared)
994+
memcpy(&shared_map, &newmap, sizeof(RelMapFile));
995+
else
996+
memcpy(&local_map, &newmap, sizeof(RelMapFile));
997997

998998
/* Now we can release the lock */
999999
LWLockRelease(RelationMappingLock);
@@ -1033,8 +1033,7 @@ relmap_redo(XLogReaderState *record)
10331033
* but grab the lock to interlock against load_relmap_file().
10341034
*/
10351035
LWLockAcquire(RelationMappingLock, LW_EXCLUSIVE);
1036-
write_relmap_file((xlrec->dbid == InvalidOid), &newmap,
1037-
false, true, false,
1036+
write_relmap_file(&newmap, false, true, false,
10381037
xlrec->dbid, xlrec->tsid, dbpath);
10391038
LWLockRelease(RelationMappingLock);
10401039

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy