Skip to content
Snippets Groups Projects
Commit 96c4212f authored by Marc G. Fournier's avatar Marc G. Fournier
Browse files

cvs add'd two files for the tprintf() patch...
parent f62d1253
No related branches found
No related tags found
No related merge requests found
/*-------------------------------------------------------------------------
*
* 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:
*/
/*-------------------------------------------------------------------------
*
* 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:
*/
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment