tools/llvm: Do not build with symbols
[minix3.git] / external / bsd / nvi / dist / common / log.c
blob9bd4b2ab469596b48034fa9224d6c391ad1d7c99
1 /* $NetBSD: log.c,v 1.2 2013/11/22 15:52:05 christos Exp $ */
2 /*-
3 * Copyright (c) 1992, 1993, 1994
4 * The Regents of the University of California. All rights reserved.
5 * Copyright (c) 1992, 1993, 1994, 1995, 1996
6 * Keith Bostic. All rights reserved.
8 * See the LICENSE file for redistribution information.
9 */
11 #include "config.h"
13 #ifndef lint
14 static const char sccsid[] = "Id: log.c,v 10.26 2002/03/02 23:12:13 skimo Exp (Berkeley) Date: 2002/03/02 23:12:13 ";
15 #endif /* not lint */
17 #include <sys/types.h>
18 #include <sys/queue.h>
19 #include <sys/stat.h>
21 #include <bitstring.h>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <limits.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
29 #include "common.h"
30 #include "dbinternal.h"
33 * The log consists of records, each containing a type byte and a variable
34 * length byte string, as follows:
36 * LOG_CURSOR_INIT MARK
37 * LOG_CURSOR_END MARK
38 * LOG_LINE_APPEND_F db_recno_t char *
39 * LOG_LINE_APPEND_B db_recno_t char *
40 * LOG_LINE_DELETE_F db_recno_t char *
41 * LOG_LINE_DELETE_B db_recno_t char *
42 * LOG_LINE_RESET_F db_recno_t char *
43 * LOG_LINE_RESET_B db_recno_t char *
44 * LOG_MARK LMARK
46 * We do before image physical logging. This means that the editor layer
47 * MAY NOT modify records in place, even if simply deleting or overwriting
48 * characters. Since the smallest unit of logging is a line, we're using
49 * up lots of space. This may eventually have to be reduced, probably by
50 * doing logical logging, which is a much cooler database phrase.
52 * The implementation of the historic vi 'u' command, using roll-forward and
53 * roll-back, is simple. Each set of changes has a LOG_CURSOR_INIT record,
54 * followed by a number of other records, followed by a LOG_CURSOR_END record.
55 * LOG_LINE_RESET records come in pairs. The first is a LOG_LINE_RESET_B
56 * record, and is the line before the change. The second is LOG_LINE_RESET_F,
57 * and is the line after the change. Roll-back is done by backing up to the
58 * first LOG_CURSOR_INIT record before a change. Roll-forward is done in a
59 * similar fashion.
61 * The 'U' command is implemented by rolling backward to a LOG_CURSOR_END
62 * record for a line different from the current one. It should be noted that
63 * this means that a subsequent 'u' command will make a change based on the
64 * new position of the log's cursor. This is okay, and, in fact, historic vi
65 * behaved that way.
68 static int vi_log_get __P((SCR *sp, db_recno_t *lnop, size_t *size));
69 static int log_cursor1 __P((SCR *, int));
70 static void log_err __P((SCR *, const char *, int));
71 #if defined(DEBUG) && 0
72 static void log_trace __P((SCR *, const char *, db_recno_t, u_char *));
73 #endif
75 /* Try and restart the log on failure, i.e. if we run out of memory. */
76 #define LOG_ERR { \
77 log_err(sp, __FILE__, __LINE__); \
78 return (1); \
81 /* offset of CHAR_T string in log needs to be aligned on some systems
82 * because it is passed to db_set as a string
84 typedef struct {
85 char data[sizeof(u_char) /* type */ + sizeof(db_recno_t)];
86 CHAR_T str[1];
87 } log_t;
88 #define CHAR_T_OFFSET ((char *)(((log_t*)0)->str) - (char *)0)
91 * log_init --
92 * Initialize the logging subsystem.
94 * PUBLIC: int log_init __P((SCR *, EXF *));
96 int
97 log_init(SCR *sp, EXF *ep)
100 * !!!
101 * ep MAY NOT BE THE SAME AS sp->ep, DON'T USE THE LATTER.
103 * Initialize the buffer. The logging subsystem has its own
104 * buffers because the global ones are almost by definition
105 * going to be in use when the log runs.
107 sp->wp->l_lp = NULL;
108 sp->wp->l_len = 0;
109 ep->l_cursor.lno = 1; /* XXX Any valid recno. */
110 ep->l_cursor.cno = 0;
111 ep->l_high = ep->l_cur = 1;
113 if (db_create(&ep->log, 0, 0) != 0 ||
114 db_open(ep->log, NULL, DB_RECNO,
115 DB_CREATE | VI_DB_THREAD, S_IRUSR | S_IWUSR) != 0) {
116 msgq(sp, M_SYSERR, "009|Log file");
117 F_SET(ep, F_NOLOG);
118 return (1);
121 ep->l_win = NULL;
122 /*LOCK_INIT(sp->wp, ep);*/
124 return (0);
128 * log_end --
129 * Close the logging subsystem.
131 * PUBLIC: int log_end __P((SCR *, EXF *));
134 log_end(SCR *sp, EXF *ep)
137 * !!!
138 * ep MAY NOT BE THE SAME AS sp->ep, DON'T USE THE LATTER.
140 /*LOCK_END(sp->wp, ep);*/
141 if (ep->log != NULL) {
142 (void)(ep->log->close)(ep->log, DB_NOSYNC);
143 ep->log = NULL;
145 if (sp->wp->l_lp != NULL) {
146 free(sp->wp->l_lp);
147 sp->wp->l_lp = NULL;
149 sp->wp->l_len = 0;
150 ep->l_cursor.lno = 1; /* XXX Any valid recno. */
151 ep->l_cursor.cno = 0;
152 ep->l_high = ep->l_cur = 1;
153 return (0);
157 * log_cursor --
158 * Log the current cursor position, starting an event.
160 * PUBLIC: int log_cursor __P((SCR *));
163 log_cursor(SCR *sp)
165 EXF *ep;
167 ep = sp->ep;
168 if (F_ISSET(ep, F_NOLOG))
169 return (0);
172 * If any changes were made since the last cursor init,
173 * put out the ending cursor record.
175 if (ep->l_cursor.lno == OOBLNO) {
176 if (ep->l_win && ep->l_win != sp->wp)
177 return 0;
178 ep->l_cursor.lno = sp->lno;
179 ep->l_cursor.cno = sp->cno;
180 ep->l_win = NULL;
181 return (log_cursor1(sp, LOG_CURSOR_END));
183 ep->l_cursor.lno = sp->lno;
184 ep->l_cursor.cno = sp->cno;
185 return (0);
189 * log_cursor1 --
190 * Actually push a cursor record out.
192 static int
193 log_cursor1(SCR *sp, int type)
195 DBT data, key;
196 EXF *ep;
198 ep = sp->ep;
201 if (type == LOG_CURSOR_INIT &&
202 LOCK_TRY(sp->wp, ep))
203 return 1;
206 BINC_RETC(sp, sp->wp->l_lp, sp->wp->l_len, sizeof(u_char) + sizeof(MARK));
207 sp->wp->l_lp[0] = type;
208 memmove(sp->wp->l_lp + sizeof(u_char), &ep->l_cursor, sizeof(MARK));
210 memset(&key, 0, sizeof(key));
211 key.data = &ep->l_cur;
212 key.size = sizeof(db_recno_t);
213 memset(&data, 0, sizeof(data));
214 data.data = sp->wp->l_lp;
215 data.size = sizeof(u_char) + sizeof(MARK);
216 if (ep->log->put(ep->log, NULL, &key, &data, 0) == -1)
217 LOG_ERR;
219 #if defined(DEBUG) && 0
220 vtrace(sp, "%lu: %s: %u/%u\n", ep->l_cur,
221 type == LOG_CURSOR_INIT ? "log_cursor_init" : "log_cursor_end",
222 sp->lno, sp->cno);
223 #endif
224 /* Reset high water mark. */
225 ep->l_high = ++ep->l_cur;
228 if (type == LOG_CURSOR_END)
229 LOCK_UNLOCK(sp->wp, ep);
231 return (0);
235 * log_line --
236 * Log a line change.
238 * PUBLIC: int log_line __P((SCR *, db_recno_t, u_int));
241 log_line(SCR *sp, db_recno_t lno, u_int action)
243 DBT data, key;
244 EXF *ep;
245 size_t len;
246 CHAR_T *lp;
247 db_recno_t lcur;
249 ep = sp->ep;
250 if (F_ISSET(ep, F_NOLOG))
251 return (0);
254 * XXX
256 * Kluge for vi. Clear the EXF undo flag so that the
257 * next 'u' command does a roll-back, regardless.
259 F_CLR(ep, F_UNDO);
261 /* Put out one initial cursor record per set of changes. */
262 if (ep->l_cursor.lno != OOBLNO) {
263 if (log_cursor1(sp, LOG_CURSOR_INIT))
264 return (1);
265 ep->l_cursor.lno = OOBLNO;
266 ep->l_win = sp->wp;
267 } /*else if (ep->l_win != sp->wp) {
268 printf("log_line own: %p, this: %p\n", ep->l_win, sp->wp);
269 return 1;
272 switch (action) {
273 /* newly added for DB4 logging */
274 case LOG_LINE_APPEND_B:
275 case LOG_LINE_DELETE_F:
276 return 0;
280 * Put out the changes. If it's a LOG_LINE_RESET_B call, it's a
281 * special case, avoid the caches. Also, if it fails and it's
282 * line 1, it just means that the user started with an empty file,
283 * so fake an empty length line.
285 if (action == LOG_LINE_RESET_B) {
286 if (db_get(sp, lno, DBG_NOCACHE, &lp, &len)) {
287 static CHAR_T nul = 0;
288 if (lno != 1) {
289 db_err(sp, lno);
290 return (1);
292 len = 0;
293 lp = &nul;
295 } else
296 if (db_get(sp, lno, DBG_FATAL, &lp, &len))
297 return (1);
298 BINC_RETC(sp,
299 sp->wp->l_lp, sp->wp->l_len,
300 len * sizeof(CHAR_T) + CHAR_T_OFFSET);
301 sp->wp->l_lp[0] = action;
302 memmove(sp->wp->l_lp + sizeof(u_char), &lno, sizeof(db_recno_t));
303 MEMMOVEW(sp->wp->l_lp + CHAR_T_OFFSET, lp, len);
305 lcur = ep->l_cur;
306 memset(&key, 0, sizeof(key));
307 key.data = &lcur;
308 key.size = sizeof(db_recno_t);
309 memset(&data, 0, sizeof(data));
310 data.data = sp->wp->l_lp;
311 data.size = len * sizeof(CHAR_T) + CHAR_T_OFFSET;
312 if (ep->log->put(ep->log, NULL, &key, &data, 0) == -1)
313 LOG_ERR;
315 #if defined(DEBUG) && 0
316 switch (action) {
317 case LOG_LINE_APPEND_F:
318 vtrace(sp, "%u: log_line: append_f: %lu {%u}\n",
319 ep->l_cur, lno, len);
320 break;
321 case LOG_LINE_APPEND_B:
322 vtrace(sp, "%u: log_line: append_b: %lu {%u}\n",
323 ep->l_cur, lno, len);
324 break;
325 case LOG_LINE_DELETE_F:
326 vtrace(sp, "%lu: log_line: delete_f: %lu {%u}\n",
327 ep->l_cur, lno, len);
328 break;
329 case LOG_LINE_DELETE_B:
330 vtrace(sp, "%lu: log_line: delete_b: %lu {%u}\n",
331 ep->l_cur, lno, len);
332 break;
333 case LOG_LINE_RESET_F:
334 vtrace(sp, "%lu: log_line: reset_f: %lu {%u}\n",
335 ep->l_cur, lno, len);
336 break;
337 case LOG_LINE_RESET_B:
338 vtrace(sp, "%lu: log_line: reset_b: %lu {%u}\n",
339 ep->l_cur, lno, len);
340 break;
342 #endif
343 /* Reset high water mark. */
344 ep->l_high = ++ep->l_cur;
346 return (0);
350 * log_mark --
351 * Log a mark position. For the log to work, we assume that there
352 * aren't any operations that just put out a log record -- this
353 * would mean that undo operations would only reset marks, and not
354 * cause any other change.
356 * PUBLIC: int log_mark __P((SCR *, LMARK *));
359 log_mark(SCR *sp, LMARK *lmp)
361 DBT data, key;
362 EXF *ep;
364 ep = sp->ep;
365 if (F_ISSET(ep, F_NOLOG))
366 return (0);
368 /* Put out one initial cursor record per set of changes. */
369 if (ep->l_cursor.lno != OOBLNO) {
370 if (log_cursor1(sp, LOG_CURSOR_INIT))
371 return (1);
372 ep->l_cursor.lno = OOBLNO;
373 ep->l_win = sp->wp;
376 BINC_RETC(sp, sp->wp->l_lp,
377 sp->wp->l_len, sizeof(u_char) + sizeof(LMARK));
378 sp->wp->l_lp[0] = LOG_MARK;
379 memmove(sp->wp->l_lp + sizeof(u_char), lmp, sizeof(LMARK));
381 memset(&key, 0, sizeof(key));
382 key.data = &ep->l_cur;
383 key.size = sizeof(db_recno_t);
384 memset(&data, 0, sizeof(data));
385 data.data = sp->wp->l_lp;
386 data.size = sizeof(u_char) + sizeof(LMARK);
387 if (ep->log->put(ep->log, NULL, &key, &data, 0) == -1)
388 LOG_ERR;
390 #if defined(DEBUG) && 0
391 vtrace(sp, "%lu: mark %c: %lu/%u\n",
392 ep->l_cur, lmp->name, lmp->lno, lmp->cno);
393 #endif
394 /* Reset high water mark. */
395 ep->l_high = ++ep->l_cur;
396 return (0);
400 * vi_log_get --
401 * Get a line from the log in log buffer.
403 static int
404 vi_log_get(SCR *sp, db_recno_t *lnop, size_t *size)
406 DBT key, data;
407 size_t nlen;
408 EXF *ep;
410 ep = sp->ep;
412 nlen = 1024;
413 retry:
414 BINC_RETC(sp, sp->wp->l_lp, sp->wp->l_len, nlen);
416 memset(&key, 0, sizeof(key));
417 key.data = lnop; /* Initialize db request. */
418 key.size = sizeof(db_recno_t);
419 memset(&data, 0, sizeof(data));
420 data.data = sp->wp->l_lp;
421 data.ulen = sp->wp->l_len;
422 data.flags = DB_DBT_USERMEM;
423 switch (ep->log->get(ep->log, NULL, &key, &data, 0)) {
424 case ENOMEM:
425 nlen = data.size;
426 goto retry;
427 case 0:
428 *size = data.size;
429 return 0;
430 default:
431 return 1;
436 * Log_backward --
437 * Roll the log backward one operation.
439 * PUBLIC: int log_backward __P((SCR *, MARK *));
442 log_backward(SCR *sp, MARK *rp)
444 EXF *ep;
445 LMARK lm;
446 MARK m;
447 db_recno_t lno;
448 int didop;
449 u_char *p;
450 size_t size;
452 ep = sp->ep;
453 if (F_ISSET(ep, F_NOLOG)) {
454 msgq(sp, M_ERR,
455 "010|Logging not being performed, undo not possible");
456 return (1);
459 if (ep->l_cur == 1) {
460 msgq(sp, M_BERR, "011|No changes to undo");
461 return (1);
464 if (ep->l_win && ep->l_win != sp->wp) {
465 ex_emsg(sp, NULL, EXM_LOCKED);
466 return 1;
468 ep->l_win = sp->wp;
471 F_SET(ep, F_NOLOG); /* Turn off logging. */
473 for (didop = 0;;) {
474 --ep->l_cur;
475 if (vi_log_get(sp, &ep->l_cur, &size))
476 LOG_ERR;
477 #if defined(DEBUG) && 0
478 log_trace(sp, "log_backward", ep->l_cur, data.data);
479 #endif
480 switch (*(p = (u_char *)sp->wp->l_lp)) {
481 case LOG_CURSOR_INIT:
482 if (didop) {
483 memmove(rp, p + sizeof(u_char), sizeof(MARK));
484 F_CLR(ep, F_NOLOG);
485 ep->l_win = NULL;
486 return (0);
488 break;
489 case LOG_CURSOR_END:
490 break;
491 case LOG_LINE_APPEND_F:
492 didop = 1;
493 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
494 if (db_delete(sp, lno))
495 goto err;
496 ++sp->rptlines[L_DELETED];
497 break;
498 case LOG_LINE_DELETE_B:
499 didop = 1;
500 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
501 if (db_insert(sp, lno,
502 (CHAR_T *)(p + CHAR_T_OFFSET),
503 (size - CHAR_T_OFFSET) / sizeof(CHAR_T)))
504 goto err;
505 ++sp->rptlines[L_ADDED];
506 break;
507 case LOG_LINE_RESET_F:
508 break;
509 case LOG_LINE_RESET_B:
510 didop = 1;
511 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
512 if (db_set(sp, lno,
513 (CHAR_T *)(p + CHAR_T_OFFSET),
514 (size - CHAR_T_OFFSET) / sizeof(CHAR_T)))
515 goto err;
516 if (sp->rptlchange != lno) {
517 sp->rptlchange = lno;
518 ++sp->rptlines[L_CHANGED];
520 break;
521 case LOG_MARK:
522 didop = 1;
523 memmove(&lm, p + sizeof(u_char), sizeof(LMARK));
524 m.lno = lm.lno;
525 m.cno = lm.cno;
526 if (mark_set(sp, lm.name, &m, 0))
527 goto err;
528 break;
529 default:
530 abort();
534 err: F_CLR(ep, F_NOLOG);
535 ep->l_win = NULL;
536 return (1);
540 * Log_setline --
541 * Reset the line to its original appearance.
543 * XXX
544 * There's a bug in this code due to our not logging cursor movements
545 * unless a change was made. If you do a change, move off the line,
546 * then move back on and do a 'U', the line will be restored to the way
547 * it was before the original change.
549 * PUBLIC: int log_setline __P((SCR *));
552 log_setline(SCR *sp)
554 EXF *ep;
555 LMARK lm;
556 MARK m;
557 db_recno_t lno;
558 u_char *p;
559 size_t size;
561 ep = sp->ep;
562 if (F_ISSET(ep, F_NOLOG)) {
563 msgq(sp, M_ERR,
564 "012|Logging not being performed, undo not possible");
565 return (1);
568 if (ep->l_cur == 1)
569 return (1);
571 if (ep->l_win && ep->l_win != sp->wp) {
572 ex_emsg(sp, NULL, EXM_LOCKED);
573 return 1;
575 ep->l_win = sp->wp;
577 F_SET(ep, F_NOLOG); /* Turn off logging. */
579 for (;;) {
580 --ep->l_cur;
581 if (vi_log_get(sp, &ep->l_cur, &size))
582 LOG_ERR;
583 #if defined(DEBUG) && 0
584 log_trace(sp, "log_setline", ep->l_cur, data.data);
585 #endif
586 switch (*(p = (u_char *)sp->wp->l_lp)) {
587 case LOG_CURSOR_INIT:
588 memmove(&m, p + sizeof(u_char), sizeof(MARK));
589 if (m.lno != sp->lno || ep->l_cur == 1) {
590 F_CLR(ep, F_NOLOG);
591 ep->l_win = NULL;
592 return (0);
594 break;
595 case LOG_CURSOR_END:
596 memmove(&m, p + sizeof(u_char), sizeof(MARK));
597 if (m.lno != sp->lno) {
598 ++ep->l_cur;
599 F_CLR(ep, F_NOLOG);
600 ep->l_win = NULL;
601 return (0);
603 break;
604 case LOG_LINE_APPEND_F:
605 case LOG_LINE_DELETE_B:
606 case LOG_LINE_RESET_F:
607 break;
608 case LOG_LINE_RESET_B:
609 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
610 if (lno == sp->lno &&
611 db_set(sp, lno, (CHAR_T *)(p + CHAR_T_OFFSET),
612 (size - CHAR_T_OFFSET) / sizeof(CHAR_T)))
613 goto err;
614 if (sp->rptlchange != lno) {
615 sp->rptlchange = lno;
616 ++sp->rptlines[L_CHANGED];
618 case LOG_MARK:
619 memmove(&lm, p + sizeof(u_char), sizeof(LMARK));
620 m.lno = lm.lno;
621 m.cno = lm.cno;
622 if (mark_set(sp, lm.name, &m, 0))
623 goto err;
624 break;
625 default:
626 abort();
630 err: F_CLR(ep, F_NOLOG);
631 ep->l_win = NULL;
632 return (1);
636 * Log_forward --
637 * Roll the log forward one operation.
639 * PUBLIC: int log_forward __P((SCR *, MARK *));
642 log_forward(SCR *sp, MARK *rp)
644 EXF *ep;
645 LMARK lm;
646 MARK m;
647 db_recno_t lno;
648 int didop;
649 u_char *p;
650 size_t size;
652 ep = sp->ep;
653 if (F_ISSET(ep, F_NOLOG)) {
654 msgq(sp, M_ERR,
655 "013|Logging not being performed, roll-forward not possible");
656 return (1);
659 if (ep->l_cur == ep->l_high) {
660 msgq(sp, M_BERR, "014|No changes to re-do");
661 return (1);
664 if (ep->l_win && ep->l_win != sp->wp) {
665 ex_emsg(sp, NULL, EXM_LOCKED);
666 return 1;
668 ep->l_win = sp->wp;
670 F_SET(ep, F_NOLOG); /* Turn off logging. */
672 for (didop = 0;;) {
673 ++ep->l_cur;
674 if (vi_log_get(sp, &ep->l_cur, &size))
675 LOG_ERR;
676 #if defined(DEBUG) && 0
677 log_trace(sp, "log_forward", ep->l_cur, data.data);
678 #endif
679 switch (*(p = (u_char *)sp->wp->l_lp)) {
680 case LOG_CURSOR_END:
681 if (didop) {
682 ++ep->l_cur;
683 memmove(rp, p + sizeof(u_char), sizeof(MARK));
684 F_CLR(ep, F_NOLOG);
685 ep->l_win = NULL;
686 return (0);
688 break;
689 case LOG_CURSOR_INIT:
690 break;
691 case LOG_LINE_APPEND_F:
692 didop = 1;
693 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
694 if (db_insert(sp, lno,
695 (CHAR_T *)(p + CHAR_T_OFFSET),
696 (size - CHAR_T_OFFSET) / sizeof(CHAR_T)))
697 goto err;
698 ++sp->rptlines[L_ADDED];
699 break;
700 case LOG_LINE_DELETE_B:
701 didop = 1;
702 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
703 if (db_delete(sp, lno))
704 goto err;
705 ++sp->rptlines[L_DELETED];
706 break;
707 case LOG_LINE_RESET_B:
708 break;
709 case LOG_LINE_RESET_F:
710 didop = 1;
711 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
712 if (db_set(sp, lno,
713 (CHAR_T *)(p + CHAR_T_OFFSET),
714 (size - CHAR_T_OFFSET) / sizeof(CHAR_T)))
715 goto err;
716 if (sp->rptlchange != lno) {
717 sp->rptlchange = lno;
718 ++sp->rptlines[L_CHANGED];
720 break;
721 case LOG_MARK:
722 didop = 1;
723 memmove(&lm, p + sizeof(u_char), sizeof(LMARK));
724 m.lno = lm.lno;
725 m.cno = lm.cno;
726 if (mark_set(sp, lm.name, &m, 0))
727 goto err;
728 break;
729 default:
730 abort();
734 err: F_CLR(ep, F_NOLOG);
735 ep->l_win = NULL;
736 return (1);
740 * log_err --
741 * Try and restart the log on failure, i.e. if we run out of memory.
743 static void
744 log_err(SCR *sp, const char *file, int line)
746 EXF *ep;
748 msgq(sp, M_SYSERR, "015|%s/%d: log put error", tail(file), line);
749 ep = sp->ep;
750 (void)ep->log->close(ep->log, DB_NOSYNC);
751 if (!log_init(sp, ep))
752 msgq(sp, M_ERR, "267|Log restarted");
755 #if defined(DEBUG) && 0
756 static void
757 log_trace(SCR *sp, const char *msg, db_recno_t rno, u_char *p)
759 LMARK lm;
760 MARK m;
761 db_recno_t lno;
763 switch (*p) {
764 case LOG_CURSOR_INIT:
765 memmove(&m, p + sizeof(u_char), sizeof(MARK));
766 vtrace(sp, "%lu: %s: C_INIT: %u/%u\n", rno, msg, m.lno, m.cno);
767 break;
768 case LOG_CURSOR_END:
769 memmove(&m, p + sizeof(u_char), sizeof(MARK));
770 vtrace(sp, "%lu: %s: C_END: %u/%u\n", rno, msg, m.lno, m.cno);
771 break;
772 case LOG_LINE_APPEND_F:
773 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
774 vtrace(sp, "%lu: %s: APPEND_F: %lu\n", rno, msg, lno);
775 break;
776 case LOG_LINE_APPEND_B:
777 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
778 vtrace(sp, "%lu: %s: APPEND_B: %lu\n", rno, msg, lno);
779 break;
780 case LOG_LINE_DELETE_F:
781 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
782 vtrace(sp, "%lu: %s: DELETE_F: %lu\n", rno, msg, lno);
783 break;
784 case LOG_LINE_DELETE_B:
785 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
786 vtrace(sp, "%lu: %s: DELETE_B: %lu\n", rno, msg, lno);
787 break;
788 case LOG_LINE_RESET_F:
789 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
790 vtrace(sp, "%lu: %s: RESET_F: %lu\n", rno, msg, lno);
791 break;
792 case LOG_LINE_RESET_B:
793 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
794 vtrace(sp, "%lu: %s: RESET_B: %lu\n", rno, msg, lno);
795 break;
796 case LOG_MARK:
797 memmove(&lm, p + sizeof(u_char), sizeof(LMARK));
798 vtrace(sp,
799 "%lu: %s: MARK: %u/%u\n", rno, msg, lm.lno, lm.cno);
800 break;
801 default:
802 abort();
805 #endif