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 + -
显示快捷键?