BSD 4_4_Lite1 release
[unix-history] / usr / src / lib / libc / db / recno / rec_put.c
CommitLineData
91b5c9e5 1/*-
e659a03d
KB
2 * Copyright (c) 1990, 1993
3 * The Regents of the University of California. All rights reserved.
91b5c9e5 4 *
ad787160
C
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
91b5c9e5
KB
32 */
33
34#if defined(LIBC_SCCS) && !defined(lint)
ed554bc5 35static char sccsid[] = "@(#)rec_put.c 8.3 (Berkeley) 3/1/94";
91b5c9e5
KB
36#endif /* LIBC_SCCS and not lint */
37
38#include <sys/types.h>
06b455fb 39
06b455fb 40#include <errno.h>
91b5c9e5
KB
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
06b455fb 44
94ac72c5 45#include <db.h>
9b023459 46#include "recno.h"
91b5c9e5
KB
47
48/*
49 * __REC_PUT -- Add a recno item to the tree.
50 *
51 * Parameters:
52 * dbp: pointer to access method
53 * key: key
54 * data: data
c38e8f03 55 * flag: R_CURSOR, R_IAFTER, R_IBEFORE, R_NOOVERWRITE
91b5c9e5
KB
56 *
57 * Returns:
c38e8f03
KB
58 * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key is
59 * already in the tree and R_NOOVERWRITE specified.
91b5c9e5
KB
60 */
61int
62__rec_put(dbp, key, data, flags)
63 const DB *dbp;
06b455fb
KB
64 DBT *key;
65 const DBT *data;
91b5c9e5
KB
66 u_int flags;
67{
68 BTREE *t;
69 DBT tdata;
70 recno_t nrec;
71 int status;
72
9b023459
KB
73 t = dbp->internal;
74
19f5c4f5
KB
75 /* Toss any page pinned across calls. */
76 if (t->bt_pinned != NULL) {
77 mpool_put(t->bt_mp, t->bt_pinned, 0);
78 t->bt_pinned = NULL;
79 }
80
9b023459 81 switch (flags) {
9b023459 82 case R_CURSOR:
46f939c2 83 if (!ISSET(t, B_SEQINIT))
9b023459
KB
84 goto einval;
85 nrec = t->bt_rcursor;
86 break;
06b455fb
KB
87 case R_SETCURSOR:
88 if ((nrec = *(recno_t *)key->data) == 0)
89 goto einval;
90 break;
9b023459 91 case R_IAFTER:
f7014608
KB
92 if ((nrec = *(recno_t *)key->data) == 0) {
93 nrec = 1;
94 flags = R_IBEFORE;
95 }
96 break;
97 case 0:
9b023459
KB
98 case R_IBEFORE:
99 if ((nrec = *(recno_t *)key->data) == 0)
100 goto einval;
101 break;
102 case R_NOOVERWRITE:
103 if ((nrec = *(recno_t *)key->data) == 0)
104 goto einval;
105 if (nrec <= t->bt_nrecs)
106 return (RET_SPECIAL);
107 break;
108 default:
109einval: errno = EINVAL;
91b5c9e5
KB
110 return (RET_ERROR);
111 }
112
113 /*
f7014608
KB
114 * Make sure that records up to and including the put record are
115 * already in the database. If skipping records, create empty ones.
91b5c9e5 116 */
91b5c9e5 117 if (nrec > t->bt_nrecs) {
46f939c2 118 if (!ISSET(t, R_EOF | R_INMEM) &&
db39ad66 119 t->bt_irec(t, nrec) == RET_ERROR)
9b023459
KB
120 return (RET_ERROR);
121 if (nrec > t->bt_nrecs + 1) {
d082d4df
KB
122 if (ISSET(t, R_FIXLEN)) {
123 if ((tdata.data =
124 (void *)malloc(t->bt_reclen)) == NULL)
125 return (RET_ERROR);
126 tdata.size = t->bt_reclen;
127 memset(tdata.data, t->bt_bval, tdata.size);
128 } else {
129 tdata.data = NULL;
130 tdata.size = 0;
131 }
0243d838 132 while (nrec > t->bt_nrecs + 1)
f7014608 133 if (__rec_iput(t,
0243d838 134 t->bt_nrecs, &tdata, 0) != RET_SUCCESS)
9b023459 135 return (RET_ERROR);
d082d4df
KB
136 if (ISSET(t, R_FIXLEN))
137 free(tdata.data);
91b5c9e5
KB
138 }
139 }
06b455fb
KB
140
141 if ((status = __rec_iput(t, nrec - 1, data, flags)) != RET_SUCCESS)
142 return (status);
143
c38e8f03 144 if (flags == R_SETCURSOR)
06b455fb 145 t->bt_rcursor = nrec;
06b455fb 146
46f939c2 147 SET(t, R_MODIFIED);
06b455fb 148 return (__rec_ret(t, NULL, nrec, key, NULL));
91b5c9e5
KB
149}
150
151/*
152 * __REC_IPUT -- Add a recno item to the tree.
153 *
154 * Parameters:
155 * t: tree
156 * nrec: record number
157 * data: data
91b5c9e5
KB
158 *
159 * Returns:
9b023459 160 * RET_ERROR, RET_SUCCESS
91b5c9e5
KB
161 */
162int
163__rec_iput(t, nrec, data, flags)
164 BTREE *t;
165 recno_t nrec;
166 const DBT *data;
167 u_int flags;
168{
169 DBT tdata;
170 EPG *e;
91b5c9e5 171 PAGE *h;
93a5373b 172 indx_t index, nxtindex;
91b5c9e5
KB
173 pgno_t pg;
174 size_t nbytes;
9b023459 175 int dflags, status;
91b5c9e5
KB
176 char *dest, db[NOVFLSIZE];
177
178 /*
179 * If the data won't fit on a page, store it on indirect pages.
180 *
181 * XXX
182 * If the insert fails later on, these pages aren't recovered.
183 */
9b023459 184 if (data->size > t->bt_ovflsize) {
91b5c9e5
KB
185 if (__ovfl_put(t, data, &pg) == RET_ERROR)
186 return (RET_ERROR);
187 tdata.data = db;
188 tdata.size = NOVFLSIZE;
189 *(pgno_t *)db = pg;
190 *(size_t *)(db + sizeof(pgno_t)) = data->size;
191 dflags = P_BIGDATA;
192 data = &tdata;
193 } else
194 dflags = 0;
195
196 /* __rec_search pins the returned page. */
0243d838 197 if ((e = __rec_search(t, nrec,
2146c1b9
KB
198 nrec > t->bt_nrecs || flags == R_IAFTER || flags == R_IBEFORE ?
199 SINSERT : SEARCH)) == NULL)
91b5c9e5
KB
200 return (RET_ERROR);
201
202 h = e->page;
203 index = e->index;
204
205 /*
9b023459
KB
206 * Add the specified key/data pair to the tree. The R_IAFTER and
207 * R_IBEFORE flags insert the key after/before the specified key.
91b5c9e5
KB
208 *
209 * Pages are split as required.
210 */
211 switch (flags) {
212 case R_IAFTER:
91b5c9e5
KB
213 ++index;
214 break;
215 case R_IBEFORE:
91b5c9e5 216 break;
91b5c9e5 217 default:
9b023459
KB
218 if (nrec < t->bt_nrecs &&
219 __rec_dleaf(t, h, index) == RET_ERROR) {
91b5c9e5
KB
220 mpool_put(t->bt_mp, h, 0);
221 return (RET_ERROR);
222 }
223 break;
224 }
225
226 /*
227 * If not enough room, split the page. The split code will insert
228 * the key and data and unpin the current page. If inserting into
229 * the offset array, shift the pointers up.
230 */
231 nbytes = NRLEAFDBT(data->size);
93a5373b 232 if (h->upper - h->lower < nbytes + sizeof(indx_t)) {
9b023459
KB
233 status = __bt_split(t, h, NULL, data, dflags, nbytes, index);
234 if (status == RET_SUCCESS)
235 ++t->bt_nrecs;
236 return (status);
237 }
91b5c9e5
KB
238
239 if (index < (nxtindex = NEXTINDEX(h)))
1911b5bf 240 memmove(h->linp + index + 1, h->linp + index,
93a5373b
KB
241 (nxtindex - index) * sizeof(indx_t));
242 h->lower += sizeof(indx_t);
91b5c9e5
KB
243
244 h->linp[index] = h->upper -= nbytes;
245 dest = (char *)h + h->upper;
246 WR_RLEAF(dest, data, dflags);
247
91b5c9e5 248 ++t->bt_nrecs;
46f939c2
KB
249 SET(t, B_MODIFIED);
250 mpool_put(t->bt_mp, h, MPOOL_DIRTY);
251
91b5c9e5
KB
252 return (RET_SUCCESS);
253}