mirror of
https://github.com/postgres/postgres.git
synced 2025-05-12 16:21:30 +03:00
cvs add'd two files for the tprintf() patch...
This commit is contained in:
parent
f62d1253ef
commit
96c4212f99
350
src/backend/utils/misc/trace.c
Normal file
350
src/backend/utils/misc/trace.c
Normal file
@ -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:
|
||||||
|
*/
|
85
src/include/utils/trace.h
Normal file
85
src/include/utils/trace.h
Normal file
@ -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:
|
||||||
|
*/
|
Loading…
x
Reference in New Issue
Block a user