1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 1996,2008 Oracle.  All rights reserved.
5 *
6 * $Id: db_err.c,v 12.72 2008/03/12 19:11:53 mbrey Exp $
7 */
8
9#include "db_config.h"
10
11#include "db_int.h"
12#include "dbinc/db_page.h"
13#include "dbinc/db_am.h"
14#include "dbinc/lock.h"
15#include "dbinc/log.h"
16#include "dbinc/mp.h"
17#include "dbinc/txn.h"
18
19static void __db_msgcall __P((const DB_ENV *, const char *, va_list));
20static void __db_msgfile __P((const DB_ENV *, const char *, va_list));
21
22/*
23 * __db_fchk --
24 *	General flags checking routine.
25 *
26 * PUBLIC: int __db_fchk __P((ENV *, const char *, u_int32_t, u_int32_t));
27 */
28int
29__db_fchk(env, name, flags, ok_flags)
30	ENV *env;
31	const char *name;
32	u_int32_t flags, ok_flags;
33{
34	return (LF_ISSET(~ok_flags) ? __db_ferr(env, name, 0) : 0);
35}
36
37/*
38 * __db_fcchk --
39 *	General combination flags checking routine.
40 *
41 * PUBLIC: int __db_fcchk
42 * PUBLIC:    __P((ENV *, const char *, u_int32_t, u_int32_t, u_int32_t));
43 */
44int
45__db_fcchk(env, name, flags, flag1, flag2)
46	ENV *env;
47	const char *name;
48	u_int32_t flags, flag1, flag2;
49{
50	return (LF_ISSET(flag1) &&
51	    LF_ISSET(flag2) ? __db_ferr(env, name, 1) : 0);
52}
53
54/*
55 * __db_ferr --
56 *	Common flag errors.
57 *
58 * PUBLIC: int __db_ferr __P((const ENV *, const char *, int));
59 */
60int
61__db_ferr(env, name, iscombo)
62	const ENV *env;
63	const char *name;
64	int iscombo;
65{
66	__db_errx(env, "illegal flag %sspecified to %s",
67	    iscombo ? "combination " : "", name);
68	return (EINVAL);
69}
70
71/*
72 * __db_fnl --
73 *	Common flag-needs-locking message.
74 *
75 * PUBLIC: int __db_fnl __P((const ENV *, const char *));
76 */
77int
78__db_fnl(env, name)
79	const ENV *env;
80	const char *name;
81{
82	__db_errx(env,
83    "%s: DB_READ_COMMITTED, DB_READ_UNCOMMITTED and DB_RMW require locking",
84	    name);
85	return (EINVAL);
86}
87
88/*
89 * __db_pgerr --
90 *	Error when unable to retrieve a specified page.
91 *
92 * PUBLIC: int __db_pgerr __P((DB *, db_pgno_t, int));
93 */
94int
95__db_pgerr(dbp, pgno, errval)
96	DB *dbp;
97	db_pgno_t pgno;
98	int errval;
99{
100	/*
101	 * Three things are certain:
102	 * Death, taxes, and lost data.
103	 * Guess which has occurred.
104	 */
105	__db_errx(dbp->env,
106	    "unable to create/retrieve page %lu", (u_long)pgno);
107	return (__env_panic(dbp->env, errval));
108}
109
110/*
111 * __db_pgfmt --
112 *	Error when a page has the wrong format.
113 *
114 * PUBLIC: int __db_pgfmt __P((ENV *, db_pgno_t));
115 */
116int
117__db_pgfmt(env, pgno)
118	ENV *env;
119	db_pgno_t pgno;
120{
121	__db_errx(env, "page %lu: illegal page type or format", (u_long)pgno);
122	return (__env_panic(env, EINVAL));
123}
124
125#ifdef DIAGNOSTIC
126/*
127 * __db_assert --
128 *	Error when an assertion fails.  Only checked if #DIAGNOSTIC defined.
129 *
130 * PUBLIC: #ifdef DIAGNOSTIC
131 * PUBLIC: void __db_assert __P((ENV *, const char *, const char *, int));
132 * PUBLIC: #endif
133 */
134void
135__db_assert(env, e, file, line)
136	ENV *env;
137	const char *e, *file;
138	int line;
139{
140	__db_errx(env, "assert failure: %s/%d: \"%s\"", file, line, e);
141
142	__os_abort(env);
143	/* NOTREACHED */
144}
145#endif
146
147/*
148 * __env_panic_msg --
149 *	Just report that someone else paniced.
150 *
151 * PUBLIC: int __env_panic_msg __P((ENV *));
152 */
153int
154__env_panic_msg(env)
155	ENV *env;
156{
157	DB_ENV *dbenv;
158	int ret;
159
160	dbenv = env->dbenv;
161
162	ret = DB_RUNRECOVERY;
163
164	__db_errx(env, "PANIC: fatal region error detected; run recovery");
165
166	if (dbenv->db_paniccall != NULL)		/* Deprecated */
167		dbenv->db_paniccall(dbenv, ret);
168	DB_EVENT(env, DB_EVENT_PANIC, &ret);
169
170	return (ret);
171}
172
173/*
174 * __env_panic --
175 *	Lock out the database environment due to unrecoverable error.
176 *
177 * PUBLIC: int __env_panic __P((ENV *, int));
178 */
179int
180__env_panic(env, errval)
181	ENV *env;
182	int errval;
183{
184	DB_ENV *dbenv;
185
186	dbenv = env->dbenv;
187
188	if (env != NULL) {
189		__env_panic_set(env, 1);
190
191		__db_err(env, errval, "PANIC");
192
193		if (dbenv->db_paniccall != NULL)	/* Deprecated */
194			dbenv->db_paniccall(dbenv, errval);
195		DB_EVENT(env, DB_EVENT_PANIC, &errval);
196	}
197
198#if defined(DIAGNOSTIC) && !defined(CONFIG_TEST)
199	/*
200	 * We want a stack trace of how this could possibly happen.
201	 *
202	 * Don't drop core if it's the test suite -- it's reasonable for the
203	 * test suite to check to make sure that DB_RUNRECOVERY is returned
204	 * under certain conditions.
205	 */
206	__os_abort(env);
207	/* NOTREACHED */
208#endif
209
210	/*
211	 * Chaos reigns within.
212	 * Reflect, repent, and reboot.
213	 * Order shall return.
214	 */
215	return (DB_RUNRECOVERY);
216}
217
218/*
219 * db_strerror --
220 *	ANSI C strerror(3) for DB.
221 *
222 * EXTERN: char *db_strerror __P((int));
223 */
224char *
225db_strerror(error)
226	int error;
227{
228	char *p;
229
230	if (error == 0)
231		return ("Successful return: 0");
232	if (error > 0) {
233		if ((p = strerror(error)) != NULL)
234			return (p);
235		return (__db_unknown_error(error));
236	}
237
238	/*
239	 * !!!
240	 * The Tcl API requires that some of these return strings be compared
241	 * against strings stored in application scripts.  So, any of these
242	 * errors that do not invariably result in a Tcl exception may not be
243	 * altered.
244	 */
245	switch (error) {
246	case DB_BUFFER_SMALL:
247		return
248		    ("DB_BUFFER_SMALL: User memory too small for return value");
249	case DB_DONOTINDEX:
250		return ("DB_DONOTINDEX: Secondary index callback returns null");
251	case DB_FOREIGN_CONFLICT:
252		return
253       ("DB_FOREIGN_CONFLICT: A foreign database constraint has been violated");
254	case DB_KEYEMPTY:
255		return ("DB_KEYEMPTY: Non-existent key/data pair");
256	case DB_KEYEXIST:
257		return ("DB_KEYEXIST: Key/data pair already exists");
258	case DB_LOCK_DEADLOCK:
259		return
260		    ("DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock");
261	case DB_LOCK_NOTGRANTED:
262		return ("DB_LOCK_NOTGRANTED: Lock not granted");
263	case DB_LOG_BUFFER_FULL:
264		return ("DB_LOG_BUFFER_FULL: In-memory log buffer is full");
265	case DB_NOSERVER:
266		return ("DB_NOSERVER: Fatal error, no RPC server");
267	case DB_NOSERVER_HOME:
268		return ("DB_NOSERVER_HOME: Home unrecognized at server");
269	case DB_NOSERVER_ID:
270		return ("DB_NOSERVER_ID: Identifier unrecognized at server");
271	case DB_NOTFOUND:
272		return ("DB_NOTFOUND: No matching key/data pair found");
273	case DB_OLD_VERSION:
274		return ("DB_OLDVERSION: Database requires a version upgrade");
275	case DB_PAGE_NOTFOUND:
276		return ("DB_PAGE_NOTFOUND: Requested page not found");
277	case DB_REP_DUPMASTER:
278		return ("DB_REP_DUPMASTER: A second master site appeared");
279	case DB_REP_HANDLE_DEAD:
280		return ("DB_REP_HANDLE_DEAD: Handle is no longer valid");
281	case DB_REP_HOLDELECTION:
282		return ("DB_REP_HOLDELECTION: Need to hold an election");
283	case DB_REP_IGNORE:
284		return ("DB_REP_IGNORE: Replication record ignored");
285	case DB_REP_ISPERM:
286		return ("DB_REP_ISPERM: Permanent record written");
287	case DB_REP_JOIN_FAILURE:
288		return
289	    ("DB_REP_JOIN_FAILURE: Unable to join replication group");
290	case DB_REP_LEASE_EXPIRED:
291		return
292	    ("DB_REP_LEASE_EXPIRED: Replication leases have expired");
293	case DB_REP_LOCKOUT:
294		return
295	    ("DB_REP_LOCKOUT: Waiting for replication recovery to complete");
296	case DB_REP_NEWSITE:
297		return ("DB_REP_NEWSITE: A new site has entered the system");
298	case DB_REP_NOTPERM:
299		return ("DB_REP_NOTPERM: Permanent log record not written");
300	case DB_REP_UNAVAIL:
301		return ("DB_REP_UNAVAIL: Unable to elect a master");
302	case DB_RUNRECOVERY:
303		return ("DB_RUNRECOVERY: Fatal error, run database recovery");
304	case DB_SECONDARY_BAD:
305		return
306	    ("DB_SECONDARY_BAD: Secondary index inconsistent with primary");
307	case DB_VERIFY_BAD:
308		return ("DB_VERIFY_BAD: Database verification failed");
309	case DB_VERSION_MISMATCH:
310		return
311	    ("DB_VERSION_MISMATCH: Database environment version mismatch");
312	default:
313		break;
314	}
315
316	return (__db_unknown_error(error));
317}
318
319/*
320 * __db_unknown_error --
321 *	Format an unknown error value into a static buffer.
322 *
323 * PUBLIC: char *__db_unknown_error __P((int));
324 */
325char *
326__db_unknown_error(error)
327	int error;
328{
329	/*
330	 * !!!
331	 * Room for a 64-bit number + slop.  This buffer is only used
332	 * if we're given an unknown error number, which should never
333	 * happen.
334	 *
335	 * We're no longer thread-safe if it does happen, but the worst
336	 * result is a corrupted error string because there will always
337	 * be a trailing nul byte since the error buffer is nul filled
338	 * and longer than any error message.
339	 */
340	(void)snprintf(DB_GLOBAL(error_buf),
341	    sizeof(DB_GLOBAL(error_buf)), "Unknown error: %d", error);
342	return (DB_GLOBAL(error_buf));
343}
344
345/*
346 * __db_syserr --
347 *	Standard error routine.
348 *
349 * PUBLIC: void __db_syserr __P((const ENV *, int, const char *, ...))
350 * PUBLIC:    __attribute__ ((__format__ (__printf__, 3, 4)));
351 */
352void
353#ifdef STDC_HEADERS
354__db_syserr(const ENV *env, int error, const char *fmt, ...)
355#else
356__db_syserr(env, error, fmt, va_alist)
357	const ENV *env;
358	int error;
359	const char *fmt;
360	va_dcl
361#endif
362{
363	DB_ENV *dbenv;
364
365	dbenv = env == NULL ? NULL : env->dbenv;
366
367	/*
368	 * The same as DB->err, except we don't default to writing to stderr
369	 * after any output channel has been configured, and we use a system-
370	 * specific function to translate errors to strings.
371	 */
372	DB_REAL_ERR(dbenv, error, DB_ERROR_SYSTEM, 0, fmt);
373}
374
375/*
376 * __db_err --
377 *	Standard error routine.
378 *
379 * PUBLIC: void __db_err __P((const ENV *, int, const char *, ...))
380 * PUBLIC:    __attribute__ ((__format__ (__printf__, 3, 4)));
381 */
382void
383#ifdef STDC_HEADERS
384__db_err(const ENV *env, int error, const char *fmt, ...)
385#else
386__db_err(env, error, fmt, va_alist)
387	const ENV *env;
388	int error;
389	const char *fmt;
390	va_dcl
391#endif
392{
393	DB_ENV *dbenv;
394
395	dbenv = env == NULL ? NULL : env->dbenv;
396
397	/*
398	 * The same as DB->err, except we don't default to writing to stderr
399	 * once an output channel has been configured.
400	 */
401	DB_REAL_ERR(dbenv, error, DB_ERROR_SET, 0, fmt);
402}
403
404/*
405 * __db_errx --
406 *	Standard error routine.
407 *
408 * PUBLIC: void __db_errx __P((const ENV *, const char *, ...))
409 * PUBLIC:    __attribute__ ((__format__ (__printf__, 2, 3)));
410 */
411void
412#ifdef STDC_HEADERS
413__db_errx(const ENV *env, const char *fmt, ...)
414#else
415__db_errx(env, fmt, va_alist)
416	const ENV *env;
417	const char *fmt;
418	va_dcl
419#endif
420{
421	DB_ENV *dbenv;
422
423	dbenv = env == NULL ? NULL : env->dbenv;
424
425	/*
426	 * The same as DB->errx, except we don't default to writing to stderr
427	 * once an output channel has been configured.
428	 */
429	DB_REAL_ERR(dbenv, 0, DB_ERROR_NOT_SET, 0, fmt);
430}
431
432/*
433 * __db_errcall --
434 *	Do the error message work for callback functions.
435 *
436 * PUBLIC: void __db_errcall
437 * PUBLIC:    __P((const DB_ENV *, int, db_error_set_t, const char *, va_list));
438 */
439void
440__db_errcall(dbenv, error, error_set, fmt, ap)
441	const DB_ENV *dbenv;
442	int error;
443	db_error_set_t error_set;
444	const char *fmt;
445	va_list ap;
446{
447	char *p;
448	char buf[2048];		/* !!!: END OF THE STACK DON'T TRUST SPRINTF. */
449	char sysbuf[1024];	/* !!!: END OF THE STACK DON'T TRUST SPRINTF. */
450
451	p = buf;
452	if (fmt != NULL)
453		p += vsnprintf(buf, sizeof(buf), fmt, ap);
454	if (error_set != DB_ERROR_NOT_SET)
455		p += snprintf(p,
456		    sizeof(buf) - (size_t)(p - buf), ": %s",
457		    error_set == DB_ERROR_SET ? db_strerror(error) :
458		    __os_strerror(error, sysbuf, sizeof(sysbuf)));
459
460	dbenv->db_errcall(dbenv, dbenv->db_errpfx, buf);
461}
462
463/*
464 * __db_errfile --
465 *	Do the error message work for FILE *s.
466 *
467 * PUBLIC: void __db_errfile
468 * PUBLIC:    __P((const DB_ENV *, int, db_error_set_t, const char *, va_list));
469 */
470void
471__db_errfile(dbenv, error, error_set, fmt, ap)
472	const DB_ENV *dbenv;
473	int error;
474	db_error_set_t error_set;
475	const char *fmt;
476	va_list ap;
477{
478	FILE *fp;
479	int need_sep;
480	char sysbuf[1024];	/* !!!: END OF THE STACK DON'T TRUST SPRINTF. */
481
482	fp = dbenv == NULL ||
483	    dbenv->db_errfile == NULL ? stderr : dbenv->db_errfile;
484	need_sep = 0;
485
486	if (dbenv != NULL && dbenv->db_errpfx != NULL) {
487		(void)fprintf(fp, "%s", dbenv->db_errpfx);
488		need_sep = 1;
489	}
490	if (fmt != NULL && fmt[0] != '\0') {
491		if (need_sep)
492			(void)fprintf(fp, ": ");
493		need_sep = 1;
494		(void)vfprintf(fp, fmt, ap);
495	}
496	if (error_set != DB_ERROR_NOT_SET)
497		(void)fprintf(fp, "%s%s",
498		    need_sep ? ": " : "",
499		    error_set == DB_ERROR_SET ? db_strerror(error) :
500		    __os_strerror(error, sysbuf, sizeof(sysbuf)));
501	(void)fprintf(fp, "\n");
502	(void)fflush(fp);
503}
504
505/*
506 * __db_msgadd --
507 *	Aggregate a set of strings into a buffer for the callback API.
508 *
509 * PUBLIC: void __db_msgadd __P((ENV *, DB_MSGBUF *, const char *, ...))
510 * PUBLIC:    __attribute__ ((__format__ (__printf__, 3, 4)));
511 */
512void
513#ifdef STDC_HEADERS
514__db_msgadd(ENV *env, DB_MSGBUF *mbp, const char *fmt, ...)
515#else
516__db_msgadd(env, mbp, fmt, va_alist)
517	ENV *env;
518	DB_MSGBUF *mbp;
519	const char *fmt;
520	va_dcl
521#endif
522{
523	va_list ap;
524
525#ifdef STDC_HEADERS
526	va_start(ap, fmt);
527#else
528	va_start(ap);
529#endif
530	__db_msgadd_ap(env, mbp, fmt, ap);
531	va_end(ap);
532}
533
534/*
535 * __db_msgadd_ap --
536 *	Aggregate a set of strings into a buffer for the callback API.
537 *
538 * PUBLIC: void __db_msgadd_ap
539 * PUBLIC:     __P((ENV *, DB_MSGBUF *, const char *, va_list));
540 */
541void
542__db_msgadd_ap(env, mbp, fmt, ap)
543	ENV *env;
544	DB_MSGBUF *mbp;
545	const char *fmt;
546	va_list ap;
547{
548	size_t len, olen;
549	char buf[2048];		/* !!!: END OF THE STACK DON'T TRUST SPRINTF. */
550
551	len = (size_t)vsnprintf(buf, sizeof(buf), fmt, ap);
552
553	/*
554	 * There's a heap buffer in the ENV handle we use to aggregate the
555	 * message chunks.  We maintain a pointer to the buffer, the next slot
556	 * to be filled in in the buffer, and a total buffer length.
557	 */
558	olen = (size_t)(mbp->cur - mbp->buf);
559	if (olen + len >= mbp->len) {
560		if (__os_realloc(env, mbp->len + len + 256, &mbp->buf))
561			return;
562		mbp->len += (len + 256);
563		mbp->cur = mbp->buf + olen;
564	}
565
566	memcpy(mbp->cur, buf, len + 1);
567	mbp->cur += len;
568}
569
570/*
571 * __db_msg --
572 *	Standard DB stat message routine.
573 *
574 * PUBLIC: void __db_msg __P((const ENV *, const char *, ...))
575 * PUBLIC:    __attribute__ ((__format__ (__printf__, 2, 3)));
576 */
577void
578#ifdef STDC_HEADERS
579__db_msg(const ENV *env, const char *fmt, ...)
580#else
581__db_msg(env, fmt, va_alist)
582	const ENV *env;
583	const char *fmt;
584	va_dcl
585#endif
586{
587	DB_ENV *dbenv;
588
589	dbenv = env == NULL ? NULL : env->dbenv;
590
591	DB_REAL_MSG(dbenv, fmt);
592}
593
594/*
595 * __db_msgcall --
596 *	Do the message work for callback functions.
597 */
598static void
599__db_msgcall(dbenv, fmt, ap)
600	const DB_ENV *dbenv;
601	const char *fmt;
602	va_list ap;
603{
604	char buf[2048];		/* !!!: END OF THE STACK DON'T TRUST SPRINTF. */
605
606	(void)vsnprintf(buf, sizeof(buf), fmt, ap);
607
608	dbenv->db_msgcall(dbenv, buf);
609}
610
611/*
612 * __db_msgfile --
613 *	Do the message work for FILE *s.
614 */
615static void
616__db_msgfile(dbenv, fmt, ap)
617	const DB_ENV *dbenv;
618	const char *fmt;
619	va_list ap;
620{
621	FILE *fp;
622
623	fp = dbenv == NULL ||
624	    dbenv->db_msgfile == NULL ? stdout : dbenv->db_msgfile;
625	(void)vfprintf(fp, fmt, ap);
626
627	(void)fprintf(fp, "\n");
628	(void)fflush(fp);
629}
630
631/*
632 * __db_unknown_flag -- report internal error
633 *
634 * PUBLIC: int __db_unknown_flag __P((ENV *, char *, u_int32_t));
635 */
636int
637__db_unknown_flag(env, routine, flag)
638	ENV *env;
639	char *routine;
640	u_int32_t flag;
641{
642	__db_errx(env, "%s: Unknown flag: %#x", routine, (u_int)flag);
643
644#ifdef DIAGNOSTIC
645	__os_abort(env);
646	/* NOTREACHED */
647#endif
648	return (EINVAL);
649}
650
651/*
652 * __db_unknown_type -- report internal database type error
653 *
654 * PUBLIC: int __db_unknown_type __P((ENV *, char *, DBTYPE));
655 */
656int
657__db_unknown_type(env, routine, type)
658	ENV *env;
659	char *routine;
660	DBTYPE type;
661{
662	__db_errx(env,
663	    "%s: Unexpected database type: %s",
664	    routine, __db_dbtype_to_string(type));
665
666#ifdef DIAGNOSTIC
667	__os_abort(env);
668	/* NOTREACHED */
669#endif
670	return (EINVAL);
671}
672
673/*
674 * __db_unknown_path -- report unexpected database code path error.
675 *
676 * PUBLIC: int __db_unknown_path __P((ENV *, char *));
677 */
678int
679__db_unknown_path(env, routine)
680	ENV *env;
681	char *routine;
682{
683	__db_errx(env, "%s: Unexpected code path error", routine);
684
685#ifdef DIAGNOSTIC
686	__os_abort(env);
687	/* NOTREACHED */
688#endif
689	return (EINVAL);
690}
691
692/*
693 * __db_check_txn --
694 *	Check for common transaction errors.
695 *
696 * PUBLIC: int __db_check_txn __P((DB *, DB_TXN *, DB_LOCKER *, int));
697 */
698int
699__db_check_txn(dbp, txn, assoc_locker, read_op)
700	DB *dbp;
701	DB_TXN *txn;
702	DB_LOCKER *assoc_locker;
703	int read_op;
704{
705	ENV *env;
706	int isp, ret;
707
708	env = dbp->env;
709
710	/*
711	 * If we are in recovery or aborting a transaction, then we
712	 * don't need to enforce the rules about dbp's not allowing
713	 * transactional operations in non-transactional dbps and
714	 * vica-versa.  This happens all the time as the dbp during
715	 * an abort may be transactional, but we undo operations
716	 * outside a transaction since we're aborting.
717	 */
718	if (IS_RECOVERING(env) || F_ISSET(dbp, DB_AM_RECOVER))
719		return (0);
720
721	/*
722	 * Check for common transaction errors:
723	 *	an operation on a handle whose open commit hasn't completed.
724	 *	a transaction handle in a non-transactional environment
725	 *	a transaction handle for a non-transactional database
726	 */
727	if (txn == NULL || F_ISSET(txn, TXN_PRIVATE)) {
728		if (dbp->cur_locker != NULL &&
729		    dbp->cur_locker->id >= TXN_MINIMUM)
730			goto open_err;
731
732		if (!read_op && F_ISSET(dbp, DB_AM_TXN)) {
733			__db_errx(env,
734		    "Transaction not specified for a transactional database");
735			return (EINVAL);
736		}
737	} else if (F_ISSET(txn, TXN_CDSGROUP)) {
738		if (!CDB_LOCKING(env)) {
739			__db_errx(env,
740			    "CDS groups can only be used in a CDS environment");
741			return (EINVAL);
742		}
743		/*
744		 * CDS group handles can be passed to any method, since they
745		 * only determine locker IDs.
746		 */
747		return (0);
748	} else {
749		if (!TXN_ON(env))
750			 return (__db_not_txn_env(env));
751
752		if (!F_ISSET(dbp, DB_AM_TXN)) {
753			__db_errx(env,
754		    "Transaction specified for a non-transactional database");
755			return (EINVAL);
756		}
757
758		if (F_ISSET(txn, TXN_DEADLOCK))
759			return (__db_txn_deadlock_err(env, txn));
760		if (dbp->cur_locker != NULL &&
761		    dbp->cur_locker->id >= TXN_MINIMUM &&
762		     dbp->cur_locker->id != txn->txnid) {
763			if ((ret = __lock_locker_is_parent(env,
764			     dbp->cur_locker, txn->locker, &isp)) != 0)
765				return (ret);
766			if (!isp)
767				goto open_err;
768		}
769	}
770
771	/*
772	 * If dbp->associate_locker is not NULL, that means we're in
773	 * the middle of a DB->associate with DB_CREATE (i.e., a secondary index
774	 * creation).
775	 *
776	 * In addition to the usual transaction rules, we need to lock out
777	 * non-transactional updates that aren't part of the associate (and
778	 * thus are using some other locker ID).
779	 *
780	 * Transactional updates should simply block;  from the time we
781	 * decide to build the secondary until commit, we'll hold a write
782	 * lock on all of its pages, so it should be safe to attempt to update
783	 * the secondary in another transaction (presumably by updating the
784	 * primary).
785	 */
786	if (!read_op && dbp->associate_locker != NULL &&
787	    txn != NULL && dbp->associate_locker != assoc_locker) {
788		__db_errx(env,
789	    "Operation forbidden while secondary index is being created");
790		return (EINVAL);
791	}
792
793	/*
794	 * Check the txn and dbp are from the same env.
795	 */
796	if (txn != NULL && env != txn->mgrp->env) {
797		__db_errx(env,
798	    "Transaction and database from different environments");
799		return (EINVAL);
800	}
801
802	return (0);
803open_err:
804	__db_errx(env,
805	    "Transaction that opened the DB handle is still active");
806	return (EINVAL);
807}
808
809/*
810 * __db_txn_deadlock_err --
811 *	Transaction has allready been deadlocked.
812 *
813 * PUBLIC: int __db_txn_deadlock_err __P((ENV *, DB_TXN *));
814 */
815int
816__db_txn_deadlock_err(env, txn)
817	ENV *env;
818	DB_TXN *txn;
819{
820	const char *name;
821
822	name = NULL;
823	(void)__txn_get_name(txn, &name);
824
825	__db_errx(env,
826	    "%s%sprevious transaction deadlock return not resolved",
827	    name == NULL ? "" : name, name == NULL ? "" : ": ");
828
829	return (EINVAL);
830}
831
832/*
833 * __db_not_txn_env --
834 *	DB handle must be in an environment that supports transactions.
835 *
836 * PUBLIC: int __db_not_txn_env __P((ENV *));
837 */
838int
839__db_not_txn_env(env)
840	ENV *env;
841{
842	__db_errx(env, "DB environment not configured for transactions");
843	return (EINVAL);
844}
845
846/*
847 * __db_rec_toobig --
848 *	Fixed record length exceeded error message.
849 *
850 * PUBLIC: int __db_rec_toobig __P((ENV *, u_int32_t, u_int32_t));
851 */
852int
853__db_rec_toobig(env, data_len, fixed_rec_len)
854	ENV *env;
855	u_int32_t data_len, fixed_rec_len;
856{
857	__db_errx(env,
858	    "%lu larger than database's maximum record length %lu",
859	    (u_long)data_len, (u_long)fixed_rec_len);
860	return (EINVAL);
861}
862
863/*
864 * __db_rec_repl --
865 *	Fixed record replacement length error message.
866 *
867 * PUBLIC: int __db_rec_repl __P((ENV *, u_int32_t, u_int32_t));
868 */
869int
870__db_rec_repl(env, data_size, data_dlen)
871	ENV *env;
872	u_int32_t data_size, data_dlen;
873{
874	__db_errx(env,
875	    "%s: replacement length %lu differs from replaced length %lu",
876	    "Record length error", (u_long)data_size, (u_long)data_dlen);
877	return (EINVAL);
878}
879
880#if defined(DIAGNOSTIC) || defined(DEBUG_ROP)  || defined(DEBUG_WOP)
881/*
882 * __dbc_logging --
883 *	In DIAGNOSTIC mode, check for bad replication combinations.
884 *
885 * PUBLIC: int __dbc_logging __P((DBC *));
886 */
887int
888__dbc_logging(dbc)
889	DBC *dbc;
890{
891	DB_REP *db_rep;
892	ENV *env;
893	int ret;
894
895	env = dbc->env;
896	db_rep = env->rep_handle;
897
898	ret = LOGGING_ON(env) &&
899	    !F_ISSET(dbc, DBC_RECOVER) && !IS_REP_CLIENT(env);
900
901	/*
902	 * If we're not using replication or running recovery, return.
903	 */
904	if (db_rep == NULL || F_ISSET(dbc, DBC_RECOVER))
905		return (ret);
906
907#ifndef	DEBUG_ROP
908	/*
909	 *  Only check when DEBUG_ROP is not configured.  People often do
910	 * non-transactional reads, and debug_rop is going to write
911	 * a log record.
912	 */
913	{
914	REP *rep;
915
916	rep = db_rep->region;
917
918	/*
919	 * If we're a client and not running recovery or non durably, error.
920	 */
921	if (IS_REP_CLIENT(env) && !F_ISSET(dbc->dbp, DB_AM_NOT_DURABLE)) {
922		__db_errx(env, "dbc_logging: Client update");
923		goto err;
924	}
925
926#ifndef DEBUG_WOP
927	/*
928	 * If DEBUG_WOP is enabled, then we'll generate debugging log records
929	 * that are non-transactional.  This is OK.
930	 */
931	if (IS_REP_MASTER(env) &&
932	    dbc->txn == NULL && !F_ISSET(dbc->dbp, DB_AM_NOT_DURABLE)) {
933		__db_errx(env, "Dbc_logging: Master non-txn update");
934		goto err;
935	}
936#endif
937
938	if (0) {
939err:		__db_errx(env, "Rep: flags 0x%lx msg_th %lu",
940		    (u_long)rep->flags, (u_long)rep->msg_th);
941		__db_errx(env, "Rep: handle %lu, opcnt %lu",
942		    (u_long)rep->handle_cnt, (u_long)rep->op_cnt);
943		__os_abort(env);
944		/* NOTREACHED */
945	}
946	}
947#endif
948	return (ret);
949}
950#endif
951
952/*
953 * __db_check_lsn --
954 *	Display the log sequence error message.
955 *
956 * PUBLIC: int __db_check_lsn __P((ENV *, DB_LSN *, DB_LSN *));
957 */
958int
959__db_check_lsn(env, lsn, prev)
960	ENV *env;
961	DB_LSN *lsn, *prev;
962{
963	__db_errx(env,
964	    "Log sequence error: page LSN %lu %lu; previous LSN %lu %lu",
965	    (u_long)(lsn)->file, (u_long)(lsn)->offset,
966	    (u_long)(prev)->file, (u_long)(prev)->offset);
967	return (EINVAL);
968}
969
970/*
971 * __db_rdonly --
972 *	Common readonly message.
973 * PUBLIC: int __db_rdonly __P((const ENV *, const char *));
974 */
975int
976__db_rdonly(env, name)
977	const ENV *env;
978	const char *name;
979{
980	__db_errx(env, "%s: attempt to modify a read-only database", name);
981	return (EACCES);
982}
983
984/*
985 * __db_space_err --
986 *	Common out of space message.
987 * PUBLIC: int __db_space_err __P((const DB *));
988 */
989int
990__db_space_err(dbp)
991	const DB *dbp;
992{
993	__db_errx(dbp->env,
994	    "%s: file limited to %lu pages",
995	    dbp->fname, (u_long)dbp->mpf->mfp->maxpgno);
996	return (ENOSPC);
997}
998
999/*
1000 * __db_failed --
1001 *	Common failed thread  message.
1002 *
1003 * PUBLIC: int __db_failed __P((const ENV *,
1004 * PUBLIC:      const char *, pid_t, db_threadid_t));
1005 */
1006int
1007__db_failed(env, msg, pid, tid)
1008	const ENV *env;
1009	const char *msg;
1010	pid_t pid;
1011	db_threadid_t tid;
1012{
1013	DB_ENV *dbenv;
1014	char buf[DB_THREADID_STRLEN];
1015
1016	dbenv = env->dbenv;
1017
1018	__db_errx(env, "Thread/process %s failed: %s",
1019	    dbenv->thread_id_string(dbenv, pid, tid, buf),  msg);
1020	return (DB_RUNRECOVERY);
1021}
1022