xref: /original-bsd/lib/libc/db/btree/bt_close.c (revision de3be680)
1 /*-
2  * Copyright (c) 1990 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Mike Olson.
7  *
8  * %sccs.include.redist.c%
9  */
10 
11 #if defined(LIBC_SCCS) && !defined(lint)
12 static char sccsid[] = "@(#)bt_close.c	5.2 (Berkeley) 09/12/91";
13 #endif /* LIBC_SCCS and not lint */
14 
15 #include <sys/param.h>
16 #include <errno.h>
17 #include <db.h>
18 #include <unistd.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include "btree.h"
23 
24 static int bt_meta __P((BTREE *));
25 
26 /*
27  * BT_CLOSE -- Close a btree.
28  *
29  * Parameters:
30  *	dbp:	pointer to access method
31  *
32  * Returns:
33  *	RET_ERROR, RET_SUCCESS
34  */
35 int
36 __bt_close(dbp)
37 	DB *dbp;
38 {
39 	BTREE *t;
40 	int fd;
41 
42 	t = dbp->internal;
43 
44 	/*
45 	 * Delete any already deleted record that we've been saving
46 	 * because the cursor pointed to it.
47 	 */
48 	if (ISSET(t, BTF_DELCRSR) && __bt_crsrdel(t, &t->bt_bcursor))
49 		return (RET_ERROR);
50 
51 	if (__bt_sync(dbp) == RET_ERROR)
52 		return (RET_ERROR);
53 
54 	if (mpool_close(t->bt_mp) == RET_ERROR)
55 		return (RET_ERROR);
56 
57 	if (t->bt_stack)
58 		free(t->bt_stack);
59 	if (t->bt_kbuf)
60 		free(t->bt_kbuf);
61 	if (t->bt_dbuf)
62 		free(t->bt_dbuf);
63 
64 	fd = t->bt_fd;
65 	free(t);
66 	free(dbp);
67 	return (close(fd) ? RET_ERROR : RET_SUCCESS);
68 }
69 
70 /*
71  * BT_SYNC -- sync the btree to disk.
72  *
73  * Parameters:
74  *	dbp:	pointer to access method
75  *
76  * Returns:
77  *	RET_SUCCESS, RET_ERROR.
78  */
79 int
80 __bt_sync(dbp)
81 	const DB *dbp;
82 {
83 	BTREE *t;
84 	int status;
85 	PAGE *h;
86 	void *p;
87 
88 	t = dbp->internal;
89 
90 	if (ISSET(t, BTF_INMEM) || ISSET(t, BTF_RDONLY))
91 		return (RET_SUCCESS);
92 
93 	if (ISSET(t, BTF_METADIRTY) && bt_meta(t) == RET_ERROR)
94 		return (RET_ERROR);
95 
96 	/*
97 	 * Nastiness.  If the cursor has been marked for deletion, but not
98 	 * actually deleted, we have to make a copy of the page, delete the
99 	 * key/data item, sync the file, and then restore the original page
100 	 * contents.
101 	 */
102 	if (ISSET(t, BTF_DELCRSR)) {
103 		if ((h = mpool_get(t->bt_mp, t->bt_bcursor.pgno, 0)) == NULL)
104 			return (RET_ERROR);
105 		if ((p = malloc(t->bt_psize)) == NULL) {
106 			mpool_put(t->bt_mp, h, 0);
107 			return (RET_ERROR);
108 		}
109 		bcopy(h, p, t->bt_psize);
110 		if (__bt_dleaf(t, h, t->bt_bcursor.index) == RET_ERROR)
111 			goto ecrsr;
112 	}
113 
114 	if ((status = mpool_sync(t->bt_mp)) == RET_SUCCESS)
115 		UNSET(t, BTF_MODIFIED);
116 ecrsr:	if (ISSET(t, BTF_DELCRSR)) {
117 		bcopy(p, h, t->bt_psize);
118 		free(p);
119 		mpool_put(t->bt_mp, h, 0);
120 	}
121 	return (status);
122 }
123 
124 /*
125  * BT_META -- write the tree meta data to disk.
126  *
127  * Parameters:
128  *	t:	tree
129  *
130  * Returns:
131  *	RET_ERROR, RET_SUCCESS
132  */
133 static int
134 bt_meta(t)
135 	BTREE *t;
136 {
137 	BTMETA m;
138 	void *p;
139 
140 	if ((p = mpool_get(t->bt_mp, P_META, 0)) == NULL)
141 		return (RET_ERROR);
142 
143 	/* Fill in metadata -- lorder is host-independent. */
144 	m.m_magic = BTREEMAGIC;
145 	m.m_version = BTREEVERSION;
146 	m.m_psize = t->bt_psize;
147 	m.m_free = 0;           		/* XXX */
148 	m.m_nrecs = t->bt_nrecs;
149 	m.m_flags = t->bt_flags & SAVEMETA;
150 	m.m_lorder = htonl((long)t->bt_lorder);
151 
152 	if (t->bt_lorder != BYTE_ORDER) {
153 		BLSWAP(m.m_magic);
154 		BLSWAP(m.m_version);
155 		BLSWAP(m.m_psize);
156 		BLSWAP(m.m_free);
157 		BLSWAP(m.m_nrecs);
158 		BLSWAP(m.m_flags);
159 	}
160 
161 	bcopy(&m, p, sizeof(BTMETA));
162 	mpool_put(t->bt_mp, p, MPOOL_DIRTY);
163 	return (RET_SUCCESS);
164 }
165