xref: /netbsd-src/external/bsd/nvi/dist/common/vi_rec.c (revision dbd550ed1a6686d6600f748306f9cc03d8cd4c94)
1 #include "db_config.h"
2 
3 #ifndef NO_SYSTEM_INCLUDES
4 #include <sys/types.h>
5 
6 #include <string.h>
7 #endif
8 
9 #include "common.h"
10 
11 #include "db_int.h"
12 #include "db_page.h"
13 #include <log.h>
14 #include "hash.h"
15 #include "btree.h"
16 
17 #define LOG_CURSOR_HIT	    -1000
18 
19 /*
20  * PUBLIC: #ifdef USE_DB4_LOGGING
21  */
22 /*
23  * __vi_marker_recover --
24  *	Recovery function for marker.
25  *
26  * PUBLIC: int __vi_marker_recover
27  * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
28  */
29 int
__vi_marker_recover(dbenv,dbtp,lsnp,op,info)30 __vi_marker_recover(dbenv, dbtp, lsnp, op, info)
31 	DB_ENV *dbenv;
32 	DBT *dbtp;
33 	DB_LSN *lsnp;
34 	db_recops op;
35 	void *info;
36 {
37 	__vi_marker_args *argp;
38 	int ret;
39 
40 	REC_PRINT(__vi_marker_print);
41 	REC_NOOP_INTRO(__vi_marker_read);
42 
43 	*lsnp = argp->prev_lsn;
44 	ret = 0;
45 
46     	REC_NOOP_CLOSE;
47 }
48 
49 /*
50  * __vi_cursor_recover --
51  *	Recovery function for cursor.
52  *
53  * PUBLIC: int __vi_cursor_recover
54  * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
55  */
56 int
__vi_cursor_recover(dbenv,dbtp,lsnp,op,info)57 __vi_cursor_recover(dbenv, dbtp, lsnp, op, info)
58 	DB_ENV *dbenv;
59 	DBT *dbtp;
60 	DB_LSN *lsnp;
61 	db_recops op;
62 	void *info;
63 {
64 	__vi_cursor_args *argp;
65 	int ret;
66 	SCR *sp;
67 
68 	REC_PRINT(__vi_cursor_print);
69 	REC_NOOP_INTRO(__vi_cursor_read);
70 
71 	sp = (SCR *)dbenv->app_private;
72 
73 	*lsnp = argp->prev_lsn;
74 	if (sp->state.undo == UNDO_SETLINE) {
75 		/* Why the check for ep->l_cur ? (copied from log.c)
76 		 */
77 		ret = (argp->lno != sp->lno ||
78 		    (argp->opcode == LOG_CURSOR_INIT && sp->ep->l_cur == 1))
79 			  ? LOG_CURSOR_HIT : 0;
80 	}
81 	else {
82 		ret = argp->opcode ==
83 			(DB_UNDO(op) ? LOG_CURSOR_INIT : LOG_CURSOR_END)
84 			  ? LOG_CURSOR_HIT : 0;
85 		if (ret) {
86 			sp->state.pos.lno = argp->lno;
87 			sp->state.pos.cno = argp->cno;
88 		}
89 	}
90 
91     	REC_NOOP_CLOSE;
92 }
93 
94 /*
95  * __vi_mark_recover --
96  *	Recovery function for mark.
97  *
98  * PUBLIC: int __vi_mark_recover
99  * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
100  */
101 int
__vi_mark_recover(dbenv,dbtp,lsnp,op,info)102 __vi_mark_recover(dbenv, dbtp, lsnp, op, info)
103 	DB_ENV *dbenv;
104 	DBT *dbtp;
105 	DB_LSN *lsnp;
106 	db_recops op;
107 	void *info;
108 {
109 	__vi_mark_args *argp;
110 	int ret;
111 	MARK m;
112 	SCR *sp;
113 
114 	REC_PRINT(__vi_mark_print);
115 	REC_NOOP_INTRO(__vi_mark_read);
116 
117 	sp = (SCR *)dbenv->app_private;
118 	*lsnp = argp->prev_lsn;
119 	m.lno = argp->lmp.lno;
120 	m.cno = argp->lmp.cno;
121 	ret = mark_set(sp, argp->lmp.name, &m, 0);
122 
123     	REC_NOOP_CLOSE;
124 }
125 
126 /*
127  * __vi_change_recover --
128  *	Recovery function for change.
129  *
130  * PUBLIC: int __vi_change_recover
131  * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
132  */
133 int
__vi_change_recover(dbenv,dbtp,lsnp,op,info)134 __vi_change_recover(dbenv, dbtp, lsnp, op, info)
135 	DB_ENV *dbenv;
136 	DBT *dbtp;
137 	DB_LSN *lsnp;
138 	db_recops op;
139 	void *info;
140 {
141 	__vi_change_args *argp;
142 	int ret;
143 	SCR *sp;
144 
145 	REC_PRINT(__vi_change_print);
146 	REC_NOOP_INTRO(__vi_change_read);
147 
148 	ret = 0;
149 
150 	sp = (SCR *)dbenv->app_private;
151 	if (DB_UNDO(op) != (argp->opcode & 1))
152 	    switch (argp->opcode) {
153 	    case LOG_LINE_RESET_B:
154 	    case LOG_LINE_RESET_F:
155 		    ret = line_insdel(sp, LINE_RESET, argp->lno);
156 		    update_cache(sp, LINE_RESET, argp->lno);
157 		    ret = scr_update(sp, argp->lno, LINE_RESET, 1) || ret;
158 		    break;
159 	    case LOG_LINE_APPEND_B:
160 	    case LOG_LINE_DELETE_F:
161 		    ret = line_insdel(sp, LINE_DELETE, argp->lno);
162 		    update_cache(sp, LINE_DELETE, argp->lno);
163 		    ret = scr_update(sp, argp->lno, LINE_DELETE, 1) || ret;
164 		    break;
165 	    case LOG_LINE_DELETE_B:
166 	    case LOG_LINE_APPEND_F:
167 		    ret = line_insdel(sp, LINE_INSERT, argp->lno);
168 		    update_cache(sp, LINE_INSERT, argp->lno);
169 		    ret = scr_update(sp, argp->lno, LINE_INSERT, 1) || ret;
170 		    break;
171 	    }
172 
173 	*lsnp = argp->prev_lsn;
174 
175     	REC_NOOP_CLOSE;
176 }
177 
178 /*
179  *
180  * PUBLIC: int __vi_log_truncate __P((EXF *ep));
181  */
182 int
__vi_log_truncate(EXF * ep)183 __vi_log_truncate(EXF *ep)
184 {
185 	DB_LSN ckplsn;
186 
187 	ZERO_LSN(ckplsn);
188 	return __log_vtruncate(ep->env, &ep->lsn_cur, &ckplsn);
189 	/*return __log_vtruncate(ep->env, &ep->lsn_cur, &ep->lsn_first);*/
190 }
191 
192 /*
193  *
194  * PUBLIC: int __vi_log_dispatch __P((DB_ENV *dbenv, DBT *data, DB_LSN *lsn, db_recops ops));
195  */
196 int
__vi_log_dispatch(DB_ENV * dbenv,DBT * data,DB_LSN * lsn,db_recops ops)197 __vi_log_dispatch(DB_ENV *dbenv, DBT *data, DB_LSN *lsn, db_recops ops)
198 {
199 	u_int32_t rectype;
200 	char	s[100];
201 
202 	memcpy(&rectype, data->data, sizeof(rectype));
203 	snprintf(s,100,"%d\n", rectype);
204 	return dbenv->dtab[rectype](dbenv, data, lsn, ops, NULL);
205 }
206 
207 static int
vi_log_get(SCR * sp,DB_LOGC * logc,DBT * data,u_int32_t which)208 vi_log_get(SCR *sp, DB_LOGC *logc, DBT *data, u_int32_t which)
209 {
210 	size_t nlen;
211 	EXF *ep;
212 
213 	ep = sp->ep;
214 
215 	nlen = 1024;
216 retry:
217 	BINC_GOTO(sp, sp->wp->l_lp, sp->wp->l_len, nlen);
218 	memset(data, 0, sizeof(*data));
219 	data->data = sp->wp->l_lp;
220 	data->ulen = sp->wp->l_len;
221 	data->flags = DB_DBT_USERMEM;
222 	switch ((sp->db_error = logc->get(logc, &ep->lsn_cur, data, which))) {
223 	case ENOMEM:
224 		nlen = data->size;
225 		goto retry;
226 	default:
227 alloc_err:
228 		msgq(sp, M_DBERR, "logc->get");
229 		F_SET(ep, F_NOLOG);
230 		return (1);
231 	case 0:
232 		;
233 	}
234 	return 0;
235 }
236 
237 /*
238  *
239  * PUBLIC: int __vi_log_traverse __P((SCR *sp, undo_t undo, MARK *));
240  */
241 int
__vi_log_traverse(SCR * sp,undo_t undo,MARK * rp)242 __vi_log_traverse(SCR *sp, undo_t undo, MARK *rp)
243 {
244 	DB_LOGC *logc;
245 	DBT data;
246 	EXF *ep;
247 	int	    ret;
248 	DB_LSN	    lsn;
249 	u_int32_t   which;
250 	db_recops   ops;
251 
252 	ep = sp->ep;
253 
254 	F_SET(ep, F_NOLOG);		/* Turn off logging. */
255 
256 	sp->state.undo = undo;
257 	ep->env->app_private = sp;
258 	if ((sp->db_error = ep->env->log_cursor(ep->env, &logc, 0))
259 		    != 0) {
260 		msgq(sp, M_DBERR, "env->log_cursor");
261 		return (1);
262 	}
263 	if (vi_log_get(sp, logc, &data, DB_SET))
264 		return 1;
265 	if (undo == UNDO_FORWARD) {
266 		ops = DB_TXN_FORWARD_ROLL;
267 		which = DB_NEXT;
268 		if (vi_log_get(sp, logc, &data, DB_NEXT))
269 			return 1;
270 	} else {
271 		ops = DB_TXN_BACKWARD_ROLL;
272 		which = DB_PREV;
273 	}
274 
275 	for (;;) {
276 		MEMCPY(&lsn, &ep->lsn_cur, 1);
277 		ret = __vi_log_dispatch(ep->env, &data, &lsn, ops);
278 		if (ret != 0) {
279 			if (ret == LOG_CURSOR_HIT)
280 				break;
281 		}
282 
283 		if (vi_log_get(sp, logc, &data, which))
284 			return 1;
285 		if (undo == UNDO_SETLINE &&
286 		    log_compare(&ep->lsn_cur, &ep->lsn_first) <= 0) {
287 			/* Move to previous record without dispatching. */
288 			undo = UNDO_BACKWARD;
289 			break;
290 		}
291 	}
292 	if (undo == UNDO_BACKWARD)
293 		if (vi_log_get(sp, logc, &data, DB_PREV))
294 			return 1;
295 
296 	logc->close(logc, 0);
297 
298 	ep->env->app_private = NULL;
299 
300 	MEMMOVE(rp, &sp->state.pos, 1);
301 
302 	F_CLR(ep, F_NOLOG);
303 
304 	return 0;
305 }
306 
307 int
vi_db_init_recover(DB_ENV * dbenv)308 vi_db_init_recover(DB_ENV *dbenv)
309 {
310 	int	ret;
311 
312 	if ((ret = __db_init_recover(dbenv)) != 0)
313 		return (ret);
314 	if ((ret = __bam_init_recover(dbenv)) != 0)
315 		return (ret);
316 
317 	return 0;
318 }
319 /*
320  * PUBLIC: #endif
321  */
322