2 * Copyright (c) 1990 The Regents of the University of California.
5 * This code is derived from software contributed to Berkeley by
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 #if defined(LIBC_SCCS) && !defined(lint)
38 static char sccsid
[] = "@(#)insert.c 5.3 (Berkeley) 2/22/91";
39 #endif /* LIBC_SCCS and not lint */
41 #include <sys/types.h>
48 * _BT_INSERT -- Insert a new user datum in the btree.
50 * This routine is called by bt_put, the public interface, once the
51 * location for the new item is known. We do the work here, and
52 * handle splits if necessary.
55 * t -- btree in which to do the insertion.
56 * item -- BTITEM describing location of new datum
57 * key -- key to insert
58 * data -- data associated with key
59 * flag -- magic cookie passed recursively to bt_put if we
63 * RET_SUCCESS, RET_ERROR.
67 _bt_insert(t
, item
, key
, data
, flag
)
80 int keysize
, datasize
;
83 if (_bt_getpage(t
, item
->bti_pgno
) == RET_ERROR
)
87 if (TOOBIG(t
, data
->size
)) {
89 datasize
= sizeof(pgno_t
);
92 datasize
= data
->size
;
95 if (TOOBIG(t
, key
->size
)) {
97 keysize
= sizeof(pgno_t
);
103 nbytes
= keysize
+ datasize
+ (sizeof(DATUM
) - sizeof(char));
104 nbytes
= LONGALIGN(nbytes
) + sizeof(index_t
);
106 /* if there's not enough room here, split the page */
107 if ((h
->h_upper
- h
->h_lower
) < nbytes
) {
108 if (_bt_split(t
) == RET_ERROR
)
111 /* okay, try again (empty the stack first, though) */
112 while (_bt_pop((BTREE
) t
) != P_NONE
)
115 return (bt_put((BTREE
) t
, key
, data
, flag
));
118 /* put together a leaf page datum from the key/data pair */
119 index
= item
->bti_index
;
120 nbytes
= keysize
+ datasize
+ (sizeof(DATUM
) - sizeof(char));
122 if ((d
= (DATUM
*) malloc((unsigned) nbytes
)) == (DATUM
*) NULL
)
125 d
->d_ksize
= keysize
;
126 d
->d_dsize
= datasize
;
130 if (_bt_indirect(t
, key
, &pgno
) == RET_ERROR
)
132 (void) bcopy((char *) &pgno
, &(d
->d_bytes
[0]), sizeof(pgno
));
133 d
->d_flags
|= D_BIGKEY
;
134 if (_bt_getpage(t
, item
->bti_pgno
) == RET_ERROR
)
137 if (d
->d_ksize
> 0) {
138 (void) bcopy((char *) key
->data
,
139 (char *) &(d
->d_bytes
[0]),
145 if (_bt_indirect(t
, data
, &pgno
) == RET_ERROR
)
147 (void) bcopy((char *) &pgno
,
148 &(d
->d_bytes
[keysize
]),
150 d
->d_flags
|= D_BIGDATA
;
151 if (_bt_getpage(t
, item
->bti_pgno
) == RET_ERROR
)
154 if (d
->d_dsize
> 0) {
155 (void) bcopy((char *) data
->data
,
156 (char *) &(d
->d_bytes
[keysize
]),
161 /* do the insertion */
162 status
= _bt_insertat(t
, (char *) d
, index
);
164 (void) free((char *) d
);
170 * _BT_INSERTI -- Insert IDATUM on current page in the btree.
172 * This routine handles insertions to internal pages after splits
173 * lower in the tree. On entry, t->bt_curpage is the page to get
174 * the new IDATUM. We are also given pgno, the page number of the
175 * IDATUM that is immediately left of the new IDATUM's position.
176 * This guarantees that the IDATUM for the right half of the page
177 * after a split goes next to the IDATUM for its left half.
180 * t -- tree in which to do insertion.
181 * id -- new IDATUM to insert
182 * pgno -- page number of IDATUM left of id's position
185 * RET_SUCCESS, RET_ERROR.
189 _bt_inserti(t
, id
, pgno
)
194 BTHEADER
*h
= t
->bt_curpage
;
202 if (id
->i_flags
& D_BIGKEY
) {
204 bcopy(&(id
->i_bytes
[0]), (char *) &chain
, sizeof(chain
));
205 if (_bt_getbig(t
, chain
, &key
, &ignore
) == RET_ERROR
)
209 key
= &(id
->i_bytes
[0]);
211 i
= _bt_binsrch(t
, key
);
214 while (i
< next
&& _bt_cmp(t
, key
, i
) >= 0)
220 /* okay, now we're close; find adjacent IDATUM */
222 idx
= (IDATUM
*) GETDATUM(h
,i
);
223 if (idx
->i_pgno
== pgno
) {
230 /* correctly positioned, do the insertion */
231 return (_bt_insertat(t
, (char *) id
, i
));
235 * _BT_INSERTAT -- Insert a datum at a given location on the current page.
237 * This routine does insertions on both leaf and internal pages.
240 * t -- tree in which to do insertion.
241 * p -- DATUM or IDATUM to insert.
242 * index -- index in line pointer array to put this item.
245 * RET_SUCCESS, RET_ERROR.
248 * Will rearrange line pointers to make space for the new
249 * entry. This means that any scans currently active are
250 * invalid after this.
253 * There must be sufficient room for the new item on the page.
257 _bt_insertat(t
, p
, index
)
262 IDATUM
*id
= (IDATUM
*) p
;
263 DATUM
*d
= (DATUM
*) p
;
270 /* insertion may confuse an active scan. fix it. */
272 if (t
->bt_flags
& BTF_SEQINIT
&& t
->bt_curpage
->h_pgno
== c
->c_pgno
)
273 if (_bt_fixscan(t
, index
, d
, INSERT
) == RET_ERROR
)
277 nxtindex
= (index_t
) NEXTINDEX(h
);
280 * If we're inserting at the middle of the line pointer array,
281 * copy pointers that will follow the new one up on the page.
284 if (index
< nxtindex
) {
285 src
= (char *) &(h
->h_linp
[index
]);
286 dest
= (char *) &(h
->h_linp
[index
+ 1]);
287 nbytes
= (h
->h_lower
- (src
- ((char *) h
)))
288 + sizeof(h
->h_linp
[0]);
289 (void) bcopy(src
, dest
, nbytes
);
292 /* compute size and copy data to page */
293 if (h
->h_flags
& F_LEAF
) {
294 nbytes
= d
->d_ksize
+ d
->d_dsize
295 + (sizeof(DATUM
) - sizeof(char));
297 nbytes
= id
->i_size
+ (sizeof(IDATUM
) - sizeof(char));
299 dest
= (((char *) h
) + h
->h_upper
) - LONGALIGN(nbytes
);
300 (void) bcopy((char *) p
, dest
, nbytes
);
302 /* update statistics */
304 h
->h_linp
[index
] = (index_t
) dest
;
305 h
->h_upper
= (index_t
) dest
;
306 h
->h_lower
+= sizeof(index_t
);
309 h
->h_flags
|= F_DIRTY
;
311 return (RET_SUCCESS
);