00001
00002
00003
00004
00005
00006
00007
00008 #include "config.h"
00009
00010 #ifndef lint
00011 static const char revid[] = "$Id: db__am_8c-source.html,v 1.1 2008/06/08 10:17:11 sebdiaz Exp $";
00012 #endif
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 "btree.h"
00025 #include "hash.h"
00026 #include "qam.h"
00027 #include "lock.h"
00028 #include "mp.h"
00029 #include "txn.h"
00030 #include "db_am.h"
00031 #include "db_ext.h"
00032
00033 #ifdef DEBUG
00034 #include "WordMonitor.h"
00035 #endif
00036
00037
00038
00039
00040
00041
00042
00043 int
00044 CDB___db_cursor(dbp, txn, dbcp, flags)
00045 DB *dbp;
00046 DB_TXN *txn;
00047 DBC **dbcp;
00048 u_int32_t flags;
00049 {
00050 DB_ENV *dbenv;
00051 DBC *dbc;
00052 db_lockmode_t mode;
00053 u_int32_t op;
00054 int ret;
00055
00056 dbenv = dbp->dbenv;
00057
00058 PANIC_CHECK(dbenv);
00059 DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->cursor");
00060
00061
00062 if ((ret = CDB___db_cursorchk(dbp, flags, F_ISSET(dbp, DB_AM_RDONLY))) != 0)
00063 return (ret);
00064
00065 if ((ret =
00066 CDB___db_icursor(dbp, txn, dbp->type, PGNO_INVALID, 0, dbcp)) != 0)
00067 return (ret);
00068 dbc = *dbcp;
00069
00070
00071
00072
00073
00074 if (LOCKING(dbenv)) {
00075 op = LF_ISSET(DB_OPFLAGS_MASK);
00076 mode = (op == DB_WRITELOCK) ? DB_LOCK_WRITE :
00077 ((op == DB_WRITECURSOR) ? DB_LOCK_IWRITE : DB_LOCK_READ);
00078 if ((ret = CDB_lock_get(dbenv, dbc->locker, 0,
00079 &dbc->lock_dbt, mode, &dbc->mylock)) != 0) {
00080 (void)CDB___db_c_close(dbc);
00081 return (ret);
00082 }
00083 if (op == DB_WRITECURSOR)
00084 F_SET(dbc, DBC_WRITECURSOR);
00085 if (op == DB_WRITELOCK)
00086 F_SET(dbc, DBC_WRITER);
00087 }
00088
00089 return (0);
00090 }
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 int
00102 CDB___db_icursor(dbp, txn, dbtype, root, is_opd, dbcp)
00103 DB *dbp;
00104 DB_TXN *txn;
00105 DBTYPE dbtype;
00106 db_pgno_t root;
00107 int is_opd;
00108 DBC **dbcp;
00109 {
00110 DBC *dbc, *adbc;
00111 DBC_INTERNAL *cp;
00112 DB_ENV *dbenv;
00113 int allocated, ret;
00114
00115 dbenv = dbp->dbenv;
00116 allocated = 0;
00117
00118
00119
00120
00121
00122
00123 MUTEX_THREAD_LOCK(dbp->mutexp);
00124 for (dbc = TAILQ_FIRST(&dbp->free_queue);
00125 dbc != NULL; dbc = TAILQ_NEXT(dbc, links))
00126 if (dbtype == dbc->dbtype) {
00127 TAILQ_REMOVE(&dbp->free_queue, dbc, links);
00128 dbc->flags = 0;
00129 break;
00130 }
00131 MUTEX_THREAD_UNLOCK(dbp->mutexp);
00132
00133 if (dbc == NULL) {
00134 if ((ret = CDB___os_calloc(dbp->dbenv, 1, sizeof(DBC), &dbc)) != 0)
00135 return (ret);
00136 allocated = 1;
00137 dbc->flags = 0;
00138
00139 dbc->dbp = dbp;
00140
00141
00142 if (LOCKING_ON(dbenv)) {
00143
00144
00145
00146
00147
00148
00149 if (!DB_IS_THREADED(dbp) &&
00150 (adbc = TAILQ_FIRST(&dbp->active_queue)) != NULL)
00151 dbc->lid = adbc->lid;
00152 else
00153 if ((ret = CDB_lock_id(dbenv, &dbc->lid)) != 0)
00154 goto err;
00155
00156 memcpy(dbc->lock.fileid, dbp->fileid, DB_FILE_ID_LEN);
00157 if (LOCKING(dbenv)) {
00158 dbc->lock_dbt.size = DB_FILE_ID_LEN;
00159 dbc->lock_dbt.data = dbc->lock.fileid;
00160 } else {
00161 dbc->lock.type = DB_PAGE_LOCK;
00162 dbc->lock_dbt.size = sizeof(dbc->lock);
00163 dbc->lock_dbt.data = &dbc->lock;
00164 }
00165 }
00166
00167 switch (dbtype) {
00168 case DB_BTREE:
00169 case DB_RECNO:
00170 if ((ret = CDB___bam_c_init(dbc, dbtype)) != 0)
00171 goto err;
00172 break;
00173 case DB_HASH:
00174 if ((ret = CDB___ham_c_init(dbc)) != 0)
00175 goto err;
00176 break;
00177 case DB_QUEUE:
00178 if ((ret = CDB___qam_c_init(dbc)) != 0)
00179 goto err;
00180 break;
00181 default:
00182 ret = CDB___db_unknown_type(dbp->dbenv,
00183 "CDB___db_icursor", dbtype);
00184 goto err;
00185 }
00186
00187 cp = dbc->internal;
00188 }
00189
00190
00191 dbc->dbtype = dbtype;
00192
00193 if ((dbc->txn = txn) == NULL)
00194 dbc->locker = dbc->lid;
00195 else
00196 dbc->locker = txn->txnid;
00197
00198 if (is_opd)
00199 F_SET(dbc, DBC_OPD);
00200 if (F_ISSET(dbp, DB_AM_RECOVER))
00201 F_SET(dbc, DBC_RECOVER);
00202
00203
00204 cp = dbc->internal;
00205 cp->opd = NULL;
00206
00207 cp->indx = 0;
00208 cp->page = NULL;
00209 cp->pgno = PGNO_INVALID;
00210 cp->root = root;
00211
00212 switch (dbtype) {
00213 case DB_BTREE:
00214 case DB_RECNO:
00215 if ((ret = CDB___bam_c_refresh(dbc)) != 0)
00216 goto err;
00217 break;
00218 case DB_HASH:
00219 case DB_QUEUE:
00220 break;
00221 default:
00222 ret = CDB___db_unknown_type(dbp->dbenv, "CDB___db_icursor", dbp->type);
00223 goto err;
00224 }
00225
00226 MUTEX_THREAD_LOCK(dbp->mutexp);
00227 TAILQ_INSERT_TAIL(&dbp->active_queue, dbc, links);
00228 F_SET(dbc, DBC_ACTIVE);
00229 MUTEX_THREAD_UNLOCK(dbp->mutexp);
00230
00231 *dbcp = dbc;
00232 return (0);
00233
00234 err: if (allocated)
00235 CDB___os_free(dbc, sizeof(*dbc));
00236 return (ret);
00237 }
00238
00239 #ifdef DEBUG
00240
00241
00242
00243
00244
00245
00246 int
00247 CDB___db_cprint(dbp)
00248 DB *dbp;
00249 {
00250 static const FN fn[] = {
00251 { DBC_ACTIVE, "active" },
00252 { DBC_OPD, "off-page-dup" },
00253 { DBC_RECOVER, "recover" },
00254 { DBC_RMW, "read-modify-write" },
00255 { DBC_WRITECURSOR, "write cursor" },
00256 { DBC_WRITEDUP, "internally dup'ed write cursor" },
00257 { DBC_WRITER, "short-term write cursor" },
00258 { 0, NULL }
00259 };
00260 DBC *dbc;
00261 DBC_INTERNAL *cp;
00262 char *s;
00263
00264 MUTEX_THREAD_LOCK(dbp->mutexp);
00265 for (dbc = TAILQ_FIRST(&dbp->active_queue);
00266 dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
00267 switch (dbc->dbtype) {
00268 case DB_BTREE:
00269 s = "btree";
00270 break;
00271 case DB_HASH:
00272 s = "hash";
00273 break;
00274 case DB_RECNO:
00275 s = "recno";
00276 break;
00277 case DB_QUEUE:
00278 s = "queue";
00279 break;
00280 default:
00281 DB_ASSERT(0);
00282 return (1);
00283 }
00284 cp = dbc->internal;
00285 fprintf(stderr, "%s/%#0lx: opd: %#0lx\n",
00286 s, P_TO_ULONG(dbc), P_TO_ULONG(cp->opd));
00287 fprintf(stderr, "\ttxn: %#0lx lid: %lu locker: %lu\n",
00288 P_TO_ULONG(dbc->txn),
00289 (u_long)dbc->lid, (u_long)dbc->locker);
00290 fprintf(stderr, "\troot: %lu page/index: %lu/%lu",
00291 (u_long)cp->root, (u_long)cp->pgno, (u_long)cp->indx);
00292 CDB___db_prflags(dbc->flags, fn, stderr);
00293 fprintf(stderr, "\n");
00294
00295 if (dbp->type == DB_BTREE)
00296 CDB___bam_cprint(dbc);
00297 }
00298 for (dbc = TAILQ_FIRST(&dbp->free_queue);
00299 dbc != NULL; dbc = TAILQ_NEXT(dbc, links))
00300 fprintf(stderr, "free: %#0lx ", P_TO_ULONG(dbc));
00301 fprintf(stderr, "\n");
00302 MUTEX_THREAD_UNLOCK(dbp->mutexp);
00303
00304 return (0);
00305 }
00306 #endif
00307
00308
00309
00310
00311
00312
00313
00314 int
00315 CDB___db_fd(dbp, fdp)
00316 DB *dbp;
00317 int *fdp;
00318 {
00319 DB_FH *fhp;
00320 int ret;
00321
00322 PANIC_CHECK(dbp->dbenv);
00323 DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->fd");
00324
00325
00326
00327
00328
00329 if ((ret = CDB___mp_xxx_fh(dbp->mpf, &fhp)) != 0)
00330 return (ret);
00331
00332 if (F_ISSET(fhp, DB_FH_VALID)) {
00333 *fdp = fhp->fd;
00334 return (0);
00335 } else {
00336 *fdp = -1;
00337 CDB___db_err(dbp->dbenv, "DB does not have a valid file handle.");
00338 return (ENOENT);
00339 }
00340 }
00341
00342
00343
00344
00345
00346
00347
00348 int
00349 CDB___db_get(dbp, txn, key, data, flags)
00350 DB *dbp;
00351 DB_TXN *txn;
00352 DBT *key, *data;
00353 u_int32_t flags;
00354 {
00355 DBC *dbc;
00356 int ret, t_ret;
00357
00358 PANIC_CHECK(dbp->dbenv);
00359 DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->get");
00360
00361 if ((ret = CDB___db_getchk(dbp, key, data, flags)) != 0)
00362 return (ret);
00363
00364 if ((ret = dbp->cursor(dbp, txn, &dbc, 0)) != 0)
00365 return (ret);
00366
00367 DEBUG_LREAD(dbc, txn, "CDB___db_get", key, NULL, flags);
00368
00369 ret = dbc->c_get(dbc, key, data,
00370 flags == 0 || flags == DB_RMW ? flags | DB_SET : flags);
00371
00372 if ((t_ret = CDB___db_c_close(dbc)) != 0 && ret == 0)
00373 ret = t_ret;
00374
00375 #ifdef DEBUG
00376 switch(flags) {
00377 case 0:
00378 word_monitor_add(DB_MONITOR(dbp->dbenv), WORD_MONITOR_GET, 1);
00379 break;
00380 case DB_NEXT:
00381 word_monitor_add(DB_MONITOR(dbp->dbenv), WORD_MONITOR_GET_NEXT, 1);
00382 break;
00383 case DB_SET_RANGE:
00384 word_monitor_add(DB_MONITOR(dbp->dbenv), WORD_MONITOR_GET_SET_RANGE, 1);
00385 break;
00386 default:
00387 word_monitor_add(DB_MONITOR(dbp->dbenv), WORD_MONITOR_GET_OTHER, 1);
00388 break;
00389 }
00390 #endif
00391 return (ret);
00392 }
00393
00394
00395
00396
00397
00398
00399
00400 int
00401 CDB___db_put(dbp, txn, key, data, flags)
00402 DB *dbp;
00403 DB_TXN *txn;
00404 DBT *key, *data;
00405 u_int32_t flags;
00406 {
00407 DBC *dbc;
00408 DBT tdata;
00409 int ret, t_ret;
00410
00411 PANIC_CHECK(dbp->dbenv);
00412 DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->put");
00413
00414 if ((ret = CDB___db_putchk(dbp, key, data,
00415 flags, F_ISSET(dbp, DB_AM_RDONLY),
00416 F_ISSET(dbp, DB_AM_DUP) || F_ISSET(key, DB_DBT_DUPOK))) != 0)
00417 return (ret);
00418
00419 if ((ret = dbp->cursor(dbp, txn, &dbc, DB_WRITELOCK)) != 0)
00420 return (ret);
00421
00422 DEBUG_LWRITE(dbc, txn, "CDB___db_put", key, data, flags);
00423
00424 if (flags == DB_NOOVERWRITE) {
00425 flags = 0;
00426
00427
00428
00429
00430
00431 memset(&tdata, 0, sizeof(tdata));
00432 F_SET(&tdata, DB_DBT_USERMEM | DB_DBT_PARTIAL);
00433
00434
00435
00436
00437
00438 if ((ret = dbc->c_get(dbc, key, &tdata,
00439 DB_SET | (STD_LOCKING(dbc) ? DB_RMW : 0))) == 0)
00440 ret = DB_KEYEXIST;
00441 else if (ret == DB_NOTFOUND)
00442 ret = 0;
00443 }
00444 if (ret == 0)
00445 ret = dbc->c_put(dbc,
00446 key, data, flags == 0 ? DB_KEYLAST : flags);
00447
00448 if ((t_ret = CDB___db_c_close(dbc)) != 0 && ret == 0)
00449 ret = t_ret;
00450
00451 #ifdef DEBUG
00452 word_monitor_add(DB_MONITOR(dbp->dbenv), WORD_MONITOR_PUT, 1);
00453 #endif
00454
00455 return (ret);
00456 }
00457
00458
00459
00460
00461
00462
00463
00464 int
00465 CDB___db_sync(dbp, flags)
00466 DB *dbp;
00467 u_int32_t flags;
00468 {
00469 int ret, t_ret;
00470
00471 PANIC_CHECK(dbp->dbenv);
00472 DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->sync");
00473
00474 if ((ret = CDB___db_syncchk(dbp, flags)) != 0)
00475 return (ret);
00476
00477
00478 if (F_ISSET(dbp, DB_AM_RDONLY))
00479 return (0);
00480
00481
00482 if (dbp->type == DB_RECNO)
00483 ret = CDB___ram_writeback(dbp);
00484
00485
00486 if (F_ISSET(dbp, DB_AM_INMEM))
00487 return (0);
00488
00489
00490 if ((t_ret = CDB_memp_fsync(dbp->mpf)) != 0 && ret == 0)
00491 ret = t_ret;
00492 return (ret);
00493 }