pgstat's on-proc-exit hook has to execute after the last transaction commit
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 27 May 2007 05:37:50 +0000 (05:37 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 27 May 2007 05:37:50 +0000 (05:37 +0000)
or abort within a backend; rearrange InitPostgres processing to make it so.
Revealed by just-added Asserts along with ECPG regression tests (hm, I wonder
why the core regression tests didn't expose it?).  This possibly is another
reason for missing stats updates ...

src/backend/postmaster/pgstat.c
src/backend/utils/init/postinit.c
src/include/pgstat.h

index 4ea491b09af254d4d7e8912a860fe0e4b71d66aa..b5454111babc9a47be523cde311fbef0104eb8ae 100644 (file)
@@ -1771,28 +1771,45 @@ CreateSharedBackendStatus(void)
 }
 
 
+/* ----------
+ * pgstat_initialize() -
+ *
+ *     Initialize pgstats state, and set up our on-proc-exit hook.
+ *     Called from InitPostgres.  MyBackendId must be set,
+ *     but we must not have started any transaction yet (since the
+ *     exit hook must run after the last transaction exit).
+ * ----------
+ */
+void
+pgstat_initialize(void)
+{
+       /* Initialize MyBEEntry */
+       Assert(MyBackendId >= 1 && MyBackendId <= MaxBackends);
+       MyBEEntry = &BackendStatusArray[MyBackendId - 1];
+
+       /* Set up a process-exit hook to clean up */
+       on_shmem_exit(pgstat_beshutdown_hook, 0);
+}
+
 /* ----------
  * pgstat_bestart() -
  *
- *     Initialize this backend's entry in the PgBackendStatus array,
- *     and set up an on-proc-exit hook that will clear it again.
- *     Called from InitPostgres.  MyBackendId and MyDatabaseId must be set.
+ *     Initialize this backend's entry in the PgBackendStatus array.
+ *     Called from InitPostgres.  MyDatabaseId and session userid must be set
+ *     (hence, this cannot be combined with pgstat_initialize).
  * ----------
  */
 void
 pgstat_bestart(void)
 {
-       volatile PgBackendStatus *beentry;
        TimestampTz proc_start_timestamp;
        Oid                     userid;
        SockAddr        clientaddr;
-
-       Assert(MyBackendId >= 1 && MyBackendId <= MaxBackends);
-       MyBEEntry = &BackendStatusArray[MyBackendId - 1];
+       volatile PgBackendStatus *beentry;
 
        /*
-        * To minimize the time spent modifying the entry, fetch all the needed
-        * data first.
+        * To minimize the time spent modifying the PgBackendStatus entry,
+        * fetch all the needed data first.
         *
         * If we have a MyProcPort, use its session start time (for consistency,
         * and to save a kernel call).
@@ -1839,11 +1856,6 @@ pgstat_bestart(void)
 
        beentry->st_changecount++;
        Assert((beentry->st_changecount & 1) == 0);
-
-       /*
-        * Set up a process-exit hook to clean up.
-        */
-       on_shmem_exit(pgstat_beshutdown_hook, 0);
 }
 
 /*
index dc40ca90da3ef9e5bca78e43ce2e143a6a9bbf7e..e8fd522ea9859b87cb4b48f594ed310086740a58 100644 (file)
@@ -435,6 +435,10 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
        /* Initialize portal manager */
        EnablePortalManager();
 
+       /* Initialize stats collection --- must happen before first xact */
+       if (!bootstrap)
+               pgstat_initialize();
+
        /*
         * Set up process-exit callback to do pre-shutdown cleanup.  This has to
         * be after we've initialized all the low-level modules like the buffer
@@ -587,7 +591,7 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
        /* initialize client encoding */
        InitializeClientEncoding();
 
-       /* initialize statistics collection for this backend */
+       /* report this backend in the PgBackendStatus array */
        if (!bootstrap)
                pgstat_bestart();
 
index 147e71bd1c6e65f23045b9ea23bec25dea650e06..74021f32cb11f87d5c5fc0b3497b77afe709f4c7 100644 (file)
@@ -501,7 +501,9 @@ extern void pgstat_report_analyze(Oid tableoid, bool shared,
                                          PgStat_Counter livetuples,
                                          PgStat_Counter deadtuples);
 
+extern void pgstat_initialize(void);
 extern void pgstat_bestart(void);
+
 extern void pgstat_report_activity(const char *what);
 extern void pgstat_report_txn_timestamp(TimestampTz tstamp);
 extern void pgstat_report_waiting(bool waiting);