diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index d98f47f9b7..e9e7ae3691 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.15 2006/03/07 17:32:22 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.16 2006/04/06 20:38:00 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -384,19 +384,7 @@ AutoVacMain(int argc, char *argv[]) continue; /* - * Don't try to access a database that was dropped. This could only - * happen if we read the pg_database flat file right before it was - * modified, after the database was dropped from the pg_database - * table. (This is of course a not-very-bulletproof test, but it's - * cheap to make. If we do mistakenly choose a recently dropped - * database, InitPostgres will fail and we'll drop out until the next - * autovac run.) - */ - if (tmp->entry->destroy != 0) - continue; - - /* - * Else remember the db with oldest autovac time. + * Remember the db with oldest autovac time. */ if (db == NULL || tmp->entry->last_autovac_time < db->entry->last_autovac_time) @@ -417,6 +405,9 @@ AutoVacMain(int argc, char *argv[]) /* * Connect to the selected database + * + * Note: if we have selected a just-deleted database (due to using + * stale stats info), we'll fail and exit here. */ InitPostgres(db->name, NULL); SetProcessingMode(NormalProcessing); diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index d8c0e5e20f..cfd3997409 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -13,7 +13,7 @@ * * Copyright (c) 2001-2006, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.121 2006/03/05 15:58:36 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.122 2006/04/06 20:38:00 tgl Exp $ * ---------- */ #include "postgres.h" @@ -69,12 +69,6 @@ #define PGSTAT_STAT_INTERVAL 500 /* How often to write the status file; * in milliseconds. */ -#define PGSTAT_DESTROY_DELAY 10000 /* How long to keep destroyed objects - * known, to give delayed UDP packets - * time to arrive; in milliseconds. */ - -#define PGSTAT_DESTROY_COUNT (PGSTAT_DESTROY_DELAY / PGSTAT_STAT_INTERVAL) - #define PGSTAT_RESTART_INTERVAL 60 /* How often to attempt to restart a * failed statistics collector; in * seconds. */ @@ -141,7 +135,6 @@ static int pgStatXactRollback = 0; static TransactionId pgStatDBHashXact = InvalidTransactionId; static HTAB *pgStatDBHash = NULL; -static HTAB *pgStatBeDead = NULL; static PgStat_StatBeEntry *pgStatBeTable = NULL; static int pgStatNumBackends = 0; @@ -1552,7 +1545,6 @@ PgstatCollectorMain(int argc, char *argv[]) int readPipe; int len = 0; struct itimerval timeout; - HASHCTL hash_ctl; bool need_timer = false; MyProcPid = getpid(); /* reset MyProcPid */ @@ -1614,16 +1606,6 @@ PgstatCollectorMain(int argc, char *argv[]) pgStatRunningInCollector = true; pgstat_read_statsfile(&pgStatDBHash, InvalidOid, NULL, NULL); - /* - * Create the dead backend hashtable - */ - memset(&hash_ctl, 0, sizeof(hash_ctl)); - hash_ctl.keysize = sizeof(int); - hash_ctl.entrysize = sizeof(PgStat_StatBeDead); - hash_ctl.hash = tag_hash; - pgStatBeDead = hash_create("Dead Backends", PGSTAT_BE_HASH_SIZE, - &hash_ctl, HASH_ELEM | HASH_FUNCTION); - /* * Create the known backends table */ @@ -2085,7 +2067,6 @@ static int pgstat_add_backend(PgStat_MsgHdr *msg) { PgStat_StatBeEntry *beentry; - PgStat_StatBeDead *deadbe; /* * Check that the backend ID is valid @@ -2111,32 +2092,13 @@ pgstat_add_backend(PgStat_MsgHdr *msg) if (beentry->procpid > 0 && beentry->procpid == msg->m_procpid) return 0; - /* - * Lookup if this backend is known to be dead. This can be caused due to - * messages arriving in the wrong order - e.g. postmaster's BETERM message - * might have arrived before we received all the backends stats messages, - * or even a new backend with the same backendid was faster in sending his - * BESTART. - * - * If the backend is known to be dead, we ignore this add. - */ - deadbe = (PgStat_StatBeDead *) hash_search(pgStatBeDead, - (void *) &(msg->m_procpid), - HASH_FIND, NULL); - if (deadbe) - return 1; - - /* - * Backend isn't known to be dead. If it's slot is currently used, we have - * to kick out the old backend. - */ - if (beentry->procpid > 0) - pgstat_sub_backend(beentry->procpid); - /* Must be able to distinguish between empty and non-empty slots */ Assert(msg->m_procpid > 0); - /* Put this new backend into the slot */ + /* + * Put this new backend into the slot (possibly overwriting an old entry, + * if we missed its BETERM or the BETERM hasn't arrived yet). + */ beentry->procpid = msg->m_procpid; beentry->start_timestamp = GetCurrentTimestamp(); beentry->activity_start_timestamp = 0; @@ -2185,7 +2147,6 @@ pgstat_get_db_entry(Oid databaseid, bool create) result->n_xact_rollback = 0; result->n_blocks_fetched = 0; result->n_blocks_hit = 0; - result->destroy = 0; result->last_autovac_time = 0; memset(&hash_ctl, 0, sizeof(hash_ctl)); @@ -2211,8 +2172,6 @@ static void pgstat_sub_backend(int procpid) { int i; - PgStat_StatBeDead *deadbe; - bool found; /* * Search in the known-backends table for the slot containing this PID. @@ -2222,28 +2181,7 @@ pgstat_sub_backend(int procpid) if (pgStatBeTable[i].procpid == procpid) { /* - * That's him. Add an entry to the known to be dead backends. Due - * to possible misorder in the arrival of UDP packets it's - * possible that even if we know the backend is dead, there could - * still be messages queued that arrive later. Those messages must - * not cause our number of backends statistics to get screwed up, - * so we remember for a couple of seconds that this PID is dead - * and ignore them (only the counting of backends, not the table - * access stats they sent). - */ - deadbe = (PgStat_StatBeDead *) hash_search(pgStatBeDead, - (void *) &procpid, - HASH_ENTER, - &found); - - if (!found) - { - deadbe->backendid = i + 1; - deadbe->destroy = PGSTAT_DESTROY_COUNT; - } - - /* - * Declare the backend slot empty. + * That's him. Mark the backend slot empty. */ pgStatBeTable[i].procpid = 0; return; @@ -2270,7 +2208,6 @@ pgstat_write_statsfile(void) HASH_SEQ_STATUS tstat; PgStat_StatDBEntry *dbentry; PgStat_StatTabEntry *tabentry; - PgStat_StatBeDead *deadbe; FILE *fpout; int i; int32 format_id; @@ -2300,31 +2237,6 @@ pgstat_write_statsfile(void) hash_seq_init(&hstat, pgStatDBHash); while ((dbentry = (PgStat_StatDBEntry *) hash_seq_search(&hstat)) != NULL) { - /* - * If this database is marked destroyed, count down and do so if it - * reaches 0. - */ - if (dbentry->destroy > 0) - { - if (--(dbentry->destroy) == 0) - { - if (dbentry->tables != NULL) - hash_destroy(dbentry->tables); - - if (hash_search(pgStatDBHash, - (void *) &(dbentry->databaseid), - HASH_REMOVE, NULL) == NULL) - ereport(ERROR, - (errmsg("database hash table corrupted " - "during cleanup --- abort"))); - } - - /* - * Don't include statistics for it. - */ - continue; - } - /* * Write out the DB entry including the number of live backends. * We don't write the tables pointer since it's of no use to any @@ -2339,30 +2251,6 @@ pgstat_write_statsfile(void) hash_seq_init(&tstat, dbentry->tables); while ((tabentry = (PgStat_StatTabEntry *) hash_seq_search(&tstat)) != NULL) { - /* - * If table entry marked for destruction, same as above for the - * database entry. - */ - if (tabentry->destroy > 0) - { - if (--(tabentry->destroy) == 0) - { - if (hash_search(dbentry->tables, - (void *) &(tabentry->tableid), - HASH_REMOVE, NULL) == NULL) - ereport(ERROR, - (errmsg("tables hash table for " - "database %u corrupted during " - "cleanup --- abort", - dbentry->databaseid))); - } - continue; - } - - /* - * At least we think this is still a live table. Emit its access - * stats. - */ fputc('T', fpout); fwrite(tabentry, sizeof(PgStat_StatTabEntry), 1, fpout); } @@ -2428,26 +2316,6 @@ pgstat_write_statsfile(void) PGSTAT_STAT_TMPFILE, PGSTAT_STAT_FILENAME))); unlink(PGSTAT_STAT_TMPFILE); } - - /* - * Clear out the dead backends table - */ - hash_seq_init(&hstat, pgStatBeDead); - while ((deadbe = (PgStat_StatBeDead *) hash_seq_search(&hstat)) != NULL) - { - /* - * Count down the destroy delay and remove entries where it reaches 0. - */ - if (--(deadbe->destroy) <= 0) - { - if (hash_search(pgStatBeDead, - (void *) &(deadbe->procpid), - HASH_REMOVE, NULL) == NULL) - ereport(ERROR, - (errmsg("dead-server-process hash table corrupted " - "during cleanup --- abort"))); - } - } } /* @@ -2595,7 +2463,6 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb, memcpy(dbentry, &dbbuf, sizeof(PgStat_StatDBEntry)); dbentry->tables = NULL; - dbentry->destroy = 0; dbentry->n_backends = 0; /* @@ -3005,12 +2872,8 @@ pgstat_recv_tabstat(PgStat_MsgTabstat *msg, int len) dbentry = pgstat_get_db_entry(msg->m_databaseid, true); /* - * If the database is marked for destroy, this is a delayed UDP packet and - * not worth being counted. + * Update database-wide stats. */ - if (dbentry->destroy > 0) - return; - dbentry->n_xact_commit += (PgStat_Counter) (msg->m_xact_commit); dbentry->n_xact_rollback += (PgStat_Counter) (msg->m_xact_rollback); @@ -3043,8 +2906,6 @@ pgstat_recv_tabstat(PgStat_MsgTabstat *msg, int len) tabentry->blocks_fetched = tabmsg[i].t_blocks_fetched; tabentry->blocks_hit = tabmsg[i].t_blocks_hit; - - tabentry->destroy = 0; } else { @@ -3085,7 +2946,6 @@ static void pgstat_recv_tabpurge(PgStat_MsgTabpurge *msg, int len) { PgStat_StatDBEntry *dbentry; - PgStat_StatTabEntry *tabentry; int i; /* @@ -3102,23 +2962,15 @@ pgstat_recv_tabpurge(PgStat_MsgTabpurge *msg, int len) if (!dbentry || !dbentry->tables) return; - /* - * If the database is marked for destroy, this is a delayed UDP packet and - * the tables will go away at DB destruction. - */ - if (dbentry->destroy > 0) - return; - /* * Process all table entries in the message. */ for (i = 0; i < msg->m_nentries; i++) { - tabentry = (PgStat_StatTabEntry *) hash_search(dbentry->tables, - (void *) &(msg->m_tableid[i]), - HASH_FIND, NULL); - if (tabentry) - tabentry->destroy = PGSTAT_DESTROY_COUNT; + /* Remove from hashtable if present; we don't care if it's not. */ + (void) hash_search(dbentry->tables, + (void *) &(msg->m_tableid[i]), + HASH_REMOVE, NULL); } } @@ -3146,10 +2998,20 @@ pgstat_recv_dropdb(PgStat_MsgDropdb *msg, int len) dbentry = pgstat_get_db_entry(msg->m_databaseid, false); /* - * Mark the database for destruction. + * If found, remove it. */ if (dbentry) - dbentry->destroy = PGSTAT_DESTROY_COUNT; + { + if (dbentry->tables != NULL) + hash_destroy(dbentry->tables); + + if (hash_search(pgStatDBHash, + (void *) &(dbentry->databaseid), + HASH_REMOVE, NULL) == NULL) + ereport(ERROR, + (errmsg("database hash table corrupted " + "during cleanup --- abort"))); + } } @@ -3191,7 +3053,6 @@ pgstat_recv_resetcounter(PgStat_MsgResetcounter *msg, int len) dbentry->n_xact_rollback = 0; dbentry->n_blocks_fetched = 0; dbentry->n_blocks_hit = 0; - dbentry->destroy = 0; memset(&hash_ctl, 0, sizeof(hash_ctl)); hash_ctl.keysize = sizeof(Oid); diff --git a/src/include/pgstat.h b/src/include/pgstat.h index 2442559b21..00631b3e12 100644 --- a/src/include/pgstat.h +++ b/src/include/pgstat.h @@ -5,7 +5,7 @@ * * Copyright (c) 2001-2006, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/include/pgstat.h,v 1.42 2006/03/05 15:58:53 momjian Exp $ + * $PostgreSQL: pgsql/src/include/pgstat.h,v 1.43 2006/04/06 20:38:00 tgl Exp $ * ---------- */ #ifndef PGSTAT_H @@ -271,16 +271,18 @@ typedef union PgStat_Msg * ------------------------------------------------------------ */ -#define PGSTAT_FILE_FORMAT_ID 0x01A5BC94 +#define PGSTAT_FILE_FORMAT_ID 0x01A5BC95 /* ---------- * PgStat_StatDBEntry The collector's data per database + * + * Note: n_backends is not maintained within the collector. It's computed + * when a backend reads the stats file for use. * ---------- */ typedef struct PgStat_StatDBEntry { Oid databaseid; - int destroy; int n_backends; PgStat_Counter n_xact_commit; PgStat_Counter n_xact_rollback; @@ -325,24 +327,6 @@ typedef struct PgStat_StatBeEntry } PgStat_StatBeEntry; -/* ---------- - * PgStat_StatBeDead Because UDP packets can arrive out of - * order, we need to keep some information - * about backends that are known to be - * dead for some seconds. This info is held - * in a hash table of these structs. - * - * (This struct is not used in the stats file.) - * ---------- - */ -typedef struct PgStat_StatBeDead -{ - int procpid; - int backendid; - int destroy; -} PgStat_StatBeDead; - - /* ---------- * PgStat_StatTabEntry The collector's data per table (or index) * ---------- @@ -350,7 +334,6 @@ typedef struct PgStat_StatBeDead typedef struct PgStat_StatTabEntry { Oid tableid; - int destroy; PgStat_Counter numscans;