trace.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:7k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * trace.c
  4.  *
  5.  *   Conditional trace ans logging functions.
  6.  *
  7.  *   Massimo Dal Zotto <dz@cs.unitn.it>
  8.  *
  9.  *-------------------------------------------------------------------------
  10.  */
  11. #include <unistd.h>
  12. #include <signal.h>
  13. #include <sys/time.h>
  14. #include <sys/types.h>
  15. #include <sys/stat.h>
  16. #include <fcntl.h>
  17. #include "postgres.h"
  18. #ifdef USE_SYSLOG
  19. #include <syslog.h>
  20. #endif
  21. #include "miscadmin.h"
  22. #include "utils/trace.h"
  23. #ifdef USE_SYSLOG
  24. /*
  25.  * Global option to control the use of syslog(3) for logging:
  26.  *
  27.  * 0 stdout/stderr only
  28.  * 1 stdout/stderr + syslog
  29.  * 2 syslog only
  30.  */
  31. #define UseSyslog pg_options[OPT_SYSLOG]
  32. #define PG_LOG_FACILITY LOG_LOCAL0
  33. #define PG_LOG_IDENT "postgres"
  34. #else
  35. #define UseSyslog 0
  36. #endif
  37. /*
  38.  * Trace option names, must match the constants in trace_opts[].
  39.  */
  40. static char *opt_names[] = {
  41. "all", /* 0=trace some, 1=trace all, -1=trace none */
  42. "verbose",
  43. "query",
  44. "plan",
  45. "parse",
  46. "rewritten",
  47. "pretty_plan",
  48. "pretty_parse",
  49. "pretty_rewritten",
  50. "parserstats",
  51. "plannerstats",
  52. "executorstats",
  53. "shortlocks", /* currently unused but needed, see lock.c */
  54. "locks",
  55. "userlocks",
  56. "spinlocks",
  57. "notify",
  58. "malloc",
  59. "palloc",
  60. "lock_debug_oidmin",
  61. "lock_debug_relid",
  62. "lock_read_priority", /* lock priority, see lock.c */
  63. "deadlock_timeout", /* deadlock timeout, see proc.c */
  64. "syslog", /* use syslog for error messages */
  65. "hostlookup", /* enable hostname lookup in ps_status */
  66. "showportnumber", /* show port number in ps_status */
  67. /* NUM_PG_OPTIONS */ /* must be the last item of enum */
  68. };
  69. /*
  70.  * Array of trace flags which can be set or reset independently.
  71.  */
  72. int pg_options[NUM_PG_OPTIONS] = {0};
  73. /*
  74.  * Print a timestamp and a message to stdout if the trace flag
  75.  * indexed by the flag value is set.
  76.  */
  77. int
  78. tprintf(int flag, const char *fmt,...)
  79. {
  80. va_list ap;
  81. char line[ELOG_MAXLEN + TIMESTAMP_SIZE + 1];
  82. #ifdef USE_SYSLOG
  83. int log_level;
  84. #endif
  85. if ((flag == TRACE_ALL) || (pg_options[TRACE_ALL] > 0))
  86. {
  87. /* uconditional trace or trace all option set */
  88. }
  89. else if (pg_options[TRACE_ALL] == 0)
  90. {
  91. if ((flag < 0) || (flag >= NUM_PG_OPTIONS) || (!pg_options[flag]))
  92. return 0;
  93. }
  94. else if (pg_options[TRACE_ALL] < 0)
  95. return 0;
  96. va_start(ap, fmt);
  97. #ifdef ELOG_TIMESTAMPS
  98. strcpy(line, tprintf_timestamp());
  99. #endif
  100. vsnprintf(line + TIMESTAMP_SIZE, ELOG_MAXLEN, fmt, ap);
  101. va_end(ap);
  102. #ifdef USE_SYSLOG
  103. log_level = ((flag == TRACE_ALL) ? LOG_INFO : LOG_DEBUG);
  104. write_syslog(log_level, line + TIMESTAMP_SIZE);
  105. #endif
  106. if (UseSyslog <= 1)
  107. {
  108. puts(line);
  109. fflush(stdout);
  110. }
  111. return 1;
  112. }
  113. /*
  114.  * Print a timestamp and a message to stdout or to syslog.
  115.  */
  116. #ifdef NOT_USED
  117. int
  118. tprintf1(const char *fmt,...)
  119. {
  120. va_list ap;
  121. char line[ELOG_MAXLEN + TIMESTAMP_SIZE + 1];
  122. va_start(ap, fmt);
  123. #ifdef ELOG_TIMESTAMPS
  124. strcpy(line, tprintf_timestamp());
  125. #endif
  126. vsnprintf(line + TIMESTAMP_SIZE, ELOG_MAXLEN, fmt, ap);
  127. va_end(ap);
  128. #ifdef USE_SYSLOG
  129. write_syslog(LOG_INFO, line + TIMESTAMP_SIZE);
  130. #endif
  131. if (UseSyslog <= 1)
  132. {
  133. puts(line);
  134. fflush(stdout);
  135. }
  136. return 1;
  137. }
  138. #endif
  139. /*
  140.  * Print a timestamp and a message to stderr.
  141.  */
  142. int
  143. eprintf(const char *fmt,...)
  144. {
  145. va_list ap;
  146. char line[ELOG_MAXLEN + TIMESTAMP_SIZE + 1];
  147. va_start(ap, fmt);
  148. #ifdef ELOG_TIMESTAMPS
  149. strcpy(line, tprintf_timestamp());
  150. #endif
  151. vsnprintf(line + TIMESTAMP_SIZE, ELOG_MAXLEN, fmt, ap);
  152. va_end(ap);
  153. #ifdef USE_SYSLOG
  154. write_syslog(LOG_ERR, line + TIMESTAMP_SIZE);
  155. #endif
  156. if (UseSyslog <= 1)
  157. {
  158. fputs(line, stderr);
  159. fputc('n', stderr);
  160. fflush(stderr);
  161. }
  162. return 1;
  163. }
  164. #ifdef USE_SYSLOG
  165. /*
  166.  * Write a message line to syslog if the syslog option is set.
  167.  */
  168. void
  169. write_syslog(int level, char *line)
  170. {
  171. static int openlog_done = 0;
  172. if (UseSyslog >= 1)
  173. {
  174. if (!openlog_done)
  175. {
  176. openlog_done = 1;
  177. openlog(PG_LOG_IDENT, LOG_PID | LOG_NDELAY, PG_LOG_FACILITY);
  178. }
  179. syslog(level, "%s", line);
  180. }
  181. }
  182. #endif
  183. #ifdef ELOG_TIMESTAMPS
  184. /*
  185.  * Return a timestamp string like "980119.17:25:59.902 [21974] "
  186.  */
  187. char *
  188. tprintf_timestamp()
  189. {
  190. struct timeval tv;
  191. struct timezone tz = { 0, 0 };
  192. struct tm  *time;
  193. time_t tm;
  194. static char timestamp[32],
  195. pid[8];
  196. gettimeofday(&tv, &tz);
  197. tm = tv.tv_sec;
  198. time = localtime(&tm);
  199. sprintf(pid, "[%d]", MyProcPid);
  200. sprintf(timestamp, "%02d%02d%02d.%02d:%02d:%02d.%03d %7s ",
  201. time->tm_year, time->tm_mon + 1, time->tm_mday,
  202. time->tm_hour, time->tm_min, time->tm_sec,
  203. (int) (tv.tv_usec/1000), pid);
  204. return timestamp;
  205. }
  206. #endif
  207. #ifdef NOT_USED
  208. static int
  209. option_flag(int flag)
  210. {
  211. if ((flag < 0) || (flag >= NUM_PG_OPTIONS))
  212. return 0;
  213. return pg_options[flag];
  214. }
  215. int
  216. set_option_flag(int flag, int value)
  217. {
  218. if ((flag < 0) || (flag >= NUM_PG_OPTIONS))
  219. return -1;
  220. pg_options[flag] = value;
  221. return value;
  222. }
  223. #endif
  224. /*
  225.  * Parse an option string like "name,name+,name-,name=value".
  226.  * Single options are delimited by ',',space,tab,newline or cr.
  227.  *
  228.  * If 'secure' is false, the option string came from a remote client via
  229.  * connection "debug options" field --- do not obey any requests that
  230.  * might potentially be security loopholes.
  231.  */
  232. void
  233. parse_options(char *str, bool secure)
  234. {
  235. char    *s,
  236.    *name;
  237. int i,
  238. len,
  239. val,
  240. is_comment;
  241. Assert((sizeof(opt_names) / sizeof(char *)) == NUM_PG_OPTIONS);
  242. str = strdup(str);
  243. for (s = str; *s;)
  244. {
  245. is_comment = 0;
  246. name = s;
  247. val = 1;
  248. for (; *s; s++)
  249. {
  250. switch (*s)
  251. {
  252. case '#':
  253. is_comment = 1;
  254. break;
  255. case '=':
  256. *s++ = '';
  257. val = strtol(s, &s, 10);
  258. goto setval;
  259. case '-':
  260. *s++ = '';
  261. val = 0;
  262. goto setval;
  263. case '+':
  264. *s++ = '';
  265. val = 1;
  266. goto setval;
  267. case ' ':
  268. case ',':
  269. case 't':
  270. case 'n':
  271. case 'r':
  272. *s = ',';
  273. val = 1;
  274. goto setval;
  275. }
  276. }
  277. setval:
  278. for (; *s; s++)
  279. {
  280. if (*s == ',')
  281. {
  282. *s++ = '';
  283. break;
  284. }
  285. }
  286. len = strlen(name);
  287. if (len == 0)
  288. continue;
  289. for (i = 0; i < NUM_PG_OPTIONS; i++)
  290. {
  291. if (strncmp(name, opt_names[i], len) == 0)
  292. {
  293. pg_options[i] = val;
  294. break;
  295. }
  296. }
  297. if (!is_comment && (i >= NUM_PG_OPTIONS))
  298. fprintf(stderr, "invalid option: %sn", name);
  299. }
  300. free(str);
  301. }
  302. #define BUF_SIZE 4096
  303. void
  304. read_pg_options(SIGNAL_ARGS)
  305. {
  306. int fd;
  307. int n;
  308. int verbose;
  309. char buffer[BUF_SIZE];
  310. char c;
  311. char    *s,
  312.    *p;
  313. if (!DataDir)
  314. {
  315. fprintf(stderr, "read_pg_options: DataDir not definedn");
  316. return;
  317. }
  318. snprintf(buffer, BUF_SIZE - 1, "%s/%s", DataDir, "pg_options");
  319. #ifndef __CYGWIN32__
  320. if ((fd = open(buffer, O_RDONLY)) < 0)
  321. #else
  322. if ((fd = open(buffer, O_RDONLY | O_BINARY)) < 0)
  323. #endif
  324. return;
  325. if ((n = read(fd, buffer, BUF_SIZE - 1)) > 0)
  326. {
  327. /* collpse buffer in place removing comments and spaces */
  328. for (s = buffer, p = buffer, c = ''; s < (buffer + n);)
  329. {
  330. switch (*s)
  331. {
  332. case '#':
  333. while ((s < (buffer + n)) && (*s++ != 'n'));
  334. break;
  335. case ' ':
  336. case 't':
  337. case 'n':
  338. case 'r':
  339. if (c != ',')
  340. c = *p++ = ',';
  341. s++;
  342. break;
  343. default:
  344. c = *p++ = *s++;
  345. break;
  346. }
  347. }
  348. if (c == ',')
  349. p--;
  350. *p = '';
  351. verbose = pg_options[TRACE_VERBOSE];
  352. parse_options(buffer, true);
  353. verbose |= pg_options[TRACE_VERBOSE];
  354. if (verbose || postgres_signal_arg == SIGHUP)
  355. tprintf(TRACE_ALL, "read_pg_options: %s", buffer);
  356. }
  357. close(fd);
  358. }
  359. /*
  360.  * Local variables:
  361.  * tab-width: 4
  362.  * c-indent-level: 4
  363.  * c-basic-offset: 4
  364.  * End:
  365.  */