4 * All the statistics collector stuff hacked up in one big, ugly file.
6 * TODO: - Separate collector, postmaster and backend stuff
7 * into different files.
9 * - Add some automatic call for pgstat vacuuming.
11 * - Add a pgstat config column to pg_database, so this
12 * entire thing can be enabled/disabled on a per db base.
14 * Copyright (c) 2001-2003, PostgreSQL Global Development Group
16 * $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.67 2004/04/19 17:42:58 momjian Exp $
23 #include <sys/param.h>
25 #include <sys/types.h>
26 #include <sys/socket.h>
28 #include <netinet/in.h>
29 #include <arpa/inet.h>
35 #include "access/xact.h"
36 #include "access/heapam.h"
37 #include "catalog/catname.h"
38 #include "catalog/pg_shadow.h"
39 #include "catalog/pg_database.h"
40 #include "libpq/pqsignal.h"
41 #include "libpq/libpq.h"
42 #include "mb/pg_wchar.h"
43 #include "miscadmin.h"
44 #include "utils/memutils.h"
45 #include "storage/backendid.h"
46 #include "storage/ipc.h"
47 #include "storage/pg_shmem.h"
48 #include "tcop/tcopprot.h"
49 #include "utils/rel.h"
50 #include "utils/hsearch.h"
51 #include "utils/ps_status.h"
52 #include "utils/syscache.h"
55 #include "utils/guc.h"
59 extern pid_t win32_forkexec(const char* path, char *argv[]);
66 bool pgstat_collect_startcollector = true;
67 bool pgstat_collect_resetonpmstart = true;
68 bool pgstat_collect_querystring = false;
69 bool pgstat_collect_tuplelevel = false;
70 bool pgstat_collect_blocklevel = false;
73 * Other global variables
76 bool pgstat_is_running = false;
82 NON_EXEC_STATIC int pgStatSock = -1;
83 static int pgStatPipe[2];
84 static struct sockaddr_storage pgStatAddr;
85 static int pgStatPmPipe[2] = {-1, -1};
86 static int pgStatCollectorPmPipe[2] = {-1, -1};
89 static time_t last_pgstat_start_time;
91 static long pgStatNumMessages = 0;
93 static bool pgStatRunningInCollector = FALSE;
95 static int pgStatTabstatAlloc = 0;
96 static int pgStatTabstatUsed = 0;
97 static PgStat_MsgTabstat **pgStatTabstatMessages = NULL;
99 #define TABSTAT_QUANTUM 4 /* we alloc this many at a time */
101 static int pgStatXactCommit = 0;
102 static int pgStatXactRollback = 0;
104 static TransactionId pgStatDBHashXact = InvalidTransactionId;
105 static HTAB *pgStatDBHash = NULL;
106 static HTAB *pgStatBeDead = NULL;
107 static PgStat_StatBeEntry *pgStatBeTable = NULL;
108 static int pgStatNumBackends = 0;
110 static char pgStat_tmpfname[MAXPGPATH];
111 static char pgStat_fname[MAXPGPATH];
115 * Local function forward declarations
119 static pid_t pgstat_forkexec(STATS_PROCESS_TYPE procType);
120 static void pgstat_parseArgs(PGSTAT_FORK_ARGS);
122 NON_EXEC_STATIC void pgstat_main(PGSTAT_FORK_ARGS);
123 NON_EXEC_STATIC void pgstat_mainChild(PGSTAT_FORK_ARGS);
124 static void pgstat_mainInit(void);
125 static void pgstat_recvbuffer(void);
126 static void pgstat_die(SIGNAL_ARGS);
128 static int pgstat_add_backend(PgStat_MsgHdr *msg);
129 static void pgstat_sub_backend(int procpid);
130 static void pgstat_drop_database(Oid databaseid);
131 static void pgstat_write_statsfile(void);
132 static void pgstat_read_statsfile(HTAB **dbhash, Oid onlydb,
133 PgStat_StatBeEntry **betab,
136 static void pgstat_setheader(PgStat_MsgHdr *hdr, int mtype);
137 static void pgstat_send(void *msg, int len);
139 static void pgstat_recv_bestart(PgStat_MsgBestart *msg, int len);
140 static void pgstat_recv_beterm(PgStat_MsgBeterm *msg, int len);
141 static void pgstat_recv_activity(PgStat_MsgActivity *msg, int len);
142 static void pgstat_recv_tabstat(PgStat_MsgTabstat *msg, int len);
143 static void pgstat_recv_tabpurge(PgStat_MsgTabpurge *msg, int len);
144 static void pgstat_recv_dropdb(PgStat_MsgDropdb *msg, int len);
145 static void pgstat_recv_resetcounter(PgStat_MsgResetcounter *msg, int len);
148 /* ------------------------------------------------------------
149 * Public functions called from postmaster follow
150 * ------------------------------------------------------------
156 pgstat_init_forkexec_backend(void)
158 Assert(DataDir != NULL);
159 snprintf(pgStat_fname, MAXPGPATH,
160 PGSTAT_STAT_FILENAME, DataDir);
168 * Called from postmaster at startup. Create the resources required
169 * by the statistics collector process. If unable to do so, do not
170 * fail --- better to let the postmaster start with stats collection
177 ACCEPT_TYPE_ARG3 alen;
178 struct addrinfo *addrs = NULL,
187 #define TESTBYTEVAL ((char) 199)
190 * Force start of collector daemon if something to collect
192 if (pgstat_collect_querystring ||
193 pgstat_collect_tuplelevel ||
194 pgstat_collect_blocklevel)
195 pgstat_collect_startcollector = true;
198 * Initialize the filenames for the status reports.
200 snprintf(pgStat_tmpfname, MAXPGPATH,
201 PGSTAT_STAT_TMPFILE, DataDir, getpid());
202 snprintf(pgStat_fname, MAXPGPATH,
203 PGSTAT_STAT_FILENAME, DataDir);
206 * If we don't have to start a collector or should reset the collected
207 * statistics on postmaster start, simply remove the file.
209 if (!pgstat_collect_startcollector || pgstat_collect_resetonpmstart)
210 unlink(pgStat_fname);
213 * Nothing else required if collector will not get started
215 if (!pgstat_collect_startcollector)
219 * Create the UDP socket for sending and receiving statistic messages
221 hints.ai_flags = AI_PASSIVE;
222 hints.ai_family = PF_UNSPEC;
223 hints.ai_socktype = SOCK_DGRAM;
224 hints.ai_protocol = 0;
225 hints.ai_addrlen = 0;
226 hints.ai_addr = NULL;
227 hints.ai_canonname = NULL;
228 hints.ai_next = NULL;
229 ret = getaddrinfo_all("localhost", NULL, &hints, &addrs);
233 (errmsg("could not resolve \"localhost\": %s",
234 gai_strerror(ret))));
239 * On some platforms, getaddrinfo_all() may return multiple addresses
240 * only one of which will actually work (eg, both IPv6 and IPv4 addresses
241 * when kernel will reject IPv6). Worse, the failure may occur at the
242 * bind() or perhaps even connect() stage. So we must loop through the
243 * results till we find a working combination. We will generate LOG
244 * messages, but no error, for bogus combinations.
246 for (addr = addrs; addr; addr = addr->ai_next)
248 #ifdef HAVE_UNIX_SOCKETS
249 /* Ignore AF_UNIX sockets, if any are returned. */
250 if (addr->ai_family == AF_UNIX)
256 if ((pgStatSock = socket(addr->ai_family, SOCK_DGRAM, 0)) < 0)
259 (errcode_for_socket_access(),
260 errmsg("could not create socket for statistics collector: %m")));
265 * Bind it to a kernel assigned port on localhost and get the assigned
266 * port via getsockname().
268 if (bind(pgStatSock, addr->ai_addr, addr->ai_addrlen) < 0)
271 (errcode_for_socket_access(),
272 errmsg("could not bind socket for statistics collector: %m")));
273 closesocket(pgStatSock);
278 alen = sizeof(pgStatAddr);
279 if (getsockname(pgStatSock, (struct sockaddr *) &pgStatAddr, &alen) < 0)
282 (errcode_for_socket_access(),
283 errmsg("could not get address of socket for statistics collector: %m")));
284 closesocket(pgStatSock);
290 * Connect the socket to its own address. This saves a few cycles by
291 * not having to respecify the target address on every send. This also
292 * provides a kernel-level check that only packets from this same
293 * address will be received.
295 if (connect(pgStatSock, (struct sockaddr *) &pgStatAddr, alen) < 0)
298 (errcode_for_socket_access(),
299 errmsg("could not connect socket for statistics collector: %m")));
300 closesocket(pgStatSock);
306 * Try to send and receive a one-byte test message on the socket.
307 * This is to catch situations where the socket can be created but
308 * will not actually pass data (for instance, because kernel packet
309 * filtering rules prevent it).
311 test_byte = TESTBYTEVAL;
312 if (send(pgStatSock, &test_byte, 1, 0) != 1)
315 (errcode_for_socket_access(),
316 errmsg("could not send test message on socket for statistics collector: %m")));
317 closesocket(pgStatSock);
323 * There could possibly be a little delay before the message can be
324 * received. We arbitrarily allow up to half a second before deciding
327 for (;;) /* need a loop to handle EINTR */
330 FD_SET(pgStatSock, &rset);
333 sel_res = select(pgStatSock+1, &rset, NULL, NULL, &tv);
334 if (sel_res >= 0 || errno != EINTR)
340 (errcode_for_socket_access(),
341 errmsg("select() failed in statistics collector: %m")));
342 closesocket(pgStatSock);
346 if (sel_res == 0 || !FD_ISSET(pgStatSock, &rset))
349 * This is the case we actually think is likely, so take pains to
350 * give a specific message for it.
352 * errno will not be set meaningfully here, so don't use it.
355 (ERRCODE_CONNECTION_FAILURE,
356 errmsg("test message did not get through on socket for statistics collector")));
357 closesocket(pgStatSock);
362 test_byte++; /* just make sure variable is changed */
364 if (recv(pgStatSock, &test_byte, 1, 0) != 1)
367 (errcode_for_socket_access(),
368 errmsg("could not receive test message on socket for statistics collector: %m")));
369 closesocket(pgStatSock);
374 if (test_byte != TESTBYTEVAL) /* strictly paranoia ... */
377 (ERRCODE_INTERNAL_ERROR,
378 errmsg("incorrect test message transmission on socket for statistics collector")));
379 closesocket(pgStatSock);
384 /* If we get here, we have a working socket */
388 /* Did we find a working address? */
389 if (!addr || pgStatSock < 0)
392 (errcode_for_socket_access(),
393 errmsg("disabling statistics collector for lack of working socket")));
398 * Set the socket to non-blocking IO. This ensures that if the
399 * collector falls behind (despite the buffering process), statistics
400 * messages will be discarded; backends won't block waiting to send
401 * messages to the collector.
403 if (!set_noblock(pgStatSock))
406 (errcode_for_socket_access(),
407 errmsg("could not set statistics collector socket to nonblocking mode: %m")));
412 * Create the pipe that controls the statistics collector shutdown
414 if (pgpipe(pgStatPmPipe) < 0 || pgpipe(pgStatCollectorPmPipe) < 0)
417 (errcode_for_socket_access(),
418 errmsg("could not create pipe for statistics collector: %m")));
422 freeaddrinfo_all(hints.ai_family, addrs);
428 freeaddrinfo_all(hints.ai_family, addrs);
431 closesocket(pgStatSock);
434 /* Adjust GUC variables to suppress useless activity */
435 pgstat_collect_startcollector = false;
436 pgstat_collect_querystring = false;
437 pgstat_collect_tuplelevel = false;
438 pgstat_collect_blocklevel = false;
445 * pgstat_forkexec() -
447 * Used to format up the arglist for, then fork and exec, statistics
448 * (buffer and collector) processes
452 pgstat_forkexec(STATS_PROCESS_TYPE procType)
456 int ac = 0, bufc = 0, i;
457 char pgstatBuf[12][MAXPGPATH];
459 av[ac++] = "postgres";
462 case STAT_PROC_BUFFER:
463 av[ac++] = "-statBuf";
466 case STAT_PROC_COLLECTOR:
467 av[ac++] = "-statCol";
474 /* Sockets + pipes */
476 snprintf(pgstatBuf[bufc++],MAXPGPATH,"%d",pgStatSock);
477 snprintf(pgstatBuf[bufc++],MAXPGPATH,"%d",pgStatPmPipe[0]);
478 snprintf(pgstatBuf[bufc++],MAXPGPATH,"%d",pgStatPmPipe[1]);
479 snprintf(pgstatBuf[bufc++],MAXPGPATH,"%d",pgStatCollectorPmPipe[0]);
480 snprintf(pgstatBuf[bufc++],MAXPGPATH,"%d",pgStatCollectorPmPipe[1]);
481 snprintf(pgstatBuf[bufc++],MAXPGPATH,"%d",pgStatPipe[0]);
482 snprintf(pgstatBuf[bufc++],MAXPGPATH,"%d",pgStatPipe[1]);
485 snprintf(pgstatBuf[bufc++],MAXPGPATH,"%d",MaxBackends);
487 /* + the pstat file names, and postgres pathname */
488 /* FIXME: [fork/exec] whitespaces in directories? */
489 snprintf(pgstatBuf[bufc++],MAXPGPATH,"%s",pgStat_tmpfname);
490 snprintf(pgstatBuf[bufc++],MAXPGPATH,"%s",pgStat_fname);
491 snprintf(pgstatBuf[bufc++],MAXPGPATH,"%s",pg_pathname);
492 snprintf(pgstatBuf[bufc++],MAXPGPATH,"%s",DataDir);
494 /* Add to the arg list */
495 Assert(bufc <= lengthof(pgstatBuf));
496 for (i = 0; i < bufc; i++)
497 av[ac++] = pgstatBuf[i];
500 Assert(ac <= lengthof(av));
502 /* Fire off execv in child */
504 pid = win32_forkexec(pg_pathname,av);
506 if ((pid = fork()) == 0 && (execv(pg_pathname,av) == -1))
507 /* FIXME: [fork/exec] suggestions for what to do here? Can't call elog... */
510 return pid; /* Parent returns pid */
515 * pgstat_parseArgs() -
517 * Used to unformat the arglist for exec'ed statistics
518 * (buffer and collector) processes
522 pgstat_parseArgs(PGSTAT_FORK_ARGS)
526 pgStatSock = atoi(argv[argc++]);
527 pgStatPmPipe[0] = atoi(argv[argc++]);
528 pgStatPmPipe[1] = atoi(argv[argc++]);
529 pgStatCollectorPmPipe[0] = atoi(argv[argc++]);
530 pgStatCollectorPmPipe[1] = atoi(argv[argc++]);
531 pgStatPipe[0] = atoi(argv[argc++]);
532 pgStatPipe[1] = atoi(argv[argc++]);
533 MaxBackends = atoi(argv[argc++]);
534 strncpy(pgStat_tmpfname,argv[argc++],MAXPGPATH);
535 strncpy(pgStat_fname, argv[argc++],MAXPGPATH);
536 strncpy(pg_pathname, argv[argc++],MAXPGPATH);
537 DataDir = strdup(argv[argc++]);
539 read_nondefault_variables();
547 * Called from postmaster at startup or after an existing collector
548 * died. Attempt to fire up a fresh statistics collector.
550 * Note: if fail, we will be called again from the postmaster main loop.
559 * Do nothing if no collector needed
561 if (pgstat_is_running || !pgstat_collect_startcollector)
565 * Do nothing if too soon since last collector start. This is a
566 * safety valve to protect against continuous respawn attempts if the
567 * collector is dying immediately at launch. Note that since we will
568 * be re-called from the postmaster main loop, we will get another
571 curtime = time(NULL);
572 if ((unsigned int) (curtime - last_pgstat_start_time) <
573 (unsigned int) PGSTAT_RESTART_INTERVAL)
575 last_pgstat_start_time = curtime;
578 * Check that the socket is there, else pgstat_init failed.
583 (errmsg("statistics collector startup skipped")));
586 * We can only get here if someone tries to manually turn
587 * pgstat_collect_startcollector on after it had been off.
589 pgstat_collect_startcollector = false;
594 * Okay, fork off the collector. Remember its PID for
602 /* Specific beos actions before backend startup */
603 beos_before_backend_startup();
607 switch ((pgStatPid = (int) pgstat_forkexec(STAT_PROC_BUFFER)))
609 switch ((pgStatPid = (int) fork()))
614 /* Specific beos actions */
615 beos_backend_startup_failed();
618 (errmsg("could not fork statistics buffer: %m")));
623 /* in postmaster child ... */
625 /* Specific beos actions after backend startup */
626 beos_backend_startup();
628 /* Close the postmaster's sockets, except for pgstat link */
629 ClosePostmasterPorts(false);
631 /* Drop our connection to postmaster's shared memory, as well */
632 PGSharedMemoryDetach();
639 pgstat_is_running = true;
646 * pgstat_ispgstat() -
648 * Called from postmaster to check if a terminated child process
649 * was the statistics collector.
653 pgstat_ispgstat(int pid)
655 if (!pgstat_is_running)
658 if (pgStatPid != pid)
662 pgstat_is_running = false;
669 * pgstat_close_sockets() -
671 * Called when postmaster forks a non-pgstat child process, to close off
672 * file descriptors that should not be held open in child processes.
676 pgstat_close_sockets(void)
678 if (pgStatPmPipe[0] >= 0)
679 closesocket(pgStatPmPipe[0]);
680 pgStatPmPipe[0] = -1;
681 if (pgStatPmPipe[1] >= 0)
682 closesocket(pgStatPmPipe[1]);
683 pgStatPmPipe[1] = -1;
684 if (pgStatCollectorPmPipe[0] >= 0)
685 closesocket(pgStatCollectorPmPipe[0]);
686 pgStatCollectorPmPipe[0] = -1;
687 if (pgStatCollectorPmPipe[1] >= 0)
688 closesocket(pgStatCollectorPmPipe[1]);
689 pgStatCollectorPmPipe[1] = -1;
696 * Called from postmaster to tell collector a backend terminated.
700 pgstat_beterm(int pid)
702 PgStat_MsgBeterm msg;
707 MemSet(&(msg.m_hdr), 0, sizeof(msg.m_hdr));
708 msg.m_hdr.m_type = PGSTAT_MTYPE_BETERM;
709 msg.m_hdr.m_procpid = pid;
711 pgstat_send(&msg, sizeof(msg));
715 /* ------------------------------------------------------------
716 * Public functions used by backends follow
717 *------------------------------------------------------------
724 * Tell the collector that this new backend is soon ready to process
725 * queries. Called from tcop/postgres.c before entering the mainloop.
731 PgStat_MsgBestart msg;
736 pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_BESTART);
737 pgstat_send(&msg, sizeof(msg));
742 * pgstat_report_activity() -
744 * Called in tcop/postgres.c to tell the collector what the backend
745 * is actually doing (usually "<IDLE>" or the start of the query to
750 pgstat_report_activity(const char *what)
752 PgStat_MsgActivity msg;
755 if (!pgstat_collect_querystring || pgStatSock < 0)
759 len = pg_mbcliplen((const unsigned char *) what, len,
760 PGSTAT_ACTIVITY_SIZE - 1);
762 memcpy(msg.m_what, what, len);
763 msg.m_what[len] = '\0';
764 len += offsetof(PgStat_MsgActivity, m_what) +1;
766 pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_ACTIVITY);
767 pgstat_send(&msg, len);
772 * pgstat_report_tabstat() -
774 * Called from tcop/postgres.c to send the so far collected
775 * per table access statistics to the collector.
779 pgstat_report_tabstat(void)
783 if (pgStatSock < 0 ||
784 !(pgstat_collect_querystring ||
785 pgstat_collect_tuplelevel ||
786 pgstat_collect_blocklevel))
788 /* Not reporting stats, so just flush whatever we have */
789 pgStatTabstatUsed = 0;
794 * For each message buffer used during the last query set the header
795 * fields and send it out.
797 for (i = 0; i < pgStatTabstatUsed; i++)
799 PgStat_MsgTabstat *tsmsg = pgStatTabstatMessages[i];
803 n = tsmsg->m_nentries;
804 len = offsetof(PgStat_MsgTabstat, m_entry[0]) +
805 n * sizeof(PgStat_TableEntry);
807 tsmsg->m_xact_commit = pgStatXactCommit;
808 tsmsg->m_xact_rollback = pgStatXactRollback;
809 pgStatXactCommit = 0;
810 pgStatXactRollback = 0;
812 pgstat_setheader(&tsmsg->m_hdr, PGSTAT_MTYPE_TABSTAT);
813 pgstat_send(tsmsg, len);
816 pgStatTabstatUsed = 0;
821 * pgstat_vacuum_tabstat() -
823 * Will tell the collector about objects he can get rid of.
827 pgstat_vacuum_tabstat(void)
835 HASH_SEQ_STATUS hstat;
836 PgStat_StatDBEntry *dbentry;
837 PgStat_StatTabEntry *tabentry;
840 PgStat_MsgTabpurge msg;
848 * If not done for this transaction, read the statistics collector
849 * stats file into some hash tables.
851 if (!TransactionIdEquals(pgStatDBHashXact, GetCurrentTransactionId()))
853 pgstat_read_statsfile(&pgStatDBHash, MyDatabaseId,
854 &pgStatBeTable, &pgStatNumBackends);
855 pgStatDBHashXact = GetCurrentTransactionId();
859 * Lookup our own database entry
861 dbentry = (PgStat_StatDBEntry *) hash_search(pgStatDBHash,
862 (void *) &MyDatabaseId,
867 if (dbentry->tables == NULL)
871 * Initialize our messages table counter to zero
876 * Check for all tables if they still exist.
878 hash_seq_init(&hstat, dbentry->tables);
879 while ((tabentry = (PgStat_StatTabEntry *) hash_seq_search(&hstat)) != NULL)
882 * Check if this relation is still alive by looking up it's
883 * pg_class tuple in the system catalog cache.
885 reltup = SearchSysCache(RELOID,
886 ObjectIdGetDatum(tabentry->tableid),
888 if (HeapTupleIsValid(reltup))
890 ReleaseSysCache(reltup);
895 * Add this tables Oid to the message
897 msg.m_tableid[msg.m_nentries++] = tabentry->tableid;
901 * If the message is full, send it out and reinitialize ot zero
903 if (msg.m_nentries >= PGSTAT_NUM_TABPURGE)
905 len = offsetof(PgStat_MsgTabpurge, m_tableid[0])
906 +msg.m_nentries * sizeof(Oid);
908 pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_TABPURGE);
909 pgstat_send(&msg, len);
918 if (msg.m_nentries > 0)
920 len = offsetof(PgStat_MsgTabpurge, m_tableid[0])
921 +msg.m_nentries * sizeof(Oid);
923 pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_TABPURGE);
924 pgstat_send(&msg, len);
928 * Read pg_database and remember the Oid's of all existing databases
932 dbidlist = (Oid *) palloc(sizeof(Oid) * dbidalloc);
934 dbrel = heap_openr(DatabaseRelationName, AccessShareLock);
935 dbscan = heap_beginscan(dbrel, SnapshotNow, 0, NULL);
936 while ((dbtup = heap_getnext(dbscan, ForwardScanDirection)) != NULL)
938 if (dbidused >= dbidalloc)
941 dbidlist = (Oid *) repalloc((char *) dbidlist,
942 sizeof(Oid) * dbidalloc);
944 dbidlist[dbidused++] = HeapTupleGetOid(dbtup);
946 heap_endscan(dbscan);
947 heap_close(dbrel, AccessShareLock);
950 * Search the database hash table for dead databases and tell the
951 * collector to drop them as well.
953 hash_seq_init(&hstat, pgStatDBHash);
954 while ((dbentry = (PgStat_StatDBEntry *) hash_seq_search(&hstat)) != NULL)
956 Oid dbid = dbentry->databaseid;
958 for (i = 0; i < dbidused; i++)
960 if (dbidlist[i] == dbid)
967 if (dbid != InvalidOid)
970 pgstat_drop_database(dbid);
975 * Free the dbid list.
977 pfree((char *) dbidlist);
980 * Tell the caller how many removeable objects we found
987 * pgstat_drop_database() -
989 * Tell the collector that we just dropped a database.
990 * This is the only message that shouldn't get lost in space. Otherwise
991 * the collector will keep the statistics for the dead DB until his
992 * stats file got removed while the postmaster is down.
996 pgstat_drop_database(Oid databaseid)
998 PgStat_MsgDropdb msg;
1003 msg.m_databaseid = databaseid;
1005 pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_DROPDB);
1006 pgstat_send(&msg, sizeof(msg));
1011 * pgstat_reset_counters() -
1013 * Tell the statistics collector to reset counters for our database.
1017 pgstat_reset_counters(void)
1019 PgStat_MsgResetcounter msg;
1026 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1027 errmsg("must be superuser to reset statistics counters")));
1029 pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_RESETCOUNTER);
1030 pgstat_send(&msg, sizeof(msg));
1037 * Send some junk data to the collector to increase traffic.
1043 PgStat_MsgDummy msg;
1048 pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_DUMMY);
1049 pgstat_send(&msg, sizeof(msg));
1053 * Create or enlarge the pgStatTabstatMessages array
1056 more_tabstat_space(void)
1058 PgStat_MsgTabstat *newMessages;
1059 PgStat_MsgTabstat **msgArray;
1060 int newAlloc = pgStatTabstatAlloc + TABSTAT_QUANTUM;
1063 /* Create (another) quantum of message buffers */
1064 newMessages = (PgStat_MsgTabstat *)
1065 malloc(sizeof(PgStat_MsgTabstat) * TABSTAT_QUANTUM);
1066 if (newMessages == NULL)
1069 (errcode(ERRCODE_OUT_OF_MEMORY),
1070 errmsg("out of memory")));
1074 /* Create or enlarge the pointer array */
1075 if (pgStatTabstatMessages == NULL)
1076 msgArray = (PgStat_MsgTabstat **)
1077 malloc(sizeof(PgStat_MsgTabstat *) * newAlloc);
1079 msgArray = (PgStat_MsgTabstat **)
1080 realloc(pgStatTabstatMessages,
1081 sizeof(PgStat_MsgTabstat *) * newAlloc);
1082 if (msgArray == NULL)
1086 (errcode(ERRCODE_OUT_OF_MEMORY),
1087 errmsg("out of memory")));
1091 MemSet(newMessages, 0, sizeof(PgStat_MsgTabstat) * TABSTAT_QUANTUM);
1092 for (i = 0; i < TABSTAT_QUANTUM; i++)
1093 msgArray[pgStatTabstatAlloc + i] = newMessages++;
1094 pgStatTabstatMessages = msgArray;
1095 pgStatTabstatAlloc = newAlloc;
1101 * pgstat_initstats() -
1103 * Called from various places usually dealing with initialization
1104 * of Relation or Scan structures. The data placed into these
1105 * structures from here tell where later to count for buffer reads,
1106 * scans and tuples fetched.
1110 pgstat_initstats(PgStat_Info *stats, Relation rel)
1112 Oid rel_id = rel->rd_id;
1113 PgStat_TableEntry *useent;
1114 PgStat_MsgTabstat *tsmsg;
1119 * Initialize data not to count at all.
1121 stats->tabentry = NULL;
1122 stats->no_stats = FALSE;
1123 stats->heap_scan_counted = FALSE;
1124 stats->index_scan_counted = FALSE;
1126 if (pgStatSock < 0 ||
1127 !(pgstat_collect_tuplelevel ||
1128 pgstat_collect_blocklevel))
1130 stats->no_stats = TRUE;
1135 * Search the already-used message slots for this relation.
1137 for (mb = 0; mb < pgStatTabstatUsed; mb++)
1139 tsmsg = pgStatTabstatMessages[mb];
1141 for (i = tsmsg->m_nentries; --i >= 0; )
1143 if (tsmsg->m_entry[i].t_id == rel_id)
1145 stats->tabentry = (void *) &(tsmsg->m_entry[i]);
1150 if (tsmsg->m_nentries >= PGSTAT_NUM_TABENTRIES)
1154 * Not found, but found a message buffer with an empty slot
1155 * instead. Fine, let's use this one.
1157 i = tsmsg->m_nentries++;
1158 useent = &tsmsg->m_entry[i];
1159 MemSet(useent, 0, sizeof(PgStat_TableEntry));
1160 useent->t_id = rel_id;
1161 stats->tabentry = (void *) useent;
1166 * If we ran out of message buffers, we just allocate more.
1168 if (pgStatTabstatUsed >= pgStatTabstatAlloc)
1170 if (!more_tabstat_space())
1172 stats->no_stats = TRUE;
1175 Assert(pgStatTabstatUsed < pgStatTabstatAlloc);
1179 * Use the first entry of the next message buffer.
1181 mb = pgStatTabstatUsed++;
1182 tsmsg = pgStatTabstatMessages[mb];
1183 tsmsg->m_nentries = 1;
1184 useent = &tsmsg->m_entry[0];
1185 MemSet(useent, 0, sizeof(PgStat_TableEntry));
1186 useent->t_id = rel_id;
1187 stats->tabentry = (void *) useent;
1192 * pgstat_count_xact_commit() -
1194 * Called from access/transam/xact.c to count transaction commits.
1198 pgstat_count_xact_commit(void)
1200 if (!(pgstat_collect_querystring ||
1201 pgstat_collect_tuplelevel ||
1202 pgstat_collect_blocklevel))
1208 * If there was no relation activity yet, just make one existing
1209 * message buffer used without slots, causing the next report to tell
1210 * new xact-counters.
1212 if (pgStatTabstatAlloc == 0)
1214 if (!more_tabstat_space())
1217 if (pgStatTabstatUsed == 0)
1219 pgStatTabstatUsed++;
1220 pgStatTabstatMessages[0]->m_nentries = 0;
1226 * pgstat_count_xact_rollback() -
1228 * Called from access/transam/xact.c to count transaction rollbacks.
1232 pgstat_count_xact_rollback(void)
1234 if (!(pgstat_collect_querystring ||
1235 pgstat_collect_tuplelevel ||
1236 pgstat_collect_blocklevel))
1239 pgStatXactRollback++;
1242 * If there was no relation activity yet, just make one existing
1243 * message buffer used without slots, causing the next report to tell
1244 * new xact-counters.
1246 if (pgStatTabstatAlloc == 0)
1248 if (!more_tabstat_space())
1251 if (pgStatTabstatUsed == 0)
1253 pgStatTabstatUsed++;
1254 pgStatTabstatMessages[0]->m_nentries = 0;
1260 * pgstat_fetch_stat_dbentry() -
1262 * Support function for the SQL-callable pgstat* functions. Returns
1263 * the collected statistics for one database or NULL. NULL doesn't mean
1264 * that the database doesn't exist, it is just not yet known by the
1265 * collector, so the caller is better off to report ZERO instead.
1268 PgStat_StatDBEntry *
1269 pgstat_fetch_stat_dbentry(Oid dbid)
1271 PgStat_StatDBEntry *dbentry;
1274 * If not done for this transaction, read the statistics collector
1275 * stats file into some hash tables. Be careful with the
1276 * read_statsfile() call below!
1278 if (!TransactionIdEquals(pgStatDBHashXact, GetCurrentTransactionId()))
1280 pgstat_read_statsfile(&pgStatDBHash, MyDatabaseId,
1281 &pgStatBeTable, &pgStatNumBackends);
1282 pgStatDBHashXact = GetCurrentTransactionId();
1286 * Lookup the requested database
1288 dbentry = (PgStat_StatDBEntry *) hash_search(pgStatDBHash,
1291 if (dbentry == NULL)
1299 * pgstat_fetch_stat_tabentry() -
1301 * Support function for the SQL-callable pgstat* functions. Returns
1302 * the collected statistics for one table or NULL. NULL doesn't mean
1303 * that the table doesn't exist, it is just not yet known by the
1304 * collector, so the caller is better off to report ZERO instead.
1307 PgStat_StatTabEntry *
1308 pgstat_fetch_stat_tabentry(Oid relid)
1310 PgStat_StatDBEntry *dbentry;
1311 PgStat_StatTabEntry *tabentry;
1314 * If not done for this transaction, read the statistics collector
1315 * stats file into some hash tables. Be careful with the
1316 * read_statsfile() call below!
1318 if (!TransactionIdEquals(pgStatDBHashXact, GetCurrentTransactionId()))
1320 pgstat_read_statsfile(&pgStatDBHash, MyDatabaseId,
1321 &pgStatBeTable, &pgStatNumBackends);
1322 pgStatDBHashXact = GetCurrentTransactionId();
1326 * Lookup our database.
1328 dbentry = (PgStat_StatDBEntry *) hash_search(pgStatDBHash,
1329 (void *) &MyDatabaseId,
1331 if (dbentry == NULL)
1335 * Now inside the DB's table hash table lookup the requested one.
1337 if (dbentry->tables == NULL)
1339 tabentry = (PgStat_StatTabEntry *) hash_search(dbentry->tables,
1342 if (tabentry == NULL)
1350 * pgstat_fetch_stat_beentry() -
1352 * Support function for the SQL-callable pgstat* functions. Returns
1353 * the actual activity slot of one active backend. The caller is
1354 * responsible for a check if the actual user is permitted to see
1355 * that info (especially the querystring).
1358 PgStat_StatBeEntry *
1359 pgstat_fetch_stat_beentry(int beid)
1361 if (!TransactionIdEquals(pgStatDBHashXact, GetCurrentTransactionId()))
1363 pgstat_read_statsfile(&pgStatDBHash, MyDatabaseId,
1364 &pgStatBeTable, &pgStatNumBackends);
1365 pgStatDBHashXact = GetCurrentTransactionId();
1368 if (beid < 1 || beid > pgStatNumBackends)
1371 return &pgStatBeTable[beid - 1];
1376 * pgstat_fetch_stat_numbackends() -
1378 * Support function for the SQL-callable pgstat* functions. Returns
1379 * the maximum current backend id.
1383 pgstat_fetch_stat_numbackends(void)
1385 if (!TransactionIdEquals(pgStatDBHashXact, GetCurrentTransactionId()))
1387 pgstat_read_statsfile(&pgStatDBHash, MyDatabaseId,
1388 &pgStatBeTable, &pgStatNumBackends);
1389 pgStatDBHashXact = GetCurrentTransactionId();
1392 return pgStatNumBackends;
1397 /* ------------------------------------------------------------
1398 * Local support functions follow
1399 * ------------------------------------------------------------
1404 * pgstat_setheader() -
1406 * Set common header fields in a statistics message
1410 pgstat_setheader(PgStat_MsgHdr *hdr, int mtype)
1412 hdr->m_type = mtype;
1413 hdr->m_backendid = MyBackendId;
1414 hdr->m_procpid = MyProcPid;
1415 hdr->m_databaseid = MyDatabaseId;
1416 hdr->m_userid = GetSessionUserId();
1423 * Send out one statistics message to the collector
1427 pgstat_send(void *msg, int len)
1432 ((PgStat_MsgHdr *) msg)->m_size = len;
1434 send(pgStatSock, msg, len, 0);
1435 /* We deliberately ignore any error from send() */
1439 /* ------------------------------------------------------------
1440 * Local functions implementing the statistics collector itself follow
1441 *------------------------------------------------------------
1445 pgstat_mainInit(void)
1447 IsUnderPostmaster = true; /* we are a postmaster subprocess now */
1450 /* In EXEC case we will not have inherited these settings */
1451 IsPostmasterEnvironment = true;
1452 whereToSendOutput = None;
1454 /* Setup global context */
1455 MemoryContextInit(); /* before any elog'ing can occur */
1456 InitializeGUCOptions();
1459 MyProcPid = getpid(); /* reset MyProcPid */
1461 /* Lose the postmaster's on-exit routines */
1465 * Ignore all signals usually bound to some action in the postmaster,
1466 * except for SIGCHLD --- see pgstat_recvbuffer.
1468 pqsignal(SIGHUP, SIG_IGN);
1469 pqsignal(SIGINT, SIG_IGN);
1470 pqsignal(SIGTERM, SIG_IGN);
1471 pqsignal(SIGQUIT, SIG_IGN);
1472 pqsignal(SIGALRM, SIG_IGN);
1473 pqsignal(SIGPIPE, SIG_IGN);
1474 pqsignal(SIGUSR1, SIG_IGN);
1475 pqsignal(SIGUSR2, SIG_IGN);
1476 pqsignal(SIGCHLD, pgstat_die);
1477 pqsignal(SIGTTIN, SIG_DFL);
1478 pqsignal(SIGTTOU, SIG_DFL);
1479 pqsignal(SIGCONT, SIG_DFL);
1480 pqsignal(SIGWINCH, SIG_DFL);
1487 * Start up the statistics collector itself. This is the body of the
1488 * postmaster child process.
1491 NON_EXEC_STATIC void
1492 pgstat_main(PGSTAT_FORK_ARGS)
1494 pgstat_mainInit(); /* Note: for *both* EXEC_BACKEND and regular cases */
1496 pgstat_parseArgs(argc,argv);
1500 * Close the writing end of the postmaster pipe, so we'll see it
1501 * closing when the postmaster terminates and can terminate as well.
1503 closesocket(pgStatPmPipe[1]);
1504 pgStatPmPipe[1] = -1;
1505 closesocket(pgStatCollectorPmPipe[1]);
1506 pgStatCollectorPmPipe[1] = -1;
1509 * Start a buffering process to read from the socket, so we have a
1510 * little more time to process incoming messages.
1512 * NOTE: the process structure is: postmaster is parent of buffer process
1513 * is parent of collector process. This way, the buffer can detect
1514 * collector failure via SIGCHLD, whereas otherwise it wouldn't notice
1515 * collector failure until it tried to write on the pipe. That would
1516 * mean that after the postmaster started a new collector, we'd have
1517 * two buffer processes competing to read from the UDP socket --- not
1520 if (pgpipe(pgStatPipe) < 0)
1523 (errcode_for_socket_access(),
1524 errmsg("could not create pipe for statistics buffer: %m")));
1529 /* child becomes collector process */
1530 switch (pgstat_forkexec(STAT_PROC_COLLECTOR))
1537 (errmsg("could not fork statistics collector: %m")));
1540 #ifndef EXEC_BACKEND
1542 /* child becomes collector process */
1548 /* parent becomes buffer process */
1549 closesocket(pgStatPipe[0]);
1550 pgstat_recvbuffer();
1556 NON_EXEC_STATIC void
1557 pgstat_mainChild(PGSTAT_FORK_ARGS)
1565 struct timeval timeout;
1566 struct timeval next_statwrite;
1567 bool need_statwrite;
1571 pgstat_mainInit(); /* Note: only in EXEC_BACKEND case */
1572 pgstat_parseArgs(argc,argv);
1574 MyProcPid = getpid(); /* reset MyProcPid */
1577 closesocket(pgStatPipe[1]);
1578 closesocket(pgStatSock);
1579 pmPipe = pgStatCollectorPmPipe[0];
1582 * In the child we can have default SIGCHLD handling (in case we want
1583 * to call system() here...)
1585 pqsignal(SIGCHLD, SIG_DFL);
1588 * Identify myself via ps
1590 init_ps_display("stats collector process", "", "");
1594 * Arrange to write the initial status file right away
1596 gettimeofday(&next_statwrite, NULL);
1597 need_statwrite = TRUE;
1600 * Read in an existing statistics stats file or initialize the stats
1603 pgStatRunningInCollector = TRUE;
1604 pgstat_read_statsfile(&pgStatDBHash, InvalidOid, NULL, NULL);
1607 * Create the dead backend hashtable
1609 memset(&hash_ctl, 0, sizeof(hash_ctl));
1610 hash_ctl.keysize = sizeof(int);
1611 hash_ctl.entrysize = sizeof(PgStat_StatBeDead);
1612 hash_ctl.hash = tag_hash;
1613 pgStatBeDead = hash_create("Dead Backends", PGSTAT_BE_HASH_SIZE,
1614 &hash_ctl, HASH_ELEM | HASH_FUNCTION);
1615 if (pgStatBeDead == NULL)
1617 /* assume the problem is out-of-memory */
1619 (errcode(ERRCODE_OUT_OF_MEMORY),
1620 errmsg("out of memory in statistics collector --- abort")));
1625 * Create the known backends table
1627 pgStatBeTable = (PgStat_StatBeEntry *) malloc(
1628 sizeof(PgStat_StatBeEntry) * MaxBackends);
1629 if (pgStatBeTable == NULL)
1632 (errcode(ERRCODE_OUT_OF_MEMORY),
1633 errmsg("out of memory in statistics collector --- abort")));
1636 memset(pgStatBeTable, 0, sizeof(PgStat_StatBeEntry) * MaxBackends);
1638 readPipe = pgStatPipe[0];
1641 * Process incoming messages and handle all the reporting stuff until
1642 * there are no more messages.
1647 * If we need to write the status file again (there have been
1648 * changes in the statistics since we wrote it last) calculate the
1649 * timeout until we have to do so.
1655 gettimeofday(&now, NULL);
1656 /* avoid assuming that tv_sec is signed */
1657 if (now.tv_sec > next_statwrite.tv_sec ||
1658 (now.tv_sec == next_statwrite.tv_sec &&
1659 now.tv_usec >= next_statwrite.tv_usec))
1662 timeout.tv_usec = 0;
1666 timeout.tv_sec = next_statwrite.tv_sec - now.tv_sec;
1667 timeout.tv_usec = next_statwrite.tv_usec - now.tv_usec;
1668 if (timeout.tv_usec < 0)
1671 timeout.tv_usec += 1000000;
1677 * Setup the descriptor set for select(2)
1680 FD_SET(readPipe, &rfds);
1683 * Now wait for something to do.
1685 nready = select(readPipe+1, &rfds, NULL, NULL,
1686 (need_statwrite) ? &timeout : NULL);
1692 (errcode_for_socket_access(),
1693 errmsg("select() failed in statistics collector: %m")));
1698 * If there are no descriptors ready, our timeout for writing the
1699 * stats file happened.
1703 pgstat_write_statsfile();
1704 need_statwrite = FALSE;
1710 * Check if there is a new statistics message to collect.
1712 if (FD_ISSET(readPipe, &rfds))
1715 * We may need to issue multiple read calls in case the buffer
1716 * process didn't write the message in a single write, which
1717 * is possible since it dumps its buffer bytewise. In any
1718 * case, we'd need two reads since we don't know the message
1722 int targetlen = sizeof(PgStat_MsgHdr); /* initial */
1723 bool pipeEOF = false;
1725 while (nread < targetlen)
1727 len = piperead(readPipe, ((char *) &msg) + nread,
1734 (errcode_for_socket_access(),
1735 errmsg("could not read from statistics collector pipe: %m")));
1738 if (len == 0) /* EOF on the pipe! */
1744 if (nread == sizeof(PgStat_MsgHdr))
1746 /* we have the header, compute actual msg length */
1747 targetlen = msg.msg_hdr.m_size;
1748 if (targetlen < (int) sizeof(PgStat_MsgHdr) ||
1749 targetlen > (int) sizeof(msg))
1752 * Bogus message length implies that we got out of
1753 * sync with the buffer process somehow. Abort so
1754 * that we can restart both processes.
1757 (errmsg("invalid statistics message length")));
1764 * EOF on the pipe implies that the buffer process exited.
1765 * Fall out of outer loop.
1771 * Distribute the message to the specific function handling
1774 switch (msg.msg_hdr.m_type)
1776 case PGSTAT_MTYPE_DUMMY:
1779 case PGSTAT_MTYPE_BESTART:
1780 pgstat_recv_bestart((PgStat_MsgBestart *) &msg, nread);
1783 case PGSTAT_MTYPE_BETERM:
1784 pgstat_recv_beterm((PgStat_MsgBeterm *) &msg, nread);
1787 case PGSTAT_MTYPE_TABSTAT:
1788 pgstat_recv_tabstat((PgStat_MsgTabstat *) &msg, nread);
1791 case PGSTAT_MTYPE_TABPURGE:
1792 pgstat_recv_tabpurge((PgStat_MsgTabpurge *) &msg, nread);
1795 case PGSTAT_MTYPE_ACTIVITY:
1796 pgstat_recv_activity((PgStat_MsgActivity *) &msg, nread);
1799 case PGSTAT_MTYPE_DROPDB:
1800 pgstat_recv_dropdb((PgStat_MsgDropdb *) &msg, nread);
1803 case PGSTAT_MTYPE_RESETCOUNTER:
1804 pgstat_recv_resetcounter((PgStat_MsgResetcounter *) &msg,
1813 * Globally count messages.
1815 pgStatNumMessages++;
1818 * If this is the first message after we wrote the stats file
1819 * the last time, setup the timeout that it'd be written.
1821 if (!need_statwrite)
1823 gettimeofday(&next_statwrite, NULL);
1824 next_statwrite.tv_usec += ((PGSTAT_STAT_INTERVAL) * 1000);
1825 next_statwrite.tv_sec += (next_statwrite.tv_usec / 1000000);
1826 next_statwrite.tv_usec %= 1000000;
1827 need_statwrite = TRUE;
1832 * Note that we do NOT check for postmaster exit inside the loop;
1833 * only EOF on the buffer pipe causes us to fall out. This
1834 * ensures we don't exit prematurely if there are still a few
1835 * messages in the buffer or pipe at postmaster shutdown.
1840 * Okay, we saw EOF on the buffer pipe, so there are no more messages
1841 * to process. If the buffer process quit because of postmaster
1842 * shutdown, we want to save the final stats to reuse at next startup.
1843 * But if the buffer process failed, it seems best not to (there may
1844 * even now be a new collector firing up, and we don't want it to read
1845 * a partially- rewritten stats file). We can tell whether the
1846 * postmaster is still alive by checking to see if the postmaster pipe
1847 * is still open. If it is read-ready (ie, EOF), the postmaster must
1851 FD_SET(pmPipe, &rfds);
1853 timeout.tv_usec = 0;
1854 nready = select(pmPipe+1,&rfds,NULL,NULL,&timeout);
1855 if (nready > 0 && FD_ISSET(pmPipe, &rfds))
1856 pgstat_write_statsfile();
1861 * pgstat_recvbuffer() -
1863 * This is the body of the separate buffering process. Its only
1864 * purpose is to receive messages from the UDP socket as fast as
1865 * possible and forward them over a pipe into the collector itself.
1866 * If the collector is slow to absorb messages, they are buffered here.
1870 pgstat_recvbuffer(void)
1874 int writePipe = pgStatPipe[1];
1875 int pmPipe = pgStatPmPipe[0];
1881 PgStat_Msg input_buffer;
1883 int msg_send = 0; /* next send index in buffer */
1884 int msg_recv = 0; /* next receive index */
1885 int msg_have = 0; /* number of bytes stored */
1886 bool overflow = false;
1889 * Identify myself via ps
1891 init_ps_display("stats buffer process", "", "");
1895 * We want to die if our child collector process does. There are two
1896 * ways we might notice that it has died: receive SIGCHLD, or get a
1897 * write failure on the pipe leading to the child. We can set SIGPIPE
1898 * to kill us here. Our SIGCHLD handler was already set up before we
1899 * forked (must do it that way, else it's a race condition).
1901 pqsignal(SIGPIPE, SIG_DFL);
1902 PG_SETMASK(&UnBlockSig);
1905 * Set the write pipe to nonblock mode, so that we cannot block when
1906 * the collector falls behind.
1908 if (!set_noblock(writePipe))
1911 (errcode_for_socket_access(),
1912 errmsg("could not set statistics collector pipe to nonblocking mode: %m")));
1917 * Allocate the message buffer
1919 msgbuffer = (char *) malloc(PGSTAT_RECVBUFFERSZ);
1920 if (msgbuffer == NULL)
1923 (errcode(ERRCODE_OUT_OF_MEMORY),
1924 errmsg("out of memory in statistics collector --- abort")));
1938 * As long as we have buffer space we add the socket to the read
1941 if (msg_have <= (int) (PGSTAT_RECVBUFFERSZ - sizeof(PgStat_Msg)))
1943 FD_SET(pgStatSock, &rfds);
1952 (errmsg("statistics buffer is full")));
1958 * If we have messages to write out, we add the pipe to the write
1959 * descriptor set. Otherwise, we check if the postmaster might
1964 FD_SET(writePipe, &wfds);
1965 if (writePipe > maxfd)
1970 FD_SET(pmPipe, &rfds);
1976 * Wait for some work to do.
1978 nready = select(maxfd + 1, &rfds, &wfds, NULL, NULL);
1984 (errcode_for_socket_access(),
1985 errmsg("select() failed in statistics buffer: %m")));
1990 * If there is a message on the socket, read it and check for
1993 if (FD_ISSET(pgStatSock, &rfds))
1995 len = recv(pgStatSock, (char *) &input_buffer,
1996 sizeof(PgStat_Msg), 0);
2000 (errcode_for_socket_access(),
2001 errmsg("could not read statistics message: %m")));
2006 * We ignore messages that are smaller than our common header
2008 if (len < sizeof(PgStat_MsgHdr))
2012 * The received length must match the length in the header
2014 if (input_buffer.msg_hdr.m_size != len)
2018 * O.K. - we accept this message. Copy it to the circular
2024 xfr = PGSTAT_RECVBUFFERSZ - msg_recv;
2028 memcpy(msgbuffer + msg_recv,
2029 ((char *) &input_buffer) + frm,
2032 if (msg_recv == PGSTAT_RECVBUFFERSZ)
2041 * If the collector is ready to receive, write some data into his
2042 * pipe. We may or may not be able to write all that we have.
2044 * NOTE: if what we have is less than PIPE_BUF bytes but more than
2045 * the space available in the pipe buffer, most kernels will
2046 * refuse to write any of it, and will return EAGAIN. This means
2047 * we will busy-loop until the situation changes (either because
2048 * the collector caught up, or because more data arrives so that
2049 * we have more than PIPE_BUF bytes buffered). This is not good,
2050 * but is there any way around it? We have no way to tell when
2051 * the collector has caught up...
2053 if (FD_ISSET(writePipe, &wfds))
2055 xfr = PGSTAT_RECVBUFFERSZ - msg_send;
2059 len = pipewrite(writePipe, msgbuffer + msg_send, xfr);
2062 if (errno == EINTR || errno == EAGAIN)
2063 continue; /* not enough space in pipe */
2065 (errcode_for_socket_access(),
2066 errmsg("could not write to statistics collector pipe: %m")));
2069 /* NB: len < xfr is okay */
2071 if (msg_send == PGSTAT_RECVBUFFERSZ)
2077 * Make sure we forwarded all messages before we check for
2078 * Postmaster termination.
2080 if (msg_have != 0 || FD_ISSET(pgStatSock, &rfds))
2084 * If the pipe from the postmaster is ready for reading, the
2085 * kernel must have closed it on exit() (the postmaster never
2086 * really writes to it). So we've done our job.
2088 if (FD_ISSET(pmPipe, &rfds))
2094 pgstat_die(SIGNAL_ARGS)
2101 * pgstat_add_backend() -
2103 * Support function to keep our backend list up to date.
2107 pgstat_add_backend(PgStat_MsgHdr *msg)
2109 PgStat_StatDBEntry *dbentry;
2110 PgStat_StatBeEntry *beentry;
2111 PgStat_StatBeDead *deadbe;
2115 * Check that the backend ID is valid
2117 if (msg->m_backendid < 1 || msg->m_backendid > MaxBackends)
2120 (errmsg("invalid server process ID %d", msg->m_backendid)));
2125 * Get the slot for this backendid.
2127 beentry = &pgStatBeTable[msg->m_backendid - 1];
2128 if (beentry->databaseid != InvalidOid)
2131 * If the slot contains the PID of this backend, everything is
2132 * fine and we got nothing to do.
2134 if (beentry->procpid == msg->m_procpid)
2139 * Lookup if this backend is known to be dead. This can be caused due
2140 * to messages arriving in the wrong order - i.e. Postmaster's BETERM
2141 * message might have arrived before we received all the backends
2142 * stats messages, or even a new backend with the same backendid was
2143 * faster in sending his BESTART.
2145 * If the backend is known to be dead, we ignore this add.
2147 deadbe = (PgStat_StatBeDead *) hash_search(pgStatBeDead,
2148 (void *) &(msg->m_procpid),
2154 * Backend isn't known to be dead. If it's slot is currently used, we
2155 * have to kick out the old backend.
2157 if (beentry->databaseid != InvalidOid)
2158 pgstat_sub_backend(beentry->procpid);
2161 * Put this new backend into the slot.
2163 beentry->databaseid = msg->m_databaseid;
2164 beentry->procpid = msg->m_procpid;
2165 beentry->userid = msg->m_userid;
2166 beentry->activity_start_sec = 0;
2167 beentry->activity_start_usec = 0;
2168 MemSet(beentry->activity, 0, PGSTAT_ACTIVITY_SIZE);
2171 * Lookup or create the database entry for this backends DB.
2173 dbentry = (PgStat_StatDBEntry *) hash_search(pgStatDBHash,
2174 (void *) &(msg->m_databaseid),
2175 HASH_ENTER, &found);
2176 if (dbentry == NULL)
2179 (errcode(ERRCODE_OUT_OF_MEMORY),
2180 errmsg("out of memory in statistics collector --- abort")));
2185 * If not found, initialize the new one.
2191 dbentry->tables = NULL;
2192 dbentry->n_xact_commit = 0;
2193 dbentry->n_xact_rollback = 0;
2194 dbentry->n_blocks_fetched = 0;
2195 dbentry->n_blocks_hit = 0;
2196 dbentry->n_connects = 0;
2197 dbentry->destroy = 0;
2199 memset(&hash_ctl, 0, sizeof(hash_ctl));
2200 hash_ctl.keysize = sizeof(Oid);
2201 hash_ctl.entrysize = sizeof(PgStat_StatTabEntry);
2202 hash_ctl.hash = tag_hash;
2203 dbentry->tables = hash_create("Per-database table",
2204 PGSTAT_TAB_HASH_SIZE,
2206 HASH_ELEM | HASH_FUNCTION);
2207 if (dbentry->tables == NULL)
2209 /* assume the problem is out-of-memory */
2211 (errcode(ERRCODE_OUT_OF_MEMORY),
2212 errmsg("out of memory in statistics collector --- abort")));
2218 * Count number of connects to the database
2220 dbentry->n_connects++;
2227 * pgstat_sub_backend() -
2229 * Remove a backend from the actual backends list.
2233 pgstat_sub_backend(int procpid)
2236 PgStat_StatBeDead *deadbe;
2240 * Search in the known-backends table for the slot containing this
2243 for (i = 0; i < MaxBackends; i++)
2245 if (pgStatBeTable[i].databaseid != InvalidOid &&
2246 pgStatBeTable[i].procpid == procpid)
2249 * That's him. Add an entry to the known to be dead backends.
2250 * Due to possible misorder in the arrival of UDP packets it's
2251 * possible that even if we know the backend is dead, there
2252 * could still be messages queued that arrive later. Those
2253 * messages must not cause our number of backends statistics
2254 * to get screwed up, so we remember for a couple of seconds
2255 * that this PID is dead and ignore them (only the counting of
2256 * backends, not the table access stats they sent).
2258 deadbe = (PgStat_StatBeDead *) hash_search(pgStatBeDead,
2265 (errcode(ERRCODE_OUT_OF_MEMORY),
2266 errmsg("out of memory in statistics collector --- abort")));
2271 deadbe->backendid = i + 1;
2272 deadbe->destroy = PGSTAT_DESTROY_COUNT;
2276 * Declare the backend slot empty.
2278 pgStatBeTable[i].databaseid = InvalidOid;
2284 * No big problem if not found. This can happen if UDP messages arrive
2285 * out of order here.
2291 * pgstat_write_statsfile() -
2297 pgstat_write_statsfile(void)
2299 HASH_SEQ_STATUS hstat;
2300 HASH_SEQ_STATUS tstat;
2301 PgStat_StatDBEntry *dbentry;
2302 PgStat_StatTabEntry *tabentry;
2303 PgStat_StatBeDead *deadbe;
2308 * Open the statistics temp file to write out the current values.
2310 fpout = fopen(pgStat_tmpfname, PG_BINARY_W);
2314 (errcode_for_file_access(),
2315 errmsg("could not open temporary statistics file \"%s\": %m",
2321 * Walk through the database table.
2323 hash_seq_init(&hstat, pgStatDBHash);
2324 while ((dbentry = (PgStat_StatDBEntry *) hash_seq_search(&hstat)) != NULL)
2327 * If this database is marked destroyed, count down and do so if
2330 if (dbentry->destroy > 0)
2332 if (--(dbentry->destroy) == 0)
2334 if (dbentry->tables != NULL)
2335 hash_destroy(dbentry->tables);
2337 if (hash_search(pgStatDBHash,
2338 (void *) &(dbentry->databaseid),
2339 HASH_REMOVE, NULL) == NULL)
2342 (errmsg("database hash table corrupted "
2343 "during cleanup --- abort")));
2349 * Don't include statistics for it.
2355 * Write out the DB line including the number of life backends.
2358 fwrite(dbentry, sizeof(PgStat_StatDBEntry), 1, fpout);
2361 * Walk through the databases access stats per table.
2363 hash_seq_init(&tstat, dbentry->tables);
2364 while ((tabentry = (PgStat_StatTabEntry *) hash_seq_search(&tstat)) != NULL)
2367 * If table entry marked for destruction, same as above for
2368 * the database entry.
2370 if (tabentry->destroy > 0)
2372 if (--(tabentry->destroy) == 0)
2374 if (hash_search(dbentry->tables,
2375 (void *) &(tabentry->tableid),
2376 HASH_REMOVE, NULL) == NULL)
2379 (errmsg("tables hash table for "
2380 "database %u corrupted during "
2381 "cleanup --- abort",
2382 dbentry->databaseid)));
2390 * At least we think this is still a life table. Print it's
2394 fwrite(tabentry, sizeof(PgStat_StatTabEntry), 1, fpout);
2398 * Mark the end of this DB
2404 * Write out the known running backends to the stats file.
2408 fwrite(&i, sizeof(i), 1, fpout);
2410 for (i = 0; i < MaxBackends; i++)
2412 if (pgStatBeTable[i].databaseid != InvalidOid)
2415 fwrite(&pgStatBeTable[i], sizeof(PgStat_StatBeEntry), 1, fpout);
2420 * No more output to be done. Close the temp file and replace the old
2421 * pgstat.stat with it.
2424 if (fclose(fpout) < 0)
2427 (errcode_for_file_access(),
2428 errmsg("could not close temporary statistics file \"%s\": %m",
2433 if (rename(pgStat_tmpfname, pgStat_fname) < 0)
2436 (errcode_for_file_access(),
2437 errmsg("could not rename temporary statistics file \"%s\" to \"%s\": %m",
2438 pgStat_tmpfname, pgStat_fname)));
2443 * Clear out the dead backends table
2445 hash_seq_init(&hstat, pgStatBeDead);
2446 while ((deadbe = (PgStat_StatBeDead *) hash_seq_search(&hstat)) != NULL)
2449 * Count down the destroy delay and remove entries where it
2452 if (--(deadbe->destroy) <= 0)
2454 if (hash_search(pgStatBeDead,
2455 (void *) &(deadbe->procpid),
2456 HASH_REMOVE, NULL) == NULL)
2459 (errmsg("dead-server-process hash table corrupted "
2460 "during cleanup --- abort")));
2469 * pgstat_read_statsfile() -
2471 * Reads in an existing statistics collector and initializes the
2472 * databases hash table (who's entries point to the tables hash tables)
2473 * and the current backend table.
2477 pgstat_read_statsfile(HTAB **dbhash, Oid onlydb,
2478 PgStat_StatBeEntry **betab, int *numbackends)
2480 PgStat_StatDBEntry *dbentry;
2481 PgStat_StatDBEntry dbbuf;
2482 PgStat_StatTabEntry *tabentry;
2483 PgStat_StatTabEntry tabbuf;
2485 HTAB *tabhash = NULL;
2487 int maxbackends = 0;
2488 int havebackends = 0;
2490 MemoryContext use_mcxt;
2494 * If running in the collector we use the DynaHashCxt memory context.
2495 * If running in a backend, we use the TopTransactionContext instead,
2496 * so the caller must only know the last XactId when this call
2497 * happened to know if his tables are still valid or already gone!
2499 if (pgStatRunningInCollector)
2506 use_mcxt = TopTransactionContext;
2507 mcxt_flags = HASH_CONTEXT;
2511 * Create the DB hashtable
2513 memset(&hash_ctl, 0, sizeof(hash_ctl));
2514 hash_ctl.keysize = sizeof(Oid);
2515 hash_ctl.entrysize = sizeof(PgStat_StatDBEntry);
2516 hash_ctl.hash = tag_hash;
2517 hash_ctl.hcxt = use_mcxt;
2518 *dbhash = hash_create("Databases hash", PGSTAT_DB_HASH_SIZE, &hash_ctl,
2519 HASH_ELEM | HASH_FUNCTION | mcxt_flags);
2520 if (*dbhash == NULL)
2522 /* assume the problem is out-of-memory */
2523 if (pgStatRunningInCollector)
2526 (errcode(ERRCODE_OUT_OF_MEMORY),
2527 errmsg("out of memory in statistics collector --- abort")));
2530 /* in backend, can do normal error */
2532 (errcode(ERRCODE_OUT_OF_MEMORY),
2533 errmsg("out of memory")));
2537 * Initialize the number of known backends to zero, just in case we do
2538 * a silent error return below.
2540 if (numbackends != NULL)
2546 * Try to open the status file. If it doesn't exist, the backends
2547 * simply return zero for anything and the collector simply starts
2548 * from scratch with empty counters.
2550 if ((fpin = fopen(pgStat_fname, PG_BINARY_R)) == NULL)
2554 * We found an existing collector stats file. Read it and put all the
2555 * hashtable entries into place.
2559 switch (fgetc(fpin))
2562 * 'D' A PgStat_StatDBEntry struct describing a database
2563 * follows. Subsequently, zero to many 'T' entries will
2564 * follow until a 'd' is encountered.
2567 if (fread(&dbbuf, 1, sizeof(dbbuf), fpin) != sizeof(dbbuf))
2569 ereport(pgStatRunningInCollector ? LOG : WARNING,
2570 (errmsg("corrupted pgstat.stat file")));
2576 * Add to the DB hash
2578 dbentry = (PgStat_StatDBEntry *) hash_search(*dbhash,
2579 (void *) &dbbuf.databaseid,
2582 if (dbentry == NULL)
2584 if (pgStatRunningInCollector)
2587 (errcode(ERRCODE_OUT_OF_MEMORY),
2588 errmsg("out of memory in statistics collector --- abort")));
2595 (errcode(ERRCODE_OUT_OF_MEMORY),
2596 errmsg("out of memory")));
2601 ereport(pgStatRunningInCollector ? LOG : WARNING,
2602 (errmsg("corrupted pgstat.stat file")));
2607 memcpy(dbentry, &dbbuf, sizeof(PgStat_StatDBEntry));
2608 dbentry->tables = NULL;
2609 dbentry->destroy = 0;
2610 dbentry->n_backends = 0;
2613 * Don't collect tables if not the requested DB
2615 if (onlydb != InvalidOid && onlydb != dbbuf.databaseid)
2618 memset(&hash_ctl, 0, sizeof(hash_ctl));
2619 hash_ctl.keysize = sizeof(Oid);
2620 hash_ctl.entrysize = sizeof(PgStat_StatTabEntry);
2621 hash_ctl.hash = tag_hash;
2622 hash_ctl.hcxt = use_mcxt;
2623 dbentry->tables = hash_create("Per-database table",
2624 PGSTAT_TAB_HASH_SIZE,
2626 HASH_ELEM | HASH_FUNCTION | mcxt_flags);
2627 if (dbentry->tables == NULL)
2629 /* assume the problem is out-of-memory */
2630 if (pgStatRunningInCollector)
2633 (errcode(ERRCODE_OUT_OF_MEMORY),
2634 errmsg("out of memory in statistics collector --- abort")));
2637 /* in backend, can do normal error */
2640 (errcode(ERRCODE_OUT_OF_MEMORY),
2641 errmsg("out of memory")));
2645 * Arrange that following 'T's add entries to this
2646 * databases tables hash table.
2648 tabhash = dbentry->tables;
2652 * 'd' End of this database.
2659 * 'T' A PgStat_StatTabEntry follows.
2662 if (fread(&tabbuf, 1, sizeof(tabbuf), fpin) != sizeof(tabbuf))
2664 ereport(pgStatRunningInCollector ? LOG : WARNING,
2665 (errmsg("corrupted pgstat.stat file")));
2671 * Skip if table belongs to a not requested database.
2673 if (tabhash == NULL)
2676 tabentry = (PgStat_StatTabEntry *) hash_search(tabhash,
2677 (void *) &tabbuf.tableid,
2678 HASH_ENTER, &found);
2679 if (tabentry == NULL)
2681 if (pgStatRunningInCollector)
2684 (errcode(ERRCODE_OUT_OF_MEMORY),
2685 errmsg("out of memory in statistics collector --- abort")));
2688 /* in backend, can do normal error */
2691 (errcode(ERRCODE_OUT_OF_MEMORY),
2692 errmsg("out of memory")));
2697 ereport(pgStatRunningInCollector ? LOG : WARNING,
2698 (errmsg("corrupted pgstat.stat file")));
2703 memcpy(tabentry, &tabbuf, sizeof(tabbuf));
2707 * 'M' The maximum number of backends to expect follows.
2710 if (betab == NULL || numbackends == NULL)
2715 if (fread(&maxbackends, 1, sizeof(maxbackends), fpin) !=
2716 sizeof(maxbackends))
2718 ereport(pgStatRunningInCollector ? LOG : WARNING,
2719 (errmsg("corrupted pgstat.stat file")));
2723 if (maxbackends == 0)
2730 * Allocate space (in TopTransactionContext too) for the
2733 if (use_mcxt == NULL)
2734 *betab = (PgStat_StatBeEntry *) malloc(
2735 sizeof(PgStat_StatBeEntry) * maxbackends);
2737 *betab = (PgStat_StatBeEntry *) MemoryContextAlloc(
2739 sizeof(PgStat_StatBeEntry) * maxbackends);
2743 * 'B' A PgStat_StatBeEntry follows.
2746 if (betab == NULL || numbackends == NULL)
2758 * Read it directly into the table.
2760 if (fread(&(*betab)[havebackends], 1,
2761 sizeof(PgStat_StatBeEntry), fpin) !=
2762 sizeof(PgStat_StatBeEntry))
2764 ereport(pgStatRunningInCollector ? LOG : WARNING,
2765 (errmsg("corrupted pgstat.stat file")));
2771 * Count backends per database here.
2773 dbentry = (PgStat_StatDBEntry *) hash_search(*dbhash,
2774 (void *) &((*betab)[havebackends].databaseid),
2777 dbentry->n_backends++;
2780 if (numbackends != 0)
2781 *numbackends = havebackends;
2782 if (havebackends >= maxbackends)
2790 * 'E' The EOF marker of a complete stats file.
2797 ereport(pgStatRunningInCollector ? LOG : WARNING,
2798 (errmsg("corrupted pgstat.stat file")));
2809 * pgstat_recv_bestart() -
2811 * Process a backend starup message.
2815 pgstat_recv_bestart(PgStat_MsgBestart *msg, int len)
2817 pgstat_add_backend(&msg->m_hdr);
2822 * pgstat_recv_beterm() -
2824 * Process a backend termination message.
2828 pgstat_recv_beterm(PgStat_MsgBeterm *msg, int len)
2830 pgstat_sub_backend(msg->m_hdr.m_procpid);
2835 * pgstat_recv_activity() -
2837 * Remember what the backend is doing.
2841 pgstat_recv_activity(PgStat_MsgActivity *msg, int len)
2843 PgStat_StatBeEntry *entry;
2846 * Here we check explicitly for 0 return, since we don't want to
2847 * mangle the activity of an active backend by a delayed packed from a
2850 if (pgstat_add_backend(&msg->m_hdr) != 0)
2853 entry = &(pgStatBeTable[msg->m_hdr.m_backendid - 1]);
2855 strncpy(entry->activity, msg->m_what, PGSTAT_ACTIVITY_SIZE);
2857 entry->activity_start_sec =
2858 GetCurrentAbsoluteTimeUsec(&entry->activity_start_usec);
2863 * pgstat_recv_tabstat() -
2865 * Count what the backend has done.
2869 pgstat_recv_tabstat(PgStat_MsgTabstat *msg, int len)
2871 PgStat_TableEntry *tabmsg = &(msg->m_entry[0]);
2872 PgStat_StatDBEntry *dbentry;
2873 PgStat_StatTabEntry *tabentry;
2878 * Make sure the backend is counted for.
2880 if (pgstat_add_backend(&msg->m_hdr) < 0)
2884 * Lookup the database in the hashtable.
2886 dbentry = (PgStat_StatDBEntry *) hash_search(pgStatDBHash,
2887 (void *) &(msg->m_hdr.m_databaseid),
2893 * If the database is marked for destroy, this is a delayed UDP packet
2894 * and not worth being counted.
2896 if (dbentry->destroy > 0)
2899 dbentry->n_xact_commit += (PgStat_Counter) (msg->m_xact_commit);
2900 dbentry->n_xact_rollback += (PgStat_Counter) (msg->m_xact_rollback);
2903 * Process all table entries in the message.
2905 for (i = 0; i < msg->m_nentries; i++)
2907 tabentry = (PgStat_StatTabEntry *) hash_search(dbentry->tables,
2908 (void *) &(tabmsg[i].t_id),
2909 HASH_ENTER, &found);
2910 if (tabentry == NULL)
2913 (errcode(ERRCODE_OUT_OF_MEMORY),
2914 errmsg("out of memory in statistics collector --- abort")));
2921 * If it's a new table entry, initialize counters to the
2922 * values we just got.
2924 tabentry->numscans = tabmsg[i].t_numscans;
2925 tabentry->tuples_returned = tabmsg[i].t_tuples_returned;
2926 tabentry->tuples_fetched = tabmsg[i].t_tuples_fetched;
2927 tabentry->tuples_inserted = tabmsg[i].t_tuples_inserted;
2928 tabentry->tuples_updated = tabmsg[i].t_tuples_updated;
2929 tabentry->tuples_deleted = tabmsg[i].t_tuples_deleted;
2930 tabentry->blocks_fetched = tabmsg[i].t_blocks_fetched;
2931 tabentry->blocks_hit = tabmsg[i].t_blocks_hit;
2933 tabentry->destroy = 0;
2938 * Otherwise add the values to the existing entry.
2940 tabentry->numscans += tabmsg[i].t_numscans;
2941 tabentry->tuples_returned += tabmsg[i].t_tuples_returned;
2942 tabentry->tuples_fetched += tabmsg[i].t_tuples_fetched;
2943 tabentry->tuples_inserted += tabmsg[i].t_tuples_inserted;
2944 tabentry->tuples_updated += tabmsg[i].t_tuples_updated;
2945 tabentry->tuples_deleted += tabmsg[i].t_tuples_deleted;
2946 tabentry->blocks_fetched += tabmsg[i].t_blocks_fetched;
2947 tabentry->blocks_hit += tabmsg[i].t_blocks_hit;
2951 * And add the block IO to the database entry.
2953 dbentry->n_blocks_fetched += tabmsg[i].t_blocks_fetched;
2954 dbentry->n_blocks_hit += tabmsg[i].t_blocks_hit;
2960 * pgstat_recv_tabpurge() -
2962 * Arrange for dead table removal.
2966 pgstat_recv_tabpurge(PgStat_MsgTabpurge *msg, int len)
2968 PgStat_StatDBEntry *dbentry;
2969 PgStat_StatTabEntry *tabentry;
2973 * Make sure the backend is counted for.
2975 if (pgstat_add_backend(&msg->m_hdr) < 0)
2979 * Lookup the database in the hashtable.
2981 dbentry = (PgStat_StatDBEntry *) hash_search(pgStatDBHash,
2982 (void *) &(msg->m_hdr.m_databaseid),
2988 * If the database is marked for destroy, this is a delayed UDP packet
2989 * and the tables will go away at DB destruction.
2991 if (dbentry->destroy > 0)
2995 * Process all table entries in the message.
2997 for (i = 0; i < msg->m_nentries; i++)
2999 tabentry = (PgStat_StatTabEntry *) hash_search(dbentry->tables,
3000 (void *) &(msg->m_tableid[i]),
3003 tabentry->destroy = PGSTAT_DESTROY_COUNT;
3009 * pgstat_recv_dropdb() -
3011 * Arrange for dead database removal
3015 pgstat_recv_dropdb(PgStat_MsgDropdb *msg, int len)
3017 PgStat_StatDBEntry *dbentry;
3020 * Make sure the backend is counted for.
3022 if (pgstat_add_backend(&msg->m_hdr) < 0)
3026 * Lookup the database in the hashtable.
3028 dbentry = (PgStat_StatDBEntry *) hash_search(pgStatDBHash,
3029 (void *) &(msg->m_databaseid),
3035 * Mark the database for destruction.
3037 dbentry->destroy = PGSTAT_DESTROY_COUNT;
3042 * pgstat_recv_dropdb() -
3044 * Arrange for dead database removal
3048 pgstat_recv_resetcounter(PgStat_MsgResetcounter *msg, int len)
3051 PgStat_StatDBEntry *dbentry;
3054 * Make sure the backend is counted for.
3056 if (pgstat_add_backend(&msg->m_hdr) < 0)
3060 * Lookup the database in the hashtable.
3062 dbentry = (PgStat_StatDBEntry *) hash_search(pgStatDBHash,
3063 (void *) &(msg->m_hdr.m_databaseid),
3069 * We simply throw away all the databases table entries by recreating
3070 * a new hash table for them.
3072 if (dbentry->tables != NULL)
3073 hash_destroy(dbentry->tables);
3075 dbentry->tables = NULL;
3076 dbentry->n_xact_commit = 0;
3077 dbentry->n_xact_rollback = 0;
3078 dbentry->n_blocks_fetched = 0;
3079 dbentry->n_blocks_hit = 0;
3080 dbentry->n_connects = 0;
3081 dbentry->destroy = 0;
3083 memset(&hash_ctl, 0, sizeof(hash_ctl));
3084 hash_ctl.keysize = sizeof(Oid);
3085 hash_ctl.entrysize = sizeof(PgStat_StatTabEntry);
3086 hash_ctl.hash = tag_hash;
3087 dbentry->tables = hash_create("Per-database table",
3088 PGSTAT_TAB_HASH_SIZE,
3090 HASH_ELEM | HASH_FUNCTION);
3091 if (dbentry->tables == NULL)
3093 /* assume the problem is out-of-memory */
3095 (errcode(ERRCODE_OUT_OF_MEMORY),
3096 errmsg("out of memory in statistics collector --- abort")));