1*0a6a1f1dSLionel Sambuc /* $NetBSD: log.c,v 1.3 2014/01/26 21:43:45 christos Exp $ */
284d9c625SLionel Sambuc /*-
384d9c625SLionel Sambuc * Copyright (c) 1992, 1993, 1994
484d9c625SLionel Sambuc * The Regents of the University of California. All rights reserved.
584d9c625SLionel Sambuc * Copyright (c) 1992, 1993, 1994, 1995, 1996
684d9c625SLionel Sambuc * Keith Bostic. All rights reserved.
784d9c625SLionel Sambuc *
884d9c625SLionel Sambuc * See the LICENSE file for redistribution information.
984d9c625SLionel Sambuc */
1084d9c625SLionel Sambuc
1184d9c625SLionel Sambuc #include "config.h"
1284d9c625SLionel Sambuc
13*0a6a1f1dSLionel Sambuc #include <sys/cdefs.h>
14*0a6a1f1dSLionel Sambuc #if 0
1584d9c625SLionel Sambuc #ifndef lint
1684d9c625SLionel Sambuc 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 ";
1784d9c625SLionel Sambuc #endif /* not lint */
18*0a6a1f1dSLionel Sambuc #else
19*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: log.c,v 1.3 2014/01/26 21:43:45 christos Exp $");
20*0a6a1f1dSLionel Sambuc #endif
2184d9c625SLionel Sambuc
2284d9c625SLionel Sambuc #include <sys/types.h>
2384d9c625SLionel Sambuc #include <sys/queue.h>
2484d9c625SLionel Sambuc #include <sys/stat.h>
2584d9c625SLionel Sambuc
2684d9c625SLionel Sambuc #include <bitstring.h>
2784d9c625SLionel Sambuc #include <errno.h>
2884d9c625SLionel Sambuc #include <fcntl.h>
2984d9c625SLionel Sambuc #include <limits.h>
3084d9c625SLionel Sambuc #include <stdio.h>
3184d9c625SLionel Sambuc #include <stdlib.h>
3284d9c625SLionel Sambuc #include <string.h>
3384d9c625SLionel Sambuc
3484d9c625SLionel Sambuc #include "common.h"
3584d9c625SLionel Sambuc #include "dbinternal.h"
3684d9c625SLionel Sambuc
3784d9c625SLionel Sambuc /*
3884d9c625SLionel Sambuc * The log consists of records, each containing a type byte and a variable
3984d9c625SLionel Sambuc * length byte string, as follows:
4084d9c625SLionel Sambuc *
4184d9c625SLionel Sambuc * LOG_CURSOR_INIT MARK
4284d9c625SLionel Sambuc * LOG_CURSOR_END MARK
4384d9c625SLionel Sambuc * LOG_LINE_APPEND_F db_recno_t char *
4484d9c625SLionel Sambuc * LOG_LINE_APPEND_B db_recno_t char *
4584d9c625SLionel Sambuc * LOG_LINE_DELETE_F db_recno_t char *
4684d9c625SLionel Sambuc * LOG_LINE_DELETE_B db_recno_t char *
4784d9c625SLionel Sambuc * LOG_LINE_RESET_F db_recno_t char *
4884d9c625SLionel Sambuc * LOG_LINE_RESET_B db_recno_t char *
4984d9c625SLionel Sambuc * LOG_MARK LMARK
5084d9c625SLionel Sambuc *
5184d9c625SLionel Sambuc * We do before image physical logging. This means that the editor layer
5284d9c625SLionel Sambuc * MAY NOT modify records in place, even if simply deleting or overwriting
5384d9c625SLionel Sambuc * characters. Since the smallest unit of logging is a line, we're using
5484d9c625SLionel Sambuc * up lots of space. This may eventually have to be reduced, probably by
5584d9c625SLionel Sambuc * doing logical logging, which is a much cooler database phrase.
5684d9c625SLionel Sambuc *
5784d9c625SLionel Sambuc * The implementation of the historic vi 'u' command, using roll-forward and
5884d9c625SLionel Sambuc * roll-back, is simple. Each set of changes has a LOG_CURSOR_INIT record,
5984d9c625SLionel Sambuc * followed by a number of other records, followed by a LOG_CURSOR_END record.
6084d9c625SLionel Sambuc * LOG_LINE_RESET records come in pairs. The first is a LOG_LINE_RESET_B
6184d9c625SLionel Sambuc * record, and is the line before the change. The second is LOG_LINE_RESET_F,
6284d9c625SLionel Sambuc * and is the line after the change. Roll-back is done by backing up to the
6384d9c625SLionel Sambuc * first LOG_CURSOR_INIT record before a change. Roll-forward is done in a
6484d9c625SLionel Sambuc * similar fashion.
6584d9c625SLionel Sambuc *
6684d9c625SLionel Sambuc * The 'U' command is implemented by rolling backward to a LOG_CURSOR_END
6784d9c625SLionel Sambuc * record for a line different from the current one. It should be noted that
6884d9c625SLionel Sambuc * this means that a subsequent 'u' command will make a change based on the
6984d9c625SLionel Sambuc * new position of the log's cursor. This is okay, and, in fact, historic vi
7084d9c625SLionel Sambuc * behaved that way.
7184d9c625SLionel Sambuc */
7284d9c625SLionel Sambuc
7384d9c625SLionel Sambuc static int vi_log_get __P((SCR *sp, db_recno_t *lnop, size_t *size));
7484d9c625SLionel Sambuc static int log_cursor1 __P((SCR *, int));
7584d9c625SLionel Sambuc static void log_err __P((SCR *, const char *, int));
7684d9c625SLionel Sambuc #if defined(DEBUG) && 0
7784d9c625SLionel Sambuc static void log_trace __P((SCR *, const char *, db_recno_t, u_char *));
7884d9c625SLionel Sambuc #endif
7984d9c625SLionel Sambuc
8084d9c625SLionel Sambuc /* Try and restart the log on failure, i.e. if we run out of memory. */
8184d9c625SLionel Sambuc #define LOG_ERR { \
8284d9c625SLionel Sambuc log_err(sp, __FILE__, __LINE__); \
8384d9c625SLionel Sambuc return (1); \
8484d9c625SLionel Sambuc }
8584d9c625SLionel Sambuc
8684d9c625SLionel Sambuc /* offset of CHAR_T string in log needs to be aligned on some systems
8784d9c625SLionel Sambuc * because it is passed to db_set as a string
8884d9c625SLionel Sambuc */
8984d9c625SLionel Sambuc typedef struct {
9084d9c625SLionel Sambuc char data[sizeof(u_char) /* type */ + sizeof(db_recno_t)];
9184d9c625SLionel Sambuc CHAR_T str[1];
9284d9c625SLionel Sambuc } log_t;
9384d9c625SLionel Sambuc #define CHAR_T_OFFSET ((char *)(((log_t*)0)->str) - (char *)0)
9484d9c625SLionel Sambuc
9584d9c625SLionel Sambuc /*
9684d9c625SLionel Sambuc * log_init --
9784d9c625SLionel Sambuc * Initialize the logging subsystem.
9884d9c625SLionel Sambuc *
9984d9c625SLionel Sambuc * PUBLIC: int log_init __P((SCR *, EXF *));
10084d9c625SLionel Sambuc */
10184d9c625SLionel Sambuc int
log_init(SCR * sp,EXF * ep)10284d9c625SLionel Sambuc log_init(SCR *sp, EXF *ep)
10384d9c625SLionel Sambuc {
10484d9c625SLionel Sambuc /*
10584d9c625SLionel Sambuc * !!!
10684d9c625SLionel Sambuc * ep MAY NOT BE THE SAME AS sp->ep, DON'T USE THE LATTER.
10784d9c625SLionel Sambuc *
10884d9c625SLionel Sambuc * Initialize the buffer. The logging subsystem has its own
10984d9c625SLionel Sambuc * buffers because the global ones are almost by definition
11084d9c625SLionel Sambuc * going to be in use when the log runs.
11184d9c625SLionel Sambuc */
11284d9c625SLionel Sambuc sp->wp->l_lp = NULL;
11384d9c625SLionel Sambuc sp->wp->l_len = 0;
11484d9c625SLionel Sambuc ep->l_cursor.lno = 1; /* XXX Any valid recno. */
11584d9c625SLionel Sambuc ep->l_cursor.cno = 0;
11684d9c625SLionel Sambuc ep->l_high = ep->l_cur = 1;
11784d9c625SLionel Sambuc
11884d9c625SLionel Sambuc if (db_create(&ep->log, 0, 0) != 0 ||
11984d9c625SLionel Sambuc db_open(ep->log, NULL, DB_RECNO,
12084d9c625SLionel Sambuc DB_CREATE | VI_DB_THREAD, S_IRUSR | S_IWUSR) != 0) {
12184d9c625SLionel Sambuc msgq(sp, M_SYSERR, "009|Log file");
12284d9c625SLionel Sambuc F_SET(ep, F_NOLOG);
12384d9c625SLionel Sambuc return (1);
12484d9c625SLionel Sambuc }
12584d9c625SLionel Sambuc
12684d9c625SLionel Sambuc ep->l_win = NULL;
12784d9c625SLionel Sambuc /*LOCK_INIT(sp->wp, ep);*/
12884d9c625SLionel Sambuc
12984d9c625SLionel Sambuc return (0);
13084d9c625SLionel Sambuc }
13184d9c625SLionel Sambuc
13284d9c625SLionel Sambuc /*
13384d9c625SLionel Sambuc * log_end --
13484d9c625SLionel Sambuc * Close the logging subsystem.
13584d9c625SLionel Sambuc *
13684d9c625SLionel Sambuc * PUBLIC: int log_end __P((SCR *, EXF *));
13784d9c625SLionel Sambuc */
13884d9c625SLionel Sambuc int
log_end(SCR * sp,EXF * ep)13984d9c625SLionel Sambuc log_end(SCR *sp, EXF *ep)
14084d9c625SLionel Sambuc {
14184d9c625SLionel Sambuc /*
14284d9c625SLionel Sambuc * !!!
14384d9c625SLionel Sambuc * ep MAY NOT BE THE SAME AS sp->ep, DON'T USE THE LATTER.
14484d9c625SLionel Sambuc */
14584d9c625SLionel Sambuc /*LOCK_END(sp->wp, ep);*/
14684d9c625SLionel Sambuc if (ep->log != NULL) {
14784d9c625SLionel Sambuc (void)(ep->log->close)(ep->log, DB_NOSYNC);
14884d9c625SLionel Sambuc ep->log = NULL;
14984d9c625SLionel Sambuc }
15084d9c625SLionel Sambuc if (sp->wp->l_lp != NULL) {
15184d9c625SLionel Sambuc free(sp->wp->l_lp);
15284d9c625SLionel Sambuc sp->wp->l_lp = NULL;
15384d9c625SLionel Sambuc }
15484d9c625SLionel Sambuc sp->wp->l_len = 0;
15584d9c625SLionel Sambuc ep->l_cursor.lno = 1; /* XXX Any valid recno. */
15684d9c625SLionel Sambuc ep->l_cursor.cno = 0;
15784d9c625SLionel Sambuc ep->l_high = ep->l_cur = 1;
15884d9c625SLionel Sambuc return (0);
15984d9c625SLionel Sambuc }
16084d9c625SLionel Sambuc
16184d9c625SLionel Sambuc /*
16284d9c625SLionel Sambuc * log_cursor --
16384d9c625SLionel Sambuc * Log the current cursor position, starting an event.
16484d9c625SLionel Sambuc *
16584d9c625SLionel Sambuc * PUBLIC: int log_cursor __P((SCR *));
16684d9c625SLionel Sambuc */
16784d9c625SLionel Sambuc int
log_cursor(SCR * sp)16884d9c625SLionel Sambuc log_cursor(SCR *sp)
16984d9c625SLionel Sambuc {
17084d9c625SLionel Sambuc EXF *ep;
17184d9c625SLionel Sambuc
17284d9c625SLionel Sambuc ep = sp->ep;
17384d9c625SLionel Sambuc if (F_ISSET(ep, F_NOLOG))
17484d9c625SLionel Sambuc return (0);
17584d9c625SLionel Sambuc
17684d9c625SLionel Sambuc /*
17784d9c625SLionel Sambuc * If any changes were made since the last cursor init,
17884d9c625SLionel Sambuc * put out the ending cursor record.
17984d9c625SLionel Sambuc */
18084d9c625SLionel Sambuc if (ep->l_cursor.lno == OOBLNO) {
18184d9c625SLionel Sambuc if (ep->l_win && ep->l_win != sp->wp)
18284d9c625SLionel Sambuc return 0;
18384d9c625SLionel Sambuc ep->l_cursor.lno = sp->lno;
18484d9c625SLionel Sambuc ep->l_cursor.cno = sp->cno;
18584d9c625SLionel Sambuc ep->l_win = NULL;
18684d9c625SLionel Sambuc return (log_cursor1(sp, LOG_CURSOR_END));
18784d9c625SLionel Sambuc }
18884d9c625SLionel Sambuc ep->l_cursor.lno = sp->lno;
18984d9c625SLionel Sambuc ep->l_cursor.cno = sp->cno;
19084d9c625SLionel Sambuc return (0);
19184d9c625SLionel Sambuc }
19284d9c625SLionel Sambuc
19384d9c625SLionel Sambuc /*
19484d9c625SLionel Sambuc * log_cursor1 --
19584d9c625SLionel Sambuc * Actually push a cursor record out.
19684d9c625SLionel Sambuc */
19784d9c625SLionel Sambuc static int
log_cursor1(SCR * sp,int type)19884d9c625SLionel Sambuc log_cursor1(SCR *sp, int type)
19984d9c625SLionel Sambuc {
20084d9c625SLionel Sambuc DBT data, key;
20184d9c625SLionel Sambuc EXF *ep;
20284d9c625SLionel Sambuc
20384d9c625SLionel Sambuc ep = sp->ep;
20484d9c625SLionel Sambuc
20584d9c625SLionel Sambuc /*
20684d9c625SLionel Sambuc if (type == LOG_CURSOR_INIT &&
20784d9c625SLionel Sambuc LOCK_TRY(sp->wp, ep))
20884d9c625SLionel Sambuc return 1;
20984d9c625SLionel Sambuc */
21084d9c625SLionel Sambuc
21184d9c625SLionel Sambuc BINC_RETC(sp, sp->wp->l_lp, sp->wp->l_len, sizeof(u_char) + sizeof(MARK));
21284d9c625SLionel Sambuc sp->wp->l_lp[0] = type;
21384d9c625SLionel Sambuc memmove(sp->wp->l_lp + sizeof(u_char), &ep->l_cursor, sizeof(MARK));
21484d9c625SLionel Sambuc
21584d9c625SLionel Sambuc memset(&key, 0, sizeof(key));
21684d9c625SLionel Sambuc key.data = &ep->l_cur;
21784d9c625SLionel Sambuc key.size = sizeof(db_recno_t);
21884d9c625SLionel Sambuc memset(&data, 0, sizeof(data));
21984d9c625SLionel Sambuc data.data = sp->wp->l_lp;
22084d9c625SLionel Sambuc data.size = sizeof(u_char) + sizeof(MARK);
22184d9c625SLionel Sambuc if (ep->log->put(ep->log, NULL, &key, &data, 0) == -1)
22284d9c625SLionel Sambuc LOG_ERR;
22384d9c625SLionel Sambuc
22484d9c625SLionel Sambuc #if defined(DEBUG) && 0
22584d9c625SLionel Sambuc vtrace(sp, "%lu: %s: %u/%u\n", ep->l_cur,
22684d9c625SLionel Sambuc type == LOG_CURSOR_INIT ? "log_cursor_init" : "log_cursor_end",
22784d9c625SLionel Sambuc sp->lno, sp->cno);
22884d9c625SLionel Sambuc #endif
22984d9c625SLionel Sambuc /* Reset high water mark. */
23084d9c625SLionel Sambuc ep->l_high = ++ep->l_cur;
23184d9c625SLionel Sambuc
23284d9c625SLionel Sambuc /*
23384d9c625SLionel Sambuc if (type == LOG_CURSOR_END)
23484d9c625SLionel Sambuc LOCK_UNLOCK(sp->wp, ep);
23584d9c625SLionel Sambuc */
23684d9c625SLionel Sambuc return (0);
23784d9c625SLionel Sambuc }
23884d9c625SLionel Sambuc
23984d9c625SLionel Sambuc /*
24084d9c625SLionel Sambuc * log_line --
24184d9c625SLionel Sambuc * Log a line change.
24284d9c625SLionel Sambuc *
24384d9c625SLionel Sambuc * PUBLIC: int log_line __P((SCR *, db_recno_t, u_int));
24484d9c625SLionel Sambuc */
24584d9c625SLionel Sambuc int
log_line(SCR * sp,db_recno_t lno,u_int action)24684d9c625SLionel Sambuc log_line(SCR *sp, db_recno_t lno, u_int action)
24784d9c625SLionel Sambuc {
24884d9c625SLionel Sambuc DBT data, key;
24984d9c625SLionel Sambuc EXF *ep;
25084d9c625SLionel Sambuc size_t len;
25184d9c625SLionel Sambuc CHAR_T *lp;
25284d9c625SLionel Sambuc db_recno_t lcur;
25384d9c625SLionel Sambuc
25484d9c625SLionel Sambuc ep = sp->ep;
25584d9c625SLionel Sambuc if (F_ISSET(ep, F_NOLOG))
25684d9c625SLionel Sambuc return (0);
25784d9c625SLionel Sambuc
25884d9c625SLionel Sambuc /*
25984d9c625SLionel Sambuc * XXX
26084d9c625SLionel Sambuc *
26184d9c625SLionel Sambuc * Kluge for vi. Clear the EXF undo flag so that the
26284d9c625SLionel Sambuc * next 'u' command does a roll-back, regardless.
26384d9c625SLionel Sambuc */
26484d9c625SLionel Sambuc F_CLR(ep, F_UNDO);
26584d9c625SLionel Sambuc
26684d9c625SLionel Sambuc /* Put out one initial cursor record per set of changes. */
26784d9c625SLionel Sambuc if (ep->l_cursor.lno != OOBLNO) {
26884d9c625SLionel Sambuc if (log_cursor1(sp, LOG_CURSOR_INIT))
26984d9c625SLionel Sambuc return (1);
27084d9c625SLionel Sambuc ep->l_cursor.lno = OOBLNO;
27184d9c625SLionel Sambuc ep->l_win = sp->wp;
27284d9c625SLionel Sambuc } /*else if (ep->l_win != sp->wp) {
27384d9c625SLionel Sambuc printf("log_line own: %p, this: %p\n", ep->l_win, sp->wp);
27484d9c625SLionel Sambuc return 1;
27584d9c625SLionel Sambuc }*/
27684d9c625SLionel Sambuc
27784d9c625SLionel Sambuc switch (action) {
27884d9c625SLionel Sambuc /* newly added for DB4 logging */
27984d9c625SLionel Sambuc case LOG_LINE_APPEND_B:
28084d9c625SLionel Sambuc case LOG_LINE_DELETE_F:
28184d9c625SLionel Sambuc return 0;
28284d9c625SLionel Sambuc }
28384d9c625SLionel Sambuc
28484d9c625SLionel Sambuc /*
28584d9c625SLionel Sambuc * Put out the changes. If it's a LOG_LINE_RESET_B call, it's a
28684d9c625SLionel Sambuc * special case, avoid the caches. Also, if it fails and it's
28784d9c625SLionel Sambuc * line 1, it just means that the user started with an empty file,
28884d9c625SLionel Sambuc * so fake an empty length line.
28984d9c625SLionel Sambuc */
29084d9c625SLionel Sambuc if (action == LOG_LINE_RESET_B) {
29184d9c625SLionel Sambuc if (db_get(sp, lno, DBG_NOCACHE, &lp, &len)) {
29284d9c625SLionel Sambuc static CHAR_T nul = 0;
29384d9c625SLionel Sambuc if (lno != 1) {
29484d9c625SLionel Sambuc db_err(sp, lno);
29584d9c625SLionel Sambuc return (1);
29684d9c625SLionel Sambuc }
29784d9c625SLionel Sambuc len = 0;
29884d9c625SLionel Sambuc lp = &nul;
29984d9c625SLionel Sambuc }
30084d9c625SLionel Sambuc } else
30184d9c625SLionel Sambuc if (db_get(sp, lno, DBG_FATAL, &lp, &len))
30284d9c625SLionel Sambuc return (1);
30384d9c625SLionel Sambuc BINC_RETC(sp,
30484d9c625SLionel Sambuc sp->wp->l_lp, sp->wp->l_len,
30584d9c625SLionel Sambuc len * sizeof(CHAR_T) + CHAR_T_OFFSET);
30684d9c625SLionel Sambuc sp->wp->l_lp[0] = action;
30784d9c625SLionel Sambuc memmove(sp->wp->l_lp + sizeof(u_char), &lno, sizeof(db_recno_t));
30884d9c625SLionel Sambuc MEMMOVEW(sp->wp->l_lp + CHAR_T_OFFSET, lp, len);
30984d9c625SLionel Sambuc
31084d9c625SLionel Sambuc lcur = ep->l_cur;
31184d9c625SLionel Sambuc memset(&key, 0, sizeof(key));
31284d9c625SLionel Sambuc key.data = &lcur;
31384d9c625SLionel Sambuc key.size = sizeof(db_recno_t);
31484d9c625SLionel Sambuc memset(&data, 0, sizeof(data));
31584d9c625SLionel Sambuc data.data = sp->wp->l_lp;
31684d9c625SLionel Sambuc data.size = len * sizeof(CHAR_T) + CHAR_T_OFFSET;
31784d9c625SLionel Sambuc if (ep->log->put(ep->log, NULL, &key, &data, 0) == -1)
31884d9c625SLionel Sambuc LOG_ERR;
31984d9c625SLionel Sambuc
32084d9c625SLionel Sambuc #if defined(DEBUG) && 0
32184d9c625SLionel Sambuc switch (action) {
32284d9c625SLionel Sambuc case LOG_LINE_APPEND_F:
32384d9c625SLionel Sambuc vtrace(sp, "%u: log_line: append_f: %lu {%u}\n",
32484d9c625SLionel Sambuc ep->l_cur, lno, len);
32584d9c625SLionel Sambuc break;
32684d9c625SLionel Sambuc case LOG_LINE_APPEND_B:
32784d9c625SLionel Sambuc vtrace(sp, "%u: log_line: append_b: %lu {%u}\n",
32884d9c625SLionel Sambuc ep->l_cur, lno, len);
32984d9c625SLionel Sambuc break;
33084d9c625SLionel Sambuc case LOG_LINE_DELETE_F:
33184d9c625SLionel Sambuc vtrace(sp, "%lu: log_line: delete_f: %lu {%u}\n",
33284d9c625SLionel Sambuc ep->l_cur, lno, len);
33384d9c625SLionel Sambuc break;
33484d9c625SLionel Sambuc case LOG_LINE_DELETE_B:
33584d9c625SLionel Sambuc vtrace(sp, "%lu: log_line: delete_b: %lu {%u}\n",
33684d9c625SLionel Sambuc ep->l_cur, lno, len);
33784d9c625SLionel Sambuc break;
33884d9c625SLionel Sambuc case LOG_LINE_RESET_F:
33984d9c625SLionel Sambuc vtrace(sp, "%lu: log_line: reset_f: %lu {%u}\n",
34084d9c625SLionel Sambuc ep->l_cur, lno, len);
34184d9c625SLionel Sambuc break;
34284d9c625SLionel Sambuc case LOG_LINE_RESET_B:
34384d9c625SLionel Sambuc vtrace(sp, "%lu: log_line: reset_b: %lu {%u}\n",
34484d9c625SLionel Sambuc ep->l_cur, lno, len);
34584d9c625SLionel Sambuc break;
34684d9c625SLionel Sambuc }
34784d9c625SLionel Sambuc #endif
34884d9c625SLionel Sambuc /* Reset high water mark. */
34984d9c625SLionel Sambuc ep->l_high = ++ep->l_cur;
35084d9c625SLionel Sambuc
35184d9c625SLionel Sambuc return (0);
35284d9c625SLionel Sambuc }
35384d9c625SLionel Sambuc
35484d9c625SLionel Sambuc /*
35584d9c625SLionel Sambuc * log_mark --
35684d9c625SLionel Sambuc * Log a mark position. For the log to work, we assume that there
35784d9c625SLionel Sambuc * aren't any operations that just put out a log record -- this
35884d9c625SLionel Sambuc * would mean that undo operations would only reset marks, and not
35984d9c625SLionel Sambuc * cause any other change.
36084d9c625SLionel Sambuc *
36184d9c625SLionel Sambuc * PUBLIC: int log_mark __P((SCR *, LMARK *));
36284d9c625SLionel Sambuc */
36384d9c625SLionel Sambuc int
log_mark(SCR * sp,LMARK * lmp)36484d9c625SLionel Sambuc log_mark(SCR *sp, LMARK *lmp)
36584d9c625SLionel Sambuc {
36684d9c625SLionel Sambuc DBT data, key;
36784d9c625SLionel Sambuc EXF *ep;
36884d9c625SLionel Sambuc
36984d9c625SLionel Sambuc ep = sp->ep;
37084d9c625SLionel Sambuc if (F_ISSET(ep, F_NOLOG))
37184d9c625SLionel Sambuc return (0);
37284d9c625SLionel Sambuc
37384d9c625SLionel Sambuc /* Put out one initial cursor record per set of changes. */
37484d9c625SLionel Sambuc if (ep->l_cursor.lno != OOBLNO) {
37584d9c625SLionel Sambuc if (log_cursor1(sp, LOG_CURSOR_INIT))
37684d9c625SLionel Sambuc return (1);
37784d9c625SLionel Sambuc ep->l_cursor.lno = OOBLNO;
37884d9c625SLionel Sambuc ep->l_win = sp->wp;
37984d9c625SLionel Sambuc }
38084d9c625SLionel Sambuc
38184d9c625SLionel Sambuc BINC_RETC(sp, sp->wp->l_lp,
38284d9c625SLionel Sambuc sp->wp->l_len, sizeof(u_char) + sizeof(LMARK));
38384d9c625SLionel Sambuc sp->wp->l_lp[0] = LOG_MARK;
38484d9c625SLionel Sambuc memmove(sp->wp->l_lp + sizeof(u_char), lmp, sizeof(LMARK));
38584d9c625SLionel Sambuc
38684d9c625SLionel Sambuc memset(&key, 0, sizeof(key));
38784d9c625SLionel Sambuc key.data = &ep->l_cur;
38884d9c625SLionel Sambuc key.size = sizeof(db_recno_t);
38984d9c625SLionel Sambuc memset(&data, 0, sizeof(data));
39084d9c625SLionel Sambuc data.data = sp->wp->l_lp;
39184d9c625SLionel Sambuc data.size = sizeof(u_char) + sizeof(LMARK);
39284d9c625SLionel Sambuc if (ep->log->put(ep->log, NULL, &key, &data, 0) == -1)
39384d9c625SLionel Sambuc LOG_ERR;
39484d9c625SLionel Sambuc
39584d9c625SLionel Sambuc #if defined(DEBUG) && 0
39684d9c625SLionel Sambuc vtrace(sp, "%lu: mark %c: %lu/%u\n",
39784d9c625SLionel Sambuc ep->l_cur, lmp->name, lmp->lno, lmp->cno);
39884d9c625SLionel Sambuc #endif
39984d9c625SLionel Sambuc /* Reset high water mark. */
40084d9c625SLionel Sambuc ep->l_high = ++ep->l_cur;
40184d9c625SLionel Sambuc return (0);
40284d9c625SLionel Sambuc }
40384d9c625SLionel Sambuc
40484d9c625SLionel Sambuc /*
40584d9c625SLionel Sambuc * vi_log_get --
40684d9c625SLionel Sambuc * Get a line from the log in log buffer.
40784d9c625SLionel Sambuc */
40884d9c625SLionel Sambuc static int
vi_log_get(SCR * sp,db_recno_t * lnop,size_t * size)40984d9c625SLionel Sambuc vi_log_get(SCR *sp, db_recno_t *lnop, size_t *size)
41084d9c625SLionel Sambuc {
41184d9c625SLionel Sambuc DBT key, data;
41284d9c625SLionel Sambuc size_t nlen;
41384d9c625SLionel Sambuc EXF *ep;
41484d9c625SLionel Sambuc
41584d9c625SLionel Sambuc ep = sp->ep;
41684d9c625SLionel Sambuc
41784d9c625SLionel Sambuc nlen = 1024;
41884d9c625SLionel Sambuc retry:
41984d9c625SLionel Sambuc BINC_RETC(sp, sp->wp->l_lp, sp->wp->l_len, nlen);
42084d9c625SLionel Sambuc
42184d9c625SLionel Sambuc memset(&key, 0, sizeof(key));
42284d9c625SLionel Sambuc key.data = lnop; /* Initialize db request. */
42384d9c625SLionel Sambuc key.size = sizeof(db_recno_t);
42484d9c625SLionel Sambuc memset(&data, 0, sizeof(data));
42584d9c625SLionel Sambuc data.data = sp->wp->l_lp;
42684d9c625SLionel Sambuc data.ulen = sp->wp->l_len;
42784d9c625SLionel Sambuc data.flags = DB_DBT_USERMEM;
42884d9c625SLionel Sambuc switch (ep->log->get(ep->log, NULL, &key, &data, 0)) {
42984d9c625SLionel Sambuc case ENOMEM:
43084d9c625SLionel Sambuc nlen = data.size;
43184d9c625SLionel Sambuc goto retry;
43284d9c625SLionel Sambuc case 0:
43384d9c625SLionel Sambuc *size = data.size;
43484d9c625SLionel Sambuc return 0;
43584d9c625SLionel Sambuc default:
43684d9c625SLionel Sambuc return 1;
43784d9c625SLionel Sambuc }
43884d9c625SLionel Sambuc }
43984d9c625SLionel Sambuc
44084d9c625SLionel Sambuc /*
44184d9c625SLionel Sambuc * Log_backward --
44284d9c625SLionel Sambuc * Roll the log backward one operation.
44384d9c625SLionel Sambuc *
44484d9c625SLionel Sambuc * PUBLIC: int log_backward __P((SCR *, MARK *));
44584d9c625SLionel Sambuc */
44684d9c625SLionel Sambuc int
log_backward(SCR * sp,MARK * rp)44784d9c625SLionel Sambuc log_backward(SCR *sp, MARK *rp)
44884d9c625SLionel Sambuc {
44984d9c625SLionel Sambuc EXF *ep;
45084d9c625SLionel Sambuc LMARK lm;
45184d9c625SLionel Sambuc MARK m;
45284d9c625SLionel Sambuc db_recno_t lno;
45384d9c625SLionel Sambuc int didop;
45484d9c625SLionel Sambuc u_char *p;
45584d9c625SLionel Sambuc size_t size;
45684d9c625SLionel Sambuc
45784d9c625SLionel Sambuc ep = sp->ep;
45884d9c625SLionel Sambuc if (F_ISSET(ep, F_NOLOG)) {
45984d9c625SLionel Sambuc msgq(sp, M_ERR,
46084d9c625SLionel Sambuc "010|Logging not being performed, undo not possible");
46184d9c625SLionel Sambuc return (1);
46284d9c625SLionel Sambuc }
46384d9c625SLionel Sambuc
46484d9c625SLionel Sambuc if (ep->l_cur == 1) {
46584d9c625SLionel Sambuc msgq(sp, M_BERR, "011|No changes to undo");
46684d9c625SLionel Sambuc return (1);
46784d9c625SLionel Sambuc }
46884d9c625SLionel Sambuc
46984d9c625SLionel Sambuc if (ep->l_win && ep->l_win != sp->wp) {
47084d9c625SLionel Sambuc ex_emsg(sp, NULL, EXM_LOCKED);
47184d9c625SLionel Sambuc return 1;
47284d9c625SLionel Sambuc }
47384d9c625SLionel Sambuc ep->l_win = sp->wp;
47484d9c625SLionel Sambuc
47584d9c625SLionel Sambuc
47684d9c625SLionel Sambuc F_SET(ep, F_NOLOG); /* Turn off logging. */
47784d9c625SLionel Sambuc
47884d9c625SLionel Sambuc for (didop = 0;;) {
47984d9c625SLionel Sambuc --ep->l_cur;
48084d9c625SLionel Sambuc if (vi_log_get(sp, &ep->l_cur, &size))
48184d9c625SLionel Sambuc LOG_ERR;
48284d9c625SLionel Sambuc #if defined(DEBUG) && 0
48384d9c625SLionel Sambuc log_trace(sp, "log_backward", ep->l_cur, data.data);
48484d9c625SLionel Sambuc #endif
48584d9c625SLionel Sambuc switch (*(p = (u_char *)sp->wp->l_lp)) {
48684d9c625SLionel Sambuc case LOG_CURSOR_INIT:
48784d9c625SLionel Sambuc if (didop) {
48884d9c625SLionel Sambuc memmove(rp, p + sizeof(u_char), sizeof(MARK));
48984d9c625SLionel Sambuc F_CLR(ep, F_NOLOG);
49084d9c625SLionel Sambuc ep->l_win = NULL;
49184d9c625SLionel Sambuc return (0);
49284d9c625SLionel Sambuc }
49384d9c625SLionel Sambuc break;
49484d9c625SLionel Sambuc case LOG_CURSOR_END:
49584d9c625SLionel Sambuc break;
49684d9c625SLionel Sambuc case LOG_LINE_APPEND_F:
49784d9c625SLionel Sambuc didop = 1;
49884d9c625SLionel Sambuc memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
49984d9c625SLionel Sambuc if (db_delete(sp, lno))
50084d9c625SLionel Sambuc goto err;
50184d9c625SLionel Sambuc ++sp->rptlines[L_DELETED];
50284d9c625SLionel Sambuc break;
50384d9c625SLionel Sambuc case LOG_LINE_DELETE_B:
50484d9c625SLionel Sambuc didop = 1;
50584d9c625SLionel Sambuc memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
50684d9c625SLionel Sambuc if (db_insert(sp, lno,
50784d9c625SLionel Sambuc (CHAR_T *)(p + CHAR_T_OFFSET),
50884d9c625SLionel Sambuc (size - CHAR_T_OFFSET) / sizeof(CHAR_T)))
50984d9c625SLionel Sambuc goto err;
51084d9c625SLionel Sambuc ++sp->rptlines[L_ADDED];
51184d9c625SLionel Sambuc break;
51284d9c625SLionel Sambuc case LOG_LINE_RESET_F:
51384d9c625SLionel Sambuc break;
51484d9c625SLionel Sambuc case LOG_LINE_RESET_B:
51584d9c625SLionel Sambuc didop = 1;
51684d9c625SLionel Sambuc memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
51784d9c625SLionel Sambuc if (db_set(sp, lno,
51884d9c625SLionel Sambuc (CHAR_T *)(p + CHAR_T_OFFSET),
51984d9c625SLionel Sambuc (size - CHAR_T_OFFSET) / sizeof(CHAR_T)))
52084d9c625SLionel Sambuc goto err;
52184d9c625SLionel Sambuc if (sp->rptlchange != lno) {
52284d9c625SLionel Sambuc sp->rptlchange = lno;
52384d9c625SLionel Sambuc ++sp->rptlines[L_CHANGED];
52484d9c625SLionel Sambuc }
52584d9c625SLionel Sambuc break;
52684d9c625SLionel Sambuc case LOG_MARK:
52784d9c625SLionel Sambuc didop = 1;
52884d9c625SLionel Sambuc memmove(&lm, p + sizeof(u_char), sizeof(LMARK));
52984d9c625SLionel Sambuc m.lno = lm.lno;
53084d9c625SLionel Sambuc m.cno = lm.cno;
53184d9c625SLionel Sambuc if (mark_set(sp, lm.name, &m, 0))
53284d9c625SLionel Sambuc goto err;
53384d9c625SLionel Sambuc break;
53484d9c625SLionel Sambuc default:
53584d9c625SLionel Sambuc abort();
53684d9c625SLionel Sambuc }
53784d9c625SLionel Sambuc }
53884d9c625SLionel Sambuc
53984d9c625SLionel Sambuc err: F_CLR(ep, F_NOLOG);
54084d9c625SLionel Sambuc ep->l_win = NULL;
54184d9c625SLionel Sambuc return (1);
54284d9c625SLionel Sambuc }
54384d9c625SLionel Sambuc
54484d9c625SLionel Sambuc /*
54584d9c625SLionel Sambuc * Log_setline --
54684d9c625SLionel Sambuc * Reset the line to its original appearance.
54784d9c625SLionel Sambuc *
54884d9c625SLionel Sambuc * XXX
54984d9c625SLionel Sambuc * There's a bug in this code due to our not logging cursor movements
55084d9c625SLionel Sambuc * unless a change was made. If you do a change, move off the line,
55184d9c625SLionel Sambuc * then move back on and do a 'U', the line will be restored to the way
55284d9c625SLionel Sambuc * it was before the original change.
55384d9c625SLionel Sambuc *
55484d9c625SLionel Sambuc * PUBLIC: int log_setline __P((SCR *));
55584d9c625SLionel Sambuc */
55684d9c625SLionel Sambuc int
log_setline(SCR * sp)55784d9c625SLionel Sambuc log_setline(SCR *sp)
55884d9c625SLionel Sambuc {
55984d9c625SLionel Sambuc EXF *ep;
56084d9c625SLionel Sambuc LMARK lm;
56184d9c625SLionel Sambuc MARK m;
56284d9c625SLionel Sambuc db_recno_t lno;
56384d9c625SLionel Sambuc u_char *p;
56484d9c625SLionel Sambuc size_t size;
56584d9c625SLionel Sambuc
56684d9c625SLionel Sambuc ep = sp->ep;
56784d9c625SLionel Sambuc if (F_ISSET(ep, F_NOLOG)) {
56884d9c625SLionel Sambuc msgq(sp, M_ERR,
56984d9c625SLionel Sambuc "012|Logging not being performed, undo not possible");
57084d9c625SLionel Sambuc return (1);
57184d9c625SLionel Sambuc }
57284d9c625SLionel Sambuc
57384d9c625SLionel Sambuc if (ep->l_cur == 1)
57484d9c625SLionel Sambuc return (1);
57584d9c625SLionel Sambuc
57684d9c625SLionel Sambuc if (ep->l_win && ep->l_win != sp->wp) {
57784d9c625SLionel Sambuc ex_emsg(sp, NULL, EXM_LOCKED);
57884d9c625SLionel Sambuc return 1;
57984d9c625SLionel Sambuc }
58084d9c625SLionel Sambuc ep->l_win = sp->wp;
58184d9c625SLionel Sambuc
58284d9c625SLionel Sambuc F_SET(ep, F_NOLOG); /* Turn off logging. */
58384d9c625SLionel Sambuc
58484d9c625SLionel Sambuc for (;;) {
58584d9c625SLionel Sambuc --ep->l_cur;
58684d9c625SLionel Sambuc if (vi_log_get(sp, &ep->l_cur, &size))
58784d9c625SLionel Sambuc LOG_ERR;
58884d9c625SLionel Sambuc #if defined(DEBUG) && 0
58984d9c625SLionel Sambuc log_trace(sp, "log_setline", ep->l_cur, data.data);
59084d9c625SLionel Sambuc #endif
59184d9c625SLionel Sambuc switch (*(p = (u_char *)sp->wp->l_lp)) {
59284d9c625SLionel Sambuc case LOG_CURSOR_INIT:
59384d9c625SLionel Sambuc memmove(&m, p + sizeof(u_char), sizeof(MARK));
59484d9c625SLionel Sambuc if (m.lno != sp->lno || ep->l_cur == 1) {
59584d9c625SLionel Sambuc F_CLR(ep, F_NOLOG);
59684d9c625SLionel Sambuc ep->l_win = NULL;
59784d9c625SLionel Sambuc return (0);
59884d9c625SLionel Sambuc }
59984d9c625SLionel Sambuc break;
60084d9c625SLionel Sambuc case LOG_CURSOR_END:
60184d9c625SLionel Sambuc memmove(&m, p + sizeof(u_char), sizeof(MARK));
60284d9c625SLionel Sambuc if (m.lno != sp->lno) {
60384d9c625SLionel Sambuc ++ep->l_cur;
60484d9c625SLionel Sambuc F_CLR(ep, F_NOLOG);
60584d9c625SLionel Sambuc ep->l_win = NULL;
60684d9c625SLionel Sambuc return (0);
60784d9c625SLionel Sambuc }
60884d9c625SLionel Sambuc break;
60984d9c625SLionel Sambuc case LOG_LINE_APPEND_F:
61084d9c625SLionel Sambuc case LOG_LINE_DELETE_B:
61184d9c625SLionel Sambuc case LOG_LINE_RESET_F:
61284d9c625SLionel Sambuc break;
61384d9c625SLionel Sambuc case LOG_LINE_RESET_B:
61484d9c625SLionel Sambuc memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
61584d9c625SLionel Sambuc if (lno == sp->lno &&
61684d9c625SLionel Sambuc db_set(sp, lno, (CHAR_T *)(p + CHAR_T_OFFSET),
61784d9c625SLionel Sambuc (size - CHAR_T_OFFSET) / sizeof(CHAR_T)))
61884d9c625SLionel Sambuc goto err;
61984d9c625SLionel Sambuc if (sp->rptlchange != lno) {
62084d9c625SLionel Sambuc sp->rptlchange = lno;
62184d9c625SLionel Sambuc ++sp->rptlines[L_CHANGED];
62284d9c625SLionel Sambuc }
62384d9c625SLionel Sambuc case LOG_MARK:
62484d9c625SLionel Sambuc memmove(&lm, p + sizeof(u_char), sizeof(LMARK));
62584d9c625SLionel Sambuc m.lno = lm.lno;
62684d9c625SLionel Sambuc m.cno = lm.cno;
62784d9c625SLionel Sambuc if (mark_set(sp, lm.name, &m, 0))
62884d9c625SLionel Sambuc goto err;
62984d9c625SLionel Sambuc break;
63084d9c625SLionel Sambuc default:
63184d9c625SLionel Sambuc abort();
63284d9c625SLionel Sambuc }
63384d9c625SLionel Sambuc }
63484d9c625SLionel Sambuc
63584d9c625SLionel Sambuc err: F_CLR(ep, F_NOLOG);
63684d9c625SLionel Sambuc ep->l_win = NULL;
63784d9c625SLionel Sambuc return (1);
63884d9c625SLionel Sambuc }
63984d9c625SLionel Sambuc
64084d9c625SLionel Sambuc /*
64184d9c625SLionel Sambuc * Log_forward --
64284d9c625SLionel Sambuc * Roll the log forward one operation.
64384d9c625SLionel Sambuc *
64484d9c625SLionel Sambuc * PUBLIC: int log_forward __P((SCR *, MARK *));
64584d9c625SLionel Sambuc */
64684d9c625SLionel Sambuc int
log_forward(SCR * sp,MARK * rp)64784d9c625SLionel Sambuc log_forward(SCR *sp, MARK *rp)
64884d9c625SLionel Sambuc {
64984d9c625SLionel Sambuc EXF *ep;
65084d9c625SLionel Sambuc LMARK lm;
65184d9c625SLionel Sambuc MARK m;
65284d9c625SLionel Sambuc db_recno_t lno;
65384d9c625SLionel Sambuc int didop;
65484d9c625SLionel Sambuc u_char *p;
65584d9c625SLionel Sambuc size_t size;
65684d9c625SLionel Sambuc
65784d9c625SLionel Sambuc ep = sp->ep;
65884d9c625SLionel Sambuc if (F_ISSET(ep, F_NOLOG)) {
65984d9c625SLionel Sambuc msgq(sp, M_ERR,
66084d9c625SLionel Sambuc "013|Logging not being performed, roll-forward not possible");
66184d9c625SLionel Sambuc return (1);
66284d9c625SLionel Sambuc }
66384d9c625SLionel Sambuc
66484d9c625SLionel Sambuc if (ep->l_cur == ep->l_high) {
66584d9c625SLionel Sambuc msgq(sp, M_BERR, "014|No changes to re-do");
66684d9c625SLionel Sambuc return (1);
66784d9c625SLionel Sambuc }
66884d9c625SLionel Sambuc
66984d9c625SLionel Sambuc if (ep->l_win && ep->l_win != sp->wp) {
67084d9c625SLionel Sambuc ex_emsg(sp, NULL, EXM_LOCKED);
67184d9c625SLionel Sambuc return 1;
67284d9c625SLionel Sambuc }
67384d9c625SLionel Sambuc ep->l_win = sp->wp;
67484d9c625SLionel Sambuc
67584d9c625SLionel Sambuc F_SET(ep, F_NOLOG); /* Turn off logging. */
67684d9c625SLionel Sambuc
67784d9c625SLionel Sambuc for (didop = 0;;) {
67884d9c625SLionel Sambuc ++ep->l_cur;
67984d9c625SLionel Sambuc if (vi_log_get(sp, &ep->l_cur, &size))
68084d9c625SLionel Sambuc LOG_ERR;
68184d9c625SLionel Sambuc #if defined(DEBUG) && 0
68284d9c625SLionel Sambuc log_trace(sp, "log_forward", ep->l_cur, data.data);
68384d9c625SLionel Sambuc #endif
68484d9c625SLionel Sambuc switch (*(p = (u_char *)sp->wp->l_lp)) {
68584d9c625SLionel Sambuc case LOG_CURSOR_END:
68684d9c625SLionel Sambuc if (didop) {
68784d9c625SLionel Sambuc ++ep->l_cur;
68884d9c625SLionel Sambuc memmove(rp, p + sizeof(u_char), sizeof(MARK));
68984d9c625SLionel Sambuc F_CLR(ep, F_NOLOG);
69084d9c625SLionel Sambuc ep->l_win = NULL;
69184d9c625SLionel Sambuc return (0);
69284d9c625SLionel Sambuc }
69384d9c625SLionel Sambuc break;
69484d9c625SLionel Sambuc case LOG_CURSOR_INIT:
69584d9c625SLionel Sambuc break;
69684d9c625SLionel Sambuc case LOG_LINE_APPEND_F:
69784d9c625SLionel Sambuc didop = 1;
69884d9c625SLionel Sambuc memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
69984d9c625SLionel Sambuc if (db_insert(sp, lno,
70084d9c625SLionel Sambuc (CHAR_T *)(p + CHAR_T_OFFSET),
70184d9c625SLionel Sambuc (size - CHAR_T_OFFSET) / sizeof(CHAR_T)))
70284d9c625SLionel Sambuc goto err;
70384d9c625SLionel Sambuc ++sp->rptlines[L_ADDED];
70484d9c625SLionel Sambuc break;
70584d9c625SLionel Sambuc case LOG_LINE_DELETE_B:
70684d9c625SLionel Sambuc didop = 1;
70784d9c625SLionel Sambuc memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
70884d9c625SLionel Sambuc if (db_delete(sp, lno))
70984d9c625SLionel Sambuc goto err;
71084d9c625SLionel Sambuc ++sp->rptlines[L_DELETED];
71184d9c625SLionel Sambuc break;
71284d9c625SLionel Sambuc case LOG_LINE_RESET_B:
71384d9c625SLionel Sambuc break;
71484d9c625SLionel Sambuc case LOG_LINE_RESET_F:
71584d9c625SLionel Sambuc didop = 1;
71684d9c625SLionel Sambuc memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
71784d9c625SLionel Sambuc if (db_set(sp, lno,
71884d9c625SLionel Sambuc (CHAR_T *)(p + CHAR_T_OFFSET),
71984d9c625SLionel Sambuc (size - CHAR_T_OFFSET) / sizeof(CHAR_T)))
72084d9c625SLionel Sambuc goto err;
72184d9c625SLionel Sambuc if (sp->rptlchange != lno) {
72284d9c625SLionel Sambuc sp->rptlchange = lno;
72384d9c625SLionel Sambuc ++sp->rptlines[L_CHANGED];
72484d9c625SLionel Sambuc }
72584d9c625SLionel Sambuc break;
72684d9c625SLionel Sambuc case LOG_MARK:
72784d9c625SLionel Sambuc didop = 1;
72884d9c625SLionel Sambuc memmove(&lm, p + sizeof(u_char), sizeof(LMARK));
72984d9c625SLionel Sambuc m.lno = lm.lno;
73084d9c625SLionel Sambuc m.cno = lm.cno;
73184d9c625SLionel Sambuc if (mark_set(sp, lm.name, &m, 0))
73284d9c625SLionel Sambuc goto err;
73384d9c625SLionel Sambuc break;
73484d9c625SLionel Sambuc default:
73584d9c625SLionel Sambuc abort();
73684d9c625SLionel Sambuc }
73784d9c625SLionel Sambuc }
73884d9c625SLionel Sambuc
73984d9c625SLionel Sambuc err: F_CLR(ep, F_NOLOG);
74084d9c625SLionel Sambuc ep->l_win = NULL;
74184d9c625SLionel Sambuc return (1);
74284d9c625SLionel Sambuc }
74384d9c625SLionel Sambuc
74484d9c625SLionel Sambuc /*
74584d9c625SLionel Sambuc * log_err --
74684d9c625SLionel Sambuc * Try and restart the log on failure, i.e. if we run out of memory.
74784d9c625SLionel Sambuc */
74884d9c625SLionel Sambuc static void
log_err(SCR * sp,const char * file,int line)74984d9c625SLionel Sambuc log_err(SCR *sp, const char *file, int line)
75084d9c625SLionel Sambuc {
75184d9c625SLionel Sambuc EXF *ep;
75284d9c625SLionel Sambuc
75384d9c625SLionel Sambuc msgq(sp, M_SYSERR, "015|%s/%d: log put error", tail(file), line);
75484d9c625SLionel Sambuc ep = sp->ep;
75584d9c625SLionel Sambuc (void)ep->log->close(ep->log, DB_NOSYNC);
75684d9c625SLionel Sambuc if (!log_init(sp, ep))
75784d9c625SLionel Sambuc msgq(sp, M_ERR, "267|Log restarted");
75884d9c625SLionel Sambuc }
75984d9c625SLionel Sambuc
76084d9c625SLionel Sambuc #if defined(DEBUG) && 0
76184d9c625SLionel Sambuc static void
log_trace(SCR * sp,const char * msg,db_recno_t rno,u_char * p)76284d9c625SLionel Sambuc log_trace(SCR *sp, const char *msg, db_recno_t rno, u_char *p)
76384d9c625SLionel Sambuc {
76484d9c625SLionel Sambuc LMARK lm;
76584d9c625SLionel Sambuc MARK m;
76684d9c625SLionel Sambuc db_recno_t lno;
76784d9c625SLionel Sambuc
76884d9c625SLionel Sambuc switch (*p) {
76984d9c625SLionel Sambuc case LOG_CURSOR_INIT:
77084d9c625SLionel Sambuc memmove(&m, p + sizeof(u_char), sizeof(MARK));
77184d9c625SLionel Sambuc vtrace(sp, "%lu: %s: C_INIT: %u/%u\n", rno, msg, m.lno, m.cno);
77284d9c625SLionel Sambuc break;
77384d9c625SLionel Sambuc case LOG_CURSOR_END:
77484d9c625SLionel Sambuc memmove(&m, p + sizeof(u_char), sizeof(MARK));
77584d9c625SLionel Sambuc vtrace(sp, "%lu: %s: C_END: %u/%u\n", rno, msg, m.lno, m.cno);
77684d9c625SLionel Sambuc break;
77784d9c625SLionel Sambuc case LOG_LINE_APPEND_F:
77884d9c625SLionel Sambuc memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
77984d9c625SLionel Sambuc vtrace(sp, "%lu: %s: APPEND_F: %lu\n", rno, msg, lno);
78084d9c625SLionel Sambuc break;
78184d9c625SLionel Sambuc case LOG_LINE_APPEND_B:
78284d9c625SLionel Sambuc memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
78384d9c625SLionel Sambuc vtrace(sp, "%lu: %s: APPEND_B: %lu\n", rno, msg, lno);
78484d9c625SLionel Sambuc break;
78584d9c625SLionel Sambuc case LOG_LINE_DELETE_F:
78684d9c625SLionel Sambuc memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
78784d9c625SLionel Sambuc vtrace(sp, "%lu: %s: DELETE_F: %lu\n", rno, msg, lno);
78884d9c625SLionel Sambuc break;
78984d9c625SLionel Sambuc case LOG_LINE_DELETE_B:
79084d9c625SLionel Sambuc memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
79184d9c625SLionel Sambuc vtrace(sp, "%lu: %s: DELETE_B: %lu\n", rno, msg, lno);
79284d9c625SLionel Sambuc break;
79384d9c625SLionel Sambuc case LOG_LINE_RESET_F:
79484d9c625SLionel Sambuc memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
79584d9c625SLionel Sambuc vtrace(sp, "%lu: %s: RESET_F: %lu\n", rno, msg, lno);
79684d9c625SLionel Sambuc break;
79784d9c625SLionel Sambuc case LOG_LINE_RESET_B:
79884d9c625SLionel Sambuc memmove(&lno, p + sizeof(u_char), sizeof(db_recno_t));
79984d9c625SLionel Sambuc vtrace(sp, "%lu: %s: RESET_B: %lu\n", rno, msg, lno);
80084d9c625SLionel Sambuc break;
80184d9c625SLionel Sambuc case LOG_MARK:
80284d9c625SLionel Sambuc memmove(&lm, p + sizeof(u_char), sizeof(LMARK));
80384d9c625SLionel Sambuc vtrace(sp,
80484d9c625SLionel Sambuc "%lu: %s: MARK: %u/%u\n", rno, msg, lm.lno, lm.cno);
80584d9c625SLionel Sambuc break;
80684d9c625SLionel Sambuc default:
80784d9c625SLionel Sambuc abort();
80884d9c625SLionel Sambuc }
80984d9c625SLionel Sambuc }
81084d9c625SLionel Sambuc #endif
811