xref: /original-bsd/lib/libc/db/recno/rec_seq.c (revision f51da917)
1 /*-
2  * Copyright (c) 1991, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)rec_seq.c	8.2 (Berkeley) 09/07/93";
10 #endif /* not lint */
11 
12 #include <sys/types.h>
13 
14 #include <errno.h>
15 #include <limits.h>
16 #include <stdio.h>
17 #include <string.h>
18 
19 #include <db.h>
20 #include "recno.h"
21 
22 /*
23  * __REC_SEQ -- Recno sequential scan interface.
24  *
25  * Parameters:
26  *	dbp:	pointer to access method
27  *	key:	key for positioning and return value
28  *	data:	data return value
29  *	flags:	R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV.
30  *
31  * Returns:
32  *	RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
33  */
34 int
35 __rec_seq(dbp, key, data, flags)
36 	const DB *dbp;
37 	DBT *key, *data;
38 	u_int flags;
39 {
40 	BTREE *t;
41 	EPG *e;
42 	recno_t nrec;
43 	int status;
44 
45 	t = dbp->internal;
46 
47 	/* Toss any page pinned across calls. */
48 	if (t->bt_pinned != NULL) {
49 		mpool_put(t->bt_mp, t->bt_pinned, 0);
50 		t->bt_pinned = NULL;
51 	}
52 
53 	switch(flags) {
54 	case R_CURSOR:
55 		if ((nrec = *(recno_t *)key->data) == 0)
56 			goto einval;
57 		break;
58 	case R_NEXT:
59 		if (ISSET(t, B_SEQINIT)) {
60 			nrec = t->bt_rcursor + 1;
61 			break;
62 		}
63 		/* FALLTHROUGH */
64 	case R_FIRST:
65 		nrec = 1;
66 		break;
67 	case R_PREV:
68 		if (ISSET(t, B_SEQINIT)) {
69 			if ((nrec = t->bt_rcursor - 1) == 0)
70 				return (RET_SPECIAL);
71 			break;
72 		}
73 		/* FALLTHROUGH */
74 	case R_LAST:
75 		if (!ISSET(t, R_EOF | R_INMEM) &&
76 		    t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
77 			return (RET_ERROR);
78 		nrec = t->bt_nrecs;
79 		break;
80 	default:
81 einval:		errno = EINVAL;
82 		return (RET_ERROR);
83 	}
84 
85 	if (t->bt_nrecs == 0 || nrec > t->bt_nrecs) {
86 		if (!ISSET(t, R_EOF | R_INMEM) &&
87 		    (status = t->bt_irec(t, nrec)) != RET_SUCCESS)
88 			return (status);
89 		if (t->bt_nrecs == 0 || nrec > t->bt_nrecs)
90 			return (RET_SPECIAL);
91 	}
92 
93 	if ((e = __rec_search(t, nrec - 1, SEARCH)) == NULL)
94 		return (RET_ERROR);
95 
96 	SET(t, B_SEQINIT);
97 	t->bt_rcursor = nrec;
98 
99 	status = __rec_ret(t, e, nrec, key, data);
100 	if (ISSET(t, B_DB_LOCK))
101 		mpool_put(t->bt_mp, e->page, 0);
102 	else
103 		t->bt_pinned = e->page;
104 	return (status);
105 }
106