mirror of
https://github.com/postgres/postgres.git
synced 2025-05-11 05:41:32 +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