diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index 5e603a00b1..aef71fd496 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -13,7 +13,7 @@ * * Copyright (c) 2001-2003, PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/backend/postmaster/pgstat.c,v 1.42 2003/08/04 00:43:21 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/postmaster/pgstat.c,v 1.43 2003/08/12 16:21:18 tgl Exp $ * ---------- */ #include "postgres.h" @@ -156,7 +156,8 @@ pgstat_init(void) /* * Force start of collector daemon if something to collect */ - if (pgstat_collect_querystring || pgstat_collect_tuplelevel || + if (pgstat_collect_querystring || + pgstat_collect_tuplelevel || pgstat_collect_blocklevel) pgstat_collect_startcollector = true; @@ -536,15 +537,16 @@ void pgstat_report_tabstat(void) { int i; - int n; - int len; - if (!pgstat_collect_querystring && !pgstat_collect_tuplelevel && - !pgstat_collect_blocklevel) - return; - - if (pgStatSock < 0) + if (pgStatSock < 0 || + !(pgstat_collect_querystring || + pgstat_collect_tuplelevel || + pgstat_collect_blocklevel)) + { + /* Not reporting stats, so just flush whatever we have */ + pgStatTabstatUsed = 0; return; + } /* * For each message buffer used during the last query set the header @@ -552,18 +554,21 @@ pgstat_report_tabstat(void) */ for (i = 0; i < pgStatTabstatUsed; i++) { - n = pgStatTabstatMessages[i]->m_nentries; + PgStat_MsgTabstat *tsmsg = pgStatTabstatMessages[i]; + int n; + int len; + + n = tsmsg->m_nentries; len = offsetof(PgStat_MsgTabstat, m_entry[0]) + n * sizeof(PgStat_TableEntry); - pgStatTabstatMessages[i]->m_xact_commit = pgStatXactCommit; - pgStatTabstatMessages[i]->m_xact_rollback = pgStatXactRollback; + tsmsg->m_xact_commit = pgStatXactCommit; + tsmsg->m_xact_rollback = pgStatXactRollback; pgStatXactCommit = 0; pgStatXactRollback = 0; - pgstat_setheader(&pgStatTabstatMessages[i]->m_hdr, - PGSTAT_MTYPE_TABSTAT); - pgstat_send(pgStatTabstatMessages[i], len); + pgstat_setheader(&tsmsg->m_hdr, PGSTAT_MTYPE_TABSTAT); + pgstat_send(tsmsg, len); } pgStatTabstatUsed = 0; @@ -802,6 +807,53 @@ pgstat_ping(void) pgstat_send(&msg, sizeof(msg)); } +/* + * Create or enlarge the pgStatTabstatMessages array + */ +static bool +more_tabstat_space(void) +{ + PgStat_MsgTabstat *newMessages; + PgStat_MsgTabstat **msgArray; + int newAlloc = pgStatTabstatAlloc + TABSTAT_QUANTUM; + int i; + + /* Create (another) quantum of message buffers */ + newMessages = (PgStat_MsgTabstat *) + malloc(sizeof(PgStat_MsgTabstat) * TABSTAT_QUANTUM); + if (newMessages == NULL) + { + ereport(LOG, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + return false; + } + + /* Create or enlarge the pointer array */ + if (pgStatTabstatMessages == NULL) + msgArray = (PgStat_MsgTabstat **) + malloc(sizeof(PgStat_MsgTabstat *) * newAlloc); + else + msgArray = (PgStat_MsgTabstat **) + realloc(pgStatTabstatMessages, + sizeof(PgStat_MsgTabstat *) * newAlloc); + if (msgArray == NULL) + { + free(newMessages); + ereport(LOG, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + return false; + } + + MemSet(newMessages, 0, sizeof(PgStat_MsgTabstat) * TABSTAT_QUANTUM); + for (i = 0; i < TABSTAT_QUANTUM; i++) + msgArray[pgStatTabstatAlloc + i] = newMessages++; + pgStatTabstatMessages = msgArray; + pgStatTabstatAlloc = newAlloc; + + return true; +} /* ---------- * pgstat_initstats() - @@ -815,8 +867,9 @@ pgstat_ping(void) void pgstat_initstats(PgStat_Info *stats, Relation rel) { - PgStat_TableEntry *useent; Oid rel_id = rel->rd_id; + PgStat_TableEntry *useent; + PgStat_MsgTabstat *tsmsg; int mb; int i; @@ -828,69 +881,39 @@ pgstat_initstats(PgStat_Info *stats, Relation rel) stats->heap_scan_counted = FALSE; stats->index_scan_counted = FALSE; - if (pgStatSock < 0) + if (pgStatSock < 0 || + !(pgstat_collect_tuplelevel || + pgstat_collect_blocklevel)) { stats->no_stats = TRUE; return; } - /* - * On the first of all calls create some message buffers. - */ - if (pgStatTabstatMessages == NULL) - { - PgStat_MsgTabstat *newMessages; - PgStat_MsgTabstat **msgArray; - - newMessages = (PgStat_MsgTabstat *) - malloc(sizeof(PgStat_MsgTabstat) * TABSTAT_QUANTUM); - if (newMessages == NULL) - { - ereport(LOG, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); - return; - } - msgArray = (PgStat_MsgTabstat **) - malloc(sizeof(PgStat_MsgTabstat *) * TABSTAT_QUANTUM); - if (msgArray == NULL) - { - free(newMessages); - ereport(LOG, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); - return; - } - MemSet(newMessages, 0, sizeof(PgStat_MsgTabstat) * TABSTAT_QUANTUM); - for (i = 0; i < TABSTAT_QUANTUM; i++) - msgArray[i] = newMessages++; - pgStatTabstatMessages = msgArray; - pgStatTabstatAlloc = TABSTAT_QUANTUM; - } - /* * Search the already-used message slots for this relation. */ for (mb = 0; mb < pgStatTabstatUsed; mb++) { - for (i = 0; i < pgStatTabstatMessages[mb]->m_nentries; i++) + tsmsg = pgStatTabstatMessages[mb]; + + for (i = tsmsg->m_nentries; --i >= 0; ) { - if (pgStatTabstatMessages[mb]->m_entry[i].t_id == rel_id) + if (tsmsg->m_entry[i].t_id == rel_id) { - stats->tabentry = (void *) &(pgStatTabstatMessages[mb]->m_entry[i]); + stats->tabentry = (void *) &(tsmsg->m_entry[i]); return; } } - if (pgStatTabstatMessages[mb]->m_nentries >= PGSTAT_NUM_TABENTRIES) + if (tsmsg->m_nentries >= PGSTAT_NUM_TABENTRIES) continue; /* * Not found, but found a message buffer with an empty slot * instead. Fine, let's use this one. */ - i = pgStatTabstatMessages[mb]->m_nentries++; - useent = &pgStatTabstatMessages[mb]->m_entry[i]; + i = tsmsg->m_nentries++; + useent = &tsmsg->m_entry[i]; MemSet(useent, 0, sizeof(PgStat_TableEntry)); useent->t_id = rel_id; stats->tabentry = (void *) useent; @@ -902,43 +925,21 @@ pgstat_initstats(PgStat_Info *stats, Relation rel) */ if (pgStatTabstatUsed >= pgStatTabstatAlloc) { - int newAlloc = pgStatTabstatAlloc + TABSTAT_QUANTUM; - PgStat_MsgTabstat *newMessages; - PgStat_MsgTabstat **msgArray; - - newMessages = (PgStat_MsgTabstat *) - malloc(sizeof(PgStat_MsgTabstat) * TABSTAT_QUANTUM); - if (newMessages == NULL) + if (!more_tabstat_space()) { - ereport(LOG, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); + stats->no_stats = TRUE; return; } - msgArray = (PgStat_MsgTabstat **) - realloc(pgStatTabstatMessages, - sizeof(PgStat_MsgTabstat *) * newAlloc); - if (msgArray == NULL) - { - free(newMessages); - ereport(LOG, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); - return; - } - MemSet(newMessages, 0, sizeof(PgStat_MsgTabstat) * TABSTAT_QUANTUM); - for (i = 0; i < TABSTAT_QUANTUM; i++) - msgArray[pgStatTabstatAlloc + i] = newMessages++; - pgStatTabstatMessages = msgArray; - pgStatTabstatAlloc = newAlloc; + Assert(pgStatTabstatUsed < pgStatTabstatAlloc); } /* * Use the first entry of the next message buffer. */ mb = pgStatTabstatUsed++; - pgStatTabstatMessages[mb]->m_nentries = 1; - useent = &pgStatTabstatMessages[mb]->m_entry[0]; + tsmsg = pgStatTabstatMessages[mb]; + tsmsg->m_nentries = 1; + useent = &tsmsg->m_entry[0]; MemSet(useent, 0, sizeof(PgStat_TableEntry)); useent->t_id = rel_id; stats->tabentry = (void *) useent; @@ -954,8 +955,9 @@ pgstat_initstats(PgStat_Info *stats, Relation rel) void pgstat_count_xact_commit(void) { - if (!pgstat_collect_querystring && !pgstat_collect_tuplelevel && - !pgstat_collect_blocklevel) + if (!(pgstat_collect_querystring || + pgstat_collect_tuplelevel || + pgstat_collect_blocklevel)) return; pgStatXactCommit++; @@ -965,13 +967,15 @@ pgstat_count_xact_commit(void) * message buffer used without slots, causing the next report to tell * new xact-counters. */ - if (pgStatTabstatAlloc > 0) + if (pgStatTabstatAlloc == 0) { - if (pgStatTabstatUsed == 0) - { - pgStatTabstatUsed++; - pgStatTabstatMessages[0]->m_nentries = 0; - } + if (!more_tabstat_space()) + return; + } + if (pgStatTabstatUsed == 0) + { + pgStatTabstatUsed++; + pgStatTabstatMessages[0]->m_nentries = 0; } } @@ -985,8 +989,9 @@ pgstat_count_xact_commit(void) void pgstat_count_xact_rollback(void) { - if (!pgstat_collect_querystring && !pgstat_collect_tuplelevel && - !pgstat_collect_blocklevel) + if (!(pgstat_collect_querystring || + pgstat_collect_tuplelevel || + pgstat_collect_blocklevel)) return; pgStatXactRollback++; @@ -996,13 +1001,15 @@ pgstat_count_xact_rollback(void) * message buffer used without slots, causing the next report to tell * new xact-counters. */ - if (pgStatTabstatAlloc > 0) + if (pgStatTabstatAlloc == 0) { - if (pgStatTabstatUsed == 0) - { - pgStatTabstatUsed++; - pgStatTabstatMessages[0]->m_nentries = 0; - } + if (!more_tabstat_space()) + return; + } + if (pgStatTabstatUsed == 0) + { + pgStatTabstatUsed++; + pgStatTabstatMessages[0]->m_nentries = 0; } }