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/hash.h"
10#include "dbinc/log.h"
11#include "dbinc/txn.h"
12
13/*
14 * PUBLIC: int __ham_insdel_read __P((ENV *, DB **, void *, void *,
15 * PUBLIC:     __ham_insdel_args **));
16 */
17int
18__ham_insdel_read(env, dbpp, td, recbuf, argpp)
19	ENV *env;
20	DB **dbpp;
21	void *td;
22	void *recbuf;
23	__ham_insdel_args **argpp;
24{
25	__ham_insdel_args *argp;
26	u_int32_t uinttmp;
27	u_int8_t *bp;
28	int ret;
29
30	if ((ret = __os_malloc(env,
31	    sizeof(__ham_insdel_args) + sizeof(DB_TXN), &argp)) != 0)
32		return (ret);
33	bp = recbuf;
34	argp->txnp = (DB_TXN *)&argp[1];
35	memset(argp->txnp, 0, sizeof(DB_TXN));
36
37	argp->txnp->td = td;
38	LOGCOPY_32(env, &argp->type, bp);
39	bp += sizeof(argp->type);
40
41	LOGCOPY_32(env, &argp->txnp->txnid, bp);
42	bp += sizeof(argp->txnp->txnid);
43
44	LOGCOPY_TOLSN(env, &argp->prev_lsn, bp);
45	bp += sizeof(DB_LSN);
46
47	LOGCOPY_32(env, &argp->opcode, bp);
48	bp += sizeof(argp->opcode);
49
50	LOGCOPY_32(env, &uinttmp, bp);
51	argp->fileid = (int32_t)uinttmp;
52	bp += sizeof(uinttmp);
53	if (dbpp != NULL) {
54		*dbpp = NULL;
55		ret = __dbreg_id_to_db(
56		    env, argp->txnp, dbpp, argp->fileid, 1);
57	}
58
59	LOGCOPY_32(env, &uinttmp, bp);
60	argp->pgno = (db_pgno_t)uinttmp;
61	bp += sizeof(uinttmp);
62
63	LOGCOPY_32(env, &argp->ndx, bp);
64	bp += sizeof(argp->ndx);
65
66	LOGCOPY_TOLSN(env, &argp->pagelsn, bp);
67	bp += sizeof(DB_LSN);
68
69	memset(&argp->key, 0, sizeof(argp->key));
70	LOGCOPY_32(env,&argp->key.size, bp);
71	bp += sizeof(u_int32_t);
72	argp->key.data = bp;
73	bp += argp->key.size;
74
75	memset(&argp->data, 0, sizeof(argp->data));
76	LOGCOPY_32(env,&argp->data.size, bp);
77	bp += sizeof(u_int32_t);
78	argp->data.data = bp;
79	bp += argp->data.size;
80
81	*argpp = argp;
82	return (ret);
83}
84
85/*
86 * PUBLIC: int __ham_insdel_log __P((DB *, DB_TXN *, DB_LSN *,
87 * PUBLIC:     u_int32_t, u_int32_t, db_pgno_t, u_int32_t, DB_LSN *,
88 * PUBLIC:     const DBT *, const DBT *));
89 */
90int
91__ham_insdel_log(dbp, txnp, ret_lsnp, flags,
92    opcode, pgno, ndx, pagelsn, key,
93    data)
94	DB *dbp;
95	DB_TXN *txnp;
96	DB_LSN *ret_lsnp;
97	u_int32_t flags;
98	u_int32_t opcode;
99	db_pgno_t pgno;
100	u_int32_t ndx;
101	DB_LSN * pagelsn;
102	const DBT *key;
103	const DBT *data;
104{
105	DBT logrec;
106	DB_LSN *lsnp, null_lsn, *rlsnp;
107	DB_TXNLOGREC *lr;
108	ENV *env;
109	u_int32_t zero, uinttmp, rectype, txn_num;
110	u_int npad;
111	u_int8_t *bp;
112	int is_durable, ret;
113
114	COMPQUIET(lr, NULL);
115
116	env = dbp->env;
117	rlsnp = ret_lsnp;
118	rectype = DB___ham_insdel;
119	npad = 0;
120	ret = 0;
121
122	if (LF_ISSET(DB_LOG_NOT_DURABLE) ||
123	    F_ISSET(dbp, DB_AM_NOT_DURABLE)) {
124		if (txnp == NULL)
125			return (0);
126		is_durable = 0;
127	} else
128		is_durable = 1;
129
130	if (txnp == NULL) {
131		txn_num = 0;
132		lsnp = &null_lsn;
133		null_lsn.file = null_lsn.offset = 0;
134	} else {
135		if (TAILQ_FIRST(&txnp->kids) != NULL &&
136		    (ret = __txn_activekids(env, rectype, txnp)) != 0)
137			return (ret);
138		/*
139		 * We need to assign begin_lsn while holding region mutex.
140		 * That assignment is done inside the DbEnv->log_put call,
141		 * so pass in the appropriate memory location to be filled
142		 * in by the log_put code.
143		 */
144		DB_SET_TXN_LSNP(txnp, &rlsnp, &lsnp);
145		txn_num = txnp->txnid;
146	}
147
148	DB_ASSERT(env, dbp->log_filename != NULL);
149	if (dbp->log_filename->id == DB_LOGFILEID_INVALID &&
150	    (ret = __dbreg_lazy_id(dbp)) != 0)
151		return (ret);
152
153	logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
154	    + sizeof(u_int32_t)
155	    + sizeof(u_int32_t)
156	    + sizeof(u_int32_t)
157	    + sizeof(u_int32_t)
158	    + sizeof(*pagelsn)
159	    + sizeof(u_int32_t) + (key == NULL ? 0 : key->size)
160	    + sizeof(u_int32_t) + (data == NULL ? 0 : data->size);
161	if (CRYPTO_ON(env)) {
162		npad = env->crypto_handle->adj_size(logrec.size);
163		logrec.size += npad;
164	}
165
166	if (is_durable || txnp == NULL) {
167		if ((ret =
168		    __os_malloc(env, logrec.size, &logrec.data)) != 0)
169			return (ret);
170	} else {
171		if ((ret = __os_malloc(env,
172		    logrec.size + sizeof(DB_TXNLOGREC), &lr)) != 0)
173			return (ret);
174#ifdef DIAGNOSTIC
175		if ((ret =
176		    __os_malloc(env, logrec.size, &logrec.data)) != 0) {
177			__os_free(env, lr);
178			return (ret);
179		}
180#else
181		logrec.data = lr->data;
182#endif
183	}
184	if (npad > 0)
185		memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad);
186
187	bp = logrec.data;
188
189	LOGCOPY_32(env, bp, &rectype);
190	bp += sizeof(rectype);
191
192	LOGCOPY_32(env, bp, &txn_num);
193	bp += sizeof(txn_num);
194
195	LOGCOPY_FROMLSN(env, bp, lsnp);
196	bp += sizeof(DB_LSN);
197
198	LOGCOPY_32(env, bp, &opcode);
199	bp += sizeof(opcode);
200
201	uinttmp = (u_int32_t)dbp->log_filename->id;
202	LOGCOPY_32(env, bp, &uinttmp);
203	bp += sizeof(uinttmp);
204
205	uinttmp = (u_int32_t)pgno;
206	LOGCOPY_32(env,bp, &uinttmp);
207	bp += sizeof(uinttmp);
208
209	LOGCOPY_32(env, bp, &ndx);
210	bp += sizeof(ndx);
211
212	if (pagelsn != NULL) {
213		if (txnp != NULL) {
214			LOG *lp = env->lg_handle->reginfo.primary;
215			if (LOG_COMPARE(pagelsn, &lp->lsn) >= 0 && (ret =
216			    __log_check_page_lsn(env, dbp, pagelsn) != 0))
217				return (ret);
218		}
219		LOGCOPY_FROMLSN(env, bp, pagelsn);
220	} else
221		memset(bp, 0, sizeof(*pagelsn));
222	bp += sizeof(*pagelsn);
223
224	if (key == NULL) {
225		zero = 0;
226		LOGCOPY_32(env, bp, &zero);
227		bp += sizeof(u_int32_t);
228	} else {
229		LOGCOPY_32(env, bp, &key->size);
230		bp += sizeof(key->size);
231		memcpy(bp, key->data, key->size);
232		bp += key->size;
233	}
234
235	if (data == NULL) {
236		zero = 0;
237		LOGCOPY_32(env, bp, &zero);
238		bp += sizeof(u_int32_t);
239	} else {
240		LOGCOPY_32(env, bp, &data->size);
241		bp += sizeof(data->size);
242		memcpy(bp, data->data, data->size);
243		bp += data->size;
244	}
245
246	DB_ASSERT(env,
247	    (u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size);
248
249	if (is_durable || txnp == NULL) {
250		if ((ret = __log_put(env, rlsnp,(DBT *)&logrec,
251		    flags | DB_LOG_NOCOPY)) == 0 && txnp != NULL) {
252			*lsnp = *rlsnp;
253			if (rlsnp != ret_lsnp)
254				 *ret_lsnp = *rlsnp;
255		}
256	} else {
257		ret = 0;
258#ifdef DIAGNOSTIC
259		/*
260		 * Set the debug bit if we are going to log non-durable
261		 * transactions so they will be ignored by recovery.
262		 */
263		memcpy(lr->data, logrec.data, logrec.size);
264		rectype |= DB_debug_FLAG;
265		LOGCOPY_32(env, logrec.data, &rectype);
266
267		if (!IS_REP_CLIENT(env))
268			ret = __log_put(env,
269			    rlsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
270#endif
271		STAILQ_INSERT_HEAD(&txnp->logs, lr, links);
272		F_SET((TXN_DETAIL *)txnp->td, TXN_DTL_INMEMORY);
273		LSN_NOT_LOGGED(*ret_lsnp);
274	}
275
276#ifdef LOG_DIAGNOSTIC
277	if (ret != 0)
278		(void)__ham_insdel_print(env,
279		    (DBT *)&logrec, ret_lsnp, DB_TXN_PRINT, NULL);
280#endif
281
282#ifdef DIAGNOSTIC
283	__os_free(env, logrec.data);
284#else
285	if (is_durable || txnp == NULL)
286		__os_free(env, logrec.data);
287#endif
288	return (ret);
289}
290
291/*
292 * PUBLIC: int __ham_newpage_read __P((ENV *, DB **, void *, void *,
293 * PUBLIC:     __ham_newpage_args **));
294 */
295int
296__ham_newpage_read(env, dbpp, td, recbuf, argpp)
297	ENV *env;
298	DB **dbpp;
299	void *td;
300	void *recbuf;
301	__ham_newpage_args **argpp;
302{
303	__ham_newpage_args *argp;
304	u_int32_t uinttmp;
305	u_int8_t *bp;
306	int ret;
307
308	if ((ret = __os_malloc(env,
309	    sizeof(__ham_newpage_args) + sizeof(DB_TXN), &argp)) != 0)
310		return (ret);
311	bp = recbuf;
312	argp->txnp = (DB_TXN *)&argp[1];
313	memset(argp->txnp, 0, sizeof(DB_TXN));
314
315	argp->txnp->td = td;
316	LOGCOPY_32(env, &argp->type, bp);
317	bp += sizeof(argp->type);
318
319	LOGCOPY_32(env, &argp->txnp->txnid, bp);
320	bp += sizeof(argp->txnp->txnid);
321
322	LOGCOPY_TOLSN(env, &argp->prev_lsn, bp);
323	bp += sizeof(DB_LSN);
324
325	LOGCOPY_32(env, &argp->opcode, bp);
326	bp += sizeof(argp->opcode);
327
328	LOGCOPY_32(env, &uinttmp, bp);
329	argp->fileid = (int32_t)uinttmp;
330	bp += sizeof(uinttmp);
331	if (dbpp != NULL) {
332		*dbpp = NULL;
333		ret = __dbreg_id_to_db(
334		    env, argp->txnp, dbpp, argp->fileid, 1);
335	}
336
337	LOGCOPY_32(env, &uinttmp, bp);
338	argp->prev_pgno = (db_pgno_t)uinttmp;
339	bp += sizeof(uinttmp);
340
341	LOGCOPY_TOLSN(env, &argp->prevlsn, bp);
342	bp += sizeof(DB_LSN);
343
344	LOGCOPY_32(env, &uinttmp, bp);
345	argp->new_pgno = (db_pgno_t)uinttmp;
346	bp += sizeof(uinttmp);
347
348	LOGCOPY_TOLSN(env, &argp->pagelsn, bp);
349	bp += sizeof(DB_LSN);
350
351	LOGCOPY_32(env, &uinttmp, bp);
352	argp->next_pgno = (db_pgno_t)uinttmp;
353	bp += sizeof(uinttmp);
354
355	LOGCOPY_TOLSN(env, &argp->nextlsn, bp);
356	bp += sizeof(DB_LSN);
357
358	*argpp = argp;
359	return (ret);
360}
361
362/*
363 * PUBLIC: int __ham_newpage_log __P((DB *, DB_TXN *, DB_LSN *,
364 * PUBLIC:     u_int32_t, u_int32_t, db_pgno_t, DB_LSN *, db_pgno_t, DB_LSN *,
365 * PUBLIC:     db_pgno_t, DB_LSN *));
366 */
367int
368__ham_newpage_log(dbp, txnp, ret_lsnp, flags,
369    opcode, prev_pgno, prevlsn, new_pgno, pagelsn,
370    next_pgno, nextlsn)
371	DB *dbp;
372	DB_TXN *txnp;
373	DB_LSN *ret_lsnp;
374	u_int32_t flags;
375	u_int32_t opcode;
376	db_pgno_t prev_pgno;
377	DB_LSN * prevlsn;
378	db_pgno_t new_pgno;
379	DB_LSN * pagelsn;
380	db_pgno_t next_pgno;
381	DB_LSN * nextlsn;
382{
383	DBT logrec;
384	DB_LSN *lsnp, null_lsn, *rlsnp;
385	DB_TXNLOGREC *lr;
386	ENV *env;
387	u_int32_t uinttmp, rectype, txn_num;
388	u_int npad;
389	u_int8_t *bp;
390	int is_durable, ret;
391
392	COMPQUIET(lr, NULL);
393
394	env = dbp->env;
395	rlsnp = ret_lsnp;
396	rectype = DB___ham_newpage;
397	npad = 0;
398	ret = 0;
399
400	if (LF_ISSET(DB_LOG_NOT_DURABLE) ||
401	    F_ISSET(dbp, DB_AM_NOT_DURABLE)) {
402		if (txnp == NULL)
403			return (0);
404		is_durable = 0;
405	} else
406		is_durable = 1;
407
408	if (txnp == NULL) {
409		txn_num = 0;
410		lsnp = &null_lsn;
411		null_lsn.file = null_lsn.offset = 0;
412	} else {
413		if (TAILQ_FIRST(&txnp->kids) != NULL &&
414		    (ret = __txn_activekids(env, rectype, txnp)) != 0)
415			return (ret);
416		/*
417		 * We need to assign begin_lsn while holding region mutex.
418		 * That assignment is done inside the DbEnv->log_put call,
419		 * so pass in the appropriate memory location to be filled
420		 * in by the log_put code.
421		 */
422		DB_SET_TXN_LSNP(txnp, &rlsnp, &lsnp);
423		txn_num = txnp->txnid;
424	}
425
426	DB_ASSERT(env, dbp->log_filename != NULL);
427	if (dbp->log_filename->id == DB_LOGFILEID_INVALID &&
428	    (ret = __dbreg_lazy_id(dbp)) != 0)
429		return (ret);
430
431	logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
432	    + sizeof(u_int32_t)
433	    + sizeof(u_int32_t)
434	    + sizeof(u_int32_t)
435	    + sizeof(*prevlsn)
436	    + sizeof(u_int32_t)
437	    + sizeof(*pagelsn)
438	    + sizeof(u_int32_t)
439	    + sizeof(*nextlsn);
440	if (CRYPTO_ON(env)) {
441		npad = env->crypto_handle->adj_size(logrec.size);
442		logrec.size += npad;
443	}
444
445	if (is_durable || txnp == NULL) {
446		if ((ret =
447		    __os_malloc(env, logrec.size, &logrec.data)) != 0)
448			return (ret);
449	} else {
450		if ((ret = __os_malloc(env,
451		    logrec.size + sizeof(DB_TXNLOGREC), &lr)) != 0)
452			return (ret);
453#ifdef DIAGNOSTIC
454		if ((ret =
455		    __os_malloc(env, logrec.size, &logrec.data)) != 0) {
456			__os_free(env, lr);
457			return (ret);
458		}
459#else
460		logrec.data = lr->data;
461#endif
462	}
463	if (npad > 0)
464		memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad);
465
466	bp = logrec.data;
467
468	LOGCOPY_32(env, bp, &rectype);
469	bp += sizeof(rectype);
470
471	LOGCOPY_32(env, bp, &txn_num);
472	bp += sizeof(txn_num);
473
474	LOGCOPY_FROMLSN(env, bp, lsnp);
475	bp += sizeof(DB_LSN);
476
477	LOGCOPY_32(env, bp, &opcode);
478	bp += sizeof(opcode);
479
480	uinttmp = (u_int32_t)dbp->log_filename->id;
481	LOGCOPY_32(env, bp, &uinttmp);
482	bp += sizeof(uinttmp);
483
484	uinttmp = (u_int32_t)prev_pgno;
485	LOGCOPY_32(env,bp, &uinttmp);
486	bp += sizeof(uinttmp);
487
488	if (prevlsn != NULL) {
489		if (txnp != NULL) {
490			LOG *lp = env->lg_handle->reginfo.primary;
491			if (LOG_COMPARE(prevlsn, &lp->lsn) >= 0 && (ret =
492			    __log_check_page_lsn(env, dbp, prevlsn) != 0))
493				return (ret);
494		}
495		LOGCOPY_FROMLSN(env, bp, prevlsn);
496	} else
497		memset(bp, 0, sizeof(*prevlsn));
498	bp += sizeof(*prevlsn);
499
500	uinttmp = (u_int32_t)new_pgno;
501	LOGCOPY_32(env,bp, &uinttmp);
502	bp += sizeof(uinttmp);
503
504	if (pagelsn != NULL) {
505		if (txnp != NULL) {
506			LOG *lp = env->lg_handle->reginfo.primary;
507			if (LOG_COMPARE(pagelsn, &lp->lsn) >= 0 && (ret =
508			    __log_check_page_lsn(env, dbp, pagelsn) != 0))
509				return (ret);
510		}
511		LOGCOPY_FROMLSN(env, bp, pagelsn);
512	} else
513		memset(bp, 0, sizeof(*pagelsn));
514	bp += sizeof(*pagelsn);
515
516	uinttmp = (u_int32_t)next_pgno;
517	LOGCOPY_32(env,bp, &uinttmp);
518	bp += sizeof(uinttmp);
519
520	if (nextlsn != NULL) {
521		if (txnp != NULL) {
522			LOG *lp = env->lg_handle->reginfo.primary;
523			if (LOG_COMPARE(nextlsn, &lp->lsn) >= 0 && (ret =
524			    __log_check_page_lsn(env, dbp, nextlsn) != 0))
525				return (ret);
526		}
527		LOGCOPY_FROMLSN(env, bp, nextlsn);
528	} else
529		memset(bp, 0, sizeof(*nextlsn));
530	bp += sizeof(*nextlsn);
531
532	DB_ASSERT(env,
533	    (u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size);
534
535	if (is_durable || txnp == NULL) {
536		if ((ret = __log_put(env, rlsnp,(DBT *)&logrec,
537		    flags | DB_LOG_NOCOPY)) == 0 && txnp != NULL) {
538			*lsnp = *rlsnp;
539			if (rlsnp != ret_lsnp)
540				 *ret_lsnp = *rlsnp;
541		}
542	} else {
543		ret = 0;
544#ifdef DIAGNOSTIC
545		/*
546		 * Set the debug bit if we are going to log non-durable
547		 * transactions so they will be ignored by recovery.
548		 */
549		memcpy(lr->data, logrec.data, logrec.size);
550		rectype |= DB_debug_FLAG;
551		LOGCOPY_32(env, logrec.data, &rectype);
552
553		if (!IS_REP_CLIENT(env))
554			ret = __log_put(env,
555			    rlsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
556#endif
557		STAILQ_INSERT_HEAD(&txnp->logs, lr, links);
558		F_SET((TXN_DETAIL *)txnp->td, TXN_DTL_INMEMORY);
559		LSN_NOT_LOGGED(*ret_lsnp);
560	}
561
562#ifdef LOG_DIAGNOSTIC
563	if (ret != 0)
564		(void)__ham_newpage_print(env,
565		    (DBT *)&logrec, ret_lsnp, DB_TXN_PRINT, NULL);
566#endif
567
568#ifdef DIAGNOSTIC
569	__os_free(env, logrec.data);
570#else
571	if (is_durable || txnp == NULL)
572		__os_free(env, logrec.data);
573#endif
574	return (ret);
575}
576
577/*
578 * PUBLIC: int __ham_splitdata_read __P((ENV *, DB **, void *,
579 * PUBLIC:     void *, __ham_splitdata_args **));
580 */
581int
582__ham_splitdata_read(env, dbpp, td, recbuf, argpp)
583	ENV *env;
584	DB **dbpp;
585	void *td;
586	void *recbuf;
587	__ham_splitdata_args **argpp;
588{
589	__ham_splitdata_args *argp;
590	u_int32_t uinttmp;
591	u_int8_t *bp;
592	int ret;
593
594	if ((ret = __os_malloc(env,
595	    sizeof(__ham_splitdata_args) + sizeof(DB_TXN), &argp)) != 0)
596		return (ret);
597	bp = recbuf;
598	argp->txnp = (DB_TXN *)&argp[1];
599	memset(argp->txnp, 0, sizeof(DB_TXN));
600
601	argp->txnp->td = td;
602	LOGCOPY_32(env, &argp->type, bp);
603	bp += sizeof(argp->type);
604
605	LOGCOPY_32(env, &argp->txnp->txnid, bp);
606	bp += sizeof(argp->txnp->txnid);
607
608	LOGCOPY_TOLSN(env, &argp->prev_lsn, bp);
609	bp += sizeof(DB_LSN);
610
611	LOGCOPY_32(env, &uinttmp, bp);
612	argp->fileid = (int32_t)uinttmp;
613	bp += sizeof(uinttmp);
614	if (dbpp != NULL) {
615		*dbpp = NULL;
616		ret = __dbreg_id_to_db(
617		    env, argp->txnp, dbpp, argp->fileid, 1);
618	}
619
620	LOGCOPY_32(env, &argp->opcode, bp);
621	bp += sizeof(argp->opcode);
622
623	LOGCOPY_32(env, &uinttmp, bp);
624	argp->pgno = (db_pgno_t)uinttmp;
625	bp += sizeof(uinttmp);
626
627	memset(&argp->pageimage, 0, sizeof(argp->pageimage));
628	LOGCOPY_32(env,&argp->pageimage.size, bp);
629	bp += sizeof(u_int32_t);
630	argp->pageimage.data = bp;
631	bp += argp->pageimage.size;
632	if (LOG_SWAPPED(env) && dbpp != NULL && *dbpp != NULL) {
633		int t_ret;
634		if ((t_ret = __db_pageswap(*dbpp, (PAGE *)argp->pageimage.data,
635		    (size_t)argp->pageimage.size, NULL, 1)) != 0)
636			return (t_ret);
637	}
638
639	LOGCOPY_TOLSN(env, &argp->pagelsn, bp);
640	bp += sizeof(DB_LSN);
641
642	*argpp = argp;
643	return (ret);
644}
645
646/*
647 * PUBLIC: int __ham_splitdata_log __P((DB *, DB_TXN *, DB_LSN *,
648 * PUBLIC:     u_int32_t, u_int32_t, db_pgno_t, const DBT *, DB_LSN *));
649 */
650int
651__ham_splitdata_log(dbp, txnp, ret_lsnp, flags, opcode, pgno, pageimage, pagelsn)
652	DB *dbp;
653	DB_TXN *txnp;
654	DB_LSN *ret_lsnp;
655	u_int32_t flags;
656	u_int32_t opcode;
657	db_pgno_t pgno;
658	const DBT *pageimage;
659	DB_LSN * pagelsn;
660{
661	DBT logrec;
662	DB_LSN *lsnp, null_lsn, *rlsnp;
663	DB_TXNLOGREC *lr;
664	ENV *env;
665	u_int32_t zero, uinttmp, rectype, txn_num;
666	u_int npad;
667	u_int8_t *bp;
668	int is_durable, ret;
669
670	COMPQUIET(lr, NULL);
671
672	env = dbp->env;
673	rlsnp = ret_lsnp;
674	rectype = DB___ham_splitdata;
675	npad = 0;
676	ret = 0;
677
678	if (LF_ISSET(DB_LOG_NOT_DURABLE) ||
679	    F_ISSET(dbp, DB_AM_NOT_DURABLE)) {
680		if (txnp == NULL)
681			return (0);
682		is_durable = 0;
683	} else
684		is_durable = 1;
685
686	if (txnp == NULL) {
687		txn_num = 0;
688		lsnp = &null_lsn;
689		null_lsn.file = null_lsn.offset = 0;
690	} else {
691		if (TAILQ_FIRST(&txnp->kids) != NULL &&
692		    (ret = __txn_activekids(env, rectype, txnp)) != 0)
693			return (ret);
694		/*
695		 * We need to assign begin_lsn while holding region mutex.
696		 * That assignment is done inside the DbEnv->log_put call,
697		 * so pass in the appropriate memory location to be filled
698		 * in by the log_put code.
699		 */
700		DB_SET_TXN_LSNP(txnp, &rlsnp, &lsnp);
701		txn_num = txnp->txnid;
702	}
703
704	DB_ASSERT(env, dbp->log_filename != NULL);
705	if (dbp->log_filename->id == DB_LOGFILEID_INVALID &&
706	    (ret = __dbreg_lazy_id(dbp)) != 0)
707		return (ret);
708
709	logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
710	    + sizeof(u_int32_t)
711	    + sizeof(u_int32_t)
712	    + sizeof(u_int32_t)
713	    + sizeof(u_int32_t) + (pageimage == NULL ? 0 : pageimage->size)
714	    + sizeof(*pagelsn);
715	if (CRYPTO_ON(env)) {
716		npad = env->crypto_handle->adj_size(logrec.size);
717		logrec.size += npad;
718	}
719
720	if (is_durable || txnp == NULL) {
721		if ((ret =
722		    __os_malloc(env, logrec.size, &logrec.data)) != 0)
723			return (ret);
724	} else {
725		if ((ret = __os_malloc(env,
726		    logrec.size + sizeof(DB_TXNLOGREC), &lr)) != 0)
727			return (ret);
728#ifdef DIAGNOSTIC
729		if ((ret =
730		    __os_malloc(env, logrec.size, &logrec.data)) != 0) {
731			__os_free(env, lr);
732			return (ret);
733		}
734#else
735		logrec.data = lr->data;
736#endif
737	}
738	if (npad > 0)
739		memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad);
740
741	bp = logrec.data;
742
743	LOGCOPY_32(env, bp, &rectype);
744	bp += sizeof(rectype);
745
746	LOGCOPY_32(env, bp, &txn_num);
747	bp += sizeof(txn_num);
748
749	LOGCOPY_FROMLSN(env, bp, lsnp);
750	bp += sizeof(DB_LSN);
751
752	uinttmp = (u_int32_t)dbp->log_filename->id;
753	LOGCOPY_32(env, bp, &uinttmp);
754	bp += sizeof(uinttmp);
755
756	LOGCOPY_32(env, bp, &opcode);
757	bp += sizeof(opcode);
758
759	uinttmp = (u_int32_t)pgno;
760	LOGCOPY_32(env,bp, &uinttmp);
761	bp += sizeof(uinttmp);
762
763	if (pageimage == NULL) {
764		zero = 0;
765		LOGCOPY_32(env, bp, &zero);
766		bp += sizeof(u_int32_t);
767	} else {
768		LOGCOPY_32(env, bp, &pageimage->size);
769		bp += sizeof(pageimage->size);
770		memcpy(bp, pageimage->data, pageimage->size);
771		if (LOG_SWAPPED(env))
772			if ((ret = __db_pageswap(dbp,
773			    (PAGE *)bp, (size_t)pageimage->size, (DBT *)NULL, 0)) != 0)
774				return (ret);
775		bp += pageimage->size;
776	}
777
778	if (pagelsn != NULL) {
779		if (txnp != NULL) {
780			LOG *lp = env->lg_handle->reginfo.primary;
781			if (LOG_COMPARE(pagelsn, &lp->lsn) >= 0 && (ret =
782			    __log_check_page_lsn(env, dbp, pagelsn) != 0))
783				return (ret);
784		}
785		LOGCOPY_FROMLSN(env, bp, pagelsn);
786	} else
787		memset(bp, 0, sizeof(*pagelsn));
788	bp += sizeof(*pagelsn);
789
790	DB_ASSERT(env,
791	    (u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size);
792
793	if (is_durable || txnp == NULL) {
794		if ((ret = __log_put(env, rlsnp,(DBT *)&logrec,
795		    flags | DB_LOG_NOCOPY)) == 0 && txnp != NULL) {
796			*lsnp = *rlsnp;
797			if (rlsnp != ret_lsnp)
798				 *ret_lsnp = *rlsnp;
799		}
800	} else {
801		ret = 0;
802#ifdef DIAGNOSTIC
803		/*
804		 * Set the debug bit if we are going to log non-durable
805		 * transactions so they will be ignored by recovery.
806		 */
807		memcpy(lr->data, logrec.data, logrec.size);
808		rectype |= DB_debug_FLAG;
809		LOGCOPY_32(env, logrec.data, &rectype);
810
811		if (!IS_REP_CLIENT(env))
812			ret = __log_put(env,
813			    rlsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
814#endif
815		STAILQ_INSERT_HEAD(&txnp->logs, lr, links);
816		F_SET((TXN_DETAIL *)txnp->td, TXN_DTL_INMEMORY);
817		LSN_NOT_LOGGED(*ret_lsnp);
818	}
819
820#ifdef LOG_DIAGNOSTIC
821	if (ret != 0)
822		(void)__ham_splitdata_print(env,
823		    (DBT *)&logrec, ret_lsnp, DB_TXN_PRINT, NULL);
824#endif
825
826#ifdef DIAGNOSTIC
827	__os_free(env, logrec.data);
828#else
829	if (is_durable || txnp == NULL)
830		__os_free(env, logrec.data);
831#endif
832	return (ret);
833}
834
835/*
836 * PUBLIC: int __ham_replace_read __P((ENV *, DB **, void *, void *,
837 * PUBLIC:     __ham_replace_args **));
838 */
839int
840__ham_replace_read(env, dbpp, td, recbuf, argpp)
841	ENV *env;
842	DB **dbpp;
843	void *td;
844	void *recbuf;
845	__ham_replace_args **argpp;
846{
847	__ham_replace_args *argp;
848	u_int32_t uinttmp;
849	u_int8_t *bp;
850	int ret;
851
852	if ((ret = __os_malloc(env,
853	    sizeof(__ham_replace_args) + sizeof(DB_TXN), &argp)) != 0)
854		return (ret);
855	bp = recbuf;
856	argp->txnp = (DB_TXN *)&argp[1];
857	memset(argp->txnp, 0, sizeof(DB_TXN));
858
859	argp->txnp->td = td;
860	LOGCOPY_32(env, &argp->type, bp);
861	bp += sizeof(argp->type);
862
863	LOGCOPY_32(env, &argp->txnp->txnid, bp);
864	bp += sizeof(argp->txnp->txnid);
865
866	LOGCOPY_TOLSN(env, &argp->prev_lsn, bp);
867	bp += sizeof(DB_LSN);
868
869	LOGCOPY_32(env, &uinttmp, bp);
870	argp->fileid = (int32_t)uinttmp;
871	bp += sizeof(uinttmp);
872	if (dbpp != NULL) {
873		*dbpp = NULL;
874		ret = __dbreg_id_to_db(
875		    env, argp->txnp, dbpp, argp->fileid, 1);
876	}
877
878	LOGCOPY_32(env, &uinttmp, bp);
879	argp->pgno = (db_pgno_t)uinttmp;
880	bp += sizeof(uinttmp);
881
882	LOGCOPY_32(env, &argp->ndx, bp);
883	bp += sizeof(argp->ndx);
884
885	LOGCOPY_TOLSN(env, &argp->pagelsn, bp);
886	bp += sizeof(DB_LSN);
887
888	LOGCOPY_32(env, &uinttmp, bp);
889	argp->off = (int32_t)uinttmp;
890	bp += sizeof(uinttmp);
891
892	memset(&argp->olditem, 0, sizeof(argp->olditem));
893	LOGCOPY_32(env,&argp->olditem.size, bp);
894	bp += sizeof(u_int32_t);
895	argp->olditem.data = bp;
896	bp += argp->olditem.size;
897
898	memset(&argp->newitem, 0, sizeof(argp->newitem));
899	LOGCOPY_32(env,&argp->newitem.size, bp);
900	bp += sizeof(u_int32_t);
901	argp->newitem.data = bp;
902	bp += argp->newitem.size;
903
904	LOGCOPY_32(env, &argp->makedup, bp);
905	bp += sizeof(argp->makedup);
906
907	*argpp = argp;
908	return (ret);
909}
910
911/*
912 * PUBLIC: int __ham_replace_log __P((DB *, DB_TXN *, DB_LSN *,
913 * PUBLIC:     u_int32_t, db_pgno_t, u_int32_t, DB_LSN *, int32_t, const DBT *,
914 * PUBLIC:     const DBT *, u_int32_t));
915 */
916int
917__ham_replace_log(dbp, txnp, ret_lsnp, flags, pgno, ndx, pagelsn, off, olditem,
918    newitem, makedup)
919	DB *dbp;
920	DB_TXN *txnp;
921	DB_LSN *ret_lsnp;
922	u_int32_t flags;
923	db_pgno_t pgno;
924	u_int32_t ndx;
925	DB_LSN * pagelsn;
926	int32_t off;
927	const DBT *olditem;
928	const DBT *newitem;
929	u_int32_t makedup;
930{
931	DBT logrec;
932	DB_LSN *lsnp, null_lsn, *rlsnp;
933	DB_TXNLOGREC *lr;
934	ENV *env;
935	u_int32_t zero, uinttmp, rectype, txn_num;
936	u_int npad;
937	u_int8_t *bp;
938	int is_durable, ret;
939
940	COMPQUIET(lr, NULL);
941
942	env = dbp->env;
943	rlsnp = ret_lsnp;
944	rectype = DB___ham_replace;
945	npad = 0;
946	ret = 0;
947
948	if (LF_ISSET(DB_LOG_NOT_DURABLE) ||
949	    F_ISSET(dbp, DB_AM_NOT_DURABLE)) {
950		if (txnp == NULL)
951			return (0);
952		is_durable = 0;
953	} else
954		is_durable = 1;
955
956	if (txnp == NULL) {
957		txn_num = 0;
958		lsnp = &null_lsn;
959		null_lsn.file = null_lsn.offset = 0;
960	} else {
961		if (TAILQ_FIRST(&txnp->kids) != NULL &&
962		    (ret = __txn_activekids(env, rectype, txnp)) != 0)
963			return (ret);
964		/*
965		 * We need to assign begin_lsn while holding region mutex.
966		 * That assignment is done inside the DbEnv->log_put call,
967		 * so pass in the appropriate memory location to be filled
968		 * in by the log_put code.
969		 */
970		DB_SET_TXN_LSNP(txnp, &rlsnp, &lsnp);
971		txn_num = txnp->txnid;
972	}
973
974	DB_ASSERT(env, dbp->log_filename != NULL);
975	if (dbp->log_filename->id == DB_LOGFILEID_INVALID &&
976	    (ret = __dbreg_lazy_id(dbp)) != 0)
977		return (ret);
978
979	logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
980	    + sizeof(u_int32_t)
981	    + sizeof(u_int32_t)
982	    + sizeof(u_int32_t)
983	    + sizeof(*pagelsn)
984	    + sizeof(u_int32_t)
985	    + sizeof(u_int32_t) + (olditem == NULL ? 0 : olditem->size)
986	    + sizeof(u_int32_t) + (newitem == NULL ? 0 : newitem->size)
987	    + sizeof(u_int32_t);
988	if (CRYPTO_ON(env)) {
989		npad = env->crypto_handle->adj_size(logrec.size);
990		logrec.size += npad;
991	}
992
993	if (is_durable || txnp == NULL) {
994		if ((ret =
995		    __os_malloc(env, logrec.size, &logrec.data)) != 0)
996			return (ret);
997	} else {
998		if ((ret = __os_malloc(env,
999		    logrec.size + sizeof(DB_TXNLOGREC), &lr)) != 0)
1000			return (ret);
1001#ifdef DIAGNOSTIC
1002		if ((ret =
1003		    __os_malloc(env, logrec.size, &logrec.data)) != 0) {
1004			__os_free(env, lr);
1005			return (ret);
1006		}
1007#else
1008		logrec.data = lr->data;
1009#endif
1010	}
1011	if (npad > 0)
1012		memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad);
1013
1014	bp = logrec.data;
1015
1016	LOGCOPY_32(env, bp, &rectype);
1017	bp += sizeof(rectype);
1018
1019	LOGCOPY_32(env, bp, &txn_num);
1020	bp += sizeof(txn_num);
1021
1022	LOGCOPY_FROMLSN(env, bp, lsnp);
1023	bp += sizeof(DB_LSN);
1024
1025	uinttmp = (u_int32_t)dbp->log_filename->id;
1026	LOGCOPY_32(env, bp, &uinttmp);
1027	bp += sizeof(uinttmp);
1028
1029	uinttmp = (u_int32_t)pgno;
1030	LOGCOPY_32(env,bp, &uinttmp);
1031	bp += sizeof(uinttmp);
1032
1033	LOGCOPY_32(env, bp, &ndx);
1034	bp += sizeof(ndx);
1035
1036	if (pagelsn != NULL) {
1037		if (txnp != NULL) {
1038			LOG *lp = env->lg_handle->reginfo.primary;
1039			if (LOG_COMPARE(pagelsn, &lp->lsn) >= 0 && (ret =
1040			    __log_check_page_lsn(env, dbp, pagelsn) != 0))
1041				return (ret);
1042		}
1043		LOGCOPY_FROMLSN(env, bp, pagelsn);
1044	} else
1045		memset(bp, 0, sizeof(*pagelsn));
1046	bp += sizeof(*pagelsn);
1047
1048	uinttmp = (u_int32_t)off;
1049	LOGCOPY_32(env,bp, &uinttmp);
1050	bp += sizeof(uinttmp);
1051
1052	if (olditem == NULL) {
1053		zero = 0;
1054		LOGCOPY_32(env, bp, &zero);
1055		bp += sizeof(u_int32_t);
1056	} else {
1057		LOGCOPY_32(env, bp, &olditem->size);
1058		bp += sizeof(olditem->size);
1059		memcpy(bp, olditem->data, olditem->size);
1060		bp += olditem->size;
1061	}
1062
1063	if (newitem == NULL) {
1064		zero = 0;
1065		LOGCOPY_32(env, bp, &zero);
1066		bp += sizeof(u_int32_t);
1067	} else {
1068		LOGCOPY_32(env, bp, &newitem->size);
1069		bp += sizeof(newitem->size);
1070		memcpy(bp, newitem->data, newitem->size);
1071		bp += newitem->size;
1072	}
1073
1074	LOGCOPY_32(env, bp, &makedup);
1075	bp += sizeof(makedup);
1076
1077	DB_ASSERT(env,
1078	    (u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size);
1079
1080	if (is_durable || txnp == NULL) {
1081		if ((ret = __log_put(env, rlsnp,(DBT *)&logrec,
1082		    flags | DB_LOG_NOCOPY)) == 0 && txnp != NULL) {
1083			*lsnp = *rlsnp;
1084			if (rlsnp != ret_lsnp)
1085				 *ret_lsnp = *rlsnp;
1086		}
1087	} else {
1088		ret = 0;
1089#ifdef DIAGNOSTIC
1090		/*
1091		 * Set the debug bit if we are going to log non-durable
1092		 * transactions so they will be ignored by recovery.
1093		 */
1094		memcpy(lr->data, logrec.data, logrec.size);
1095		rectype |= DB_debug_FLAG;
1096		LOGCOPY_32(env, logrec.data, &rectype);
1097
1098		if (!IS_REP_CLIENT(env))
1099			ret = __log_put(env,
1100			    rlsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
1101#endif
1102		STAILQ_INSERT_HEAD(&txnp->logs, lr, links);
1103		F_SET((TXN_DETAIL *)txnp->td, TXN_DTL_INMEMORY);
1104		LSN_NOT_LOGGED(*ret_lsnp);
1105	}
1106
1107#ifdef LOG_DIAGNOSTIC
1108	if (ret != 0)
1109		(void)__ham_replace_print(env,
1110		    (DBT *)&logrec, ret_lsnp, DB_TXN_PRINT, NULL);
1111#endif
1112
1113#ifdef DIAGNOSTIC
1114	__os_free(env, logrec.data);
1115#else
1116	if (is_durable || txnp == NULL)
1117		__os_free(env, logrec.data);
1118#endif
1119	return (ret);
1120}
1121
1122/*
1123 * PUBLIC: int __ham_copypage_read __P((ENV *, DB **, void *,
1124 * PUBLIC:     void *, __ham_copypage_args **));
1125 */
1126int
1127__ham_copypage_read(env, dbpp, td, recbuf, argpp)
1128	ENV *env;
1129	DB **dbpp;
1130	void *td;
1131	void *recbuf;
1132	__ham_copypage_args **argpp;
1133{
1134	__ham_copypage_args *argp;
1135	u_int32_t uinttmp;
1136	u_int8_t *bp;
1137	int ret;
1138
1139	if ((ret = __os_malloc(env,
1140	    sizeof(__ham_copypage_args) + sizeof(DB_TXN), &argp)) != 0)
1141		return (ret);
1142	bp = recbuf;
1143	argp->txnp = (DB_TXN *)&argp[1];
1144	memset(argp->txnp, 0, sizeof(DB_TXN));
1145
1146	argp->txnp->td = td;
1147	LOGCOPY_32(env, &argp->type, bp);
1148	bp += sizeof(argp->type);
1149
1150	LOGCOPY_32(env, &argp->txnp->txnid, bp);
1151	bp += sizeof(argp->txnp->txnid);
1152
1153	LOGCOPY_TOLSN(env, &argp->prev_lsn, bp);
1154	bp += sizeof(DB_LSN);
1155
1156	LOGCOPY_32(env, &uinttmp, bp);
1157	argp->fileid = (int32_t)uinttmp;
1158	bp += sizeof(uinttmp);
1159	if (dbpp != NULL) {
1160		*dbpp = NULL;
1161		ret = __dbreg_id_to_db(
1162		    env, argp->txnp, dbpp, argp->fileid, 1);
1163	}
1164
1165	LOGCOPY_32(env, &uinttmp, bp);
1166	argp->pgno = (db_pgno_t)uinttmp;
1167	bp += sizeof(uinttmp);
1168
1169	LOGCOPY_TOLSN(env, &argp->pagelsn, bp);
1170	bp += sizeof(DB_LSN);
1171
1172	LOGCOPY_32(env, &uinttmp, bp);
1173	argp->next_pgno = (db_pgno_t)uinttmp;
1174	bp += sizeof(uinttmp);
1175
1176	LOGCOPY_TOLSN(env, &argp->nextlsn, bp);
1177	bp += sizeof(DB_LSN);
1178
1179	LOGCOPY_32(env, &uinttmp, bp);
1180	argp->nnext_pgno = (db_pgno_t)uinttmp;
1181	bp += sizeof(uinttmp);
1182
1183	LOGCOPY_TOLSN(env, &argp->nnextlsn, bp);
1184	bp += sizeof(DB_LSN);
1185
1186	memset(&argp->page, 0, sizeof(argp->page));
1187	LOGCOPY_32(env,&argp->page.size, bp);
1188	bp += sizeof(u_int32_t);
1189	argp->page.data = bp;
1190	bp += argp->page.size;
1191	if (LOG_SWAPPED(env) && dbpp != NULL && *dbpp != NULL) {
1192		int t_ret;
1193		if ((t_ret = __db_pageswap(*dbpp, (PAGE *)argp->page.data,
1194		    (size_t)argp->page.size, NULL, 1)) != 0)
1195			return (t_ret);
1196	}
1197
1198	*argpp = argp;
1199	return (ret);
1200}
1201
1202/*
1203 * PUBLIC: int __ham_copypage_log __P((DB *, DB_TXN *, DB_LSN *,
1204 * PUBLIC:     u_int32_t, db_pgno_t, DB_LSN *, db_pgno_t, DB_LSN *, db_pgno_t,
1205 * PUBLIC:     DB_LSN *, const DBT *));
1206 */
1207int
1208__ham_copypage_log(dbp, txnp, ret_lsnp, flags, pgno, pagelsn, next_pgno, nextlsn, nnext_pgno,
1209    nnextlsn, page)
1210	DB *dbp;
1211	DB_TXN *txnp;
1212	DB_LSN *ret_lsnp;
1213	u_int32_t flags;
1214	db_pgno_t pgno;
1215	DB_LSN * pagelsn;
1216	db_pgno_t next_pgno;
1217	DB_LSN * nextlsn;
1218	db_pgno_t nnext_pgno;
1219	DB_LSN * nnextlsn;
1220	const DBT *page;
1221{
1222	DBT logrec;
1223	DB_LSN *lsnp, null_lsn, *rlsnp;
1224	DB_TXNLOGREC *lr;
1225	ENV *env;
1226	u_int32_t zero, uinttmp, rectype, txn_num;
1227	u_int npad;
1228	u_int8_t *bp;
1229	int is_durable, ret;
1230
1231	COMPQUIET(lr, NULL);
1232
1233	env = dbp->env;
1234	rlsnp = ret_lsnp;
1235	rectype = DB___ham_copypage;
1236	npad = 0;
1237	ret = 0;
1238
1239	if (LF_ISSET(DB_LOG_NOT_DURABLE) ||
1240	    F_ISSET(dbp, DB_AM_NOT_DURABLE)) {
1241		if (txnp == NULL)
1242			return (0);
1243		is_durable = 0;
1244	} else
1245		is_durable = 1;
1246
1247	if (txnp == NULL) {
1248		txn_num = 0;
1249		lsnp = &null_lsn;
1250		null_lsn.file = null_lsn.offset = 0;
1251	} else {
1252		if (TAILQ_FIRST(&txnp->kids) != NULL &&
1253		    (ret = __txn_activekids(env, rectype, txnp)) != 0)
1254			return (ret);
1255		/*
1256		 * We need to assign begin_lsn while holding region mutex.
1257		 * That assignment is done inside the DbEnv->log_put call,
1258		 * so pass in the appropriate memory location to be filled
1259		 * in by the log_put code.
1260		 */
1261		DB_SET_TXN_LSNP(txnp, &rlsnp, &lsnp);
1262		txn_num = txnp->txnid;
1263	}
1264
1265	DB_ASSERT(env, dbp->log_filename != NULL);
1266	if (dbp->log_filename->id == DB_LOGFILEID_INVALID &&
1267	    (ret = __dbreg_lazy_id(dbp)) != 0)
1268		return (ret);
1269
1270	logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
1271	    + sizeof(u_int32_t)
1272	    + sizeof(u_int32_t)
1273	    + sizeof(*pagelsn)
1274	    + sizeof(u_int32_t)
1275	    + sizeof(*nextlsn)
1276	    + sizeof(u_int32_t)
1277	    + sizeof(*nnextlsn)
1278	    + sizeof(u_int32_t) + (page == NULL ? 0 : page->size);
1279	if (CRYPTO_ON(env)) {
1280		npad = env->crypto_handle->adj_size(logrec.size);
1281		logrec.size += npad;
1282	}
1283
1284	if (is_durable || txnp == NULL) {
1285		if ((ret =
1286		    __os_malloc(env, logrec.size, &logrec.data)) != 0)
1287			return (ret);
1288	} else {
1289		if ((ret = __os_malloc(env,
1290		    logrec.size + sizeof(DB_TXNLOGREC), &lr)) != 0)
1291			return (ret);
1292#ifdef DIAGNOSTIC
1293		if ((ret =
1294		    __os_malloc(env, logrec.size, &logrec.data)) != 0) {
1295			__os_free(env, lr);
1296			return (ret);
1297		}
1298#else
1299		logrec.data = lr->data;
1300#endif
1301	}
1302	if (npad > 0)
1303		memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad);
1304
1305	bp = logrec.data;
1306
1307	LOGCOPY_32(env, bp, &rectype);
1308	bp += sizeof(rectype);
1309
1310	LOGCOPY_32(env, bp, &txn_num);
1311	bp += sizeof(txn_num);
1312
1313	LOGCOPY_FROMLSN(env, bp, lsnp);
1314	bp += sizeof(DB_LSN);
1315
1316	uinttmp = (u_int32_t)dbp->log_filename->id;
1317	LOGCOPY_32(env, bp, &uinttmp);
1318	bp += sizeof(uinttmp);
1319
1320	uinttmp = (u_int32_t)pgno;
1321	LOGCOPY_32(env,bp, &uinttmp);
1322	bp += sizeof(uinttmp);
1323
1324	if (pagelsn != NULL) {
1325		if (txnp != NULL) {
1326			LOG *lp = env->lg_handle->reginfo.primary;
1327			if (LOG_COMPARE(pagelsn, &lp->lsn) >= 0 && (ret =
1328			    __log_check_page_lsn(env, dbp, pagelsn) != 0))
1329				return (ret);
1330		}
1331		LOGCOPY_FROMLSN(env, bp, pagelsn);
1332	} else
1333		memset(bp, 0, sizeof(*pagelsn));
1334	bp += sizeof(*pagelsn);
1335
1336	uinttmp = (u_int32_t)next_pgno;
1337	LOGCOPY_32(env,bp, &uinttmp);
1338	bp += sizeof(uinttmp);
1339
1340	if (nextlsn != NULL) {
1341		if (txnp != NULL) {
1342			LOG *lp = env->lg_handle->reginfo.primary;
1343			if (LOG_COMPARE(nextlsn, &lp->lsn) >= 0 && (ret =
1344			    __log_check_page_lsn(env, dbp, nextlsn) != 0))
1345				return (ret);
1346		}
1347		LOGCOPY_FROMLSN(env, bp, nextlsn);
1348	} else
1349		memset(bp, 0, sizeof(*nextlsn));
1350	bp += sizeof(*nextlsn);
1351
1352	uinttmp = (u_int32_t)nnext_pgno;
1353	LOGCOPY_32(env,bp, &uinttmp);
1354	bp += sizeof(uinttmp);
1355
1356	if (nnextlsn != NULL) {
1357		if (txnp != NULL) {
1358			LOG *lp = env->lg_handle->reginfo.primary;
1359			if (LOG_COMPARE(nnextlsn, &lp->lsn) >= 0 && (ret =
1360			    __log_check_page_lsn(env, dbp, nnextlsn) != 0))
1361				return (ret);
1362		}
1363		LOGCOPY_FROMLSN(env, bp, nnextlsn);
1364	} else
1365		memset(bp, 0, sizeof(*nnextlsn));
1366	bp += sizeof(*nnextlsn);
1367
1368	if (page == NULL) {
1369		zero = 0;
1370		LOGCOPY_32(env, bp, &zero);
1371		bp += sizeof(u_int32_t);
1372	} else {
1373		LOGCOPY_32(env, bp, &page->size);
1374		bp += sizeof(page->size);
1375		memcpy(bp, page->data, page->size);
1376		if (LOG_SWAPPED(env))
1377			if ((ret = __db_pageswap(dbp,
1378			    (PAGE *)bp, (size_t)page->size, (DBT *)NULL, 0)) != 0)
1379				return (ret);
1380		bp += page->size;
1381	}
1382
1383	DB_ASSERT(env,
1384	    (u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size);
1385
1386	if (is_durable || txnp == NULL) {
1387		if ((ret = __log_put(env, rlsnp,(DBT *)&logrec,
1388		    flags | DB_LOG_NOCOPY)) == 0 && txnp != NULL) {
1389			*lsnp = *rlsnp;
1390			if (rlsnp != ret_lsnp)
1391				 *ret_lsnp = *rlsnp;
1392		}
1393	} else {
1394		ret = 0;
1395#ifdef DIAGNOSTIC
1396		/*
1397		 * Set the debug bit if we are going to log non-durable
1398		 * transactions so they will be ignored by recovery.
1399		 */
1400		memcpy(lr->data, logrec.data, logrec.size);
1401		rectype |= DB_debug_FLAG;
1402		LOGCOPY_32(env, logrec.data, &rectype);
1403
1404		if (!IS_REP_CLIENT(env))
1405			ret = __log_put(env,
1406			    rlsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
1407#endif
1408		STAILQ_INSERT_HEAD(&txnp->logs, lr, links);
1409		F_SET((TXN_DETAIL *)txnp->td, TXN_DTL_INMEMORY);
1410		LSN_NOT_LOGGED(*ret_lsnp);
1411	}
1412
1413#ifdef LOG_DIAGNOSTIC
1414	if (ret != 0)
1415		(void)__ham_copypage_print(env,
1416		    (DBT *)&logrec, ret_lsnp, DB_TXN_PRINT, NULL);
1417#endif
1418
1419#ifdef DIAGNOSTIC
1420	__os_free(env, logrec.data);
1421#else
1422	if (is_durable || txnp == NULL)
1423		__os_free(env, logrec.data);
1424#endif
1425	return (ret);
1426}
1427
1428/*
1429 * PUBLIC: int __ham_metagroup_42_read __P((ENV *, DB **, void *,
1430 * PUBLIC:     void *, __ham_metagroup_42_args **));
1431 */
1432int
1433__ham_metagroup_42_read(env, dbpp, td, recbuf, argpp)
1434	ENV *env;
1435	DB **dbpp;
1436	void *td;
1437	void *recbuf;
1438	__ham_metagroup_42_args **argpp;
1439{
1440	__ham_metagroup_42_args *argp;
1441	u_int32_t uinttmp;
1442	u_int8_t *bp;
1443	int ret;
1444
1445	if ((ret = __os_malloc(env,
1446	    sizeof(__ham_metagroup_42_args) + sizeof(DB_TXN), &argp)) != 0)
1447		return (ret);
1448	bp = recbuf;
1449	argp->txnp = (DB_TXN *)&argp[1];
1450	memset(argp->txnp, 0, sizeof(DB_TXN));
1451
1452	argp->txnp->td = td;
1453	LOGCOPY_32(env, &argp->type, bp);
1454	bp += sizeof(argp->type);
1455
1456	LOGCOPY_32(env, &argp->txnp->txnid, bp);
1457	bp += sizeof(argp->txnp->txnid);
1458
1459	LOGCOPY_TOLSN(env, &argp->prev_lsn, bp);
1460	bp += sizeof(DB_LSN);
1461
1462	LOGCOPY_32(env, &uinttmp, bp);
1463	argp->fileid = (int32_t)uinttmp;
1464	bp += sizeof(uinttmp);
1465	if (dbpp != NULL) {
1466		*dbpp = NULL;
1467		ret = __dbreg_id_to_db(
1468		    env, argp->txnp, dbpp, argp->fileid, 1);
1469	}
1470
1471	LOGCOPY_32(env, &argp->bucket, bp);
1472	bp += sizeof(argp->bucket);
1473
1474	LOGCOPY_32(env, &uinttmp, bp);
1475	argp->mmpgno = (db_pgno_t)uinttmp;
1476	bp += sizeof(uinttmp);
1477
1478	LOGCOPY_TOLSN(env, &argp->mmetalsn, bp);
1479	bp += sizeof(DB_LSN);
1480
1481	LOGCOPY_32(env, &uinttmp, bp);
1482	argp->mpgno = (db_pgno_t)uinttmp;
1483	bp += sizeof(uinttmp);
1484
1485	LOGCOPY_TOLSN(env, &argp->metalsn, bp);
1486	bp += sizeof(DB_LSN);
1487
1488	LOGCOPY_32(env, &uinttmp, bp);
1489	argp->pgno = (db_pgno_t)uinttmp;
1490	bp += sizeof(uinttmp);
1491
1492	LOGCOPY_TOLSN(env, &argp->pagelsn, bp);
1493	bp += sizeof(DB_LSN);
1494
1495	LOGCOPY_32(env, &argp->newalloc, bp);
1496	bp += sizeof(argp->newalloc);
1497
1498	*argpp = argp;
1499	return (ret);
1500}
1501
1502/*
1503 * PUBLIC: int __ham_metagroup_read __P((ENV *, DB **, void *,
1504 * PUBLIC:     void *, __ham_metagroup_args **));
1505 */
1506int
1507__ham_metagroup_read(env, dbpp, td, recbuf, argpp)
1508	ENV *env;
1509	DB **dbpp;
1510	void *td;
1511	void *recbuf;
1512	__ham_metagroup_args **argpp;
1513{
1514	__ham_metagroup_args *argp;
1515	u_int32_t uinttmp;
1516	u_int8_t *bp;
1517	int ret;
1518
1519	if ((ret = __os_malloc(env,
1520	    sizeof(__ham_metagroup_args) + sizeof(DB_TXN), &argp)) != 0)
1521		return (ret);
1522	bp = recbuf;
1523	argp->txnp = (DB_TXN *)&argp[1];
1524	memset(argp->txnp, 0, sizeof(DB_TXN));
1525
1526	argp->txnp->td = td;
1527	LOGCOPY_32(env, &argp->type, bp);
1528	bp += sizeof(argp->type);
1529
1530	LOGCOPY_32(env, &argp->txnp->txnid, bp);
1531	bp += sizeof(argp->txnp->txnid);
1532
1533	LOGCOPY_TOLSN(env, &argp->prev_lsn, bp);
1534	bp += sizeof(DB_LSN);
1535
1536	LOGCOPY_32(env, &uinttmp, bp);
1537	argp->fileid = (int32_t)uinttmp;
1538	bp += sizeof(uinttmp);
1539	if (dbpp != NULL) {
1540		*dbpp = NULL;
1541		ret = __dbreg_id_to_db(
1542		    env, argp->txnp, dbpp, argp->fileid, 1);
1543	}
1544
1545	LOGCOPY_32(env, &argp->bucket, bp);
1546	bp += sizeof(argp->bucket);
1547
1548	LOGCOPY_32(env, &uinttmp, bp);
1549	argp->mmpgno = (db_pgno_t)uinttmp;
1550	bp += sizeof(uinttmp);
1551
1552	LOGCOPY_TOLSN(env, &argp->mmetalsn, bp);
1553	bp += sizeof(DB_LSN);
1554
1555	LOGCOPY_32(env, &uinttmp, bp);
1556	argp->mpgno = (db_pgno_t)uinttmp;
1557	bp += sizeof(uinttmp);
1558
1559	LOGCOPY_TOLSN(env, &argp->metalsn, bp);
1560	bp += sizeof(DB_LSN);
1561
1562	LOGCOPY_32(env, &uinttmp, bp);
1563	argp->pgno = (db_pgno_t)uinttmp;
1564	bp += sizeof(uinttmp);
1565
1566	LOGCOPY_TOLSN(env, &argp->pagelsn, bp);
1567	bp += sizeof(DB_LSN);
1568
1569	LOGCOPY_32(env, &argp->newalloc, bp);
1570	bp += sizeof(argp->newalloc);
1571
1572	LOGCOPY_32(env, &uinttmp, bp);
1573	argp->last_pgno = (db_pgno_t)uinttmp;
1574	bp += sizeof(uinttmp);
1575
1576	*argpp = argp;
1577	return (ret);
1578}
1579
1580/*
1581 * PUBLIC: int __ham_metagroup_log __P((DB *, DB_TXN *, DB_LSN *,
1582 * PUBLIC:     u_int32_t, u_int32_t, db_pgno_t, DB_LSN *, db_pgno_t, DB_LSN *,
1583 * PUBLIC:     db_pgno_t, DB_LSN *, u_int32_t, db_pgno_t));
1584 */
1585int
1586__ham_metagroup_log(dbp, txnp, ret_lsnp, flags, bucket, mmpgno, mmetalsn, mpgno, metalsn,
1587    pgno, pagelsn, newalloc, last_pgno)
1588	DB *dbp;
1589	DB_TXN *txnp;
1590	DB_LSN *ret_lsnp;
1591	u_int32_t flags;
1592	u_int32_t bucket;
1593	db_pgno_t mmpgno;
1594	DB_LSN * mmetalsn;
1595	db_pgno_t mpgno;
1596	DB_LSN * metalsn;
1597	db_pgno_t pgno;
1598	DB_LSN * pagelsn;
1599	u_int32_t newalloc;
1600	db_pgno_t last_pgno;
1601{
1602	DBT logrec;
1603	DB_LSN *lsnp, null_lsn, *rlsnp;
1604	DB_TXNLOGREC *lr;
1605	ENV *env;
1606	u_int32_t uinttmp, rectype, txn_num;
1607	u_int npad;
1608	u_int8_t *bp;
1609	int is_durable, ret;
1610
1611	COMPQUIET(lr, NULL);
1612
1613	env = dbp->env;
1614	rlsnp = ret_lsnp;
1615	rectype = DB___ham_metagroup;
1616	npad = 0;
1617	ret = 0;
1618
1619	if (LF_ISSET(DB_LOG_NOT_DURABLE) ||
1620	    F_ISSET(dbp, DB_AM_NOT_DURABLE)) {
1621		if (txnp == NULL)
1622			return (0);
1623		is_durable = 0;
1624	} else
1625		is_durable = 1;
1626
1627	if (txnp == NULL) {
1628		txn_num = 0;
1629		lsnp = &null_lsn;
1630		null_lsn.file = null_lsn.offset = 0;
1631	} else {
1632		if (TAILQ_FIRST(&txnp->kids) != NULL &&
1633		    (ret = __txn_activekids(env, rectype, txnp)) != 0)
1634			return (ret);
1635		/*
1636		 * We need to assign begin_lsn while holding region mutex.
1637		 * That assignment is done inside the DbEnv->log_put call,
1638		 * so pass in the appropriate memory location to be filled
1639		 * in by the log_put code.
1640		 */
1641		DB_SET_TXN_LSNP(txnp, &rlsnp, &lsnp);
1642		txn_num = txnp->txnid;
1643	}
1644
1645	DB_ASSERT(env, dbp->log_filename != NULL);
1646	if (dbp->log_filename->id == DB_LOGFILEID_INVALID &&
1647	    (ret = __dbreg_lazy_id(dbp)) != 0)
1648		return (ret);
1649
1650	logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
1651	    + sizeof(u_int32_t)
1652	    + sizeof(u_int32_t)
1653	    + sizeof(u_int32_t)
1654	    + sizeof(*mmetalsn)
1655	    + sizeof(u_int32_t)
1656	    + sizeof(*metalsn)
1657	    + sizeof(u_int32_t)
1658	    + sizeof(*pagelsn)
1659	    + sizeof(u_int32_t)
1660	    + sizeof(u_int32_t);
1661	if (CRYPTO_ON(env)) {
1662		npad = env->crypto_handle->adj_size(logrec.size);
1663		logrec.size += npad;
1664	}
1665
1666	if (is_durable || txnp == NULL) {
1667		if ((ret =
1668		    __os_malloc(env, logrec.size, &logrec.data)) != 0)
1669			return (ret);
1670	} else {
1671		if ((ret = __os_malloc(env,
1672		    logrec.size + sizeof(DB_TXNLOGREC), &lr)) != 0)
1673			return (ret);
1674#ifdef DIAGNOSTIC
1675		if ((ret =
1676		    __os_malloc(env, logrec.size, &logrec.data)) != 0) {
1677			__os_free(env, lr);
1678			return (ret);
1679		}
1680#else
1681		logrec.data = lr->data;
1682#endif
1683	}
1684	if (npad > 0)
1685		memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad);
1686
1687	bp = logrec.data;
1688
1689	LOGCOPY_32(env, bp, &rectype);
1690	bp += sizeof(rectype);
1691
1692	LOGCOPY_32(env, bp, &txn_num);
1693	bp += sizeof(txn_num);
1694
1695	LOGCOPY_FROMLSN(env, bp, lsnp);
1696	bp += sizeof(DB_LSN);
1697
1698	uinttmp = (u_int32_t)dbp->log_filename->id;
1699	LOGCOPY_32(env, bp, &uinttmp);
1700	bp += sizeof(uinttmp);
1701
1702	LOGCOPY_32(env, bp, &bucket);
1703	bp += sizeof(bucket);
1704
1705	uinttmp = (u_int32_t)mmpgno;
1706	LOGCOPY_32(env,bp, &uinttmp);
1707	bp += sizeof(uinttmp);
1708
1709	if (mmetalsn != NULL) {
1710		if (txnp != NULL) {
1711			LOG *lp = env->lg_handle->reginfo.primary;
1712			if (LOG_COMPARE(mmetalsn, &lp->lsn) >= 0 && (ret =
1713			    __log_check_page_lsn(env, dbp, mmetalsn) != 0))
1714				return (ret);
1715		}
1716		LOGCOPY_FROMLSN(env, bp, mmetalsn);
1717	} else
1718		memset(bp, 0, sizeof(*mmetalsn));
1719	bp += sizeof(*mmetalsn);
1720
1721	uinttmp = (u_int32_t)mpgno;
1722	LOGCOPY_32(env,bp, &uinttmp);
1723	bp += sizeof(uinttmp);
1724
1725	if (metalsn != NULL) {
1726		if (txnp != NULL) {
1727			LOG *lp = env->lg_handle->reginfo.primary;
1728			if (LOG_COMPARE(metalsn, &lp->lsn) >= 0 && (ret =
1729			    __log_check_page_lsn(env, dbp, metalsn) != 0))
1730				return (ret);
1731		}
1732		LOGCOPY_FROMLSN(env, bp, metalsn);
1733	} else
1734		memset(bp, 0, sizeof(*metalsn));
1735	bp += sizeof(*metalsn);
1736
1737	uinttmp = (u_int32_t)pgno;
1738	LOGCOPY_32(env,bp, &uinttmp);
1739	bp += sizeof(uinttmp);
1740
1741	if (pagelsn != NULL) {
1742		if (txnp != NULL) {
1743			LOG *lp = env->lg_handle->reginfo.primary;
1744			if (LOG_COMPARE(pagelsn, &lp->lsn) >= 0 && (ret =
1745			    __log_check_page_lsn(env, dbp, pagelsn) != 0))
1746				return (ret);
1747		}
1748		LOGCOPY_FROMLSN(env, bp, pagelsn);
1749	} else
1750		memset(bp, 0, sizeof(*pagelsn));
1751	bp += sizeof(*pagelsn);
1752
1753	LOGCOPY_32(env, bp, &newalloc);
1754	bp += sizeof(newalloc);
1755
1756	uinttmp = (u_int32_t)last_pgno;
1757	LOGCOPY_32(env,bp, &uinttmp);
1758	bp += sizeof(uinttmp);
1759
1760	DB_ASSERT(env,
1761	    (u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size);
1762
1763	if (is_durable || txnp == NULL) {
1764		if ((ret = __log_put(env, rlsnp,(DBT *)&logrec,
1765		    flags | DB_LOG_NOCOPY)) == 0 && txnp != NULL) {
1766			*lsnp = *rlsnp;
1767			if (rlsnp != ret_lsnp)
1768				 *ret_lsnp = *rlsnp;
1769		}
1770	} else {
1771		ret = 0;
1772#ifdef DIAGNOSTIC
1773		/*
1774		 * Set the debug bit if we are going to log non-durable
1775		 * transactions so they will be ignored by recovery.
1776		 */
1777		memcpy(lr->data, logrec.data, logrec.size);
1778		rectype |= DB_debug_FLAG;
1779		LOGCOPY_32(env, logrec.data, &rectype);
1780
1781		if (!IS_REP_CLIENT(env))
1782			ret = __log_put(env,
1783			    rlsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
1784#endif
1785		STAILQ_INSERT_HEAD(&txnp->logs, lr, links);
1786		F_SET((TXN_DETAIL *)txnp->td, TXN_DTL_INMEMORY);
1787		LSN_NOT_LOGGED(*ret_lsnp);
1788	}
1789
1790#ifdef LOG_DIAGNOSTIC
1791	if (ret != 0)
1792		(void)__ham_metagroup_print(env,
1793		    (DBT *)&logrec, ret_lsnp, DB_TXN_PRINT, NULL);
1794#endif
1795
1796#ifdef DIAGNOSTIC
1797	__os_free(env, logrec.data);
1798#else
1799	if (is_durable || txnp == NULL)
1800		__os_free(env, logrec.data);
1801#endif
1802	return (ret);
1803}
1804
1805/*
1806 * PUBLIC: int __ham_groupalloc_42_read __P((ENV *, DB **, void *,
1807 * PUBLIC:     void *, __ham_groupalloc_42_args **));
1808 */
1809int
1810__ham_groupalloc_42_read(env, dbpp, td, recbuf, argpp)
1811	ENV *env;
1812	DB **dbpp;
1813	void *td;
1814	void *recbuf;
1815	__ham_groupalloc_42_args **argpp;
1816{
1817	__ham_groupalloc_42_args *argp;
1818	u_int32_t uinttmp;
1819	u_int8_t *bp;
1820	int ret;
1821
1822	if ((ret = __os_malloc(env,
1823	    sizeof(__ham_groupalloc_42_args) + sizeof(DB_TXN), &argp)) != 0)
1824		return (ret);
1825	bp = recbuf;
1826	argp->txnp = (DB_TXN *)&argp[1];
1827	memset(argp->txnp, 0, sizeof(DB_TXN));
1828
1829	argp->txnp->td = td;
1830	LOGCOPY_32(env, &argp->type, bp);
1831	bp += sizeof(argp->type);
1832
1833	LOGCOPY_32(env, &argp->txnp->txnid, bp);
1834	bp += sizeof(argp->txnp->txnid);
1835
1836	LOGCOPY_TOLSN(env, &argp->prev_lsn, bp);
1837	bp += sizeof(DB_LSN);
1838
1839	LOGCOPY_32(env, &uinttmp, bp);
1840	argp->fileid = (int32_t)uinttmp;
1841	bp += sizeof(uinttmp);
1842	if (dbpp != NULL) {
1843		*dbpp = NULL;
1844		ret = __dbreg_id_to_db(
1845		    env, argp->txnp, dbpp, argp->fileid, 1);
1846	}
1847
1848	LOGCOPY_TOLSN(env, &argp->meta_lsn, bp);
1849	bp += sizeof(DB_LSN);
1850
1851	LOGCOPY_32(env, &uinttmp, bp);
1852	argp->start_pgno = (db_pgno_t)uinttmp;
1853	bp += sizeof(uinttmp);
1854
1855	LOGCOPY_32(env, &argp->num, bp);
1856	bp += sizeof(argp->num);
1857
1858	LOGCOPY_32(env, &uinttmp, bp);
1859	argp->free = (db_pgno_t)uinttmp;
1860	bp += sizeof(uinttmp);
1861
1862	*argpp = argp;
1863	return (ret);
1864}
1865
1866/*
1867 * PUBLIC: int __ham_groupalloc_read __P((ENV *, DB **, void *,
1868 * PUBLIC:     void *, __ham_groupalloc_args **));
1869 */
1870int
1871__ham_groupalloc_read(env, dbpp, td, recbuf, argpp)
1872	ENV *env;
1873	DB **dbpp;
1874	void *td;
1875	void *recbuf;
1876	__ham_groupalloc_args **argpp;
1877{
1878	__ham_groupalloc_args *argp;
1879	u_int32_t uinttmp;
1880	u_int8_t *bp;
1881	int ret;
1882
1883	if ((ret = __os_malloc(env,
1884	    sizeof(__ham_groupalloc_args) + sizeof(DB_TXN), &argp)) != 0)
1885		return (ret);
1886	bp = recbuf;
1887	argp->txnp = (DB_TXN *)&argp[1];
1888	memset(argp->txnp, 0, sizeof(DB_TXN));
1889
1890	argp->txnp->td = td;
1891	LOGCOPY_32(env, &argp->type, bp);
1892	bp += sizeof(argp->type);
1893
1894	LOGCOPY_32(env, &argp->txnp->txnid, bp);
1895	bp += sizeof(argp->txnp->txnid);
1896
1897	LOGCOPY_TOLSN(env, &argp->prev_lsn, bp);
1898	bp += sizeof(DB_LSN);
1899
1900	LOGCOPY_32(env, &uinttmp, bp);
1901	argp->fileid = (int32_t)uinttmp;
1902	bp += sizeof(uinttmp);
1903	if (dbpp != NULL) {
1904		*dbpp = NULL;
1905		ret = __dbreg_id_to_db(
1906		    env, argp->txnp, dbpp, argp->fileid, 1);
1907	}
1908
1909	LOGCOPY_TOLSN(env, &argp->meta_lsn, bp);
1910	bp += sizeof(DB_LSN);
1911
1912	LOGCOPY_32(env, &uinttmp, bp);
1913	argp->start_pgno = (db_pgno_t)uinttmp;
1914	bp += sizeof(uinttmp);
1915
1916	LOGCOPY_32(env, &argp->num, bp);
1917	bp += sizeof(argp->num);
1918
1919	LOGCOPY_32(env, &uinttmp, bp);
1920	argp->unused = (db_pgno_t)uinttmp;
1921	bp += sizeof(uinttmp);
1922
1923	LOGCOPY_32(env, &uinttmp, bp);
1924	argp->last_pgno = (db_pgno_t)uinttmp;
1925	bp += sizeof(uinttmp);
1926
1927	*argpp = argp;
1928	return (ret);
1929}
1930
1931/*
1932 * PUBLIC: int __ham_groupalloc_log __P((DB *, DB_TXN *, DB_LSN *,
1933 * PUBLIC:     u_int32_t, DB_LSN *, db_pgno_t, u_int32_t, db_pgno_t,
1934 * PUBLIC:     db_pgno_t));
1935 */
1936int
1937__ham_groupalloc_log(dbp, txnp, ret_lsnp, flags, meta_lsn, start_pgno, num, unused, last_pgno)
1938	DB *dbp;
1939	DB_TXN *txnp;
1940	DB_LSN *ret_lsnp;
1941	u_int32_t flags;
1942	DB_LSN * meta_lsn;
1943	db_pgno_t start_pgno;
1944	u_int32_t num;
1945	db_pgno_t unused;
1946	db_pgno_t last_pgno;
1947{
1948	DBT logrec;
1949	DB_LSN *lsnp, null_lsn, *rlsnp;
1950	DB_TXNLOGREC *lr;
1951	ENV *env;
1952	u_int32_t uinttmp, rectype, txn_num;
1953	u_int npad;
1954	u_int8_t *bp;
1955	int is_durable, ret;
1956
1957	COMPQUIET(lr, NULL);
1958
1959	env = dbp->env;
1960	rlsnp = ret_lsnp;
1961	rectype = DB___ham_groupalloc;
1962	npad = 0;
1963	ret = 0;
1964
1965	if (LF_ISSET(DB_LOG_NOT_DURABLE) ||
1966	    F_ISSET(dbp, DB_AM_NOT_DURABLE)) {
1967		if (txnp == NULL)
1968			return (0);
1969		is_durable = 0;
1970	} else
1971		is_durable = 1;
1972
1973	if (txnp == NULL) {
1974		txn_num = 0;
1975		lsnp = &null_lsn;
1976		null_lsn.file = null_lsn.offset = 0;
1977	} else {
1978		if (TAILQ_FIRST(&txnp->kids) != NULL &&
1979		    (ret = __txn_activekids(env, rectype, txnp)) != 0)
1980			return (ret);
1981		/*
1982		 * We need to assign begin_lsn while holding region mutex.
1983		 * That assignment is done inside the DbEnv->log_put call,
1984		 * so pass in the appropriate memory location to be filled
1985		 * in by the log_put code.
1986		 */
1987		DB_SET_TXN_LSNP(txnp, &rlsnp, &lsnp);
1988		txn_num = txnp->txnid;
1989	}
1990
1991	DB_ASSERT(env, dbp->log_filename != NULL);
1992	if (dbp->log_filename->id == DB_LOGFILEID_INVALID &&
1993	    (ret = __dbreg_lazy_id(dbp)) != 0)
1994		return (ret);
1995
1996	logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
1997	    + sizeof(u_int32_t)
1998	    + sizeof(*meta_lsn)
1999	    + sizeof(u_int32_t)
2000	    + sizeof(u_int32_t)
2001	    + sizeof(u_int32_t)
2002	    + sizeof(u_int32_t);
2003	if (CRYPTO_ON(env)) {
2004		npad = env->crypto_handle->adj_size(logrec.size);
2005		logrec.size += npad;
2006	}
2007
2008	if (is_durable || txnp == NULL) {
2009		if ((ret =
2010		    __os_malloc(env, logrec.size, &logrec.data)) != 0)
2011			return (ret);
2012	} else {
2013		if ((ret = __os_malloc(env,
2014		    logrec.size + sizeof(DB_TXNLOGREC), &lr)) != 0)
2015			return (ret);
2016#ifdef DIAGNOSTIC
2017		if ((ret =
2018		    __os_malloc(env, logrec.size, &logrec.data)) != 0) {
2019			__os_free(env, lr);
2020			return (ret);
2021		}
2022#else
2023		logrec.data = lr->data;
2024#endif
2025	}
2026	if (npad > 0)
2027		memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad);
2028
2029	bp = logrec.data;
2030
2031	LOGCOPY_32(env, bp, &rectype);
2032	bp += sizeof(rectype);
2033
2034	LOGCOPY_32(env, bp, &txn_num);
2035	bp += sizeof(txn_num);
2036
2037	LOGCOPY_FROMLSN(env, bp, lsnp);
2038	bp += sizeof(DB_LSN);
2039
2040	uinttmp = (u_int32_t)dbp->log_filename->id;
2041	LOGCOPY_32(env, bp, &uinttmp);
2042	bp += sizeof(uinttmp);
2043
2044	if (meta_lsn != NULL) {
2045		if (txnp != NULL) {
2046			LOG *lp = env->lg_handle->reginfo.primary;
2047			if (LOG_COMPARE(meta_lsn, &lp->lsn) >= 0 && (ret =
2048			    __log_check_page_lsn(env, dbp, meta_lsn) != 0))
2049				return (ret);
2050		}
2051		LOGCOPY_FROMLSN(env, bp, meta_lsn);
2052	} else
2053		memset(bp, 0, sizeof(*meta_lsn));
2054	bp += sizeof(*meta_lsn);
2055
2056	uinttmp = (u_int32_t)start_pgno;
2057	LOGCOPY_32(env,bp, &uinttmp);
2058	bp += sizeof(uinttmp);
2059
2060	LOGCOPY_32(env, bp, &num);
2061	bp += sizeof(num);
2062
2063	uinttmp = (u_int32_t)unused;
2064	LOGCOPY_32(env,bp, &uinttmp);
2065	bp += sizeof(uinttmp);
2066
2067	uinttmp = (u_int32_t)last_pgno;
2068	LOGCOPY_32(env,bp, &uinttmp);
2069	bp += sizeof(uinttmp);
2070
2071	DB_ASSERT(env,
2072	    (u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size);
2073
2074	if (is_durable || txnp == NULL) {
2075		if ((ret = __log_put(env, rlsnp,(DBT *)&logrec,
2076		    flags | DB_LOG_NOCOPY)) == 0 && txnp != NULL) {
2077			*lsnp = *rlsnp;
2078			if (rlsnp != ret_lsnp)
2079				 *ret_lsnp = *rlsnp;
2080		}
2081	} else {
2082		ret = 0;
2083#ifdef DIAGNOSTIC
2084		/*
2085		 * Set the debug bit if we are going to log non-durable
2086		 * transactions so they will be ignored by recovery.
2087		 */
2088		memcpy(lr->data, logrec.data, logrec.size);
2089		rectype |= DB_debug_FLAG;
2090		LOGCOPY_32(env, logrec.data, &rectype);
2091
2092		if (!IS_REP_CLIENT(env))
2093			ret = __log_put(env,
2094			    rlsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
2095#endif
2096		STAILQ_INSERT_HEAD(&txnp->logs, lr, links);
2097		F_SET((TXN_DETAIL *)txnp->td, TXN_DTL_INMEMORY);
2098		LSN_NOT_LOGGED(*ret_lsnp);
2099	}
2100
2101#ifdef LOG_DIAGNOSTIC
2102	if (ret != 0)
2103		(void)__ham_groupalloc_print(env,
2104		    (DBT *)&logrec, ret_lsnp, DB_TXN_PRINT, NULL);
2105#endif
2106
2107#ifdef DIAGNOSTIC
2108	__os_free(env, logrec.data);
2109#else
2110	if (is_durable || txnp == NULL)
2111		__os_free(env, logrec.data);
2112#endif
2113	return (ret);
2114}
2115
2116/*
2117 * PUBLIC: int __ham_curadj_read __P((ENV *, DB **, void *, void *,
2118 * PUBLIC:     __ham_curadj_args **));
2119 */
2120int
2121__ham_curadj_read(env, dbpp, td, recbuf, argpp)
2122	ENV *env;
2123	DB **dbpp;
2124	void *td;
2125	void *recbuf;
2126	__ham_curadj_args **argpp;
2127{
2128	__ham_curadj_args *argp;
2129	u_int32_t uinttmp;
2130	u_int8_t *bp;
2131	int ret;
2132
2133	if ((ret = __os_malloc(env,
2134	    sizeof(__ham_curadj_args) + sizeof(DB_TXN), &argp)) != 0)
2135		return (ret);
2136	bp = recbuf;
2137	argp->txnp = (DB_TXN *)&argp[1];
2138	memset(argp->txnp, 0, sizeof(DB_TXN));
2139
2140	argp->txnp->td = td;
2141	LOGCOPY_32(env, &argp->type, bp);
2142	bp += sizeof(argp->type);
2143
2144	LOGCOPY_32(env, &argp->txnp->txnid, bp);
2145	bp += sizeof(argp->txnp->txnid);
2146
2147	LOGCOPY_TOLSN(env, &argp->prev_lsn, bp);
2148	bp += sizeof(DB_LSN);
2149
2150	LOGCOPY_32(env, &uinttmp, bp);
2151	argp->fileid = (int32_t)uinttmp;
2152	bp += sizeof(uinttmp);
2153	if (dbpp != NULL) {
2154		*dbpp = NULL;
2155		ret = __dbreg_id_to_db(
2156		    env, argp->txnp, dbpp, argp->fileid, 1);
2157	}
2158
2159	LOGCOPY_32(env, &uinttmp, bp);
2160	argp->pgno = (db_pgno_t)uinttmp;
2161	bp += sizeof(uinttmp);
2162
2163	LOGCOPY_32(env, &argp->indx, bp);
2164	bp += sizeof(argp->indx);
2165
2166	LOGCOPY_32(env, &argp->len, bp);
2167	bp += sizeof(argp->len);
2168
2169	LOGCOPY_32(env, &argp->dup_off, bp);
2170	bp += sizeof(argp->dup_off);
2171
2172	LOGCOPY_32(env, &uinttmp, bp);
2173	argp->add = (int)uinttmp;
2174	bp += sizeof(uinttmp);
2175
2176	LOGCOPY_32(env, &uinttmp, bp);
2177	argp->is_dup = (int)uinttmp;
2178	bp += sizeof(uinttmp);
2179
2180	LOGCOPY_32(env, &argp->order, bp);
2181	bp += sizeof(argp->order);
2182
2183	*argpp = argp;
2184	return (ret);
2185}
2186
2187/*
2188 * PUBLIC: int __ham_curadj_log __P((DB *, DB_TXN *, DB_LSN *,
2189 * PUBLIC:     u_int32_t, db_pgno_t, u_int32_t, u_int32_t, u_int32_t, int, int,
2190 * PUBLIC:     u_int32_t));
2191 */
2192int
2193__ham_curadj_log(dbp, txnp, ret_lsnp, flags, pgno, indx, len, dup_off, add,
2194    is_dup, order)
2195	DB *dbp;
2196	DB_TXN *txnp;
2197	DB_LSN *ret_lsnp;
2198	u_int32_t flags;
2199	db_pgno_t pgno;
2200	u_int32_t indx;
2201	u_int32_t len;
2202	u_int32_t dup_off;
2203	int add;
2204	int is_dup;
2205	u_int32_t order;
2206{
2207	DBT logrec;
2208	DB_LSN *lsnp, null_lsn, *rlsnp;
2209	DB_TXNLOGREC *lr;
2210	ENV *env;
2211	u_int32_t uinttmp, rectype, txn_num;
2212	u_int npad;
2213	u_int8_t *bp;
2214	int is_durable, ret;
2215
2216	COMPQUIET(lr, NULL);
2217
2218	env = dbp->env;
2219	rlsnp = ret_lsnp;
2220	rectype = DB___ham_curadj;
2221	npad = 0;
2222	ret = 0;
2223
2224	if (LF_ISSET(DB_LOG_NOT_DURABLE) ||
2225	    F_ISSET(dbp, DB_AM_NOT_DURABLE)) {
2226		if (txnp == NULL)
2227			return (0);
2228		is_durable = 0;
2229	} else
2230		is_durable = 1;
2231
2232	if (txnp == NULL) {
2233		txn_num = 0;
2234		lsnp = &null_lsn;
2235		null_lsn.file = null_lsn.offset = 0;
2236	} else {
2237		if (TAILQ_FIRST(&txnp->kids) != NULL &&
2238		    (ret = __txn_activekids(env, rectype, txnp)) != 0)
2239			return (ret);
2240		/*
2241		 * We need to assign begin_lsn while holding region mutex.
2242		 * That assignment is done inside the DbEnv->log_put call,
2243		 * so pass in the appropriate memory location to be filled
2244		 * in by the log_put code.
2245		 */
2246		DB_SET_TXN_LSNP(txnp, &rlsnp, &lsnp);
2247		txn_num = txnp->txnid;
2248	}
2249
2250	DB_ASSERT(env, dbp->log_filename != NULL);
2251	if (dbp->log_filename->id == DB_LOGFILEID_INVALID &&
2252	    (ret = __dbreg_lazy_id(dbp)) != 0)
2253		return (ret);
2254
2255	logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
2256	    + sizeof(u_int32_t)
2257	    + sizeof(u_int32_t)
2258	    + sizeof(u_int32_t)
2259	    + sizeof(u_int32_t)
2260	    + sizeof(u_int32_t)
2261	    + sizeof(u_int32_t)
2262	    + sizeof(u_int32_t)
2263	    + sizeof(u_int32_t);
2264	if (CRYPTO_ON(env)) {
2265		npad = env->crypto_handle->adj_size(logrec.size);
2266		logrec.size += npad;
2267	}
2268
2269	if (is_durable || txnp == NULL) {
2270		if ((ret =
2271		    __os_malloc(env, logrec.size, &logrec.data)) != 0)
2272			return (ret);
2273	} else {
2274		if ((ret = __os_malloc(env,
2275		    logrec.size + sizeof(DB_TXNLOGREC), &lr)) != 0)
2276			return (ret);
2277#ifdef DIAGNOSTIC
2278		if ((ret =
2279		    __os_malloc(env, logrec.size, &logrec.data)) != 0) {
2280			__os_free(env, lr);
2281			return (ret);
2282		}
2283#else
2284		logrec.data = lr->data;
2285#endif
2286	}
2287	if (npad > 0)
2288		memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad);
2289
2290	bp = logrec.data;
2291
2292	LOGCOPY_32(env, bp, &rectype);
2293	bp += sizeof(rectype);
2294
2295	LOGCOPY_32(env, bp, &txn_num);
2296	bp += sizeof(txn_num);
2297
2298	LOGCOPY_FROMLSN(env, bp, lsnp);
2299	bp += sizeof(DB_LSN);
2300
2301	uinttmp = (u_int32_t)dbp->log_filename->id;
2302	LOGCOPY_32(env, bp, &uinttmp);
2303	bp += sizeof(uinttmp);
2304
2305	uinttmp = (u_int32_t)pgno;
2306	LOGCOPY_32(env,bp, &uinttmp);
2307	bp += sizeof(uinttmp);
2308
2309	LOGCOPY_32(env, bp, &indx);
2310	bp += sizeof(indx);
2311
2312	LOGCOPY_32(env, bp, &len);
2313	bp += sizeof(len);
2314
2315	LOGCOPY_32(env, bp, &dup_off);
2316	bp += sizeof(dup_off);
2317
2318	uinttmp = (u_int32_t)add;
2319	LOGCOPY_32(env,bp, &uinttmp);
2320	bp += sizeof(uinttmp);
2321
2322	uinttmp = (u_int32_t)is_dup;
2323	LOGCOPY_32(env,bp, &uinttmp);
2324	bp += sizeof(uinttmp);
2325
2326	LOGCOPY_32(env, bp, &order);
2327	bp += sizeof(order);
2328
2329	DB_ASSERT(env,
2330	    (u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size);
2331
2332	if (is_durable || txnp == NULL) {
2333		if ((ret = __log_put(env, rlsnp,(DBT *)&logrec,
2334		    flags | DB_LOG_NOCOPY)) == 0 && txnp != NULL) {
2335			*lsnp = *rlsnp;
2336			if (rlsnp != ret_lsnp)
2337				 *ret_lsnp = *rlsnp;
2338		}
2339	} else {
2340		ret = 0;
2341#ifdef DIAGNOSTIC
2342		/*
2343		 * Set the debug bit if we are going to log non-durable
2344		 * transactions so they will be ignored by recovery.
2345		 */
2346		memcpy(lr->data, logrec.data, logrec.size);
2347		rectype |= DB_debug_FLAG;
2348		LOGCOPY_32(env, logrec.data, &rectype);
2349
2350		if (!IS_REP_CLIENT(env))
2351			ret = __log_put(env,
2352			    rlsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
2353#endif
2354		STAILQ_INSERT_HEAD(&txnp->logs, lr, links);
2355		F_SET((TXN_DETAIL *)txnp->td, TXN_DTL_INMEMORY);
2356		LSN_NOT_LOGGED(*ret_lsnp);
2357	}
2358
2359#ifdef LOG_DIAGNOSTIC
2360	if (ret != 0)
2361		(void)__ham_curadj_print(env,
2362		    (DBT *)&logrec, ret_lsnp, DB_TXN_PRINT, NULL);
2363#endif
2364
2365#ifdef DIAGNOSTIC
2366	__os_free(env, logrec.data);
2367#else
2368	if (is_durable || txnp == NULL)
2369		__os_free(env, logrec.data);
2370#endif
2371	return (ret);
2372}
2373
2374/*
2375 * PUBLIC: int __ham_chgpg_read __P((ENV *, DB **, void *, void *,
2376 * PUBLIC:     __ham_chgpg_args **));
2377 */
2378int
2379__ham_chgpg_read(env, dbpp, td, recbuf, argpp)
2380	ENV *env;
2381	DB **dbpp;
2382	void *td;
2383	void *recbuf;
2384	__ham_chgpg_args **argpp;
2385{
2386	__ham_chgpg_args *argp;
2387	u_int32_t uinttmp;
2388	u_int8_t *bp;
2389	int ret;
2390
2391	if ((ret = __os_malloc(env,
2392	    sizeof(__ham_chgpg_args) + sizeof(DB_TXN), &argp)) != 0)
2393		return (ret);
2394	bp = recbuf;
2395	argp->txnp = (DB_TXN *)&argp[1];
2396	memset(argp->txnp, 0, sizeof(DB_TXN));
2397
2398	argp->txnp->td = td;
2399	LOGCOPY_32(env, &argp->type, bp);
2400	bp += sizeof(argp->type);
2401
2402	LOGCOPY_32(env, &argp->txnp->txnid, bp);
2403	bp += sizeof(argp->txnp->txnid);
2404
2405	LOGCOPY_TOLSN(env, &argp->prev_lsn, bp);
2406	bp += sizeof(DB_LSN);
2407
2408	LOGCOPY_32(env, &uinttmp, bp);
2409	argp->fileid = (int32_t)uinttmp;
2410	bp += sizeof(uinttmp);
2411	if (dbpp != NULL) {
2412		*dbpp = NULL;
2413		ret = __dbreg_id_to_db(
2414		    env, argp->txnp, dbpp, argp->fileid, 1);
2415	}
2416
2417	LOGCOPY_32(env, &uinttmp, bp);
2418	argp->mode = (db_ham_mode)uinttmp;
2419	bp += sizeof(uinttmp);
2420
2421	LOGCOPY_32(env, &uinttmp, bp);
2422	argp->old_pgno = (db_pgno_t)uinttmp;
2423	bp += sizeof(uinttmp);
2424
2425	LOGCOPY_32(env, &uinttmp, bp);
2426	argp->new_pgno = (db_pgno_t)uinttmp;
2427	bp += sizeof(uinttmp);
2428
2429	LOGCOPY_32(env, &argp->old_indx, bp);
2430	bp += sizeof(argp->old_indx);
2431
2432	LOGCOPY_32(env, &argp->new_indx, bp);
2433	bp += sizeof(argp->new_indx);
2434
2435	*argpp = argp;
2436	return (ret);
2437}
2438
2439/*
2440 * PUBLIC: int __ham_chgpg_log __P((DB *, DB_TXN *, DB_LSN *,
2441 * PUBLIC:     u_int32_t, db_ham_mode, db_pgno_t, db_pgno_t, u_int32_t,
2442 * PUBLIC:     u_int32_t));
2443 */
2444int
2445__ham_chgpg_log(dbp, txnp, ret_lsnp, flags, mode, old_pgno, new_pgno, old_indx, new_indx)
2446	DB *dbp;
2447	DB_TXN *txnp;
2448	DB_LSN *ret_lsnp;
2449	u_int32_t flags;
2450	db_ham_mode mode;
2451	db_pgno_t old_pgno;
2452	db_pgno_t new_pgno;
2453	u_int32_t old_indx;
2454	u_int32_t new_indx;
2455{
2456	DBT logrec;
2457	DB_LSN *lsnp, null_lsn, *rlsnp;
2458	DB_TXNLOGREC *lr;
2459	ENV *env;
2460	u_int32_t uinttmp, rectype, txn_num;
2461	u_int npad;
2462	u_int8_t *bp;
2463	int is_durable, ret;
2464
2465	COMPQUIET(lr, NULL);
2466
2467	env = dbp->env;
2468	rlsnp = ret_lsnp;
2469	rectype = DB___ham_chgpg;
2470	npad = 0;
2471	ret = 0;
2472
2473	if (LF_ISSET(DB_LOG_NOT_DURABLE) ||
2474	    F_ISSET(dbp, DB_AM_NOT_DURABLE)) {
2475		if (txnp == NULL)
2476			return (0);
2477		is_durable = 0;
2478	} else
2479		is_durable = 1;
2480
2481	if (txnp == NULL) {
2482		txn_num = 0;
2483		lsnp = &null_lsn;
2484		null_lsn.file = null_lsn.offset = 0;
2485	} else {
2486		if (TAILQ_FIRST(&txnp->kids) != NULL &&
2487		    (ret = __txn_activekids(env, rectype, txnp)) != 0)
2488			return (ret);
2489		/*
2490		 * We need to assign begin_lsn while holding region mutex.
2491		 * That assignment is done inside the DbEnv->log_put call,
2492		 * so pass in the appropriate memory location to be filled
2493		 * in by the log_put code.
2494		 */
2495		DB_SET_TXN_LSNP(txnp, &rlsnp, &lsnp);
2496		txn_num = txnp->txnid;
2497	}
2498
2499	DB_ASSERT(env, dbp->log_filename != NULL);
2500	if (dbp->log_filename->id == DB_LOGFILEID_INVALID &&
2501	    (ret = __dbreg_lazy_id(dbp)) != 0)
2502		return (ret);
2503
2504	logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
2505	    + sizeof(u_int32_t)
2506	    + sizeof(u_int32_t)
2507	    + sizeof(u_int32_t)
2508	    + sizeof(u_int32_t)
2509	    + sizeof(u_int32_t)
2510	    + sizeof(u_int32_t);
2511	if (CRYPTO_ON(env)) {
2512		npad = env->crypto_handle->adj_size(logrec.size);
2513		logrec.size += npad;
2514	}
2515
2516	if (is_durable || txnp == NULL) {
2517		if ((ret =
2518		    __os_malloc(env, logrec.size, &logrec.data)) != 0)
2519			return (ret);
2520	} else {
2521		if ((ret = __os_malloc(env,
2522		    logrec.size + sizeof(DB_TXNLOGREC), &lr)) != 0)
2523			return (ret);
2524#ifdef DIAGNOSTIC
2525		if ((ret =
2526		    __os_malloc(env, logrec.size, &logrec.data)) != 0) {
2527			__os_free(env, lr);
2528			return (ret);
2529		}
2530#else
2531		logrec.data = lr->data;
2532#endif
2533	}
2534	if (npad > 0)
2535		memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad);
2536
2537	bp = logrec.data;
2538
2539	LOGCOPY_32(env, bp, &rectype);
2540	bp += sizeof(rectype);
2541
2542	LOGCOPY_32(env, bp, &txn_num);
2543	bp += sizeof(txn_num);
2544
2545	LOGCOPY_FROMLSN(env, bp, lsnp);
2546	bp += sizeof(DB_LSN);
2547
2548	uinttmp = (u_int32_t)dbp->log_filename->id;
2549	LOGCOPY_32(env, bp, &uinttmp);
2550	bp += sizeof(uinttmp);
2551
2552	uinttmp = (u_int32_t)mode;
2553	LOGCOPY_32(env,bp, &uinttmp);
2554	bp += sizeof(uinttmp);
2555
2556	uinttmp = (u_int32_t)old_pgno;
2557	LOGCOPY_32(env,bp, &uinttmp);
2558	bp += sizeof(uinttmp);
2559
2560	uinttmp = (u_int32_t)new_pgno;
2561	LOGCOPY_32(env,bp, &uinttmp);
2562	bp += sizeof(uinttmp);
2563
2564	LOGCOPY_32(env, bp, &old_indx);
2565	bp += sizeof(old_indx);
2566
2567	LOGCOPY_32(env, bp, &new_indx);
2568	bp += sizeof(new_indx);
2569
2570	DB_ASSERT(env,
2571	    (u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size);
2572
2573	if (is_durable || txnp == NULL) {
2574		if ((ret = __log_put(env, rlsnp,(DBT *)&logrec,
2575		    flags | DB_LOG_NOCOPY)) == 0 && txnp != NULL) {
2576			*lsnp = *rlsnp;
2577			if (rlsnp != ret_lsnp)
2578				 *ret_lsnp = *rlsnp;
2579		}
2580	} else {
2581		ret = 0;
2582#ifdef DIAGNOSTIC
2583		/*
2584		 * Set the debug bit if we are going to log non-durable
2585		 * transactions so they will be ignored by recovery.
2586		 */
2587		memcpy(lr->data, logrec.data, logrec.size);
2588		rectype |= DB_debug_FLAG;
2589		LOGCOPY_32(env, logrec.data, &rectype);
2590
2591		if (!IS_REP_CLIENT(env))
2592			ret = __log_put(env,
2593			    rlsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
2594#endif
2595		STAILQ_INSERT_HEAD(&txnp->logs, lr, links);
2596		F_SET((TXN_DETAIL *)txnp->td, TXN_DTL_INMEMORY);
2597		LSN_NOT_LOGGED(*ret_lsnp);
2598	}
2599
2600#ifdef LOG_DIAGNOSTIC
2601	if (ret != 0)
2602		(void)__ham_chgpg_print(env,
2603		    (DBT *)&logrec, ret_lsnp, DB_TXN_PRINT, NULL);
2604#endif
2605
2606#ifdef DIAGNOSTIC
2607	__os_free(env, logrec.data);
2608#else
2609	if (is_durable || txnp == NULL)
2610		__os_free(env, logrec.data);
2611#endif
2612	return (ret);
2613}
2614
2615/*
2616 * PUBLIC: int __ham_init_recover __P((ENV *, DB_DISTAB *));
2617 */
2618int
2619__ham_init_recover(env, dtabp)
2620	ENV *env;
2621	DB_DISTAB *dtabp;
2622{
2623	int ret;
2624
2625	if ((ret = __db_add_recovery_int(env, dtabp,
2626	    __ham_insdel_recover, DB___ham_insdel)) != 0)
2627		return (ret);
2628	if ((ret = __db_add_recovery_int(env, dtabp,
2629	    __ham_newpage_recover, DB___ham_newpage)) != 0)
2630		return (ret);
2631	if ((ret = __db_add_recovery_int(env, dtabp,
2632	    __ham_splitdata_recover, DB___ham_splitdata)) != 0)
2633		return (ret);
2634	if ((ret = __db_add_recovery_int(env, dtabp,
2635	    __ham_replace_recover, DB___ham_replace)) != 0)
2636		return (ret);
2637	if ((ret = __db_add_recovery_int(env, dtabp,
2638	    __ham_copypage_recover, DB___ham_copypage)) != 0)
2639		return (ret);
2640	if ((ret = __db_add_recovery_int(env, dtabp,
2641	    __ham_metagroup_recover, DB___ham_metagroup)) != 0)
2642		return (ret);
2643	if ((ret = __db_add_recovery_int(env, dtabp,
2644	    __ham_groupalloc_recover, DB___ham_groupalloc)) != 0)
2645		return (ret);
2646	if ((ret = __db_add_recovery_int(env, dtabp,
2647	    __ham_curadj_recover, DB___ham_curadj)) != 0)
2648		return (ret);
2649	if ((ret = __db_add_recovery_int(env, dtabp,
2650	    __ham_chgpg_recover, DB___ham_chgpg)) != 0)
2651		return (ret);
2652	return (0);
2653}
2654