|
80 | 80 | * Portions Copyright (c) 1994, Regents of the University of California
|
81 | 81 | *
|
82 | 82 | * IDENTIFICATION
|
83 |
| - * $PostgreSQL: pgsql/src/backend/utils/cache/inval.c,v 1.91 2010/01/02 16:57:55 momjian Exp $ |
| 83 | + * $PostgreSQL: pgsql/src/backend/utils/cache/inval.c,v 1.92 2010/01/09 16:49:27 sriggs Exp $ |
84 | 84 | *
|
85 | 85 | *-------------------------------------------------------------------------
|
86 | 86 | */
|
|
89 | 89 | #include "access/twophase_rmgr.h"
|
90 | 90 | #include "access/xact.h"
|
91 | 91 | #include "catalog/catalog.h"
|
| 92 | +#include "catalog/pg_tablespace.h" |
92 | 93 | #include "miscadmin.h"
|
93 | 94 | #include "storage/sinval.h"
|
94 | 95 | #include "storage/smgr.h"
|
@@ -871,6 +872,111 @@ xactGetCommittedInvalidationMessages(SharedInvalidationMessage **msgs,
|
871 | 872 | return numSharedInvalidMessagesArray;
|
872 | 873 | }
|
873 | 874 |
|
| 875 | +#define RecoveryRelationCacheInitFileInvalidate(dbo, tbo, tf) \ |
| 876 | +{ \ |
| 877 | + DatabasePath = GetDatabasePath(dbo, tbo); \ |
| 878 | + elog(trace_recovery(DEBUG4), "removing relcache init file in %s", DatabasePath); \ |
| 879 | + RelationCacheInitFileInvalidate(tf); \ |
| 880 | + pfree(DatabasePath); \ |
| 881 | +} |
| 882 | + |
| 883 | +/* |
| 884 | + * ProcessCommittedInvalidationMessages is executed by xact_redo_commit() |
| 885 | + * to process invalidation messages added to commit records. |
| 886 | + * |
| 887 | + * If we have to invalidate the relcache init file we need to extract |
| 888 | + * the database id from each message so we can correctly locate the database |
| 889 | + * path and so remove that database's init file. We note that the relcache |
| 890 | + * only contains entries for catalog tables from a single database, or |
| 891 | + * shared relations. There are smgr invalidations that reference other |
| 892 | + * databases but they never cause relcache file invalidations. |
| 893 | + * So we only need to access either global or default tablespaces and |
| 894 | + * never have need to scan pg_database to discover tablespace oids. |
| 895 | + * |
| 896 | + * Relcache init file invalidation requires processing both |
| 897 | + * before and after we send the SI messages. See AtEOXact_Inval() |
| 898 | + * |
| 899 | + * We deliberately avoid SetDatabasePath() since it is intended to be used |
| 900 | + * only once by normal backends, so we set DatabasePath directly then |
| 901 | + * pfree after use. See RecoveryRelationCacheInitFileInvalidate() macro. |
| 902 | + */ |
| 903 | +void |
| 904 | +ProcessCommittedInvalidationMessages(SharedInvalidationMessage *msgs, |
| 905 | + int nmsgs, bool RelcacheInitFileInval) |
| 906 | +{ |
| 907 | + Oid dboid = 0; |
| 908 | + bool invalidate_global = false; |
| 909 | + |
| 910 | + if (nmsgs > 0) |
| 911 | + elog(trace_recovery(DEBUG4), "replaying commit with %d messages%s", nmsgs, |
| 912 | + (RelcacheInitFileInval ? " and relcache file invalidation" : "")); |
| 913 | + else |
| 914 | + return; |
| 915 | + |
| 916 | + if (RelcacheInitFileInval) |
| 917 | + { |
| 918 | + int i; |
| 919 | + |
| 920 | + /* |
| 921 | + * Check messages to record dboid |
| 922 | + */ |
| 923 | + for (i = 0; i < nmsgs; i++) |
| 924 | + { |
| 925 | + SharedInvalidationMessage *inval_msg = &(msgs[i]); |
| 926 | + Oid loop_dboid = 0; |
| 927 | + |
| 928 | + /* |
| 929 | + * Extract the database Oid from the message |
| 930 | + */ |
| 931 | + if (inval_msg->id >= 0) |
| 932 | + loop_dboid = inval_msg->cc.dbId; |
| 933 | + else if (inval_msg->id == SHAREDINVALRELCACHE_ID) |
| 934 | + loop_dboid = inval_msg->rc.dbId; |
| 935 | + else |
| 936 | + { |
| 937 | + /* |
| 938 | + * Invalidation message is a SHAREDINVALSMGR_ID |
| 939 | + * which never cause relcache file invalidation, |
| 940 | + * so we ignore them, no matter which db they're for. |
| 941 | + */ |
| 942 | + continue; |
| 943 | + } |
| 944 | + |
| 945 | + if (loop_dboid == 0) |
| 946 | + invalidate_global = true; |
| 947 | + else |
| 948 | + { |
| 949 | + Assert(dboid == 0 || dboid == loop_dboid); |
| 950 | + dboid = loop_dboid; |
| 951 | + } |
| 952 | + } |
| 953 | + |
| 954 | + /* |
| 955 | + * If shared, dboid will be the global tablespace, otherwise it will |
| 956 | + * be a local catalog relation in the default tablespace. |
| 957 | + */ |
| 958 | + if (invalidate_global) |
| 959 | + RecoveryRelationCacheInitFileInvalidate(0, GLOBALTABLESPACE_OID, true); |
| 960 | + |
| 961 | + if (dboid != 0) |
| 962 | + RecoveryRelationCacheInitFileInvalidate(dboid, DEFAULTTABLESPACE_OID, true); |
| 963 | + } |
| 964 | + |
| 965 | + SendSharedInvalidMessages(msgs, nmsgs); |
| 966 | + |
| 967 | + if (RelcacheInitFileInval) |
| 968 | + { |
| 969 | + /* |
| 970 | + * Second invalidation, very similar to above. See RelationCacheInitFileInvalidate() |
| 971 | + */ |
| 972 | + if (invalidate_global) |
| 973 | + RecoveryRelationCacheInitFileInvalidate(0, GLOBALTABLESPACE_OID, false); |
| 974 | + |
| 975 | + if (dboid != 0) |
| 976 | + RecoveryRelationCacheInitFileInvalidate(dboid, DEFAULTTABLESPACE_OID, false); |
| 977 | + } |
| 978 | +} |
| 979 | + |
874 | 980 | /*
|
875 | 981 | * AtEOXact_Inval
|
876 | 982 | * Process queued-up invalidation messages at end of main transaction.
|
|
0 commit comments