From 96c4212f998534d60235a117038bd39f09fa9091 Mon Sep 17 00:00:00 2001 From: "Marc G. Fournier" Date: Tue, 25 Aug 1998 21:43:47 +0000 Subject: [PATCH] cvs add'd two files for the tprintf() patch... --- src/backend/utils/misc/trace.c | 350 +++++++++++++++++++++++++++++++++ src/include/utils/trace.h | 85 ++++++++ 2 files changed, 435 insertions(+) create mode 100644 src/backend/utils/misc/trace.c create mode 100644 src/include/utils/trace.h diff --git a/src/backend/utils/misc/trace.c b/src/backend/utils/misc/trace.c new file mode 100644 index 0000000000..04148e7df4 --- /dev/null +++ b/src/backend/utils/misc/trace.c @@ -0,0 +1,350 @@ +/*------------------------------------------------------------------------- + * + * trace.c-- + * + * Conditional trace ans logging functions. + * + * Massimo Dal Zotto + * + *------------------------------------------------------------------------- + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef USE_SYSLOG +#include +#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)) { + 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 index 0000000000..7884e197fd --- /dev/null +++ b/src/include/utils/trace.h @@ -0,0 +1,85 @@ +/*------------------------------------------------------------------------- + * + * trace.h-- + * + * Conditional trace definitions. + * + * Massimo Dal Zotto + * + *------------------------------------------------------------------------- + */ + +#ifndef TRACE_H +#define TRACE_H + +#include +#include +#include +#include + +#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: + */ -- 2.40.0