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