00001 /*- 00002 * See the file LICENSE for redistribution information. 00003 * 00004 * Copyright (c) 1999, 2000 00005 * Sleepycat Software. All rights reserved. 00006 */ 00007 00008 #include "config.h" 00009 00010 #ifndef lint 00011 static const char revid[] = "$Id: qam__rec_8c-source.html,v 1.1 2008年06月08日 10:21:46 sebdiaz Exp $"; 00012 #endif /* not lint */ 00013 00014 #ifndef NO_SYSTEM_INCLUDES 00015 #include <sys/types.h> 00016 00017 #include <errno.h> 00018 #include <string.h> 00019 #endif 00020 00021 #include "db_int.h" 00022 #include "db_page.h" 00023 #include "db_shash.h" 00024 #include "lock.h" 00025 #include "db_am.h" 00026 #include "qam.h" 00027 #include "log.h" 00028 00029 /* 00030 * CDB___qam_inc_recover -- 00031 * Recovery function for inc. 00032 * 00033 * PUBLIC: int CDB___qam_inc_recover __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); 00034 */ 00035 int 00036 CDB___qam_inc_recover(dbenv, dbtp, lsnp, op, info) 00037 DB_ENV *dbenv; 00038 DBT *dbtp; 00039 DB_LSN *lsnp; 00040 db_recops op; 00041 void *info; 00042 { 00043 __qam_inc_args *argp; 00044 DB *file_dbp; 00045 DBC *dbc; 00046 DB_LOCK lock; 00047 DB_MPOOLFILE *mpf; 00048 QMETA *meta; 00049 db_pgno_t metapg; 00050 int cmp_p, modified, ret; 00051 00052 COMPQUIET(info, NULL); 00053 REC_PRINT(CDB___qam_inc_print); 00054 REC_INTRO(CDB___qam_inc_read, 1); 00055 00056 metapg = ((QUEUE *)file_dbp->q_internal)->q_meta; 00057 00058 if ((ret = CDB___db_lget(dbc, 00059 LCK_ROLLBACK, metapg, DB_LOCK_WRITE, 0, &lock)) != 0) 00060 goto done; 00061 if ((ret = CDB_memp_fget(mpf, &metapg, 0, &meta)) != 0) { 00062 if (DB_REDO(op)) { 00063 if ((ret = CDB_memp_fget(mpf, 00064 &metapg, DB_MPOOL_CREATE, &meta)) != 0) { 00065 (void)__LPUT(dbc, lock); 00066 goto out; 00067 } 00068 meta->dbmeta.pgno = metapg; 00069 meta->dbmeta.type = P_QAMMETA; 00070 00071 } else { 00072 *lsnp = argp->prev_lsn; 00073 ret = 0; 00074 (void)__LPUT(dbc, lock); 00075 goto out; 00076 } 00077 } 00078 00079 modified = 0; 00080 cmp_p = CDB_log_compare(&LSN(meta), &argp->lsn); 00081 CHECK_LSN(op, cmp_p, &LSN(meta), &argp->lsn); 00082 00083 /* 00084 * The cur_recno never goes backwards. It is a point of 00085 * contention among appenders. If one fails cur_recno will 00086 * most likely be beyond that one when it aborts. 00087 * We move it ahead on either an abort or a commit 00088 * and make the LSN reflect that fact. 00089 */ 00090 if (cmp_p == 0) { 00091 modified = 1; 00092 meta->cur_recno++; 00093 meta->dbmeta.lsn = *lsnp; 00094 } 00095 if ((ret = CDB_memp_fput(mpf, meta, modified ? DB_MPOOL_DIRTY : 0))) 00096 goto out; 00097 00098 (void)__LPUT(dbc, lock); 00099 00100 done: *lsnp = argp->prev_lsn; 00101 ret = 0; 00102 00103 out: REC_CLOSE; 00104 } 00105 00106 /* 00107 * CDB___qam_incfirst_recover -- 00108 * Recovery function for incfirst. 00109 * 00110 * PUBLIC: int CDB___qam_incfirst_recover 00111 * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); 00112 */ 00113 int 00114 CDB___qam_incfirst_recover(dbenv, dbtp, lsnp, op, info) 00115 DB_ENV *dbenv; 00116 DBT *dbtp; 00117 DB_LSN *lsnp; 00118 db_recops op; 00119 void *info; 00120 { 00121 __qam_incfirst_args *argp; 00122 DB *file_dbp; 00123 DBC *dbc; 00124 DB_LOCK lock; 00125 DB_MPOOLFILE *mpf; 00126 QMETA *meta; 00127 db_pgno_t metapg; 00128 int modified, ret; 00129 00130 COMPQUIET(info, NULL); 00131 REC_PRINT(CDB___qam_incfirst_print); 00132 REC_INTRO(CDB___qam_incfirst_read, 1); 00133 00134 metapg = ((QUEUE *)file_dbp->q_internal)->q_meta; 00135 00136 if ((ret = CDB___db_lget(dbc, 00137 LCK_ROLLBACK, metapg, DB_LOCK_WRITE, 0, &lock)) != 0) 00138 goto done; 00139 if ((ret = CDB_memp_fget(mpf, &metapg, 0, &meta)) != 0) { 00140 if (DB_REDO(op)) { 00141 if ((ret = CDB_memp_fget(mpf, 00142 &metapg, DB_MPOOL_CREATE, &meta)) != 0) { 00143 (void)__LPUT(dbc, lock); 00144 goto out; 00145 } 00146 meta->dbmeta.pgno = metapg; 00147 meta->dbmeta.type = P_QAMMETA; 00148 } else { 00149 *lsnp = argp->prev_lsn; 00150 ret = 0; 00151 (void)__LPUT(dbc, lock); 00152 goto out; 00153 } 00154 } 00155 00156 modified = 0; 00157 00158 /* 00159 * Only move first_recno backwards so we pick up the aborted delete. 00160 * If we are going forward then we could patch first up, but it will 00161 * get fixed by normal operations. 00162 */ 00163 if (DB_UNDO(op)) { 00164 if (meta->first_recno > argp->recno) { 00165 meta->first_recno = argp->recno; 00166 modified = 1; 00167 } 00168 } 00169 00170 if ((ret = CDB_memp_fput(mpf, meta, modified ? DB_MPOOL_DIRTY : 0))) 00171 goto out; 00172 00173 (void)__LPUT(dbc, lock); 00174 00175 done: *lsnp = argp->prev_lsn; 00176 ret = 0; 00177 00178 out: REC_CLOSE; 00179 } 00180 00181 /* 00182 * CDB___qam_mvptr_recover -- 00183 * Recovery function for mvptr. 00184 * 00185 * PUBLIC: int CDB___qam_mvptr_recover 00186 * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); 00187 */ 00188 int 00189 CDB___qam_mvptr_recover(dbenv, dbtp, lsnp, op, info) 00190 DB_ENV *dbenv; 00191 DBT *dbtp; 00192 DB_LSN *lsnp; 00193 db_recops op; 00194 void *info; 00195 { 00196 __qam_mvptr_args *argp; 00197 DB *file_dbp; 00198 DBC *dbc; 00199 DB_LOCK lock; 00200 DB_MPOOLFILE *mpf; 00201 QMETA *meta; 00202 db_pgno_t metapg; 00203 int cmp_p, modified, ret; 00204 00205 COMPQUIET(info, NULL); 00206 REC_PRINT(CDB___qam_mvptr_print); 00207 REC_INTRO(CDB___qam_mvptr_read, 1); 00208 00209 metapg = ((QUEUE *)file_dbp->q_internal)->q_meta; 00210 00211 if ((ret = CDB___db_lget(dbc, 00212 LCK_ROLLBACK, metapg, DB_LOCK_WRITE, 0, &lock)) != 0) 00213 goto done; 00214 if ((ret = CDB_memp_fget(mpf, &metapg, 0, &meta)) != 0) { 00215 if (DB_REDO(op)) { 00216 if ((ret = CDB_memp_fget(mpf, 00217 &metapg, DB_MPOOL_CREATE, &meta)) != 0) { 00218 (void)__LPUT(dbc, lock); 00219 goto out; 00220 } 00221 meta->dbmeta.pgno = metapg; 00222 meta->dbmeta.type = P_QAMMETA; 00223 } else { 00224 *lsnp = argp->prev_lsn; 00225 ret = 0; 00226 (void)__LPUT(dbc, lock); 00227 goto out; 00228 } 00229 } 00230 00231 modified = 0; 00232 cmp_p = CDB_log_compare(&meta->dbmeta.lsn, &argp->metalsn); 00233 00234 /* 00235 * We never undo a movement of one of the pointers. 00236 * Just move them along regardless of abort/commit. 00237 */ 00238 if (cmp_p == 0) { 00239 if (argp->opcode & QAM_SETFIRST) 00240 meta->first_recno = argp->new_first; 00241 00242 if (argp->opcode & QAM_SETCUR) 00243 meta->cur_recno = argp->new_cur; 00244 00245 modified = 1; 00246 meta->dbmeta.lsn = *lsnp; 00247 } 00248 00249 if ((ret = CDB_memp_fput(mpf, meta, modified ? DB_MPOOL_DIRTY : 0))) 00250 goto out; 00251 00252 (void)__LPUT(dbc, lock); 00253 00254 done: *lsnp = argp->prev_lsn; 00255 ret = 0; 00256 00257 out: REC_CLOSE; 00258 } 00259 /* 00260 * CDB___qam_del_recover -- 00261 * Recovery function for del. 00262 * 00263 * PUBLIC: int CDB___qam_del_recover __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); 00264 */ 00265 int 00266 CDB___qam_del_recover(dbenv, dbtp, lsnp, op, info) 00267 DB_ENV *dbenv; 00268 DBT *dbtp; 00269 DB_LSN *lsnp; 00270 db_recops op; 00271 void *info; 00272 { 00273 __qam_del_args *argp; 00274 DB *file_dbp; 00275 DBC *dbc; 00276 DB_LOCK lock; 00277 DB_MPOOLFILE *mpf; 00278 QAMDATA *qp; 00279 QMETA *meta; 00280 QPAGE *pagep; 00281 db_pgno_t metapg; 00282 int cmp_n, modified, ret; 00283 00284 COMPQUIET(info, NULL); 00285 REC_PRINT(CDB___qam_del_print); 00286 REC_INTRO(CDB___qam_del_read, 1); 00287 00288 if ((ret = CDB_memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { 00289 if (DB_REDO(op)) { 00290 if ((ret = CDB_memp_fget(mpf, 00291 &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0) 00292 goto out; 00293 pagep->pgno = argp->pgno; 00294 pagep->type = P_QAMDATA; 00295 } else { 00296 *lsnp = argp->prev_lsn; 00297 ret = 0; 00298 goto out; 00299 } 00300 } 00301 00302 modified = 0; 00303 cmp_n = CDB_log_compare(lsnp, &LSN(pagep)); 00304 00305 if (cmp_n > 0 && DB_REDO(op)) { 00306 /* Need to redo delete - clear the valid bit */ 00307 qp = QAM_GET_RECORD(file_dbp, pagep, argp->indx); 00308 F_CLR(qp, QAM_VALID); 00309 LSN(pagep) = *lsnp; 00310 modified = 1; 00311 } else if (cmp_n <= 0 && DB_UNDO(op)) { 00312 /* make sure first is behind us */ 00313 metapg = ((QUEUE *)file_dbp->q_internal)->q_meta; 00314 if ((ret = CDB___db_lget(dbc, 00315 LCK_ROLLBACK, metapg, DB_LOCK_WRITE, 0, &lock)) != 0) 00316 return (ret); 00317 if ((ret = CDB_memp_fget(file_dbp->mpf, &metapg, 0, &meta)) != 0) { 00318 (void)__LPUT(dbc, lock); 00319 goto done; 00320 } 00321 if (argp->recno < meta->first_recno) { 00322 meta->first_recno = argp->recno; 00323 (void)CDB_memp_fput(file_dbp->mpf, meta, DB_MPOOL_DIRTY); 00324 } else 00325 (void)CDB_memp_fput(file_dbp->mpf, meta, 0); 00326 (void)__LPUT(dbc, lock); 00327 00328 /* Need to undo delete - mark the record as present */ 00329 qp = QAM_GET_RECORD(file_dbp, pagep, argp->indx); 00330 F_SET(qp, QAM_VALID); 00331 LSN(pagep) = argp->lsn; 00332 modified = 1; 00333 } 00334 if ((ret = CDB_memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))) 00335 goto out; 00336 00337 done: *lsnp = argp->prev_lsn; 00338 ret = 0; 00339 00340 out: REC_CLOSE; 00341 } 00342 00343 /* 00344 * CDB___qam_add_recover -- 00345 * Recovery function for add. 00346 * 00347 * PUBLIC: int CDB___qam_add_recover __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); 00348 */ 00349 int 00350 CDB___qam_add_recover(dbenv, dbtp, lsnp, op, info) 00351 DB_ENV *dbenv; 00352 DBT *dbtp; 00353 DB_LSN *lsnp; 00354 db_recops op; 00355 void *info; 00356 { 00357 __qam_add_args *argp; 00358 DB *file_dbp; 00359 DBC *dbc; 00360 DB_MPOOLFILE *mpf; 00361 QAMDATA *qp; 00362 QPAGE *pagep; 00363 int cmp_n, cmp_p, modified, ret; 00364 00365 COMPQUIET(info, NULL); 00366 REC_PRINT(CDB___qam_add_print); 00367 REC_INTRO(CDB___qam_add_read, 1); 00368 00369 modified = 0; 00370 if ((ret = CDB_memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { 00371 if ((ret = CDB_memp_fget(mpf, 00372 &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0) 00373 goto out; 00374 pagep->pgno = argp->pgno; 00375 pagep->type = P_QAMDATA; 00376 modified = 1; 00377 } 00378 00379 cmp_n = CDB_log_compare(lsnp, &LSN(pagep)); 00380 cmp_p = CDB_log_compare(&LSN(pagep), &argp->lsn); 00381 00382 if (cmp_p <= 0 && DB_REDO(op)) { 00383 /* Need to redo add - put the record on page */ 00384 if ((ret = CDB___qam_pitem(dbc, pagep, argp->indx, argp->recno, 00385 &argp->data)) != 0) 00386 goto err; 00387 LSN(pagep) = *lsnp; 00388 modified = 1; 00389 } else if (cmp_n >= 0 && DB_UNDO(op)) { 00390 /* 00391 * Need to undo add 00392 * If this was an overwrite, put old record back. 00393 * Otherwise just clear the valid bit 00394 */ 00395 if (argp->olddata.size != 0) { 00396 if ((ret = CDB___qam_pitem(dbc, pagep, 00397 argp->indx, argp->recno, &argp->olddata)) != 0) 00398 goto err; 00399 00400 if (!(argp->vflag & QAM_VALID)) { 00401 qp = QAM_GET_RECORD( 00402 file_dbp, pagep, argp->indx); 00403 F_CLR(qp, QAM_VALID); 00404 } 00405 modified = 1; 00406 } else { 00407 qp = QAM_GET_RECORD(file_dbp, pagep, argp->indx); 00408 qp->flags = 0; 00409 modified = 1; 00410 } 00411 LSN(pagep) = argp->lsn; 00412 } 00413 00414 err: if ((ret = CDB_memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0))) 00415 goto out; 00416 00417 done: *lsnp = argp->prev_lsn; 00418 ret = 0; 00419 00420 out: REC_CLOSE; 00421 }