Skip to content

Commit 944a17b

Browse files
committed
Delay write of pg_stats file to once every five minutes, during
shutdown, or when requested by a backend: It changes so the file is only written once every 5 minutes (changeable of course, I just picked something) instead of once every half second. It's still written when the stats collector shuts down, just as before. And it is now also written on backend request. A backend requests a rewrite by simply sending a special stats message. It operates on the assumption that the backends aren't actually going to read the statistics file very often, compared to how frequent it's written today. Magnus Hagander
1 parent a1e5331 commit 944a17b

File tree

2 files changed

+121
-14
lines changed

2 files changed

+121
-14
lines changed

src/backend/postmaster/pgstat.c

Lines changed: 109 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
*
1414
* Copyright (c) 2001-2006, PostgreSQL Global Development Group
1515
*
16-
* $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.123 2006/04/20 10:51:32 momjian Exp $
16+
* $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.124 2006/04/27 00:06:58 momjian Exp $
1717
* ----------
1818
*/
1919
#include "postgres.h"
@@ -28,6 +28,7 @@
2828
#include <arpa/inet.h>
2929
#include <signal.h>
3030
#include <time.h>
31+
#include <sys/stat.h>
3132

3233
#include "pgstat.h"
3334

@@ -66,12 +67,15 @@
6667
* Timer definitions.
6768
* ----------
6869
*/
69-
#define PGSTAT_STAT_INTERVAL 500 /* How often to write the status file;
70-
* in milliseconds. */
7170

72-
#define PGSTAT_RESTART_INTERVAL 60 /* How often to attempt to restart a
73-
* failed statistics collector; in
74-
* seconds. */
71+
/* How often to write the status file, in milliseconds. */
72+
#define PGSTAT_STAT_INTERVAL (5*60*1000)
73+
74+
/*
75+
* How often to attempt to restart a failed statistics collector; in ms.
76+
* Must be at least PGSTAT_STAT_INTERVAL.
77+
*/
78+
#define PGSTAT_RESTART_INTERVAL (5*60*1000)
7579

7680
/* ----------
7781
* Amount of space reserved in pgstat_recvbuffer().
@@ -172,11 +176,12 @@ static void pgstat_drop_database(Oid databaseid);
172176
static void pgstat_write_statsfile(void);
173177
static void pgstat_read_statsfile(HTAB **dbhash, Oid onlydb,
174178
PgStat_StatBeEntry **betab,
175-
int *numbackends);
179+
int *numbackends, bool rewrite);
176180
static void backend_read_statsfile(void);
177181

178182
static void pgstat_setheader(PgStat_MsgHdr *hdr, StatMsgType mtype);
179183
static void pgstat_send(void *msg, int len);
184+
static void pgstat_send_rewrite(void);
180185

181186
static void pgstat_recv_bestart(PgStat_MsgBestart *msg, int len);
182187
static void pgstat_recv_beterm(PgStat_MsgBeterm *msg, int len);
@@ -1449,6 +1454,24 @@ pgstat_send(void *msg, int len)
14491454
#endif
14501455
}
14511456

1457+
/*
1458+
* pgstat_send_rewrite() -
1459+
*
1460+
* Send a command to the collector to rewrite the stats file.
1461+
* ----------
1462+
*/
1463+
static void
1464+
pgstat_send_rewrite(void)
1465+
{
1466+
PgStat_MsgRewrite msg;
1467+
1468+
if (pgStatSock < 0)
1469+
return;
1470+
1471+
pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_REWRITE);
1472+
pgstat_send(&msg, sizeof(msg));
1473+
}
1474+
14521475

14531476
/* ----------
14541477
* PgstatBufferMain() -
@@ -1549,7 +1572,7 @@ PgstatCollectorMain(int argc, char *argv[])
15491572
fd_set rfds;
15501573
int readPipe;
15511574
int len = 0;
1552-
struct itimerval timeout;
1575+
struct itimerval timeout, canceltimeout;
15531576
bool need_timer = false;
15541577

15551578
MyProcPid = getpid(); /* reset MyProcPid */
@@ -1604,12 +1627,15 @@ PgstatCollectorMain(int argc, char *argv[])
16041627
timeout.it_value.tv_sec = PGSTAT_STAT_INTERVAL / 1000;
16051628
timeout.it_value.tv_usec = PGSTAT_STAT_INTERVAL % 1000;
16061629

1630+
/* Values set to zero will cancel the active timer */
1631+
MemSet(&canceltimeout, 0, sizeof(struct itimerval));
1632+
16071633
/*
16081634
* Read in an existing statistics stats file or initialize the stats to
16091635
* zero.
16101636
*/
16111637
pgStatRunningInCollector = true;
1612-
pgstat_read_statsfile(&pgStatDBHash, InvalidOid, NULL, NULL);
1638+
pgstat_read_statsfile(&pgStatDBHash, InvalidOid, NULL, NULL, false);
16131639

16141640
/*
16151641
* Create the known backends table
@@ -1764,6 +1790,12 @@ PgstatCollectorMain(int argc, char *argv[])
17641790
pgstat_recv_analyze((PgStat_MsgAnalyze *) &msg, nread);
17651791
break;
17661792

1793+
case PGSTAT_MTYPE_REWRITE:
1794+
need_statwrite = true;
1795+
/* Disable the timer - it will be restarted on next data update */
1796+
setitimer(ITIMER_REAL, &canceltimeout, NULL);
1797+
break;
1798+
17671799
default:
17681800
break;
17691801
}
@@ -2344,7 +2376,7 @@ comparePids(const void *v1, const void *v2)
23442376
*/
23452377
static void
23462378
pgstat_read_statsfile(HTAB **dbhash, Oid onlydb,
2347-
PgStat_StatBeEntry **betab, int *numbackends)
2379+
PgStat_StatBeEntry **betab, int *numbackends, bool rewrite)
23482380
{
23492381
PgStat_StatDBEntry *dbentry;
23502382
PgStat_StatDBEntry dbbuf;
@@ -2363,6 +2395,71 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb,
23632395
MemoryContext use_mcxt;
23642396
int mcxt_flags;
23652397

2398+
2399+
if (rewrite)
2400+
{
2401+
/*
2402+
* To force a rewrite of the stats file from the collector, send
2403+
* a REWRITE message to the stats collector. Then wait for the file
2404+
* to change. On Unix, we wait for the inode to change (as the file
2405+
* is renamed into place from a different file). Win32 has no concept
2406+
* of inodes, so we wait for the date on the file to change instead.
2407+
* We can do this on win32 because we have high-res timing on the
2408+
* file dates, but we can't on unix, because it has 1sec resolution
2409+
* on the fields in struct stat.
2410+
*/
2411+
int i;
2412+
#ifndef WIN32
2413+
struct stat st1, st2;
2414+
2415+
if (stat(PGSTAT_STAT_FILENAME, &st1))
2416+
{
2417+
/* Assume no file there yet */
2418+
st1.st_ino = 0;
2419+
}
2420+
st2.st_ino = 0;
2421+
#else
2422+
WIN32_FILE_ATTRIBUTE_DATA fd1, fd2;
2423+
2424+
if (!GetFileAttributesEx(PGSTAT_STAT_FILENAME, GetFileExInfoStandard, &fd1))
2425+
{
2426+
fd1.ftLastWriteTime.dwLowDateTime = 0;
2427+
fd1.ftLastWriteTime.dwHighDateTime = 0;
2428+
}
2429+
fd2.ftLastWriteTime.dwLowDateTime = 0;
2430+
fd2.ftLastWriteTime.dwHighDateTime = 0;
2431+
#endif
2432+
2433+
2434+
/* Send rewrite message */
2435+
pgstat_send_rewrite();
2436+
2437+
/* Now wait for the file to change */
2438+
for (i=0; i < 50; i++)
2439+
{
2440+
#ifndef WIN32
2441+
if (!stat(PGSTAT_STAT_FILENAME, &st2))
2442+
{
2443+
if (st2.st_ino != st1.st_ino)
2444+
break;
2445+
}
2446+
#else
2447+
if (GetFileAttributesEx(PGSTAT_STAT_FILENAME, GetFileExInfoStandard, &fd2))
2448+
{
2449+
if (fd1.ftLastWriteTime.dwLowDateTime != fd2.ftLastWriteTime.dwLowDateTime ||
2450+
fd1.ftLastWriteTime.dwHighDateTime != fd2.ftLastWriteTime.dwHighDateTime)
2451+
break;
2452+
}
2453+
#endif
2454+
2455+
pg_usleep(50000);
2456+
}
2457+
if (i >= 50)
2458+
ereport(WARNING,
2459+
(errmsg("pgstat update timeout")));
2460+
/* Fallthrough and read the old file anyway - old data better than no data */
2461+
}
2462+
23662463
/*
23672464
* If running in the collector or the autovacuum process, we use the
23682465
* DynaHashCxt memory context. If running in a backend, we use the
@@ -2681,7 +2778,7 @@ backend_read_statsfile(void)
26812778
return;
26822779
Assert(!pgStatRunningInCollector);
26832780
pgstat_read_statsfile(&pgStatDBHash, InvalidOid,
2684-
&pgStatBeTable, &pgStatNumBackends);
2781+
&pgStatBeTable, &pgStatNumBackends, true);
26852782
}
26862783
else
26872784
{
@@ -2691,7 +2788,7 @@ backend_read_statsfile(void)
26912788
{
26922789
Assert(!pgStatRunningInCollector);
26932790
pgstat_read_statsfile(&pgStatDBHash, MyDatabaseId,
2694-
&pgStatBeTable, &pgStatNumBackends);
2791+
&pgStatBeTable, &pgStatNumBackends, true);
26952792
pgStatDBHashXact = topXid;
26962793
}
26972794
}

src/include/pgstat.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*
66
* Copyright (c) 2001-2006, PostgreSQL Global Development Group
77
*
8-
* $PostgreSQL: pgsql/src/include/pgstat.h,v 1.43 2006/04/06 20:38:00 tgl Exp $
8+
* $PostgreSQL: pgsql/src/include/pgstat.h,v 1.44 2006/04/27 00:06:59 momjian Exp $
99
* ----------
1010
*/
1111
#ifndef PGSTAT_H
@@ -32,7 +32,8 @@ typedef enum StatMsgType
3232
PGSTAT_MTYPE_RESETCOUNTER,
3333
PGSTAT_MTYPE_AUTOVAC_START,
3434
PGSTAT_MTYPE_VACUUM,
35-
PGSTAT_MTYPE_ANALYZE
35+
PGSTAT_MTYPE_ANALYZE,
36+
PGSTAT_MTYPE_REWRITE
3637
} StatMsgType;
3738

3839
/* ----------
@@ -107,6 +108,15 @@ typedef struct PgStat_MsgDummy
107108
char m_dummy[512];
108109
} PgStat_MsgDummy;
109110

111+
/* ----------
112+
* PgStat_MsgRewrite Sent by backends to cause a rewrite of the stats file
113+
* ----------
114+
*/
115+
typedef struct Pgstat_MsgRewrite
116+
{
117+
PgStat_MsgHdr m_hdr;
118+
} PgStat_MsgRewrite;
119+
110120
/* ----------
111121
* PgStat_MsgBestart Sent by the backend on startup
112122
* ----------

0 commit comments

Comments
 (0)