00001 /*------------------------------------------------------------------------- 00002 * 00003 * sinval.c 00004 * POSTGRES shared cache invalidation communication code. 00005 * 00006 * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group 00007 * Portions Copyright (c) 1994, Regents of the University of California 00008 * 00009 * 00010 * IDENTIFICATION 00011 * src/backend/storage/ipc/sinval.c 00012 * 00013 *------------------------------------------------------------------------- 00014 */ 00015 #include "postgres.h" 00016 00017 #include "access/xact.h" 00018 #include "commands/async.h" 00019 #include "miscadmin.h" 00020 #include "storage/ipc.h" 00021 #include "storage/sinvaladt.h" 00022 #include "utils/inval.h" 00023 00024 00025 uint64 SharedInvalidMessageCounter; 00026 00027 00028 /* 00029 * Because backends sitting idle will not be reading sinval events, we 00030 * need a way to give an idle backend a swift kick in the rear and make 00031 * it catch up before the sinval queue overflows and forces it to go 00032 * through a cache reset exercise. This is done by sending 00033 * PROCSIG_CATCHUP_INTERRUPT to any backend that gets too far behind. 00034 * 00035 * State for catchup events consists of two flags: one saying whether 00036 * the signal handler is currently allowed to call ProcessCatchupEvent 00037 * directly, and one saying whether the signal has occurred but the handler 00038 * was not allowed to call ProcessCatchupEvent at the time. 00039 * 00040 * NB: the "volatile" on these declarations is critical! If your compiler 00041 * does not grok "volatile", you'd be best advised to compile this file 00042 * with all optimization turned off. 00043 */ 00044 static volatile int catchupInterruptEnabled = 0; 00045 static volatile int catchupInterruptOccurred = 0; 00046 00047 static void ProcessCatchupEvent(void); 00048 00049 00050 /* 00051 * SendSharedInvalidMessages 00052 * Add shared-cache-invalidation message(s) to the global SI message queue. 00053 */ 00054 void 00055 SendSharedInvalidMessages(const SharedInvalidationMessage *msgs, int n) 00056 { 00057 SIInsertDataEntries(msgs, n); 00058 } 00059 00060 /* 00061 * ReceiveSharedInvalidMessages 00062 * Process shared-cache-invalidation messages waiting for this backend 00063 * 00064 * We guarantee to process all messages that had been queued before the 00065 * routine was entered. It is of course possible for more messages to get 00066 * queued right after our last SIGetDataEntries call. 00067 * 00068 * NOTE: it is entirely possible for this routine to be invoked recursively 00069 * as a consequence of processing inside the invalFunction or resetFunction. 00070 * Furthermore, such a recursive call must guarantee that all outstanding 00071 * inval messages have been processed before it exits. This is the reason 00072 * for the strange-looking choice to use a statically allocated buffer array 00073 * and counters; it's so that a recursive call can process messages already 00074 * sucked out of sinvaladt.c. 00075 */ 00076 void 00077 ReceiveSharedInvalidMessages( 00078 void (*invalFunction) (SharedInvalidationMessage *msg), 00079 void (*resetFunction) (void)) 00080 { 00081 #define MAXINVALMSGS 32 00082 static SharedInvalidationMessage messages[MAXINVALMSGS]; 00083 00084 /* 00085 * We use volatile here to prevent bugs if a compiler doesn't realize that 00086 * recursion is a possibility ... 00087 */ 00088 static volatile int nextmsg = 0; 00089 static volatile int nummsgs = 0; 00090 00091 /* Deal with any messages still pending from an outer recursion */ 00092 while (nextmsg < nummsgs) 00093 { 00094 SharedInvalidationMessage *msg = &messages[nextmsg++]; 00095 00096 SharedInvalidMessageCounter++; 00097 invalFunction(msg); 00098 } 00099 00100 do 00101 { 00102 int getResult; 00103 00104 nextmsg = nummsgs = 0; 00105 00106 /* Try to get some more messages */ 00107 getResult = SIGetDataEntries(messages, MAXINVALMSGS); 00108 00109 if (getResult < 0) 00110 { 00111 /* got a reset message */ 00112 elog(DEBUG4, "cache state reset"); 00113 SharedInvalidMessageCounter++; 00114 resetFunction(); 00115 break; /* nothing more to do */ 00116 } 00117 00118 /* Process them, being wary that a recursive call might eat some */ 00119 nextmsg = 0; 00120 nummsgs = getResult; 00121 00122 while (nextmsg < nummsgs) 00123 { 00124 SharedInvalidationMessage *msg = &messages[nextmsg++]; 00125 00126 SharedInvalidMessageCounter++; 00127 invalFunction(msg); 00128 } 00129 00130 /* 00131 * We only need to loop if the last SIGetDataEntries call (which might 00132 * have been within a recursive call) returned a full buffer. 00133 */ 00134 } while (nummsgs == MAXINVALMSGS); 00135 00136 /* 00137 * We are now caught up. If we received a catchup signal, reset that 00138 * flag, and call SICleanupQueue(). This is not so much because we need 00139 * to flush dead messages right now, as that we want to pass on the 00140 * catchup signal to the next slowest backend. "Daisy chaining" the 00141 * catchup signal this way avoids creating spikes in system load for what 00142 * should be just a background maintenance activity. 00143 */ 00144 if (catchupInterruptOccurred) 00145 { 00146 catchupInterruptOccurred = 0; 00147 elog(DEBUG4, "sinval catchup complete, cleaning queue"); 00148 SICleanupQueue(false, 0); 00149 } 00150 } 00151 00152 00153 /* 00154 * HandleCatchupInterrupt 00155 * 00156 * This is called when PROCSIG_CATCHUP_INTERRUPT is received. 00157 * 00158 * If we are idle (catchupInterruptEnabled is set), we can safely 00159 * invoke ProcessCatchupEvent directly. Otherwise, just set a flag 00160 * to do it later. (Note that it's quite possible for normal processing 00161 * of the current transaction to cause ReceiveSharedInvalidMessages() 00162 * to be run later on; in that case the flag will get cleared again, 00163 * since there's no longer any reason to do anything.) 00164 */ 00165 void 00166 HandleCatchupInterrupt(void) 00167 { 00168 /* 00169 * Note: this is called by a SIGNAL HANDLER. You must be very wary what 00170 * you do here. 00171 */ 00172 00173 /* Don't joggle the elbow of proc_exit */ 00174 if (proc_exit_inprogress) 00175 return; 00176 00177 if (catchupInterruptEnabled) 00178 { 00179 bool save_ImmediateInterruptOK = ImmediateInterruptOK; 00180 00181 /* 00182 * We may be called while ImmediateInterruptOK is true; turn it off 00183 * while messing with the catchup state. (We would have to save and 00184 * restore it anyway, because PGSemaphore operations inside 00185 * ProcessCatchupEvent() might reset it.) 00186 */ 00187 ImmediateInterruptOK = false; 00188 00189 /* 00190 * I'm not sure whether some flavors of Unix might allow another 00191 * SIGUSR1 occurrence to recursively interrupt this routine. To cope 00192 * with the possibility, we do the same sort of dance that 00193 * EnableCatchupInterrupt must do --- see that routine for comments. 00194 */ 00195 catchupInterruptEnabled = 0; /* disable any recursive signal */ 00196 catchupInterruptOccurred = 1; /* do at least one iteration */ 00197 for (;;) 00198 { 00199 catchupInterruptEnabled = 1; 00200 if (!catchupInterruptOccurred) 00201 break; 00202 catchupInterruptEnabled = 0; 00203 if (catchupInterruptOccurred) 00204 { 00205 /* Here, it is finally safe to do stuff. */ 00206 ProcessCatchupEvent(); 00207 } 00208 } 00209 00210 /* 00211 * Restore ImmediateInterruptOK, and check for interrupts if needed. 00212 */ 00213 ImmediateInterruptOK = save_ImmediateInterruptOK; 00214 if (save_ImmediateInterruptOK) 00215 CHECK_FOR_INTERRUPTS(); 00216 } 00217 else 00218 { 00219 /* 00220 * In this path it is NOT SAFE to do much of anything, except this: 00221 */ 00222 catchupInterruptOccurred = 1; 00223 } 00224 } 00225 00226 /* 00227 * EnableCatchupInterrupt 00228 * 00229 * This is called by the PostgresMain main loop just before waiting 00230 * for a frontend command. We process any pending catchup events, 00231 * and enable the signal handler to process future events directly. 00232 * 00233 * NOTE: the signal handler starts out disabled, and stays so until 00234 * PostgresMain calls this the first time. 00235 */ 00236 void 00237 EnableCatchupInterrupt(void) 00238 { 00239 /* 00240 * This code is tricky because we are communicating with a signal handler 00241 * that could interrupt us at any point. If we just checked 00242 * catchupInterruptOccurred and then set catchupInterruptEnabled, we could 00243 * fail to respond promptly to a signal that happens in between those two 00244 * steps. (A very small time window, perhaps, but Murphy's Law says you 00245 * can hit it...) Instead, we first set the enable flag, then test the 00246 * occurred flag. If we see an unserviced interrupt has occurred, we 00247 * re-clear the enable flag before going off to do the service work. (That 00248 * prevents re-entrant invocation of ProcessCatchupEvent() if another 00249 * interrupt occurs.) If an interrupt comes in between the setting and 00250 * clearing of catchupInterruptEnabled, then it will have done the service 00251 * work and left catchupInterruptOccurred zero, so we have to check again 00252 * after clearing enable. The whole thing has to be in a loop in case 00253 * another interrupt occurs while we're servicing the first. Once we get 00254 * out of the loop, enable is set and we know there is no unserviced 00255 * interrupt. 00256 * 00257 * NB: an overenthusiastic optimizing compiler could easily break this 00258 * code. Hopefully, they all understand what "volatile" means these days. 00259 */ 00260 for (;;) 00261 { 00262 catchupInterruptEnabled = 1; 00263 if (!catchupInterruptOccurred) 00264 break; 00265 catchupInterruptEnabled = 0; 00266 if (catchupInterruptOccurred) 00267 ProcessCatchupEvent(); 00268 } 00269 } 00270 00271 /* 00272 * DisableCatchupInterrupt 00273 * 00274 * This is called by the PostgresMain main loop just after receiving 00275 * a frontend command. Signal handler execution of catchup events 00276 * is disabled until the next EnableCatchupInterrupt call. 00277 * 00278 * The PROCSIG_NOTIFY_INTERRUPT signal handler also needs to call this, 00279 * so as to prevent conflicts if one signal interrupts the other. So we 00280 * must return the previous state of the flag. 00281 */ 00282 bool 00283 DisableCatchupInterrupt(void) 00284 { 00285 bool result = (catchupInterruptEnabled != 0); 00286 00287 catchupInterruptEnabled = 0; 00288 00289 return result; 00290 } 00291 00292 /* 00293 * ProcessCatchupEvent 00294 * 00295 * Respond to a catchup event (PROCSIG_CATCHUP_INTERRUPT) from another 00296 * backend. 00297 * 00298 * This is called either directly from the PROCSIG_CATCHUP_INTERRUPT 00299 * signal handler, or the next time control reaches the outer idle loop 00300 * (assuming there's still anything to do by then). 00301 */ 00302 static void 00303 ProcessCatchupEvent(void) 00304 { 00305 bool notify_enabled; 00306 00307 /* Must prevent notify interrupt while I am running */ 00308 notify_enabled = DisableNotifyInterrupt(); 00309 00310 /* 00311 * What we need to do here is cause ReceiveSharedInvalidMessages() to run, 00312 * which will do the necessary work and also reset the 00313 * catchupInterruptOccurred flag. If we are inside a transaction we can 00314 * just call AcceptInvalidationMessages() to do this. If we aren't, we 00315 * start and immediately end a transaction; the call to 00316 * AcceptInvalidationMessages() happens down inside transaction start. 00317 * 00318 * It is awfully tempting to just call AcceptInvalidationMessages() 00319 * without the rest of the xact start/stop overhead, and I think that 00320 * would actually work in the normal case; but I am not sure that things 00321 * would clean up nicely if we got an error partway through. 00322 */ 00323 if (IsTransactionOrTransactionBlock()) 00324 { 00325 elog(DEBUG4, "ProcessCatchupEvent inside transaction"); 00326 AcceptInvalidationMessages(); 00327 } 00328 else 00329 { 00330 elog(DEBUG4, "ProcessCatchupEvent outside transaction"); 00331 StartTransactionCommand(); 00332 CommitTransactionCommand(); 00333 } 00334 00335 if (notify_enabled) 00336 EnableNotifyInterrupt(); 00337 }