elog.c
来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 1,486 行 · 第 1/3 页
C
1,486 行
/* we don't bother incrementing recursion_depth */ CHECK_STACK_DEPTH(); edata->sqlerrcode = sqlerrcode; return 0; /* return value does not matter */}/* * errcode_for_file_access --- add SQLSTATE error code to the current error * * The SQLSTATE code is chosen based on the saved errno value. We assume * that the failing operation was some type of disk file access. * * NOTE: the primary error message string should generally include %m * when this is used. */interrcode_for_file_access(void){ ErrorData *edata = &errordata[errordata_stack_depth]; /* we don't bother incrementing recursion_depth */ CHECK_STACK_DEPTH(); switch (edata->saved_errno) { /* Permission-denied failures */ case EPERM: /* Not super-user */ case EACCES: /* Permission denied */#ifdef EROFS case EROFS: /* Read only file system */#endif edata->sqlerrcode = ERRCODE_INSUFFICIENT_PRIVILEGE; break; /* File not found */ case ENOENT: /* No such file or directory */ edata->sqlerrcode = ERRCODE_UNDEFINED_FILE; break; /* Duplicate file */ case EEXIST: /* File exists */ edata->sqlerrcode = ERRCODE_DUPLICATE_FILE; break; /* Wrong object type or state */ case ENOTDIR: /* Not a directory */ case EISDIR: /* Is a directory */#if defined(ENOTEMPTY) && (ENOTEMPTY != EEXIST) /* same code on AIX */ case ENOTEMPTY: /* Directory not empty */#endif edata->sqlerrcode = ERRCODE_WRONG_OBJECT_TYPE; break; /* Insufficient resources */ case ENOSPC: /* No space left on device */ edata->sqlerrcode = ERRCODE_DISK_FULL; break; case ENFILE: /* File table overflow */ case EMFILE: /* Too many open files */ edata->sqlerrcode = ERRCODE_INSUFFICIENT_RESOURCES; break; /* Hardware failure */ case EIO: /* I/O error */ edata->sqlerrcode = ERRCODE_IO_ERROR; break; /* All else is classified as internal errors */ default: edata->sqlerrcode = ERRCODE_INTERNAL_ERROR; break; } return 0; /* return value does not matter */}/* * errcode_for_socket_access --- add SQLSTATE error code to the current error * * The SQLSTATE code is chosen based on the saved errno value. We assume * that the failing operation was some type of socket access. * * NOTE: the primary error message string should generally include %m * when this is used. */interrcode_for_socket_access(void){ ErrorData *edata = &errordata[errordata_stack_depth]; /* we don't bother incrementing recursion_depth */ CHECK_STACK_DEPTH(); switch (edata->saved_errno) { /* Loss of connection */ case EPIPE:#ifdef ECONNRESET case ECONNRESET:#endif edata->sqlerrcode = ERRCODE_CONNECTION_FAILURE; break; /* All else is classified as internal errors */ default: edata->sqlerrcode = ERRCODE_INTERNAL_ERROR; break; } return 0; /* return value does not matter */}/* * This macro handles expansion of a format string and associated parameters; * it's common code for errmsg(), errdetail(), etc. Must be called inside * a routine that is declared like "const char *fmt, ..." and has an edata * pointer set up. The message is assigned to edata->targetfield, or * appended to it if appendval is true. * * Note: we pstrdup the buffer rather than just transferring its storage * to the edata field because the buffer might be considerably larger than * really necessary. */#define EVALUATE_MESSAGE(targetfield, appendval) \ { \ char *fmtbuf; \ StringInfoData buf; \ /* Internationalize the error format string */ \ fmt = gettext(fmt); \ /* Expand %m in format string */ \ fmtbuf = expand_fmt_string(fmt, edata); \ initStringInfo(&buf); \ if ((appendval) && edata->targetfield) \ appendStringInfo(&buf, "%s\n", edata->targetfield); \ /* Generate actual output --- have to use appendStringInfoVA */ \ for (;;) \ { \ va_list args; \ bool success; \ va_start(args, fmt); \ success = appendStringInfoVA(&buf, fmtbuf, args); \ va_end(args); \ if (success) \ break; \ enlargeStringInfo(&buf, buf.maxlen); \ } \ /* Done with expanded fmt */ \ pfree(fmtbuf); \ /* Save the completed message into the stack item */ \ if (edata->targetfield) \ pfree(edata->targetfield); \ edata->targetfield = pstrdup(buf.data); \ pfree(buf.data); \ }/* * errmsg --- add a primary error message text to the current error * * In addition to the usual %-escapes recognized by printf, "%m" in * fmt is replaced by the error message for the caller's value of errno. * * Note: no newline is needed at the end of the fmt string, since * ereport will provide one for the output methods that need it. */interrmsg(const char *fmt,...){ ErrorData *edata = &errordata[errordata_stack_depth]; MemoryContext oldcontext; recursion_depth++; CHECK_STACK_DEPTH(); oldcontext = MemoryContextSwitchTo(ErrorContext); EVALUATE_MESSAGE(message, false); MemoryContextSwitchTo(oldcontext); recursion_depth--; return 0; /* return value does not matter */}/* * errmsg_internal --- add a primary error message text to the current error * * This is exactly like errmsg() except that strings passed to errmsg_internal * are customarily left out of the internationalization message dictionary. * This should be used for "can't happen" cases that are probably not worth * spending translation effort on. */interrmsg_internal(const char *fmt,...){ ErrorData *edata = &errordata[errordata_stack_depth]; MemoryContext oldcontext; recursion_depth++; CHECK_STACK_DEPTH(); oldcontext = MemoryContextSwitchTo(ErrorContext); EVALUATE_MESSAGE(message, false); MemoryContextSwitchTo(oldcontext); recursion_depth--; return 0; /* return value does not matter */}/* * errdetail --- add a detail error message text to the current error */interrdetail(const char *fmt,...){ ErrorData *edata = &errordata[errordata_stack_depth]; MemoryContext oldcontext; recursion_depth++; CHECK_STACK_DEPTH(); oldcontext = MemoryContextSwitchTo(ErrorContext); EVALUATE_MESSAGE(detail, false); MemoryContextSwitchTo(oldcontext); recursion_depth--; return 0; /* return value does not matter */}/* * errhint --- add a hint error message text to the current error */interrhint(const char *fmt,...){ ErrorData *edata = &errordata[errordata_stack_depth]; MemoryContext oldcontext; recursion_depth++; CHECK_STACK_DEPTH(); oldcontext = MemoryContextSwitchTo(ErrorContext); EVALUATE_MESSAGE(hint, false); MemoryContextSwitchTo(oldcontext); recursion_depth--; return 0; /* return value does not matter */}/* * errcontext --- add a context error message text to the current error * * Unlike other cases, multiple calls are allowed to build up a stack of * context information. We assume earlier calls represent more-closely-nested * states. */interrcontext(const char *fmt,...){ ErrorData *edata = &errordata[errordata_stack_depth]; MemoryContext oldcontext; recursion_depth++; CHECK_STACK_DEPTH(); oldcontext = MemoryContextSwitchTo(ErrorContext); EVALUATE_MESSAGE(context, true); MemoryContextSwitchTo(oldcontext); recursion_depth--; return 0; /* return value does not matter */}/* * errfunction --- add reporting function name to the current error * * This is used when backwards compatibility demands that the function * name appear in messages sent to old-protocol clients. Note that the * passed string is expected to be a non-freeable constant string. */interrfunction(const char *funcname){ ErrorData *edata = &errordata[errordata_stack_depth]; /* we don't bother incrementing recursion_depth */ CHECK_STACK_DEPTH(); edata->funcname = funcname; edata->show_funcname = true; return 0; /* return value does not matter */}/* * errposition --- add cursor position to the current error */interrposition(int cursorpos){ ErrorData *edata = &errordata[errordata_stack_depth]; /* we don't bother incrementing recursion_depth */ CHECK_STACK_DEPTH(); edata->cursorpos = cursorpos; return 0; /* return value does not matter */}/* * elog_finish --- finish up for old-style API * * The elog() macro already called errstart, but with ERROR rather than * the true elevel. */voidelog_finish(int elevel, const char *fmt,...){ ErrorData *edata = &errordata[errordata_stack_depth]; MemoryContext oldcontext; CHECK_STACK_DEPTH(); /* * We need to redo errstart() because the elog macro had to call it * with bogus elevel. */ errordata_stack_depth--; errno = edata->saved_errno; if (!errstart(elevel, edata->filename, edata->lineno, edata->funcname)) return; /* nothing to do */ /* * Format error message just like errmsg(). */ recursion_depth++; oldcontext = MemoryContextSwitchTo(ErrorContext); EVALUATE_MESSAGE(message, false); MemoryContextSwitchTo(oldcontext); recursion_depth--; /* * And let errfinish() finish up. */ errfinish(0);}/* * Initialization of error output file */voidDebugFileOpen(void){ int fd, istty; if (OutputFileName[0]) { /* * A debug-output file name was given. * * Make sure we can write the file, and find out if it's a tty. */ if ((fd = open(OutputFileName, O_CREAT | O_APPEND | O_WRONLY, 0666)) < 0) ereport(FATAL, (errcode_for_file_access(), errmsg("could not open file \"%s\": %m", OutputFileName))); istty = isatty(fd); close(fd); /* * Redirect our stderr to the debug output file. */ if (!freopen(OutputFileName, "a", stderr)) ereport(FATAL, (errcode_for_file_access(), errmsg("could not reopen file \"%s\" as stderr: %m", OutputFileName))); /* * If the file is a tty and we're running under the postmaster, * try to send stdout there as well (if it isn't a tty then stderr * will block out stdout, so we may as well let stdout go wherever * it was going before). */ if (istty && IsUnderPostmaster) if (!freopen(OutputFileName, "a", stdout)) ereport(FATAL, (errcode_for_file_access(), errmsg("could not reopen file \"%s\" as stdout: %m", OutputFileName))); }}#ifdef HAVE_SYSLOG#ifndef PG_SYSLOG_LIMIT#define PG_SYSLOG_LIMIT 128#endif/* * Write a message line to syslog if the syslog option is set. * * Our problem here is that many syslog implementations don't handle * long messages in an acceptable manner. While this function doesn't * help that fact, it does work around by splitting up messages into * smaller pieces. */static voidwrite_syslog(int level, const char *line){ static bool openlog_done = false; static unsigned long seq = 0; static int syslog_fac = LOG_LOCAL0; int len = strlen(line); if (Use_syslog == 0) return; if (!openlog_done) { if (strcasecmp(Syslog_facility, "LOCAL0") == 0) syslog_fac = LOG_LOCAL0; if (strcasecmp(Syslog_facility, "LOCAL1") == 0) syslog_fac = LOG_LOCAL1; if (strcasecmp(Syslog_facility, "LOCAL2") == 0) syslog_fac = LOG_LOCAL2; if (strcasecmp(Syslog_facility, "LOCAL3") == 0) syslog_fac = LOG_LOCAL3; if (strcasecmp(Syslog_facility, "LOCAL4") == 0) syslog_fac = LOG_LOCAL4; if (strcasecmp(Syslog_facility, "LOCAL5") == 0) syslog_fac = LOG_LOCAL5; if (strcasecmp(Syslog_facility, "LOCAL6") == 0) syslog_fac = LOG_LOCAL6; if (strcasecmp(Syslog_facility, "LOCAL7") == 0) syslog_fac = LOG_LOCAL7; openlog(Syslog_ident, LOG_PID | LOG_NDELAY, syslog_fac); openlog_done = true; } /* * We add a sequence number to each log message to suppress "same" * messages. */ seq++; /* divide into multiple syslog() calls if message is too long */ /* or if the message contains embedded NewLine(s) '\n' */ if (len > PG_SYSLOG_LIMIT || strchr(line, '\n') != NULL) { int chunk_nr = 0; while (len > 0) { char buf[PG_SYSLOG_LIMIT + 1]; int buflen; int i; /* if we start at a newline, move ahead one char */ if (line[0] == '\n') { line++; len--; continue; } strncpy(buf, line, PG_SYSLOG_LIMIT); buf[PG_SYSLOG_LIMIT] = '\0'; if (strchr(buf, '\n') != NULL) *strchr(buf, '\n') = '\0'; buflen = strlen(buf); /* trim to multibyte letter boundary */ buflen = pg_mbcliplen(buf, buflen, buflen); if (buflen <= 0) return; buf[buflen] = '\0';
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?