00001
00002
00003
00004
00005
00006
00007
00008 #include "config.h"
00009
00010 #ifndef lint
00011 static const char revid[] = "$Id: bt__recno_8c-source.html,v 1.1 2008/06/08 10:13:41 sebdiaz Exp $";
00012 #endif
00013
00014 #ifndef NO_SYSTEM_INCLUDES
00015 #include <sys/types.h>
00016
00017 #include <errno.h>
00018 #include <limits.h>
00019 #include <string.h>
00020 #endif
00021
00022 #include "db_int.h"
00023 #include "db_page.h"
00024 #include "btree.h"
00025 #include "db_ext.h"
00026 #include "db_shash.h"
00027 #include "lock.h"
00028 #include "lock_ext.h"
00029 #include "qam.h"
00030
00031 static int __ram_add __P((DBC *, db_recno_t *, DBT *, u_int32_t, u_int32_t));
00032 static void __ram_ca __P((DBC *, db_recno_t, ca_recno_arg));
00033 static int __ram_delete __P((DB *, DB_TXN *, DBT *, u_int32_t));
00034 static int __ram_fmap __P((DBC *, db_recno_t));
00035 static int __ram_put __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
00036 static int __ram_source __P((DB *));
00037 static int __ram_update __P((DBC *, db_recno_t, int));
00038 static int __ram_vmap __P((DBC *, db_recno_t));
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 #define CD_SET(dbp, cp) { \
00058 if (F_ISSET(cp, C_RENUMBER)) \
00059 F_SET(cp, C_DELETED); \
00060 }
00061 #define CD_CLR(dbp, cp) { \
00062 if (F_ISSET(cp, C_RENUMBER)) \
00063 F_CLR(cp, C_DELETED); \
00064 }
00065 #define CD_ISSET(dbp, cp) \
00066 (F_ISSET(cp, C_RENUMBER) && F_ISSET(cp, C_DELETED))
00067
00068
00069
00070
00071
00072
00073
00074 int
00075 CDB___ram_open(dbp, name, base_pgno, flags)
00076 DB *dbp;
00077 const char *name;
00078 db_pgno_t base_pgno;
00079 u_int32_t flags;
00080 {
00081 BTREE *t;
00082 DBC *dbc;
00083 int ret, t_ret;
00084
00085 t = dbp->bt_internal;
00086
00087
00088 dbp->del = __ram_delete;
00089 dbp->put = __ram_put;
00090 dbp->stat = CDB___bam_stat;
00091
00092
00093 if ((ret = CDB___bam_read_root(dbp, name, base_pgno, flags)) != 0)
00094 goto err;
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 if (t->re_source != NULL && (ret = __ram_source(dbp)) != 0)
00105 goto err;
00106
00107
00108 if (F_ISSET(dbp, DB_RE_SNAPSHOT)) {
00109
00110 if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0)
00111 goto err;
00112
00113
00114 if ((ret = __ram_update(dbc,
00115 DB_MAX_RECORDS, 0)) != 0 && ret == DB_NOTFOUND)
00116 ret = 0;
00117
00118
00119 if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
00120 ret = t_ret;
00121
00122 if (ret != 0)
00123 goto err;
00124 }
00125
00126 return (0);
00127
00128 err:
00129 if (t->re_smap != NULL)
00130 (void)CDB___os_unmapfile(dbp->dbenv, t->re_smap, t->re_msize);
00131
00132
00133 if (F_ISSET(&t->re_fh, DB_FH_VALID))
00134 (void)CDB___os_closehandle(&t->re_fh);
00135 if (t->re_source != NULL)
00136 CDB___os_freestr(t->re_source);
00137
00138 return (ret);
00139 }
00140
00141
00142
00143
00144
00145 static int
00146 __ram_delete(dbp, txn, key, flags)
00147 DB *dbp;
00148 DB_TXN *txn;
00149 DBT *key;
00150 u_int32_t flags;
00151 {
00152 BTREE_CURSOR *cp;
00153 DBC *dbc;
00154 db_recno_t recno;
00155 int ret, t_ret;
00156
00157 PANIC_CHECK(dbp->dbenv);
00158
00159
00160 if ((ret = CDB___db_delchk(dbp,
00161 key, flags, F_ISSET(dbp, DB_AM_RDONLY))) != 0)
00162 return (ret);
00163
00164
00165 if ((ret = dbp->cursor(dbp, txn, &dbc, DB_WRITELOCK)) != 0)
00166 return (ret);
00167
00168 DEBUG_LWRITE(dbc, txn, "ram_delete", key, NULL, flags);
00169
00170
00171 if ((ret = CDB___ram_getno(dbc, key, &recno, 0)) != 0)
00172 goto err;
00173
00174
00175 cp = (BTREE_CURSOR *)dbc->internal;
00176 cp->recno = recno;
00177
00178 ret = CDB___ram_c_del(dbc);
00179
00180
00181 err: if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
00182 ret = t_ret;
00183
00184 return (ret);
00185 }
00186
00187
00188
00189
00190
00191 static int
00192 __ram_put(dbp, txn, key, data, flags)
00193 DB *dbp;
00194 DB_TXN *txn;
00195 DBT *key, *data;
00196 u_int32_t flags;
00197 {
00198 DBC *dbc;
00199 db_recno_t recno;
00200 int ret, t_ret;
00201
00202 PANIC_CHECK(dbp->dbenv);
00203
00204
00205 if ((ret = CDB___db_putchk(dbp,
00206 key, data, flags, F_ISSET(dbp, DB_AM_RDONLY), 0)) != 0)
00207 return (ret);
00208
00209
00210 if ((ret = dbp->cursor(dbp, txn, &dbc, DB_WRITELOCK)) != 0)
00211 return (ret);
00212
00213 DEBUG_LWRITE(dbc, txn, "ram_put", key, data, flags);
00214
00215
00216
00217
00218
00219
00220 if (flags == DB_APPEND) {
00221 if ((ret = __ram_update(
00222 dbc, DB_MAX_RECORDS, 0)) != 0 && ret == DB_NOTFOUND)
00223 ret = 0;
00224 } else
00225 ret = CDB___ram_getno(dbc, key, &recno, 1);
00226
00227
00228 if (ret == 0)
00229 ret = __ram_add(dbc, &recno, data, flags, 0);
00230
00231
00232 if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
00233 ret = t_ret;
00234
00235
00236 if (ret == 0 && flags == DB_APPEND)
00237 ret = CDB___db_retcopy(dbp, key, &recno, sizeof(recno),
00238 &dbc->rkey.data, &dbc->rkey.ulen);
00239
00240 return (ret);
00241 }
00242
00243
00244
00245
00246
00247
00248
00249 int
00250 CDB___ram_c_del(dbc)
00251 DBC *dbc;
00252 {
00253 BKEYDATA bk;
00254 BTREE *t;
00255 BTREE_CURSOR *cp;
00256 DB *dbp;
00257 DBT hdr, data;
00258 EPG *epg;
00259 int exact, ret, stack;
00260
00261 dbp = dbc->dbp;
00262 cp = (BTREE_CURSOR *)dbc->internal;
00263 t = dbp->bt_internal;
00264 stack = 0;
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280 if ((ret = CDB___bam_rsearch(dbc, &cp->recno, S_DELETE, 1, &exact)) != 0)
00281 goto err;
00282 if (!exact) {
00283 ret = DB_NOTFOUND;
00284 goto err;
00285 }
00286 stack = 1;
00287 cp->page = cp->csp->page;
00288 cp->pgno = cp->csp->page->pgno;
00289 cp->indx = cp->csp->indx;
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302 if (B_DISSET(GET_BKEYDATA(cp->page, cp->indx)->type)) {
00303 ret = DB_KEYEMPTY;
00304 goto err;
00305 }
00306
00307 if (F_ISSET(cp, C_RENUMBER)) {
00308
00309 if ((ret = CDB___bam_ditem(dbc, cp->page, cp->indx)) != 0)
00310 goto err;
00311 CDB___bam_adjust(dbc, -1);
00312 __ram_ca(dbc, cp->recno, CA_DELETE);
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327 if (NUM_ENT(cp->page) == 0 && PGNO(cp->page) != cp->root) {
00328
00329
00330
00331
00332
00333
00334 for (epg = cp->sp; epg <= cp->csp; ++epg)
00335 if (NUM_ENT(epg->page) <= 1)
00336 break;
00337
00338
00339
00340
00341
00342 ret = CDB___bam_dpages(dbc, --epg);
00343
00344
00345
00346
00347
00348 stack = 0;
00349 cp->page = NULL;
00350 }
00351 } else {
00352
00353 if ((ret = CDB___bam_ditem(dbc, cp->page, cp->indx)) != 0)
00354 goto err;
00355
00356 B_TSET(bk.type, B_KEYDATA, 1);
00357 bk.len = 0;
00358 memset(&hdr, 0, sizeof(hdr));
00359 hdr.data = &bk;
00360 hdr.size = SSZA(BKEYDATA, data);
00361 memset(&data, 0, sizeof(data));
00362 data.data = (void *)"";
00363 data.size = 0;
00364 if ((ret = CDB___db_pitem(dbc,
00365 cp->page, cp->indx, BKEYDATA_SIZE(0), &hdr, &data)) != 0)
00366 goto err;
00367 }
00368
00369 F_SET(t, RECNO_MODIFIED);
00370
00371 err: if (stack)
00372 CDB___bam_stkrel(dbc, STK_CLRDBC);
00373
00374 return (ret);
00375 }
00376
00377
00378
00379
00380
00381
00382
00383
00384 int
00385 CDB___ram_c_get(dbc, key, data, flags, pgnop)
00386 DBC *dbc;
00387 DBT *key, *data;
00388 u_int32_t flags;
00389 db_pgno_t *pgnop;
00390 {
00391 BTREE_CURSOR *cp;
00392 DB *dbp;
00393 int cmp, exact, ret;
00394
00395 COMPQUIET(pgnop, NULL);
00396
00397 dbp = dbc->dbp;
00398 cp = (BTREE_CURSOR *)dbc->internal;
00399
00400 retry: switch (flags) {
00401 case DB_CURRENT:
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412 if (F_ISSET(dbc, DBC_OPD) && F_ISSET(cp, C_DELETED))
00413 return (DB_KEYEMPTY);
00414 break;
00415 case DB_NEXT_DUP:
00416
00417
00418
00419
00420
00421
00422 if (!F_ISSET(dbc, DBC_OPD))
00423 return (DB_NOTFOUND);
00424
00425 case DB_NEXT_NODUP:
00426
00427
00428
00429
00430
00431 case DB_NEXT:
00432 flags = DB_NEXT;
00433
00434
00435
00436
00437
00438 if (CD_ISSET(dbp, cp))
00439 break;
00440
00441 if (cp->recno != RECNO_OOB) {
00442 ++cp->recno;
00443 break;
00444 }
00445
00446 case DB_FIRST:
00447 flags = DB_NEXT;
00448 cp->recno = 1;
00449 break;
00450 case DB_PREV_NODUP:
00451
00452
00453
00454
00455
00456 case DB_PREV:
00457 flags = DB_PREV;
00458 if (cp->recno != RECNO_OOB) {
00459 if (cp->recno == 1) {
00460 ret = DB_NOTFOUND;
00461 goto err;
00462 }
00463 --cp->recno;
00464 break;
00465 }
00466
00467 case DB_LAST:
00468 flags = DB_PREV;
00469 if (((ret = __ram_update(dbc,
00470 DB_MAX_RECORDS, 0)) != 0) && ret != DB_NOTFOUND)
00471 goto err;
00472 if ((ret = CDB___bam_nrecs(dbc, &cp->recno)) != 0)
00473 goto err;
00474 if (cp->recno == 0) {
00475 ret = DB_NOTFOUND;
00476 goto err;
00477 }
00478 break;
00479 case DB_GET_BOTHC:
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489 if (F_ISSET(dbc, DBC_OPD)) {
00490 cp->recno++;
00491 break;
00492 } else
00493 ret = DB_NOTFOUND;
00494 goto err;
00495
00496 case DB_GET_BOTH:
00497
00498
00499
00500
00501
00502
00503 if (F_ISSET(dbc, DBC_OPD)) {
00504 cp->recno = 1;
00505 break;
00506 }
00507
00508 case DB_SET:
00509 case DB_SET_RANGE:
00510 if ((ret = CDB___ram_getno(dbc, key, &cp->recno, 0)) != 0)
00511 goto err;
00512 break;
00513 default:
00514 ret = CDB___db_unknown_flag(dbp->dbenv, "CDB___ram_c_get", flags);
00515 goto err;
00516 }
00517
00518
00519
00520
00521
00522
00523
00524
00525 if ((flags == DB_NEXT || flags == DB_CURRENT) && ((ret =
00526 __ram_update(dbc, cp->recno, 0)) != 0) && ret != DB_NOTFOUND)
00527 goto err;
00528
00529 for (;; ++cp->recno) {
00530
00531 if ((ret = CDB___bam_rsearch(dbc, &cp->recno,
00532 F_ISSET(dbc, DBC_RMW) ? S_FIND_WR : S_FIND,
00533 1, &exact)) != 0)
00534 goto err;
00535 if (!exact) {
00536 ret = DB_NOTFOUND;
00537 goto err;
00538 }
00539
00540
00541
00542
00543
00544 cp->page = cp->csp->page;
00545 cp->pgno = cp->csp->page->pgno;
00546 cp->indx = cp->csp->indx;
00547 (void)__TLPUT(dbc, cp->lock);
00548 cp->lock = cp->csp->lock;
00549 cp->lock_mode = cp->csp->lock_mode;
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560 if (B_DISSET(GET_BKEYDATA(cp->page, cp->indx)->type))
00561 switch (flags) {
00562 case DB_NEXT:
00563 case DB_PREV:
00564 (void)CDB___bam_stkrel(dbc, STK_CLRDBC);
00565 goto retry;
00566 case DB_GET_BOTH:
00567 (void)CDB___bam_stkrel(dbc, STK_CLRDBC);
00568 continue;
00569 default:
00570 ret = DB_KEYEMPTY;
00571 goto err;
00572 }
00573
00574 if (flags == DB_GET_BOTH || flags == DB_GET_BOTHC) {
00575 if ((ret = CDB___bam_cmp(dbp, data,
00576 cp->page, cp->indx, CDB___bam_defcmp, &cmp)) != 0)
00577 return (ret);
00578 if (cmp == 0)
00579 break;
00580 if (!F_ISSET(dbc, DBC_OPD)) {
00581 ret = DB_NOTFOUND;
00582 goto err;
00583 }
00584 (void)CDB___bam_stkrel(dbc, STK_CLRDBC);
00585 } else
00586 break;
00587 }
00588
00589
00590 if (!F_ISSET(dbc, DBC_OPD)) {
00591 if (flags != DB_SET && flags != DB_SET_RANGE)
00592 ret = CDB___db_retcopy(dbp,
00593 key, &cp->recno, sizeof(cp->recno),
00594 &dbc->rkey.data, &dbc->rkey.ulen);
00595 F_SET(key, DB_DBT_ISSET);
00596 }
00597
00598
00599 err: CD_CLR(dbp, cp);
00600
00601 return (ret);
00602 }
00603
00604
00605
00606
00607
00608
00609
00610 int
00611 CDB___ram_c_put(dbc, key, data, flags, pgnop)
00612 DBC *dbc;
00613 DBT *key, *data;
00614 u_int32_t flags;
00615 db_pgno_t *pgnop;
00616 {
00617 BTREE_CURSOR *cp;
00618 DB *dbp;
00619 int exact, ret, t_ret;
00620 void *arg;
00621
00622 COMPQUIET(pgnop, NULL);
00623
00624 dbp = dbc->dbp;
00625 cp = (BTREE_CURSOR *)dbc->internal;
00626
00627
00628
00629
00630
00631
00632 switch (flags) {
00633 case DB_KEYFIRST:
00634 cp->recno = 1;
00635 flags = DB_BEFORE;
00636 break;
00637 case DB_KEYLAST:
00638 return (__ram_add(dbc, &cp->recno, data, DB_APPEND, 0));
00639 }
00640
00641 split: if ((ret = CDB___bam_rsearch(dbc, &cp->recno, S_INSERT, 1, &exact)) != 0)
00642 goto err;
00643 if (!exact) {
00644 ret = DB_NOTFOUND;
00645 goto err;
00646 }
00647 cp->page = cp->csp->page;
00648 cp->pgno = cp->csp->page->pgno;
00649 cp->indx = cp->csp->indx;
00650
00651 ret = CDB___bam_iitem(dbc, key, data, flags, 0);
00652 t_ret = CDB___bam_stkrel(dbc, STK_CLRDBC);
00653
00654 if (t_ret != 0 && (ret == 0 || ret == DB_NEEDSPLIT))
00655 ret = t_ret;
00656 else if (ret == DB_NEEDSPLIT) {
00657 arg = &cp->recno;
00658 if ((ret = CDB___bam_split(dbc, arg)) != 0)
00659 goto err;
00660 goto split;
00661 }
00662 if (ret != 0)
00663 goto err;
00664
00665 switch (flags) {
00666 case DB_AFTER:
00667 __ram_ca(dbc, cp->recno, CA_IAFTER);
00668 ++cp->recno;
00669 break;
00670 case DB_BEFORE:
00671 __ram_ca(dbc, cp->recno, CA_IBEFORE);
00672 --cp->recno;
00673 break;
00674 }
00675
00676
00677 if (!F_ISSET(dbc, DBC_OPD) && (flags == DB_AFTER || flags == DB_BEFORE))
00678 ret = CDB___db_retcopy(dbp, key, &cp->recno,
00679 sizeof(cp->recno), &dbc->rkey.data, &dbc->rkey.ulen);
00680
00681
00682 err: CD_CLR(dbp, cp);
00683
00684 return (ret);
00685 }
00686
00687
00688
00689
00690
00691 static void
00692 __ram_ca(dbc_arg, recno, op)
00693 DBC *dbc_arg;
00694 db_recno_t recno;
00695 ca_recno_arg op;
00696 {
00697 BTREE_CURSOR *cp;
00698 DB *dbp;
00699 DBC *dbc;
00700 db_recno_t nrecs;
00701
00702 dbp = dbc_arg->dbp;
00703
00704
00705
00706
00707 MUTEX_THREAD_LOCK(dbp->mutexp);
00708 for (dbc = TAILQ_FIRST(&dbp->active_queue);
00709 dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
00710 cp = (BTREE_CURSOR *)dbc->internal;
00711 if (dbc_arg->internal->root != cp->root)
00712 continue;
00713
00714 switch (op) {
00715 case CA_DELETE:
00716 if (recno < cp->recno)
00717 --cp->recno;
00718 if (recno == cp->recno) {
00719
00720
00721
00722
00723
00724 if (!F_ISSET(dbc, DBC_OPD) &&
00725 CDB___bam_nrecs(dbc, &nrecs) == 0 &&
00726 recno > nrecs)
00727 --cp->recno;
00728 else
00729 CD_SET(dbp, cp);
00730 }
00731 break;
00732 case CA_IAFTER:
00733 if (recno < cp->recno)
00734 ++cp->recno;
00735 break;
00736 case CA_IBEFORE:
00737 if (recno <= cp->recno)
00738 ++cp->recno;
00739 break;
00740 }
00741 }
00742 MUTEX_THREAD_UNLOCK(dbp->mutexp);
00743 }
00744
00745
00746
00747
00748
00749
00750
00751 int
00752 CDB___ram_getno(dbc, key, rep, can_create)
00753 DBC *dbc;
00754 const DBT *key;
00755 db_recno_t *rep;
00756 int can_create;
00757 {
00758 DB *dbp;
00759 db_recno_t recno;
00760
00761 dbp = dbc->dbp;
00762
00763
00764 if ((recno = *(db_recno_t *)key->data) == 0) {
00765 CDB___db_err(dbp->dbenv, "illegal record number of 0");
00766 return (EINVAL);
00767 }
00768 if (rep != NULL)
00769 *rep = recno;
00770
00771
00772
00773
00774
00775 return (dbc->dbtype == DB_RECNO ?
00776 __ram_update(dbc, recno, can_create) : 0);
00777 }
00778
00779
00780
00781
00782
00783 static int
00784 __ram_update(dbc, recno, can_create)
00785 DBC *dbc;
00786 db_recno_t recno;
00787 int can_create;
00788 {
00789 BTREE *t;
00790 BTREE_CURSOR *cp;
00791 DB *dbp;
00792 db_recno_t nrecs;
00793 int ret;
00794
00795 dbp = dbc->dbp;
00796 cp = (BTREE_CURSOR *)dbc->internal;
00797 t = dbp->bt_internal;
00798
00799
00800
00801
00802
00803 if (!can_create && !F_ISSET(t, RECNO_READFILE))
00804 return (0);
00805
00806
00807
00808
00809
00810 if ((ret = CDB___bam_nrecs(dbc, &nrecs)) != 0)
00811 return (ret);
00812 if (F_ISSET(t, RECNO_READFILE) && recno > nrecs) {
00813 if ((ret = t->re_irec(dbc, recno)) != 0)
00814 return (ret);
00815 if ((ret = CDB___bam_nrecs(dbc, &nrecs)) != 0)
00816 return (ret);
00817 }
00818
00819
00820
00821
00822
00823 if (!can_create || recno <= nrecs + 1)
00824 return (0);
00825
00826 dbc->rdata.dlen = 0;
00827 dbc->rdata.doff = 0;
00828 dbc->rdata.flags = 0;
00829 if (F_ISSET(dbp, DB_RE_FIXEDLEN)) {
00830 if (dbc->rdata.ulen < t->re_len) {
00831 if ((ret = CDB___os_realloc(dbp->dbenv,
00832 t->re_len, NULL, &dbc->rdata.data)) != 0) {
00833 dbc->rdata.ulen = 0;
00834 dbc->rdata.data = NULL;
00835 return (ret);
00836 }
00837 dbc->rdata.ulen = t->re_len;
00838 }
00839 dbc->rdata.size = t->re_len;
00840 memset(dbc->rdata.data, t->re_pad, t->re_len);
00841 } else
00842 dbc->rdata.size = 0;
00843
00844 while (recno > ++nrecs)
00845 if ((ret = __ram_add(dbc,
00846 &nrecs, &dbc->rdata, 0, BI_DELETED)) != 0)
00847 return (ret);
00848 return (0);
00849 }
00850
00851
00852
00853
00854
00855 static int
00856 __ram_source(dbp)
00857 DB *dbp;
00858 {
00859 BTREE *t;
00860 size_t size;
00861 u_int32_t bytes, mbytes;
00862 char *source;
00863 int ret;
00864
00865 t = dbp->bt_internal;
00866 source = t->re_source;
00867
00868
00869
00870
00871
00872
00873 ret = CDB___db_appname(dbp->dbenv,
00874 DB_APP_DATA, NULL, source, 0, NULL, &t->re_source);
00875
00876 CDB___os_freestr(source);
00877
00878 if (ret != 0)
00879 return (ret);
00880
00881
00882
00883
00884
00885
00886
00887 ret = CDB___os_open(dbp->dbenv, t->re_source,
00888 F_ISSET(dbp, DB_AM_RDONLY) ? DB_OSO_RDONLY : 0, 0, &t->re_fh);
00889 if (ret != 0 && !F_ISSET(dbp, DB_AM_RDONLY))
00890 ret = CDB___os_open(dbp->dbenv,
00891 t->re_source, DB_OSO_RDONLY, 0, &t->re_fh);
00892 if (ret != 0) {
00893 CDB___db_err(dbp->dbenv, "%s: %s", t->re_source, CDB_db_strerror(ret));
00894 return (ret);
00895 }
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905 if ((ret = CDB___os_ioinfo(dbp->dbenv, t->re_source,
00906 &t->re_fh, &mbytes, &bytes, NULL)) != 0) {
00907 CDB___db_err(dbp->dbenv, "%s: %s", t->re_source, CDB_db_strerror(ret));
00908 return (ret);
00909 }
00910 if (mbytes == 0 && bytes == 0)
00911 return (0);
00912
00913 size = mbytes * MEGABYTE + bytes;
00914 if ((ret = CDB___os_mapfile(dbp->dbenv, t->re_source,
00915 &t->re_fh, (size_t)size, 1, &t->re_smap)) != 0)
00916 return (ret);
00917 t->re_cmap = t->re_smap;
00918 t->re_emap = (u_int8_t *)t->re_smap + (t->re_msize = size);
00919 t->re_irec = F_ISSET(dbp, DB_RE_FIXEDLEN) ? __ram_fmap : __ram_vmap;
00920 F_SET(t, RECNO_READFILE);
00921 return (0);
00922 }
00923
00924
00925
00926
00927
00928
00929
00930 int
00931 CDB___ram_writeback(dbp)
00932 DB *dbp;
00933 {
00934 BTREE *t;
00935 DB_ENV *dbenv;
00936 DB_FH fh;
00937 DBC *dbc;
00938 DBT key, data;
00939 db_recno_t keyno;
00940 size_t nw;
00941 int ret, t_ret;
00942 u_int8_t delim, *pad;
00943
00944 t = dbp->bt_internal;
00945 dbenv = dbp->dbenv;
00946
00947
00948 if (!F_ISSET(t, RECNO_MODIFIED))
00949 return (0);
00950
00951
00952 if (t->re_source == NULL) {
00953 F_CLR(t, RECNO_MODIFIED);
00954 return (0);
00955 }
00956
00957
00958 if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0)
00959 return (ret);
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978 if ((ret =
00979 __ram_update(dbc, DB_MAX_RECORDS, 0)) != 0 && ret != DB_NOTFOUND)
00980 return (ret);
00981
00982
00983
00984
00985
00986
00987
00988 if (t->re_smap != NULL) {
00989 (void)CDB___os_unmapfile(dbenv, t->re_smap, t->re_msize);
00990 t->re_smap = NULL;
00991 }
00992
00993
00994 if (F_ISSET(&t->re_fh, DB_FH_VALID))
00995 (void)CDB___os_closehandle(&t->re_fh);
00996
00997
00998 if ((ret = CDB___os_open(dbenv,
00999 t->re_source, DB_OSO_SEQ | DB_OSO_TRUNC, 0, &fh)) != 0) {
01000 CDB___db_err(dbenv, "%s: %s", t->re_source, CDB_db_strerror(ret));
01001 goto err;
01002 }
01003
01004
01005
01006
01007
01008
01009 memset(&key, 0, sizeof(key));
01010 memset(&data, 0, sizeof(data));
01011 key.size = sizeof(db_recno_t);
01012 key.data = &keyno;
01013
01014
01015
01016
01017
01018 delim = t->re_delim;
01019 if (F_ISSET(dbp, DB_RE_FIXEDLEN)) {
01020 if ((ret = CDB___os_malloc(dbenv, t->re_len, NULL, &pad)) != 0)
01021 goto err;
01022 memset(pad, t->re_pad, t->re_len);
01023 } else
01024 COMPQUIET(pad, NULL);
01025 for (keyno = 1;; ++keyno) {
01026 switch (ret = dbp->get(dbp, NULL, &key, &data, 0)) {
01027 case 0:
01028 if ((ret = CDB___os_write(dbenv,
01029 &fh, data.data, data.size, &nw)) != 0)
01030 goto err;
01031 if (nw != (size_t)data.size) {
01032 ret = EIO;
01033 goto write_err;
01034 }
01035 break;
01036 case DB_KEYEMPTY:
01037 if (F_ISSET(dbp, DB_RE_FIXEDLEN)) {
01038 if ((ret = CDB___os_write(dbenv,
01039 &fh, pad, t->re_len, &nw)) != 0)
01040 goto write_err;
01041 if (nw != (size_t)t->re_len) {
01042 ret = EIO;
01043 goto write_err;
01044 }
01045 }
01046 break;
01047 case DB_NOTFOUND:
01048 ret = 0;
01049 goto done;
01050 }
01051 if (!F_ISSET(dbp, DB_RE_FIXEDLEN)) {
01052 if ((ret = CDB___os_write(dbenv, &fh, &delim, 1, &nw)) != 0)
01053 goto write_err;
01054 if (nw != 1) {
01055 ret = EIO;
01056 write_err: CDB___db_err(dbp->dbenv,
01057 "Write failed to backing file");
01058 goto err;
01059 }
01060 }
01061 }
01062
01063 err:
01064 done:
01065 if (F_ISSET(&fh, DB_FH_VALID) &&
01066 (t_ret = CDB___os_closehandle(&fh)) != 0 && ret == 0)
01067 ret = t_ret;
01068
01069
01070 if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
01071 ret = t_ret;
01072
01073 if (ret == 0)
01074 F_CLR(t, RECNO_MODIFIED);
01075
01076 return (ret);
01077 }
01078
01079
01080
01081
01082
01083 static int
01084 __ram_fmap(dbc, top)
01085 DBC *dbc;
01086 db_recno_t top;
01087 {
01088 BTREE *t;
01089 BTREE_CURSOR *cp;
01090 DB *dbp;
01091 DBT data;
01092 db_recno_t recno;
01093 u_int32_t len;
01094 u_int8_t *sp, *ep, *p;
01095 int is_modified, ret;
01096
01097 dbp = dbc->dbp;
01098 cp = (BTREE_CURSOR *)dbc->internal;
01099 t = dbp->bt_internal;
01100
01101 if ((ret = CDB___bam_nrecs(dbc, &recno)) != 0)
01102 return (ret);
01103
01104 if (dbc->rdata.ulen < t->re_len) {
01105 if ((ret = CDB___os_realloc(dbp->dbenv,
01106 t->re_len, NULL, &dbc->rdata.data)) != 0) {
01107 dbc->rdata.ulen = 0;
01108 dbc->rdata.data = NULL;
01109 return (ret);
01110 }
01111 dbc->rdata.ulen = t->re_len;
01112 }
01113
01114 is_modified = F_ISSET(t, RECNO_MODIFIED);
01115
01116 memset(&data, 0, sizeof(data));
01117 data.data = dbc->rdata.data;
01118 data.size = t->re_len;
01119
01120 sp = (u_int8_t *)t->re_cmap;
01121 ep = (u_int8_t *)t->re_emap;
01122 while (recno < top) {
01123 if (sp >= ep) {
01124 F_CLR(t, RECNO_READFILE);
01125 ret = DB_NOTFOUND;
01126 goto err;
01127 }
01128 len = t->re_len;
01129 for (p = dbc->rdata.data;
01130 sp < ep && len > 0; *p++ = *sp++, --len)
01131 ;
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143 if (t->re_last >= recno) {
01144 if (len != 0)
01145 memset(p, t->re_pad, len);
01146
01147 ++recno;
01148 if ((ret = __ram_add(dbc, &recno, &data, 0, 0)) != 0)
01149 goto err;
01150 }
01151 ++t->re_last;
01152 }
01153 t->re_cmap = sp;
01154
01155 err: if (!is_modified)
01156 F_CLR(t, RECNO_MODIFIED);
01157
01158 return (0);
01159 }
01160
01161
01162
01163
01164
01165 static int
01166 __ram_vmap(dbc, top)
01167 DBC *dbc;
01168 db_recno_t top;
01169 {
01170 BTREE *t;
01171 DBT data;
01172 db_recno_t recno;
01173 u_int8_t *sp, *ep;
01174 int delim, is_modified, ret;
01175
01176 t = dbc->dbp->bt_internal;
01177
01178 if ((ret = CDB___bam_nrecs(dbc, &recno)) != 0)
01179 return (ret);
01180
01181 delim = t->re_delim;
01182 is_modified = F_ISSET(t, RECNO_MODIFIED);
01183
01184 memset(&data, 0, sizeof(data));
01185
01186 sp = (u_int8_t *)t->re_cmap;
01187 ep = (u_int8_t *)t->re_emap;
01188 while (recno < top) {
01189 if (sp >= ep) {
01190 F_CLR(t, RECNO_READFILE);
01191 ret = DB_NOTFOUND;
01192 goto err;
01193 }
01194 for (data.data = sp; sp < ep && *sp != delim; ++sp)
01195 ;
01196
01197
01198
01199
01200
01201
01202
01203
01204 if (t->re_last >= recno) {
01205 data.size = sp - (u_int8_t *)data.data;
01206 ++recno;
01207 if ((ret = __ram_add(dbc, &recno, &data, 0, 0)) != 0)
01208 goto err;
01209 }
01210 ++t->re_last;
01211 ++sp;
01212 }
01213 t->re_cmap = sp;
01214
01215 err: if (!is_modified)
01216 F_CLR(t, RECNO_MODIFIED);
01217
01218 return (ret);
01219 }
01220
01221
01222
01223
01224
01225 static int
01226 __ram_add(dbc, recnop, data, flags, bi_flags)
01227 DBC *dbc;
01228 db_recno_t *recnop;
01229 DBT *data;
01230 u_int32_t flags, bi_flags;
01231 {
01232 BKEYDATA *bk;
01233 BTREE_CURSOR *cp;
01234 int exact, ret, stack;
01235
01236 cp = (BTREE_CURSOR *)dbc->internal;
01237
01238 retry:
01239 if ((ret = CDB___bam_rsearch(dbc, recnop,
01240 S_INSERT | (flags == DB_APPEND ? S_APPEND : 0), 1, &exact)) != 0)
01241 return (ret);
01242 stack = 1;
01243 cp->page = cp->csp->page;
01244 cp->pgno = cp->csp->page->pgno;
01245 cp->indx = cp->csp->indx;
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257 if (exact) {
01258 bk = GET_BKEYDATA(cp->page, cp->indx);
01259 if (!B_DISSET(bk->type) && flags == DB_NOOVERWRITE) {
01260 ret = DB_KEYEXIST;
01261 goto err;
01262 }
01263 }
01264
01265
01266
01267
01268
01269
01270
01271
01272 switch (ret = CDB___bam_iitem(dbc,
01273 NULL, data, exact ? DB_CURRENT : DB_BEFORE, bi_flags)) {
01274 case 0:
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290 break;
01291 case DB_NEEDSPLIT:
01292
01293 (void)CDB___bam_stkrel(dbc, STK_CLRDBC);
01294 stack = 0;
01295
01296 if ((ret = CDB___bam_split(dbc, recnop)) != 0)
01297 goto err;
01298
01299 goto retry;
01300
01301 default:
01302 goto err;
01303 }
01304
01305 err: if (stack)
01306 CDB___bam_stkrel(dbc, STK_CLRDBC);
01307
01308 return (ret);
01309 }