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