57 #define AUTOPREWARM_FILE "autoprewarm.blocks" 92 static int apw_dump_now(
bool is_bgworker,
bool dump_unlogged);
113 "Sets the interval between dumps of shared buffers",
114 "If set to zero, time-based dumping is disabled.",
129 "Starts the autoprewarm worker.",
155 bool first_time =
true;
156 bool final_dump_allowed =
true;
181 (
errmsg(
"autoprewarm worker is already running under PID %lu",
241 if (delay_in_ms <= 0)
263 if (final_dump_allowed)
291 (
errmsg(
"skipping prewarm because block dump file is being written by PID %lu",
313 errmsg(
"could not read file \"%s\": %m",
318 if (fscanf(file,
"<<%d>>\n", &num_elements) != 1)
321 errmsg(
"could not read from file \"%s\": %m",
329 for (i = 0; i < num_elements; i++)
333 if (fscanf(file,
"%u,%u,%u,%u,%u\n", &blkinfo[i].
database,
335 &forknum, &blkinfo[i].
blocknum) != 5)
337 (
errmsg(
"autoprewarm block dump file is corrupted at line %d",
364 while (j < num_elements)
366 if (current_db != blkinfo[j].
database)
424 (
errmsg(
"autoprewarm successfully prewarmed %d of %d previously-loaded blocks",
451 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
452 errmsg(
"could not map dynamic shared memory segment")));
513 if (old_blk == NULL ||
576 char transient_dump_file_path[
MAXPGPATH];
589 (
errmsg(
"could not perform block dump because dump file is being used by PID %lu",
593 (
errmsg(
"skipping block dump because it is already being performed by PID %lu",
601 for (num_blocks = 0, i = 0; i <
NBuffers; i++)
636 errmsg(
"could not open file \"%s\": %m",
637 transient_dump_file_path)));
639 ret =
fprintf(file,
"<<%d>>\n", num_blocks);
642 int save_errno = errno;
645 unlink(transient_dump_file_path);
649 errmsg(
"could not write to file \"%s\": %m",
650 transient_dump_file_path)));
653 for (i = 0; i < num_blocks; i++)
657 ret =
fprintf(file,
"%u,%u,%u,%u,%u\n",
665 int save_errno = errno;
668 unlink(transient_dump_file_path);
672 errmsg(
"could not write to file \"%s\": %m",
673 transient_dump_file_path)));
677 pfree(block_info_array);
686 int save_errno = errno;
688 unlink(transient_dump_file_path);
692 errmsg(
"could not close file \"%s\": %m",
693 transient_dump_file_path)));
714 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
715 errmsg(
"autoprewarm is disabled")));
724 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
725 errmsg(
"autoprewarm worker is already running under PID %lu",
726 (
unsigned long) pid)));
813 strcpy(worker.
bgw_name,
"autoprewarm leader");
814 strcpy(worker.
bgw_type,
"autoprewarm leader");
827 (
errcode(ERRCODE_INSUFFICIENT_RESOURCES),
828 errmsg(
"could not register background process"),
829 errhint(
"You may need to increase max_worker_processes.")));
834 (
errcode(ERRCODE_INSUFFICIENT_RESOURCES),
835 errmsg(
"could not start background process"),
836 errhint(
"More details may be available in the server log.")));
855 strcpy(worker.
bgw_name,
"autoprewarm worker");
856 strcpy(worker.
bgw_type,
"autoprewarm worker");
863 (
errcode(ERRCODE_INSUFFICIENT_RESOURCES),
864 errmsg(
"registering dynamic bgworker autoprewarm failed"),
865 errhint(
"Consider increasing configuration parameter \"max_worker_processes\".")));
875 #define cmp_member_elem(fld) \ 877 if (a->fld < b->fld) \ 879 else if (a->fld > b->fld) \
void DefineCustomIntVariable(const char *name, const char *short_desc, const char *long_desc, int *valueAddr, int bootValue, int minValue, int maxValue, GucContext context, int flags, GucIntCheckHook check_hook, GucIntAssignHook assign_hook, GucShowHook show_hook)
BgwHandleStatus WaitForBackgroundWorkerStartup(BackgroundWorkerHandle *handle, pid_t *pidp)
void RegisterBackgroundWorker(BackgroundWorker *worker)
void RequestAddinShmemSpace(Size size)
int errhint(const char *fmt,...)
int LWLockNewTrancheId(void)
void autoprewarm_main(Datum main_arg)
void ProcessConfigFile(GucContext context)
bool process_shared_preload_libraries_in_progress
TimestampTz GetCurrentTimestamp(void)
#define PG_RETURN_INT64(x)
struct SMgrRelationData * rd_smgr
void SignalHandlerForConfigReload(SIGNAL_ARGS)
static int autoprewarm_interval
void CommitTransactionCommand(void)
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
dsm_segment * dsm_attach(dsm_handle h)
Oid RelidByRelfilenode(Oid reltablespace, Oid relfilenode)
#define cmp_member_elem(fld)
dsm_handle dsm_segment_handle(dsm_segment *seg)
int errcode(int sqlerrcode)
#define MemSet(start, val, len)
void ReleaseBuffer(Buffer buffer)
bool smgrexists(SMgrRelation reln, ForkNumber forknum)
#define BGWORKER_SHMEM_ACCESS
#define OidIsValid(objectId)
static int apw_dump_now(bool is_bgworker, bool dump_unlogged)
char bgw_function_name[BGW_MAXLEN]
Relation try_relation_open(Oid relationId, LOCKMODE lockmode)
void ResetLatch(Latch *latch)
int WaitLatch(Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
void LWLockRegisterTranche(int tranche_id, const char *tranche_name)
void LWLockRelease(LWLock *lock)
#define RelationOpenSmgr(relation)
#define DSM_HANDLE_INVALID
#define PG_ENSURE_ERROR_CLEANUP(cleanup_function, arg)
void pfree(void *pointer)
BgwHandleStatus WaitForBackgroundWorkerShutdown(BackgroundWorkerHandle *handle)
struct AutoPrewarmSharedState AutoPrewarmSharedState
static AutoPrewarmSharedState * apw_state
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
void EmitWarningsOnPlaceholders(const char *className)
static void apw_start_database_worker(void)
static void apw_start_leader_worker(void)
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
int errcode_for_file_access(void)
#define GetBufferDescriptor(id)
dsm_handle block_info_handle
FILE * AllocateFile(const char *name, const char *mode)
#define BGW_NEVER_RESTART
static bool apw_init_shmem(void)
int durable_rename(const char *oldfile, const char *newfile, int elevel)
volatile sig_atomic_t ShutdownRequestPending
PG_FUNCTION_INFO_V1(autoprewarm_start_worker)
void SignalHandlerForShutdownRequest(SIGNAL_ARGS)
void LWLockInitialize(LWLock *lock, int tranche_id)
dsm_segment * dsm_create(Size size, int flags)
#define PG_WAIT_EXTENSION
struct BlockInfoRecord BlockInfoRecord
bool have_free_buffer(void)
void BackgroundWorkerInitializeConnectionByOid(Oid dboid, Oid useroid, uint32 flags)
#define TimestampTzPlusMilliseconds(tz, ms)
#define ereport(elevel,...)
pqsigfunc pqsignal(int signum, pqsigfunc handler)
BlockNumber RelationGetNumberOfBlocksInFork(Relation relation, ForkNumber forkNum)
int errmsg_internal(const char *fmt,...)
uint32 LockBufHdr(BufferDesc *desc)
void * dsm_segment_address(dsm_segment *seg)
void relation_close(Relation relation, LOCKMODE lockmode)
char bgw_name[BGW_MAXLEN]
#define Assert(condition)
#define BGWORKER_BACKEND_DATABASE_CONNECTION
void StartTransactionCommand(void)
BgWorkerStartTime bgw_start_time
void pg_qsort(void *base, size_t nel, size_t elsize, int(*cmp)(const void *, const void *))
bool RegisterDynamicBackgroundWorker(BackgroundWorker *worker, BackgroundWorkerHandle **handle)
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
#define BufferIsValid(bufnum)
#define PG_END_ENSURE_ERROR_CLEANUP(cleanup_function, arg)
char bgw_type[BGW_MAXLEN]
void dsm_detach(dsm_segment *seg)
int errmsg(const char *fmt,...)
#define UnlockBufHdr(desc, s)
Datum autoprewarm_dump_now(PG_FUNCTION_ARGS)
volatile sig_atomic_t ConfigReloadPending
static void apw_detach_shmem(int code, Datum arg)
static void apw_load_buffers(void)
#define CHECK_FOR_INTERRUPTS()
Datum autoprewarm_start_worker(PG_FUNCTION_ARGS)
void procsignal_sigusr1_handler(SIGNAL_ARGS)
static void static void status(const char *fmt,...) pg_attribute_printf(1
char bgw_library_name[BGW_MAXLEN]
void DefineCustomBoolVariable(const char *name, const char *short_desc, const char *long_desc, bool *valueAddr, bool bootValue, GucContext context, int flags, GucBoolCheckHook check_hook, GucBoolAssignHook assign_hook, GucShowHook show_hook)
static int apw_compare_blockinfo(const void *p, const void *q)
void autoprewarm_database_main(Datum main_arg)
long TimestampDifferenceMilliseconds(TimestampTz start_time, TimestampTz stop_time)
#define WL_EXIT_ON_PM_DEATH
void BackgroundWorkerUnblockSignals(void)