13
13
*
14
14
* Copyright (c) 2001-2005, PostgreSQL Global Development Group
15
15
*
16
- * $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.93 2005/05/09 11:31:33 neilc Exp $
16
+ * $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.94 2005/05/11 01:41:40 neilc Exp $
17
17
* ----------
18
18
*/
19
19
#include "postgres.h"
@@ -162,6 +162,7 @@ static void pgstat_exit(SIGNAL_ARGS);
162
162
static void pgstat_die (SIGNAL_ARGS );
163
163
static void pgstat_beshutdown_hook (int code , Datum arg );
164
164
165
+ static PgStat_StatDBEntry * pgstat_get_db_entry (int databaseid );
165
166
static int pgstat_add_backend (PgStat_MsgHdr * msg );
166
167
static void pgstat_sub_backend (int procpid );
167
168
static void pgstat_drop_database (Oid databaseid );
@@ -653,6 +654,9 @@ pgstat_bestart(void)
653
654
return ;
654
655
655
656
pgstat_setheader (& msg .m_hdr , PGSTAT_MTYPE_BESTART );
657
+ msg .m_databaseid = MyDatabaseId ;
658
+ msg .m_userid = GetSessionUserId ();
659
+ memcpy (& msg .m_clientaddr , & MyProcPort -> raddr , sizeof (msg .m_clientaddr ));
656
660
pgstat_send (& msg , sizeof (msg ));
657
661
658
662
/*
@@ -748,6 +752,7 @@ pgstat_report_tabstat(void)
748
752
pgStatXactRollback = 0 ;
749
753
750
754
pgstat_setheader (& tsmsg -> m_hdr , PGSTAT_MTYPE_TABSTAT );
755
+ tsmsg -> m_databaseid = MyDatabaseId ;
751
756
pgstat_send (tsmsg , len );
752
757
}
753
758
@@ -825,7 +830,7 @@ pgstat_vacuum_tabstat(void)
825
830
}
826
831
827
832
/*
828
- * Add this tables Oid to the message
833
+ * Add this table's Oid to the message
829
834
*/
830
835
msg .m_tableid [msg .m_nentries ++ ] = tabentry -> tableid ;
831
836
nobjects ++ ;
@@ -854,6 +859,7 @@ pgstat_vacuum_tabstat(void)
854
859
+ msg .m_nentries * sizeof (Oid );
855
860
856
861
pgstat_setheader (& msg .m_hdr , PGSTAT_MTYPE_TABPURGE );
862
+ msg .m_databaseid = MyDatabaseId ;
857
863
pgstat_send (& msg , len );
858
864
}
859
865
@@ -933,9 +939,8 @@ pgstat_drop_database(Oid databaseid)
933
939
if (pgStatSock < 0 )
934
940
return ;
935
941
936
- msg .m_databaseid = databaseid ;
937
-
938
942
pgstat_setheader (& msg .m_hdr , PGSTAT_MTYPE_DROPDB );
943
+ msg .m_databaseid = databaseid ;
939
944
pgstat_send (& msg , sizeof (msg ));
940
945
}
941
946
@@ -960,6 +965,7 @@ pgstat_reset_counters(void)
960
965
errmsg ("must be superuser to reset statistics counters" )));
961
966
962
967
pgstat_setheader (& msg .m_hdr , PGSTAT_MTYPE_RESETCOUNTER );
968
+ msg .m_databaseid = MyDatabaseId ;
963
969
pgstat_send (& msg , sizeof (msg ));
964
970
}
965
971
@@ -1176,24 +1182,18 @@ pgstat_count_xact_rollback(void)
1176
1182
PgStat_StatDBEntry *
1177
1183
pgstat_fetch_stat_dbentry (Oid dbid )
1178
1184
{
1179
- PgStat_StatDBEntry * dbentry ;
1180
-
1181
1185
/*
1182
1186
* If not done for this transaction, read the statistics collector
1183
1187
* stats file into some hash tables.
1184
1188
*/
1185
1189
backend_read_statsfile ();
1186
1190
1187
1191
/*
1188
- * Lookup the requested database
1192
+ * Lookup the requested database; return NULL if not found
1189
1193
*/
1190
- dbentry = (PgStat_StatDBEntry * ) hash_search (pgStatDBHash ,
1191
- (void * ) & dbid ,
1192
- HASH_FIND , NULL );
1193
- if (dbentry == NULL )
1194
- return NULL ;
1195
-
1196
- return dbentry ;
1194
+ return (PgStat_StatDBEntry * ) hash_search (pgStatDBHash ,
1195
+ (void * ) & dbid ,
1196
+ HASH_FIND , NULL );
1197
1197
}
1198
1198
1199
1199
@@ -1298,9 +1298,6 @@ pgstat_setheader(PgStat_MsgHdr *hdr, int mtype)
1298
1298
hdr -> m_type = mtype ;
1299
1299
hdr -> m_backendid = MyBackendId ;
1300
1300
hdr -> m_procpid = MyProcPid ;
1301
- hdr -> m_databaseid = MyDatabaseId ;
1302
- hdr -> m_userid = GetSessionUserId ();
1303
- memcpy (& hdr -> m_clientaddr , & MyProcPort -> raddr , sizeof (hdr -> m_clientaddr ));
1304
1301
}
1305
1302
1306
1303
@@ -1976,10 +1973,8 @@ pgstat_die(SIGNAL_ARGS)
1976
1973
static int
1977
1974
pgstat_add_backend (PgStat_MsgHdr * msg )
1978
1975
{
1979
- PgStat_StatDBEntry * dbentry ;
1980
1976
PgStat_StatBeEntry * beentry ;
1981
1977
PgStat_StatBeDead * deadbe ;
1982
- bool found ;
1983
1978
1984
1979
/*
1985
1980
* Check that the backend ID is valid
@@ -1995,19 +1990,19 @@ pgstat_add_backend(PgStat_MsgHdr *msg)
1995
1990
* Get the slot for this backendid.
1996
1991
*/
1997
1992
beentry = & pgStatBeTable [msg -> m_backendid - 1 ];
1998
- if ( beentry -> databaseid != InvalidOid )
1999
- {
2000
- /*
2001
- * If the slot contains the PID of this backend, everything is
2002
- * fine and we got nothing to do.
2003
- */
2004
- if ( beentry -> procpid == msg -> m_procpid )
2005
- return 0 ;
2006
- }
1993
+
1994
+ /*
1995
+ * If the slot contains the PID of this backend, everything is
1996
+ * fine and we have nothing to do. Note that all the slots are
1997
+ * zero'd out when the collector is started. We assume that a slot
1998
+ * is "empty" iff procpid == 0.
1999
+ */
2000
+ if ( beentry -> procpid > 0 && beentry -> procpid == msg -> m_procpid )
2001
+ return 0 ;
2007
2002
2008
2003
/*
2009
2004
* Lookup if this backend is known to be dead. This can be caused due
2010
- * to messages arriving in the wrong order - i.e. Postmaster 's BETERM
2005
+ * to messages arriving in the wrong order - e.g. postmaster 's BETERM
2011
2006
* message might have arrived before we received all the backends
2012
2007
* stats messages, or even a new backend with the same backendid was
2013
2008
* faster in sending his BESTART.
@@ -2024,65 +2019,78 @@ pgstat_add_backend(PgStat_MsgHdr *msg)
2024
2019
* Backend isn't known to be dead. If it's slot is currently used, we
2025
2020
* have to kick out the old backend.
2026
2021
*/
2027
- if (beentry -> databaseid != InvalidOid )
2022
+ if (beentry -> procpid > 0 )
2028
2023
pgstat_sub_backend (beentry -> procpid );
2029
2024
2030
- /*
2031
- * Put this new backend into the slot.
2032
- */
2033
- beentry -> databaseid = msg -> m_databaseid ;
2025
+ /* Must be able to distinguish between empty and non-empty slots */
2026
+ Assert ( msg -> m_procpid > 0 );
2027
+
2028
+ /* Put this new backend into the slot */
2034
2029
beentry -> procpid = msg -> m_procpid ;
2035
- beentry -> userid = msg -> m_userid ;
2036
2030
beentry -> start_sec =
2037
2031
GetCurrentAbsoluteTimeUsec (& beentry -> start_usec );
2038
2032
beentry -> activity_start_sec = 0 ;
2039
2033
beentry -> activity_start_usec = 0 ;
2040
- memcpy (& beentry -> clientaddr , & msg -> m_clientaddr , sizeof (beentry -> clientaddr ));
2041
- MemSet (beentry -> activity , 0 , PGSTAT_ACTIVITY_SIZE );
2034
+ beentry -> activity [0 ] = '\0' ;
2042
2035
2043
2036
/*
2044
- * Lookup or create the database entry for this backend's DB.
2037
+ * We can't initialize the rest of the data in this slot until we
2038
+ * see the BESTART message. Therefore, we set the database and
2039
+ * user to sentinel values, to indicate "undefined". There is no
2040
+ * easy way to do this for the client address, so make sure to
2041
+ * check that the database or user are defined before accessing
2042
+ * the client address.
2045
2043
*/
2046
- dbentry = (PgStat_StatDBEntry * ) hash_search (pgStatDBHash ,
2047
- (void * ) & (msg -> m_databaseid ),
2048
- HASH_ENTER , & found );
2049
- if (dbentry == NULL )
2044
+ beentry -> userid = InvalidOid ;
2045
+ beentry -> databaseid = InvalidOid ;
2046
+
2047
+ return 0 ;
2048
+ }
2049
+
2050
+ /*
2051
+ * Lookup the hash table entry for the specified database. If no hash
2052
+ * table entry exists, initialize it.
2053
+ */
2054
+ static PgStat_StatDBEntry *
2055
+ pgstat_get_db_entry (int databaseid )
2056
+ {
2057
+ PgStat_StatDBEntry * result ;
2058
+ bool found ;
2059
+
2060
+ /* Lookup or create the hash table entry for this database */
2061
+ result = (PgStat_StatDBEntry * ) hash_search (pgStatDBHash ,
2062
+ & databaseid ,
2063
+ HASH_ENTER , & found );
2064
+ if (result == NULL )
2050
2065
ereport (ERROR ,
2051
2066
(errcode (ERRCODE_OUT_OF_MEMORY ),
2052
- errmsg ("out of memory in statistics collector --- abort" )));
2067
+ errmsg ("out of memory in statistics collector --- abort" )));
2053
2068
2054
- /*
2055
- * If not found, initialize the new one.
2056
- */
2069
+ /* If not found, initialize the new one. */
2057
2070
if (!found )
2058
2071
{
2059
2072
HASHCTL hash_ctl ;
2060
2073
2061
- dbentry -> tables = NULL ;
2062
- dbentry -> n_xact_commit = 0 ;
2063
- dbentry -> n_xact_rollback = 0 ;
2064
- dbentry -> n_blocks_fetched = 0 ;
2065
- dbentry -> n_blocks_hit = 0 ;
2066
- dbentry -> n_connects = 0 ;
2067
- dbentry -> destroy = 0 ;
2074
+ result -> tables = NULL ;
2075
+ result -> n_xact_commit = 0 ;
2076
+ result -> n_xact_rollback = 0 ;
2077
+ result -> n_blocks_fetched = 0 ;
2078
+ result -> n_blocks_hit = 0 ;
2079
+ result -> destroy = 0 ;
2068
2080
2069
2081
memset (& hash_ctl , 0 , sizeof (hash_ctl ));
2070
2082
hash_ctl .keysize = sizeof (Oid );
2071
2083
hash_ctl .entrysize = sizeof (PgStat_StatTabEntry );
2072
2084
hash_ctl .hash = oid_hash ;
2073
- dbentry -> tables = hash_create ("Per-database table" ,
2085
+ result -> tables = hash_create ("Per-database table" ,
2074
2086
PGSTAT_TAB_HASH_SIZE ,
2075
2087
& hash_ctl ,
2076
2088
HASH_ELEM | HASH_FUNCTION );
2077
2089
}
2078
2090
2079
- /* Count the number of connects to the database */
2080
- dbentry -> n_connects ++ ;
2081
-
2082
- return 0 ;
2091
+ return result ;
2083
2092
}
2084
2093
2085
-
2086
2094
/* ----------
2087
2095
* pgstat_sub_backend() -
2088
2096
*
@@ -2102,8 +2110,7 @@ pgstat_sub_backend(int procpid)
2102
2110
*/
2103
2111
for (i = 0 ; i < MaxBackends ; i ++ )
2104
2112
{
2105
- if (pgStatBeTable [i ].databaseid != InvalidOid &&
2106
- pgStatBeTable [i ].procpid == procpid )
2113
+ if (pgStatBeTable [i ].procpid == procpid )
2107
2114
{
2108
2115
/*
2109
2116
* That's him. Add an entry to the known to be dead backends.
@@ -2133,7 +2140,7 @@ pgstat_sub_backend(int procpid)
2133
2140
/*
2134
2141
* Declare the backend slot empty.
2135
2142
*/
2136
- pgStatBeTable [i ].databaseid = InvalidOid ;
2143
+ pgStatBeTable [i ].procpid = 0 ;
2137
2144
return ;
2138
2145
}
2139
2146
}
@@ -2263,7 +2270,7 @@ pgstat_write_statsfile(void)
2263
2270
2264
2271
for (i = 0 ; i < MaxBackends ; i ++ )
2265
2272
{
2266
- if (pgStatBeTable [i ].databaseid != InvalidOid )
2273
+ if (pgStatBeTable [i ].procpid > 0 )
2267
2274
{
2268
2275
fputc ('B' , fpout );
2269
2276
fwrite (& pgStatBeTable [i ], sizeof (PgStat_StatBeEntry ), 1 , fpout );
@@ -2624,7 +2631,20 @@ backend_read_statsfile(void)
2624
2631
static void
2625
2632
pgstat_recv_bestart (PgStat_MsgBestart * msg , int len )
2626
2633
{
2627
- pgstat_add_backend (& msg -> m_hdr );
2634
+ PgStat_StatBeEntry * entry ;
2635
+
2636
+ /*
2637
+ * If the backend is known dead, we ignore the message -- we don't
2638
+ * want to update the backend entry's state since this BESTART
2639
+ * message refers to an old, dead backend
2640
+ */
2641
+ if (pgstat_add_backend (& msg -> m_hdr ) != 0 )
2642
+ return ;
2643
+
2644
+ entry = & (pgStatBeTable [msg -> m_hdr .m_backendid - 1 ]);
2645
+ entry -> userid = msg -> m_userid ;
2646
+ memcpy (& entry -> clientaddr , & msg -> m_clientaddr , sizeof (entry -> clientaddr ));
2647
+ entry -> databaseid = msg -> m_databaseid ;
2628
2648
}
2629
2649
2630
2650
@@ -2690,14 +2710,7 @@ pgstat_recv_tabstat(PgStat_MsgTabstat *msg, int len)
2690
2710
if (pgstat_add_backend (& msg -> m_hdr ) < 0 )
2691
2711
return ;
2692
2712
2693
- /*
2694
- * Lookup the database in the hashtable.
2695
- */
2696
- dbentry = (PgStat_StatDBEntry * ) hash_search (pgStatDBHash ,
2697
- (void * ) & (msg -> m_hdr .m_databaseid ),
2698
- HASH_FIND , NULL );
2699
- if (!dbentry )
2700
- return ;
2713
+ dbentry = pgstat_get_db_entry (msg -> m_databaseid );
2701
2714
2702
2715
/*
2703
2716
* If the database is marked for destroy, this is a delayed UDP packet
@@ -2782,14 +2795,7 @@ pgstat_recv_tabpurge(PgStat_MsgTabpurge *msg, int len)
2782
2795
if (pgstat_add_backend (& msg -> m_hdr ) < 0 )
2783
2796
return ;
2784
2797
2785
- /*
2786
- * Lookup the database in the hashtable.
2787
- */
2788
- dbentry = (PgStat_StatDBEntry * ) hash_search (pgStatDBHash ,
2789
- (void * ) & (msg -> m_hdr .m_databaseid ),
2790
- HASH_FIND , NULL );
2791
- if (!dbentry )
2792
- return ;
2798
+ dbentry = pgstat_get_db_entry (msg -> m_databaseid );
2793
2799
2794
2800
/*
2795
2801
* If the database is marked for destroy, this is a delayed UDP packet
@@ -2832,11 +2838,7 @@ pgstat_recv_dropdb(PgStat_MsgDropdb *msg, int len)
2832
2838
/*
2833
2839
* Lookup the database in the hashtable.
2834
2840
*/
2835
- dbentry = (PgStat_StatDBEntry * ) hash_search (pgStatDBHash ,
2836
- (void * ) & (msg -> m_databaseid ),
2837
- HASH_FIND , NULL );
2838
- if (!dbentry )
2839
- return ;
2841
+ dbentry = pgstat_get_db_entry (msg -> m_databaseid );
2840
2842
2841
2843
/*
2842
2844
* Mark the database for destruction.
@@ -2846,9 +2848,9 @@ pgstat_recv_dropdb(PgStat_MsgDropdb *msg, int len)
2846
2848
2847
2849
2848
2850
/* ----------
2849
- * pgstat_recv_dropdb () -
2851
+ * pgstat_recv_resetcounter () -
2850
2852
*
2851
- * Arrange for dead database removal
2853
+ * Reset the statistics for the specified database.
2852
2854
* ----------
2853
2855
*/
2854
2856
static void
@@ -2866,15 +2868,11 @@ pgstat_recv_resetcounter(PgStat_MsgResetcounter *msg, int len)
2866
2868
/*
2867
2869
* Lookup the database in the hashtable.
2868
2870
*/
2869
- dbentry = (PgStat_StatDBEntry * ) hash_search (pgStatDBHash ,
2870
- (void * ) & (msg -> m_hdr .m_databaseid ),
2871
- HASH_FIND , NULL );
2872
- if (!dbentry )
2873
- return ;
2871
+ dbentry = pgstat_get_db_entry (msg -> m_databaseid );
2874
2872
2875
2873
/*
2876
- * We simply throw away all the databases table entries by recreating
2877
- * a new hash table for them.
2874
+ * We simply throw away all the database's table entries by
2875
+ * recreating a new hash table for them.
2878
2876
*/
2879
2877
if (dbentry -> tables != NULL )
2880
2878
hash_destroy (dbentry -> tables );
@@ -2884,7 +2882,6 @@ pgstat_recv_resetcounter(PgStat_MsgResetcounter *msg, int len)
2884
2882
dbentry -> n_xact_rollback = 0 ;
2885
2883
dbentry -> n_blocks_fetched = 0 ;
2886
2884
dbentry -> n_blocks_hit = 0 ;
2887
- dbentry -> n_connects = 0 ;
2888
2885
dbentry -> destroy = 0 ;
2889
2886
2890
2887
memset (& hash_ctl , 0 , sizeof (hash_ctl ));
0 commit comments