elog.c

来自「postgresql8.3.4源码,开源数据库」· C语言 代码 · 共 2,491 行 · 第 1/5 页

C
2,491
字号
		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 = _(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 */}/* * errhidestmt --- optionally suppress STATEMENT: field of log entry * * This should be called if the message text already includes the statement. */interrhidestmt(bool hide_stmt){	ErrorData  *edata = &errordata[errordata_stack_depth];	/* we don't bother incrementing recursion_depth */	CHECK_STACK_DEPTH();	edata->hide_stmt = hide_stmt;	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 */}/* * internalerrposition --- add internal cursor position to the current error */intinternalerrposition(int cursorpos){	ErrorData  *edata = &errordata[errordata_stack_depth];	/* we don't bother incrementing recursion_depth */	CHECK_STACK_DEPTH();	edata->internalpos = cursorpos;	return 0;					/* return value does not matter */}/* * internalerrquery --- add internal query text to the current error * * Can also pass NULL to drop the internal query text entry.  This case * is intended for use in error callback subroutines that are editorializing * on the layout of the error report. */intinternalerrquery(const char *query){	ErrorData  *edata = &errordata[errordata_stack_depth];	/* we don't bother incrementing recursion_depth */	CHECK_STACK_DEPTH();	if (edata->internalquery)	{		pfree(edata->internalquery);		edata->internalquery = NULL;	}	if (query)		edata->internalquery = MemoryContextStrdup(ErrorContext, query);	return 0;					/* return value does not matter */}/* * geterrposition --- return the currently set error position (0 if none) * * This is only intended for use in error callback subroutines, since there * is no other place outside elog.c where the concept is meaningful. */intgeterrposition(void){	ErrorData  *edata = &errordata[errordata_stack_depth];	/* we don't bother incrementing recursion_depth */	CHECK_STACK_DEPTH();	return edata->cursorpos;}/* * getinternalerrposition --- same for internal error position * * This is only intended for use in error callback subroutines, since there * is no other place outside elog.c where the concept is meaningful. */intgetinternalerrposition(void){	ErrorData  *edata = &errordata[errordata_stack_depth];	/* we don't bother incrementing recursion_depth */	CHECK_STACK_DEPTH();	return edata->internalpos;}/* * elog_start --- startup for old-style API * * All that we do here is stash the hidden filename/lineno/funcname * arguments into a stack entry. * * We need this to be separate from elog_finish because there's no other * portable way to deal with inserting extra arguments into the elog call. * (If macros with variable numbers of arguments were portable, it'd be * easy, but they aren't.) */voidelog_start(const char *filename, int lineno, const char *funcname){	ErrorData  *edata;	if (++errordata_stack_depth >= ERRORDATA_STACK_SIZE)	{		/*		 * Wups, stack not big enough.	We treat this as a PANIC condition		 * because it suggests an infinite loop of errors during error		 * recovery.		 */		errordata_stack_depth = -1;		/* make room on stack */		ereport(PANIC, (errmsg_internal("ERRORDATA_STACK_SIZE exceeded")));	}	edata = &errordata[errordata_stack_depth];	edata->filename = filename;	edata->lineno = lineno;	edata->funcname = funcname;	/* errno is saved now so that error parameter eval can't change it */	edata->saved_errno = errno;}/* * elog_finish --- finish up for old-style API */voidelog_finish(int elevel, const char *fmt,...){	ErrorData  *edata = &errordata[errordata_stack_depth];	MemoryContext oldcontext;	CHECK_STACK_DEPTH();	/*	 * Do errstart() to see if we actually want to report the message.	 */	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);}/* * Actual output of the top-of-stack error message * * In the ereport(ERROR) case this is called from PostgresMain (or not at all, * if the error is caught by somebody).  For all other severity levels this * is called by errfinish. */voidEmitErrorReport(void){	ErrorData  *edata = &errordata[errordata_stack_depth];	MemoryContext oldcontext;	recursion_depth++;	CHECK_STACK_DEPTH();	oldcontext = MemoryContextSwitchTo(ErrorContext);	/* Send to server log, if enabled */	if (edata->output_to_server)		send_message_to_server_log(edata);	/* Send to client, if enabled */	if (edata->output_to_client)		send_message_to_frontend(edata);	MemoryContextSwitchTo(oldcontext);	recursion_depth--;}/* * CopyErrorData --- obtain a copy of the topmost error stack entry * * This is only for use in error handler code.	The data is copied into the * current memory context, so callers should always switch away from * ErrorContext first; otherwise it will be lost when FlushErrorState is done. */ErrorData *CopyErrorData(void){	ErrorData  *edata = &errordata[errordata_stack_depth];	ErrorData  *newedata;	/*	 * we don't increment recursion_depth because out-of-memory here does not	 * indicate a problem within the error subsystem.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?