pass thread specific data do db
[nvi.git] / common / log.c
blob609ba238a6e3ce03216289316dc856b57bc0a704
1 /*-
2 * Copyright (c) 1992, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 * Copyright (c) 1992, 1993, 1994, 1995, 1996
5 * Keith Bostic. All rights reserved.
7 * See the LICENSE file for redistribution information.
8 */
10 #include "config.h"
12 #ifndef lint
13 static const char sccsid[] = "$Id: log.c,v 10.16 2000/07/22 10:20:31 skimo Exp $ (Berkeley) $Date: 2000/07/22 10:20:31 $";
14 #endif /* not lint */
16 #include <sys/types.h>
17 #include <sys/queue.h>
18 #include <sys/stat.h>
20 #include <bitstring.h>
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <limits.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
28 #include "common.h"
31 * The log consists of records, each containing a type byte and a variable
32 * length byte string, as follows:
34 * LOG_CURSOR_INIT MARK
35 * LOG_CURSOR_END MARK
36 * LOG_LINE_APPEND db_recno_t char *
37 * LOG_LINE_DELETE db_recno_t char *
38 * LOG_LINE_INSERT db_recno_t char *
39 * LOG_LINE_RESET_F db_recno_t char *
40 * LOG_LINE_RESET_B db_recno_t char *
41 * LOG_MARK LMARK
43 * We do before image physical logging. This means that the editor layer
44 * MAY NOT modify records in place, even if simply deleting or overwriting
45 * characters. Since the smallest unit of logging is a line, we're using
46 * up lots of space. This may eventually have to be reduced, probably by
47 * doing logical logging, which is a much cooler database phrase.
49 * The implementation of the historic vi 'u' command, using roll-forward and
50 * roll-back, is simple. Each set of changes has a LOG_CURSOR_INIT record,
51 * followed by a number of other records, followed by a LOG_CURSOR_END record.
52 * LOG_LINE_RESET records come in pairs. The first is a LOG_LINE_RESET_B
53 * record, and is the line before the change. The second is LOG_LINE_RESET_F,
54 * and is the line after the change. Roll-back is done by backing up to the
55 * first LOG_CURSOR_INIT record before a change. Roll-forward is done in a
56 * similar fashion.
58 * The 'U' command is implemented by rolling backward to a LOG_CURSOR_END
59 * record for a line different from the current one. It should be noted that
60 * this means that a subsequent 'u' command will make a change based on the
61 * new position of the log's cursor. This is okay, and, in fact, historic vi
62 * behaved that way.
65 static int vi_log_get __P((SCR *sp, db_recno_t *lnop, size_t *size));
66 static int log_cursor1 __P((SCR *, int));
67 static void log_err __P((SCR *, char *, int));
68 #if defined(DEBUG) && 0
69 static void log_trace __P((SCR *, char *, db_recno_t, u_char *));
70 #endif
72 /* Try and restart the log on failure, i.e. if we run out of memory. */
73 #define LOG_ERR { \
74 log_err(sp, __FILE__, __LINE__); \
75 return (1); \
79 * log_init --
80 * Initialize the logging subsystem.
82 * PUBLIC: int log_init __P((SCR *, EXF *));
84 int
85 log_init(sp, ep)
86 SCR *sp;
87 EXF *ep;
90 * !!!
91 * ep MAY NOT BE THE SAME AS sp->ep, DON'T USE THE LATTER.
93 * Initialize the buffer. The logging subsystem has its own
94 * buffers because the global ones are almost by definition
95 * going to be in use when the log runs.
97 sp->wp->l_lp = NULL;
98 sp->wp->l_len = 0;
99 ep->l_cursor.lno = 1; /* XXX Any valid recno. */
100 ep->l_cursor.cno = 0;
101 ep->l_high = ep->l_cur = 1;
103 if (db_create(&ep->log, sp->gp->env, 0) != 0 ||
104 ep->log->open(ep->log, NULL, NULL, DB_RECNO, DB_CREATE | DB_THREAD,
105 S_IRUSR | S_IWUSR) != 0) {
106 msgq(sp, M_SYSERR, "009|Log file");
107 F_SET(ep, F_NOLOG);
108 return (1);
111 return (0);
115 * log_end --
116 * Close the logging subsystem.
118 * PUBLIC: int log_end __P((SCR *, EXF *));
121 log_end(sp, ep)
122 SCR *sp;
123 EXF *ep;
126 * !!!
127 * ep MAY NOT BE THE SAME AS sp->ep, DON'T USE THE LATTER.
129 if (ep->log != NULL) {
130 (void)(ep->log->close)(ep->log,DB_NOSYNC);
131 ep->log = NULL;
133 if (sp->wp->l_lp != NULL) {
134 free(sp->wp->l_lp);
135 sp->wp->l_lp = NULL;
137 sp->wp->l_len = 0;
138 ep->l_cursor.lno = 1; /* XXX Any valid recno. */
139 ep->l_cursor.cno = 0;
140 ep->l_high = ep->l_cur = 1;
141 return (0);
145 * log_cursor --
146 * Log the current cursor position, starting an event.
148 * PUBLIC: int log_cursor __P((SCR *));
151 log_cursor(sp)
152 SCR *sp;
154 EXF *ep;
156 ep = sp->ep;
157 if (F_ISSET(ep, F_NOLOG))
158 return (0);
161 * If any changes were made since the last cursor init,
162 * put out the ending cursor record.
164 if (ep->l_cursor.lno == OOBLNO) {
165 ep->l_cursor.lno = sp->lno;
166 ep->l_cursor.cno = sp->cno;
167 return (log_cursor1(sp, LOG_CURSOR_END));
169 ep->l_cursor.lno = sp->lno;
170 ep->l_cursor.cno = sp->cno;
171 return (0);
175 * log_cursor1 --
176 * Actually push a cursor record out.
178 static int
179 log_cursor1(sp, type)
180 SCR *sp;
181 int type;
183 DBT data, key;
184 EXF *ep;
186 ep = sp->ep;
187 BINC_RET(sp, sp->wp->l_lp, sp->wp->l_len, sizeof(u_char) + sizeof(MARK));
188 sp->wp->l_lp[0] = type;
189 memmove(sp->wp->l_lp + sizeof(u_char), &ep->l_cursor, sizeof(MARK));
191 memset(&key, 0, sizeof(key));
192 key.data = &ep->l_cur;
193 key.size = sizeof(db_recno_t);
194 memset(&data, 0, sizeof(data));
195 data.data = sp->wp->l_lp;
196 data.size = sizeof(u_char) + sizeof(MARK);
197 if (ep->log->put(ep->log, NULL, &key, &data, 0) == -1)
198 LOG_ERR;
200 #if defined(DEBUG) && 0
201 vtrace(sp, "%lu: %s: %u/%u\n", ep->l_cur,
202 type == LOG_CURSOR_INIT ? "log_cursor_init" : "log_cursor_end",
203 sp->lno, sp->cno);
204 #endif
205 /* Reset high water mark. */
206 ep->l_high = ++ep->l_cur;
208 return (0);
212 * log_line --
213 * Log a line change.
215 * PUBLIC: int log_line __P((SCR *, db_recno_t, u_int));
218 log_line(sp, lno, action)
219 SCR *sp;
220 db_recno_t lno;
221 u_int action;
223 DBT data, key;
224 EXF *ep;
225 size_t len;
226 CHAR_T *lp;
228 ep = sp->ep;
229 if (F_ISSET(ep, F_NOLOG))
230 return (0);
233 * XXX
235 * Kluge for vi. Clear the EXF undo flag so that the
236 * next 'u' command does a roll-back, regardless.
238 F_CLR(ep, F_UNDO);
240 /* Put out one initial cursor record per set of changes. */
241 if (ep->l_cursor.lno != OOBLNO) {
242 if (log_cursor1(sp, LOG_CURSOR_INIT))
243 return (1);
244 ep->l_cursor.lno = OOBLNO;
248 * Put out the changes. If it's a LOG_LINE_RESET_B call, it's a
249 * special case, avoid the caches. Also, if it fails and it's
250 * line 1, it just means that the user started with an empty file,
251 * so fake an empty length line.
253 if (action == LOG_LINE_RESET_B) {
254 if (db_get(sp, lno, DBG_NOCACHE, &lp, &len)) {
255 static CHAR_T nul = 0;
256 if (lno != 1) {
257 db_err(sp, lno);
258 return (1);
260 len = 0;
261 lp = &nul;
263 } else
264 if (db_get(sp, lno, DBG_FATAL, &lp, &len))
265 return (1);
266 BINC_RET(sp,
267 sp->wp->l_lp, sp->wp->l_len,
268 len * sizeof(CHAR_T) + sizeof(u_char) + sizeof(db_recno_t));
269 sp->wp->l_lp[0] = action;
270 memmove(sp->wp->l_lp + sizeof(u_char), &lno, sizeof(db_recno_t));
271 MEMMOVEW(sp->wp->l_lp + sizeof(u_char) + sizeof(db_recno_t), lp, len);
273 memset(&key, 0, sizeof(key));
274 key.data = &ep->l_cur;
275 key.size = sizeof(db_recno_t);
276 memset(&data, 0, sizeof(data));
277 data.data = sp->wp->l_lp;
278 data.size = len * sizeof(CHAR_T) +
279 sizeof(u_char) + sizeof(db_recno_t);
280 if (ep->log->put(ep->log, NULL, &key, &data, 0) == -1)
281 LOG_ERR;
283 #if defined(DEBUG) && 0
284 switch (action) {
285 case LOG_LINE_APPEND:
286 vtrace(sp, "%u: log_line: append: %lu {%u}\n",
287 ep->l_cur, lno, len);
288 break;
289 case LOG_LINE_DELETE:
290 vtrace(sp, "%lu: log_line: delete: %lu {%u}\n",
291 ep->l_cur, lno, len);
292 break;
293 case LOG_LINE_INSERT:
294 vtrace(sp, "%lu: log_line: insert: %lu {%u}\n",
295 ep->l_cur, lno, len);
296 break;
297 case LOG_LINE_RESET_F:
298 vtrace(sp, "%lu: log_line: reset_f: %lu {%u}\n",
299 ep->l_cur, lno, len);
300 break;
301 case LOG_LINE_RESET_B:
302 vtrace(sp, "%lu: log_line: reset_b: %lu {%u}\n",
303 ep->l_cur, lno, len);
304 break;
306 #endif
307 /* Reset high water mark. */
308 ep->l_high = ++ep->l_cur;
310 return (0);
314 * log_mark --
315 * Log a mark position. For the log to work, we assume that there
316 * aren't any operations that just put out a log record -- this
317 * would mean that undo operations would only reset marks, and not
318 * cause any other change.
320 * PUBLIC: int log_mark __P((SCR *, LMARK *));
323 log_mark(sp, lmp)
324 SCR *sp;
325 LMARK *lmp;
327 DBT data, key;
328 EXF *ep;
330 ep = sp->ep;
331 if (F_ISSET(ep, F_NOLOG))
332 return (0);
334 /* Put out one initial cursor record per set of changes. */
335 if (ep->l_cursor.lno != OOBLNO) {
336 if (log_cursor1(sp, LOG_CURSOR_INIT))
337 return (1);
338 ep->l_cursor.lno = OOBLNO;
341 BINC_RET(sp, sp->wp->l_lp,
342 sp->wp->l_len, sizeof(u_char) + sizeof(LMARK));
343 sp->wp->l_lp[0] = LOG_MARK;
344 memmove(sp->wp->l_lp + sizeof(u_char), lmp, sizeof(LMARK));
346 memset(&key, 0, sizeof(key));
347 key.data = &ep->l_cur;
348 key.size = sizeof(db_recno_t);
349 memset(&data, 0, sizeof(data));
350 data.data = sp->wp->l_lp;
351 data.size = sizeof(u_char) + sizeof(LMARK);
352 if (ep->log->put(ep->log, NULL, &key, &data, 0) == -1)
353 LOG_ERR;
355 #if defined(DEBUG) && 0
356 vtrace(sp, "%lu: mark %c: %lu/%u\n",
357 ep->l_cur, lmp->name, lmp->lno, lmp->cno);
358 #endif
359 /* Reset high water mark. */
360 ep->l_high = ++ep->l_cur;
361 return (0);
365 * vi_log_get --
366 * Get a line from the log in log buffer.
368 static int
369 vi_log_get(SCR *sp, db_recno_t *lnop, size_t *size)
371 DBT key, data;
372 size_t nlen;
373 EXF *ep;
375 ep = sp->ep;
377 nlen = 1024;
378 retry:
379 BINC_RET(sp, sp->wp->l_lp, sp->wp->l_len, nlen);
381 memset(&key, 0, sizeof(key));
382 key.data = lnop; /* Initialize db request. */
383 key.size = sizeof(db_recno_t);
384 memset(&data, 0, sizeof(data));
385 data.data = sp->wp->l_lp;
386 data.ulen = sp->wp->l_len;
387 data.flags = DB_DBT_USERMEM;
388 switch (ep->log->get(ep->log, NULL, &key, &data, 0)) {
389 case ENOMEM:
390 nlen = data.size;
391 goto retry;
392 case 0:
393 *size = data.size;
394 return 0;
395 default:
396 return 1;
401 * Log_backward --
402 * Roll the log backward one operation.
404 * PUBLIC: int log_backward __P((SCR *, MARK *));
407 log_backward(sp, rp)
408 SCR *sp;
409 MARK *rp;
411 EXF *ep;
412 LMARK lm;
413 MARK m;
414 db_recno_t lno;
415 int didop;
416 u_char *p;
417 size_t size;
419 ep = sp->ep;
420 if (F_ISSET(ep, F_NOLOG)) {
421 msgq(sp, M_ERR,
422 "010|Logging not being performed, undo not possible");
423 return (1);
426 if (ep->l_cur == 1) {
427 msgq(sp, M_BERR, "011|No changes to undo");
428 return (1);
431 F_SET(ep, F_NOLOG); /* Turn off logging. */
433 for (didop = 0;;) {
434 --ep->l_cur;
435 if (vi_log_get(sp, &ep->l_cur, &size))
436 LOG_ERR;
437 #if defined(DEBUG) && 0
438 log_trace(sp, "log_backward", ep->l_cur, data.data);
439 #endif
440 switch (*(p = (u_char *)sp->wp->l_lp)) {
441 case LOG_CURSOR_INIT:
442 if (didop) {
443 memmove(rp, p + sizeof(u_char), sizeof(MARK));
444 F_CLR(ep, F_NOLOG);
445 return (0);
447 break;
448 case LOG_CURSOR_END:
449 break;
450 case LOG_LINE_APPEND:
451 case LOG_LINE_INSERT:
452 didop = 1;
453 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
454 if (db_delete(sp, lno))
455 goto err;
456 ++sp->rptlines[L_DELETED];
457 break;
458 case LOG_LINE_DELETE:
459 didop = 1;
460 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
461 if (db_insert(sp, lno,
462 (CHAR_T *)(p + sizeof(u_char) +
463 sizeof(db_recno_t)),
464 (size - sizeof(u_char) - sizeof(db_recno_t))
465 / sizeof(CHAR_T)))
466 goto err;
467 ++sp->rptlines[L_ADDED];
468 break;
469 case LOG_LINE_RESET_F:
470 break;
471 case LOG_LINE_RESET_B:
472 didop = 1;
473 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
474 if (db_set(sp, lno,
475 (CHAR_T *)(p + sizeof(u_char) +
476 sizeof(db_recno_t)),
477 (size - sizeof(u_char) - sizeof(db_recno_t))
478 / sizeof(CHAR_T)))
479 goto err;
480 if (sp->rptlchange != lno) {
481 sp->rptlchange = lno;
482 ++sp->rptlines[L_CHANGED];
484 break;
485 case LOG_MARK:
486 didop = 1;
487 memmove(&lm, p + sizeof(u_char), sizeof(LMARK));
488 m.lno = lm.lno;
489 m.cno = lm.cno;
490 if (mark_set(sp, lm.name, &m, 0))
491 goto err;
492 break;
493 default:
494 abort();
498 err: F_CLR(ep, F_NOLOG);
499 return (1);
503 * Log_setline --
504 * Reset the line to its original appearance.
506 * XXX
507 * There's a bug in this code due to our not logging cursor movements
508 * unless a change was made. If you do a change, move off the line,
509 * then move back on and do a 'U', the line will be restored to the way
510 * it was before the original change.
512 * PUBLIC: int log_setline __P((SCR *));
515 log_setline(sp)
516 SCR *sp;
518 EXF *ep;
519 LMARK lm;
520 MARK m;
521 db_recno_t lno;
522 u_char *p;
523 size_t size;
525 ep = sp->ep;
526 if (F_ISSET(ep, F_NOLOG)) {
527 msgq(sp, M_ERR,
528 "012|Logging not being performed, undo not possible");
529 return (1);
532 if (ep->l_cur == 1)
533 return (1);
535 F_SET(ep, F_NOLOG); /* Turn off logging. */
537 for (;;) {
538 --ep->l_cur;
539 if (vi_log_get(sp, &ep->l_cur, &size))
540 LOG_ERR;
541 #if defined(DEBUG) && 0
542 log_trace(sp, "log_setline", ep->l_cur, data.data);
543 #endif
544 switch (*(p = (u_char *)sp->wp->l_lp)) {
545 case LOG_CURSOR_INIT:
546 memmove(&m, p + sizeof(u_char), sizeof(MARK));
547 if (m.lno != sp->lno || ep->l_cur == 1) {
548 F_CLR(ep, F_NOLOG);
549 return (0);
551 break;
552 case LOG_CURSOR_END:
553 memmove(&m, p + sizeof(u_char), sizeof(MARK));
554 if (m.lno != sp->lno) {
555 ++ep->l_cur;
556 F_CLR(ep, F_NOLOG);
557 return (0);
559 break;
560 case LOG_LINE_APPEND:
561 case LOG_LINE_INSERT:
562 case LOG_LINE_DELETE:
563 case LOG_LINE_RESET_F:
564 break;
565 case LOG_LINE_RESET_B:
566 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
567 if (lno == sp->lno &&
568 db_set(sp, lno, (CHAR_T *)(p + sizeof(u_char) +
569 sizeof(db_recno_t)), size - sizeof(u_char) -
570 sizeof(db_recno_t)))
571 goto err;
572 if (sp->rptlchange != lno) {
573 sp->rptlchange = lno;
574 ++sp->rptlines[L_CHANGED];
576 case LOG_MARK:
577 memmove(&lm, p + sizeof(u_char), sizeof(LMARK));
578 m.lno = lm.lno;
579 m.cno = lm.cno;
580 if (mark_set(sp, lm.name, &m, 0))
581 goto err;
582 break;
583 default:
584 abort();
588 err: F_CLR(ep, F_NOLOG);
589 return (1);
593 * Log_forward --
594 * Roll the log forward one operation.
596 * PUBLIC: int log_forward __P((SCR *, MARK *));
599 log_forward(sp, rp)
600 SCR *sp;
601 MARK *rp;
603 EXF *ep;
604 LMARK lm;
605 MARK m;
606 db_recno_t lno;
607 int didop;
608 u_char *p;
609 size_t size;
611 ep = sp->ep;
612 if (F_ISSET(ep, F_NOLOG)) {
613 msgq(sp, M_ERR,
614 "013|Logging not being performed, roll-forward not possible");
615 return (1);
618 if (ep->l_cur == ep->l_high) {
619 msgq(sp, M_BERR, "014|No changes to re-do");
620 return (1);
623 F_SET(ep, F_NOLOG); /* Turn off logging. */
625 for (didop = 0;;) {
626 ++ep->l_cur;
627 if (vi_log_get(sp, &ep->l_cur, &size))
628 LOG_ERR;
629 #if defined(DEBUG) && 0
630 log_trace(sp, "log_forward", ep->l_cur, data.data);
631 #endif
632 switch (*(p = (u_char *)sp->wp->l_lp)) {
633 case LOG_CURSOR_END:
634 if (didop) {
635 ++ep->l_cur;
636 memmove(rp, p + sizeof(u_char), sizeof(MARK));
637 F_CLR(ep, F_NOLOG);
638 return (0);
640 break;
641 case LOG_CURSOR_INIT:
642 break;
643 /* XXXX LOG_LINE_APPEND and LOG_LINE_INSERT split
644 for now, because db_insert won't work for adding
645 last line
647 case LOG_LINE_APPEND:
648 didop = 1;
649 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
650 --lno;
651 if (db_append(sp, 1, lno,
652 (CHAR_T *)(p + sizeof(u_char) +
653 sizeof(db_recno_t)),
654 (size - sizeof(u_char) - sizeof(db_recno_t))
655 / sizeof(CHAR_T)))
656 goto err;
657 ++sp->rptlines[L_ADDED];
658 break;
659 case LOG_LINE_INSERT:
660 didop = 1;
661 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
662 if (db_insert(sp, lno,
663 (CHAR_T *)(p + sizeof(u_char) +
664 sizeof(db_recno_t)),
665 (size - sizeof(u_char) - sizeof(db_recno_t))
666 / sizeof(CHAR_T)))
667 goto err;
668 ++sp->rptlines[L_ADDED];
669 break;
670 case LOG_LINE_DELETE:
671 didop = 1;
672 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
673 if (db_delete(sp, lno))
674 goto err;
675 ++sp->rptlines[L_DELETED];
676 break;
677 case LOG_LINE_RESET_B:
678 break;
679 case LOG_LINE_RESET_F:
680 didop = 1;
681 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
682 if (db_set(sp, lno,
683 (CHAR_T *)(p + sizeof(u_char) +
684 sizeof(db_recno_t)),
685 (size - sizeof(u_char) - sizeof(db_recno_t))
686 / sizeof(CHAR_T)))
687 goto err;
688 if (sp->rptlchange != lno) {
689 sp->rptlchange = lno;
690 ++sp->rptlines[L_CHANGED];
692 break;
693 case LOG_MARK:
694 didop = 1;
695 memmove(&lm, p + sizeof(u_char), sizeof(LMARK));
696 m.lno = lm.lno;
697 m.cno = lm.cno;
698 if (mark_set(sp, lm.name, &m, 0))
699 goto err;
700 break;
701 default:
702 abort();
706 err: F_CLR(ep, F_NOLOG);
707 return (1);
711 * log_err --
712 * Try and restart the log on failure, i.e. if we run out of memory.
714 static void
715 log_err(sp, file, line)
716 SCR *sp;
717 char *file;
718 int line;
720 EXF *ep;
722 msgq(sp, M_SYSERR, "015|%s/%d: log put error", tail(file), line);
723 ep = sp->ep;
724 (void)ep->log->close(ep->log, DB_NOSYNC);
725 if (!log_init(sp, ep))
726 msgq(sp, M_ERR, "267|Log restarted");
729 #if defined(DEBUG) && 0
730 static void
731 log_trace(sp, msg, rno, p)
732 SCR *sp;
733 char *msg;
734 db_recno_t rno;
735 u_char *p;
737 LMARK lm;
738 MARK m;
739 db_recno_t lno;
741 switch (*p) {
742 case LOG_CURSOR_INIT:
743 memmove(&m, p + sizeof(u_char), sizeof(MARK));
744 vtrace(sp, "%lu: %s: C_INIT: %u/%u\n", rno, msg, m.lno, m.cno);
745 break;
746 case LOG_CURSOR_END:
747 memmove(&m, p + sizeof(u_char), sizeof(MARK));
748 vtrace(sp, "%lu: %s: C_END: %u/%u\n", rno, msg, m.lno, m.cno);
749 break;
750 case LOG_LINE_APPEND:
751 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
752 vtrace(sp, "%lu: %s: APPEND: %lu\n", rno, msg, lno);
753 break;
754 case LOG_LINE_INSERT:
755 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
756 vtrace(sp, "%lu: %s: INSERT: %lu\n", rno, msg, lno);
757 break;
758 case LOG_LINE_DELETE:
759 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
760 vtrace(sp, "%lu: %s: DELETE: %lu\n", rno, msg, lno);
761 break;
762 case LOG_LINE_RESET_F:
763 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
764 vtrace(sp, "%lu: %s: RESET_F: %lu\n", rno, msg, lno);
765 break;
766 case LOG_LINE_RESET_B:
767 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
768 vtrace(sp, "%lu: %s: RESET_B: %lu\n", rno, msg, lno);
769 break;
770 case LOG_MARK:
771 memmove(&lm, p + sizeof(u_char), sizeof(LMARK));
772 vtrace(sp,
773 "%lu: %s: MARK: %u/%u\n", rno, msg, lm.lno, lm.cno);
774 break;
775 default:
776 abort();
779 #endif