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/lock.h"
10#include "dbinc/log.h"
11#include "dbinc/txn.h"
12
13/*
14 * PUBLIC: int __txn_regop_42_read __P((ENV *, void *,
15 * PUBLIC:     __txn_regop_42_args **));
16 */
17int
18__txn_regop_42_read(env, recbuf, argpp)
19	ENV *env;
20	void *recbuf;
21	__txn_regop_42_args **argpp;
22{
23	__txn_regop_42_args *argp;
24	u_int32_t uinttmp;
25	u_int8_t *bp;
26	int ret;
27
28	if ((ret = __os_malloc(env,
29	    sizeof(__txn_regop_42_args) + sizeof(DB_TXN), &argp)) != 0)
30		return (ret);
31	bp = recbuf;
32	argp->txnp = (DB_TXN *)&argp[1];
33	memset(argp->txnp, 0, sizeof(DB_TXN));
34
35	LOGCOPY_32(env, &argp->type, bp);
36	bp += sizeof(argp->type);
37
38	LOGCOPY_32(env, &argp->txnp->txnid, bp);
39	bp += sizeof(argp->txnp->txnid);
40
41	LOGCOPY_TOLSN(env, &argp->prev_lsn, bp);
42	bp += sizeof(DB_LSN);
43
44	LOGCOPY_32(env, &argp->opcode, bp);
45	bp += sizeof(argp->opcode);
46
47	LOGCOPY_32(env, &uinttmp, bp);
48	argp->timestamp = (int32_t)uinttmp;
49	bp += sizeof(uinttmp);
50
51	memset(&argp->locks, 0, sizeof(argp->locks));
52	LOGCOPY_32(env,&argp->locks.size, bp);
53	bp += sizeof(u_int32_t);
54	argp->locks.data = bp;
55	bp += argp->locks.size;
56
57	*argpp = argp;
58	return (ret);
59}
60
61/*
62 * PUBLIC: int __txn_regop_read __P((ENV *, void *, __txn_regop_args **));
63 */
64int
65__txn_regop_read(env, recbuf, argpp)
66	ENV *env;
67	void *recbuf;
68	__txn_regop_args **argpp;
69{
70	__txn_regop_args *argp;
71	u_int32_t uinttmp;
72	u_int8_t *bp;
73	int ret;
74
75	if ((ret = __os_malloc(env,
76	    sizeof(__txn_regop_args) + sizeof(DB_TXN), &argp)) != 0)
77		return (ret);
78	bp = recbuf;
79	argp->txnp = (DB_TXN *)&argp[1];
80	memset(argp->txnp, 0, sizeof(DB_TXN));
81
82	LOGCOPY_32(env, &argp->type, bp);
83	bp += sizeof(argp->type);
84
85	LOGCOPY_32(env, &argp->txnp->txnid, bp);
86	bp += sizeof(argp->txnp->txnid);
87
88	LOGCOPY_TOLSN(env, &argp->prev_lsn, bp);
89	bp += sizeof(DB_LSN);
90
91	LOGCOPY_32(env, &argp->opcode, bp);
92	bp += sizeof(argp->opcode);
93
94	LOGCOPY_32(env, &uinttmp, bp);
95	argp->timestamp = (int32_t)uinttmp;
96	bp += sizeof(uinttmp);
97
98	LOGCOPY_32(env, &argp->envid, bp);
99	bp += sizeof(argp->envid);
100
101	memset(&argp->locks, 0, sizeof(argp->locks));
102	LOGCOPY_32(env,&argp->locks.size, bp);
103	bp += sizeof(u_int32_t);
104	argp->locks.data = bp;
105	bp += argp->locks.size;
106
107	*argpp = argp;
108	return (ret);
109}
110
111/*
112 * PUBLIC: int __txn_regop_log __P((ENV *, DB_TXN *, DB_LSN *,
113 * PUBLIC:     u_int32_t, u_int32_t, int32_t, u_int32_t, const DBT *));
114 */
115int
116__txn_regop_log(env, txnp, ret_lsnp, flags,
117    opcode, timestamp, envid, locks)
118	ENV *env;
119	DB_TXN *txnp;
120	DB_LSN *ret_lsnp;
121	u_int32_t flags;
122	u_int32_t opcode;
123	int32_t timestamp;
124	u_int32_t envid;
125	const DBT *locks;
126{
127	DBT logrec;
128	DB_LSN *lsnp, null_lsn, *rlsnp;
129	DB_TXNLOGREC *lr;
130	u_int32_t zero, uinttmp, rectype, txn_num;
131	u_int npad;
132	u_int8_t *bp;
133	int is_durable, ret;
134
135	COMPQUIET(lr, NULL);
136
137	rlsnp = ret_lsnp;
138	rectype = DB___txn_regop;
139	npad = 0;
140	ret = 0;
141
142	if (LF_ISSET(DB_LOG_NOT_DURABLE)) {
143		if (txnp == NULL)
144			return (0);
145		if (txnp == NULL)
146			return (0);
147		is_durable = 0;
148	} else
149		is_durable = 1;
150
151	if (txnp == NULL) {
152		txn_num = 0;
153		lsnp = &null_lsn;
154		null_lsn.file = null_lsn.offset = 0;
155	} else {
156		if (TAILQ_FIRST(&txnp->kids) != NULL &&
157		    (ret = __txn_activekids(env, rectype, txnp)) != 0)
158			return (ret);
159		/*
160		 * We need to assign begin_lsn while holding region mutex.
161		 * That assignment is done inside the DbEnv->log_put call,
162		 * so pass in the appropriate memory location to be filled
163		 * in by the log_put code.
164		 */
165		DB_SET_TXN_LSNP(txnp, &rlsnp, &lsnp);
166		txn_num = txnp->txnid;
167	}
168
169	logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
170	    + sizeof(u_int32_t)
171	    + sizeof(u_int32_t)
172	    + sizeof(u_int32_t)
173	    + sizeof(u_int32_t) + (locks == NULL ? 0 : locks->size);
174	if (CRYPTO_ON(env)) {
175		npad = env->crypto_handle->adj_size(logrec.size);
176		logrec.size += npad;
177	}
178
179	if (is_durable || txnp == NULL) {
180		if ((ret =
181		    __os_malloc(env, logrec.size, &logrec.data)) != 0)
182			return (ret);
183	} else {
184		if ((ret = __os_malloc(env,
185		    logrec.size + sizeof(DB_TXNLOGREC), &lr)) != 0)
186			return (ret);
187#ifdef DIAGNOSTIC
188		if ((ret =
189		    __os_malloc(env, logrec.size, &logrec.data)) != 0) {
190			__os_free(env, lr);
191			return (ret);
192		}
193#else
194		logrec.data = lr->data;
195#endif
196	}
197	if (npad > 0)
198		memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad);
199
200	bp = logrec.data;
201
202	LOGCOPY_32(env, bp, &rectype);
203	bp += sizeof(rectype);
204
205	LOGCOPY_32(env, bp, &txn_num);
206	bp += sizeof(txn_num);
207
208	LOGCOPY_FROMLSN(env, bp, lsnp);
209	bp += sizeof(DB_LSN);
210
211	LOGCOPY_32(env, bp, &opcode);
212	bp += sizeof(opcode);
213
214	uinttmp = (u_int32_t)timestamp;
215	LOGCOPY_32(env,bp, &uinttmp);
216	bp += sizeof(uinttmp);
217
218	LOGCOPY_32(env, bp, &envid);
219	bp += sizeof(envid);
220
221	if (locks == NULL) {
222		zero = 0;
223		LOGCOPY_32(env, bp, &zero);
224		bp += sizeof(u_int32_t);
225	} else {
226		LOGCOPY_32(env, bp, &locks->size);
227		bp += sizeof(locks->size);
228		memcpy(bp, locks->data, locks->size);
229		bp += locks->size;
230	}
231
232	DB_ASSERT(env,
233	    (u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size);
234
235	if (is_durable || txnp == NULL) {
236		if ((ret = __log_put(env, rlsnp,(DBT *)&logrec,
237		    flags | DB_LOG_NOCOPY)) == 0 && txnp != NULL) {
238			*lsnp = *rlsnp;
239			if (rlsnp != ret_lsnp)
240				 *ret_lsnp = *rlsnp;
241		}
242	} else {
243		ret = 0;
244#ifdef DIAGNOSTIC
245		/*
246		 * Set the debug bit if we are going to log non-durable
247		 * transactions so they will be ignored by recovery.
248		 */
249		memcpy(lr->data, logrec.data, logrec.size);
250		rectype |= DB_debug_FLAG;
251		LOGCOPY_32(env, logrec.data, &rectype);
252
253		if (!IS_REP_CLIENT(env))
254			ret = __log_put(env,
255			    rlsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
256#endif
257		STAILQ_INSERT_HEAD(&txnp->logs, lr, links);
258		F_SET((TXN_DETAIL *)txnp->td, TXN_DTL_INMEMORY);
259		LSN_NOT_LOGGED(*ret_lsnp);
260	}
261
262#ifdef LOG_DIAGNOSTIC
263	if (ret != 0)
264		(void)__txn_regop_print(env,
265		    (DBT *)&logrec, ret_lsnp, DB_TXN_PRINT, NULL);
266#endif
267
268#ifdef DIAGNOSTIC
269	__os_free(env, logrec.data);
270#else
271	if (is_durable || txnp == NULL)
272		__os_free(env, logrec.data);
273#endif
274	return (ret);
275}
276
277/*
278 * PUBLIC: int __txn_ckp_42_read __P((ENV *, void *, __txn_ckp_42_args **));
279 */
280int
281__txn_ckp_42_read(env, recbuf, argpp)
282	ENV *env;
283	void *recbuf;
284	__txn_ckp_42_args **argpp;
285{
286	__txn_ckp_42_args *argp;
287	u_int32_t uinttmp;
288	u_int8_t *bp;
289	int ret;
290
291	if ((ret = __os_malloc(env,
292	    sizeof(__txn_ckp_42_args) + sizeof(DB_TXN), &argp)) != 0)
293		return (ret);
294	bp = recbuf;
295	argp->txnp = (DB_TXN *)&argp[1];
296	memset(argp->txnp, 0, sizeof(DB_TXN));
297
298	LOGCOPY_32(env, &argp->type, bp);
299	bp += sizeof(argp->type);
300
301	LOGCOPY_32(env, &argp->txnp->txnid, bp);
302	bp += sizeof(argp->txnp->txnid);
303
304	LOGCOPY_TOLSN(env, &argp->prev_lsn, bp);
305	bp += sizeof(DB_LSN);
306
307	LOGCOPY_TOLSN(env, &argp->ckp_lsn, bp);
308	bp += sizeof(DB_LSN);
309
310	LOGCOPY_TOLSN(env, &argp->last_ckp, bp);
311	bp += sizeof(DB_LSN);
312
313	LOGCOPY_32(env, &uinttmp, bp);
314	argp->timestamp = (int32_t)uinttmp;
315	bp += sizeof(uinttmp);
316
317	LOGCOPY_32(env, &argp->rep_gen, bp);
318	bp += sizeof(argp->rep_gen);
319
320	*argpp = argp;
321	return (ret);
322}
323
324/*
325 * PUBLIC: int __txn_ckp_read __P((ENV *, void *, __txn_ckp_args **));
326 */
327int
328__txn_ckp_read(env, recbuf, argpp)
329	ENV *env;
330	void *recbuf;
331	__txn_ckp_args **argpp;
332{
333	__txn_ckp_args *argp;
334	u_int32_t uinttmp;
335	u_int8_t *bp;
336	int ret;
337
338	if ((ret = __os_malloc(env,
339	    sizeof(__txn_ckp_args) + sizeof(DB_TXN), &argp)) != 0)
340		return (ret);
341	bp = recbuf;
342	argp->txnp = (DB_TXN *)&argp[1];
343	memset(argp->txnp, 0, sizeof(DB_TXN));
344
345	LOGCOPY_32(env, &argp->type, bp);
346	bp += sizeof(argp->type);
347
348	LOGCOPY_32(env, &argp->txnp->txnid, bp);
349	bp += sizeof(argp->txnp->txnid);
350
351	LOGCOPY_TOLSN(env, &argp->prev_lsn, bp);
352	bp += sizeof(DB_LSN);
353
354	LOGCOPY_TOLSN(env, &argp->ckp_lsn, bp);
355	bp += sizeof(DB_LSN);
356
357	LOGCOPY_TOLSN(env, &argp->last_ckp, bp);
358	bp += sizeof(DB_LSN);
359
360	LOGCOPY_32(env, &uinttmp, bp);
361	argp->timestamp = (int32_t)uinttmp;
362	bp += sizeof(uinttmp);
363
364	LOGCOPY_32(env, &argp->envid, bp);
365	bp += sizeof(argp->envid);
366
367	LOGCOPY_32(env, &argp->spare, bp);
368	bp += sizeof(argp->spare);
369
370	*argpp = argp;
371	return (ret);
372}
373
374/*
375 * PUBLIC: int __txn_ckp_log __P((ENV *, DB_TXN *, DB_LSN *,
376 * PUBLIC:     u_int32_t, DB_LSN *, DB_LSN *, int32_t, u_int32_t, u_int32_t));
377 */
378int
379__txn_ckp_log(env, txnp, ret_lsnp, flags,
380    ckp_lsn, last_ckp, timestamp, envid, spare)
381	ENV *env;
382	DB_TXN *txnp;
383	DB_LSN *ret_lsnp;
384	u_int32_t flags;
385	DB_LSN * ckp_lsn;
386	DB_LSN * last_ckp;
387	int32_t timestamp;
388	u_int32_t envid;
389	u_int32_t spare;
390{
391	DBT logrec;
392	DB_LSN *lsnp, null_lsn, *rlsnp;
393	DB_TXNLOGREC *lr;
394	u_int32_t uinttmp, rectype, txn_num;
395	u_int npad;
396	u_int8_t *bp;
397	int is_durable, ret;
398
399	COMPQUIET(lr, NULL);
400
401	rlsnp = ret_lsnp;
402	rectype = DB___txn_ckp;
403	npad = 0;
404	ret = 0;
405
406	if (LF_ISSET(DB_LOG_NOT_DURABLE)) {
407		if (txnp == NULL)
408			return (0);
409		if (txnp == NULL)
410			return (0);
411		is_durable = 0;
412	} else
413		is_durable = 1;
414
415	if (txnp == NULL) {
416		txn_num = 0;
417		lsnp = &null_lsn;
418		null_lsn.file = null_lsn.offset = 0;
419	} else {
420		if (TAILQ_FIRST(&txnp->kids) != NULL &&
421		    (ret = __txn_activekids(env, rectype, txnp)) != 0)
422			return (ret);
423		/*
424		 * We need to assign begin_lsn while holding region mutex.
425		 * That assignment is done inside the DbEnv->log_put call,
426		 * so pass in the appropriate memory location to be filled
427		 * in by the log_put code.
428		 */
429		DB_SET_TXN_LSNP(txnp, &rlsnp, &lsnp);
430		txn_num = txnp->txnid;
431	}
432
433	logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
434	    + sizeof(*ckp_lsn)
435	    + sizeof(*last_ckp)
436	    + sizeof(u_int32_t)
437	    + sizeof(u_int32_t)
438	    + sizeof(u_int32_t);
439	if (CRYPTO_ON(env)) {
440		npad = env->crypto_handle->adj_size(logrec.size);
441		logrec.size += npad;
442	}
443
444	if (is_durable || txnp == NULL) {
445		if ((ret =
446		    __os_malloc(env, logrec.size, &logrec.data)) != 0)
447			return (ret);
448	} else {
449		if ((ret = __os_malloc(env,
450		    logrec.size + sizeof(DB_TXNLOGREC), &lr)) != 0)
451			return (ret);
452#ifdef DIAGNOSTIC
453		if ((ret =
454		    __os_malloc(env, logrec.size, &logrec.data)) != 0) {
455			__os_free(env, lr);
456			return (ret);
457		}
458#else
459		logrec.data = lr->data;
460#endif
461	}
462	if (npad > 0)
463		memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad);
464
465	bp = logrec.data;
466
467	LOGCOPY_32(env, bp, &rectype);
468	bp += sizeof(rectype);
469
470	LOGCOPY_32(env, bp, &txn_num);
471	bp += sizeof(txn_num);
472
473	LOGCOPY_FROMLSN(env, bp, lsnp);
474	bp += sizeof(DB_LSN);
475
476	if (ckp_lsn != NULL)
477		LOGCOPY_FROMLSN(env, bp, ckp_lsn);
478	else
479		memset(bp, 0, sizeof(*ckp_lsn));
480	bp += sizeof(*ckp_lsn);
481
482	if (last_ckp != NULL)
483		LOGCOPY_FROMLSN(env, bp, last_ckp);
484	else
485		memset(bp, 0, sizeof(*last_ckp));
486	bp += sizeof(*last_ckp);
487
488	uinttmp = (u_int32_t)timestamp;
489	LOGCOPY_32(env,bp, &uinttmp);
490	bp += sizeof(uinttmp);
491
492	LOGCOPY_32(env, bp, &envid);
493	bp += sizeof(envid);
494
495	LOGCOPY_32(env, bp, &spare);
496	bp += sizeof(spare);
497
498	DB_ASSERT(env,
499	    (u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size);
500
501	if (is_durable || txnp == NULL) {
502		if ((ret = __log_put(env, rlsnp,(DBT *)&logrec,
503		    flags | DB_LOG_NOCOPY)) == 0 && txnp != NULL) {
504			*lsnp = *rlsnp;
505			if (rlsnp != ret_lsnp)
506				 *ret_lsnp = *rlsnp;
507		}
508	} else {
509		ret = 0;
510#ifdef DIAGNOSTIC
511		/*
512		 * Set the debug bit if we are going to log non-durable
513		 * transactions so they will be ignored by recovery.
514		 */
515		memcpy(lr->data, logrec.data, logrec.size);
516		rectype |= DB_debug_FLAG;
517		LOGCOPY_32(env, logrec.data, &rectype);
518
519		if (!IS_REP_CLIENT(env))
520			ret = __log_put(env,
521			    rlsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
522#endif
523		STAILQ_INSERT_HEAD(&txnp->logs, lr, links);
524		F_SET((TXN_DETAIL *)txnp->td, TXN_DTL_INMEMORY);
525		LSN_NOT_LOGGED(*ret_lsnp);
526	}
527
528#ifdef LOG_DIAGNOSTIC
529	if (ret != 0)
530		(void)__txn_ckp_print(env,
531		    (DBT *)&logrec, ret_lsnp, DB_TXN_PRINT, NULL);
532#endif
533
534#ifdef DIAGNOSTIC
535	__os_free(env, logrec.data);
536#else
537	if (is_durable || txnp == NULL)
538		__os_free(env, logrec.data);
539#endif
540	return (ret);
541}
542
543/*
544 * PUBLIC: int __txn_child_read __P((ENV *, void *, __txn_child_args **));
545 */
546int
547__txn_child_read(env, recbuf, argpp)
548	ENV *env;
549	void *recbuf;
550	__txn_child_args **argpp;
551{
552	__txn_child_args *argp;
553	u_int8_t *bp;
554	int ret;
555
556	if ((ret = __os_malloc(env,
557	    sizeof(__txn_child_args) + sizeof(DB_TXN), &argp)) != 0)
558		return (ret);
559	bp = recbuf;
560	argp->txnp = (DB_TXN *)&argp[1];
561	memset(argp->txnp, 0, sizeof(DB_TXN));
562
563	LOGCOPY_32(env, &argp->type, bp);
564	bp += sizeof(argp->type);
565
566	LOGCOPY_32(env, &argp->txnp->txnid, bp);
567	bp += sizeof(argp->txnp->txnid);
568
569	LOGCOPY_TOLSN(env, &argp->prev_lsn, bp);
570	bp += sizeof(DB_LSN);
571
572	LOGCOPY_32(env, &argp->child, bp);
573	bp += sizeof(argp->child);
574
575	LOGCOPY_TOLSN(env, &argp->c_lsn, bp);
576	bp += sizeof(DB_LSN);
577
578	*argpp = argp;
579	return (ret);
580}
581
582/*
583 * PUBLIC: int __txn_child_log __P((ENV *, DB_TXN *, DB_LSN *,
584 * PUBLIC:     u_int32_t, u_int32_t, DB_LSN *));
585 */
586int
587__txn_child_log(env, txnp, ret_lsnp, flags,
588    child, c_lsn)
589	ENV *env;
590	DB_TXN *txnp;
591	DB_LSN *ret_lsnp;
592	u_int32_t flags;
593	u_int32_t child;
594	DB_LSN * c_lsn;
595{
596	DBT logrec;
597	DB_LSN *lsnp, null_lsn, *rlsnp;
598	DB_TXNLOGREC *lr;
599	u_int32_t rectype, txn_num;
600	u_int npad;
601	u_int8_t *bp;
602	int is_durable, ret;
603
604	COMPQUIET(lr, NULL);
605
606	rlsnp = ret_lsnp;
607	rectype = DB___txn_child;
608	npad = 0;
609	ret = 0;
610
611	if (LF_ISSET(DB_LOG_NOT_DURABLE)) {
612		if (txnp == NULL)
613			return (0);
614		if (txnp == NULL)
615			return (0);
616		is_durable = 0;
617	} else
618		is_durable = 1;
619
620	if (txnp == NULL) {
621		txn_num = 0;
622		lsnp = &null_lsn;
623		null_lsn.file = null_lsn.offset = 0;
624	} else {
625		if (TAILQ_FIRST(&txnp->kids) != NULL &&
626		    (ret = __txn_activekids(env, rectype, txnp)) != 0)
627			return (ret);
628		/*
629		 * We need to assign begin_lsn while holding region mutex.
630		 * That assignment is done inside the DbEnv->log_put call,
631		 * so pass in the appropriate memory location to be filled
632		 * in by the log_put code.
633		 */
634		DB_SET_TXN_LSNP(txnp, &rlsnp, &lsnp);
635		txn_num = txnp->txnid;
636	}
637
638	logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
639	    + sizeof(u_int32_t)
640	    + sizeof(*c_lsn);
641	if (CRYPTO_ON(env)) {
642		npad = env->crypto_handle->adj_size(logrec.size);
643		logrec.size += npad;
644	}
645
646	if (is_durable || txnp == NULL) {
647		if ((ret =
648		    __os_malloc(env, logrec.size, &logrec.data)) != 0)
649			return (ret);
650	} else {
651		if ((ret = __os_malloc(env,
652		    logrec.size + sizeof(DB_TXNLOGREC), &lr)) != 0)
653			return (ret);
654#ifdef DIAGNOSTIC
655		if ((ret =
656		    __os_malloc(env, logrec.size, &logrec.data)) != 0) {
657			__os_free(env, lr);
658			return (ret);
659		}
660#else
661		logrec.data = lr->data;
662#endif
663	}
664	if (npad > 0)
665		memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad);
666
667	bp = logrec.data;
668
669	LOGCOPY_32(env, bp, &rectype);
670	bp += sizeof(rectype);
671
672	LOGCOPY_32(env, bp, &txn_num);
673	bp += sizeof(txn_num);
674
675	LOGCOPY_FROMLSN(env, bp, lsnp);
676	bp += sizeof(DB_LSN);
677
678	LOGCOPY_32(env, bp, &child);
679	bp += sizeof(child);
680
681	if (c_lsn != NULL)
682		LOGCOPY_FROMLSN(env, bp, c_lsn);
683	else
684		memset(bp, 0, sizeof(*c_lsn));
685	bp += sizeof(*c_lsn);
686
687	DB_ASSERT(env,
688	    (u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size);
689
690	if (is_durable || txnp == NULL) {
691		if ((ret = __log_put(env, rlsnp,(DBT *)&logrec,
692		    flags | DB_LOG_NOCOPY)) == 0 && txnp != NULL) {
693			*lsnp = *rlsnp;
694			if (rlsnp != ret_lsnp)
695				 *ret_lsnp = *rlsnp;
696		}
697	} else {
698		ret = 0;
699#ifdef DIAGNOSTIC
700		/*
701		 * Set the debug bit if we are going to log non-durable
702		 * transactions so they will be ignored by recovery.
703		 */
704		memcpy(lr->data, logrec.data, logrec.size);
705		rectype |= DB_debug_FLAG;
706		LOGCOPY_32(env, logrec.data, &rectype);
707
708		if (!IS_REP_CLIENT(env))
709			ret = __log_put(env,
710			    rlsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
711#endif
712		STAILQ_INSERT_HEAD(&txnp->logs, lr, links);
713		F_SET((TXN_DETAIL *)txnp->td, TXN_DTL_INMEMORY);
714		LSN_NOT_LOGGED(*ret_lsnp);
715	}
716
717#ifdef LOG_DIAGNOSTIC
718	if (ret != 0)
719		(void)__txn_child_print(env,
720		    (DBT *)&logrec, ret_lsnp, DB_TXN_PRINT, NULL);
721#endif
722
723#ifdef DIAGNOSTIC
724	__os_free(env, logrec.data);
725#else
726	if (is_durable || txnp == NULL)
727		__os_free(env, logrec.data);
728#endif
729	return (ret);
730}
731
732/*
733 * PUBLIC: int __txn_xa_regop_read __P((ENV *, void *,
734 * PUBLIC:     __txn_xa_regop_args **));
735 */
736int
737__txn_xa_regop_read(env, recbuf, argpp)
738	ENV *env;
739	void *recbuf;
740	__txn_xa_regop_args **argpp;
741{
742	__txn_xa_regop_args *argp;
743	u_int32_t uinttmp;
744	u_int8_t *bp;
745	int ret;
746
747	if ((ret = __os_malloc(env,
748	    sizeof(__txn_xa_regop_args) + sizeof(DB_TXN), &argp)) != 0)
749		return (ret);
750	bp = recbuf;
751	argp->txnp = (DB_TXN *)&argp[1];
752	memset(argp->txnp, 0, sizeof(DB_TXN));
753
754	LOGCOPY_32(env, &argp->type, bp);
755	bp += sizeof(argp->type);
756
757	LOGCOPY_32(env, &argp->txnp->txnid, bp);
758	bp += sizeof(argp->txnp->txnid);
759
760	LOGCOPY_TOLSN(env, &argp->prev_lsn, bp);
761	bp += sizeof(DB_LSN);
762
763	LOGCOPY_32(env, &argp->opcode, bp);
764	bp += sizeof(argp->opcode);
765
766	memset(&argp->xid, 0, sizeof(argp->xid));
767	LOGCOPY_32(env,&argp->xid.size, bp);
768	bp += sizeof(u_int32_t);
769	argp->xid.data = bp;
770	bp += argp->xid.size;
771
772	LOGCOPY_32(env, &uinttmp, bp);
773	argp->formatID = (int32_t)uinttmp;
774	bp += sizeof(uinttmp);
775
776	LOGCOPY_32(env, &argp->gtrid, bp);
777	bp += sizeof(argp->gtrid);
778
779	LOGCOPY_32(env, &argp->bqual, bp);
780	bp += sizeof(argp->bqual);
781
782	LOGCOPY_TOLSN(env, &argp->begin_lsn, bp);
783	bp += sizeof(DB_LSN);
784
785	memset(&argp->locks, 0, sizeof(argp->locks));
786	LOGCOPY_32(env,&argp->locks.size, bp);
787	bp += sizeof(u_int32_t);
788	argp->locks.data = bp;
789	bp += argp->locks.size;
790
791	*argpp = argp;
792	return (ret);
793}
794
795/*
796 * PUBLIC: int __txn_xa_regop_log __P((ENV *, DB_TXN *, DB_LSN *,
797 * PUBLIC:     u_int32_t, u_int32_t, const DBT *, int32_t, u_int32_t, u_int32_t,
798 * PUBLIC:     DB_LSN *, const DBT *));
799 */
800int
801__txn_xa_regop_log(env, txnp, ret_lsnp, flags,
802    opcode, xid, formatID, gtrid, bqual, begin_lsn,
803    locks)
804	ENV *env;
805	DB_TXN *txnp;
806	DB_LSN *ret_lsnp;
807	u_int32_t flags;
808	u_int32_t opcode;
809	const DBT *xid;
810	int32_t formatID;
811	u_int32_t gtrid;
812	u_int32_t bqual;
813	DB_LSN * begin_lsn;
814	const DBT *locks;
815{
816	DBT logrec;
817	DB_LSN *lsnp, null_lsn, *rlsnp;
818	DB_TXNLOGREC *lr;
819	u_int32_t zero, uinttmp, rectype, txn_num;
820	u_int npad;
821	u_int8_t *bp;
822	int is_durable, ret;
823
824	COMPQUIET(lr, NULL);
825
826	rlsnp = ret_lsnp;
827	rectype = DB___txn_xa_regop;
828	npad = 0;
829	ret = 0;
830
831	if (LF_ISSET(DB_LOG_NOT_DURABLE)) {
832		if (txnp == NULL)
833			return (0);
834		if (txnp == NULL)
835			return (0);
836		is_durable = 0;
837	} else
838		is_durable = 1;
839
840	if (txnp == NULL) {
841		txn_num = 0;
842		lsnp = &null_lsn;
843		null_lsn.file = null_lsn.offset = 0;
844	} else {
845		if (TAILQ_FIRST(&txnp->kids) != NULL &&
846		    (ret = __txn_activekids(env, rectype, txnp)) != 0)
847			return (ret);
848		/*
849		 * We need to assign begin_lsn while holding region mutex.
850		 * That assignment is done inside the DbEnv->log_put call,
851		 * so pass in the appropriate memory location to be filled
852		 * in by the log_put code.
853		 */
854		DB_SET_TXN_LSNP(txnp, &rlsnp, &lsnp);
855		txn_num = txnp->txnid;
856	}
857
858	logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
859	    + sizeof(u_int32_t)
860	    + sizeof(u_int32_t) + (xid == NULL ? 0 : xid->size)
861	    + sizeof(u_int32_t)
862	    + sizeof(u_int32_t)
863	    + sizeof(u_int32_t)
864	    + sizeof(*begin_lsn)
865	    + sizeof(u_int32_t) + (locks == NULL ? 0 : locks->size);
866	if (CRYPTO_ON(env)) {
867		npad = env->crypto_handle->adj_size(logrec.size);
868		logrec.size += npad;
869	}
870
871	if (is_durable || txnp == NULL) {
872		if ((ret =
873		    __os_malloc(env, logrec.size, &logrec.data)) != 0)
874			return (ret);
875	} else {
876		if ((ret = __os_malloc(env,
877		    logrec.size + sizeof(DB_TXNLOGREC), &lr)) != 0)
878			return (ret);
879#ifdef DIAGNOSTIC
880		if ((ret =
881		    __os_malloc(env, logrec.size, &logrec.data)) != 0) {
882			__os_free(env, lr);
883			return (ret);
884		}
885#else
886		logrec.data = lr->data;
887#endif
888	}
889	if (npad > 0)
890		memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad);
891
892	bp = logrec.data;
893
894	LOGCOPY_32(env, bp, &rectype);
895	bp += sizeof(rectype);
896
897	LOGCOPY_32(env, bp, &txn_num);
898	bp += sizeof(txn_num);
899
900	LOGCOPY_FROMLSN(env, bp, lsnp);
901	bp += sizeof(DB_LSN);
902
903	LOGCOPY_32(env, bp, &opcode);
904	bp += sizeof(opcode);
905
906	if (xid == NULL) {
907		zero = 0;
908		LOGCOPY_32(env, bp, &zero);
909		bp += sizeof(u_int32_t);
910	} else {
911		LOGCOPY_32(env, bp, &xid->size);
912		bp += sizeof(xid->size);
913		memcpy(bp, xid->data, xid->size);
914		bp += xid->size;
915	}
916
917	uinttmp = (u_int32_t)formatID;
918	LOGCOPY_32(env,bp, &uinttmp);
919	bp += sizeof(uinttmp);
920
921	LOGCOPY_32(env, bp, &gtrid);
922	bp += sizeof(gtrid);
923
924	LOGCOPY_32(env, bp, &bqual);
925	bp += sizeof(bqual);
926
927	if (begin_lsn != NULL)
928		LOGCOPY_FROMLSN(env, bp, begin_lsn);
929	else
930		memset(bp, 0, sizeof(*begin_lsn));
931	bp += sizeof(*begin_lsn);
932
933	if (locks == NULL) {
934		zero = 0;
935		LOGCOPY_32(env, bp, &zero);
936		bp += sizeof(u_int32_t);
937	} else {
938		LOGCOPY_32(env, bp, &locks->size);
939		bp += sizeof(locks->size);
940		memcpy(bp, locks->data, locks->size);
941		bp += locks->size;
942	}
943
944	DB_ASSERT(env,
945	    (u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size);
946
947	if (is_durable || txnp == NULL) {
948		if ((ret = __log_put(env, rlsnp,(DBT *)&logrec,
949		    flags | DB_LOG_NOCOPY)) == 0 && txnp != NULL) {
950			*lsnp = *rlsnp;
951			if (rlsnp != ret_lsnp)
952				 *ret_lsnp = *rlsnp;
953		}
954	} else {
955		ret = 0;
956#ifdef DIAGNOSTIC
957		/*
958		 * Set the debug bit if we are going to log non-durable
959		 * transactions so they will be ignored by recovery.
960		 */
961		memcpy(lr->data, logrec.data, logrec.size);
962		rectype |= DB_debug_FLAG;
963		LOGCOPY_32(env, logrec.data, &rectype);
964
965		if (!IS_REP_CLIENT(env))
966			ret = __log_put(env,
967			    rlsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
968#endif
969		STAILQ_INSERT_HEAD(&txnp->logs, lr, links);
970		F_SET((TXN_DETAIL *)txnp->td, TXN_DTL_INMEMORY);
971		LSN_NOT_LOGGED(*ret_lsnp);
972	}
973
974#ifdef LOG_DIAGNOSTIC
975	if (ret != 0)
976		(void)__txn_xa_regop_print(env,
977		    (DBT *)&logrec, ret_lsnp, DB_TXN_PRINT, NULL);
978#endif
979
980#ifdef DIAGNOSTIC
981	__os_free(env, logrec.data);
982#else
983	if (is_durable || txnp == NULL)
984		__os_free(env, logrec.data);
985#endif
986	return (ret);
987}
988
989/*
990 * PUBLIC: int __txn_recycle_read __P((ENV *, void *, __txn_recycle_args **));
991 */
992int
993__txn_recycle_read(env, recbuf, argpp)
994	ENV *env;
995	void *recbuf;
996	__txn_recycle_args **argpp;
997{
998	__txn_recycle_args *argp;
999	u_int8_t *bp;
1000	int ret;
1001
1002	if ((ret = __os_malloc(env,
1003	    sizeof(__txn_recycle_args) + sizeof(DB_TXN), &argp)) != 0)
1004		return (ret);
1005	bp = recbuf;
1006	argp->txnp = (DB_TXN *)&argp[1];
1007	memset(argp->txnp, 0, sizeof(DB_TXN));
1008
1009	LOGCOPY_32(env, &argp->type, bp);
1010	bp += sizeof(argp->type);
1011
1012	LOGCOPY_32(env, &argp->txnp->txnid, bp);
1013	bp += sizeof(argp->txnp->txnid);
1014
1015	LOGCOPY_TOLSN(env, &argp->prev_lsn, bp);
1016	bp += sizeof(DB_LSN);
1017
1018	LOGCOPY_32(env, &argp->min, bp);
1019	bp += sizeof(argp->min);
1020
1021	LOGCOPY_32(env, &argp->max, bp);
1022	bp += sizeof(argp->max);
1023
1024	*argpp = argp;
1025	return (ret);
1026}
1027
1028/*
1029 * PUBLIC: int __txn_recycle_log __P((ENV *, DB_TXN *, DB_LSN *,
1030 * PUBLIC:     u_int32_t, u_int32_t, u_int32_t));
1031 */
1032int
1033__txn_recycle_log(env, txnp, ret_lsnp, flags,
1034    min, max)
1035	ENV *env;
1036	DB_TXN *txnp;
1037	DB_LSN *ret_lsnp;
1038	u_int32_t flags;
1039	u_int32_t min;
1040	u_int32_t max;
1041{
1042	DBT logrec;
1043	DB_LSN *lsnp, null_lsn, *rlsnp;
1044	DB_TXNLOGREC *lr;
1045	u_int32_t rectype, txn_num;
1046	u_int npad;
1047	u_int8_t *bp;
1048	int is_durable, ret;
1049
1050	COMPQUIET(lr, NULL);
1051
1052	rlsnp = ret_lsnp;
1053	rectype = DB___txn_recycle;
1054	npad = 0;
1055	ret = 0;
1056
1057	if (LF_ISSET(DB_LOG_NOT_DURABLE)) {
1058		if (txnp == NULL)
1059			return (0);
1060		if (txnp == NULL)
1061			return (0);
1062		is_durable = 0;
1063	} else
1064		is_durable = 1;
1065
1066	if (txnp == NULL) {
1067		txn_num = 0;
1068		lsnp = &null_lsn;
1069		null_lsn.file = null_lsn.offset = 0;
1070	} else {
1071		if (TAILQ_FIRST(&txnp->kids) != NULL &&
1072		    (ret = __txn_activekids(env, rectype, txnp)) != 0)
1073			return (ret);
1074		/*
1075		 * We need to assign begin_lsn while holding region mutex.
1076		 * That assignment is done inside the DbEnv->log_put call,
1077		 * so pass in the appropriate memory location to be filled
1078		 * in by the log_put code.
1079		 */
1080		DB_SET_TXN_LSNP(txnp, &rlsnp, &lsnp);
1081		txn_num = txnp->txnid;
1082	}
1083
1084	logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN)
1085	    + sizeof(u_int32_t)
1086	    + sizeof(u_int32_t);
1087	if (CRYPTO_ON(env)) {
1088		npad = env->crypto_handle->adj_size(logrec.size);
1089		logrec.size += npad;
1090	}
1091
1092	if (is_durable || txnp == NULL) {
1093		if ((ret =
1094		    __os_malloc(env, logrec.size, &logrec.data)) != 0)
1095			return (ret);
1096	} else {
1097		if ((ret = __os_malloc(env,
1098		    logrec.size + sizeof(DB_TXNLOGREC), &lr)) != 0)
1099			return (ret);
1100#ifdef DIAGNOSTIC
1101		if ((ret =
1102		    __os_malloc(env, logrec.size, &logrec.data)) != 0) {
1103			__os_free(env, lr);
1104			return (ret);
1105		}
1106#else
1107		logrec.data = lr->data;
1108#endif
1109	}
1110	if (npad > 0)
1111		memset((u_int8_t *)logrec.data + logrec.size - npad, 0, npad);
1112
1113	bp = logrec.data;
1114
1115	LOGCOPY_32(env, bp, &rectype);
1116	bp += sizeof(rectype);
1117
1118	LOGCOPY_32(env, bp, &txn_num);
1119	bp += sizeof(txn_num);
1120
1121	LOGCOPY_FROMLSN(env, bp, lsnp);
1122	bp += sizeof(DB_LSN);
1123
1124	LOGCOPY_32(env, bp, &min);
1125	bp += sizeof(min);
1126
1127	LOGCOPY_32(env, bp, &max);
1128	bp += sizeof(max);
1129
1130	DB_ASSERT(env,
1131	    (u_int32_t)(bp - (u_int8_t *)logrec.data) <= logrec.size);
1132
1133	if (is_durable || txnp == NULL) {
1134		if ((ret = __log_put(env, rlsnp,(DBT *)&logrec,
1135		    flags | DB_LOG_NOCOPY)) == 0 && txnp != NULL) {
1136			*lsnp = *rlsnp;
1137			if (rlsnp != ret_lsnp)
1138				 *ret_lsnp = *rlsnp;
1139		}
1140	} else {
1141		ret = 0;
1142#ifdef DIAGNOSTIC
1143		/*
1144		 * Set the debug bit if we are going to log non-durable
1145		 * transactions so they will be ignored by recovery.
1146		 */
1147		memcpy(lr->data, logrec.data, logrec.size);
1148		rectype |= DB_debug_FLAG;
1149		LOGCOPY_32(env, logrec.data, &rectype);
1150
1151		if (!IS_REP_CLIENT(env))
1152			ret = __log_put(env,
1153			    rlsnp, (DBT *)&logrec, flags | DB_LOG_NOCOPY);
1154#endif
1155		STAILQ_INSERT_HEAD(&txnp->logs, lr, links);
1156		F_SET((TXN_DETAIL *)txnp->td, TXN_DTL_INMEMORY);
1157		LSN_NOT_LOGGED(*ret_lsnp);
1158	}
1159
1160#ifdef LOG_DIAGNOSTIC
1161	if (ret != 0)
1162		(void)__txn_recycle_print(env,
1163		    (DBT *)&logrec, ret_lsnp, DB_TXN_PRINT, NULL);
1164#endif
1165
1166#ifdef DIAGNOSTIC
1167	__os_free(env, logrec.data);
1168#else
1169	if (is_durable || txnp == NULL)
1170		__os_free(env, logrec.data);
1171#endif
1172	return (ret);
1173}
1174
1175/*
1176 * PUBLIC: int __txn_init_recover __P((ENV *, DB_DISTAB *));
1177 */
1178int
1179__txn_init_recover(env, dtabp)
1180	ENV *env;
1181	DB_DISTAB *dtabp;
1182{
1183	int ret;
1184
1185	if ((ret = __db_add_recovery_int(env, dtabp,
1186	    __txn_regop_recover, DB___txn_regop)) != 0)
1187		return (ret);
1188	if ((ret = __db_add_recovery_int(env, dtabp,
1189	    __txn_ckp_recover, DB___txn_ckp)) != 0)
1190		return (ret);
1191	if ((ret = __db_add_recovery_int(env, dtabp,
1192	    __txn_child_recover, DB___txn_child)) != 0)
1193		return (ret);
1194	if ((ret = __db_add_recovery_int(env, dtabp,
1195	    __txn_xa_regop_recover, DB___txn_xa_regop)) != 0)
1196		return (ret);
1197	if ((ret = __db_add_recovery_int(env, dtabp,
1198	    __txn_recycle_recover, DB___txn_recycle)) != 0)
1199		return (ret);
1200	return (0);
1201}
1202