guard against Solaris preprocessor polution
[nvi.git] / common / log.c
blobb3854e0271c21357aaffb03997378cb62962c720
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.23 2001/05/13 09:25:45 skimo Exp $ (Berkeley) $Date: 2001/05/13 09:25:45 $";
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); \
78 /* offset of CHAR_T string in log needs to be aligned on some systems
79 * because it is passed to db_set as a string
81 typedef struct {
82 char data[sizeof(u_char) /* type */ + sizeof(db_recno_t)];
83 CHAR_T str[1];
84 } log_t;
85 #define CHAR_T_OFFSET ((char *)(((log_t*)0)->str) - (char *)0)
88 * log_init --
89 * Initialize the logging subsystem.
91 * PUBLIC: int log_init __P((SCR *, EXF *));
93 int
94 log_init(sp, ep)
95 SCR *sp;
96 EXF *ep;
99 * !!!
100 * ep MAY NOT BE THE SAME AS sp->ep, DON'T USE THE LATTER.
102 * Initialize the buffer. The logging subsystem has its own
103 * buffers because the global ones are almost by definition
104 * going to be in use when the log runs.
106 sp->wp->l_lp = NULL;
107 sp->wp->l_len = 0;
108 ep->l_cursor.lno = 1; /* XXX Any valid recno. */
109 ep->l_cursor.cno = 0;
110 ep->l_high = ep->l_cur = 1;
112 if (db_create(&ep->log, sp->gp->env, 0) != 0 ||
113 ep->log->open(ep->log, NULL, NULL, DB_RECNO,
114 DB_CREATE | VI_DB_THREAD, S_IRUSR | S_IWUSR) != 0) {
115 msgq(sp, M_SYSERR, "009|Log file");
116 F_SET(ep, F_NOLOG);
117 return (1);
120 ep->l_win = NULL;
121 /*LOCK_INIT(sp->wp, ep);*/
123 return (0);
127 * log_end --
128 * Close the logging subsystem.
130 * PUBLIC: int log_end __P((SCR *, EXF *));
133 log_end(sp, ep)
134 SCR *sp;
135 EXF *ep;
138 * !!!
139 * ep MAY NOT BE THE SAME AS sp->ep, DON'T USE THE LATTER.
141 /*LOCK_END(sp->wp, ep);*/
142 if (ep->log != NULL) {
143 (void)(ep->log->close)(ep->log,DB_NOSYNC);
144 ep->log = NULL;
146 if (sp->wp->l_lp != NULL) {
147 free(sp->wp->l_lp);
148 sp->wp->l_lp = NULL;
150 sp->wp->l_len = 0;
151 ep->l_cursor.lno = 1; /* XXX Any valid recno. */
152 ep->l_cursor.cno = 0;
153 ep->l_high = ep->l_cur = 1;
154 return (0);
158 * log_cursor --
159 * Log the current cursor position, starting an event.
161 * PUBLIC: int log_cursor __P((SCR *));
164 log_cursor(sp)
165 SCR *sp;
167 EXF *ep;
169 ep = sp->ep;
170 if (F_ISSET(ep, F_NOLOG))
171 return (0);
174 * If any changes were made since the last cursor init,
175 * put out the ending cursor record.
177 if (ep->l_cursor.lno == OOBLNO) {
178 if (ep->l_win && ep->l_win != sp->wp)
179 return 0;
180 ep->l_cursor.lno = sp->lno;
181 ep->l_cursor.cno = sp->cno;
182 ep->l_win = NULL;
183 return (log_cursor1(sp, LOG_CURSOR_END));
185 ep->l_cursor.lno = sp->lno;
186 ep->l_cursor.cno = sp->cno;
187 return (0);
191 * log_cursor1 --
192 * Actually push a cursor record out.
194 static int
195 log_cursor1(sp, type)
196 SCR *sp;
197 int type;
199 DBT data, key;
200 EXF *ep;
202 ep = sp->ep;
205 if (type == LOG_CURSOR_INIT &&
206 LOCK_TRY(sp->wp, ep))
207 return 1;
210 BINC_RET(sp, sp->wp->l_lp, sp->wp->l_len, sizeof(u_char) + sizeof(MARK));
211 sp->wp->l_lp[0] = type;
212 memmove(sp->wp->l_lp + sizeof(u_char), &ep->l_cursor, sizeof(MARK));
214 memset(&key, 0, sizeof(key));
215 key.data = &ep->l_cur;
216 key.size = sizeof(db_recno_t);
217 memset(&data, 0, sizeof(data));
218 data.data = sp->wp->l_lp;
219 data.size = sizeof(u_char) + sizeof(MARK);
220 if (ep->log->put(ep->log, NULL, &key, &data, 0) == -1)
221 LOG_ERR;
223 #if defined(DEBUG) && 0
224 vtrace(sp, "%lu: %s: %u/%u\n", ep->l_cur,
225 type == LOG_CURSOR_INIT ? "log_cursor_init" : "log_cursor_end",
226 sp->lno, sp->cno);
227 #endif
228 /* Reset high water mark. */
229 ep->l_high = ++ep->l_cur;
232 if (type == LOG_CURSOR_END)
233 LOCK_UNLOCK(sp->wp, ep);
235 return (0);
239 * log_line --
240 * Log a line change.
242 * PUBLIC: int log_line __P((SCR *, db_recno_t, u_int));
245 log_line(sp, lno, action)
246 SCR *sp;
247 db_recno_t lno;
248 u_int action;
250 DBT data, key;
251 EXF *ep;
252 size_t len;
253 CHAR_T *lp;
254 db_recno_t lcur;
256 ep = sp->ep;
257 if (F_ISSET(ep, F_NOLOG))
258 return (0);
261 * XXX
263 * Kluge for vi. Clear the EXF undo flag so that the
264 * next 'u' command does a roll-back, regardless.
266 F_CLR(ep, F_UNDO);
268 /* Put out one initial cursor record per set of changes. */
269 if (ep->l_cursor.lno != OOBLNO) {
270 if (log_cursor1(sp, LOG_CURSOR_INIT))
271 return (1);
272 ep->l_cursor.lno = OOBLNO;
273 ep->l_win = sp->wp;
274 } /*else if (ep->l_win != sp->wp) {
275 printf("log_line own: %p, this: %p\n", ep->l_win, sp->wp);
276 return 1;
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_RET(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:
318 vtrace(sp, "%u: log_line: append: %lu {%u}\n",
319 ep->l_cur, lno, len);
320 break;
321 case LOG_LINE_DELETE:
322 vtrace(sp, "%lu: log_line: delete: %lu {%u}\n",
323 ep->l_cur, lno, len);
324 break;
325 case LOG_LINE_INSERT:
326 vtrace(sp, "%lu: log_line: insert: %lu {%u}\n",
327 ep->l_cur, lno, len);
328 break;
329 case LOG_LINE_RESET_F:
330 vtrace(sp, "%lu: log_line: reset_f: %lu {%u}\n",
331 ep->l_cur, lno, len);
332 break;
333 case LOG_LINE_RESET_B:
334 vtrace(sp, "%lu: log_line: reset_b: %lu {%u}\n",
335 ep->l_cur, lno, len);
336 break;
338 #endif
339 /* Reset high water mark. */
340 ep->l_high = ++ep->l_cur;
342 return (0);
346 * log_mark --
347 * Log a mark position. For the log to work, we assume that there
348 * aren't any operations that just put out a log record -- this
349 * would mean that undo operations would only reset marks, and not
350 * cause any other change.
352 * PUBLIC: int log_mark __P((SCR *, LMARK *));
355 log_mark(sp, lmp)
356 SCR *sp;
357 LMARK *lmp;
359 DBT data, key;
360 EXF *ep;
362 ep = sp->ep;
363 if (F_ISSET(ep, F_NOLOG))
364 return (0);
366 /* Put out one initial cursor record per set of changes. */
367 if (ep->l_cursor.lno != OOBLNO) {
368 if (log_cursor1(sp, LOG_CURSOR_INIT))
369 return (1);
370 ep->l_cursor.lno = OOBLNO;
371 ep->l_win = sp->wp;
374 BINC_RET(sp, sp->wp->l_lp,
375 sp->wp->l_len, sizeof(u_char) + sizeof(LMARK));
376 sp->wp->l_lp[0] = LOG_MARK;
377 memmove(sp->wp->l_lp + sizeof(u_char), lmp, sizeof(LMARK));
379 memset(&key, 0, sizeof(key));
380 key.data = &ep->l_cur;
381 key.size = sizeof(db_recno_t);
382 memset(&data, 0, sizeof(data));
383 data.data = sp->wp->l_lp;
384 data.size = sizeof(u_char) + sizeof(LMARK);
385 if (ep->log->put(ep->log, NULL, &key, &data, 0) == -1)
386 LOG_ERR;
388 #if defined(DEBUG) && 0
389 vtrace(sp, "%lu: mark %c: %lu/%u\n",
390 ep->l_cur, lmp->name, lmp->lno, lmp->cno);
391 #endif
392 /* Reset high water mark. */
393 ep->l_high = ++ep->l_cur;
394 return (0);
398 * vi_log_get --
399 * Get a line from the log in log buffer.
401 static int
402 vi_log_get(SCR *sp, db_recno_t *lnop, size_t *size)
404 DBT key, data;
405 size_t nlen;
406 EXF *ep;
408 ep = sp->ep;
410 nlen = 1024;
411 retry:
412 BINC_RET(sp, sp->wp->l_lp, sp->wp->l_len, nlen);
414 memset(&key, 0, sizeof(key));
415 key.data = lnop; /* Initialize db request. */
416 key.size = sizeof(db_recno_t);
417 memset(&data, 0, sizeof(data));
418 data.data = sp->wp->l_lp;
419 data.ulen = sp->wp->l_len;
420 data.flags = DB_DBT_USERMEM;
421 switch (ep->log->get(ep->log, NULL, &key, &data, 0)) {
422 case ENOMEM:
423 nlen = data.size;
424 goto retry;
425 case 0:
426 *size = data.size;
427 return 0;
428 default:
429 return 1;
434 * Log_backward --
435 * Roll the log backward one operation.
437 * PUBLIC: int log_backward __P((SCR *, MARK *));
440 log_backward(sp, rp)
441 SCR *sp;
442 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:
492 case LOG_LINE_INSERT:
493 didop = 1;
494 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
495 if (db_delete(sp, lno))
496 goto err;
497 ++sp->rptlines[L_DELETED];
498 break;
499 case LOG_LINE_DELETE:
500 didop = 1;
501 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
502 if (db_insert(sp, lno,
503 (CHAR_T *)(p + CHAR_T_OFFSET),
504 (size - CHAR_T_OFFSET) / sizeof(CHAR_T)))
505 goto err;
506 ++sp->rptlines[L_ADDED];
507 break;
508 case LOG_LINE_RESET_F:
509 break;
510 case LOG_LINE_RESET_B:
511 didop = 1;
512 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
513 if (db_set(sp, lno,
514 (CHAR_T *)(p + CHAR_T_OFFSET),
515 (size - CHAR_T_OFFSET) / sizeof(CHAR_T)))
516 goto err;
517 if (sp->rptlchange != lno) {
518 sp->rptlchange = lno;
519 ++sp->rptlines[L_CHANGED];
521 break;
522 case LOG_MARK:
523 didop = 1;
524 memmove(&lm, p + sizeof(u_char), sizeof(LMARK));
525 m.lno = lm.lno;
526 m.cno = lm.cno;
527 if (mark_set(sp, lm.name, &m, 0))
528 goto err;
529 break;
530 default:
531 abort();
535 err: F_CLR(ep, F_NOLOG);
536 ep->l_win = NULL;
537 return (1);
541 * Log_setline --
542 * Reset the line to its original appearance.
544 * XXX
545 * There's a bug in this code due to our not logging cursor movements
546 * unless a change was made. If you do a change, move off the line,
547 * then move back on and do a 'U', the line will be restored to the way
548 * it was before the original change.
550 * PUBLIC: int log_setline __P((SCR *));
553 log_setline(sp)
554 SCR *sp;
556 EXF *ep;
557 LMARK lm;
558 MARK m;
559 db_recno_t lno;
560 u_char *p;
561 size_t size;
563 ep = sp->ep;
564 if (F_ISSET(ep, F_NOLOG)) {
565 msgq(sp, M_ERR,
566 "012|Logging not being performed, undo not possible");
567 return (1);
570 if (ep->l_cur == 1)
571 return (1);
573 if (ep->l_win && ep->l_win != sp->wp) {
574 ex_emsg(sp, NULL, EXM_LOCKED);
575 return 1;
577 ep->l_win = sp->wp;
579 F_SET(ep, F_NOLOG); /* Turn off logging. */
581 for (;;) {
582 --ep->l_cur;
583 if (vi_log_get(sp, &ep->l_cur, &size))
584 LOG_ERR;
585 #if defined(DEBUG) && 0
586 log_trace(sp, "log_setline", ep->l_cur, data.data);
587 #endif
588 switch (*(p = (u_char *)sp->wp->l_lp)) {
589 case LOG_CURSOR_INIT:
590 memmove(&m, p + sizeof(u_char), sizeof(MARK));
591 if (m.lno != sp->lno || ep->l_cur == 1) {
592 F_CLR(ep, F_NOLOG);
593 ep->l_win = NULL;
594 return (0);
596 break;
597 case LOG_CURSOR_END:
598 memmove(&m, p + sizeof(u_char), sizeof(MARK));
599 if (m.lno != sp->lno) {
600 ++ep->l_cur;
601 F_CLR(ep, F_NOLOG);
602 ep->l_win = NULL;
603 return (0);
605 break;
606 case LOG_LINE_APPEND:
607 case LOG_LINE_INSERT:
608 case LOG_LINE_DELETE:
609 case LOG_LINE_RESET_F:
610 break;
611 case LOG_LINE_RESET_B:
612 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
613 if (lno == sp->lno &&
614 db_set(sp, lno, (CHAR_T *)(p + CHAR_T_OFFSET),
615 (size - CHAR_T_OFFSET) / sizeof(CHAR_T)))
616 goto err;
617 if (sp->rptlchange != lno) {
618 sp->rptlchange = lno;
619 ++sp->rptlines[L_CHANGED];
621 case LOG_MARK:
622 memmove(&lm, p + sizeof(u_char), sizeof(LMARK));
623 m.lno = lm.lno;
624 m.cno = lm.cno;
625 if (mark_set(sp, lm.name, &m, 0))
626 goto err;
627 break;
628 default:
629 abort();
633 err: F_CLR(ep, F_NOLOG);
634 ep->l_win = NULL;
635 return (1);
639 * Log_forward --
640 * Roll the log forward one operation.
642 * PUBLIC: int log_forward __P((SCR *, MARK *));
645 log_forward(sp, rp)
646 SCR *sp;
647 MARK *rp;
649 EXF *ep;
650 LMARK lm;
651 MARK m;
652 db_recno_t lno;
653 int didop;
654 u_char *p;
655 size_t size;
657 ep = sp->ep;
658 if (F_ISSET(ep, F_NOLOG)) {
659 msgq(sp, M_ERR,
660 "013|Logging not being performed, roll-forward not possible");
661 return (1);
664 if (ep->l_cur == ep->l_high) {
665 msgq(sp, M_BERR, "014|No changes to re-do");
666 return (1);
669 if (ep->l_win && ep->l_win != sp->wp) {
670 ex_emsg(sp, NULL, EXM_LOCKED);
671 return 1;
673 ep->l_win = sp->wp;
675 F_SET(ep, F_NOLOG); /* Turn off logging. */
677 for (didop = 0;;) {
678 ++ep->l_cur;
679 if (vi_log_get(sp, &ep->l_cur, &size))
680 LOG_ERR;
681 #if defined(DEBUG) && 0
682 log_trace(sp, "log_forward", ep->l_cur, data.data);
683 #endif
684 switch (*(p = (u_char *)sp->wp->l_lp)) {
685 case LOG_CURSOR_END:
686 if (didop) {
687 ++ep->l_cur;
688 memmove(rp, p + sizeof(u_char), sizeof(MARK));
689 F_CLR(ep, F_NOLOG);
690 ep->l_win = NULL;
691 return (0);
693 break;
694 case LOG_CURSOR_INIT:
695 break;
696 /* XXXX LOG_LINE_APPEND and LOG_LINE_INSERT split
697 for now, because db_insert won't work for adding
698 last line
700 case LOG_LINE_APPEND:
701 didop = 1;
702 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
703 --lno;
704 if (db_append(sp, 1, lno,
705 (CHAR_T *)(p + CHAR_T_OFFSET),
706 (size - CHAR_T_OFFSET) / sizeof(CHAR_T)))
707 goto err;
708 ++sp->rptlines[L_ADDED];
709 break;
710 case LOG_LINE_INSERT:
711 didop = 1;
712 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
713 if (db_insert(sp, lno,
714 (CHAR_T *)(p + CHAR_T_OFFSET),
715 (size - CHAR_T_OFFSET) / sizeof(CHAR_T)))
716 goto err;
717 ++sp->rptlines[L_ADDED];
718 break;
719 case LOG_LINE_DELETE:
720 didop = 1;
721 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
722 if (db_delete(sp, lno))
723 goto err;
724 ++sp->rptlines[L_DELETED];
725 break;
726 case LOG_LINE_RESET_B:
727 break;
728 case LOG_LINE_RESET_F:
729 didop = 1;
730 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
731 if (db_set(sp, lno,
732 (CHAR_T *)(p + CHAR_T_OFFSET),
733 (size - CHAR_T_OFFSET) / sizeof(CHAR_T)))
734 goto err;
735 if (sp->rptlchange != lno) {
736 sp->rptlchange = lno;
737 ++sp->rptlines[L_CHANGED];
739 break;
740 case LOG_MARK:
741 didop = 1;
742 memmove(&lm, p + sizeof(u_char), sizeof(LMARK));
743 m.lno = lm.lno;
744 m.cno = lm.cno;
745 if (mark_set(sp, lm.name, &m, 0))
746 goto err;
747 break;
748 default:
749 abort();
753 err: F_CLR(ep, F_NOLOG);
754 ep->l_win = NULL;
755 return (1);
759 * log_err --
760 * Try and restart the log on failure, i.e. if we run out of memory.
762 static void
763 log_err(sp, file, line)
764 SCR *sp;
765 char *file;
766 int line;
768 EXF *ep;
770 msgq(sp, M_SYSERR, "015|%s/%d: log put error", tail(file), line);
771 ep = sp->ep;
772 (void)ep->log->close(ep->log, DB_NOSYNC);
773 if (!log_init(sp, ep))
774 msgq(sp, M_ERR, "267|Log restarted");
777 #if defined(DEBUG) && 0
778 static void
779 log_trace(sp, msg, rno, p)
780 SCR *sp;
781 char *msg;
782 db_recno_t rno;
783 u_char *p;
785 LMARK lm;
786 MARK m;
787 db_recno_t lno;
789 switch (*p) {
790 case LOG_CURSOR_INIT:
791 memmove(&m, p + sizeof(u_char), sizeof(MARK));
792 vtrace(sp, "%lu: %s: C_INIT: %u/%u\n", rno, msg, m.lno, m.cno);
793 break;
794 case LOG_CURSOR_END:
795 memmove(&m, p + sizeof(u_char), sizeof(MARK));
796 vtrace(sp, "%lu: %s: C_END: %u/%u\n", rno, msg, m.lno, m.cno);
797 break;
798 case LOG_LINE_APPEND:
799 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
800 vtrace(sp, "%lu: %s: APPEND: %lu\n", rno, msg, lno);
801 break;
802 case LOG_LINE_INSERT:
803 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
804 vtrace(sp, "%lu: %s: INSERT: %lu\n", rno, msg, lno);
805 break;
806 case LOG_LINE_DELETE:
807 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
808 vtrace(sp, "%lu: %s: DELETE: %lu\n", rno, msg, lno);
809 break;
810 case LOG_LINE_RESET_F:
811 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
812 vtrace(sp, "%lu: %s: RESET_F: %lu\n", rno, msg, lno);
813 break;
814 case LOG_LINE_RESET_B:
815 memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
816 vtrace(sp, "%lu: %s: RESET_B: %lu\n", rno, msg, lno);
817 break;
818 case LOG_MARK:
819 memmove(&lm, p + sizeof(u_char), sizeof(LMARK));
820 vtrace(sp,
821 "%lu: %s: MARK: %u/%u\n", rno, msg, lm.lno, lm.cno);
822 break;
823 default:
824 abort();
827 #endif