1/* Do not edit: automatically built by gen_rec.awk. */
2
3#include "db_config.h"
4#include "db_int.h"
5#include "dbinc/crypto.h"
6#include "dbinc/db_page.h"
7#include "dbinc/db_am.h"
8#include "dbinc/btree.h"
9#include "dbinc/log.h"
10#include "dbinc/txn.h"
11
12/*
13 * PUBLIC: int __bam_split_read __P((ENV *, DB **, void *, void *,
14 * PUBLIC:     __bam_split_args **));
15 */
16int
17__bam_split_read(env, dbpp, td, recbuf, argpp)
18	ENV *env;
19	DB **dbpp;
20	void *td;
21	void *recbuf;
22	__bam_split_args **argpp;
23{
24	__bam_split_args *argp;
25	u_int32_t uinttmp;
26	u_int8_t *bp;
27	int ret;
28
29	if ((ret = __os_malloc(env,
30	    sizeof(__bam_split_args) + sizeof(DB_TXN), &argp)) != 0)
31		return (ret);
32	bp = recbuf;
33	argp->txnp = (DB_TXN *)&argp[1];
34	memset(argp->txnp, 0, sizeof(DB_TXN));
35
36	argp->txnp->td = td;
37	LOGCOPY_32(env, &argp->type, bp);
38	bp += sizeof(argp->type);
39
40	LOGCOPY_32(env, &argp->txnp->txnid, bp);
41	bp += sizeof(argp->txnp->txnid);
42
43	LOGCOPY_TOLSN(env, &argp->prev_lsn, bp);
44	bp += sizeof(DB_LSN);
45
46	LOGCOPY_32(env, &uinttmp, bp);
47	argp->fileid = (int32_t)uinttmp;
48	bp += sizeof(uinttmp);
49	if (dbpp != NULL) {
50		*dbpp = NULL;
51		ret = __dbreg_id_to_db(
52		    env, argp->txnp, dbpp, argp->fileid, 1);
53	}
54
55	LOGCOPY_32(env, &uinttmp, bp);
56	argp->left = (db_pgno_t)uinttmp;
57	bp += sizeof(uinttmp);
58
59	LOGCOPY_TOLSN(env, &argp->llsn, bp);
60	bp += sizeof(DB_LSN);
61
62	LOGCOPY_32(env, &uinttmp, bp);
63	argp->right = (db_pgno_t)uinttmp;
64	bp += sizeof(uinttmp);
65
66	LOGCOPY_TOLSN(env, &argp->rlsn, bp);
67	bp += sizeof(DB_LSN);
68
69	LOGCOPY_32(env, &argp->indx, bp);
70	bp += sizeof(argp->indx);
71
72	LOGCOPY_32(env, &uinttmp, bp);
73	argp->npgno = (db_pgno_t)uinttmp;
74	bp += sizeof(uinttmp);
75
76	LOGCOPY_TOLSN(env, &argp->nlsn, bp);
77	bp += sizeof(DB_LSN);
78
79	LOGCOPY_32(env, &uinttmp, bp);
80	argp->ppgno = (db_pgno_t)uinttmp;
81	bp += sizeof(uinttmp);
82
83	LOGCOPY_TOLSN(env, &argp->plsn, bp);
84	bp += sizeof(DB_LSN);
85
86	LOGCOPY_32(env, &argp->pindx, bp);
87	bp += sizeof(argp->pindx);
88
89	memset(&argp->pg, 0, sizeof(argp->pg));
90	LOGCOPY_32(env,&argp->pg.size, bp);
91	bp += sizeof(u_int32_t);
92	argp->pg.data = bp;
93	bp += argp->pg.size;
94	if (LOG_SWAPPED(env) && dbpp != NULL && *dbpp != NULL) {
95		int t_ret;
96		if ((t_ret = __db_pageswap(*dbpp, (PAGE *)argp->pg.data,
97		    (size_t)argp->pg.size, NULL, 1)) != 0)
98			return (t_ret);
99	}
100
101	memset(&argp->pentry, 0, sizeof(argp->pentry));
102	LOGCOPY_32(env,&argp->pentry.size, bp);
103	bp += sizeof(u_int32_t);
104	argp->pentry.data = bp;
105	bp += argp->pentry.size;
106
107	memset(&argp->rentry, 0, sizeof(argp->rentry));
108	LOGCOPY_32(env,&argp->rentry.size, bp);
109	bp += sizeof(u_int32_t);
110	argp->rentry.data = bp;
111	bp += argp->rentry.size;
112
113	LOGCOPY_32(env, &argp->opflags, bp);
114	bp += sizeof(argp->opflags);
115
116	*argpp = argp;
117	return (ret);
118}
119
120/*
121 * PUBLIC: int __bam_split_log __P((DB *, DB_TXN *, DB_LSN *,
122 * PUBLIC:     u_int32_t, db_pgno_t, DB_LSN *, db_pgno_t, DB_LSN *, u_int32_t,
123 * PUBLIC:     db_pgno_t, DB_LSN *, db_pgno_t, DB_LSN *, u_int32_t, const DBT *,
124 * PUBLIC:     const DBT *, const DBT *, u_int32_t));
125 */
126int
127__bam_split_log(dbp, txnp, ret_lsnp, flags, left, llsn, right, rlsn, indx,
128    npgno, nlsn, ppgno, plsn, pindx, pg,
129    pentry, rentry, opflags)
130	DB *dbp;
131	DB_TXN *txnp;
132	DB_LSN *ret_lsnp;
133	u_int32_t flags;
134	db_pgno_t left;
135	DB_LSN * llsn;
136	db_pgno_t right;
137	DB_LSN * rlsn;
138	u_int32_t indx;
139	db_pgno_t npgno;
140	DB_LSN * nlsn;
141	db_pgno_t ppgno;
142	DB_LSN * plsn;
143	u_int32_t pindx;
144	const DBT *pg;
145	const DBT *pentry;
146	const DBT *rentry;
147	u_int32_t opflags;
148{
149	DBT logrec;
150	DB_LSN *lsnp, null_lsn, *rlsnp;
151	DB_TXNLOGREC *lr;
152	ENV *env;
153	u_int32_t zero, uinttmp, rectype, txn_num;
154	u_int npad;
155	u_int8_t *bp;
156	int is_durable, ret;
157
158	COMPQUIET(lr, NULL);
159
160	env = dbp->env;
161	rlsnp = ret_lsnp;
162	rectype = DB___bam_split;
163	npad = 0;
164	ret = 0;
165
166	if (LF_ISSET(DB_LOG_NOT_DURABLE) ||
167	    F_ISSET(dbp, DB_AM_NOT_DURABLE)) {
168		if (txnp == NULL)
169			return (0);
170		is_durable = 0;
171	} else
172		is_durable = 1;
173
174	if (txnp == NULL) {
175		txn_num = 0;
176		lsnp = &null_lsn;
177		null_lsn.file = null_lsn.offset = 0;
178	} else {
179		if (TAILQ_FIRST(&txnp->kids) != NULL &&
180		    (ret = __txn_activekids(env, rectype, txnp)) != 0)
181			return (ret);
182		/*
183		 * We need to assign begin_lsn while holding region mutex.
184		 * That assignment is done inside the DbEnv->log_put call,
185		 * so pass in the appropriate memory location to be filled
186		 * in by the log_put code.
187		 */
188		DB_SET_TXN_LSNP(txnp, &rlsnp, &lsnp);
189		txn_num = txnp->txnid;
190	}
191
192	DB_ASSERT(env, dbp->log_filename != NULL);
193	if (dbp->log_filename->id == DB_LOGFILEID_INVALID &&
194	    (ret = __dbreg_lazy_id(dbp)) != 0)
195		return (ret);
196
197	logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
198	    + sizeof(u_int32_t)
199	    + sizeof(u_int32_t)
200	    + sizeof(*llsn)
201	    + sizeof(u_int32_t)
202	    + sizeof(*rlsn)
203	    + sizeof(u_int32_t)
204	    + sizeof(u_int32_t)
205	    + sizeof(*nlsn)
206	    + sizeof(u_int32_t)
207	    + sizeof(*plsn)
208	    + sizeof(u_int32_t)
209	    + sizeof(u_int32_t) + (pg == NULL ? 0 : pg->size)
210	    + sizeof(u_int32_t) + (pentry == NULL ? 0 : pentry->size)
211	    + sizeof(u_int32_t) + (rentry == NULL ? 0 : rentry->size)
212	    + sizeof(u_int32_t);
213	if (CRYPTO_ON(env)) {
214		npad = env->crypto_handle->adj_size(logrec.size);
215		logrec.size += npad;
216	}
217
218	if (is_durable || txnp == NULL) {
219		if ((ret =
220		    __os_malloc(env, logrec.size, &logrec.data)) != 0)
221			return (ret);
222	} else {
223		if ((ret = __os_malloc(env,
224		    logrec.size + sizeof(DB_TXNLOGREC), &lr)) != 0)
225			return (ret);
226#ifdef DIAGNOSTIC
227		if ((ret =
228		    __os_malloc(env, logrec.size, &logrec.data)) != 0) {
229			__os_free(env, lr);
230			return (ret);
231		}
232#else
233		logrec.data = lr->data;
234#endif
235	}
236	if (npad > 0)
237		memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad);
238
239	bp = logrec.data;
240
241	LOGCOPY_32(env, bp, &rectype);
242	bp += sizeof(rectype);
243
244	LOGCOPY_32(env, bp, &txn_num);
245	bp += sizeof(txn_num);
246
247	LOGCOPY_FROMLSN(env, bp, lsnp);
248	bp += sizeof(DB_LSN);
249
250	uinttmp = (u_int32_t)dbp->log_filename->id;
251	LOGCOPY_32(env, bp, &uinttmp);
252	bp += sizeof(uinttmp);
253
254	uinttmp = (u_int32_t)left;
255	LOGCOPY_32(env,bp, &uinttmp);
256	bp += sizeof(uinttmp);
257
258	if (llsn != NULL) {
259		if (txnp != NULL) {
260			LOG *lp = env->lg_handle->reginfo.primary;
261			if (LOG_COMPARE(llsn, &lp->lsn) >= 0 && (ret =
262			    __log_check_page_lsn(env, dbp, llsn)) != 0)
263				return (ret);
264		}
265		LOGCOPY_FROMLSN(env, bp, llsn);
266	} else
267		memset(bp, 0, sizeof(*llsn));
268	bp += sizeof(*llsn);
269
270	uinttmp = (u_int32_t)right;
271	LOGCOPY_32(env,bp, &uinttmp);
272	bp += sizeof(uinttmp);
273
274	if (rlsn != NULL) {
275		if (txnp != NULL) {
276			LOG *lp = env->lg_handle->reginfo.primary;
277			if (LOG_COMPARE(rlsn, &lp->lsn) >= 0 && (ret =
278			    __log_check_page_lsn(env, dbp, rlsn)) != 0)
279				return (ret);
280		}
281		LOGCOPY_FROMLSN(env, bp, rlsn);
282	} else
283		memset(bp, 0, sizeof(*rlsn));
284	bp += sizeof(*rlsn);
285
286	LOGCOPY_32(env, bp, &indx);
287	bp += sizeof(indx);
288
289	uinttmp = (u_int32_t)npgno;
290	LOGCOPY_32(env,bp, &uinttmp);
291	bp += sizeof(uinttmp);
292
293	if (nlsn != NULL) {
294		if (txnp != NULL) {
295			LOG *lp = env->lg_handle->reginfo.primary;
296			if (LOG_COMPARE(nlsn, &lp->lsn) >= 0 && (ret =
297			    __log_check_page_lsn(env, dbp, nlsn)) != 0)
298				return (ret);
299		}
300		LOGCOPY_FROMLSN(env, bp, nlsn);
301	} else
302		memset(bp, 0, sizeof(*nlsn));
303	bp += sizeof(*nlsn);
304
305	uinttmp = (u_int32_t)ppgno;
306	LOGCOPY_32(env,bp, &uinttmp);
307	bp += sizeof(uinttmp);
308
309	if (plsn != NULL) {
310		if (txnp != NULL) {
311			LOG *lp = env->lg_handle->reginfo.primary;
312			if (LOG_COMPARE(plsn, &lp->lsn) >= 0 && (ret =
313			    __log_check_page_lsn(env, dbp, plsn)) != 0)
314				return (ret);
315		}
316		LOGCOPY_FROMLSN(env, bp, plsn);
317	} else
318		memset(bp, 0, sizeof(*plsn));
319	bp += sizeof(*plsn);
320
321	LOGCOPY_32(env, bp, &pindx);
322	bp += sizeof(pindx);
323
324	if (pg == NULL) {
325		zero = 0;
326		LOGCOPY_32(env, bp, &zero);
327		bp += sizeof(u_int32_t);
328	} else {
329		LOGCOPY_32(env, bp, &pg->size);
330		bp += sizeof(pg->size);
331		memcpy(bp, pg->data, pg->size);
332		if (LOG_SWAPPED(env))
333			if ((ret = __db_pageswap(dbp,
334			    (PAGE *)bp, (size_t)pg->size, (DBT *)NULL, 0)) != 0)
335				return (ret);
336		bp += pg->size;
337	}
338
339	if (pentry == NULL) {
340		zero = 0;
341		LOGCOPY_32(env, bp, &zero);
342		bp += sizeof(u_int32_t);
343	} else {
344		LOGCOPY_32(env, bp, &pentry->size);
345		bp += sizeof(pentry->size);
346		memcpy(bp, pentry->data, pentry->size);
347		bp += pentry->size;
348	}
349
350	if (rentry == NULL) {
351		zero = 0;
352		LOGCOPY_32(env, bp, &zero);
353		bp += sizeof(u_int32_t);
354	} else {
355		LOGCOPY_32(env, bp, &rentry->size);
356		bp += sizeof(rentry->size);
357		memcpy(bp, rentry->data, rentry->size);
358		bp += rentry->size;
359	}
360
361	LOGCOPY_32(env, bp, &opflags);
362	bp += sizeof(opflags);
363
364	DB_ASSERT(env,
365	    (u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size);
366
367	if (is_durable || txnp == NULL) {
368		if ((ret = __log_put(env, rlsnp,(DBT *)&logrec,
369		    flags | DB_LOG_NOCOPY)) == 0 && txnp != NULL) {
370			*lsnp = *rlsnp;
371			if (rlsnp != ret_lsnp)
372				 *ret_lsnp = *rlsnp;
373		}
374	} else {
375		ret = 0;
376#ifdef DIAGNOSTIC
377		/*
378		 * Set the debug bit if we are going to log non-durable
379		 * transactions so they will be ignored by recovery.
380		 */
381		memcpy(lr->data, logrec.data, logrec.size);
382		rectype |= DB_debug_FLAG;
383		LOGCOPY_32(env, logrec.data, &rectype);
384
385		if (!IS_REP_CLIENT(env))
386			ret = __log_put(env,
387			    rlsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
388#endif
389		STAILQ_INSERT_HEAD(&txnp->logs, lr, links);
390		F_SET((TXN_DETAIL *)txnp->td, TXN_DTL_INMEMORY);
391		LSN_NOT_LOGGED(*ret_lsnp);
392	}
393
394#ifdef LOG_DIAGNOSTIC
395	if (ret != 0)
396		(void)__bam_split_print(env,
397		    (DBT *)&logrec, ret_lsnp, DB_TXN_PRINT, NULL);
398#endif
399
400#ifdef DIAGNOSTIC
401	__os_free(env, logrec.data);
402#else
403	if (is_durable || txnp == NULL)
404		__os_free(env, logrec.data);
405#endif
406	return (ret);
407}
408
409/*
410 * PUBLIC: int __bam_split_42_read __P((ENV *, DB **, void *,
411 * PUBLIC:     void *, __bam_split_42_args **));
412 */
413int
414__bam_split_42_read(env, dbpp, td, recbuf, argpp)
415	ENV *env;
416	DB **dbpp;
417	void *td;
418	void *recbuf;
419	__bam_split_42_args **argpp;
420{
421	__bam_split_42_args *argp;
422	u_int32_t uinttmp;
423	u_int8_t *bp;
424	int ret;
425
426	if ((ret = __os_malloc(env,
427	    sizeof(__bam_split_42_args) + sizeof(DB_TXN), &argp)) != 0)
428		return (ret);
429	bp = recbuf;
430	argp->txnp = (DB_TXN *)&argp[1];
431	memset(argp->txnp, 0, sizeof(DB_TXN));
432
433	argp->txnp->td = td;
434	LOGCOPY_32(env, &argp->type, bp);
435	bp += sizeof(argp->type);
436
437	LOGCOPY_32(env, &argp->txnp->txnid, bp);
438	bp += sizeof(argp->txnp->txnid);
439
440	LOGCOPY_TOLSN(env, &argp->prev_lsn, bp);
441	bp += sizeof(DB_LSN);
442
443	LOGCOPY_32(env, &uinttmp, bp);
444	argp->fileid = (int32_t)uinttmp;
445	bp += sizeof(uinttmp);
446	if (dbpp != NULL) {
447		*dbpp = NULL;
448		ret = __dbreg_id_to_db(
449		    env, argp->txnp, dbpp, argp->fileid, 1);
450	}
451
452	LOGCOPY_32(env, &uinttmp, bp);
453	argp->left = (db_pgno_t)uinttmp;
454	bp += sizeof(uinttmp);
455
456	LOGCOPY_TOLSN(env, &argp->llsn, bp);
457	bp += sizeof(DB_LSN);
458
459	LOGCOPY_32(env, &uinttmp, bp);
460	argp->right = (db_pgno_t)uinttmp;
461	bp += sizeof(uinttmp);
462
463	LOGCOPY_TOLSN(env, &argp->rlsn, bp);
464	bp += sizeof(DB_LSN);
465
466	LOGCOPY_32(env, &argp->indx, bp);
467	bp += sizeof(argp->indx);
468
469	LOGCOPY_32(env, &uinttmp, bp);
470	argp->npgno = (db_pgno_t)uinttmp;
471	bp += sizeof(uinttmp);
472
473	LOGCOPY_TOLSN(env, &argp->nlsn, bp);
474	bp += sizeof(DB_LSN);
475
476	LOGCOPY_32(env, &uinttmp, bp);
477	argp->root_pgno = (db_pgno_t)uinttmp;
478	bp += sizeof(uinttmp);
479
480	memset(&argp->pg, 0, sizeof(argp->pg));
481	LOGCOPY_32(env,&argp->pg.size, bp);
482	bp += sizeof(u_int32_t);
483	argp->pg.data = bp;
484	bp += argp->pg.size;
485
486	LOGCOPY_32(env, &argp->opflags, bp);
487	bp += sizeof(argp->opflags);
488
489	*argpp = argp;
490	return (ret);
491}
492
493/*
494 * PUBLIC: int __bam_rsplit_read __P((ENV *, DB **, void *, void *,
495 * PUBLIC:     __bam_rsplit_args **));
496 */
497int
498__bam_rsplit_read(env, dbpp, td, recbuf, argpp)
499	ENV *env;
500	DB **dbpp;
501	void *td;
502	void *recbuf;
503	__bam_rsplit_args **argpp;
504{
505	__bam_rsplit_args *argp;
506	u_int32_t uinttmp;
507	u_int8_t *bp;
508	int ret;
509
510	if ((ret = __os_malloc(env,
511	    sizeof(__bam_rsplit_args) + sizeof(DB_TXN), &argp)) != 0)
512		return (ret);
513	bp = recbuf;
514	argp->txnp = (DB_TXN *)&argp[1];
515	memset(argp->txnp, 0, sizeof(DB_TXN));
516
517	argp->txnp->td = td;
518	LOGCOPY_32(env, &argp->type, bp);
519	bp += sizeof(argp->type);
520
521	LOGCOPY_32(env, &argp->txnp->txnid, bp);
522	bp += sizeof(argp->txnp->txnid);
523
524	LOGCOPY_TOLSN(env, &argp->prev_lsn, bp);
525	bp += sizeof(DB_LSN);
526
527	LOGCOPY_32(env, &uinttmp, bp);
528	argp->fileid = (int32_t)uinttmp;
529	bp += sizeof(uinttmp);
530	if (dbpp != NULL) {
531		*dbpp = NULL;
532		ret = __dbreg_id_to_db(
533		    env, argp->txnp, dbpp, argp->fileid, 1);
534	}
535
536	LOGCOPY_32(env, &uinttmp, bp);
537	argp->pgno = (db_pgno_t)uinttmp;
538	bp += sizeof(uinttmp);
539
540	memset(&argp->pgdbt, 0, sizeof(argp->pgdbt));
541	LOGCOPY_32(env,&argp->pgdbt.size, bp);
542	bp += sizeof(u_int32_t);
543	argp->pgdbt.data = bp;
544	bp += argp->pgdbt.size;
545	if (LOG_SWAPPED(env) && dbpp != NULL && *dbpp != NULL) {
546		int t_ret;
547		if ((t_ret = __db_pageswap(*dbpp, (PAGE *)argp->pgdbt.data,
548		    (size_t)argp->pgdbt.size, NULL, 1)) != 0)
549			return (t_ret);
550	}
551
552	LOGCOPY_32(env, &uinttmp, bp);
553	argp->root_pgno = (db_pgno_t)uinttmp;
554	bp += sizeof(uinttmp);
555
556	LOGCOPY_32(env, &uinttmp, bp);
557	argp->nrec = (db_pgno_t)uinttmp;
558	bp += sizeof(uinttmp);
559
560	memset(&argp->rootent, 0, sizeof(argp->rootent));
561	LOGCOPY_32(env,&argp->rootent.size, bp);
562	bp += sizeof(u_int32_t);
563	argp->rootent.data = bp;
564	bp += argp->rootent.size;
565
566	LOGCOPY_TOLSN(env, &argp->rootlsn, bp);
567	bp += sizeof(DB_LSN);
568
569	*argpp = argp;
570	return (ret);
571}
572
573/*
574 * PUBLIC: int __bam_rsplit_log __P((DB *, DB_TXN *, DB_LSN *,
575 * PUBLIC:     u_int32_t, db_pgno_t, const DBT *, db_pgno_t, db_pgno_t,
576 * PUBLIC:     const DBT *, DB_LSN *));
577 */
578int
579__bam_rsplit_log(dbp, txnp, ret_lsnp, flags, pgno, pgdbt, root_pgno, nrec, rootent,
580    rootlsn)
581	DB *dbp;
582	DB_TXN *txnp;
583	DB_LSN *ret_lsnp;
584	u_int32_t flags;
585	db_pgno_t pgno;
586	const DBT *pgdbt;
587	db_pgno_t root_pgno;
588	db_pgno_t nrec;
589	const DBT *rootent;
590	DB_LSN * rootlsn;
591{
592	DBT logrec;
593	DB_LSN *lsnp, null_lsn, *rlsnp;
594	DB_TXNLOGREC *lr;
595	ENV *env;
596	u_int32_t zero, uinttmp, rectype, txn_num;
597	u_int npad;
598	u_int8_t *bp;
599	int is_durable, ret;
600
601	COMPQUIET(lr, NULL);
602
603	env = dbp->env;
604	rlsnp = ret_lsnp;
605	rectype = DB___bam_rsplit;
606	npad = 0;
607	ret = 0;
608
609	if (LF_ISSET(DB_LOG_NOT_DURABLE) ||
610	    F_ISSET(dbp, DB_AM_NOT_DURABLE)) {
611		if (txnp == NULL)
612			return (0);
613		is_durable = 0;
614	} else
615		is_durable = 1;
616
617	if (txnp == NULL) {
618		txn_num = 0;
619		lsnp = &null_lsn;
620		null_lsn.file = null_lsn.offset = 0;
621	} else {
622		if (TAILQ_FIRST(&txnp->kids) != NULL &&
623		    (ret = __txn_activekids(env, rectype, txnp)) != 0)
624			return (ret);
625		/*
626		 * We need to assign begin_lsn while holding region mutex.
627		 * That assignment is done inside the DbEnv->log_put call,
628		 * so pass in the appropriate memory location to be filled
629		 * in by the log_put code.
630		 */
631		DB_SET_TXN_LSNP(txnp, &rlsnp, &lsnp);
632		txn_num = txnp->txnid;
633	}
634
635	DB_ASSERT(env, dbp->log_filename != NULL);
636	if (dbp->log_filename->id == DB_LOGFILEID_INVALID &&
637	    (ret = __dbreg_lazy_id(dbp)) != 0)
638		return (ret);
639
640	logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
641	    + sizeof(u_int32_t)
642	    + sizeof(u_int32_t)
643	    + sizeof(u_int32_t) + (pgdbt == NULL ? 0 : pgdbt->size)
644	    + sizeof(u_int32_t)
645	    + sizeof(u_int32_t)
646	    + sizeof(u_int32_t) + (rootent == NULL ? 0 : rootent->size)
647	    + sizeof(*rootlsn);
648	if (CRYPTO_ON(env)) {
649		npad = env->crypto_handle->adj_size(logrec.size);
650		logrec.size += npad;
651	}
652
653	if (is_durable || txnp == NULL) {
654		if ((ret =
655		    __os_malloc(env, logrec.size, &logrec.data)) != 0)
656			return (ret);
657	} else {
658		if ((ret = __os_malloc(env,
659		    logrec.size + sizeof(DB_TXNLOGREC), &lr)) != 0)
660			return (ret);
661#ifdef DIAGNOSTIC
662		if ((ret =
663		    __os_malloc(env, logrec.size, &logrec.data)) != 0) {
664			__os_free(env, lr);
665			return (ret);
666		}
667#else
668		logrec.data = lr->data;
669#endif
670	}
671	if (npad > 0)
672		memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad);
673
674	bp = logrec.data;
675
676	LOGCOPY_32(env, bp, &rectype);
677	bp += sizeof(rectype);
678
679	LOGCOPY_32(env, bp, &txn_num);
680	bp += sizeof(txn_num);
681
682	LOGCOPY_FROMLSN(env, bp, lsnp);
683	bp += sizeof(DB_LSN);
684
685	uinttmp = (u_int32_t)dbp->log_filename->id;
686	LOGCOPY_32(env, bp, &uinttmp);
687	bp += sizeof(uinttmp);
688
689	uinttmp = (u_int32_t)pgno;
690	LOGCOPY_32(env,bp, &uinttmp);
691	bp += sizeof(uinttmp);
692
693	if (pgdbt == NULL) {
694		zero = 0;
695		LOGCOPY_32(env, bp, &zero);
696		bp += sizeof(u_int32_t);
697	} else {
698		LOGCOPY_32(env, bp, &pgdbt->size);
699		bp += sizeof(pgdbt->size);
700		memcpy(bp, pgdbt->data, pgdbt->size);
701		if (LOG_SWAPPED(env))
702			if ((ret = __db_pageswap(dbp,
703			    (PAGE *)bp, (size_t)pgdbt->size, (DBT *)NULL, 0)) != 0)
704				return (ret);
705		bp += pgdbt->size;
706	}
707
708	uinttmp = (u_int32_t)root_pgno;
709	LOGCOPY_32(env,bp, &uinttmp);
710	bp += sizeof(uinttmp);
711
712	uinttmp = (u_int32_t)nrec;
713	LOGCOPY_32(env,bp, &uinttmp);
714	bp += sizeof(uinttmp);
715
716	if (rootent == NULL) {
717		zero = 0;
718		LOGCOPY_32(env, bp, &zero);
719		bp += sizeof(u_int32_t);
720	} else {
721		LOGCOPY_32(env, bp, &rootent->size);
722		bp += sizeof(rootent->size);
723		memcpy(bp, rootent->data, rootent->size);
724		bp += rootent->size;
725	}
726
727	if (rootlsn != NULL) {
728		if (txnp != NULL) {
729			LOG *lp = env->lg_handle->reginfo.primary;
730			if (LOG_COMPARE(rootlsn, &lp->lsn) >= 0 && (ret =
731			    __log_check_page_lsn(env, dbp, rootlsn)) != 0)
732				return (ret);
733		}
734		LOGCOPY_FROMLSN(env, bp, rootlsn);
735	} else
736		memset(bp, 0, sizeof(*rootlsn));
737	bp += sizeof(*rootlsn);
738
739	DB_ASSERT(env,
740	    (u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size);
741
742	if (is_durable || txnp == NULL) {
743		if ((ret = __log_put(env, rlsnp,(DBT *)&logrec,
744		    flags | DB_LOG_NOCOPY)) == 0 && txnp != NULL) {
745			*lsnp = *rlsnp;
746			if (rlsnp != ret_lsnp)
747				 *ret_lsnp = *rlsnp;
748		}
749	} else {
750		ret = 0;
751#ifdef DIAGNOSTIC
752		/*
753		 * Set the debug bit if we are going to log non-durable
754		 * transactions so they will be ignored by recovery.
755		 */
756		memcpy(lr->data, logrec.data, logrec.size);
757		rectype |= DB_debug_FLAG;
758		LOGCOPY_32(env, logrec.data, &rectype);
759
760		if (!IS_REP_CLIENT(env))
761			ret = __log_put(env,
762			    rlsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
763#endif
764		STAILQ_INSERT_HEAD(&txnp->logs, lr, links);
765		F_SET((TXN_DETAIL *)txnp->td, TXN_DTL_INMEMORY);
766		LSN_NOT_LOGGED(*ret_lsnp);
767	}
768
769#ifdef LOG_DIAGNOSTIC
770	if (ret != 0)
771		(void)__bam_rsplit_print(env,
772		    (DBT *)&logrec, ret_lsnp, DB_TXN_PRINT, NULL);
773#endif
774
775#ifdef DIAGNOSTIC
776	__os_free(env, logrec.data);
777#else
778	if (is_durable || txnp == NULL)
779		__os_free(env, logrec.data);
780#endif
781	return (ret);
782}
783
784/*
785 * PUBLIC: int __bam_adj_read __P((ENV *, DB **, void *, void *,
786 * PUBLIC:     __bam_adj_args **));
787 */
788int
789__bam_adj_read(env, dbpp, td, recbuf, argpp)
790	ENV *env;
791	DB **dbpp;
792	void *td;
793	void *recbuf;
794	__bam_adj_args **argpp;
795{
796	__bam_adj_args *argp;
797	u_int32_t uinttmp;
798	u_int8_t *bp;
799	int ret;
800
801	if ((ret = __os_malloc(env,
802	    sizeof(__bam_adj_args) + sizeof(DB_TXN), &argp)) != 0)
803		return (ret);
804	bp = recbuf;
805	argp->txnp = (DB_TXN *)&argp[1];
806	memset(argp->txnp, 0, sizeof(DB_TXN));
807
808	argp->txnp->td = td;
809	LOGCOPY_32(env, &argp->type, bp);
810	bp += sizeof(argp->type);
811
812	LOGCOPY_32(env, &argp->txnp->txnid, bp);
813	bp += sizeof(argp->txnp->txnid);
814
815	LOGCOPY_TOLSN(env, &argp->prev_lsn, bp);
816	bp += sizeof(DB_LSN);
817
818	LOGCOPY_32(env, &uinttmp, bp);
819	argp->fileid = (int32_t)uinttmp;
820	bp += sizeof(uinttmp);
821	if (dbpp != NULL) {
822		*dbpp = NULL;
823		ret = __dbreg_id_to_db(
824		    env, argp->txnp, dbpp, argp->fileid, 1);
825	}
826
827	LOGCOPY_32(env, &uinttmp, bp);
828	argp->pgno = (db_pgno_t)uinttmp;
829	bp += sizeof(uinttmp);
830
831	LOGCOPY_TOLSN(env, &argp->lsn, bp);
832	bp += sizeof(DB_LSN);
833
834	LOGCOPY_32(env, &argp->indx, bp);
835	bp += sizeof(argp->indx);
836
837	LOGCOPY_32(env, &argp->indx_copy, bp);
838	bp += sizeof(argp->indx_copy);
839
840	LOGCOPY_32(env, &argp->is_insert, bp);
841	bp += sizeof(argp->is_insert);
842
843	*argpp = argp;
844	return (ret);
845}
846
847/*
848 * PUBLIC: int __bam_adj_log __P((DB *, DB_TXN *, DB_LSN *,
849 * PUBLIC:     u_int32_t, db_pgno_t, DB_LSN *, u_int32_t, u_int32_t,
850 * PUBLIC:     u_int32_t));
851 */
852int
853__bam_adj_log(dbp, txnp, ret_lsnp, flags, pgno, lsn, indx, indx_copy, is_insert)
854	DB *dbp;
855	DB_TXN *txnp;
856	DB_LSN *ret_lsnp;
857	u_int32_t flags;
858	db_pgno_t pgno;
859	DB_LSN * lsn;
860	u_int32_t indx;
861	u_int32_t indx_copy;
862	u_int32_t is_insert;
863{
864	DBT logrec;
865	DB_LSN *lsnp, null_lsn, *rlsnp;
866	DB_TXNLOGREC *lr;
867	ENV *env;
868	u_int32_t uinttmp, rectype, txn_num;
869	u_int npad;
870	u_int8_t *bp;
871	int is_durable, ret;
872
873	COMPQUIET(lr, NULL);
874
875	env = dbp->env;
876	rlsnp = ret_lsnp;
877	rectype = DB___bam_adj;
878	npad = 0;
879	ret = 0;
880
881	if (LF_ISSET(DB_LOG_NOT_DURABLE) ||
882	    F_ISSET(dbp, DB_AM_NOT_DURABLE)) {
883		if (txnp == NULL)
884			return (0);
885		is_durable = 0;
886	} else
887		is_durable = 1;
888
889	if (txnp == NULL) {
890		txn_num = 0;
891		lsnp = &null_lsn;
892		null_lsn.file = null_lsn.offset = 0;
893	} else {
894		if (TAILQ_FIRST(&txnp->kids) != NULL &&
895		    (ret = __txn_activekids(env, rectype, txnp)) != 0)
896			return (ret);
897		/*
898		 * We need to assign begin_lsn while holding region mutex.
899		 * That assignment is done inside the DbEnv->log_put call,
900		 * so pass in the appropriate memory location to be filled
901		 * in by the log_put code.
902		 */
903		DB_SET_TXN_LSNP(txnp, &rlsnp, &lsnp);
904		txn_num = txnp->txnid;
905	}
906
907	DB_ASSERT(env, dbp->log_filename != NULL);
908	if (dbp->log_filename->id == DB_LOGFILEID_INVALID &&
909	    (ret = __dbreg_lazy_id(dbp)) != 0)
910		return (ret);
911
912	logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
913	    + sizeof(u_int32_t)
914	    + sizeof(u_int32_t)
915	    + sizeof(*lsn)
916	    + sizeof(u_int32_t)
917	    + sizeof(u_int32_t)
918	    + sizeof(u_int32_t);
919	if (CRYPTO_ON(env)) {
920		npad = env->crypto_handle->adj_size(logrec.size);
921		logrec.size += npad;
922	}
923
924	if (is_durable || txnp == NULL) {
925		if ((ret =
926		    __os_malloc(env, logrec.size, &logrec.data)) != 0)
927			return (ret);
928	} else {
929		if ((ret = __os_malloc(env,
930		    logrec.size + sizeof(DB_TXNLOGREC), &lr)) != 0)
931			return (ret);
932#ifdef DIAGNOSTIC
933		if ((ret =
934		    __os_malloc(env, logrec.size, &logrec.data)) != 0) {
935			__os_free(env, lr);
936			return (ret);
937		}
938#else
939		logrec.data = lr->data;
940#endif
941	}
942	if (npad > 0)
943		memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad);
944
945	bp = logrec.data;
946
947	LOGCOPY_32(env, bp, &rectype);
948	bp += sizeof(rectype);
949
950	LOGCOPY_32(env, bp, &txn_num);
951	bp += sizeof(txn_num);
952
953	LOGCOPY_FROMLSN(env, bp, lsnp);
954	bp += sizeof(DB_LSN);
955
956	uinttmp = (u_int32_t)dbp->log_filename->id;
957	LOGCOPY_32(env, bp, &uinttmp);
958	bp += sizeof(uinttmp);
959
960	uinttmp = (u_int32_t)pgno;
961	LOGCOPY_32(env,bp, &uinttmp);
962	bp += sizeof(uinttmp);
963
964	if (lsn != NULL) {
965		if (txnp != NULL) {
966			LOG *lp = env->lg_handle->reginfo.primary;
967			if (LOG_COMPARE(lsn, &lp->lsn) >= 0 && (ret =
968			    __log_check_page_lsn(env, dbp, lsn)) != 0)
969				return (ret);
970		}
971		LOGCOPY_FROMLSN(env, bp, lsn);
972	} else
973		memset(bp, 0, sizeof(*lsn));
974	bp += sizeof(*lsn);
975
976	LOGCOPY_32(env, bp, &indx);
977	bp += sizeof(indx);
978
979	LOGCOPY_32(env, bp, &indx_copy);
980	bp += sizeof(indx_copy);
981
982	LOGCOPY_32(env, bp, &is_insert);
983	bp += sizeof(is_insert);
984
985	DB_ASSERT(env,
986	    (u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size);
987
988	if (is_durable || txnp == NULL) {
989		if ((ret = __log_put(env, rlsnp,(DBT *)&logrec,
990		    flags | DB_LOG_NOCOPY)) == 0 && txnp != NULL) {
991			*lsnp = *rlsnp;
992			if (rlsnp != ret_lsnp)
993				 *ret_lsnp = *rlsnp;
994		}
995	} else {
996		ret = 0;
997#ifdef DIAGNOSTIC
998		/*
999		 * Set the debug bit if we are going to log non-durable
1000		 * transactions so they will be ignored by recovery.
1001		 */
1002		memcpy(lr->data, logrec.data, logrec.size);
1003		rectype |= DB_debug_FLAG;
1004		LOGCOPY_32(env, logrec.data, &rectype);
1005
1006		if (!IS_REP_CLIENT(env))
1007			ret = __log_put(env,
1008			    rlsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
1009#endif
1010		STAILQ_INSERT_HEAD(&txnp->logs, lr, links);
1011		F_SET((TXN_DETAIL *)txnp->td, TXN_DTL_INMEMORY);
1012		LSN_NOT_LOGGED(*ret_lsnp);
1013	}
1014
1015#ifdef LOG_DIAGNOSTIC
1016	if (ret != 0)
1017		(void)__bam_adj_print(env,
1018		    (DBT *)&logrec, ret_lsnp, DB_TXN_PRINT, NULL);
1019#endif
1020
1021#ifdef DIAGNOSTIC
1022	__os_free(env, logrec.data);
1023#else
1024	if (is_durable || txnp == NULL)
1025		__os_free(env, logrec.data);
1026#endif
1027	return (ret);
1028}
1029
1030/*
1031 * PUBLIC: int __bam_cadjust_read __P((ENV *, DB **, void *, void *,
1032 * PUBLIC:     __bam_cadjust_args **));
1033 */
1034int
1035__bam_cadjust_read(env, dbpp, td, recbuf, argpp)
1036	ENV *env;
1037	DB **dbpp;
1038	void *td;
1039	void *recbuf;
1040	__bam_cadjust_args **argpp;
1041{
1042	__bam_cadjust_args *argp;
1043	u_int32_t uinttmp;
1044	u_int8_t *bp;
1045	int ret;
1046
1047	if ((ret = __os_malloc(env,
1048	    sizeof(__bam_cadjust_args) + sizeof(DB_TXN), &argp)) != 0)
1049		return (ret);
1050	bp = recbuf;
1051	argp->txnp = (DB_TXN *)&argp[1];
1052	memset(argp->txnp, 0, sizeof(DB_TXN));
1053
1054	argp->txnp->td = td;
1055	LOGCOPY_32(env, &argp->type, bp);
1056	bp += sizeof(argp->type);
1057
1058	LOGCOPY_32(env, &argp->txnp->txnid, bp);
1059	bp += sizeof(argp->txnp->txnid);
1060
1061	LOGCOPY_TOLSN(env, &argp->prev_lsn, bp);
1062	bp += sizeof(DB_LSN);
1063
1064	LOGCOPY_32(env, &uinttmp, bp);
1065	argp->fileid = (int32_t)uinttmp;
1066	bp += sizeof(uinttmp);
1067	if (dbpp != NULL) {
1068		*dbpp = NULL;
1069		ret = __dbreg_id_to_db(
1070		    env, argp->txnp, dbpp, argp->fileid, 1);
1071	}
1072
1073	LOGCOPY_32(env, &uinttmp, bp);
1074	argp->pgno = (db_pgno_t)uinttmp;
1075	bp += sizeof(uinttmp);
1076
1077	LOGCOPY_TOLSN(env, &argp->lsn, bp);
1078	bp += sizeof(DB_LSN);
1079
1080	LOGCOPY_32(env, &argp->indx, bp);
1081	bp += sizeof(argp->indx);
1082
1083	LOGCOPY_32(env, &uinttmp, bp);
1084	argp->adjust = (int32_t)uinttmp;
1085	bp += sizeof(uinttmp);
1086
1087	LOGCOPY_32(env, &argp->opflags, bp);
1088	bp += sizeof(argp->opflags);
1089
1090	*argpp = argp;
1091	return (ret);
1092}
1093
1094/*
1095 * PUBLIC: int __bam_cadjust_log __P((DB *, DB_TXN *, DB_LSN *,
1096 * PUBLIC:     u_int32_t, db_pgno_t, DB_LSN *, u_int32_t, int32_t, u_int32_t));
1097 */
1098int
1099__bam_cadjust_log(dbp, txnp, ret_lsnp, flags, pgno, lsn, indx, adjust, opflags)
1100	DB *dbp;
1101	DB_TXN *txnp;
1102	DB_LSN *ret_lsnp;
1103	u_int32_t flags;
1104	db_pgno_t pgno;
1105	DB_LSN * lsn;
1106	u_int32_t indx;
1107	int32_t adjust;
1108	u_int32_t opflags;
1109{
1110	DBT logrec;
1111	DB_LSN *lsnp, null_lsn, *rlsnp;
1112	DB_TXNLOGREC *lr;
1113	ENV *env;
1114	u_int32_t uinttmp, rectype, txn_num;
1115	u_int npad;
1116	u_int8_t *bp;
1117	int is_durable, ret;
1118
1119	COMPQUIET(lr, NULL);
1120
1121	env = dbp->env;
1122	rlsnp = ret_lsnp;
1123	rectype = DB___bam_cadjust;
1124	npad = 0;
1125	ret = 0;
1126
1127	if (LF_ISSET(DB_LOG_NOT_DURABLE) ||
1128	    F_ISSET(dbp, DB_AM_NOT_DURABLE)) {
1129		if (txnp == NULL)
1130			return (0);
1131		is_durable = 0;
1132	} else
1133		is_durable = 1;
1134
1135	if (txnp == NULL) {
1136		txn_num = 0;
1137		lsnp = &null_lsn;
1138		null_lsn.file = null_lsn.offset = 0;
1139	} else {
1140		if (TAILQ_FIRST(&txnp->kids) != NULL &&
1141		    (ret = __txn_activekids(env, rectype, txnp)) != 0)
1142			return (ret);
1143		/*
1144		 * We need to assign begin_lsn while holding region mutex.
1145		 * That assignment is done inside the DbEnv->log_put call,
1146		 * so pass in the appropriate memory location to be filled
1147		 * in by the log_put code.
1148		 */
1149		DB_SET_TXN_LSNP(txnp, &rlsnp, &lsnp);
1150		txn_num = txnp->txnid;
1151	}
1152
1153	DB_ASSERT(env, dbp->log_filename != NULL);
1154	if (dbp->log_filename->id == DB_LOGFILEID_INVALID &&
1155	    (ret = __dbreg_lazy_id(dbp)) != 0)
1156		return (ret);
1157
1158	logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
1159	    + sizeof(u_int32_t)
1160	    + sizeof(u_int32_t)
1161	    + sizeof(*lsn)
1162	    + sizeof(u_int32_t)
1163	    + sizeof(u_int32_t)
1164	    + sizeof(u_int32_t);
1165	if (CRYPTO_ON(env)) {
1166		npad = env->crypto_handle->adj_size(logrec.size);
1167		logrec.size += npad;
1168	}
1169
1170	if (is_durable || txnp == NULL) {
1171		if ((ret =
1172		    __os_malloc(env, logrec.size, &logrec.data)) != 0)
1173			return (ret);
1174	} else {
1175		if ((ret = __os_malloc(env,
1176		    logrec.size + sizeof(DB_TXNLOGREC), &lr)) != 0)
1177			return (ret);
1178#ifdef DIAGNOSTIC
1179		if ((ret =
1180		    __os_malloc(env, logrec.size, &logrec.data)) != 0) {
1181			__os_free(env, lr);
1182			return (ret);
1183		}
1184#else
1185		logrec.data = lr->data;
1186#endif
1187	}
1188	if (npad > 0)
1189		memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad);
1190
1191	bp = logrec.data;
1192
1193	LOGCOPY_32(env, bp, &rectype);
1194	bp += sizeof(rectype);
1195
1196	LOGCOPY_32(env, bp, &txn_num);
1197	bp += sizeof(txn_num);
1198
1199	LOGCOPY_FROMLSN(env, bp, lsnp);
1200	bp += sizeof(DB_LSN);
1201
1202	uinttmp = (u_int32_t)dbp->log_filename->id;
1203	LOGCOPY_32(env, bp, &uinttmp);
1204	bp += sizeof(uinttmp);
1205
1206	uinttmp = (u_int32_t)pgno;
1207	LOGCOPY_32(env,bp, &uinttmp);
1208	bp += sizeof(uinttmp);
1209
1210	if (lsn != NULL) {
1211		if (txnp != NULL) {
1212			LOG *lp = env->lg_handle->reginfo.primary;
1213			if (LOG_COMPARE(lsn, &lp->lsn) >= 0 && (ret =
1214			    __log_check_page_lsn(env, dbp, lsn)) != 0)
1215				return (ret);
1216		}
1217		LOGCOPY_FROMLSN(env, bp, lsn);
1218	} else
1219		memset(bp, 0, sizeof(*lsn));
1220	bp += sizeof(*lsn);
1221
1222	LOGCOPY_32(env, bp, &indx);
1223	bp += sizeof(indx);
1224
1225	uinttmp = (u_int32_t)adjust;
1226	LOGCOPY_32(env,bp, &uinttmp);
1227	bp += sizeof(uinttmp);
1228
1229	LOGCOPY_32(env, bp, &opflags);
1230	bp += sizeof(opflags);
1231
1232	DB_ASSERT(env,
1233	    (u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size);
1234
1235	if (is_durable || txnp == NULL) {
1236		if ((ret = __log_put(env, rlsnp,(DBT *)&logrec,
1237		    flags | DB_LOG_NOCOPY)) == 0 && txnp != NULL) {
1238			*lsnp = *rlsnp;
1239			if (rlsnp != ret_lsnp)
1240				 *ret_lsnp = *rlsnp;
1241		}
1242	} else {
1243		ret = 0;
1244#ifdef DIAGNOSTIC
1245		/*
1246		 * Set the debug bit if we are going to log non-durable
1247		 * transactions so they will be ignored by recovery.
1248		 */
1249		memcpy(lr->data, logrec.data, logrec.size);
1250		rectype |= DB_debug_FLAG;
1251		LOGCOPY_32(env, logrec.data, &rectype);
1252
1253		if (!IS_REP_CLIENT(env))
1254			ret = __log_put(env,
1255			    rlsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
1256#endif
1257		STAILQ_INSERT_HEAD(&txnp->logs, lr, links);
1258		F_SET((TXN_DETAIL *)txnp->td, TXN_DTL_INMEMORY);
1259		LSN_NOT_LOGGED(*ret_lsnp);
1260	}
1261
1262#ifdef LOG_DIAGNOSTIC
1263	if (ret != 0)
1264		(void)__bam_cadjust_print(env,
1265		    (DBT *)&logrec, ret_lsnp, DB_TXN_PRINT, NULL);
1266#endif
1267
1268#ifdef DIAGNOSTIC
1269	__os_free(env, logrec.data);
1270#else
1271	if (is_durable || txnp == NULL)
1272		__os_free(env, logrec.data);
1273#endif
1274	return (ret);
1275}
1276
1277/*
1278 * PUBLIC: int __bam_cdel_read __P((ENV *, DB **, void *, void *,
1279 * PUBLIC:     __bam_cdel_args **));
1280 */
1281int
1282__bam_cdel_read(env, dbpp, td, recbuf, argpp)
1283	ENV *env;
1284	DB **dbpp;
1285	void *td;
1286	void *recbuf;
1287	__bam_cdel_args **argpp;
1288{
1289	__bam_cdel_args *argp;
1290	u_int32_t uinttmp;
1291	u_int8_t *bp;
1292	int ret;
1293
1294	if ((ret = __os_malloc(env,
1295	    sizeof(__bam_cdel_args) + sizeof(DB_TXN), &argp)) != 0)
1296		return (ret);
1297	bp = recbuf;
1298	argp->txnp = (DB_TXN *)&argp[1];
1299	memset(argp->txnp, 0, sizeof(DB_TXN));
1300
1301	argp->txnp->td = td;
1302	LOGCOPY_32(env, &argp->type, bp);
1303	bp += sizeof(argp->type);
1304
1305	LOGCOPY_32(env, &argp->txnp->txnid, bp);
1306	bp += sizeof(argp->txnp->txnid);
1307
1308	LOGCOPY_TOLSN(env, &argp->prev_lsn, bp);
1309	bp += sizeof(DB_LSN);
1310
1311	LOGCOPY_32(env, &uinttmp, bp);
1312	argp->fileid = (int32_t)uinttmp;
1313	bp += sizeof(uinttmp);
1314	if (dbpp != NULL) {
1315		*dbpp = NULL;
1316		ret = __dbreg_id_to_db(
1317		    env, argp->txnp, dbpp, argp->fileid, 1);
1318	}
1319
1320	LOGCOPY_32(env, &uinttmp, bp);
1321	argp->pgno = (db_pgno_t)uinttmp;
1322	bp += sizeof(uinttmp);
1323
1324	LOGCOPY_TOLSN(env, &argp->lsn, bp);
1325	bp += sizeof(DB_LSN);
1326
1327	LOGCOPY_32(env, &argp->indx, bp);
1328	bp += sizeof(argp->indx);
1329
1330	*argpp = argp;
1331	return (ret);
1332}
1333
1334/*
1335 * PUBLIC: int __bam_cdel_log __P((DB *, DB_TXN *, DB_LSN *,
1336 * PUBLIC:     u_int32_t, db_pgno_t, DB_LSN *, u_int32_t));
1337 */
1338int
1339__bam_cdel_log(dbp, txnp, ret_lsnp, flags, pgno, lsn, indx)
1340	DB *dbp;
1341	DB_TXN *txnp;
1342	DB_LSN *ret_lsnp;
1343	u_int32_t flags;
1344	db_pgno_t pgno;
1345	DB_LSN * lsn;
1346	u_int32_t indx;
1347{
1348	DBT logrec;
1349	DB_LSN *lsnp, null_lsn, *rlsnp;
1350	DB_TXNLOGREC *lr;
1351	ENV *env;
1352	u_int32_t uinttmp, rectype, txn_num;
1353	u_int npad;
1354	u_int8_t *bp;
1355	int is_durable, ret;
1356
1357	COMPQUIET(lr, NULL);
1358
1359	env = dbp->env;
1360	rlsnp = ret_lsnp;
1361	rectype = DB___bam_cdel;
1362	npad = 0;
1363	ret = 0;
1364
1365	if (LF_ISSET(DB_LOG_NOT_DURABLE) ||
1366	    F_ISSET(dbp, DB_AM_NOT_DURABLE)) {
1367		if (txnp == NULL)
1368			return (0);
1369		is_durable = 0;
1370	} else
1371		is_durable = 1;
1372
1373	if (txnp == NULL) {
1374		txn_num = 0;
1375		lsnp = &null_lsn;
1376		null_lsn.file = null_lsn.offset = 0;
1377	} else {
1378		if (TAILQ_FIRST(&txnp->kids) != NULL &&
1379		    (ret = __txn_activekids(env, rectype, txnp)) != 0)
1380			return (ret);
1381		/*
1382		 * We need to assign begin_lsn while holding region mutex.
1383		 * That assignment is done inside the DbEnv->log_put call,
1384		 * so pass in the appropriate memory location to be filled
1385		 * in by the log_put code.
1386		 */
1387		DB_SET_TXN_LSNP(txnp, &rlsnp, &lsnp);
1388		txn_num = txnp->txnid;
1389	}
1390
1391	DB_ASSERT(env, dbp->log_filename != NULL);
1392	if (dbp->log_filename->id == DB_LOGFILEID_INVALID &&
1393	    (ret = __dbreg_lazy_id(dbp)) != 0)
1394		return (ret);
1395
1396	logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
1397	    + sizeof(u_int32_t)
1398	    + sizeof(u_int32_t)
1399	    + sizeof(*lsn)
1400	    + sizeof(u_int32_t);
1401	if (CRYPTO_ON(env)) {
1402		npad = env->crypto_handle->adj_size(logrec.size);
1403		logrec.size += npad;
1404	}
1405
1406	if (is_durable || txnp == NULL) {
1407		if ((ret =
1408		    __os_malloc(env, logrec.size, &logrec.data)) != 0)
1409			return (ret);
1410	} else {
1411		if ((ret = __os_malloc(env,
1412		    logrec.size + sizeof(DB_TXNLOGREC), &lr)) != 0)
1413			return (ret);
1414#ifdef DIAGNOSTIC
1415		if ((ret =
1416		    __os_malloc(env, logrec.size, &logrec.data)) != 0) {
1417			__os_free(env, lr);
1418			return (ret);
1419		}
1420#else
1421		logrec.data = lr->data;
1422#endif
1423	}
1424	if (npad > 0)
1425		memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad);
1426
1427	bp = logrec.data;
1428
1429	LOGCOPY_32(env, bp, &rectype);
1430	bp += sizeof(rectype);
1431
1432	LOGCOPY_32(env, bp, &txn_num);
1433	bp += sizeof(txn_num);
1434
1435	LOGCOPY_FROMLSN(env, bp, lsnp);
1436	bp += sizeof(DB_LSN);
1437
1438	uinttmp = (u_int32_t)dbp->log_filename->id;
1439	LOGCOPY_32(env, bp, &uinttmp);
1440	bp += sizeof(uinttmp);
1441
1442	uinttmp = (u_int32_t)pgno;
1443	LOGCOPY_32(env,bp, &uinttmp);
1444	bp += sizeof(uinttmp);
1445
1446	if (lsn != NULL) {
1447		if (txnp != NULL) {
1448			LOG *lp = env->lg_handle->reginfo.primary;
1449			if (LOG_COMPARE(lsn, &lp->lsn) >= 0 && (ret =
1450			    __log_check_page_lsn(env, dbp, lsn)) != 0)
1451				return (ret);
1452		}
1453		LOGCOPY_FROMLSN(env, bp, lsn);
1454	} else
1455		memset(bp, 0, sizeof(*lsn));
1456	bp += sizeof(*lsn);
1457
1458	LOGCOPY_32(env, bp, &indx);
1459	bp += sizeof(indx);
1460
1461	DB_ASSERT(env,
1462	    (u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size);
1463
1464	if (is_durable || txnp == NULL) {
1465		if ((ret = __log_put(env, rlsnp,(DBT *)&logrec,
1466		    flags | DB_LOG_NOCOPY)) == 0 && txnp != NULL) {
1467			*lsnp = *rlsnp;
1468			if (rlsnp != ret_lsnp)
1469				 *ret_lsnp = *rlsnp;
1470		}
1471	} else {
1472		ret = 0;
1473#ifdef DIAGNOSTIC
1474		/*
1475		 * Set the debug bit if we are going to log non-durable
1476		 * transactions so they will be ignored by recovery.
1477		 */
1478		memcpy(lr->data, logrec.data, logrec.size);
1479		rectype |= DB_debug_FLAG;
1480		LOGCOPY_32(env, logrec.data, &rectype);
1481
1482		if (!IS_REP_CLIENT(env))
1483			ret = __log_put(env,
1484			    rlsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
1485#endif
1486		STAILQ_INSERT_HEAD(&txnp->logs, lr, links);
1487		F_SET((TXN_DETAIL *)txnp->td, TXN_DTL_INMEMORY);
1488		LSN_NOT_LOGGED(*ret_lsnp);
1489	}
1490
1491#ifdef LOG_DIAGNOSTIC
1492	if (ret != 0)
1493		(void)__bam_cdel_print(env,
1494		    (DBT *)&logrec, ret_lsnp, DB_TXN_PRINT, NULL);
1495#endif
1496
1497#ifdef DIAGNOSTIC
1498	__os_free(env, logrec.data);
1499#else
1500	if (is_durable || txnp == NULL)
1501		__os_free(env, logrec.data);
1502#endif
1503	return (ret);
1504}
1505
1506/*
1507 * PUBLIC: int __bam_repl_read __P((ENV *, DB **, void *, void *,
1508 * PUBLIC:     __bam_repl_args **));
1509 */
1510int
1511__bam_repl_read(env, dbpp, td, recbuf, argpp)
1512	ENV *env;
1513	DB **dbpp;
1514	void *td;
1515	void *recbuf;
1516	__bam_repl_args **argpp;
1517{
1518	__bam_repl_args *argp;
1519	u_int32_t uinttmp;
1520	u_int8_t *bp;
1521	int ret;
1522
1523	if ((ret = __os_malloc(env,
1524	    sizeof(__bam_repl_args) + sizeof(DB_TXN), &argp)) != 0)
1525		return (ret);
1526	bp = recbuf;
1527	argp->txnp = (DB_TXN *)&argp[1];
1528	memset(argp->txnp, 0, sizeof(DB_TXN));
1529
1530	argp->txnp->td = td;
1531	LOGCOPY_32(env, &argp->type, bp);
1532	bp += sizeof(argp->type);
1533
1534	LOGCOPY_32(env, &argp->txnp->txnid, bp);
1535	bp += sizeof(argp->txnp->txnid);
1536
1537	LOGCOPY_TOLSN(env, &argp->prev_lsn, bp);
1538	bp += sizeof(DB_LSN);
1539
1540	LOGCOPY_32(env, &uinttmp, bp);
1541	argp->fileid = (int32_t)uinttmp;
1542	bp += sizeof(uinttmp);
1543	if (dbpp != NULL) {
1544		*dbpp = NULL;
1545		ret = __dbreg_id_to_db(
1546		    env, argp->txnp, dbpp, argp->fileid, 1);
1547	}
1548
1549	LOGCOPY_32(env, &uinttmp, bp);
1550	argp->pgno = (db_pgno_t)uinttmp;
1551	bp += sizeof(uinttmp);
1552
1553	LOGCOPY_TOLSN(env, &argp->lsn, bp);
1554	bp += sizeof(DB_LSN);
1555
1556	LOGCOPY_32(env, &argp->indx, bp);
1557	bp += sizeof(argp->indx);
1558
1559	LOGCOPY_32(env, &argp->isdeleted, bp);
1560	bp += sizeof(argp->isdeleted);
1561
1562	memset(&argp->orig, 0, sizeof(argp->orig));
1563	LOGCOPY_32(env,&argp->orig.size, bp);
1564	bp += sizeof(u_int32_t);
1565	argp->orig.data = bp;
1566	bp += argp->orig.size;
1567
1568	memset(&argp->repl, 0, sizeof(argp->repl));
1569	LOGCOPY_32(env,&argp->repl.size, bp);
1570	bp += sizeof(u_int32_t);
1571	argp->repl.data = bp;
1572	bp += argp->repl.size;
1573
1574	LOGCOPY_32(env, &argp->prefix, bp);
1575	bp += sizeof(argp->prefix);
1576
1577	LOGCOPY_32(env, &argp->suffix, bp);
1578	bp += sizeof(argp->suffix);
1579
1580	*argpp = argp;
1581	return (ret);
1582}
1583
1584/*
1585 * PUBLIC: int __bam_repl_log __P((DB *, DB_TXN *, DB_LSN *,
1586 * PUBLIC:     u_int32_t, db_pgno_t, DB_LSN *, u_int32_t, u_int32_t,
1587 * PUBLIC:     const DBT *, const DBT *, u_int32_t, u_int32_t));
1588 */
1589int
1590__bam_repl_log(dbp, txnp, ret_lsnp, flags, pgno, lsn, indx, isdeleted, orig,
1591    repl, prefix, suffix)
1592	DB *dbp;
1593	DB_TXN *txnp;
1594	DB_LSN *ret_lsnp;
1595	u_int32_t flags;
1596	db_pgno_t pgno;
1597	DB_LSN * lsn;
1598	u_int32_t indx;
1599	u_int32_t isdeleted;
1600	const DBT *orig;
1601	const DBT *repl;
1602	u_int32_t prefix;
1603	u_int32_t suffix;
1604{
1605	DBT logrec;
1606	DB_LSN *lsnp, null_lsn, *rlsnp;
1607	DB_TXNLOGREC *lr;
1608	ENV *env;
1609	u_int32_t zero, uinttmp, rectype, txn_num;
1610	u_int npad;
1611	u_int8_t *bp;
1612	int is_durable, ret;
1613
1614	COMPQUIET(lr, NULL);
1615
1616	env = dbp->env;
1617	rlsnp = ret_lsnp;
1618	rectype = DB___bam_repl;
1619	npad = 0;
1620	ret = 0;
1621
1622	if (LF_ISSET(DB_LOG_NOT_DURABLE) ||
1623	    F_ISSET(dbp, DB_AM_NOT_DURABLE)) {
1624		if (txnp == NULL)
1625			return (0);
1626		is_durable = 0;
1627	} else
1628		is_durable = 1;
1629
1630	if (txnp == NULL) {
1631		txn_num = 0;
1632		lsnp = &null_lsn;
1633		null_lsn.file = null_lsn.offset = 0;
1634	} else {
1635		if (TAILQ_FIRST(&txnp->kids) != NULL &&
1636		    (ret = __txn_activekids(env, rectype, txnp)) != 0)
1637			return (ret);
1638		/*
1639		 * We need to assign begin_lsn while holding region mutex.
1640		 * That assignment is done inside the DbEnv->log_put call,
1641		 * so pass in the appropriate memory location to be filled
1642		 * in by the log_put code.
1643		 */
1644		DB_SET_TXN_LSNP(txnp, &rlsnp, &lsnp);
1645		txn_num = txnp->txnid;
1646	}
1647
1648	DB_ASSERT(env, dbp->log_filename != NULL);
1649	if (dbp->log_filename->id == DB_LOGFILEID_INVALID &&
1650	    (ret = __dbreg_lazy_id(dbp)) != 0)
1651		return (ret);
1652
1653	logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
1654	    + sizeof(u_int32_t)
1655	    + sizeof(u_int32_t)
1656	    + sizeof(*lsn)
1657	    + sizeof(u_int32_t)
1658	    + sizeof(u_int32_t)
1659	    + sizeof(u_int32_t) + (orig == NULL ? 0 : orig->size)
1660	    + sizeof(u_int32_t) + (repl == NULL ? 0 : repl->size)
1661	    + sizeof(u_int32_t)
1662	    + sizeof(u_int32_t);
1663	if (CRYPTO_ON(env)) {
1664		npad = env->crypto_handle->adj_size(logrec.size);
1665		logrec.size += npad;
1666	}
1667
1668	if (is_durable || txnp == NULL) {
1669		if ((ret =
1670		    __os_malloc(env, logrec.size, &logrec.data)) != 0)
1671			return (ret);
1672	} else {
1673		if ((ret = __os_malloc(env,
1674		    logrec.size + sizeof(DB_TXNLOGREC), &lr)) != 0)
1675			return (ret);
1676#ifdef DIAGNOSTIC
1677		if ((ret =
1678		    __os_malloc(env, logrec.size, &logrec.data)) != 0) {
1679			__os_free(env, lr);
1680			return (ret);
1681		}
1682#else
1683		logrec.data = lr->data;
1684#endif
1685	}
1686	if (npad > 0)
1687		memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad);
1688
1689	bp = logrec.data;
1690
1691	LOGCOPY_32(env, bp, &rectype);
1692	bp += sizeof(rectype);
1693
1694	LOGCOPY_32(env, bp, &txn_num);
1695	bp += sizeof(txn_num);
1696
1697	LOGCOPY_FROMLSN(env, bp, lsnp);
1698	bp += sizeof(DB_LSN);
1699
1700	uinttmp = (u_int32_t)dbp->log_filename->id;
1701	LOGCOPY_32(env, bp, &uinttmp);
1702	bp += sizeof(uinttmp);
1703
1704	uinttmp = (u_int32_t)pgno;
1705	LOGCOPY_32(env,bp, &uinttmp);
1706	bp += sizeof(uinttmp);
1707
1708	if (lsn != NULL) {
1709		if (txnp != NULL) {
1710			LOG *lp = env->lg_handle->reginfo.primary;
1711			if (LOG_COMPARE(lsn, &lp->lsn) >= 0 && (ret =
1712			    __log_check_page_lsn(env, dbp, lsn)) != 0)
1713				return (ret);
1714		}
1715		LOGCOPY_FROMLSN(env, bp, lsn);
1716	} else
1717		memset(bp, 0, sizeof(*lsn));
1718	bp += sizeof(*lsn);
1719
1720	LOGCOPY_32(env, bp, &indx);
1721	bp += sizeof(indx);
1722
1723	LOGCOPY_32(env, bp, &isdeleted);
1724	bp += sizeof(isdeleted);
1725
1726	if (orig == NULL) {
1727		zero = 0;
1728		LOGCOPY_32(env, bp, &zero);
1729		bp += sizeof(u_int32_t);
1730	} else {
1731		LOGCOPY_32(env, bp, &orig->size);
1732		bp += sizeof(orig->size);
1733		memcpy(bp, orig->data, orig->size);
1734		bp += orig->size;
1735	}
1736
1737	if (repl == NULL) {
1738		zero = 0;
1739		LOGCOPY_32(env, bp, &zero);
1740		bp += sizeof(u_int32_t);
1741	} else {
1742		LOGCOPY_32(env, bp, &repl->size);
1743		bp += sizeof(repl->size);
1744		memcpy(bp, repl->data, repl->size);
1745		bp += repl->size;
1746	}
1747
1748	LOGCOPY_32(env, bp, &prefix);
1749	bp += sizeof(prefix);
1750
1751	LOGCOPY_32(env, bp, &suffix);
1752	bp += sizeof(suffix);
1753
1754	DB_ASSERT(env,
1755	    (u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size);
1756
1757	if (is_durable || txnp == NULL) {
1758		if ((ret = __log_put(env, rlsnp,(DBT *)&logrec,
1759		    flags | DB_LOG_NOCOPY)) == 0 && txnp != NULL) {
1760			*lsnp = *rlsnp;
1761			if (rlsnp != ret_lsnp)
1762				 *ret_lsnp = *rlsnp;
1763		}
1764	} else {
1765		ret = 0;
1766#ifdef DIAGNOSTIC
1767		/*
1768		 * Set the debug bit if we are going to log non-durable
1769		 * transactions so they will be ignored by recovery.
1770		 */
1771		memcpy(lr->data, logrec.data, logrec.size);
1772		rectype |= DB_debug_FLAG;
1773		LOGCOPY_32(env, logrec.data, &rectype);
1774
1775		if (!IS_REP_CLIENT(env))
1776			ret = __log_put(env,
1777			    rlsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
1778#endif
1779		STAILQ_INSERT_HEAD(&txnp->logs, lr, links);
1780		F_SET((TXN_DETAIL *)txnp->td, TXN_DTL_INMEMORY);
1781		LSN_NOT_LOGGED(*ret_lsnp);
1782	}
1783
1784#ifdef LOG_DIAGNOSTIC
1785	if (ret != 0)
1786		(void)__bam_repl_print(env,
1787		    (DBT *)&logrec, ret_lsnp, DB_TXN_PRINT, NULL);
1788#endif
1789
1790#ifdef DIAGNOSTIC
1791	__os_free(env, logrec.data);
1792#else
1793	if (is_durable || txnp == NULL)
1794		__os_free(env, logrec.data);
1795#endif
1796	return (ret);
1797}
1798
1799/*
1800 * PUBLIC: int __bam_root_read __P((ENV *, DB **, void *, void *,
1801 * PUBLIC:     __bam_root_args **));
1802 */
1803int
1804__bam_root_read(env, dbpp, td, recbuf, argpp)
1805	ENV *env;
1806	DB **dbpp;
1807	void *td;
1808	void *recbuf;
1809	__bam_root_args **argpp;
1810{
1811	__bam_root_args *argp;
1812	u_int32_t uinttmp;
1813	u_int8_t *bp;
1814	int ret;
1815
1816	if ((ret = __os_malloc(env,
1817	    sizeof(__bam_root_args) + sizeof(DB_TXN), &argp)) != 0)
1818		return (ret);
1819	bp = recbuf;
1820	argp->txnp = (DB_TXN *)&argp[1];
1821	memset(argp->txnp, 0, sizeof(DB_TXN));
1822
1823	argp->txnp->td = td;
1824	LOGCOPY_32(env, &argp->type, bp);
1825	bp += sizeof(argp->type);
1826
1827	LOGCOPY_32(env, &argp->txnp->txnid, bp);
1828	bp += sizeof(argp->txnp->txnid);
1829
1830	LOGCOPY_TOLSN(env, &argp->prev_lsn, bp);
1831	bp += sizeof(DB_LSN);
1832
1833	LOGCOPY_32(env, &uinttmp, bp);
1834	argp->fileid = (int32_t)uinttmp;
1835	bp += sizeof(uinttmp);
1836	if (dbpp != NULL) {
1837		*dbpp = NULL;
1838		ret = __dbreg_id_to_db(
1839		    env, argp->txnp, dbpp, argp->fileid, 1);
1840	}
1841
1842	LOGCOPY_32(env, &uinttmp, bp);
1843	argp->meta_pgno = (db_pgno_t)uinttmp;
1844	bp += sizeof(uinttmp);
1845
1846	LOGCOPY_32(env, &uinttmp, bp);
1847	argp->root_pgno = (db_pgno_t)uinttmp;
1848	bp += sizeof(uinttmp);
1849
1850	LOGCOPY_TOLSN(env, &argp->meta_lsn, bp);
1851	bp += sizeof(DB_LSN);
1852
1853	*argpp = argp;
1854	return (ret);
1855}
1856
1857/*
1858 * PUBLIC: int __bam_root_log __P((DB *, DB_TXN *, DB_LSN *,
1859 * PUBLIC:     u_int32_t, db_pgno_t, db_pgno_t, DB_LSN *));
1860 */
1861int
1862__bam_root_log(dbp, txnp, ret_lsnp, flags, meta_pgno, root_pgno, meta_lsn)
1863	DB *dbp;
1864	DB_TXN *txnp;
1865	DB_LSN *ret_lsnp;
1866	u_int32_t flags;
1867	db_pgno_t meta_pgno;
1868	db_pgno_t root_pgno;
1869	DB_LSN * meta_lsn;
1870{
1871	DBT logrec;
1872	DB_LSN *lsnp, null_lsn, *rlsnp;
1873	DB_TXNLOGREC *lr;
1874	ENV *env;
1875	u_int32_t uinttmp, rectype, txn_num;
1876	u_int npad;
1877	u_int8_t *bp;
1878	int is_durable, ret;
1879
1880	COMPQUIET(lr, NULL);
1881
1882	env = dbp->env;
1883	rlsnp = ret_lsnp;
1884	rectype = DB___bam_root;
1885	npad = 0;
1886	ret = 0;
1887
1888	if (LF_ISSET(DB_LOG_NOT_DURABLE) ||
1889	    F_ISSET(dbp, DB_AM_NOT_DURABLE)) {
1890		if (txnp == NULL)
1891			return (0);
1892		is_durable = 0;
1893	} else
1894		is_durable = 1;
1895
1896	if (txnp == NULL) {
1897		txn_num = 0;
1898		lsnp = &null_lsn;
1899		null_lsn.file = null_lsn.offset = 0;
1900	} else {
1901		if (TAILQ_FIRST(&txnp->kids) != NULL &&
1902		    (ret = __txn_activekids(env, rectype, txnp)) != 0)
1903			return (ret);
1904		/*
1905		 * We need to assign begin_lsn while holding region mutex.
1906		 * That assignment is done inside the DbEnv->log_put call,
1907		 * so pass in the appropriate memory location to be filled
1908		 * in by the log_put code.
1909		 */
1910		DB_SET_TXN_LSNP(txnp, &rlsnp, &lsnp);
1911		txn_num = txnp->txnid;
1912	}
1913
1914	DB_ASSERT(env, dbp->log_filename != NULL);
1915	if (dbp->log_filename->id == DB_LOGFILEID_INVALID &&
1916	    (ret = __dbreg_lazy_id(dbp)) != 0)
1917		return (ret);
1918
1919	logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
1920	    + sizeof(u_int32_t)
1921	    + sizeof(u_int32_t)
1922	    + sizeof(u_int32_t)
1923	    + sizeof(*meta_lsn);
1924	if (CRYPTO_ON(env)) {
1925		npad = env->crypto_handle->adj_size(logrec.size);
1926		logrec.size += npad;
1927	}
1928
1929	if (is_durable || txnp == NULL) {
1930		if ((ret =
1931		    __os_malloc(env, logrec.size, &logrec.data)) != 0)
1932			return (ret);
1933	} else {
1934		if ((ret = __os_malloc(env,
1935		    logrec.size + sizeof(DB_TXNLOGREC), &lr)) != 0)
1936			return (ret);
1937#ifdef DIAGNOSTIC
1938		if ((ret =
1939		    __os_malloc(env, logrec.size, &logrec.data)) != 0) {
1940			__os_free(env, lr);
1941			return (ret);
1942		}
1943#else
1944		logrec.data = lr->data;
1945#endif
1946	}
1947	if (npad > 0)
1948		memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad);
1949
1950	bp = logrec.data;
1951
1952	LOGCOPY_32(env, bp, &rectype);
1953	bp += sizeof(rectype);
1954
1955	LOGCOPY_32(env, bp, &txn_num);
1956	bp += sizeof(txn_num);
1957
1958	LOGCOPY_FROMLSN(env, bp, lsnp);
1959	bp += sizeof(DB_LSN);
1960
1961	uinttmp = (u_int32_t)dbp->log_filename->id;
1962	LOGCOPY_32(env, bp, &uinttmp);
1963	bp += sizeof(uinttmp);
1964
1965	uinttmp = (u_int32_t)meta_pgno;
1966	LOGCOPY_32(env,bp, &uinttmp);
1967	bp += sizeof(uinttmp);
1968
1969	uinttmp = (u_int32_t)root_pgno;
1970	LOGCOPY_32(env,bp, &uinttmp);
1971	bp += sizeof(uinttmp);
1972
1973	if (meta_lsn != NULL) {
1974		if (txnp != NULL) {
1975			LOG *lp = env->lg_handle->reginfo.primary;
1976			if (LOG_COMPARE(meta_lsn, &lp->lsn) >= 0 && (ret =
1977			    __log_check_page_lsn(env, dbp, meta_lsn)) != 0)
1978				return (ret);
1979		}
1980		LOGCOPY_FROMLSN(env, bp, meta_lsn);
1981	} else
1982		memset(bp, 0, sizeof(*meta_lsn));
1983	bp += sizeof(*meta_lsn);
1984
1985	DB_ASSERT(env,
1986	    (u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size);
1987
1988	if (is_durable || txnp == NULL) {
1989		if ((ret = __log_put(env, rlsnp,(DBT *)&logrec,
1990		    flags | DB_LOG_NOCOPY)) == 0 && txnp != NULL) {
1991			*lsnp = *rlsnp;
1992			if (rlsnp != ret_lsnp)
1993				 *ret_lsnp = *rlsnp;
1994		}
1995	} else {
1996		ret = 0;
1997#ifdef DIAGNOSTIC
1998		/*
1999		 * Set the debug bit if we are going to log non-durable
2000		 * transactions so they will be ignored by recovery.
2001		 */
2002		memcpy(lr->data, logrec.data, logrec.size);
2003		rectype |= DB_debug_FLAG;
2004		LOGCOPY_32(env, logrec.data, &rectype);
2005
2006		if (!IS_REP_CLIENT(env))
2007			ret = __log_put(env,
2008			    rlsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
2009#endif
2010		STAILQ_INSERT_HEAD(&txnp->logs, lr, links);
2011		F_SET((TXN_DETAIL *)txnp->td, TXN_DTL_INMEMORY);
2012		LSN_NOT_LOGGED(*ret_lsnp);
2013	}
2014
2015#ifdef LOG_DIAGNOSTIC
2016	if (ret != 0)
2017		(void)__bam_root_print(env,
2018		    (DBT *)&logrec, ret_lsnp, DB_TXN_PRINT, NULL);
2019#endif
2020
2021#ifdef DIAGNOSTIC
2022	__os_free(env, logrec.data);
2023#else
2024	if (is_durable || txnp == NULL)
2025		__os_free(env, logrec.data);
2026#endif
2027	return (ret);
2028}
2029
2030/*
2031 * PUBLIC: int __bam_curadj_read __P((ENV *, DB **, void *, void *,
2032 * PUBLIC:     __bam_curadj_args **));
2033 */
2034int
2035__bam_curadj_read(env, dbpp, td, recbuf, argpp)
2036	ENV *env;
2037	DB **dbpp;
2038	void *td;
2039	void *recbuf;
2040	__bam_curadj_args **argpp;
2041{
2042	__bam_curadj_args *argp;
2043	u_int32_t uinttmp;
2044	u_int8_t *bp;
2045	int ret;
2046
2047	if ((ret = __os_malloc(env,
2048	    sizeof(__bam_curadj_args) + sizeof(DB_TXN), &argp)) != 0)
2049		return (ret);
2050	bp = recbuf;
2051	argp->txnp = (DB_TXN *)&argp[1];
2052	memset(argp->txnp, 0, sizeof(DB_TXN));
2053
2054	argp->txnp->td = td;
2055	LOGCOPY_32(env, &argp->type, bp);
2056	bp += sizeof(argp->type);
2057
2058	LOGCOPY_32(env, &argp->txnp->txnid, bp);
2059	bp += sizeof(argp->txnp->txnid);
2060
2061	LOGCOPY_TOLSN(env, &argp->prev_lsn, bp);
2062	bp += sizeof(DB_LSN);
2063
2064	LOGCOPY_32(env, &uinttmp, bp);
2065	argp->fileid = (int32_t)uinttmp;
2066	bp += sizeof(uinttmp);
2067	if (dbpp != NULL) {
2068		*dbpp = NULL;
2069		ret = __dbreg_id_to_db(
2070		    env, argp->txnp, dbpp, argp->fileid, 1);
2071	}
2072
2073	LOGCOPY_32(env, &uinttmp, bp);
2074	argp->mode = (db_ca_mode)uinttmp;
2075	bp += sizeof(uinttmp);
2076
2077	LOGCOPY_32(env, &uinttmp, bp);
2078	argp->from_pgno = (db_pgno_t)uinttmp;
2079	bp += sizeof(uinttmp);
2080
2081	LOGCOPY_32(env, &uinttmp, bp);
2082	argp->to_pgno = (db_pgno_t)uinttmp;
2083	bp += sizeof(uinttmp);
2084
2085	LOGCOPY_32(env, &uinttmp, bp);
2086	argp->left_pgno = (db_pgno_t)uinttmp;
2087	bp += sizeof(uinttmp);
2088
2089	LOGCOPY_32(env, &argp->first_indx, bp);
2090	bp += sizeof(argp->first_indx);
2091
2092	LOGCOPY_32(env, &argp->from_indx, bp);
2093	bp += sizeof(argp->from_indx);
2094
2095	LOGCOPY_32(env, &argp->to_indx, bp);
2096	bp += sizeof(argp->to_indx);
2097
2098	*argpp = argp;
2099	return (ret);
2100}
2101
2102/*
2103 * PUBLIC: int __bam_curadj_log __P((DB *, DB_TXN *, DB_LSN *,
2104 * PUBLIC:     u_int32_t, db_ca_mode, db_pgno_t, db_pgno_t, db_pgno_t,
2105 * PUBLIC:     u_int32_t, u_int32_t, u_int32_t));
2106 */
2107int
2108__bam_curadj_log(dbp, txnp, ret_lsnp, flags, mode, from_pgno, to_pgno, left_pgno, first_indx,
2109    from_indx, to_indx)
2110	DB *dbp;
2111	DB_TXN *txnp;
2112	DB_LSN *ret_lsnp;
2113	u_int32_t flags;
2114	db_ca_mode mode;
2115	db_pgno_t from_pgno;
2116	db_pgno_t to_pgno;
2117	db_pgno_t left_pgno;
2118	u_int32_t first_indx;
2119	u_int32_t from_indx;
2120	u_int32_t to_indx;
2121{
2122	DBT logrec;
2123	DB_LSN *lsnp, null_lsn, *rlsnp;
2124	DB_TXNLOGREC *lr;
2125	ENV *env;
2126	u_int32_t uinttmp, rectype, txn_num;
2127	u_int npad;
2128	u_int8_t *bp;
2129	int is_durable, ret;
2130
2131	COMPQUIET(lr, NULL);
2132
2133	env = dbp->env;
2134	rlsnp = ret_lsnp;
2135	rectype = DB___bam_curadj;
2136	npad = 0;
2137	ret = 0;
2138
2139	if (LF_ISSET(DB_LOG_NOT_DURABLE) ||
2140	    F_ISSET(dbp, DB_AM_NOT_DURABLE)) {
2141		if (txnp == NULL)
2142			return (0);
2143		is_durable = 0;
2144	} else
2145		is_durable = 1;
2146
2147	if (txnp == NULL) {
2148		txn_num = 0;
2149		lsnp = &null_lsn;
2150		null_lsn.file = null_lsn.offset = 0;
2151	} else {
2152		if (TAILQ_FIRST(&txnp->kids) != NULL &&
2153		    (ret = __txn_activekids(env, rectype, txnp)) != 0)
2154			return (ret);
2155		/*
2156		 * We need to assign begin_lsn while holding region mutex.
2157		 * That assignment is done inside the DbEnv->log_put call,
2158		 * so pass in the appropriate memory location to be filled
2159		 * in by the log_put code.
2160		 */
2161		DB_SET_TXN_LSNP(txnp, &rlsnp, &lsnp);
2162		txn_num = txnp->txnid;
2163	}
2164
2165	DB_ASSERT(env, dbp->log_filename != NULL);
2166	if (dbp->log_filename->id == DB_LOGFILEID_INVALID &&
2167	    (ret = __dbreg_lazy_id(dbp)) != 0)
2168		return (ret);
2169
2170	logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
2171	    + sizeof(u_int32_t)
2172	    + sizeof(u_int32_t)
2173	    + sizeof(u_int32_t)
2174	    + sizeof(u_int32_t)
2175	    + sizeof(u_int32_t)
2176	    + sizeof(u_int32_t)
2177	    + sizeof(u_int32_t)
2178	    + sizeof(u_int32_t);
2179	if (CRYPTO_ON(env)) {
2180		npad = env->crypto_handle->adj_size(logrec.size);
2181		logrec.size += npad;
2182	}
2183
2184	if (is_durable || txnp == NULL) {
2185		if ((ret =
2186		    __os_malloc(env, logrec.size, &logrec.data)) != 0)
2187			return (ret);
2188	} else {
2189		if ((ret = __os_malloc(env,
2190		    logrec.size + sizeof(DB_TXNLOGREC), &lr)) != 0)
2191			return (ret);
2192#ifdef DIAGNOSTIC
2193		if ((ret =
2194		    __os_malloc(env, logrec.size, &logrec.data)) != 0) {
2195			__os_free(env, lr);
2196			return (ret);
2197		}
2198#else
2199		logrec.data = lr->data;
2200#endif
2201	}
2202	if (npad > 0)
2203		memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad);
2204
2205	bp = logrec.data;
2206
2207	LOGCOPY_32(env, bp, &rectype);
2208	bp += sizeof(rectype);
2209
2210	LOGCOPY_32(env, bp, &txn_num);
2211	bp += sizeof(txn_num);
2212
2213	LOGCOPY_FROMLSN(env, bp, lsnp);
2214	bp += sizeof(DB_LSN);
2215
2216	uinttmp = (u_int32_t)dbp->log_filename->id;
2217	LOGCOPY_32(env, bp, &uinttmp);
2218	bp += sizeof(uinttmp);
2219
2220	uinttmp = (u_int32_t)mode;
2221	LOGCOPY_32(env,bp, &uinttmp);
2222	bp += sizeof(uinttmp);
2223
2224	uinttmp = (u_int32_t)from_pgno;
2225	LOGCOPY_32(env,bp, &uinttmp);
2226	bp += sizeof(uinttmp);
2227
2228	uinttmp = (u_int32_t)to_pgno;
2229	LOGCOPY_32(env,bp, &uinttmp);
2230	bp += sizeof(uinttmp);
2231
2232	uinttmp = (u_int32_t)left_pgno;
2233	LOGCOPY_32(env,bp, &uinttmp);
2234	bp += sizeof(uinttmp);
2235
2236	LOGCOPY_32(env, bp, &first_indx);
2237	bp += sizeof(first_indx);
2238
2239	LOGCOPY_32(env, bp, &from_indx);
2240	bp += sizeof(from_indx);
2241
2242	LOGCOPY_32(env, bp, &to_indx);
2243	bp += sizeof(to_indx);
2244
2245	DB_ASSERT(env,
2246	    (u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size);
2247
2248	if (is_durable || txnp == NULL) {
2249		if ((ret = __log_put(env, rlsnp,(DBT *)&logrec,
2250		    flags | DB_LOG_NOCOPY)) == 0 && txnp != NULL) {
2251			*lsnp = *rlsnp;
2252			if (rlsnp != ret_lsnp)
2253				 *ret_lsnp = *rlsnp;
2254		}
2255	} else {
2256		ret = 0;
2257#ifdef DIAGNOSTIC
2258		/*
2259		 * Set the debug bit if we are going to log non-durable
2260		 * transactions so they will be ignored by recovery.
2261		 */
2262		memcpy(lr->data, logrec.data, logrec.size);
2263		rectype |= DB_debug_FLAG;
2264		LOGCOPY_32(env, logrec.data, &rectype);
2265
2266		if (!IS_REP_CLIENT(env))
2267			ret = __log_put(env,
2268			    rlsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
2269#endif
2270		STAILQ_INSERT_HEAD(&txnp->logs, lr, links);
2271		F_SET((TXN_DETAIL *)txnp->td, TXN_DTL_INMEMORY);
2272		LSN_NOT_LOGGED(*ret_lsnp);
2273	}
2274
2275#ifdef LOG_DIAGNOSTIC
2276	if (ret != 0)
2277		(void)__bam_curadj_print(env,
2278		    (DBT *)&logrec, ret_lsnp, DB_TXN_PRINT, NULL);
2279#endif
2280
2281#ifdef DIAGNOSTIC
2282	__os_free(env, logrec.data);
2283#else
2284	if (is_durable || txnp == NULL)
2285		__os_free(env, logrec.data);
2286#endif
2287	return (ret);
2288}
2289
2290/*
2291 * PUBLIC: int __bam_rcuradj_read __P((ENV *, DB **, void *, void *,
2292 * PUBLIC:     __bam_rcuradj_args **));
2293 */
2294int
2295__bam_rcuradj_read(env, dbpp, td, recbuf, argpp)
2296	ENV *env;
2297	DB **dbpp;
2298	void *td;
2299	void *recbuf;
2300	__bam_rcuradj_args **argpp;
2301{
2302	__bam_rcuradj_args *argp;
2303	u_int32_t uinttmp;
2304	u_int8_t *bp;
2305	int ret;
2306
2307	if ((ret = __os_malloc(env,
2308	    sizeof(__bam_rcuradj_args) + sizeof(DB_TXN), &argp)) != 0)
2309		return (ret);
2310	bp = recbuf;
2311	argp->txnp = (DB_TXN *)&argp[1];
2312	memset(argp->txnp, 0, sizeof(DB_TXN));
2313
2314	argp->txnp->td = td;
2315	LOGCOPY_32(env, &argp->type, bp);
2316	bp += sizeof(argp->type);
2317
2318	LOGCOPY_32(env, &argp->txnp->txnid, bp);
2319	bp += sizeof(argp->txnp->txnid);
2320
2321	LOGCOPY_TOLSN(env, &argp->prev_lsn, bp);
2322	bp += sizeof(DB_LSN);
2323
2324	LOGCOPY_32(env, &uinttmp, bp);
2325	argp->fileid = (int32_t)uinttmp;
2326	bp += sizeof(uinttmp);
2327	if (dbpp != NULL) {
2328		*dbpp = NULL;
2329		ret = __dbreg_id_to_db(
2330		    env, argp->txnp, dbpp, argp->fileid, 1);
2331	}
2332
2333	LOGCOPY_32(env, &uinttmp, bp);
2334	argp->mode = (ca_recno_arg)uinttmp;
2335	bp += sizeof(uinttmp);
2336
2337	LOGCOPY_32(env, &uinttmp, bp);
2338	argp->root = (db_pgno_t)uinttmp;
2339	bp += sizeof(uinttmp);
2340
2341	LOGCOPY_32(env, &uinttmp, bp);
2342	argp->recno = (db_recno_t)uinttmp;
2343	bp += sizeof(uinttmp);
2344
2345	LOGCOPY_32(env, &argp->order, bp);
2346	bp += sizeof(argp->order);
2347
2348	*argpp = argp;
2349	return (ret);
2350}
2351
2352/*
2353 * PUBLIC: int __bam_rcuradj_log __P((DB *, DB_TXN *, DB_LSN *,
2354 * PUBLIC:     u_int32_t, ca_recno_arg, db_pgno_t, db_recno_t, u_int32_t));
2355 */
2356int
2357__bam_rcuradj_log(dbp, txnp, ret_lsnp, flags, mode, root, recno, order)
2358	DB *dbp;
2359	DB_TXN *txnp;
2360	DB_LSN *ret_lsnp;
2361	u_int32_t flags;
2362	ca_recno_arg mode;
2363	db_pgno_t root;
2364	db_recno_t recno;
2365	u_int32_t order;
2366{
2367	DBT logrec;
2368	DB_LSN *lsnp, null_lsn, *rlsnp;
2369	DB_TXNLOGREC *lr;
2370	ENV *env;
2371	u_int32_t uinttmp, rectype, txn_num;
2372	u_int npad;
2373	u_int8_t *bp;
2374	int is_durable, ret;
2375
2376	COMPQUIET(lr, NULL);
2377
2378	env = dbp->env;
2379	rlsnp = ret_lsnp;
2380	rectype = DB___bam_rcuradj;
2381	npad = 0;
2382	ret = 0;
2383
2384	if (LF_ISSET(DB_LOG_NOT_DURABLE) ||
2385	    F_ISSET(dbp, DB_AM_NOT_DURABLE)) {
2386		if (txnp == NULL)
2387			return (0);
2388		is_durable = 0;
2389	} else
2390		is_durable = 1;
2391
2392	if (txnp == NULL) {
2393		txn_num = 0;
2394		lsnp = &null_lsn;
2395		null_lsn.file = null_lsn.offset = 0;
2396	} else {
2397		if (TAILQ_FIRST(&txnp->kids) != NULL &&
2398		    (ret = __txn_activekids(env, rectype, txnp)) != 0)
2399			return (ret);
2400		/*
2401		 * We need to assign begin_lsn while holding region mutex.
2402		 * That assignment is done inside the DbEnv->log_put call,
2403		 * so pass in the appropriate memory location to be filled
2404		 * in by the log_put code.
2405		 */
2406		DB_SET_TXN_LSNP(txnp, &rlsnp, &lsnp);
2407		txn_num = txnp->txnid;
2408	}
2409
2410	DB_ASSERT(env, dbp->log_filename != NULL);
2411	if (dbp->log_filename->id == DB_LOGFILEID_INVALID &&
2412	    (ret = __dbreg_lazy_id(dbp)) != 0)
2413		return (ret);
2414
2415	logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
2416	    + sizeof(u_int32_t)
2417	    + sizeof(u_int32_t)
2418	    + sizeof(u_int32_t)
2419	    + sizeof(u_int32_t)
2420	    + sizeof(u_int32_t);
2421	if (CRYPTO_ON(env)) {
2422		npad = env->crypto_handle->adj_size(logrec.size);
2423		logrec.size += npad;
2424	}
2425
2426	if (is_durable || txnp == NULL) {
2427		if ((ret =
2428		    __os_malloc(env, logrec.size, &logrec.data)) != 0)
2429			return (ret);
2430	} else {
2431		if ((ret = __os_malloc(env,
2432		    logrec.size + sizeof(DB_TXNLOGREC), &lr)) != 0)
2433			return (ret);
2434#ifdef DIAGNOSTIC
2435		if ((ret =
2436		    __os_malloc(env, logrec.size, &logrec.data)) != 0) {
2437			__os_free(env, lr);
2438			return (ret);
2439		}
2440#else
2441		logrec.data = lr->data;
2442#endif
2443	}
2444	if (npad > 0)
2445		memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad);
2446
2447	bp = logrec.data;
2448
2449	LOGCOPY_32(env, bp, &rectype);
2450	bp += sizeof(rectype);
2451
2452	LOGCOPY_32(env, bp, &txn_num);
2453	bp += sizeof(txn_num);
2454
2455	LOGCOPY_FROMLSN(env, bp, lsnp);
2456	bp += sizeof(DB_LSN);
2457
2458	uinttmp = (u_int32_t)dbp->log_filename->id;
2459	LOGCOPY_32(env, bp, &uinttmp);
2460	bp += sizeof(uinttmp);
2461
2462	uinttmp = (u_int32_t)mode;
2463	LOGCOPY_32(env,bp, &uinttmp);
2464	bp += sizeof(uinttmp);
2465
2466	uinttmp = (u_int32_t)root;
2467	LOGCOPY_32(env,bp, &uinttmp);
2468	bp += sizeof(uinttmp);
2469
2470	uinttmp = (u_int32_t)recno;
2471	LOGCOPY_32(env,bp, &uinttmp);
2472	bp += sizeof(uinttmp);
2473
2474	LOGCOPY_32(env, bp, &order);
2475	bp += sizeof(order);
2476
2477	DB_ASSERT(env,
2478	    (u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size);
2479
2480	if (is_durable || txnp == NULL) {
2481		if ((ret = __log_put(env, rlsnp,(DBT *)&logrec,
2482		    flags | DB_LOG_NOCOPY)) == 0 && txnp != NULL) {
2483			*lsnp = *rlsnp;
2484			if (rlsnp != ret_lsnp)
2485				 *ret_lsnp = *rlsnp;
2486		}
2487	} else {
2488		ret = 0;
2489#ifdef DIAGNOSTIC
2490		/*
2491		 * Set the debug bit if we are going to log non-durable
2492		 * transactions so they will be ignored by recovery.
2493		 */
2494		memcpy(lr->data, logrec.data, logrec.size);
2495		rectype |= DB_debug_FLAG;
2496		LOGCOPY_32(env, logrec.data, &rectype);
2497
2498		if (!IS_REP_CLIENT(env))
2499			ret = __log_put(env,
2500			    rlsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
2501#endif
2502		STAILQ_INSERT_HEAD(&txnp->logs, lr, links);
2503		F_SET((TXN_DETAIL *)txnp->td, TXN_DTL_INMEMORY);
2504		LSN_NOT_LOGGED(*ret_lsnp);
2505	}
2506
2507#ifdef LOG_DIAGNOSTIC
2508	if (ret != 0)
2509		(void)__bam_rcuradj_print(env,
2510		    (DBT *)&logrec, ret_lsnp, DB_TXN_PRINT, NULL);
2511#endif
2512
2513#ifdef DIAGNOSTIC
2514	__os_free(env, logrec.data);
2515#else
2516	if (is_durable || txnp == NULL)
2517		__os_free(env, logrec.data);
2518#endif
2519	return (ret);
2520}
2521
2522/*
2523 * PUBLIC: int __bam_relink_43_read __P((ENV *, DB **, void *,
2524 * PUBLIC:     void *, __bam_relink_43_args **));
2525 */
2526int
2527__bam_relink_43_read(env, dbpp, td, recbuf, argpp)
2528	ENV *env;
2529	DB **dbpp;
2530	void *td;
2531	void *recbuf;
2532	__bam_relink_43_args **argpp;
2533{
2534	__bam_relink_43_args *argp;
2535	u_int32_t uinttmp;
2536	u_int8_t *bp;
2537	int ret;
2538
2539	if ((ret = __os_malloc(env,
2540	    sizeof(__bam_relink_43_args) + sizeof(DB_TXN), &argp)) != 0)
2541		return (ret);
2542	bp = recbuf;
2543	argp->txnp = (DB_TXN *)&argp[1];
2544	memset(argp->txnp, 0, sizeof(DB_TXN));
2545
2546	argp->txnp->td = td;
2547	LOGCOPY_32(env, &argp->type, bp);
2548	bp += sizeof(argp->type);
2549
2550	LOGCOPY_32(env, &argp->txnp->txnid, bp);
2551	bp += sizeof(argp->txnp->txnid);
2552
2553	LOGCOPY_TOLSN(env, &argp->prev_lsn, bp);
2554	bp += sizeof(DB_LSN);
2555
2556	LOGCOPY_32(env, &uinttmp, bp);
2557	argp->fileid = (int32_t)uinttmp;
2558	bp += sizeof(uinttmp);
2559	if (dbpp != NULL) {
2560		*dbpp = NULL;
2561		ret = __dbreg_id_to_db(
2562		    env, argp->txnp, dbpp, argp->fileid, 1);
2563	}
2564
2565	LOGCOPY_32(env, &uinttmp, bp);
2566	argp->pgno = (db_pgno_t)uinttmp;
2567	bp += sizeof(uinttmp);
2568
2569	LOGCOPY_TOLSN(env, &argp->lsn, bp);
2570	bp += sizeof(DB_LSN);
2571
2572	LOGCOPY_32(env, &uinttmp, bp);
2573	argp->prev = (db_pgno_t)uinttmp;
2574	bp += sizeof(uinttmp);
2575
2576	LOGCOPY_TOLSN(env, &argp->lsn_prev, bp);
2577	bp += sizeof(DB_LSN);
2578
2579	LOGCOPY_32(env, &uinttmp, bp);
2580	argp->next = (db_pgno_t)uinttmp;
2581	bp += sizeof(uinttmp);
2582
2583	LOGCOPY_TOLSN(env, &argp->lsn_next, bp);
2584	bp += sizeof(DB_LSN);
2585
2586	*argpp = argp;
2587	return (ret);
2588}
2589
2590/*
2591 * PUBLIC: int __bam_relink_read __P((ENV *, DB **, void *, void *,
2592 * PUBLIC:     __bam_relink_args **));
2593 */
2594int
2595__bam_relink_read(env, dbpp, td, recbuf, argpp)
2596	ENV *env;
2597	DB **dbpp;
2598	void *td;
2599	void *recbuf;
2600	__bam_relink_args **argpp;
2601{
2602	__bam_relink_args *argp;
2603	u_int32_t uinttmp;
2604	u_int8_t *bp;
2605	int ret;
2606
2607	if ((ret = __os_malloc(env,
2608	    sizeof(__bam_relink_args) + sizeof(DB_TXN), &argp)) != 0)
2609		return (ret);
2610	bp = recbuf;
2611	argp->txnp = (DB_TXN *)&argp[1];
2612	memset(argp->txnp, 0, sizeof(DB_TXN));
2613
2614	argp->txnp->td = td;
2615	LOGCOPY_32(env, &argp->type, bp);
2616	bp += sizeof(argp->type);
2617
2618	LOGCOPY_32(env, &argp->txnp->txnid, bp);
2619	bp += sizeof(argp->txnp->txnid);
2620
2621	LOGCOPY_TOLSN(env, &argp->prev_lsn, bp);
2622	bp += sizeof(DB_LSN);
2623
2624	LOGCOPY_32(env, &uinttmp, bp);
2625	argp->fileid = (int32_t)uinttmp;
2626	bp += sizeof(uinttmp);
2627	if (dbpp != NULL) {
2628		*dbpp = NULL;
2629		ret = __dbreg_id_to_db(
2630		    env, argp->txnp, dbpp, argp->fileid, 1);
2631	}
2632
2633	LOGCOPY_32(env, &uinttmp, bp);
2634	argp->pgno = (db_pgno_t)uinttmp;
2635	bp += sizeof(uinttmp);
2636
2637	LOGCOPY_32(env, &uinttmp, bp);
2638	argp->new_pgno = (db_pgno_t)uinttmp;
2639	bp += sizeof(uinttmp);
2640
2641	LOGCOPY_32(env, &uinttmp, bp);
2642	argp->prev = (db_pgno_t)uinttmp;
2643	bp += sizeof(uinttmp);
2644
2645	LOGCOPY_TOLSN(env, &argp->lsn_prev, bp);
2646	bp += sizeof(DB_LSN);
2647
2648	LOGCOPY_32(env, &uinttmp, bp);
2649	argp->next = (db_pgno_t)uinttmp;
2650	bp += sizeof(uinttmp);
2651
2652	LOGCOPY_TOLSN(env, &argp->lsn_next, bp);
2653	bp += sizeof(DB_LSN);
2654
2655	*argpp = argp;
2656	return (ret);
2657}
2658
2659/*
2660 * PUBLIC: int __bam_relink_log __P((DB *, DB_TXN *, DB_LSN *,
2661 * PUBLIC:     u_int32_t, db_pgno_t, db_pgno_t, db_pgno_t, DB_LSN *, db_pgno_t,
2662 * PUBLIC:     DB_LSN *));
2663 */
2664int
2665__bam_relink_log(dbp, txnp, ret_lsnp, flags, pgno, new_pgno, prev, lsn_prev, next,
2666    lsn_next)
2667	DB *dbp;
2668	DB_TXN *txnp;
2669	DB_LSN *ret_lsnp;
2670	u_int32_t flags;
2671	db_pgno_t pgno;
2672	db_pgno_t new_pgno;
2673	db_pgno_t prev;
2674	DB_LSN * lsn_prev;
2675	db_pgno_t next;
2676	DB_LSN * lsn_next;
2677{
2678	DBT logrec;
2679	DB_LSN *lsnp, null_lsn, *rlsnp;
2680	DB_TXNLOGREC *lr;
2681	ENV *env;
2682	u_int32_t uinttmp, rectype, txn_num;
2683	u_int npad;
2684	u_int8_t *bp;
2685	int is_durable, ret;
2686
2687	COMPQUIET(lr, NULL);
2688
2689	env = dbp->env;
2690	rlsnp = ret_lsnp;
2691	rectype = DB___bam_relink;
2692	npad = 0;
2693	ret = 0;
2694
2695	if (LF_ISSET(DB_LOG_NOT_DURABLE) ||
2696	    F_ISSET(dbp, DB_AM_NOT_DURABLE)) {
2697		if (txnp == NULL)
2698			return (0);
2699		is_durable = 0;
2700	} else
2701		is_durable = 1;
2702
2703	if (txnp == NULL) {
2704		txn_num = 0;
2705		lsnp = &null_lsn;
2706		null_lsn.file = null_lsn.offset = 0;
2707	} else {
2708		if (TAILQ_FIRST(&txnp->kids) != NULL &&
2709		    (ret = __txn_activekids(env, rectype, txnp)) != 0)
2710			return (ret);
2711		/*
2712		 * We need to assign begin_lsn while holding region mutex.
2713		 * That assignment is done inside the DbEnv->log_put call,
2714		 * so pass in the appropriate memory location to be filled
2715		 * in by the log_put code.
2716		 */
2717		DB_SET_TXN_LSNP(txnp, &rlsnp, &lsnp);
2718		txn_num = txnp->txnid;
2719	}
2720
2721	DB_ASSERT(env, dbp->log_filename != NULL);
2722	if (dbp->log_filename->id == DB_LOGFILEID_INVALID &&
2723	    (ret = __dbreg_lazy_id(dbp)) != 0)
2724		return (ret);
2725
2726	logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
2727	    + sizeof(u_int32_t)
2728	    + sizeof(u_int32_t)
2729	    + sizeof(u_int32_t)
2730	    + sizeof(u_int32_t)
2731	    + sizeof(*lsn_prev)
2732	    + sizeof(u_int32_t)
2733	    + sizeof(*lsn_next);
2734	if (CRYPTO_ON(env)) {
2735		npad = env->crypto_handle->adj_size(logrec.size);
2736		logrec.size += npad;
2737	}
2738
2739	if (is_durable || txnp == NULL) {
2740		if ((ret =
2741		    __os_malloc(env, logrec.size, &logrec.data)) != 0)
2742			return (ret);
2743	} else {
2744		if ((ret = __os_malloc(env,
2745		    logrec.size + sizeof(DB_TXNLOGREC), &lr)) != 0)
2746			return (ret);
2747#ifdef DIAGNOSTIC
2748		if ((ret =
2749		    __os_malloc(env, logrec.size, &logrec.data)) != 0) {
2750			__os_free(env, lr);
2751			return (ret);
2752		}
2753#else
2754		logrec.data = lr->data;
2755#endif
2756	}
2757	if (npad > 0)
2758		memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad);
2759
2760	bp = logrec.data;
2761
2762	LOGCOPY_32(env, bp, &rectype);
2763	bp += sizeof(rectype);
2764
2765	LOGCOPY_32(env, bp, &txn_num);
2766	bp += sizeof(txn_num);
2767
2768	LOGCOPY_FROMLSN(env, bp, lsnp);
2769	bp += sizeof(DB_LSN);
2770
2771	uinttmp = (u_int32_t)dbp->log_filename->id;
2772	LOGCOPY_32(env, bp, &uinttmp);
2773	bp += sizeof(uinttmp);
2774
2775	uinttmp = (u_int32_t)pgno;
2776	LOGCOPY_32(env,bp, &uinttmp);
2777	bp += sizeof(uinttmp);
2778
2779	uinttmp = (u_int32_t)new_pgno;
2780	LOGCOPY_32(env,bp, &uinttmp);
2781	bp += sizeof(uinttmp);
2782
2783	uinttmp = (u_int32_t)prev;
2784	LOGCOPY_32(env,bp, &uinttmp);
2785	bp += sizeof(uinttmp);
2786
2787	if (lsn_prev != NULL) {
2788		if (txnp != NULL) {
2789			LOG *lp = env->lg_handle->reginfo.primary;
2790			if (LOG_COMPARE(lsn_prev, &lp->lsn) >= 0 && (ret =
2791			    __log_check_page_lsn(env, dbp, lsn_prev)) != 0)
2792				return (ret);
2793		}
2794		LOGCOPY_FROMLSN(env, bp, lsn_prev);
2795	} else
2796		memset(bp, 0, sizeof(*lsn_prev));
2797	bp += sizeof(*lsn_prev);
2798
2799	uinttmp = (u_int32_t)next;
2800	LOGCOPY_32(env,bp, &uinttmp);
2801	bp += sizeof(uinttmp);
2802
2803	if (lsn_next != NULL) {
2804		if (txnp != NULL) {
2805			LOG *lp = env->lg_handle->reginfo.primary;
2806			if (LOG_COMPARE(lsn_next, &lp->lsn) >= 0 && (ret =
2807			    __log_check_page_lsn(env, dbp, lsn_next)) != 0)
2808				return (ret);
2809		}
2810		LOGCOPY_FROMLSN(env, bp, lsn_next);
2811	} else
2812		memset(bp, 0, sizeof(*lsn_next));
2813	bp += sizeof(*lsn_next);
2814
2815	DB_ASSERT(env,
2816	    (u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size);
2817
2818	if (is_durable || txnp == NULL) {
2819		if ((ret = __log_put(env, rlsnp,(DBT *)&logrec,
2820		    flags | DB_LOG_NOCOPY)) == 0 && txnp != NULL) {
2821			*lsnp = *rlsnp;
2822			if (rlsnp != ret_lsnp)
2823				 *ret_lsnp = *rlsnp;
2824		}
2825	} else {
2826		ret = 0;
2827#ifdef DIAGNOSTIC
2828		/*
2829		 * Set the debug bit if we are going to log non-durable
2830		 * transactions so they will be ignored by recovery.
2831		 */
2832		memcpy(lr->data, logrec.data, logrec.size);
2833		rectype |= DB_debug_FLAG;
2834		LOGCOPY_32(env, logrec.data, &rectype);
2835
2836		if (!IS_REP_CLIENT(env))
2837			ret = __log_put(env,
2838			    rlsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
2839#endif
2840		STAILQ_INSERT_HEAD(&txnp->logs, lr, links);
2841		F_SET((TXN_DETAIL *)txnp->td, TXN_DTL_INMEMORY);
2842		LSN_NOT_LOGGED(*ret_lsnp);
2843	}
2844
2845#ifdef LOG_DIAGNOSTIC
2846	if (ret != 0)
2847		(void)__bam_relink_print(env,
2848		    (DBT *)&logrec, ret_lsnp, DB_TXN_PRINT, NULL);
2849#endif
2850
2851#ifdef DIAGNOSTIC
2852	__os_free(env, logrec.data);
2853#else
2854	if (is_durable || txnp == NULL)
2855		__os_free(env, logrec.data);
2856#endif
2857	return (ret);
2858}
2859
2860/*
2861 * PUBLIC: int __bam_merge_44_read __P((ENV *, DB **, void *,
2862 * PUBLIC:     void *, __bam_merge_44_args **));
2863 */
2864int
2865__bam_merge_44_read(env, dbpp, td, recbuf, argpp)
2866	ENV *env;
2867	DB **dbpp;
2868	void *td;
2869	void *recbuf;
2870	__bam_merge_44_args **argpp;
2871{
2872	__bam_merge_44_args *argp;
2873	u_int32_t uinttmp;
2874	u_int8_t *bp;
2875	int ret;
2876
2877	if ((ret = __os_malloc(env,
2878	    sizeof(__bam_merge_44_args) + sizeof(DB_TXN), &argp)) != 0)
2879		return (ret);
2880	bp = recbuf;
2881	argp->txnp = (DB_TXN *)&argp[1];
2882	memset(argp->txnp, 0, sizeof(DB_TXN));
2883
2884	argp->txnp->td = td;
2885	LOGCOPY_32(env, &argp->type, bp);
2886	bp += sizeof(argp->type);
2887
2888	LOGCOPY_32(env, &argp->txnp->txnid, bp);
2889	bp += sizeof(argp->txnp->txnid);
2890
2891	LOGCOPY_TOLSN(env, &argp->prev_lsn, bp);
2892	bp += sizeof(DB_LSN);
2893
2894	LOGCOPY_32(env, &uinttmp, bp);
2895	argp->fileid = (int32_t)uinttmp;
2896	bp += sizeof(uinttmp);
2897	if (dbpp != NULL) {
2898		*dbpp = NULL;
2899		ret = __dbreg_id_to_db(
2900		    env, argp->txnp, dbpp, argp->fileid, 1);
2901	}
2902
2903	LOGCOPY_32(env, &uinttmp, bp);
2904	argp->pgno = (db_pgno_t)uinttmp;
2905	bp += sizeof(uinttmp);
2906
2907	LOGCOPY_TOLSN(env, &argp->lsn, bp);
2908	bp += sizeof(DB_LSN);
2909
2910	LOGCOPY_32(env, &uinttmp, bp);
2911	argp->npgno = (db_pgno_t)uinttmp;
2912	bp += sizeof(uinttmp);
2913
2914	LOGCOPY_TOLSN(env, &argp->nlsn, bp);
2915	bp += sizeof(DB_LSN);
2916
2917	memset(&argp->hdr, 0, sizeof(argp->hdr));
2918	LOGCOPY_32(env,&argp->hdr.size, bp);
2919	bp += sizeof(u_int32_t);
2920	argp->hdr.data = bp;
2921	bp += argp->hdr.size;
2922
2923	memset(&argp->data, 0, sizeof(argp->data));
2924	LOGCOPY_32(env,&argp->data.size, bp);
2925	bp += sizeof(u_int32_t);
2926	argp->data.data = bp;
2927	bp += argp->data.size;
2928
2929	memset(&argp->ind, 0, sizeof(argp->ind));
2930	LOGCOPY_32(env,&argp->ind.size, bp);
2931	bp += sizeof(u_int32_t);
2932	argp->ind.data = bp;
2933	bp += argp->ind.size;
2934
2935	*argpp = argp;
2936	return (ret);
2937}
2938
2939/*
2940 * PUBLIC: int __bam_merge_read __P((ENV *, DB **, void *, void *,
2941 * PUBLIC:     __bam_merge_args **));
2942 */
2943int
2944__bam_merge_read(env, dbpp, td, recbuf, argpp)
2945	ENV *env;
2946	DB **dbpp;
2947	void *td;
2948	void *recbuf;
2949	__bam_merge_args **argpp;
2950{
2951	__bam_merge_args *argp;
2952	u_int32_t uinttmp;
2953	u_int8_t *bp;
2954	int ret;
2955
2956	if ((ret = __os_malloc(env,
2957	    sizeof(__bam_merge_args) + sizeof(DB_TXN), &argp)) != 0)
2958		return (ret);
2959	bp = recbuf;
2960	argp->txnp = (DB_TXN *)&argp[1];
2961	memset(argp->txnp, 0, sizeof(DB_TXN));
2962
2963	argp->txnp->td = td;
2964	LOGCOPY_32(env, &argp->type, bp);
2965	bp += sizeof(argp->type);
2966
2967	LOGCOPY_32(env, &argp->txnp->txnid, bp);
2968	bp += sizeof(argp->txnp->txnid);
2969
2970	LOGCOPY_TOLSN(env, &argp->prev_lsn, bp);
2971	bp += sizeof(DB_LSN);
2972
2973	LOGCOPY_32(env, &uinttmp, bp);
2974	argp->fileid = (int32_t)uinttmp;
2975	bp += sizeof(uinttmp);
2976	if (dbpp != NULL) {
2977		*dbpp = NULL;
2978		ret = __dbreg_id_to_db(
2979		    env, argp->txnp, dbpp, argp->fileid, 1);
2980	}
2981
2982	LOGCOPY_32(env, &uinttmp, bp);
2983	argp->pgno = (db_pgno_t)uinttmp;
2984	bp += sizeof(uinttmp);
2985
2986	LOGCOPY_TOLSN(env, &argp->lsn, bp);
2987	bp += sizeof(DB_LSN);
2988
2989	LOGCOPY_32(env, &uinttmp, bp);
2990	argp->npgno = (db_pgno_t)uinttmp;
2991	bp += sizeof(uinttmp);
2992
2993	LOGCOPY_TOLSN(env, &argp->nlsn, bp);
2994	bp += sizeof(DB_LSN);
2995
2996	memset(&argp->hdr, 0, sizeof(argp->hdr));
2997	LOGCOPY_32(env,&argp->hdr.size, bp);
2998	bp += sizeof(u_int32_t);
2999	argp->hdr.data = bp;
3000	bp += argp->hdr.size;
3001
3002	memset(&argp->data, 0, sizeof(argp->data));
3003	LOGCOPY_32(env,&argp->data.size, bp);
3004	bp += sizeof(u_int32_t);
3005	argp->data.data = bp;
3006	bp += argp->data.size;
3007	if (LOG_SWAPPED(env) && dbpp != NULL && *dbpp != NULL) {
3008		int t_ret;
3009		if ((t_ret = __db_pageswap(*dbpp,
3010		    (PAGE *)argp->hdr.data, (size_t)argp->hdr.size,
3011		    &argp->data, 1)) != 0)
3012			return (t_ret);
3013	}
3014
3015	LOGCOPY_32(env, &uinttmp, bp);
3016	argp->pg_copy = (int32_t)uinttmp;
3017	bp += sizeof(uinttmp);
3018
3019	*argpp = argp;
3020	return (ret);
3021}
3022
3023/*
3024 * PUBLIC: int __bam_merge_log __P((DB *, DB_TXN *, DB_LSN *,
3025 * PUBLIC:     u_int32_t, db_pgno_t, DB_LSN *, db_pgno_t, DB_LSN *, const DBT *,
3026 * PUBLIC:     const DBT *, int32_t));
3027 */
3028int
3029__bam_merge_log(dbp, txnp, ret_lsnp, flags, pgno, lsn, npgno, nlsn, hdr,
3030    data, pg_copy)
3031	DB *dbp;
3032	DB_TXN *txnp;
3033	DB_LSN *ret_lsnp;
3034	u_int32_t flags;
3035	db_pgno_t pgno;
3036	DB_LSN * lsn;
3037	db_pgno_t npgno;
3038	DB_LSN * nlsn;
3039	const DBT *hdr;
3040	const DBT *data;
3041	int32_t pg_copy;
3042{
3043	DBT logrec;
3044	DB_LSN *lsnp, null_lsn, *rlsnp;
3045	DB_TXNLOGREC *lr;
3046	ENV *env;
3047	u_int32_t zero, uinttmp, rectype, txn_num;
3048	u_int npad;
3049	u_int8_t *bp;
3050	int is_durable, ret;
3051
3052	COMPQUIET(lr, NULL);
3053
3054	env = dbp->env;
3055	rlsnp = ret_lsnp;
3056	rectype = DB___bam_merge;
3057	npad = 0;
3058	ret = 0;
3059
3060	if (LF_ISSET(DB_LOG_NOT_DURABLE) ||
3061	    F_ISSET(dbp, DB_AM_NOT_DURABLE)) {
3062		if (txnp == NULL)
3063			return (0);
3064		is_durable = 0;
3065	} else
3066		is_durable = 1;
3067
3068	if (txnp == NULL) {
3069		txn_num = 0;
3070		lsnp = &null_lsn;
3071		null_lsn.file = null_lsn.offset = 0;
3072	} else {
3073		if (TAILQ_FIRST(&txnp->kids) != NULL &&
3074		    (ret = __txn_activekids(env, rectype, txnp)) != 0)
3075			return (ret);
3076		/*
3077		 * We need to assign begin_lsn while holding region mutex.
3078		 * That assignment is done inside the DbEnv->log_put call,
3079		 * so pass in the appropriate memory location to be filled
3080		 * in by the log_put code.
3081		 */
3082		DB_SET_TXN_LSNP(txnp, &rlsnp, &lsnp);
3083		txn_num = txnp->txnid;
3084	}
3085
3086	DB_ASSERT(env, dbp->log_filename != NULL);
3087	if (dbp->log_filename->id == DB_LOGFILEID_INVALID &&
3088	    (ret = __dbreg_lazy_id(dbp)) != 0)
3089		return (ret);
3090
3091	logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
3092	    + sizeof(u_int32_t)
3093	    + sizeof(u_int32_t)
3094	    + sizeof(*lsn)
3095	    + sizeof(u_int32_t)
3096	    + sizeof(*nlsn)
3097	    + sizeof(u_int32_t) + (hdr == NULL ? 0 : hdr->size)
3098	    + sizeof(u_int32_t) + (data == NULL ? 0 : data->size)
3099	    + sizeof(u_int32_t);
3100	if (CRYPTO_ON(env)) {
3101		npad = env->crypto_handle->adj_size(logrec.size);
3102		logrec.size += npad;
3103	}
3104
3105	if (is_durable || txnp == NULL) {
3106		if ((ret =
3107		    __os_malloc(env, logrec.size, &logrec.data)) != 0)
3108			return (ret);
3109	} else {
3110		if ((ret = __os_malloc(env,
3111		    logrec.size + sizeof(DB_TXNLOGREC), &lr)) != 0)
3112			return (ret);
3113#ifdef DIAGNOSTIC
3114		if ((ret =
3115		    __os_malloc(env, logrec.size, &logrec.data)) != 0) {
3116			__os_free(env, lr);
3117			return (ret);
3118		}
3119#else
3120		logrec.data = lr->data;
3121#endif
3122	}
3123	if (npad > 0)
3124		memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad);
3125
3126	bp = logrec.data;
3127
3128	LOGCOPY_32(env, bp, &rectype);
3129	bp += sizeof(rectype);
3130
3131	LOGCOPY_32(env, bp, &txn_num);
3132	bp += sizeof(txn_num);
3133
3134	LOGCOPY_FROMLSN(env, bp, lsnp);
3135	bp += sizeof(DB_LSN);
3136
3137	uinttmp = (u_int32_t)dbp->log_filename->id;
3138	LOGCOPY_32(env, bp, &uinttmp);
3139	bp += sizeof(uinttmp);
3140
3141	uinttmp = (u_int32_t)pgno;
3142	LOGCOPY_32(env,bp, &uinttmp);
3143	bp += sizeof(uinttmp);
3144
3145	if (lsn != NULL) {
3146		if (txnp != NULL) {
3147			LOG *lp = env->lg_handle->reginfo.primary;
3148			if (LOG_COMPARE(lsn, &lp->lsn) >= 0 && (ret =
3149			    __log_check_page_lsn(env, dbp, lsn)) != 0)
3150				return (ret);
3151		}
3152		LOGCOPY_FROMLSN(env, bp, lsn);
3153	} else
3154		memset(bp, 0, sizeof(*lsn));
3155	bp += sizeof(*lsn);
3156
3157	uinttmp = (u_int32_t)npgno;
3158	LOGCOPY_32(env,bp, &uinttmp);
3159	bp += sizeof(uinttmp);
3160
3161	if (nlsn != NULL) {
3162		if (txnp != NULL) {
3163			LOG *lp = env->lg_handle->reginfo.primary;
3164			if (LOG_COMPARE(nlsn, &lp->lsn) >= 0 && (ret =
3165			    __log_check_page_lsn(env, dbp, nlsn)) != 0)
3166				return (ret);
3167		}
3168		LOGCOPY_FROMLSN(env, bp, nlsn);
3169	} else
3170		memset(bp, 0, sizeof(*nlsn));
3171	bp += sizeof(*nlsn);
3172
3173	if (hdr == NULL) {
3174		zero = 0;
3175		LOGCOPY_32(env, bp, &zero);
3176		bp += sizeof(u_int32_t);
3177	} else {
3178		LOGCOPY_32(env, bp, &hdr->size);
3179		bp += sizeof(hdr->size);
3180		memcpy(bp, hdr->data, hdr->size);
3181		if (LOG_SWAPPED(env))
3182			if ((ret = __db_pageswap(dbp,
3183			    (PAGE *)bp, (size_t)hdr->size, (DBT *)data, 0)) != 0)
3184				return (ret);
3185		bp += hdr->size;
3186	}
3187
3188	if (data == NULL) {
3189		zero = 0;
3190		LOGCOPY_32(env, bp, &zero);
3191		bp += sizeof(u_int32_t);
3192	} else {
3193		LOGCOPY_32(env, bp, &data->size);
3194		bp += sizeof(data->size);
3195		memcpy(bp, data->data, data->size);
3196		if (LOG_SWAPPED(env) && F_ISSET(data, DB_DBT_APPMALLOC))
3197			__os_free(env, data->data);
3198		bp += data->size;
3199	}
3200
3201	uinttmp = (u_int32_t)pg_copy;
3202	LOGCOPY_32(env,bp, &uinttmp);
3203	bp += sizeof(uinttmp);
3204
3205	DB_ASSERT(env,
3206	    (u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size);
3207
3208	if (is_durable || txnp == NULL) {
3209		if ((ret = __log_put(env, rlsnp,(DBT *)&logrec,
3210		    flags | DB_LOG_NOCOPY)) == 0 && txnp != NULL) {
3211			*lsnp = *rlsnp;
3212			if (rlsnp != ret_lsnp)
3213				 *ret_lsnp = *rlsnp;
3214		}
3215	} else {
3216		ret = 0;
3217#ifdef DIAGNOSTIC
3218		/*
3219		 * Set the debug bit if we are going to log non-durable
3220		 * transactions so they will be ignored by recovery.
3221		 */
3222		memcpy(lr->data, logrec.data, logrec.size);
3223		rectype |= DB_debug_FLAG;
3224		LOGCOPY_32(env, logrec.data, &rectype);
3225
3226		if (!IS_REP_CLIENT(env))
3227			ret = __log_put(env,
3228			    rlsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
3229#endif
3230		STAILQ_INSERT_HEAD(&txnp->logs, lr, links);
3231		F_SET((TXN_DETAIL *)txnp->td, TXN_DTL_INMEMORY);
3232		LSN_NOT_LOGGED(*ret_lsnp);
3233	}
3234
3235#ifdef LOG_DIAGNOSTIC
3236	if (ret != 0)
3237		(void)__bam_merge_print(env,
3238		    (DBT *)&logrec, ret_lsnp, DB_TXN_PRINT, NULL);
3239#endif
3240
3241#ifdef DIAGNOSTIC
3242	__os_free(env, logrec.data);
3243#else
3244	if (is_durable || txnp == NULL)
3245		__os_free(env, logrec.data);
3246#endif
3247	return (ret);
3248}
3249
3250/*
3251 * PUBLIC: int __bam_pgno_read __P((ENV *, DB **, void *, void *,
3252 * PUBLIC:     __bam_pgno_args **));
3253 */
3254int
3255__bam_pgno_read(env, dbpp, td, recbuf, argpp)
3256	ENV *env;
3257	DB **dbpp;
3258	void *td;
3259	void *recbuf;
3260	__bam_pgno_args **argpp;
3261{
3262	__bam_pgno_args *argp;
3263	u_int32_t uinttmp;
3264	u_int8_t *bp;
3265	int ret;
3266
3267	if ((ret = __os_malloc(env,
3268	    sizeof(__bam_pgno_args) + sizeof(DB_TXN), &argp)) != 0)
3269		return (ret);
3270	bp = recbuf;
3271	argp->txnp = (DB_TXN *)&argp[1];
3272	memset(argp->txnp, 0, sizeof(DB_TXN));
3273
3274	argp->txnp->td = td;
3275	LOGCOPY_32(env, &argp->type, bp);
3276	bp += sizeof(argp->type);
3277
3278	LOGCOPY_32(env, &argp->txnp->txnid, bp);
3279	bp += sizeof(argp->txnp->txnid);
3280
3281	LOGCOPY_TOLSN(env, &argp->prev_lsn, bp);
3282	bp += sizeof(DB_LSN);
3283
3284	LOGCOPY_32(env, &uinttmp, bp);
3285	argp->fileid = (int32_t)uinttmp;
3286	bp += sizeof(uinttmp);
3287	if (dbpp != NULL) {
3288		*dbpp = NULL;
3289		ret = __dbreg_id_to_db(
3290		    env, argp->txnp, dbpp, argp->fileid, 1);
3291	}
3292
3293	LOGCOPY_32(env, &uinttmp, bp);
3294	argp->pgno = (db_pgno_t)uinttmp;
3295	bp += sizeof(uinttmp);
3296
3297	LOGCOPY_TOLSN(env, &argp->lsn, bp);
3298	bp += sizeof(DB_LSN);
3299
3300	LOGCOPY_32(env, &argp->indx, bp);
3301	bp += sizeof(argp->indx);
3302
3303	LOGCOPY_32(env, &uinttmp, bp);
3304	argp->opgno = (db_pgno_t)uinttmp;
3305	bp += sizeof(uinttmp);
3306
3307	LOGCOPY_32(env, &uinttmp, bp);
3308	argp->npgno = (db_pgno_t)uinttmp;
3309	bp += sizeof(uinttmp);
3310
3311	*argpp = argp;
3312	return (ret);
3313}
3314
3315/*
3316 * PUBLIC: int __bam_pgno_log __P((DB *, DB_TXN *, DB_LSN *,
3317 * PUBLIC:     u_int32_t, db_pgno_t, DB_LSN *, u_int32_t, db_pgno_t,
3318 * PUBLIC:     db_pgno_t));
3319 */
3320int
3321__bam_pgno_log(dbp, txnp, ret_lsnp, flags, pgno, lsn, indx, opgno, npgno)
3322	DB *dbp;
3323	DB_TXN *txnp;
3324	DB_LSN *ret_lsnp;
3325	u_int32_t flags;
3326	db_pgno_t pgno;
3327	DB_LSN * lsn;
3328	u_int32_t indx;
3329	db_pgno_t opgno;
3330	db_pgno_t npgno;
3331{
3332	DBT logrec;
3333	DB_LSN *lsnp, null_lsn, *rlsnp;
3334	DB_TXNLOGREC *lr;
3335	ENV *env;
3336	u_int32_t uinttmp, rectype, txn_num;
3337	u_int npad;
3338	u_int8_t *bp;
3339	int is_durable, ret;
3340
3341	COMPQUIET(lr, NULL);
3342
3343	env = dbp->env;
3344	rlsnp = ret_lsnp;
3345	rectype = DB___bam_pgno;
3346	npad = 0;
3347	ret = 0;
3348
3349	if (LF_ISSET(DB_LOG_NOT_DURABLE) ||
3350	    F_ISSET(dbp, DB_AM_NOT_DURABLE)) {
3351		if (txnp == NULL)
3352			return (0);
3353		is_durable = 0;
3354	} else
3355		is_durable = 1;
3356
3357	if (txnp == NULL) {
3358		txn_num = 0;
3359		lsnp = &null_lsn;
3360		null_lsn.file = null_lsn.offset = 0;
3361	} else {
3362		if (TAILQ_FIRST(&txnp->kids) != NULL &&
3363		    (ret = __txn_activekids(env, rectype, txnp)) != 0)
3364			return (ret);
3365		/*
3366		 * We need to assign begin_lsn while holding region mutex.
3367		 * That assignment is done inside the DbEnv->log_put call,
3368		 * so pass in the appropriate memory location to be filled
3369		 * in by the log_put code.
3370		 */
3371		DB_SET_TXN_LSNP(txnp, &rlsnp, &lsnp);
3372		txn_num = txnp->txnid;
3373	}
3374
3375	DB_ASSERT(env, dbp->log_filename != NULL);
3376	if (dbp->log_filename->id == DB_LOGFILEID_INVALID &&
3377	    (ret = __dbreg_lazy_id(dbp)) != 0)
3378		return (ret);
3379
3380	logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
3381	    + sizeof(u_int32_t)
3382	    + sizeof(u_int32_t)
3383	    + sizeof(*lsn)
3384	    + sizeof(u_int32_t)
3385	    + sizeof(u_int32_t)
3386	    + sizeof(u_int32_t);
3387	if (CRYPTO_ON(env)) {
3388		npad = env->crypto_handle->adj_size(logrec.size);
3389		logrec.size += npad;
3390	}
3391
3392	if (is_durable || txnp == NULL) {
3393		if ((ret =
3394		    __os_malloc(env, logrec.size, &logrec.data)) != 0)
3395			return (ret);
3396	} else {
3397		if ((ret = __os_malloc(env,
3398		    logrec.size + sizeof(DB_TXNLOGREC), &lr)) != 0)
3399			return (ret);
3400#ifdef DIAGNOSTIC
3401		if ((ret =
3402		    __os_malloc(env, logrec.size, &logrec.data)) != 0) {
3403			__os_free(env, lr);
3404			return (ret);
3405		}
3406#else
3407		logrec.data = lr->data;
3408#endif
3409	}
3410	if (npad > 0)
3411		memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad);
3412
3413	bp = logrec.data;
3414
3415	LOGCOPY_32(env, bp, &rectype);
3416	bp += sizeof(rectype);
3417
3418	LOGCOPY_32(env, bp, &txn_num);
3419	bp += sizeof(txn_num);
3420
3421	LOGCOPY_FROMLSN(env, bp, lsnp);
3422	bp += sizeof(DB_LSN);
3423
3424	uinttmp = (u_int32_t)dbp->log_filename->id;
3425	LOGCOPY_32(env, bp, &uinttmp);
3426	bp += sizeof(uinttmp);
3427
3428	uinttmp = (u_int32_t)pgno;
3429	LOGCOPY_32(env,bp, &uinttmp);
3430	bp += sizeof(uinttmp);
3431
3432	if (lsn != NULL) {
3433		if (txnp != NULL) {
3434			LOG *lp = env->lg_handle->reginfo.primary;
3435			if (LOG_COMPARE(lsn, &lp->lsn) >= 0 && (ret =
3436			    __log_check_page_lsn(env, dbp, lsn)) != 0)
3437				return (ret);
3438		}
3439		LOGCOPY_FROMLSN(env, bp, lsn);
3440	} else
3441		memset(bp, 0, sizeof(*lsn));
3442	bp += sizeof(*lsn);
3443
3444	LOGCOPY_32(env, bp, &indx);
3445	bp += sizeof(indx);
3446
3447	uinttmp = (u_int32_t)opgno;
3448	LOGCOPY_32(env,bp, &uinttmp);
3449	bp += sizeof(uinttmp);
3450
3451	uinttmp = (u_int32_t)npgno;
3452	LOGCOPY_32(env,bp, &uinttmp);
3453	bp += sizeof(uinttmp);
3454
3455	DB_ASSERT(env,
3456	    (u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size);
3457
3458	if (is_durable || txnp == NULL) {
3459		if ((ret = __log_put(env, rlsnp,(DBT *)&logrec,
3460		    flags | DB_LOG_NOCOPY)) == 0 && txnp != NULL) {
3461			*lsnp = *rlsnp;
3462			if (rlsnp != ret_lsnp)
3463				 *ret_lsnp = *rlsnp;
3464		}
3465	} else {
3466		ret = 0;
3467#ifdef DIAGNOSTIC
3468		/*
3469		 * Set the debug bit if we are going to log non-durable
3470		 * transactions so they will be ignored by recovery.
3471		 */
3472		memcpy(lr->data, logrec.data, logrec.size);
3473		rectype |= DB_debug_FLAG;
3474		LOGCOPY_32(env, logrec.data, &rectype);
3475
3476		if (!IS_REP_CLIENT(env))
3477			ret = __log_put(env,
3478			    rlsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
3479#endif
3480		STAILQ_INSERT_HEAD(&txnp->logs, lr, links);
3481		F_SET((TXN_DETAIL *)txnp->td, TXN_DTL_INMEMORY);
3482		LSN_NOT_LOGGED(*ret_lsnp);
3483	}
3484
3485#ifdef LOG_DIAGNOSTIC
3486	if (ret != 0)
3487		(void)__bam_pgno_print(env,
3488		    (DBT *)&logrec, ret_lsnp, DB_TXN_PRINT, NULL);
3489#endif
3490
3491#ifdef DIAGNOSTIC
3492	__os_free(env, logrec.data);
3493#else
3494	if (is_durable || txnp == NULL)
3495		__os_free(env, logrec.data);
3496#endif
3497	return (ret);
3498}
3499
3500/*
3501 * PUBLIC: int __bam_init_recover __P((ENV *, DB_DISTAB *));
3502 */
3503int
3504__bam_init_recover(env, dtabp)
3505	ENV *env;
3506	DB_DISTAB *dtabp;
3507{
3508	int ret;
3509
3510	if ((ret = __db_add_recovery_int(env, dtabp,
3511	    __bam_split_recover, DB___bam_split)) != 0)
3512		return (ret);
3513	if ((ret = __db_add_recovery_int(env, dtabp,
3514	    __bam_rsplit_recover, DB___bam_rsplit)) != 0)
3515		return (ret);
3516	if ((ret = __db_add_recovery_int(env, dtabp,
3517	    __bam_adj_recover, DB___bam_adj)) != 0)
3518		return (ret);
3519	if ((ret = __db_add_recovery_int(env, dtabp,
3520	    __bam_cadjust_recover, DB___bam_cadjust)) != 0)
3521		return (ret);
3522	if ((ret = __db_add_recovery_int(env, dtabp,
3523	    __bam_cdel_recover, DB___bam_cdel)) != 0)
3524		return (ret);
3525	if ((ret = __db_add_recovery_int(env, dtabp,
3526	    __bam_repl_recover, DB___bam_repl)) != 0)
3527		return (ret);
3528	if ((ret = __db_add_recovery_int(env, dtabp,
3529	    __bam_root_recover, DB___bam_root)) != 0)
3530		return (ret);
3531	if ((ret = __db_add_recovery_int(env, dtabp,
3532	    __bam_curadj_recover, DB___bam_curadj)) != 0)
3533		return (ret);
3534	if ((ret = __db_add_recovery_int(env, dtabp,
3535	    __bam_rcuradj_recover, DB___bam_rcuradj)) != 0)
3536		return (ret);
3537	if ((ret = __db_add_recovery_int(env, dtabp,
3538	    __bam_relink_recover, DB___bam_relink)) != 0)
3539		return (ret);
3540	if ((ret = __db_add_recovery_int(env, dtabp,
3541	    __bam_merge_recover, DB___bam_merge)) != 0)
3542		return (ret);
3543	if ((ret = __db_add_recovery_int(env, dtabp,
3544	    __bam_pgno_recover, DB___bam_pgno)) != 0)
3545		return (ret);
3546	return (0);
3547}
3548