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