void StreamBatchWaitAndRemove(StreamBatch *batch) { int cycle = 0; while (!StreamBatchAllAcked(batch)) { if (cycle % CHECK_CRASH_CYCLES == 0) { int num_crashes = num_cq_crashes(batch); cycle = 0; if (num_crashes == 0) continue; // All tuples have been read, and we've received acks from all workers that didn't crash. if (StreamBatchAllRead(batch) && batch->num_wacks >= (batch->num_tups * (bms_num_members(batch->readers) - num_crashes))) break; } pg_usleep(SLEEP_MS * 1000); cycle++; } ShmemDynFree(batch); }
static jint initializeJavaVM(JVMOptList *optList) { jint jstat; JavaVMInitArgs vm_args; if(pljava_debug) { elog(INFO, "Backend pid = %d. Attach the debugger and set pljava_debug to false to continue", getpid()); while(pljava_debug) pg_usleep(1000000L); } vm_args.nOptions = optList->size; vm_args.options = optList->options; vm_args.version = JNI_VERSION_1_4; vm_args.ignoreUnrecognized = JNI_FALSE; elog(DEBUG2, "creating Java virtual machine"); jstat = JNI_createVM(&s_javaVM, &vm_args); if(jstat == JNI_OK && JNI_exceptionCheck()) { JNI_exceptionDescribe(); JNI_exceptionClear(); jstat = JNI_ERR; } JVMOptList_delete(optList); return jstat; }
static void terminate_group(ContQueryProcGroup *grp) { bool found; int i; grp->active = true; for (i = 0; i < TOTAL_SLOTS; i++) { ContQueryProc *proc = &grp->procs[i]; /* Wake up processes, so they can see the terminate flag. */ SetLatch(proc->latch); /* Let workers crash now as well in case we force terminate them. */ ChangeBackgroundWorkerRestartState(&proc->handle, true, 0); } /* Wait for a bit and then force terminate any processes that are still alive. */ pg_usleep(Max(ContQuerySchedulerShmem->params.max_wait, MIN_WAIT_TERMINATE_MS) * 1000); for (i = 0; i < TOTAL_SLOTS; i++) { ContQueryProc *proc = &grp->procs[i]; TerminateBackgroundWorker(&proc->handle); } hash_search(ContQuerySchedulerShmem->proc_table, &grp->db_oid, HASH_REMOVE, &found); Assert(found); TupleBufferDrain(WorkerTupleBuffer, grp->db_oid); TupleBufferDrain(CombinerTupleBuffer, grp->db_oid); }
/* * Wait while spinning on a contended spinlock. */ void perform_spin_delay(SpinDelayStatus *status) { /* CPU-specific delay each time through the loop */ SPIN_DELAY(); /* Block the process every spins_per_delay tries */ if (++(status->spins) >= spins_per_delay) { if (++(status->delays) > NUM_DELAYS) s_lock_stuck(status->file, status->line, status->func); if (status->cur_delay == 0) /* first time to delay? */ status->cur_delay = MIN_DELAY_USEC; pg_usleep(status->cur_delay); #if defined(S_LOCK_TEST) fprintf(stdout, "*"); fflush(stdout); #endif /* increase delay by a random fraction between 1X and 2X */ status->cur_delay += (int) (status->cur_delay * ((double) random() / (double) MAX_RANDOM_VALUE) + 0.5); /* wrap back to minimum delay when max is exceeded */ if (status->cur_delay > MAX_DELAY_USEC) status->cur_delay = MIN_DELAY_USEC; status->spins = 0; } }
/* * pgrename */ int pgrename(const char *from, const char *to) { int loops = 0; /* * We need to loop because even though PostgreSQL uses flags that * allow rename while the file is open, other applications might have * the file open without those flags. However, we won't wait * indefinitely for someone else to close the file. */ #if defined(WIN32) && !defined(__CYGWIN__) while (!MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING)) #else while (rename(from, to) < 0) #endif { #if defined(WIN32) && !defined(__CYGWIN__) if (GetLastError() != ERROR_ACCESS_DENIED) #else if (errno != EACCES) #endif /* set errno? */ return -1; if (++loops > 300) /* time out after 30 sec */ return -1; pg_usleep(100000); /* us */ } return 0; }
/* * Synchronize threads to finish for this process to die. Dispatching * threads need to acknowledge that we are dying, otherwise the main * thread will cleanup memory contexts which could cause process crash * while the threads are touching stale pointers. Threads will check * proc_exit_inprogress and immediately stops once it's found to be true. */ void cdbdisp_waitThreads(void) { int i, max_retry; long interval = 10 * 1000; /* 10 msec */ /* * Just in case to avoid to be stuck in the final stage of process * lifecycle, insure by setting time limit. If it exceeds, it probably * means some threads are stuck and not progressing, in which case * we can go ahead and cleanup things anyway. The duration should be * longer than the select timeout in thread_DispatchWait. */ max_retry = (DISPATCH_WAIT_TIMEOUT_SEC + 10) * 1000000L / interval; /* * This is supposed to be called after the flag is set. */ Assert(proc_exit_inprogress); for (i = 0; i < max_retry; i++) { if (RunningThreadCount == 0) break; pg_usleep(interval); } }
/* * pgunlink */ int pgunlink(const char *path) { int loops = 0; /* Is this loop even necessary now that we have win32_open()? */ while (unlink(path)) { if (errno != EACCES) /* set errno? */ return -1; pg_usleep(100000); /* us */ if (loops == 30) #ifndef FRONTEND elog(LOG, "could not unlink \"%s\", continuing to try", path); #else fprintf(stderr, "could not unlink \"%s\", continuing to try\n", path); #endif loops++; } if (loops > 30) #ifndef FRONTEND elog(LOG, "completed unlink of \"%s\"", path); #else fprintf(stderr, "completed unlink of \"%s\"\n", path); #endif return 0; }
/* * Standby wait logic for ResolveRecoveryConflictWithVirtualXIDs. * We wait here for a while then return. If we decide we can't wait any * more then we return true, if we can wait some more return false. */ static bool WaitExceedsMaxStandbyDelay(void) { TimestampTz ltime; /* Are we past the limit time? */ ltime = GetStandbyLimitTime(); if (ltime && GetCurrentTimestamp() >= ltime) return true; /* * Sleep a bit (this is essential to avoid busy-waiting). */ pg_usleep(standbyWait_us); /* * Progressively increase the sleep times, but not to more than 1s, since * pg_usleep isn't interruptable on some platforms. */ standbyWait_us *= 2; if (standbyWait_us > 1000000) standbyWait_us = 1000000; return false; }
/* * RestoreWALFileForRecovery() * * Perform the action required to restore the file from archive */ static bool RestoreWALFileForRecovery(void) { int rc = 0; int numretries = 0; if (debug) { fprintf(stderr, "running restore: "); fflush(stderr); } while (numretries <= maxretries) { rc = system(restoreCommand); if (rc == 0) { if (debug) { fprintf(stderr, "OK\n"); fflush(stderr); } return true; } pg_usleep(numretries++ * sleeptime * 1000000L); } /* * Allow caller to add additional info */ if (debug) fprintf(stderr, "not restored\n"); return false; }
void ResolveRecoveryConflictWithDatabase(Oid dbid) { /* * We don't do ResolveRecoveryConflictWithVirtualXIDs() here since that * only waits for transactions and completely idle sessions would block * us. This is rare enough that we do this as simply as possible: no wait, * just force them off immediately. * * No locking is required here because we already acquired * AccessExclusiveLock. Anybody trying to connect while we do this will * block during InitPostgres() and then disconnect when they see the * database has been removed. */ while (CountDBBackends(dbid) > 0) { CancelDBBackends(dbid, PROCSIG_RECOVERY_CONFLICT_DATABASE, true); /* * Wait awhile for them to die so that we avoid flooding an * unresponsive backend when system is heavily loaded. */ pg_usleep(10000); } }
/* * ForgetRelationFsyncRequests -- ensure any fsyncs for a rel are forgotten */ void ForgetRelationFsyncRequests(RelFileNode rnode) { if (pendingOpsTable) { /* standalone backend or startup process: fsync state is local */ RememberFsyncRequest(rnode, FORGET_RELATION_FSYNC); } else if (IsUnderPostmaster) { /* * Notify the bgwriter about it. If we fail to queue the revoke * message, we have to sleep and try again ... ugly, but hopefully * won't happen often. * * XXX should we CHECK_FOR_INTERRUPTS in this loop? Escaping with * an error would leave the no-longer-used file still present on * disk, which would be bad, so I'm inclined to assume that the * bgwriter will always empty the queue soon. */ while (!ForwardFsyncRequest(rnode, FORGET_RELATION_FSYNC)) pg_usleep(10000L); /* 10 msec seems a good number */ /* * Note we don't wait for the bgwriter to actually absorb the * revoke message; see mdsync() for the implications. */ } }
/* * FileRepPrimary_RunResyncWorker() * */ static int FileRepPrimary_RunResyncWorker(void) { int status = STATUS_OK; FileRepResyncHashEntry_s *entry = NULL; ChangeTrackingRequest *request = NULL; FileRep_InsertConfigLogEntry("run resync worker"); while (1) { FileRepSubProcess_ProcessSignals(); if (! (FileRepSubProcess_GetState() == FileRepStateReady && dataState == DataStateInResync)) { break; } entry = FileRepPrimary_GetResyncEntry(&request); if (entry == NULL && request == NULL) { pg_usleep(100000L); /* 100 ms */ continue; } Assert(! (entry != NULL && request != NULL)); if (entry != NULL) { status = FileRepPrimary_ResyncWrite(entry); if (status == STATUS_OK) { if (entry->mirrorBufpoolResyncChangedPageCount == 0) { entry->mirrorBufpoolResyncChangedPageCount = (entry->mirrorAppendOnlyNewEof - entry->mirrorAppendOnlyLossEof) / BLCKSZ; } status = FileRepResync_UpdateEntry(entry); } } if (request != NULL) { status = FileRepPrimary_ResyncBufferPoolIncrementalWrite(request); request = NULL; } if (status != STATUS_OK) { break; } } return status; }
int FileRead(File file, char *buffer, int amount) { int returnCode; Assert(FileIsValid(file)); DO_DB(elog(LOG, "FileRead: %d (%s) " INT64_FORMAT " %d %p", file, VfdCache[file].fileName, VfdCache[file].seekPos, amount, buffer)); if (Debug_filerep_print) (elog(LOG, "FileRead: %d (%s) " INT64_FORMAT " %d %p", file, VfdCache[file].fileName, VfdCache[file].seekPos, amount, buffer)); returnCode = FileAccess(file); if (returnCode < 0) return returnCode; retry: returnCode = read(VfdCache[file].fd, buffer, amount); if (returnCode >= 0) VfdCache[file].seekPos += returnCode; else { /* * Windows may run out of kernel buffers and return "Insufficient * system resources" error. Wait a bit and retry to solve it. * * It is rumored that EINTR is also possible on some Unix filesystems, * in which case immediate retry is indicated. */ #ifdef WIN32 DWORD error = GetLastError(); switch (error) { case ERROR_NO_SYSTEM_RESOURCES: pg_usleep(1000L); errno = EINTR; break; default: _dosmaperr(error); break; } #endif /* OK to retry if interrupted */ if (errno == EINTR) goto retry; /* Trouble, so assume we don't know the file position anymore */ VfdCache[file].seekPos = FileUnknownPos; } return returnCode; }
static void LWLockTryLockWaiting( PGPROC *proc, LWLockId lockid, LWLockMode mode) { volatile LWLock *lock = &(LWLockArray[lockid].lock); int milliseconds = 0; int exclusivePid; while(true) { pg_usleep(5000L); if (PGSemaphoreTryLock(&proc->sem)) { if (milliseconds >= 750) elog(LOG, "Done waiting on lockid %d", lockid); return; } milliseconds += 5; if (milliseconds == 750) { int l; int count = 0; char buffer[200]; SpinLockAcquire(&lock->mutex); if (lock->exclusive > 0) exclusivePid = lock->exclusivePid; else exclusivePid = 0; SpinLockRelease(&lock->mutex); memcpy(buffer, "none", 5); for (l = 0; l < num_held_lwlocks; l++) { if (l == 0) count += sprintf(&buffer[count],"("); else count += sprintf(&buffer[count],", "); count += sprintf(&buffer[count], "lockid %d", held_lwlocks[l]); } if (num_held_lwlocks > 0) count += sprintf(&buffer[count],")"); elog(LOG, "Waited .75 seconds on lockid %d with no success. Exclusive pid %d. Already held: %s", lockid, exclusivePid, buffer); } } }
/* * FileRepPrimary_StartResyncWorker() */ void FileRepPrimary_StartResyncWorker(void) { int status = STATUS_OK; FileRep_InsertConfigLogEntry("start resync worker"); Insist(fileRepRole == FileRepPrimaryRole); while (1) { if (status != STATUS_OK) { FileRep_SetSegmentState(SegmentStateFault, FaultTypeMirror); FileRepSubProcess_SetState(FileRepStateFault); } /* * We are waiting for following conditions to move forward: * * Database is running * And * if dataState is InResync, we wait for FileRepSubProcess to Ready state * else don't wait */ while (!isDatabaseRunning() || !(dataState == DataStateInResync ? FileRepSubProcess_GetState() == FileRepStateReady : true)) { FileRepSubProcess_ProcessSignals(); if (FileRepSubProcess_GetState() == FileRepStateShutdown || FileRepSubProcess_GetState() == FileRepStateShutdownBackends) { break; } pg_usleep(50000L); /* 50 ms */ } if (FileRepSubProcess_GetState() == FileRepStateShutdown || FileRepSubProcess_GetState() == FileRepStateShutdownBackends) { break; } FileRepSubProcess_InitHeapAccess(); status = FileRepPrimary_RunResyncWorker(); if (status != STATUS_OK) { continue; } break; } // while(1) }
/* * Wrapper of simple pthread locking functionality, using pthread_mutex_trylock * and loop to make it interruptible when waiting the lock; * * return true if successfuly acquires the lock, false if unable to get the lock * and interrupted by SIGTERM, otherwise, infinitely loop to acquire the mutex. * * If we are going to return false, we close the socket to client; this is crucial * for exiting dispatch thread if it is stuck on sending NOTICE to client, and hence * avoid mutex deadlock; * * NOTE: should not call CHECK_FOR_INTERRUPTS and ereport in this routine, since * it is in multi-thread context; */ static bool pq_send_mutex_lock() { int count = PQ_BUSY_TEST_COUNT_IN_EXITING; int mutex_res; do { mutex_res = pthread_mutex_trylock(&send_mutex); if (mutex_res == 0) { return true; } if (mutex_res == EBUSY) { /* No need to acquire lock for TermSignalReceived, since we are in * a loop here */ if (TermSignalReceived) { /* * try PQ_BUSY_TEST_COUNT_IN_EXITING times before going to * close the socket, in case real concurrent writing is in * progress(compared to stuck send call in secure_write); * * It cannot help completely eliminate the false negative * cases, but giving the process is exiting, it is acceptable * to discard some messages, contrasted with the chance of * infinite stuck; */ if (count-- < 0) { /* On Redhat and Suse, simple closing the socket would not get * send() out of hanging state, shutdown() can do this(though not * explicitly mentioned in manual page); however, if send over a * socket which has been shutdown, process would be terminated by * SIGPIPE; to avoid this race condition, we set the socket to be * invalid before calling shutdown() * * On OSX, close() can get send() out of hanging state, while * shutdown() would lead to SIGPIPE */ int saved_fd = MyProcPort->sock; MyProcPort->sock = -1; whereToSendOutput = DestNone; #ifndef __darwin__ shutdown(saved_fd, SHUT_WR); #endif closesocket(saved_fd); return false; } } } pg_usleep(1000L); } while (true); }
/* * Used by "reader" qExecs to find the slot in the sharedsnapshotArray with the * specified slotId. In general, we should always be able to find the specified * slot unless something unexpected. If the slot is not found, then NULL is * returned. * * MPP-4599: retry in the same pattern as the writer. */ static SharedSnapshotSlot * SharedSnapshotLookup(int4 slotId) { SharedSnapshotSlot *slot = NULL; volatile SharedSnapshotStruct *arrayP = sharedSnapshotArray; int retryCount = gp_snapshotadd_timeout * 10; /* .1 s per wait */ int index; for (;;) { CHECK_FOR_INTERRUPTS(); LWLockAcquire(SharedSnapshotLock, LW_SHARED); for (index=0; index < arrayP->maxSlots; index++) { SharedSnapshotSlot *testSlot; testSlot = &arrayP->slots[index]; if (testSlot->slotindex > arrayP->maxSlots) { LWLockRelease(SharedSnapshotLock); elog(ERROR, "Shared Local Snapshots Array appears corrupted: %s", SharedSnapshotDump()); } if (testSlot->slotid == slotId) { slot = testSlot; break; } } LWLockRelease(SharedSnapshotLock); if (slot != NULL) { break; } else { if (retryCount > 0) { retryCount--; pg_usleep(100000); /* 100ms, wait gp_snapshotadd_timeout seconds max. */ } else { break; } } } return slot; }
/* * pg_sleep - delay for N seconds */ Datum pg_sleep(PG_FUNCTION_ARGS) { float8 secs = PG_GETARG_FLOAT8(0); float8 endtime; /* * We break the requested sleep into segments of no more than 1 second, to * put an upper bound on how long it will take us to respond to a cancel * or die interrupt. (Note that pg_usleep is interruptible by signals on * some platforms but not others.) Also, this method avoids exposing * pg_usleep's upper bound on allowed delays. * * By computing the intended stop time initially, we avoid accumulation of * extra delay across multiple sleeps. This also ensures we won't delay * less than the specified time if pg_usleep is interrupted by other * signals such as SIGHUP. */ #ifdef HAVE_INT64_TIMESTAMP #define GetNowFloat() ((float8) GetCurrentTimestamp() / 1000000.0) #else #define GetNowFloat() GetCurrentTimestamp() #endif endtime = GetNowFloat() + secs; for (;;) { float8 delay; CHECK_FOR_INTERRUPTS(); delay = endtime - GetNowFloat(); if (delay >= 1.0) pg_usleep(1000000L); else if (delay > 0.0) pg_usleep((long) ceil(delay * 1000000.0)); else break; } PG_RETURN_VOID(); }
/* * CheckpointWriteDelay -- control rate of checkpoint * * This function is called after each page write performed by BufferSync(). * It is responsible for throttling BufferSync()'s write rate to hit * checkpoint_completion_target. * * The checkpoint request flags should be passed in; currently the only one * examined is CHECKPOINT_IMMEDIATE, which disables delays between writes. * * 'progress' is an estimate of how much of the work has been done, as a * fraction between 0.0 meaning none, and 1.0 meaning all done. */ void CheckpointWriteDelay(int flags, double progress) { static int absorb_counter = WRITES_PER_ABSORB; /* Do nothing if checkpoint is being executed by non-checkpointer process */ if (!AmCheckpointerProcess()) return; /* * Perform the usual duties and take a nap, unless we're behind schedule, * in which case we just try to catch up as quickly as possible. */ if (!(flags & CHECKPOINT_IMMEDIATE) && !shutdown_requested && !ImmediateCheckpointRequested() && IsCheckpointOnSchedule(progress)) { if (got_SIGHUP) { got_SIGHUP = false; ProcessConfigFile(PGC_SIGHUP); /* update shmem copies of config variables */ UpdateSharedMemoryConfig(); } AbsorbFsyncRequests(); absorb_counter = WRITES_PER_ABSORB; CheckArchiveTimeout(); /* * Report interim activity statistics to the stats collector. */ pgstat_send_bgwriter(); /* * This sleep used to be connected to bgwriter_delay, typically 200ms. * That resulted in more frequent wakeups if not much work to do. * Checkpointer and bgwriter are no longer related so take the Big * Sleep. */ pg_usleep(100000L); } else if (--absorb_counter <= 0) { /* * Absorb pending fsync requests after each WRITES_PER_ABSORB write * operations even when we don't sleep, to prevent overflow of the * fsync request queue. */ AbsorbFsyncRequests(); absorb_counter = WRITES_PER_ABSORB; } }
/* * pgarch_ArchiverCopyLoop * * Archives all outstanding xlogs then returns */ static void pgarch_ArchiverCopyLoop(void) { char xlog[MAX_XFN_CHARS + 1]; if (!XLogArchiveCommandSet()) { ereport(WARNING, (errmsg("archive_mode enabled, yet archive_command is not set"))); /* can't do anything if no command ... */ return; } /* * loop through all xlogs with archive_status of .ready and archive * them...mostly we expect this to be a single file, though it is possible * some backend will add files onto the list of those that need archiving * while we are still copying earlier archives */ while (pgarch_readyXlog(xlog)) { int failures = 0; for (;;) { /* * Do not initiate any more archive commands after receiving * SIGTERM, nor after the postmaster has died unexpectedly. The * first condition is to try to keep from having init SIGKILL the * command, and the second is to avoid conflicts with another * archiver spawned by a newer postmaster. */ if (got_SIGTERM || !PostmasterIsAlive(true)) return; if (pgarch_archiveXlog(xlog)) { /* successful */ pgarch_archiveDone(xlog); break; /* out of inner retry loop */ } else { if (++failures >= NUM_ARCHIVE_RETRIES) { ereport(WARNING, (errmsg("transaction log file \"%s\" could not be archived: too many failures", xlog))); return; /* give up archiving for now */ } pg_usleep(1000000L); /* wait a bit before retrying */ } } } }
/* * BgWriterNap -- Nap for the configured time or until a signal is received. */ static void BgWriterNap(void) { long udelay; /* * Send off activity statistics to the stats collector */ pgstat_send_bgwriter(); /* * Nap for the configured time, or sleep for 10 seconds if there is no * bgwriter activity configured. * * On some platforms, signals won't interrupt the sleep. To ensure we * respond reasonably promptly when someone signals us, break down the * sleep into 1-second increments, and check for interrupts after each * nap. * * We absorb pending requests after each short sleep. */ if (bgwriter_lru_maxpages > 0 || ckpt_active) udelay = BgWriterDelay * 1000L; else if (XLogArchiveTimeout > 0) udelay = 1000000L; /* One second */ else udelay = 10000000L; /* Ten seconds */ while (udelay > 999999L) { if (got_SIGHUP || shutdown_requested || (ckpt_active ? ImmediateCheckpointRequested() : checkpoint_requested)) break; pg_usleep(1000000L); AbsorbFsyncRequests(); udelay -= 1000000L; } if (!(got_SIGHUP || shutdown_requested || (ckpt_active ? ImmediateCheckpointRequested() : checkpoint_requested))) pg_usleep(udelay); }
/* * pgarch_MainLoop * * Main loop for archiver */ static void pgarch_MainLoop(void) { time_t last_copy_time = 0; /* * We run the copy loop immediately upon entry, in case there are * unarchived files left over from a previous database run (or maybe the * archiver died unexpectedly). After that we wait for a signal or * timeout before doing more. */ wakened = true; do { /* Check for config update */ if (got_SIGHUP) { got_SIGHUP = false; ProcessConfigFile(PGC_SIGHUP); if (!XLogArchivingActive()) break; /* user wants us to shut down */ } /* Do what we're here for */ if (wakened) { wakened = false; pgarch_ArchiverCopyLoop(); last_copy_time = time(NULL); } /* * There shouldn't be anything for the archiver to do except to wait * for a signal ... however, the archiver exists to protect our data, * so she wakes up occasionally to allow herself to be proactive. * * On some platforms, signals won't interrupt the sleep. To ensure we * respond reasonably promptly when someone signals us, break down the * sleep into 1-second increments, and check for interrupts after each * nap. */ while (!(wakened || got_SIGHUP)) { time_t curtime; pg_usleep(1000000L); curtime = time(NULL); if ((unsigned int) (curtime - last_copy_time) >= (unsigned int) PGARCH_AUTOWAKE_INTERVAL) wakened = true; } } while (PostmasterIsAlive(true)); }
int FileWrite(File file, char *buffer, int amount) { int returnCode; Assert(FileIsValid(file)); DO_DB(elog(LOG, "FileWrite: %d (%s) %ld %d %p", file, VfdCache[file].fileName, VfdCache[file].seekPos, amount, buffer)); returnCode = FileAccess(file); if (returnCode < 0) return returnCode; retry: errno = 0; returnCode = write(VfdCache[file].fd, buffer, amount); /* if write didn't set errno, assume problem is no disk space */ if (returnCode != amount && errno == 0) errno = ENOSPC; if (returnCode >= 0) VfdCache[file].seekPos += returnCode; else { /* * See comments in FileRead() */ #ifdef WIN32 DWORD error = GetLastError(); switch (error) { case ERROR_NO_SYSTEM_RESOURCES: pg_usleep(1000L); errno = EINTR; break; default: _dosmaperr(error); break; } #endif /* OK to retry if interrupted */ if (errno == EINTR) goto retry; /* Trouble, so assume we don't know the file position anymore */ VfdCache[file].seekPos = FileUnknownPos; } return returnCode; }
Datum lock_test2(PG_FUNCTION_ARGS) { Oid table_oid; text *lock_type; float8 sleep_time; const char *lock_type_str; LOCKMODE lockmode; Relation heapRelation; table_oid = PG_GETARG_OID(0); lock_type = PG_GETARG_TEXT_P(1); sleep_time = PG_GETARG_FLOAT8(2); lock_type_str = text_to_cstring(lock_type); if (pg_strcasecmp(lock_type_str, "NOLOCK") == 0) lockmode = NoLock; else if (pg_strcasecmp(lock_type_str, "ACCESSSHARELOCK") == 0) lockmode = AccessShareLock; else if (pg_strcasecmp(lock_type_str, "ROWSHARELOCK") == 0) lockmode = RowShareLock; else if (pg_strcasecmp(lock_type_str, "ROWEXCLUSIVELOCK") == 0) lockmode = RowExclusiveLock; else if (pg_strcasecmp(lock_type_str, "SHAREUPDATEEXCLUSIVELOCK") == 0) lockmode = ShareUpdateExclusiveLock; else if (pg_strcasecmp(lock_type_str, "SHARELOCK") == 0) lockmode = ShareLock; else if (pg_strcasecmp(lock_type_str, "SHAREEXCLUSIVELOCK") == 0) lockmode = ShareRowExclusiveLock; else if (pg_strcasecmp(lock_type_str, "EXCLUSIVELOCK") == 0) lockmode = ExclusiveLock; else if (pg_strcasecmp(lock_type_str, "ACCESSEXCLUSIVELOCK") == 0) lockmode = AccessExclusiveLock; else ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("\"lock_mode\" is set to invalid string: %s", lock_type_str), errhint("\"lock_mode\" must select one among NoLock, AccessShareLock, RowShareLock, RowExclusiveLock, ShareUpdateExclusiveLock, ShareLock, ShareExclusiveLock, ExclusiveLock, and AccessExclusiveLock"))); elog(NOTICE, "enter lock %d as %s", table_oid, lock_type_str); heapRelation = relation_open(table_oid, lockmode); elog(NOTICE, "succeed locking %d as %s", table_oid, lock_type_str); pg_usleep(sleep_time * 1000000L); relation_close(heapRelation, lockmode); elog(NOTICE, "exit lock %d as %s", table_oid, lock_type_str); PG_RETURN_VOID(); }
void PleaseDebugMe(char *caller) { int i; for (i = 0; i < 300;i++) { elog(LOG, "%s --> Now would be a good time to debug pid = %d", caller, MyProcPid); elog(NOTICE, "%s --> Now would be a good time to debug pid = %d", caller, MyProcPid); pg_usleep(1000000L); } }
/* * Stop walreceiver (if running) and wait for it to die. * Executed by the Startup process. */ void ShutdownWalRcv(void) { WalRcvData *walrcv = WalRcv; pid_t walrcvpid = 0; /* * Request walreceiver to stop. Walreceiver will switch to WALRCV_STOPPED * mode once it's finished, and will also request postmaster to not * restart itself. */ SpinLockAcquire(&walrcv->mutex); switch (walrcv->walRcvState) { case WALRCV_STOPPED: break; case WALRCV_STARTING: walrcv->walRcvState = WALRCV_STOPPED; break; case WALRCV_STREAMING: case WALRCV_WAITING: case WALRCV_RESTARTING: walrcv->walRcvState = WALRCV_STOPPING; /* fall through */ case WALRCV_STOPPING: walrcvpid = walrcv->pid; break; } SpinLockRelease(&walrcv->mutex); /* * Signal walreceiver process if it was still running. */ if (walrcvpid != 0) kill(walrcvpid, SIGTERM); /* * Wait for walreceiver to acknowledge its death by setting state to * WALRCV_STOPPED. */ while (WalRcvRunning()) { /* * This possibly-long loop needs to handle interrupts of startup * process. */ HandleStartupProcInterrupts(); pg_usleep(100000); /* 100ms */ } }
/* * pgarch_MainLoop * * Main loop for archiver */ static void pgarch_MainLoop(void) { time_t last_copy_time = 0; time_t curtime; /* * We run the copy loop immediately upon entry, in case there are * unarchived files left over from a previous database run (or maybe the * archiver died unexpectedly). After that we wait for a signal or * timeout before doing more. */ wakened = true; do { /* Check for config update */ if (got_SIGHUP) { got_SIGHUP = false; ProcessConfigFile(PGC_SIGHUP); if (!XLogArchivingActive()) break; /* user wants us to shut down */ } /* Do what we're here for */ if (wakened) { wakened = false; pgarch_ArchiverCopyLoop(); last_copy_time = time(NULL); } /* * There shouldn't be anything for the archiver to do except to wait * for a signal, ... however, the archiver exists to protect our data, * so she wakes up occasionally to allow herself to be proactive. In * particular this avoids getting stuck if a signal arrives just * before we sleep. */ if (!wakened) { pg_usleep(PGARCH_AUTOWAKE_INTERVAL * 1000000L); curtime = time(NULL); if ((unsigned int) (curtime - last_copy_time) >= (unsigned int) PGARCH_AUTOWAKE_INTERVAL) wakened = true; } } while (PostmasterIsAlive(true)); }
/* * CustomizableNextWALFileReady() * * Is the requested file ready yet? */ static bool CustomizableNextWALFileReady() { if (stat(WALFilePath, &stat_buf) == 0) { /* * If it's a backup file, return immediately. If it's a regular file * return only if it's the right size already. */ if (strlen(nextWALFileName) > 24 && strspn(nextWALFileName, "0123456789ABCDEF") == 24 && strcmp(nextWALFileName + strlen(nextWALFileName) - strlen(".backup"), ".backup") == 0) { nextWALFileType = XLOG_BACKUP_LABEL; return true; } else if (stat_buf.st_size == XLOG_SEG_SIZE) { #ifdef WIN32 /* * Windows 'cp' sets the final file size before the copy is * complete, and not yet ready to be opened by pg_standby. So we * wait for sleeptime secs before attempting to restore. If that * is not enough, we will rely on the retry/holdoff mechanism. * GNUWin32's cp does not have this problem. */ pg_usleep(sleeptime * 1000000L); #endif nextWALFileType = XLOG_DATA; return true; } /* * If still too small, wait until it is the correct size */ if (stat_buf.st_size > XLOG_SEG_SIZE) { if (debug) { fprintf(stderr, "file size greater than expected\n"); fflush(stderr); } exit(3); } } return false; }
/* * CustomizableNextWALFileReady() * * Is the requested file ready yet? */ static bool CustomizableNextWALFileReady() { if (stat(WALFilePath, &stat_buf) == 0) { /* * If its a backup file, return immediately * If its a regular file return only if its the right size already */ if (strlen(nextWALFileName) > 24 && strspn(nextWALFileName, "0123456789ABCDEF") == 24 && strcmp(nextWALFileName + strlen(nextWALFileName) - strlen(".backup"), ".backup") == 0) { nextWALFileType = XLOG_BACKUP_LABEL; return true; } else if (stat_buf.st_size == XLOG_SEG_SIZE) { #ifdef WIN32 /* * Windows reports that the file has the right number of bytes * even though the file is still being copied and cannot be * opened by pg_standby yet. So we wait for sleeptime secs * before attempting to restore. If that is not enough, we * will rely on the retry/holdoff mechanism. */ pg_usleep(sleeptime * 1000000L); #endif nextWALFileType = XLOG_DATA; return true; } /* * If still too small, wait until it is the correct size */ if (stat_buf.st_size > XLOG_SEG_SIZE) { if (debug) { fprintf(stderr, "file size greater than expected\n"); fflush(stderr); } exit(3); } } return false; }
/* * Stop walreceiver (if running) and wait for it to die. */ void ShutdownWalRcv(void) { /* use volatile pointer to prevent code rearrangement */ volatile WalRcvData *walrcv = WalRcv; pid_t walrcvpid = 0; /* * Request walreceiver to stop. Walreceiver will switch to WALRCV_STOPPED * mode once it's finished, and will also request postmaster to not * restart itself. */ spin_lock(&walrcv->mutex); switch (walrcv->walRcvState) { case WALRCV_STOPPED: break; case WALRCV_STARTING: walrcv->walRcvState = WALRCV_STOPPED; break; case WALRCV_RUNNING: walrcv->walRcvState = WALRCV_STOPPING; /* fall through */ case WALRCV_STOPPING: walrcvpid = walrcv->pid; break; } spin_unlock(&walrcv->mutex); /* * Signal walreceiver process if it was still running. */ if (walrcvpid != 0) kill(walrcvpid, SIGTERM); /* * Wait for walreceiver to acknowledge its death by setting state to * WALRCV_STOPPED. */ while (walrcv_in_progress()) { /* * This possibly-long loop needs to handle interrupts of startup * process. */ handle_startup_proc_intr(); pg_usleep(100000); /* 100ms */ } }