2 * See the file LICENSE for redistribution information.
4 * Copyright (c) 1997, 1998
5 * Sleepycat Software. All rights reserved.
11 static const char sccsid
[] = "@(#)bt_recno.c 10.37 (Sleepycat) 5/23/98";
14 #ifndef NO_SYSTEM_INCLUDES
15 #include <sys/types.h>
26 static int __ram_add
__P((DB
*, db_recno_t
*, DBT
*, u_int32_t
, u_int32_t
));
27 static int __ram_c_close
__P((DBC
*));
28 static int __ram_c_del
__P((DBC
*, u_int32_t
));
29 static int __ram_c_get
__P((DBC
*, DBT
*, DBT
*, u_int32_t
));
30 static int __ram_c_put
__P((DBC
*, DBT
*, DBT
*, u_int32_t
));
31 static int __ram_fmap
__P((DB
*, db_recno_t
));
32 static int __ram_get
__P((DB
*, DB_TXN
*, DBT
*, DBT
*, u_int32_t
));
33 static int __ram_iget
__P((DB
*, DBT
*, DBT
*));
34 static int __ram_put
__P((DB
*, DB_TXN
*, DBT
*, DBT
*, u_int32_t
));
35 static int __ram_source
__P((DB
*, RECNO
*, const char *));
36 static int __ram_sync
__P((DB
*, u_int32_t
));
37 static int __ram_update
__P((DB
*, db_recno_t
, int));
38 static int __ram_vmap
__P((DB
*, db_recno_t
));
39 static int __ram_writeback
__P((DB
*));
42 * If we're renumbering records, then we have to detect in the cursor that a
43 * record was deleted, and adjust the cursor as necessary. If not renumbering
44 * records, then we can detect this by looking at the actual record, so we
45 * ignore the cursor delete flag.
47 #define CD_SET(dbp, cp) { \
48 if (F_ISSET(dbp, DB_RE_RENUMBER)) \
49 F_SET(cp, CR_DELETED); \
51 #define CD_CLR(dbp, cp) { \
52 if (F_ISSET(dbp, DB_RE_RENUMBER)) \
53 F_CLR(cp, CR_DELETED); \
55 #define CD_ISSET(dbp, cp) \
56 (F_ISSET(dbp, DB_RE_RENUMBER) && F_ISSET(cp, CR_DELETED))
60 * Recno open function.
62 * PUBLIC: int __ram_open __P((DB *, DBTYPE, DB_INFO *));
65 __ram_open(dbp
, type
, dbinfo
)
74 COMPQUIET(type
, DB_RECNO
);
78 /* Allocate and initialize the private RECNO structure. */
79 if ((rp
= (RECNO
*)__db_calloc(1, sizeof(*rp
))) == NULL
)
84 * If the user specified a source tree, open it and map it in.
87 * We don't complain if the user specified transactions or
88 * threads. It's possible to make it work, but you'd better
89 * know what you're doing!
91 if (dbinfo
->re_source
== NULL
) {
96 __ram_source(dbp
, rp
, dbinfo
->re_source
)) != 0)
100 /* Copy delimiter, length and padding values. */
102 F_ISSET(dbp
, DB_RE_DELIMITER
) ? dbinfo
->re_delim
: '\n';
103 rp
->re_pad
= F_ISSET(dbp
, DB_RE_PAD
) ? dbinfo
->re_pad
: ' ';
105 if (F_ISSET(dbp
, DB_RE_FIXEDLEN
)) {
106 if ((rp
->re_len
= dbinfo
->re_len
) == 0) {
108 "record length must be greater than 0");
118 F_SET(rp
, RECNO_EOF
);
121 /* Open the underlying btree. */
122 if ((ret
= __bam_open(dbp
, DB_RECNO
, dbinfo
)) != 0)
125 /* Set the routines necessary to make it look like a recno tree. */
126 dbp
->cursor
= __ram_cursor
;
127 dbp
->del
= __ram_delete
;
128 dbp
->get
= __ram_get
;
129 dbp
->put
= __ram_put
;
130 dbp
->sync
= __ram_sync
;
132 /* Link in the private recno structure. */
133 ((BTREE
*)dbp
->internal
)->bt_recno
= rp
;
135 /* If we're snapshotting an underlying source file, do it now. */
136 if (dbinfo
!= NULL
&& F_ISSET(dbinfo
, DB_SNAPSHOT
))
137 if ((ret
= __ram_snapshot(dbp
)) != 0 && ret
!= DB_NOTFOUND
)
142 err
: /* If we mmap'd a source file, discard it. */
143 if (rp
->re_smap
!= NULL
)
144 (void)__db_unmapfile(rp
->re_smap
, rp
->re_msize
);
146 /* If we opened a source file, discard it. */
148 (void)__db_close(rp
->re_fd
);
149 if (rp
->re_source
!= NULL
)
150 FREES(rp
->re_source
);
152 /* If we allocated room for key/data return, discard it. */
154 if (t
!= NULL
&& t
->bt_rkey
.data
!= NULL
)
155 __db_free(t
->bt_rkey
.data
);
157 FREE(rp
, sizeof(*rp
));
164 * Recno db->cursor function.
166 * PUBLIC: int __ram_cursor __P((DB *, DB_TXN *, DBC **));
169 __ram_cursor(dbp
, txn
, dbcp
)
177 DEBUG_LWRITE(dbp
, txn
, "ram_cursor", NULL
, NULL
, 0);
179 if ((dbc
= (DBC
*)__db_calloc(1, sizeof(DBC
))) == NULL
)
181 if ((cp
= (RCURSOR
*)__db_calloc(1, sizeof(RCURSOR
))) == NULL
) {
187 cp
->recno
= RECNO_OOB
;
192 dbc
->c_close
= __ram_c_close
;
193 dbc
->c_del
= __ram_c_del
;
194 dbc
->c_get
= __ram_c_get
;
195 dbc
->c_put
= __ram_c_put
;
198 * All cursors are queued from the master DB structure. Add the
199 * cursor to that queue.
202 TAILQ_INSERT_HEAD(&dbp
->curs_queue
, dbc
, links
);
203 CURSOR_TEARDOWN(dbp
);
211 * Recno db->get function.
214 __ram_get(argdbp
, txn
, key
, data
, flags
)
223 DEBUG_LWRITE(argdbp
, txn
, "ram_get", key
, NULL
, flags
);
225 /* Check for invalid flags. */
226 if ((ret
= __db_getchk(argdbp
, key
, data
, flags
)) != 0)
229 GETHANDLE(argdbp
, txn
, &dbp
, ret
);
231 ret
= __ram_iget(dbp
, key
, data
);
239 * Internal ram get function, called for both standard and cursor
240 * get after the flags have been checked.
243 __ram_iget(dbp
, key
, data
)
251 int exact
, ret
, stack
;
256 /* Check the user's record number and fill in as necessary. */
257 if ((ret
= __ram_getno(dbp
, key
, &recno
, 0)) != 0)
260 /* Search the tree for the record. */
261 if ((ret
= __bam_rsearch(dbp
, &recno
, S_FIND
, 1, &exact
)) != 0)
264 return (DB_NOTFOUND
);
268 indx
= t
->bt_csp
->indx
;
270 /* If the record has already been deleted, we couldn't have found it. */
271 if (B_DISSET(GET_BKEYDATA(h
, indx
)->type
)) {
276 /* Return the data item. */
278 h
, indx
, data
, &t
->bt_rdata
.data
, &t
->bt_rdata
.ulen
);
281 done
: /* Discard the stack. */
290 * Recno db->put function.
293 __ram_put(argdbp
, txn
, key
, data
, flags
)
304 DEBUG_LWRITE(argdbp
, txn
, "ram_put", key
, data
, flags
);
306 /* Check for invalid flags. */
307 if ((ret
= __db_putchk(argdbp
,
308 key
, data
, flags
, F_ISSET(argdbp
, DB_AM_RDONLY
), 0)) != 0)
311 GETHANDLE(argdbp
, txn
, &dbp
, ret
);
314 * If we're appending to the tree, make sure we've read in all of
315 * the backing source file. Otherwise, check the user's record
316 * number and fill in as necessary.
318 ret
= LF_ISSET(DB_APPEND
) ?
319 __ram_snapshot(dbp
) : __ram_getno(dbp
, key
, &recno
, 1);
321 /* Add the record. */
323 ret
= __ram_add(dbp
, &recno
, data
, flags
, 0);
325 /* If we're appending to the tree, we have to return the record. */
326 if (ret
== 0 && LF_ISSET(DB_APPEND
)) {
328 ret
= __db_retcopy(key
, &recno
, sizeof(recno
),
329 &t
->bt_rkey
.data
, &t
->bt_rkey
.ulen
, dbp
->db_malloc
);
338 * Recno db->sync function.
341 __ram_sync(argdbp
, flags
)
348 DEBUG_LWRITE(argdbp
, NULL
, "ram_sync", NULL
, NULL
, flags
);
350 /* Sync the underlying btree. */
351 if ((ret
= __bam_sync(argdbp
, flags
)) != 0)
354 /* Copy back the backing source file. */
355 GETHANDLE(argdbp
, NULL
, &dbp
, ret
);
356 ret
= __ram_writeback(dbp
);
364 * Recno db->close function.
366 * PUBLIC: int __ram_close __P((DB *));
374 DEBUG_LWRITE(argdbp
, NULL
, "ram_close", NULL
, NULL
, 0);
376 rp
= ((BTREE
*)argdbp
->internal
)->bt_recno
;
378 /* Close any underlying mmap region. */
379 if (rp
->re_smap
!= NULL
)
380 (void)__db_unmapfile(rp
->re_smap
, rp
->re_msize
);
382 /* Close any backing source file descriptor. */
384 (void)__db_close(rp
->re_fd
);
386 /* Free any backing source file name. */
387 if (rp
->re_source
!= NULL
)
388 FREES(rp
->re_source
);
390 /* Free allocated memory. */
391 FREE(rp
, sizeof(RECNO
));
392 ((BTREE
*)argdbp
->internal
)->bt_recno
= NULL
;
394 /* Close the underlying btree. */
395 return (__bam_close(argdbp
));
400 * Recno cursor->close function.
406 DEBUG_LWRITE(dbc
->dbp
, dbc
->txn
, "ram_c_close", NULL
, NULL
, 0);
408 return (__ram_c_iclose(dbc
->dbp
, dbc
));
413 * Close a single cursor -- internal version.
415 * PUBLIC: int __ram_c_iclose __P((DB *, DBC *));
418 __ram_c_iclose(dbp
, dbc
)
422 /* Remove the cursor from the queue. */
424 TAILQ_REMOVE(&dbp
->curs_queue
, dbc
, links
);
425 CURSOR_TEARDOWN(dbp
);
427 /* Discard the structures. */
428 FREE(dbc
->internal
, sizeof(RCURSOR
));
429 FREE(dbc
, sizeof(DBC
));
436 * Recno cursor->c_del function.
439 __ram_c_del(dbc
, flags
)
447 DEBUG_LWRITE(dbc
->dbp
, dbc
->txn
, "ram_c_del", NULL
, NULL
, flags
);
451 /* Check for invalid flags. */
452 if ((ret
= __db_cdelchk(dbc
->dbp
, flags
,
453 F_ISSET(dbc
->dbp
, DB_AM_RDONLY
), cp
->recno
!= RECNO_OOB
)) != 0)
456 /* If already deleted, return failure. */
457 if (CD_ISSET(dbc
->dbp
, cp
))
458 return (DB_KEYEMPTY
);
460 /* Build a normal delete request. */
461 memset(&key
, 0, sizeof(key
));
462 key
.data
= &cp
->recno
;
463 key
.size
= sizeof(db_recno_t
);
464 if ((ret
= __ram_delete(dbc
->dbp
, dbc
->txn
, &key
, 0)) == 0)
465 CD_SET(dbc
->dbp
, cp
);
472 * Recno cursor->c_get function.
475 __ram_c_get(dbc
, key
, data
, flags
)
485 DEBUG_LREAD(dbc
->dbp
, dbc
->txn
, "ram_c_get",
486 flags
== DB_SET
|| flags
== DB_SET_RANGE
? key
: NULL
,
492 /* Check for invalid flags. */
493 if ((ret
= __db_cgetchk(dbc
->dbp
,
494 key
, data
, flags
, cp
->recno
!= RECNO_OOB
)) != 0)
497 GETHANDLE(dbc
->dbp
, dbc
->txn
, &dbp
, ret
);
500 /* Initialize the cursor for a new retrieval. */
503 retry
: /* Update the record number. */
506 if (CD_ISSET(dbp
, cp
)) {
508 return (DB_KEYEMPTY
);
512 if (CD_ISSET(dbp
, cp
))
514 if (cp
->recno
!= RECNO_OOB
) {
524 if (cp
->recno
!= RECNO_OOB
) {
526 return (DB_NOTFOUND
);
533 if (((ret
= __ram_snapshot(dbp
)) != 0) && ret
!= DB_NOTFOUND
)
535 if ((ret
= __bam_nrecs(dbp
, &cp
->recno
)) != 0)
538 return (DB_NOTFOUND
);
542 if ((ret
= __ram_getno(dbp
, key
, &cp
->recno
, 0)) != 0)
548 * Return the key if the user didn't give us one, and then pass it
551 if (flags
!= DB_SET
&& flags
!= DB_SET_RANGE
&&
552 (ret
= __db_retcopy(key
, &cp
->recno
, sizeof(cp
->recno
),
553 &t
->bt_rkey
.data
, &t
->bt_rkey
.ulen
, dbp
->db_malloc
)) != 0)
557 * The cursor was reset, so the delete adjustment is no
563 * Retrieve the record.
565 * Skip any keys that don't really exist.
567 if ((ret
= __ram_iget(dbp
, key
, data
)) != 0)
568 if (ret
== DB_KEYEMPTY
&&
569 (flags
== DB_NEXT
|| flags
== DB_PREV
))
581 * Recno cursor->c_put function.
584 __ram_c_put(dbc
, key
, data
, flags
)
595 DEBUG_LWRITE(dbc
->dbp
, dbc
->txn
, "ram_c_put", NULL
, data
, flags
);
599 if ((ret
= __db_cputchk(dbc
->dbp
, key
, data
, flags
,
600 F_ISSET(dbc
->dbp
, DB_AM_RDONLY
), cp
->recno
!= RECNO_OOB
)) != 0)
603 GETHANDLE(dbc
->dbp
, dbc
->txn
, &dbp
, ret
);
606 /* Initialize the cursor for a new retrieval. */
610 * To split, we need a valid key for the page. Since it's a cursor,
611 * we have to build one.
613 * The split code discards all short-term locks and stack pages.
616 split
: arg
= &cp
->recno
;
617 if ((ret
= __bam_split(dbp
, arg
)) != 0)
621 if ((ret
= __bam_rsearch(dbp
, &cp
->recno
, S_INSERT
, 1, &exact
)) != 0)
627 if ((ret
= __bam_iitem(dbp
, &t
->bt_csp
->page
,
628 &t
->bt_csp
->indx
, key
, data
, flags
, 0)) == DB_NEEDSPLIT
) {
629 if ((ret
= __bam_stkrel(dbp
)) != 0)
633 if ((ret
= __bam_stkrel(dbp
)) != 0)
638 /* Adjust the cursors. */
639 __ram_ca(dbp
, cp
->recno
, CA_IAFTER
);
641 /* Set this cursor to reference the new record. */
642 cp
->recno
= copy
.recno
+ 1;
645 /* Adjust the cursors. */
646 __ram_ca(dbp
, cp
->recno
, CA_IBEFORE
);
648 /* Set this cursor to reference the new record. */
649 cp
->recno
= copy
.recno
;
654 * The cursor was reset, so the delete adjustment is no
670 * PUBLIC: void __ram_ca __P((DB *, db_recno_t, ca_recno_arg));
673 __ram_ca(dbp
, recno
, op
)
682 * Adjust the cursors. See the comment in __bam_ca_delete().
685 for (dbc
= TAILQ_FIRST(&dbp
->curs_queue
);
686 dbc
!= NULL
; dbc
= TAILQ_NEXT(dbc
, links
)) {
687 cp
= (RCURSOR
*)dbc
->internal
;
690 if (recno
> cp
->recno
)
694 if (recno
> cp
->recno
)
698 if (recno
>= cp
->recno
)
703 CURSOR_TEARDOWN(dbp
);
709 * Display the current recno cursor list.
711 * PUBLIC: int __ram_cprint __P((DB *));
721 for (dbc
= TAILQ_FIRST(&dbp
->curs_queue
);
722 dbc
!= NULL
; dbc
= TAILQ_NEXT(dbc
, links
)) {
723 cp
= (RCURSOR
*)dbc
->internal
;
725 "%#0x: recno: %lu\n", (u_int
)cp
, (u_long
)cp
->recno
);
727 CURSOR_TEARDOWN(dbp
);
735 * Check the user's record number, and make sure we've seen it.
737 * PUBLIC: int __ram_getno __P((DB *, const DBT *, db_recno_t *, int));
740 __ram_getno(dbp
, key
, rep
, can_create
)
748 /* Check the user's record number. */
749 if ((recno
= *(db_recno_t
*)key
->data
) == 0) {
750 __db_err(dbp
->dbenv
, "illegal record number of 0");
757 * Btree can neither create records or read them in. Recno can
758 * do both, see if we can find the record.
760 return (dbp
->type
== DB_RECNO
?
761 __ram_update(dbp
, recno
, can_create
) : 0);
766 * Read in any remaining records from the backing input file.
768 * PUBLIC: int __ram_snapshot __P((DB *));
774 return (__ram_update(dbp
, DB_MAX_RECORDS
, 0));
779 * Ensure the tree has records up to and including the specified one.
782 __ram_update(dbp
, recno
, can_create
)
796 * If we can't create records and we've read the entire backing input
799 if (!can_create
&& F_ISSET(rp
, RECNO_EOF
))
803 * If we haven't seen this record yet, try to get it from the original
806 if ((ret
= __bam_nrecs(dbp
, &nrecs
)) != 0)
808 if (!F_ISSET(rp
, RECNO_EOF
) && recno
> nrecs
) {
809 if ((ret
= rp
->re_irec(dbp
, recno
)) != 0)
811 if ((ret
= __bam_nrecs(dbp
, &nrecs
)) != 0)
816 * If we can create records, create empty ones up to the requested
819 if (!can_create
|| recno
<= nrecs
+ 1)
822 t
->bt_rdata
.dlen
= 0;
823 t
->bt_rdata
.doff
= 0;
824 t
->bt_rdata
.flags
= 0;
825 if (F_ISSET(dbp
, DB_RE_FIXEDLEN
)) {
826 if (t
->bt_rdata
.ulen
< rp
->re_len
) {
827 t
->bt_rdata
.data
= t
->bt_rdata
.data
== NULL
?
828 (void *)__db_malloc(rp
->re_len
) :
829 (void *)__db_realloc(t
->bt_rdata
.data
, rp
->re_len
);
830 if (t
->bt_rdata
.data
== NULL
) {
831 t
->bt_rdata
.ulen
= 0;
834 t
->bt_rdata
.ulen
= rp
->re_len
;
836 t
->bt_rdata
.size
= rp
->re_len
;
837 memset(t
->bt_rdata
.data
, rp
->re_pad
, rp
->re_len
);
839 t
->bt_rdata
.size
= 0;
841 while (recno
> ++nrecs
)
842 if ((ret
= __ram_add(dbp
,
843 &nrecs
, &t
->bt_rdata
, 0, BI_DELETED
)) != 0)
850 * Load information about the backing file.
853 __ram_source(dbp
, rp
, fname
)
859 u_int32_t bytes
, mbytes
, oflags
;
862 if ((ret
= __db_appname(dbp
->dbenv
,
863 DB_APP_DATA
, NULL
, fname
, 0, NULL
, &rp
->re_source
)) != 0)
866 oflags
= F_ISSET(dbp
, DB_AM_RDONLY
) ? DB_RDONLY
: 0;
868 __db_open(rp
->re_source
, oflags
, oflags
, 0, &rp
->re_fd
)) != 0) {
869 __db_err(dbp
->dbenv
, "%s: %s", rp
->re_source
, strerror(ret
));
875 * We'd like to test to see if the file is too big to mmap. Since we
876 * don't know what size or type off_t's or size_t's are, or the largest
877 * unsigned integral type is, or what random insanity the local C
878 * compiler will perpetrate, doing the comparison in a portable way is
879 * flatly impossible. Hope that mmap fails if the file is too large.
881 if ((ret
= __db_ioinfo(rp
->re_source
,
882 rp
->re_fd
, &mbytes
, &bytes
, NULL
)) != 0) {
883 __db_err(dbp
->dbenv
, "%s: %s", rp
->re_source
, strerror(ret
));
886 if (mbytes
== 0 && bytes
== 0) {
887 F_SET(rp
, RECNO_EOF
);
891 size
= mbytes
* MEGABYTE
+ bytes
;
892 if ((ret
= __db_mapfile(rp
->re_source
,
893 rp
->re_fd
, (size_t)size
, 1, &rp
->re_smap
)) != 0)
895 rp
->re_cmap
= rp
->re_smap
;
896 rp
->re_emap
= (u_int8_t
*)rp
->re_smap
+ (rp
->re_msize
= size
);
897 rp
->re_irec
= F_ISSET(dbp
, DB_RE_FIXEDLEN
) ? __ram_fmap
: __ram_vmap
;
900 err
: FREES(rp
->re_source
)
906 * Rewrite the backing file.
917 u_int8_t delim
, *pad
;
919 rp
= ((BTREE
*)dbp
->internal
)->bt_recno
;
921 /* If the file wasn't modified, we're done. */
922 if (!F_ISSET(rp
, RECNO_MODIFIED
))
925 /* If there's no backing source file, we're done. */
926 if (rp
->re_source
== NULL
) {
927 F_CLR(rp
, RECNO_MODIFIED
);
932 * Read any remaining records into the tree.
935 * This is why we can't support transactions when applications specify
936 * backing (re_source) files. At this point we have to read in the
937 * rest of the records from the file so that we can write all of the
938 * records back out again, which could modify a page for which we'd
939 * have to log changes and which we don't have locked. This could be
940 * partially fixed by taking a snapshot of the entire file during the
941 * db_open(), or, since db_open() isn't transaction protected, as part
942 * of the first DB operation. But, if a checkpoint occurs then, the
943 * part of the log holding the copy of the file could be discarded, and
944 * that would make it impossible to recover in the face of disaster.
945 * This could all probably be fixed, but it would require transaction
946 * protecting the backing source file, i.e. mpool would have to know
947 * about it, and we don't want to go there.
949 if ((ret
= __ram_snapshot(dbp
)) != 0 && ret
!= DB_NOTFOUND
)
954 * Close any underlying mmap region. This is required for Windows NT
955 * (4.0, Service Pack 2) -- if the file is still mapped, the following
958 if (rp
->re_smap
!= NULL
) {
959 (void)__db_unmapfile(rp
->re_smap
, rp
->re_msize
);
963 /* Get rid of any backing file descriptor, just on GP's. */
964 if (rp
->re_fd
!= -1) {
965 (void)__db_close(rp
->re_fd
);
969 /* Open the file, truncating it. */
970 if ((ret
= __db_open(rp
->re_source
,
971 DB_SEQUENTIAL
| DB_TRUNCATE
,
972 DB_SEQUENTIAL
| DB_TRUNCATE
, 0, &fd
)) != 0) {
973 __db_err(dbp
->dbenv
, "%s: %s", rp
->re_source
, strerror(ret
));
978 * We step through the records, writing each one out. Use the record
979 * number and the dbp->get() function, instead of a cursor, so we find
980 * and write out "deleted" or non-existent records.
982 memset(&key
, 0, sizeof(key
));
983 memset(&data
, 0, sizeof(data
));
984 key
.size
= sizeof(db_recno_t
);
988 * We'll need the delimiter if we're doing variable-length records,
989 * and the pad character if we're doing fixed-length records.
991 delim
= rp
->re_delim
;
992 if (F_ISSET(dbp
, DB_RE_FIXEDLEN
)) {
993 if ((pad
= (u_int8_t
*)__db_malloc(rp
->re_len
)) == NULL
) {
997 memset(pad
, rp
->re_pad
, rp
->re_len
);
999 COMPQUIET(pad
, NULL
);
1000 for (keyno
= 1;; ++keyno
) {
1001 switch (ret
= dbp
->get(dbp
, NULL
, &key
, &data
, 0)) {
1004 __db_write(fd
, data
.data
, data
.size
, &nw
)) != 0)
1006 if (nw
!= (ssize_t
)data
.size
) {
1012 if (F_ISSET(dbp
, DB_RE_FIXEDLEN
)) {
1014 __db_write(fd
, pad
, rp
->re_len
, &nw
)) != 0)
1016 if (nw
!= (ssize_t
)rp
->re_len
) {
1026 if (!F_ISSET(dbp
, DB_RE_FIXEDLEN
)) {
1027 if ((ret
= __db_write(fd
, &delim
, 1, &nw
)) != 0)
1037 done
: /* Close the file descriptor. */
1038 if ((t_ret
= __db_close(fd
)) != 0 || ret
== 0)
1042 F_CLR(rp
, RECNO_MODIFIED
);
1048 * Get fixed length records from a file.
1051 __ram_fmap(dbp
, top
)
1060 u_int8_t
*sp
, *ep
, *p
;
1063 if ((ret
= __bam_nrecs(dbp
, &recno
)) != 0)
1068 if (t
->bt_rdata
.ulen
< rp
->re_len
) {
1069 t
->bt_rdata
.data
= t
->bt_rdata
.data
== NULL
?
1070 (void *)__db_malloc(rp
->re_len
) :
1071 (void *)__db_realloc(t
->bt_rdata
.data
, rp
->re_len
);
1072 if (t
->bt_rdata
.data
== NULL
) {
1073 t
->bt_rdata
.ulen
= 0;
1076 t
->bt_rdata
.ulen
= rp
->re_len
;
1079 memset(&data
, 0, sizeof(data
));
1080 data
.data
= t
->bt_rdata
.data
;
1081 data
.size
= rp
->re_len
;
1083 sp
= (u_int8_t
*)rp
->re_cmap
;
1084 ep
= (u_int8_t
*)rp
->re_emap
;
1085 while (recno
< top
) {
1087 F_SET(rp
, RECNO_EOF
);
1088 return (DB_NOTFOUND
);
1091 for (p
= t
->bt_rdata
.data
;
1092 sp
< ep
&& len
> 0; *p
++ = *sp
++, --len
)
1096 * Another process may have read this record from the input
1097 * file and stored it into the database already, in which
1098 * case we don't need to repeat that operation. We detect
1099 * this by checking if the last record we've read is greater
1100 * or equal to the number of records in the database.
1103 * We should just do a seek, since the records are fixed
1106 if (rp
->re_last
>= recno
) {
1108 memset(p
, rp
->re_pad
, len
);
1111 if ((ret
= __ram_add(dbp
, &recno
, &data
, 0, 0)) != 0)
1122 * Get variable length records from a file.
1125 __ram_vmap(dbp
, top
)
1139 if ((ret
= __bam_nrecs(dbp
, &recno
)) != 0)
1142 memset(&data
, 0, sizeof(data
));
1144 delim
= rp
->re_delim
;
1146 sp
= (u_int8_t
*)rp
->re_cmap
;
1147 ep
= (u_int8_t
*)rp
->re_emap
;
1148 while (recno
< top
) {
1150 F_SET(rp
, RECNO_EOF
);
1151 return (DB_NOTFOUND
);
1153 for (data
.data
= sp
; sp
< ep
&& *sp
!= delim
; ++sp
)
1157 * Another process may have read this record from the input
1158 * file and stored it into the database already, in which
1159 * case we don't need to repeat that operation. We detect
1160 * this by checking if the last record we've read is greater
1161 * or equal to the number of records in the database.
1163 if (rp
->re_last
>= recno
) {
1164 data
.size
= sp
- (u_int8_t
*)data
.data
;
1166 if ((ret
= __ram_add(dbp
, &recno
, &data
, 0, 0)) != 0)
1178 * Add records into the tree.
1181 __ram_add(dbp
, recnop
, data
, flags
, bi_flags
)
1185 u_int32_t flags
, bi_flags
;
1191 int exact
, isdeleted
, ret
, stack
;
1195 retry
: /* Find the slot for insertion. */
1196 if ((ret
= __bam_rsearch(dbp
, recnop
,
1197 S_INSERT
| (LF_ISSET(DB_APPEND
) ? S_APPEND
: 0), 1, &exact
)) != 0)
1199 h
= t
->bt_csp
->page
;
1200 indx
= t
->bt_csp
->indx
;
1204 * If DB_NOOVERWRITE is set and the item already exists in the tree,
1205 * return an error unless the item has been marked for deletion.
1209 bk
= GET_BKEYDATA(h
, indx
);
1210 if (B_DISSET(bk
->type
)) {
1212 __bam_ca_replace(dbp
, h
->pgno
, indx
, REPLACE_SETUP
);
1214 if (LF_ISSET(DB_NOOVERWRITE
)) {
1221 * Select the arguments for __bam_iitem() and do the insert. If the
1222 * key is an exact match, or we're replacing the data item with a
1223 * new data item, replace the current item. If the key isn't an exact
1224 * match, we're inserting a new key/data pair, before the search
1227 switch (ret
= __bam_iitem(dbp
,
1228 &h
, &indx
, NULL
, data
, exact
? DB_CURRENT
: DB_BEFORE
, bi_flags
)) {
1231 * Done. Clean up the cursor and adjust the internal page
1235 __bam_ca_replace(dbp
, h
->pgno
, indx
, REPLACE_SUCCESS
);
1239 * We have to split the page. Back out the cursor setup,
1240 * discard the stack of pages, and do the split.
1243 __bam_ca_replace(dbp
, h
->pgno
, indx
, REPLACE_FAILED
);
1245 (void)__bam_stkrel(dbp
);
1248 if ((ret
= __bam_split(dbp
, recnop
)) != 0)
1255 __bam_ca_replace(dbp
, h
->pgno
, indx
, REPLACE_FAILED
);