xref: /csrg-svn/lib/libc/db/btree/bt_get.c (revision 46135)
1*46135Smao /*-
2*46135Smao  * Copyright (c) 1990 The Regents of the University of California.
3*46135Smao  * All rights reserved.
4*46135Smao  *
5*46135Smao  * This code is derived from software contributed to Berkeley by
6*46135Smao  * Mike Olson.
7*46135Smao  *
8*46135Smao  * %sccs.include.redist.c%
9*46135Smao  */
10*46135Smao 
11*46135Smao #if defined(LIBC_SCCS) && !defined(lint)
12*46135Smao static char sccsid[] = "@(#)bt_get.c	5.1 (Berkeley) 01/23/91";
13*46135Smao #endif /* LIBC_SCCS and not lint */
14*46135Smao 
15*46135Smao #include <sys/param.h>
16*46135Smao #include <sys/types.h>
17*46135Smao #include <sys/errno.h>
18*46135Smao #include <sys/file.h>
19*46135Smao #include <db.h>
20*46135Smao #include "btree.h"
21*46135Smao 
22*46135Smao /*
23*46135Smao  *  BT_GETPAGE -- Make pgno the current page of the btree.
24*46135Smao  *
25*46135Smao  *	This routine is just a wrapper that decides whether to call the
26*46135Smao  *	memory or disk-based routine to do the work.
27*46135Smao  *
28*46135Smao  *	Parameters:
29*46135Smao  *		t -- btree in which to get page
30*46135Smao  *		pgno -- page number to get
31*46135Smao  *
32*46135Smao  *	Returns:
33*46135Smao  *		RET_SUCCESS or RET_ERROR.
34*46135Smao  */
35*46135Smao 
36*46135Smao int
37*46135Smao _bt_getpage(t, pgno)
38*46135Smao 	BTREE_P t;
39*46135Smao 	pgno_t pgno;
40*46135Smao {
41*46135Smao #ifdef DEBUG
42*46135Smao 	if (pgno == P_NONE)
43*46135Smao 		_punt();
44*46135Smao #endif /* DEBUG */
45*46135Smao 
46*46135Smao 	/* see if we can get away without doing any work */
47*46135Smao 	if (t->bt_curpage != (BTHEADER *) NULL) {
48*46135Smao 		if (t->bt_curpage->h_pgno == pgno)
49*46135Smao 			return (RET_SUCCESS);
50*46135Smao 	}
51*46135Smao 
52*46135Smao 	if (t->bt_fname == (char *) NULL)
53*46135Smao 		return (_bt_getmpage(t, pgno));
54*46135Smao 	else
55*46135Smao 		return (_bt_getdpage(t, pgno));
56*46135Smao }
57*46135Smao 
58*46135Smao /*
59*46135Smao  *  _BT_GETMPAGE -- Make pgno the current page of the btree.
60*46135Smao  *
61*46135Smao  *	This routine gets pages for in-memory btrees.
62*46135Smao  *
63*46135Smao  *	Parameters:
64*46135Smao  *		t -- btree in which to get page
65*46135Smao  *		pgno -- page number to get
66*46135Smao  *
67*46135Smao  *	Returns:
68*46135Smao  *		RET_SUCCESS or RET_ERROR.
69*46135Smao  */
70*46135Smao 
71*46135Smao int
72*46135Smao _bt_getmpage(t, pgno)
73*46135Smao 	register BTREE_P t;
74*46135Smao 	pgno_t pgno;
75*46135Smao {
76*46135Smao 	int htindex;
77*46135Smao 	BTHEADER *h;
78*46135Smao 	HTBUCKET *b;
79*46135Smao 
80*46135Smao 	if (t->bt_curpage == (BTHEADER *) NULL) {
81*46135Smao 		if (pgno != P_ROOT) {
82*46135Smao 			errno = EBADF;
83*46135Smao 			return (RET_ERROR);
84*46135Smao 		}
85*46135Smao 
86*46135Smao 		t->bt_npages++;
87*46135Smao 		h = (BTHEADER *) malloc((unsigned) t->bt_psize);
88*46135Smao 		if (h == (BTHEADER *) NULL)
89*46135Smao 			return (RET_ERROR);
90*46135Smao 
91*46135Smao 		h->h_pgno = P_ROOT;
92*46135Smao 		h->h_flags = F_LEAF;
93*46135Smao 		h->h_lower = (index_t)
94*46135Smao 				(((char *) &(h->h_linp[0])) - ((char *) h));
95*46135Smao 		h->h_upper = t->bt_psize;
96*46135Smao 		h->h_prevpg = h->h_nextpg = P_NONE;
97*46135Smao 
98*46135Smao 		t->bt_curpage = h;
99*46135Smao 
100*46135Smao 		/* get the root page into the hash table */
101*46135Smao 		if (_bt_write(t, h, RELEASE) == RET_ERROR)
102*46135Smao 			return (RET_ERROR);
103*46135Smao 	}
104*46135Smao 
105*46135Smao 	htindex = HASHKEY(pgno);
106*46135Smao 
107*46135Smao 	for (b = t->bt_s.bt_ht[htindex];
108*46135Smao 	     b != (HTBUCKET *) NULL;
109*46135Smao 	     b = b->ht_next) {
110*46135Smao 		if (b->ht_pgno == pgno) {
111*46135Smao 			t->bt_curpage = b->ht_page;
112*46135Smao 			return (RET_SUCCESS);
113*46135Smao 		}
114*46135Smao 	}
115*46135Smao 	return (RET_ERROR);
116*46135Smao }
117*46135Smao 
118*46135Smao /*
119*46135Smao  *  _BT_GETDPAGE -- Make pgno the current page of the btree.
120*46135Smao  *
121*46135Smao  *	This routine gets pages for disk btrees.
122*46135Smao  *
123*46135Smao  *	Because disk btree pages must be readable across machine architectures,
124*46135Smao  *	the btree code writes integers out in network format.  This routine
125*46135Smao  *	converts them back to host format before returning the page.
126*46135Smao  *
127*46135Smao  *	Parameters:
128*46135Smao  *		t -- btree in which to get page
129*46135Smao  *		pgno -- page number to get
130*46135Smao  *
131*46135Smao  *	Returns:
132*46135Smao  *		RET_SUCCESS, RET_ERROR.
133*46135Smao  */
134*46135Smao 
135*46135Smao int
136*46135Smao _bt_getdpage(t, pgno)
137*46135Smao 	register BTREE_P t;
138*46135Smao 	pgno_t pgno;
139*46135Smao {
140*46135Smao 	BTHEADER *h;
141*46135Smao 	char *cache;
142*46135Smao 	long pos;
143*46135Smao 	int n, nbytes;
144*46135Smao 
145*46135Smao 	/* if we have an lru cache, let the cache code do the work */
146*46135Smao 	if (ISCACHE(t)) {
147*46135Smao 		cache = t->bt_s.bt_d.d_cache;
148*46135Smao 
149*46135Smao 		/* release the old page */
150*46135Smao 		if (t->bt_curpage != (BTHEADER *) NULL) {
151*46135Smao 			pgno_t opgno = t->bt_curpage->h_pgno;
152*46135Smao 			t->bt_curpage->h_flags &= ~F_DIRTY;
153*46135Smao 
154*46135Smao 			if (lruwrite(cache, (int) opgno) < 0)
155*46135Smao 				return (RET_ERROR);
156*46135Smao 
157*46135Smao 			if (lrurelease(cache, (int) opgno) < 0)
158*46135Smao 				return (RET_ERROR);
159*46135Smao 		}
160*46135Smao 
161*46135Smao 		if (pgno > t->bt_npages) {
162*46135Smao 			if ((h = (BTHEADER *) lrugetnew(cache, (int)pgno, &nbytes))
163*46135Smao 			    == (BTHEADER *) NULL)
164*46135Smao 				return (RET_ERROR);
165*46135Smao 			t->bt_npages = pgno;
166*46135Smao 		} else {
167*46135Smao 			if ((h = (BTHEADER *) lruget(cache, (int)pgno, &nbytes))
168*46135Smao 			    == (BTHEADER *) NULL)
169*46135Smao 				return (RET_ERROR);
170*46135Smao 		}
171*46135Smao 
172*46135Smao 		/* init this page, if necessary */
173*46135Smao 		if (nbytes == 0) {
174*46135Smao 			h->h_pgno = pgno;
175*46135Smao 			h->h_flags = F_LEAF;
176*46135Smao 			h->h_lower = (index_t)
177*46135Smao 				(((char *) &(h->h_linp[0])) - ((char *) h));
178*46135Smao 			h->h_upper = t->bt_psize;
179*46135Smao 			h->h_prevpg = h->h_nextpg = P_NONE;
180*46135Smao 		}
181*46135Smao 
182*46135Smao 		t->bt_curpage = h;
183*46135Smao 
184*46135Smao 		return (RET_SUCCESS);
185*46135Smao 	}
186*46135Smao 
187*46135Smao 	/* sync the current page, if necessary */
188*46135Smao 	if (t->bt_curpage != (BTHEADER *) NULL) {
189*46135Smao 		if (t->bt_curpage->h_flags & F_DIRTY)
190*46135Smao 			if (_bt_write(t, t->bt_curpage, RELEASE) == RET_ERROR)
191*46135Smao 				return (RET_ERROR);
192*46135Smao 	} else {
193*46135Smao 		if (t->bt_npages == 0)
194*46135Smao 			t->bt_npages = 1;
195*46135Smao 
196*46135Smao 		/* if no current page, get space for one */
197*46135Smao 		if ((t->bt_curpage = (BTHEADER *) malloc((unsigned) t->bt_psize))
198*46135Smao 		    == (BTHEADER *) NULL) {
199*46135Smao 			return (RET_ERROR);
200*46135Smao 		}
201*46135Smao 	}
202*46135Smao 
203*46135Smao 	n = t->bt_psize;
204*46135Smao 	pos = (long) (pgno * n);
205*46135Smao 
206*46135Smao 	/* seek to correct location in file */
207*46135Smao 	if (lseek(t->bt_s.bt_d.d_fd, pos, L_SET) != pos) {
208*46135Smao 		return (RET_ERROR);
209*46135Smao 	}
210*46135Smao 
211*46135Smao 	/* read the page */
212*46135Smao 	if ((nbytes = read(t->bt_s.bt_d.d_fd, t->bt_curpage, n)) < n) {
213*46135Smao 
214*46135Smao 		/*
215*46135Smao 		 *  If we didn't get a full page, we must have gotten no
216*46135Smao 		 *  data at all -- in which case we're trying to read a
217*46135Smao 		 *  root page that doesn't exist yet.  This is the only
218*46135Smao 		 *  case in which this is okay.  If this happens, construct
219*46135Smao 		 *  an empty root page by hand.
220*46135Smao 		 */
221*46135Smao 		if (nbytes != 0 || pgno != P_ROOT) {
222*46135Smao 			errno = EBADF;
223*46135Smao 			return (RET_ERROR);
224*46135Smao 		}
225*46135Smao 
226*46135Smao 		h = (BTHEADER *) t->bt_curpage;
227*46135Smao 		h->h_pgno = pgno;
228*46135Smao 		h->h_flags = F_LEAF;
229*46135Smao 		h->h_lower = (index_t)
230*46135Smao 				(((char *) &(h->h_linp[0])) - ((char *) h));
231*46135Smao 		h->h_upper = t->bt_psize;
232*46135Smao 		h->h_prevpg = h->h_nextpg = P_NONE;
233*46135Smao 	} else
234*46135Smao 		(void) _bt_pgin(t->bt_curpage, (char *) t->bt_lorder);
235*46135Smao 
236*46135Smao 	return (RET_SUCCESS);
237*46135Smao }
238*46135Smao 
239*46135Smao /*
240*46135Smao  *  _BT_PGOUT, _BT_PGIN -- Convert host-specific number layout to/from
241*46135Smao  *			   the host-independent format stored on disk.
242*46135Smao  *
243*46135Smao  *	Parameters:
244*46135Smao  *		h -- page to convert
245*46135Smao  *		_lorder -- byte order for pages (stored as a char * in the
246*46135Smao  *			   cache, and passed around as a magic cookie).
247*46135Smao  *
248*46135Smao  *	Returns:
249*46135Smao  *		RET_SUCCESS (lru code requires a return value).
250*46135Smao  *
251*46135Smao  *	Side Effects:
252*46135Smao  *		Layout of tree metadata on the page is changed in place.
253*46135Smao  *
254*46135Smao  *	Warnings:
255*46135Smao  *		Everywhere else in the code, the types pgno_t and index_t
256*46135Smao  *		are opaque.  These two routines know what they really
257*46135Smao  *		are.
258*46135Smao  */
259*46135Smao 
260*46135Smao int
261*46135Smao _bt_pgout(h, _lorder)
262*46135Smao 	BTHEADER *h;
263*46135Smao 	char *_lorder;
264*46135Smao {
265*46135Smao 	int i;
266*46135Smao 	int top;
267*46135Smao 	int lorder;
268*46135Smao 	DATUM *d;
269*46135Smao 	IDATUM *id;
270*46135Smao 	size_t chain;
271*46135Smao 
272*46135Smao 	lorder = (int) _lorder;
273*46135Smao 	if (lorder == BYTE_ORDER)
274*46135Smao 		return (RET_SUCCESS);
275*46135Smao 
276*46135Smao 	if (h->h_flags & F_LEAF) {
277*46135Smao 		if (h->h_flags & F_CONT) {
278*46135Smao 			if (h->h_prevpg == P_NONE) {
279*46135Smao 				size_t longsz;
280*46135Smao 
281*46135Smao 				(void) bcopy((char *) &(h->h_linp[0]),
282*46135Smao 					      (char *) &longsz,
283*46135Smao 					      sizeof(longsz));
284*46135Smao 				BLSWAP(longsz);
285*46135Smao 				(void) bcopy((char *) &longsz,
286*46135Smao 					      (char *) &(h->h_linp[0]),
287*46135Smao 					      sizeof(longsz));
288*46135Smao 			}
289*46135Smao 		} else {
290*46135Smao 			top = NEXTINDEX(h);
291*46135Smao 			for (i = 0; i < top; i++) {
292*46135Smao 				d = (DATUM *) GETDATUM(h, i);
293*46135Smao 				if (d->d_flags & D_BIGKEY) {
294*46135Smao 					(void) bcopy((char *) &(d->d_bytes[0]),
295*46135Smao 						      (char *) &chain,
296*46135Smao 						      sizeof(chain));
297*46135Smao 					BLSWAP(chain);
298*46135Smao 					(void) bcopy((char *) &chain,
299*46135Smao 						      (char *) &(d->d_bytes[0]),
300*46135Smao 						      sizeof(chain));
301*46135Smao 				}
302*46135Smao 				if (d->d_flags & D_BIGDATA) {
303*46135Smao 					(void) bcopy((char *) &(d->d_bytes[d->d_ksize]),
304*46135Smao 						      (char *) &chain,
305*46135Smao 						      sizeof(chain));
306*46135Smao 					BLSWAP(chain);
307*46135Smao 					(void) bcopy((char *) &chain,
308*46135Smao 						      (char *) &(d->d_bytes[d->d_ksize]),
309*46135Smao 						      sizeof(chain));
310*46135Smao 				}
311*46135Smao 				BLSWAP(d->d_dsize);
312*46135Smao 				BLSWAP(d->d_ksize);
313*46135Smao 				BLSWAP(d->d_flags);
314*46135Smao 				BLSWAP(h->h_linp[i]);
315*46135Smao 			}
316*46135Smao 		}
317*46135Smao 	} else {
318*46135Smao 		top = NEXTINDEX(h);
319*46135Smao 		for (i = 0; i < top; i++) {
320*46135Smao 			id = (IDATUM *) GETDATUM(h, i);
321*46135Smao 			BLSWAP(id->i_size);
322*46135Smao 			BLSWAP(id->i_pgno);
323*46135Smao 			BLSWAP(id->i_flags);
324*46135Smao 			if (id->i_flags & D_BIGKEY) {
325*46135Smao 				(void) bcopy((char *) &(id->i_bytes[0]),
326*46135Smao 					      (char *) &chain,
327*46135Smao 					      sizeof(chain));
328*46135Smao 				BLSWAP(chain);
329*46135Smao 				(void) bcopy((char *) &chain,
330*46135Smao 					      (char *) &(id->i_bytes[0]),
331*46135Smao 					      sizeof(chain));
332*46135Smao 			}
333*46135Smao 			BLSWAP(h->h_linp[i]);
334*46135Smao 		}
335*46135Smao 	}
336*46135Smao 	BLSWAP(h->h_flags);
337*46135Smao 	BLSWAP(h->h_pgno);
338*46135Smao 	BLSWAP(h->h_prevpg);
339*46135Smao 	BLSWAP(h->h_nextpg);
340*46135Smao 	BLSWAP(h->h_lower);
341*46135Smao 	BLSWAP(h->h_upper);
342*46135Smao 
343*46135Smao 	return (RET_SUCCESS);
344*46135Smao }
345*46135Smao 
346*46135Smao int
347*46135Smao _bt_pgin(h, _lorder)
348*46135Smao 	BTHEADER *h;
349*46135Smao 	char *_lorder;
350*46135Smao {
351*46135Smao 	int i;
352*46135Smao 	int top;
353*46135Smao 	int lorder;
354*46135Smao 	DATUM *d;
355*46135Smao 	IDATUM *id;
356*46135Smao 	size_t chain;
357*46135Smao 
358*46135Smao 	/*
359*46135Smao 	 *  If btree pages are to be stored in the host byte order, don't
360*46135Smao 	 *  bother swapping.
361*46135Smao 	 */
362*46135Smao 	lorder = (int) _lorder;
363*46135Smao 	if (lorder == BYTE_ORDER)
364*46135Smao 		return (RET_SUCCESS);
365*46135Smao 
366*46135Smao 	BLSWAP(h->h_upper);
367*46135Smao 	BLSWAP(h->h_lower);
368*46135Smao 	BLSWAP(h->h_nextpg);
369*46135Smao 	BLSWAP(h->h_prevpg);
370*46135Smao 	BLSWAP(h->h_pgno);
371*46135Smao 	BLSWAP(h->h_flags);
372*46135Smao 
373*46135Smao 	if (h->h_flags & F_LEAF) {
374*46135Smao 		if (h->h_flags & F_CONT) {
375*46135Smao 			if (h->h_prevpg == P_NONE) {
376*46135Smao 				size_t longsz;
377*46135Smao 
378*46135Smao 				(void) bcopy((char *) &(h->h_linp[0]),
379*46135Smao 					      (char *) &longsz,
380*46135Smao 					      sizeof(longsz));
381*46135Smao 				BLSWAP(longsz);
382*46135Smao 				(void) bcopy((char *) &longsz,
383*46135Smao 					      (char *) &(h->h_linp[0]),
384*46135Smao 					      sizeof(longsz));
385*46135Smao 			}
386*46135Smao 		} else {
387*46135Smao 			top = NEXTINDEX(h);
388*46135Smao 			for (i = 0; i < top; i++) {
389*46135Smao 				BLSWAP(h->h_linp[i]);
390*46135Smao 				d = (DATUM *) GETDATUM(h, i);
391*46135Smao 				BLSWAP(d->d_dsize);
392*46135Smao 				BLSWAP(d->d_ksize);
393*46135Smao 				BLSWAP(d->d_flags);
394*46135Smao 				if (d->d_flags & D_BIGKEY) {
395*46135Smao 					(void) bcopy((char *) &(d->d_bytes[0]),
396*46135Smao 						      (char *) &chain,
397*46135Smao 						      sizeof(chain));
398*46135Smao 					BLSWAP(chain);
399*46135Smao 					(void) bcopy((char *) &chain,
400*46135Smao 						      (char *) &(d->d_bytes[0]),
401*46135Smao 						      sizeof(chain));
402*46135Smao 				}
403*46135Smao 				if (d->d_flags & D_BIGDATA) {
404*46135Smao 					(void) bcopy((char *) &(d->d_bytes[d->d_ksize]),
405*46135Smao 						      (char *) &chain,
406*46135Smao 						      sizeof(chain));
407*46135Smao 					BLSWAP(chain);
408*46135Smao 					(void) bcopy((char *) &chain,
409*46135Smao 						      (char *) &(d->d_bytes[d->d_ksize]),
410*46135Smao 						      sizeof(chain));
411*46135Smao 				}
412*46135Smao 			}
413*46135Smao 		}
414*46135Smao 	} else {
415*46135Smao 		top = NEXTINDEX(h);
416*46135Smao 		for (i = 0; i < top; i++) {
417*46135Smao 			BLSWAP(h->h_linp[i]);
418*46135Smao 			id = (IDATUM *) GETDATUM(h, i);
419*46135Smao 			BLSWAP(id->i_size);
420*46135Smao 			BLSWAP(id->i_pgno);
421*46135Smao 			BLSWAP(id->i_flags);
422*46135Smao 			if (id->i_flags & D_BIGKEY) {
423*46135Smao 				(void) bcopy((char *) &(id->i_bytes[0]),
424*46135Smao 					      (char *) &chain,
425*46135Smao 					      sizeof(chain));
426*46135Smao 				BLSWAP(chain);
427*46135Smao 				(void) bcopy((char *) &chain,
428*46135Smao 					      (char *) &(id->i_bytes[0]),
429*46135Smao 					      sizeof(chain));
430*46135Smao 			}
431*46135Smao 		}
432*46135Smao 	}
433*46135Smao 	return (RET_SUCCESS);
434*46135Smao }
435*46135Smao 
436*46135Smao /*
437*46135Smao  *  _BT_ALLOCPG -- allocate a new page in the btree.
438*46135Smao  *
439*46135Smao  *	This is called when we split a page, to get space to do the split.
440*46135Smao  *	For disk btrees, these pages are released when the split is done.
441*46135Smao  *	For memory btrees, they are not.
442*46135Smao  *
443*46135Smao  *	Parameters:
444*46135Smao  *		t -- tree in which to do split
445*46135Smao  *
446*46135Smao  *	Returns:
447*46135Smao  *		Pointer to the newly-allocated page
448*46135Smao  */
449*46135Smao 
450*46135Smao BTHEADER *
451*46135Smao _bt_allocpg(t)
452*46135Smao 	BTREE_P t;
453*46135Smao {
454*46135Smao 	BTHEADER *h = t->bt_curpage;
455*46135Smao 	BTHEADER *nh;
456*46135Smao 	int nbytes;
457*46135Smao 
458*46135Smao 	/* if we have a cache, let the cache code do the work */
459*46135Smao 	if (ISDISK(t) && ISCACHE(t)) {
460*46135Smao 		nh = (BTHEADER *) lrugetnew(t->bt_s.bt_d.d_cache,
461*46135Smao 					    (int) (t->bt_npages + 1),
462*46135Smao 					    &nbytes);
463*46135Smao 	} else {
464*46135Smao 		nh = (BTHEADER *) malloc((unsigned) t->bt_psize);
465*46135Smao 	}
466*46135Smao 
467*46135Smao 	if (nh != (BTHEADER *) NULL) {
468*46135Smao 		nh->h_pgno = nh->h_prevpg = nh->h_nextpg = P_NONE;
469*46135Smao 		nh->h_flags = h->h_flags;
470*46135Smao 		nh->h_lower = (index_t)
471*46135Smao 				(((char *) &(nh->h_linp[0])) - ((char *) nh));
472*46135Smao 		nh->h_upper = t->bt_psize;
473*46135Smao 	}
474*46135Smao 
475*46135Smao 	return (nh);
476*46135Smao }
477*46135Smao 
478*46135Smao /*
479*46135Smao  *  _BT_WRITE -- Write a specific page to a btree file.
480*46135Smao  *
481*46135Smao  *	Parameters:
482*46135Smao  *		t -- btree to get the page
483*46135Smao  *		h -- page to write
484*46135Smao  *		relflag -- (int) this page may/may not be released
485*46135Smao  *
486*46135Smao  *	Returns:
487*46135Smao  *		RET_SUCCESS, RET_ERROR.
488*46135Smao  *
489*46135Smao  *	Side Effects:
490*46135Smao  *		Writes a metadata page if none has been written yet.
491*46135Smao  */
492*46135Smao 
493*46135Smao int
494*46135Smao _bt_write(t, h, relflag)
495*46135Smao 	BTREE_P t;
496*46135Smao 	BTHEADER *h;
497*46135Smao 	int relflag;
498*46135Smao {
499*46135Smao 	long pos;
500*46135Smao 	int htindex;
501*46135Smao 	HTBUCKET *b;
502*46135Smao 	char *cache;
503*46135Smao 	pgno_t pgno;
504*46135Smao 
505*46135Smao 	h->h_flags &= ~F_DIRTY;
506*46135Smao 	if (ISDISK(t)) {
507*46135Smao 
508*46135Smao 		/* if we haven't done so yet, write the metadata */
509*46135Smao 		if (!(t->bt_flags & BTF_METAOK)) {
510*46135Smao 			if (_bt_wrtmeta(t) == RET_ERROR)
511*46135Smao 				return (RET_ERROR);
512*46135Smao 		}
513*46135Smao 
514*46135Smao 		pgno = h->h_pgno;
515*46135Smao 
516*46135Smao 
517*46135Smao 		/* if we have a cache, let the cache code do the work */
518*46135Smao 		if ((cache = t->bt_s.bt_d.d_cache) != (char *) NULL) {
519*46135Smao 			if (lruwrite(cache, (int) pgno) < 0)
520*46135Smao 				return (RET_ERROR);
521*46135Smao 			if (relflag && lrurelease(cache, (int) pgno) < 0)
522*46135Smao 				return (RET_ERROR);
523*46135Smao 
524*46135Smao 		} else {
525*46135Smao 			(void) _bt_pgout(h, (char *) t->bt_lorder);
526*46135Smao 			/* now write the current page */
527*46135Smao 			pos = (long) (pgno * t->bt_psize);
528*46135Smao 			if (lseek(t->bt_s.bt_d.d_fd, pos, L_SET) != pos)
529*46135Smao 				return (RET_ERROR);
530*46135Smao 			if (write(t->bt_s.bt_d.d_fd, (char *) h, (int) t->bt_psize)
531*46135Smao 			    < t->bt_psize)
532*46135Smao 				return (RET_ERROR);
533*46135Smao 			if (!relflag)
534*46135Smao 				(void) _bt_pgin(h, (char *) t->bt_lorder);
535*46135Smao 		}
536*46135Smao 	} else {
537*46135Smao 		/* in-memory btree */
538*46135Smao 		htindex = HASHKEY(h->h_pgno);
539*46135Smao 
540*46135Smao 		/* see if we need to overwrite existing entry */
541*46135Smao 		for (b = t->bt_s.bt_ht[htindex];
542*46135Smao 		     b != (HTBUCKET *) NULL;
543*46135Smao 		     b = b->ht_next) {
544*46135Smao 			if (b->ht_pgno == h->h_pgno) {
545*46135Smao 				b->ht_page = h;
546*46135Smao 				return (RET_SUCCESS);
547*46135Smao 			}
548*46135Smao 		}
549*46135Smao 
550*46135Smao 		/* new entry, write it */
551*46135Smao 		b = (HTBUCKET *) malloc((unsigned) sizeof (HTBUCKET));
552*46135Smao 		if (b == (HTBUCKET *) NULL)
553*46135Smao 			return (RET_ERROR);
554*46135Smao 
555*46135Smao 		b->ht_pgno = h->h_pgno;
556*46135Smao 		b->ht_page = h;
557*46135Smao 		b->ht_next = t->bt_s.bt_ht[htindex];
558*46135Smao 		t->bt_s.bt_ht[htindex] = b;
559*46135Smao 	}
560*46135Smao 	return (RET_SUCCESS);
561*46135Smao }
562*46135Smao 
563*46135Smao /*
564*46135Smao  *  _BT_RELEASE -- Release a locked-down cache page
565*46135Smao  *
566*46135Smao  *	During page splits, we want to force pages out to the cache
567*46135Smao  *	before we actually release them, in some cases.  This routine
568*46135Smao  *	releases such a page when it is no longer needed.
569*46135Smao  *
570*46135Smao  *	Parameters:
571*46135Smao  *		t -- btree in which to release page
572*46135Smao  *		h -- page to release
573*46135Smao  *
574*46135Smao  *	Returns:
575*46135Smao  *		RET_SUCCESS, RET_ERROR.
576*46135Smao  *
577*46135Smao  *	Side Effects:
578*46135Smao  *		None.
579*46135Smao  */
580*46135Smao 
581*46135Smao int
582*46135Smao _bt_release(t, h)
583*46135Smao 	BTREE_P t;
584*46135Smao 	BTHEADER *h;
585*46135Smao {
586*46135Smao 	if (ISDISK(t) && ISCACHE(t)) {
587*46135Smao 		if (lrurelease(t->bt_s.bt_d.d_cache, (int) (h->h_pgno)) < 0)
588*46135Smao 			return (RET_ERROR);
589*46135Smao 	}
590*46135Smao 	return (RET_SUCCESS);
591*46135Smao }
592*46135Smao 
593*46135Smao /*
594*46135Smao  *  _BT_WRTMETA -- Write metadata to the btree.
595*46135Smao  *
596*46135Smao  *	Parameters:
597*46135Smao  *		t -- tree to which to write
598*46135Smao  *
599*46135Smao  *	Returns:
600*46135Smao  *		RET_SUCCESS, RET_ERROR.
601*46135Smao  */
602*46135Smao 
603*46135Smao int
604*46135Smao _bt_wrtmeta(t)
605*46135Smao 	BTREE_P t;
606*46135Smao {
607*46135Smao 	BTMETA m;
608*46135Smao 
609*46135Smao 	if (lseek(t->bt_s.bt_d.d_fd, 0l, L_SET) != 0l)
610*46135Smao 		return (RET_ERROR);
611*46135Smao 
612*46135Smao 	/* lorder has to be in host-independent format */
613*46135Smao 	m.m_lorder = (u_long) htonl((long) t->bt_lorder);
614*46135Smao 
615*46135Smao 	m.m_magic = BTREEMAGIC;
616*46135Smao 	m.m_version = BTREEVERSION;
617*46135Smao 	m.m_psize = t->bt_psize;
618*46135Smao 	m.m_free = t->bt_free;
619*46135Smao 	m.m_flags = t->bt_flags & BTF_NODUPS;
620*46135Smao 
621*46135Smao 	if (t->bt_lorder != BYTE_ORDER) {
622*46135Smao 		BLSWAP(m.m_magic);
623*46135Smao 		BLSWAP(m.m_version);
624*46135Smao 		BLSWAP(m.m_psize);
625*46135Smao 		BLSWAP(m.m_free);
626*46135Smao 		BLSWAP(m.m_flags);
627*46135Smao 	}
628*46135Smao 
629*46135Smao 	if (write(t->bt_s.bt_d.d_fd, (char *) &m, sizeof(m))
630*46135Smao 	    != sizeof(m)) {
631*46135Smao 		return (RET_ERROR);
632*46135Smao 	}
633*46135Smao 
634*46135Smao 	t->bt_flags |= BTF_METAOK;
635*46135Smao 
636*46135Smao 	return (RET_SUCCESS);
637*46135Smao }
638