]> granicus.if.org Git - postgresql/commitdiff
cvs add'd two files for the tprintf() patch...
authorMarc G. Fournier <scrappy@hub.org>
Tue, 25 Aug 1998 21:43:47 +0000 (21:43 +0000)
committerMarc G. Fournier <scrappy@hub.org>
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 <dz@cs.unitn.it>
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#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 <dz@cs.unitn.it>
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#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:
+ */