cvs add'd two files for the tprintf() patch...
authorMarc G. Fournier <[email protected]>
Tue, 25 Aug 1998 21:43:47 +0000 (21:43 +0000)
committerMarc G. Fournier <[email protected]>
Tue, 25 Aug 1998 21:43:47 +0000 (21:43 +0000)
src/backend/utils/misc/trace.c [new file with mode: 0644]
src/include/utils/trace.h [new file with mode: 0644]

diff --git a/src/backend/utils/misc/trace.c b/src/backend/utils/misc/trace.c
new file mode 100644 (file)
index 0000000..04148e7
--- /dev/null
@@ -0,0 +1,350 @@
+/*-------------------------------------------------------------------------
+ *
+ * trace.c--
+ *
+ *   Conditional trace ans logging functions.
+ *
+ *    Massimo Dal Zotto <[email protected]>
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#ifdef USE_SYSLOG
+#include <syslog.h>
+#endif
+
+#include "postgres.h"
+#include "miscadmin.h"
+#include "utils/trace.h"
+#include "libpq/pqsignal.h"
+
+#ifdef USE_SYSLOG
+/*
+ * Global option to control the use of syslog(3) for logging:
+ *
+ *     0   stdout/stderr only
+ *     1   stdout/stderr + syslog
+ *     2   syslog only
+ */
+#define UseSyslog      pg_options[OPT_SYSLOG]
+#define PG_LOG_FACILITY    LOG_LOCAL0
+#define PG_LOG_IDENT   "postgres"
+#else
+#define UseSyslog 0
+#endif
+
+/*
+ * Trace option names, must match the constants in trace_opts[].
+ */
+static char *opt_names[] = {
+   "all",
+   "verbose",
+   "query",
+   "plan",
+   "parse",
+   "rewritten",
+   "parserstats",
+   "plannerstats",
+   "executorstats",
+   "shortlocks",           /* currently unused but needed, see lock.c */
+   "locks",
+   "userlocks",
+   "spinlocks",
+   "notify",
+   "malloc",
+   "palloc",
+   "lock_debug_oidmin",
+   "lock_debug_relid",
+   "lock_read_priority",   /* lock priority, see lock.c */
+   "deadlock_timeout",     /* deadlock timeout, see proc.c */
+   "syslog",               /* use syslog for error messages */
+   "hostlookup",           /* enable hostname lookup in ps_status */
+   "showportnumber",       /* show port number in ps_status */
+   "notifyunlock",         /* enable unlock of pg_listener after notify */
+   "notifyhack"            /* enable notify hack to remove duplicate tuples */
+};
+
+/*
+ * Array of trace flags which can be set or reset independently.
+ */
+int pg_options[NUM_PG_OPTIONS] = { 0 };
+
+static int openlog_done = 0;
+
+/*
+ * Print a timestamp and a message to stdout if the trace flag
+ * indexed by the flag value is set.
+ */
+int
+tprintf(int flag, const char *fmt, ... )
+{
+   va_list     ap;
+   char        line[ELOG_MAXLEN+TIMESTAMP_SIZE+1];
+
+#ifdef USE_SYSLOG
+   int         log_level;
+#endif
+
+   if ((flag == TRACE_ALL) || (pg_options[TRACE_ALL] > 0)) {
+       /* uconditional trace or trace all option set */
+   } else if (pg_options[TRACE_ALL] == 0) {
+       if ((flag < 0) || (flag >= NUM_PG_OPTIONS) || (!pg_options[flag])) {
+           return 0;
+       }
+   } else if (pg_options[TRACE_ALL] < 0) {
+       return 0;
+   }
+
+   va_start(ap, fmt);
+#ifdef ELOG_TIMESTAMPS
+   strcpy(line, tprintf_timestamp());
+#endif
+   vsprintf(line+TIMESTAMP_SIZE, fmt, ap);
+   va_end(ap);
+
+#ifdef USE_SYSLOG
+   log_level = ((flag == TRACE_ALL) ? LOG_INFO : LOG_DEBUG);
+   write_syslog(log_level, line+TIMESTAMP_SIZE);
+#endif
+
+   if (UseSyslog <= 1) {
+       puts(line);
+       fflush(stdout);
+   }
+
+   return 1;
+}
+
+/*
+ * Print a timestamp and a message to stderr.
+ */
+int
+eprintf(const char *fmt, ... )
+{
+   va_list     ap;
+   char        line[ELOG_MAXLEN+TIMESTAMP_SIZE+1];
+
+   va_start(ap, fmt);
+#ifdef ELOG_TIMESTAMPS
+   strcpy(line, tprintf_timestamp());
+#endif
+   vsprintf(line+TIMESTAMP_SIZE, fmt, ap);
+   va_end(ap);
+
+#ifdef USE_SYSLOG
+   write_syslog(LOG_ERR, line+TIMESTAMP_SIZE);
+#endif
+
+   if (UseSyslog <= 1) {
+       fputs(line, stderr);
+       fputc('\n', stderr);
+       fflush(stderr);
+   }
+
+   return 1;
+}
+
+#ifdef USE_SYSLOG
+/*
+ * Write a message line to syslog if the syslog option is set.
+ */
+void
+write_syslog(int level, char *line)
+{
+   if (UseSyslog >= 1) {
+       if (!openlog_done) {
+           openlog_done = 1;
+           openlog(PG_LOG_IDENT, LOG_PID|LOG_NDELAY, PG_LOG_FACILITY);
+       }
+       syslog(level, "%s", line);
+   }
+}
+#endif
+
+#ifdef ELOG_TIMESTAMPS
+/*
+ * Return a timestamp string like "980119.17:25:59.902 [21974] "
+ */
+char *
+tprintf_timestamp()
+{
+   struct timeval  tv;
+   struct tm       *time;
+   time_t          tm;
+   static char     timestamp[32], pid[8];
+
+   gettimeofday(&tv, DST_NONE);
+   tm = tv.tv_sec;
+   time = localtime(&tm);
+
+   sprintf(pid, "[%d]", MyProcPid);
+   sprintf(timestamp, "%02d%02d%02d.%02d:%02d:%02d.%03d %7s ",
+           time->tm_year, time->tm_mon+1, time->tm_mday,
+           time->tm_hour, time->tm_min, time->tm_sec,
+           tv.tv_usec/1000, pid);
+
+   return timestamp;
+}
+#endif
+
+int
+option_flag(int flag)
+{
+   if ((flag < 0) || (flag >= NUM_PG_OPTIONS)) {
+       return 0;
+   }
+   return pg_options[flag];
+}
+
+int
+set_option_flag(int flag, int value)
+{
+   if ((flag < 0) || (flag >= NUM_PG_OPTIONS)) {
+       return -1;
+   }
+
+   pg_options[flag] = value;
+   return value;
+}
+
+/*
+ * Parse an option string like "name,name+,name-,name=value".
+ * Single options are delimited by ',',space,tab,newline or cr.
+ */ 
+void
+parse_options(char *str)
+{
+   char    *s,
+           *name;
+   int     i,
+           len,
+           val,
+           is_comment;
+
+   Assert((sizeof(opt_names)/sizeof(char*)) == NUM_PG_OPTIONS);
+   str = strdup(str);
+   for (s=str; *s;) {
+       is_comment = 0;
+       name = s;
+       val = 1;
+       for (; *s; s++) {
+           switch (*s) {
+               case '#':
+                   is_comment = 1;
+                   break;
+               case '=':
+                   *s++ = '\0';
+                   val = strtol(s, &s, 10);
+                   goto setval;
+               case '-':
+                   *s++ = '\0';
+                   val = 0;
+                   goto setval;
+               case '+':
+                   *s++ = '\0';
+                   val = 1;
+                   goto setval;
+               case ' ':
+               case ',':
+               case '\t':
+               case '\n':
+               case '\r':
+                   *s = ',';
+                   val = 1;
+                   goto setval;
+           }
+       }
+    setval:
+       for (; *s; s++) {
+           if (*s == ',') {
+               *s++ = '\0';
+               break;
+           }
+       }
+       len = strlen(name);
+       if (len == 0) {
+           continue;
+       }
+       for (i=0; i<NUM_PG_OPTIONS; i++) {
+           if (strncmp(name, opt_names[i], len) == 0) {
+               pg_options[i] = val;
+               break;
+           }
+       }
+       if (!is_comment && (i >= NUM_PG_OPTIONS)) {
+           fprintf(stderr, "invalid option: %s\n", name);
+       }
+   }
+   free(str);
+}
+
+#define BUF_SIZE 4096
+
+void
+read_pg_options(SIGNAL_ARGS)
+{
+   int         fd;
+   int         n;
+   int         verbose;
+   char        buffer[BUF_SIZE];
+   char        c;
+   char        *s,
+               *p;
+
+   sprintf(buffer, "%s/%s", DataDir, "pg_options");
+   if ((fd = open(buffer, O_RDONLY)) < 0) {
+       return;
+   }
+
+   if ((n = read(fd, buffer, BUF_SIZE-1)) > 0) {
+       /* collpse buffer in place removing comments and spaces */
+       for (s=buffer,p=buffer,c='\0'; s<(buffer+n); ) {
+           switch (*s) {
+               case '#':
+                   while ((s < (buffer+n)) && (*s++ != '\n'));
+                   break;
+               case ' ':
+               case '\t':
+               case '\n':
+               case '\r':
+                   if (c != ',')
+                       c = *p++ = ',';
+                   s++;
+                   break;
+               default:
+                   c = *p++ = *s++;
+                   break;
+           }
+       }
+       if (c == ',')
+           p--;
+       *p = '\0';
+       verbose = pg_options[TRACE_VERBOSE];
+       parse_options(buffer);
+       verbose |= pg_options[TRACE_VERBOSE];
+       if (verbose || postgres_signal_arg == SIGHUP) {
+           tprintf(TRACE_ALL, "read_pg_options: %s", buffer);
+       }
+   }
+
+   close(fd);
+}
+
+/*
+ * Local variables:
+ *  tab-width: 4
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ * End:
+ */
diff --git a/src/include/utils/trace.h b/src/include/utils/trace.h
new file mode 100644 (file)
index 0000000..7884e19
--- /dev/null
@@ -0,0 +1,85 @@
+/*-------------------------------------------------------------------------
+ *
+ * trace.h--
+ *
+ *   Conditional trace definitions.
+ *
+ *    Massimo Dal Zotto <[email protected]>
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef TRACE_H
+#define TRACE_H
+
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <stdarg.h>
+
+#include "postgres.h"
+
+#ifdef ELOG_TIMESTAMPS
+char *tprintf_timestamp(void);
+#define TIMESTAMP_SIZE 28
+#else
+#define TIMESTAMP_SIZE 0
+#endif
+
+extern int tprintf(int flag, const char *fmt, ...);
+extern int eprintf(const char *fmt, ...);
+extern int option_flag(int flag);
+extern int set_option_flag(int flag, int value);
+extern void write_syslog(int level, char *line);
+extern void parse_options(char *str);
+extern void read_pg_options(SIGNAL_ARGS);
+
+/*
+ * Trace options, used as index into pg_options.
+ * Must match the constants in pg_options[].
+ */
+enum pg_option_enum {
+   TRACE_ALL,              /* 0=trace some, 1=trace all, -1=trace none */
+   TRACE_VERBOSE,
+   TRACE_QUERY,
+   TRACE_PLAN,
+   TRACE_PARSE,
+   TRACE_REWRITTEN,
+   TRACE_PARSERSTATS,
+   TRACE_PLANNERSTATS,
+   TRACE_EXECUTORSTATS,
+   TRACE_SHORTLOCKS,       /* currently unused but needed, see lock.c */
+   TRACE_LOCKS,
+   TRACE_USERLOCKS,
+   TRACE_SPINLOCKS,
+   TRACE_NOTIFY,
+   TRACE_MALLOC,
+   TRACE_PALLOC,
+   TRACE_LOCKOIDMIN,
+   TRACE_LOCKRELATION,
+   OPT_LOCKREADPRIORITY,   /* lock priority, see lock.c */
+   OPT_DEADLOCKTIMEOUT,    /* deadlock timeout, see proc.c */
+   OPT_SYSLOG,             /* use syslog for error messages */
+   OPT_HOSTLOOKUP,         /* enable hostname lookup in ps_status */
+   OPT_SHOWPORTNUMBER,     /* show port number in ps_status */
+   OPT_NOTIFYUNLOCK,       /* enable unlock of pg_listener after notify */
+   OPT_NOTIFYHACK,         /* enable notify hack to remove duplicate tuples */
+
+   NUM_PG_OPTIONS          /* must be the last item of enum */
+};
+
+extern int pg_options[NUM_PG_OPTIONS];
+
+#define PRINTF(args...)            tprintf(TRACE_ALL, args)
+#define EPRINTF(args...)       eprintf(args)
+#define TPRINTF(flag, args...) tprintf(flag, args)
+
+#endif                         /* TRACE_H */
+
+/*
+ * Local variables:
+ *  tab-width: 4
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ * End:
+ */