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