13
13
*
14
14
* Copyright (c) 2001-2007, PostgreSQL Global Development Group
15
15
*
16
- * $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.144 2007/01/26 20:06:52 tgl Exp $
16
+ * $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.145 2007/02/07 23:11:29 tgl Exp $
17
17
* ----------
18
18
*/
19
19
#include "postgres.h"
@@ -130,9 +130,8 @@ static TabStatArray SharedTabStat = {0, 0, NULL};
130
130
static int pgStatXactCommit = 0 ;
131
131
static int pgStatXactRollback = 0 ;
132
132
133
- static TransactionId pgStatDBHashXact = InvalidTransactionId ;
133
+ static MemoryContext pgStatLocalContext = NULL ;
134
134
static HTAB * pgStatDBHash = NULL ;
135
- static TransactionId pgStatLocalStatusXact = InvalidTransactionId ;
136
135
static PgBackendStatus * localBackendStatusTable = NULL ;
137
136
static int localNumBackends = 0 ;
138
137
@@ -156,11 +155,13 @@ static void pgstat_beshutdown_hook(int code, Datum arg);
156
155
static PgStat_StatDBEntry * pgstat_get_db_entry (Oid databaseid , bool create );
157
156
static void pgstat_drop_database (Oid databaseid );
158
157
static void pgstat_write_statsfile (void );
159
- static void pgstat_read_statsfile ( HTAB * * dbhash , Oid onlydb );
158
+ static HTAB * pgstat_read_statsfile ( Oid onlydb );
160
159
static void backend_read_statsfile (void );
161
160
static void pgstat_read_current_status (void );
162
161
static HTAB * pgstat_collect_oids (Oid catalogid );
163
162
163
+ static void pgstat_setup_memcxt (void );
164
+
164
165
static void pgstat_setheader (PgStat_MsgHdr * hdr , StatMsgType mtype );
165
166
static void pgstat_send (void * msg , int len );
166
167
@@ -1535,22 +1536,24 @@ pgstat_report_waiting(bool waiting)
1535
1536
static void
1536
1537
pgstat_read_current_status (void )
1537
1538
{
1538
- TransactionId topXid = GetTopTransactionId ();
1539
1539
volatile PgBackendStatus * beentry ;
1540
+ PgBackendStatus * localtable ;
1540
1541
PgBackendStatus * localentry ;
1541
1542
int i ;
1542
1543
1543
1544
Assert (!pgStatRunningInCollector );
1544
- if (TransactionIdEquals ( pgStatLocalStatusXact , topXid ) )
1545
+ if (localBackendStatusTable )
1545
1546
return ; /* already done */
1546
1547
1547
- localBackendStatusTable = (PgBackendStatus * )
1548
- MemoryContextAlloc (TopTransactionContext ,
1548
+ pgstat_setup_memcxt ();
1549
+
1550
+ localtable = (PgBackendStatus * )
1551
+ MemoryContextAlloc (pgStatLocalContext ,
1549
1552
sizeof (PgBackendStatus ) * MaxBackends );
1550
1553
localNumBackends = 0 ;
1551
1554
1552
1555
beentry = BackendStatusArray ;
1553
- localentry = localBackendStatusTable ;
1556
+ localentry = localtable ;
1554
1557
for (i = 1 ; i <= MaxBackends ; i ++ )
1555
1558
{
1556
1559
/*
@@ -1587,7 +1590,8 @@ pgstat_read_current_status(void)
1587
1590
}
1588
1591
}
1589
1592
1590
- pgStatLocalStatusXact = topXid ;
1593
+ /* Set the pointer only after completion of a valid table */
1594
+ localBackendStatusTable = localtable ;
1591
1595
}
1592
1596
1593
1597
@@ -1720,7 +1724,7 @@ PgstatCollectorMain(int argc, char *argv[])
1720
1724
* zero.
1721
1725
*/
1722
1726
pgStatRunningInCollector = true;
1723
- pgstat_read_statsfile ( & pgStatDBHash , InvalidOid );
1727
+ pgStatDBHash = pgstat_read_statsfile ( InvalidOid );
1724
1728
1725
1729
/*
1726
1730
* Setup the descriptor set for select(2). Since only one bit in the set
@@ -2090,38 +2094,24 @@ pgstat_write_statsfile(void)
2090
2094
* databases' hash table (whose entries point to the tables' hash tables).
2091
2095
* ----------
2092
2096
*/
2093
- static void
2094
- pgstat_read_statsfile (HTAB * * dbhash , Oid onlydb )
2097
+ static HTAB *
2098
+ pgstat_read_statsfile (Oid onlydb )
2095
2099
{
2096
2100
PgStat_StatDBEntry * dbentry ;
2097
2101
PgStat_StatDBEntry dbbuf ;
2098
2102
PgStat_StatTabEntry * tabentry ;
2099
2103
PgStat_StatTabEntry tabbuf ;
2100
2104
HASHCTL hash_ctl ;
2105
+ HTAB * dbhash ;
2101
2106
HTAB * tabhash = NULL ;
2102
2107
FILE * fpin ;
2103
2108
int32 format_id ;
2104
2109
bool found ;
2105
- MemoryContext use_mcxt ;
2106
- int mcxt_flags ;
2107
2110
2108
2111
/*
2109
- * If running in the collector or the autovacuum process, we use the
2110
- * DynaHashCxt memory context. If running in a backend, we use the
2111
- * TopTransactionContext instead, so the caller must only know the last
2112
- * XactId when this call happened to know if his tables are still valid or
2113
- * already gone!
2112
+ * The tables will live in pgStatLocalContext.
2114
2113
*/
2115
- if (pgStatRunningInCollector || IsAutoVacuumProcess ())
2116
- {
2117
- use_mcxt = NULL ;
2118
- mcxt_flags = 0 ;
2119
- }
2120
- else
2121
- {
2122
- use_mcxt = TopTransactionContext ;
2123
- mcxt_flags = HASH_CONTEXT ;
2124
- }
2114
+ pgstat_setup_memcxt ();
2125
2115
2126
2116
/*
2127
2117
* Create the DB hashtable
@@ -2130,17 +2120,17 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb)
2130
2120
hash_ctl .keysize = sizeof (Oid );
2131
2121
hash_ctl .entrysize = sizeof (PgStat_StatDBEntry );
2132
2122
hash_ctl .hash = oid_hash ;
2133
- hash_ctl .hcxt = use_mcxt ;
2134
- * dbhash = hash_create ("Databases hash" , PGSTAT_DB_HASH_SIZE , & hash_ctl ,
2135
- HASH_ELEM | HASH_FUNCTION | mcxt_flags );
2123
+ hash_ctl .hcxt = pgStatLocalContext ;
2124
+ dbhash = hash_create ("Databases hash" , PGSTAT_DB_HASH_SIZE , & hash_ctl ,
2125
+ HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT );
2136
2126
2137
2127
/*
2138
2128
* Try to open the status file. If it doesn't exist, the backends simply
2139
2129
* return zero for anything and the collector simply starts from scratch
2140
2130
* with empty counters.
2141
2131
*/
2142
2132
if ((fpin = AllocateFile (PGSTAT_STAT_FILENAME , PG_BINARY_R )) == NULL )
2143
- return ;
2133
+ return dbhash ;
2144
2134
2145
2135
/*
2146
2136
* Verify it's of the expected format.
@@ -2178,7 +2168,7 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb)
2178
2168
/*
2179
2169
* Add to the DB hash
2180
2170
*/
2181
- dbentry = (PgStat_StatDBEntry * ) hash_search (* dbhash ,
2171
+ dbentry = (PgStat_StatDBEntry * ) hash_search (dbhash ,
2182
2172
(void * ) & dbbuf .databaseid ,
2183
2173
HASH_ENTER ,
2184
2174
& found );
@@ -2207,11 +2197,11 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb)
2207
2197
hash_ctl .keysize = sizeof (Oid );
2208
2198
hash_ctl .entrysize = sizeof (PgStat_StatTabEntry );
2209
2199
hash_ctl .hash = oid_hash ;
2210
- hash_ctl .hcxt = use_mcxt ;
2200
+ hash_ctl .hcxt = pgStatLocalContext ;
2211
2201
dbentry -> tables = hash_create ("Per-database table" ,
2212
2202
PGSTAT_TAB_HASH_SIZE ,
2213
2203
& hash_ctl ,
2214
- HASH_ELEM | HASH_FUNCTION | mcxt_flags );
2204
+ HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT );
2215
2205
2216
2206
/*
2217
2207
* Arrange that following 'T's add entries to this database's
@@ -2274,44 +2264,78 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb)
2274
2264
2275
2265
done :
2276
2266
FreeFile (fpin );
2267
+
2268
+ return dbhash ;
2277
2269
}
2278
2270
2279
2271
/*
2280
- * If not done for this transaction, read the statistics collector
2281
- * stats file into some hash tables.
2282
- *
2283
- * Because we store the tables in TopTransactionContext, the result
2284
- * is good for the entire current main transaction.
2285
- *
2286
- * Inside the autovacuum process, the statfile is assumed to be valid
2287
- * "forever", that is one iteration, within one database. This means
2288
- * we only consider the statistics as they were when the autovacuum
2289
- * iteration started.
2272
+ * If not already done, read the statistics collector stats file into
2273
+ * some hash tables. The results will be kept until pgstat_clear_snapshot()
2274
+ * is called (typically, at end of transaction).
2290
2275
*/
2291
2276
static void
2292
2277
backend_read_statsfile (void )
2293
2278
{
2279
+ /* already read it? */
2280
+ if (pgStatDBHash )
2281
+ return ;
2282
+ Assert (!pgStatRunningInCollector );
2283
+
2284
+ /* Autovacuum wants stats about all databases */
2294
2285
if (IsAutoVacuumProcess ())
2295
- {
2296
- /* already read it? */
2297
- if (pgStatDBHash )
2298
- return ;
2299
- Assert (!pgStatRunningInCollector );
2300
- pgstat_read_statsfile (& pgStatDBHash , InvalidOid );
2301
- }
2286
+ pgStatDBHash = pgstat_read_statsfile (InvalidOid );
2302
2287
else
2303
- {
2304
- TransactionId topXid = GetTopTransactionId ();
2288
+ pgStatDBHash = pgstat_read_statsfile ( MyDatabaseId );
2289
+ }
2305
2290
2306
- if (!TransactionIdEquals (pgStatDBHashXact , topXid ))
2307
- {
2308
- Assert (!pgStatRunningInCollector );
2309
- pgstat_read_statsfile (& pgStatDBHash , MyDatabaseId );
2310
- pgStatDBHashXact = topXid ;
2311
- }
2312
- }
2291
+
2292
+ /* ----------
2293
+ * pgstat_setup_memcxt() -
2294
+ *
2295
+ * Create pgStatLocalContext, if not already done.
2296
+ * ----------
2297
+ */
2298
+ static void
2299
+ pgstat_setup_memcxt (void )
2300
+ {
2301
+ if (!pgStatLocalContext )
2302
+ pgStatLocalContext = AllocSetContextCreate (TopMemoryContext ,
2303
+ "Statistics snapshot" ,
2304
+ ALLOCSET_SMALL_MINSIZE ,
2305
+ ALLOCSET_SMALL_INITSIZE ,
2306
+ ALLOCSET_SMALL_MAXSIZE );
2313
2307
}
2314
2308
2309
+
2310
+ /* ----------
2311
+ * pgstat_clear_snapshot() -
2312
+ *
2313
+ * Discard any data collected in the current transaction. Any subsequent
2314
+ * request will cause new snapshots to be read.
2315
+ *
2316
+ * This is also invoked during transaction commit or abort to discard
2317
+ * the no-longer-wanted snapshot.
2318
+ * ----------
2319
+ */
2320
+ void
2321
+ pgstat_clear_snapshot (void )
2322
+ {
2323
+ /* In an autovacuum process we keep the stats forever */
2324
+ if (IsAutoVacuumProcess ())
2325
+ return ;
2326
+
2327
+ /* Release memory, if any was allocated */
2328
+ if (pgStatLocalContext )
2329
+ MemoryContextDelete (pgStatLocalContext );
2330
+
2331
+ /* Reset variables */
2332
+ pgStatLocalContext = NULL ;
2333
+ pgStatDBHash = NULL ;
2334
+ localBackendStatusTable = NULL ;
2335
+ localNumBackends = 0 ;
2336
+ }
2337
+
2338
+
2315
2339
/* ----------
2316
2340
* pgstat_recv_tabstat() -
2317
2341
*
0 commit comments