13
13
*
14
14
* Copyright (c) 2001-2006, PostgreSQL Global Development Group
15
15
*
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 $
17
17
* ----------
18
18
*/
19
19
#include "postgres.h"
28
28
#include <arpa/inet.h>
29
29
#include <signal.h>
30
30
#include <time.h>
31
+ #include <sys/stat.h>
31
32
32
33
#include "pgstat.h"
33
34
66
67
* Timer definitions.
67
68
* ----------
68
69
*/
69
- #define PGSTAT_STAT_INTERVAL 500 /* How often to write the status file;
70
- * in milliseconds. */
71
70
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)
75
79
76
80
/* ----------
77
81
* Amount of space reserved in pgstat_recvbuffer().
@@ -172,11 +176,12 @@ static void pgstat_drop_database(Oid databaseid);
172
176
static void pgstat_write_statsfile (void );
173
177
static void pgstat_read_statsfile (HTAB * * dbhash , Oid onlydb ,
174
178
PgStat_StatBeEntry * * betab ,
175
- int * numbackends );
179
+ int * numbackends , bool rewrite );
176
180
static void backend_read_statsfile (void );
177
181
178
182
static void pgstat_setheader (PgStat_MsgHdr * hdr , StatMsgType mtype );
179
183
static void pgstat_send (void * msg , int len );
184
+ static void pgstat_send_rewrite (void );
180
185
181
186
static void pgstat_recv_bestart (PgStat_MsgBestart * msg , int len );
182
187
static void pgstat_recv_beterm (PgStat_MsgBeterm * msg , int len );
@@ -1449,6 +1454,24 @@ pgstat_send(void *msg, int len)
1449
1454
#endif
1450
1455
}
1451
1456
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
+
1452
1475
1453
1476
/* ----------
1454
1477
* PgstatBufferMain() -
@@ -1549,7 +1572,7 @@ PgstatCollectorMain(int argc, char *argv[])
1549
1572
fd_set rfds ;
1550
1573
int readPipe ;
1551
1574
int len = 0 ;
1552
- struct itimerval timeout ;
1575
+ struct itimerval timeout , canceltimeout ;
1553
1576
bool need_timer = false;
1554
1577
1555
1578
MyProcPid = getpid (); /* reset MyProcPid */
@@ -1604,12 +1627,15 @@ PgstatCollectorMain(int argc, char *argv[])
1604
1627
timeout .it_value .tv_sec = PGSTAT_STAT_INTERVAL / 1000 ;
1605
1628
timeout .it_value .tv_usec = PGSTAT_STAT_INTERVAL % 1000 ;
1606
1629
1630
+ /* Values set to zero will cancel the active timer */
1631
+ MemSet (& canceltimeout , 0 , sizeof (struct itimerval ));
1632
+
1607
1633
/*
1608
1634
* Read in an existing statistics stats file or initialize the stats to
1609
1635
* zero.
1610
1636
*/
1611
1637
pgStatRunningInCollector = true;
1612
- pgstat_read_statsfile (& pgStatDBHash , InvalidOid , NULL , NULL );
1638
+ pgstat_read_statsfile (& pgStatDBHash , InvalidOid , NULL , NULL , false );
1613
1639
1614
1640
/*
1615
1641
* Create the known backends table
@@ -1764,6 +1790,12 @@ PgstatCollectorMain(int argc, char *argv[])
1764
1790
pgstat_recv_analyze ((PgStat_MsgAnalyze * ) & msg , nread );
1765
1791
break ;
1766
1792
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
+
1767
1799
default :
1768
1800
break ;
1769
1801
}
@@ -2344,7 +2376,7 @@ comparePids(const void *v1, const void *v2)
2344
2376
*/
2345
2377
static void
2346
2378
pgstat_read_statsfile (HTAB * * dbhash , Oid onlydb ,
2347
- PgStat_StatBeEntry * * betab , int * numbackends )
2379
+ PgStat_StatBeEntry * * betab , int * numbackends , bool rewrite )
2348
2380
{
2349
2381
PgStat_StatDBEntry * dbentry ;
2350
2382
PgStat_StatDBEntry dbbuf ;
@@ -2363,6 +2395,71 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb,
2363
2395
MemoryContext use_mcxt ;
2364
2396
int mcxt_flags ;
2365
2397
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
+
2366
2463
/*
2367
2464
* If running in the collector or the autovacuum process, we use the
2368
2465
* DynaHashCxt memory context. If running in a backend, we use the
@@ -2681,7 +2778,7 @@ backend_read_statsfile(void)
2681
2778
return ;
2682
2779
Assert (!pgStatRunningInCollector );
2683
2780
pgstat_read_statsfile (& pgStatDBHash , InvalidOid ,
2684
- & pgStatBeTable , & pgStatNumBackends );
2781
+ & pgStatBeTable , & pgStatNumBackends , true );
2685
2782
}
2686
2783
else
2687
2784
{
@@ -2691,7 +2788,7 @@ backend_read_statsfile(void)
2691
2788
{
2692
2789
Assert (!pgStatRunningInCollector );
2693
2790
pgstat_read_statsfile (& pgStatDBHash , MyDatabaseId ,
2694
- & pgStatBeTable , & pgStatNumBackends );
2791
+ & pgStatBeTable , & pgStatNumBackends , true );
2695
2792
pgStatDBHashXact = topXid ;
2696
2793
}
2697
2794
}
0 commit comments