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