*
* Copyright (c) 2001, PostgreSQL Global Development Group
*
- * $Header: /cvsroot/pgsql/src/backend/postmaster/pgstat.c,v 1.18 2002/03/06 06:10:00 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/postmaster/pgstat.c,v 1.19 2002/04/03 00:27:25 tgl Exp $
* ----------
*/
#include "postgres.h"
*
* Called from postmaster at startup. Create the resources required
* by the statistics collector process.
+ *
+ * NOTE: failure exit from this routine causes the postmaster to abort.
+ * This is unfriendly and should not be done except in dire straits.
+ * Better to let the postmaster start with stats collection disabled.
* ----------
*/
int
*/
if ((pgStatSock = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
{
- perror("PGSTAT: socket(2)");
- return -1;
+ elog(LOG, "PGSTAT: socket() failed: %m");
+ goto startup_failed;
}
/*
alen = sizeof(pgStatAddr);
if (bind(pgStatSock, (struct sockaddr *) & pgStatAddr, alen) < 0)
{
- perror("PGSTAT: bind(2)");
- close(pgStatSock);
- pgStatSock = -1;
- return -1;
+ elog(LOG, "PGSTAT: bind(127.0.0.1) failed: %m");
+ goto startup_failed;
}
if (getsockname(pgStatSock, (struct sockaddr *) & pgStatAddr, &alen) < 0)
{
- perror("PGSTAT: getsockname(2)");
- close(pgStatSock);
- pgStatSock = -1;
- return -1;
+ elog(LOG, "PGSTAT: getsockname() failed: %m");
+ goto startup_failed;
}
/*
*/
if (connect(pgStatSock, (struct sockaddr *) & pgStatAddr, alen) < 0)
{
- perror("PGSTAT: connect(2)");
- close(pgStatSock);
- pgStatSock = -1;
- return -1;
+ elog(LOG, "PGSTAT: connect() failed: %m");
+ goto startup_failed;
}
/*
*/
if (fcntl(pgStatSock, F_SETFL, O_NONBLOCK) < 0)
{
- perror("PGSTAT: fcntl(2)");
- close(pgStatSock);
- pgStatSock = -1;
- return -1;
+ elog(LOG, "PGSTAT: fcntl() failed: %m");
+ goto startup_failed;
}
/*
*/
if (pipe(pgStatPmPipe) < 0)
{
- perror("PGSTAT: pipe(2)");
- close(pgStatSock);
- pgStatSock = -1;
- return -1;
+ elog(LOG, "PGSTAT: pipe() failed: %m");
+ goto startup_failed;
}
+ return 0;
+
+startup_failed:
+ if (pgStatSock >= 0)
+ close(pgStatSock);
+ pgStatSock = -1;
+
+ /* Adjust GUC variables to suppress useless activity */
+ pgstat_collect_querystring = false;
+ pgstat_collect_tuplelevel = false;
+ pgstat_collect_blocklevel = false;
+
return 0;
}
*
* Called from postmaster at startup or after an existing collector
* died. Fire up a fresh statistics collector.
+ *
+ * NOTE: failure exit from this routine causes the postmaster to abort.
* ----------
*/
int
return 0;
/*
- * Check that the socket at least is there
+ * Check that the socket is there, else pgstat_init failed
*/
if (pgStatSock < 0)
{
- fprintf(stderr,
- "PGSTAT: suppress collector startup due to missing socket\n");
+ elog(LOG, "PGSTAT: statistics collector startup skipped");
return 0;
}
/* Specific beos actions */
beos_backend_startup_failed();
#endif
- perror("PGSTAT: fork(2)");
+ elog(LOG, "PGSTAT: fork() failed: %m");
pgStatRunning = 0;
- return -1;
+ return 0;
case 0:
break;
{
PgStat_MsgBeterm msg;
- if (!pgstat_collect_startcollector || pgStatSock < 0)
+ if (pgStatSock < 0)
return;
msg.m_hdr.m_type = PGSTAT_MTYPE_BETERM;
{
PgStat_MsgBestart msg;
- if (!pgstat_collect_startcollector || pgStatSock < 0)
+ if (pgStatSock < 0)
return;
pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_BESTART);
stats->heap_scan_counted = FALSE;
stats->index_scan_counted = FALSE;
- if (!pgstat_collect_startcollector || pgStatSock < 0)
+ if (pgStatSock < 0)
{
stats->no_stats = TRUE;
return;
malloc(sizeof(PgStat_MsgTabstat *) * pgStatTabstatAlloc);
if (pgStatTabstatMessages == NULL)
{
- perror("PGSTATBE: malloc(2)");
+ elog(LOG, "PGSTATBE: malloc() failed");
return;
}
for (i = 0; i < pgStatTabstatAlloc; i++)
malloc(sizeof(PgStat_MsgTabstat));
if (pgStatTabstatMessages[i] == NULL)
{
- perror("PGSTATBE: malloc(2)");
+ elog(LOG, "PGSTATBE: malloc() failed");
return;
}
}
if (pgStatTabstatMessages == NULL)
{
pgStatTabstatAlloc -= 4;
- perror("PGSTATBE: malloc(2)");
+ elog(LOG, "PGSTATBE: malloc() failed");
return;
}
for (i = pgStatTabstatUsed; i < pgStatTabstatAlloc; i++)
if (pgStatTabstatMessages[i] == NULL)
{
pgStatTabstatAlloc -= 4;
- perror("PGSTATBE: malloc(2)");
+ elog(LOG, "PGSTATBE: malloc() failed");
return;
}
}
*/
if (pipe(pgStatPipe) < 0)
{
- perror("PGSTAT: pipe(2)");
+ elog(LOG, "PGSTAT: pipe() failed: %m");
exit(1);
}
switch (fork())
{
case -1:
- perror("PGSTAT: fork(2)");
+ elog(LOG, "PGSTAT: fork() failed: %m");
exit(1);
case 0:
&hash_ctl, HASH_ELEM | HASH_FUNCTION);
if (pgStatBeDead == NULL)
{
- fprintf(stderr,
- "PGSTAT: Creation of dead backend hash table failed\n");
+ elog(LOG, "PGSTAT: Creation of dead backend hash table failed");
exit(1);
}
sizeof(PgStat_StatBeEntry) * MaxBackends);
if (pgStatBeTable == NULL)
{
- perror("PGSTAT: Allocation of backend table failed");
+ elog(LOG, "PGSTAT: Allocation of backend table failed");
exit(1);
}
memset(pgStatBeTable, 0, sizeof(PgStat_StatBeEntry) * MaxBackends);
{
if (errno == EINTR)
continue;
- perror("PGSTAT: select(2)");
+ elog(LOG, "PGSTAT: select() failed: %m");
exit(1);
}
{
if (errno == EINTR)
continue;
- perror("PGSTAT: read(2)");
+ elog(LOG, "PGSTAT: read() failed: %m");
exit(1);
}
if (len == 0) /* EOF on the pipe! */
* sync with the buffer process somehow. Abort so
* that we can restart both processes.
*/
- fprintf(stderr, "PGSTAT: bogus message length\n");
+ elog(LOG, "PGSTAT: bogus message length");
exit(1);
}
}
*/
if (fcntl(writePipe, F_SETFL, O_NONBLOCK) < 0)
{
- perror("PGSTATBUFF: fcntl(2)");
+ elog(LOG, "PGSTATBUFF: fcntl() failed: %m");
exit(1);
}
msgbuffer = (char *) malloc(PGSTAT_RECVBUFFERSZ);
if (msgbuffer == NULL)
{
- perror("PGSTATBUFF: malloc()");
+ elog(LOG, "PGSTATBUFF: malloc() failed");
exit(1);
}
{
if (!overflow)
{
- fprintf(stderr, "PGSTATBUFF: Warning - receive buffer full\n");
+ elog(LOG, "PGSTATBUFF: Warning - receive buffer full");
overflow = true;
}
}
{
if (errno == EINTR)
continue;
- perror("PGSTATBUFF: select(2)");
+ elog(LOG, "PGSTATBUFF: select() failed: %m");
exit(1);
}
(struct sockaddr *) &fromaddr, &fromlen);
if (len < 0)
{
- perror("PGSTATBUFF: recvfrom(2)");
+ elog(LOG, "PGSTATBUFF: recvfrom() failed: %m");
exit(1);
}
{
if (errno == EINTR || errno == EAGAIN)
continue; /* not enough space in pipe */
- perror("PGSTATBUFF: write(2)");
+ elog(LOG, "PGSTATBUFF: write() failed: %m");
exit(1);
}
/* NB: len < xfr is okay */
*/
if (msg->m_backendid < 1 || msg->m_backendid > MaxBackends)
{
- fprintf(stderr, "PGSTAT: Invalid backend ID %d\n", msg->m_backendid);
+ elog(LOG, "PGSTAT: Invalid backend ID %d", msg->m_backendid);
return -1;
}
HASH_ENTER, &found);
if (dbentry == NULL)
{
- fprintf(stderr, "PGSTAT: DB hash table out of memory - abort\n");
+ elog(LOG, "PGSTAT: DB hash table out of memory - abort");
exit(1);
}
HASH_ELEM | HASH_FUNCTION);
if (dbentry->tables == NULL)
{
- fprintf(stderr, "PGSTAT: failed to initialize hash table for "
- "new database entry\n");
+ elog(LOG, "PGSTAT: failed to initialize hash table for "
+ "new database entry");
exit(1);
}
}
HASH_ENTER, &found);
if (deadbe == NULL)
{
- fprintf(stderr, "PGSTAT: dead backend hash table out of memory "
- "- abort\n");
+ elog(LOG, "PGSTAT: dead backend hash table out of memory");
exit(1);
}
if (!found)
fpout = fopen(pgStat_tmpfname, PG_BINARY_W);
if (fpout == NULL)
{
- fprintf(stderr, "PGSTAT: cannot open temp stats file\nPGSTAT: ");
- perror(pgStat_tmpfname);
- fflush(stderr);
+ elog(LOG, "PGSTAT: cannot open temp stats file %s: %m",
+ pgStat_tmpfname);
return;
}
(void *) &(dbentry->databaseid),
HASH_REMOVE, NULL) == NULL)
{
- fprintf(stderr, "PGSTAT: database hash table corrupted "
- "during cleanup - abort\n");
+ elog(LOG, "PGSTAT: database hash table corrupted "
+ "during cleanup - abort");
exit(1);
}
}
(void *) &(tabentry->tableid),
HASH_REMOVE, NULL) == NULL)
{
- fprintf(stderr, "PGSTAT: tables hash table for "
+ elog(LOG, "PGSTAT: tables hash table for "
"database %d corrupted during "
- "cleanup - abort\n",
+ "cleanup - abort",
dbentry->databaseid);
exit(1);
}
fputc('E', fpout);
if (fclose(fpout) < 0)
{
- fprintf(stderr, "PGSTAT: Error closing temp stats file\nPGSTAT: ");
- perror(pgStat_tmpfname);
- fprintf(stderr, "PGSTAT: Abort\n");
- fflush(stderr);
- exit(1);
+ elog(LOG, "PGSTAT: Error closing temp stats file %s: %m",
+ pgStat_tmpfname);
}
else
{
if (rename(pgStat_tmpfname, pgStat_fname) < 0)
{
- fprintf(stderr, "PGSTAT: Cannot rename temp stats file\n"
- "PGSTAT: ");
- perror(pgStat_fname);
- fflush(stderr);
+ elog(LOG, "PGSTAT: Cannot rename temp stats file %s: %m",
+ pgStat_fname);
}
}
(void *) &(deadbe->procpid),
HASH_REMOVE, NULL) == NULL)
{
- fprintf(stderr, "PGSTAT: dead backend hash table corrupted "
- "during cleanup - abort\n");
+ elog(LOG, "PGSTAT: dead backend hash table corrupted "
+ "during cleanup - abort");
exit(1);
}
}
{
if (pgStatRunningInCollector)
{
- fprintf(stderr, "PGSTAT: Creation of DB hash table failed\n");
+ elog(LOG, "PGSTAT: Creation of DB hash table failed");
exit(1);
}
+ /* in backend, can do normal error */
elog(ERROR, "PGSTAT: Creation of DB hash table failed");
}
{
if (pgStatRunningInCollector)
{
- fprintf(stderr,
- "PGSTAT: corrupted pgstat.stat file\n");
+ elog(LOG, "PGSTAT: corrupted pgstat.stat file");
fclose(fpin);
return;
}
else
{
- elog(WARNING,
- "PGSTAT: corrupted pgstat.stat file");
+ elog(WARNING, "PGSTAT: corrupted pgstat.stat file");
fclose(fpin);
return;
}
{
if (pgStatRunningInCollector)
{
- fprintf(stderr, "PGSTAT: DB hash table out of memory\n");
+ elog(LOG, "PGSTAT: DB hash table out of memory");
exit(1);
}
else
{
if (pgStatRunningInCollector)
{
- fprintf(stderr,
- "PGSTAT: corrupted pgstat.stat file\n");
+ elog(LOG, "PGSTAT: corrupted pgstat.stat file");
fclose(fpin);
return;
}
else
{
- elog(WARNING,
- "PGSTAT: corrupted pgstat.stat file");
+ elog(WARNING, "PGSTAT: corrupted pgstat.stat file");
fclose(fpin);
return;
}
{
if (pgStatRunningInCollector)
{
- fprintf(stderr, "PGSTAT: failed to initialize "
- "hash table for new database entry\n");
+ elog(LOG, "PGSTAT: failed to initialize "
+ "hash table for new database entry");
exit(1);
}
else
{
fclose(fpin);
elog(ERROR, "PGSTAT: failed to initialize "
- "hash table for new database entry\n");
+ "hash table for new database entry");
}
}
{
if (pgStatRunningInCollector)
{
- fprintf(stderr,
- "PGSTAT: corrupted pgstat.stat file\n");
+ elog(LOG, "PGSTAT: corrupted pgstat.stat file");
fclose(fpin);
return;
}
else
{
- elog(WARNING,
- "PGSTAT: corrupted pgstat.stat file");
+ elog(WARNING, "PGSTAT: corrupted pgstat.stat file");
fclose(fpin);
return;
}
{
if (pgStatRunningInCollector)
{
- fprintf(stderr, "PGSTAT: Tab hash table out of memory\n");
+ elog(LOG, "PGSTAT: Tab hash table out of memory");
exit(1);
}
else
{
if (pgStatRunningInCollector)
{
- fprintf(stderr,
- "PGSTAT: corrupted pgstat.stat file\n");
+ elog(LOG, "PGSTAT: corrupted pgstat.stat file");
fclose(fpin);
return;
}
else
{
- elog(WARNING,
- "PGSTAT: corrupted pgstat.stat file");
+ elog(WARNING, "PGSTAT: corrupted pgstat.stat file");
fclose(fpin);
return;
}
{
if (pgStatRunningInCollector)
{
- fprintf(stderr,
- "PGSTAT: corrupted pgstat.stat file\n");
+ elog(LOG, "PGSTAT: corrupted pgstat.stat file");
fclose(fpin);
return;
}
else
{
- elog(WARNING,
- "PGSTAT: corrupted pgstat.stat file");
+ elog(WARNING, "PGSTAT: corrupted pgstat.stat file");
fclose(fpin);
return;
}
{
if (pgStatRunningInCollector)
{
- fprintf(stderr,
- "PGSTAT: corrupted pgstat.stat file\n");
+ elog(LOG, "PGSTAT: corrupted pgstat.stat file");
fclose(fpin);
return;
}
else
{
- elog(WARNING,
- "PGSTAT: corrupted pgstat.stat file");
+ elog(WARNING, "PGSTAT: corrupted pgstat.stat file");
fclose(fpin);
return;
}
default:
if (pgStatRunningInCollector)
{
- fprintf(stderr, "PGSTAT: corrupted pgstat.stat file\n");
+ elog(LOG, "PGSTAT: corrupted pgstat.stat file");
fclose(fpin);
return;
}
HASH_ENTER, &found);
if (tabentry == NULL)
{
- fprintf(stderr, "PGSTAT: tables hash table out of memory for "
- "database %d - abort\n", dbentry->databaseid);
+ elog(LOG, "PGSTAT: tables hash table out of memory for "
+ "database %d - abort", dbentry->databaseid);
exit(1);
}
HASH_ELEM | HASH_FUNCTION);
if (dbentry->tables == NULL)
{
- fprintf(stderr, "PGSTAT: failed to reinitialize hash table for "
- "database entry\n");
+ elog(LOG, "PGSTAT: failed to reinitialize hash table for "
+ "database entry");
exit(1);
}
}