xref: /csrg-svn/lib/libc/db/btree/bt_close.c (revision 51970)
150990Sbostic /*-
250990Sbostic  * Copyright (c) 1990 The Regents of the University of California.
350990Sbostic  * All rights reserved.
450990Sbostic  *
550990Sbostic  * This code is derived from software contributed to Berkeley by
650990Sbostic  * Mike Olson.
750990Sbostic  *
850990Sbostic  * %sccs.include.redist.c%
950990Sbostic  */
1050990Sbostic 
1150990Sbostic #if defined(LIBC_SCCS) && !defined(lint)
12*51970Sbostic static char sccsid[] = "@(#)bt_close.c	5.4 (Berkeley) 12/16/91";
1350990Sbostic #endif /* LIBC_SCCS and not lint */
1450990Sbostic 
1550990Sbostic #include <sys/param.h>
1650990Sbostic #include <errno.h>
1750990Sbostic #include <db.h>
1850990Sbostic #include <unistd.h>
1950990Sbostic #include <stdio.h>
2050990Sbostic #include <stdlib.h>
2150990Sbostic #include <string.h>
2250990Sbostic #include "btree.h"
2350990Sbostic 
2450990Sbostic static int bt_meta __P((BTREE *));
2550990Sbostic 
2650990Sbostic /*
2750990Sbostic  * BT_CLOSE -- Close a btree.
2850990Sbostic  *
2950990Sbostic  * Parameters:
3050990Sbostic  *	dbp:	pointer to access method
3150990Sbostic  *
3250990Sbostic  * Returns:
3350990Sbostic  *	RET_ERROR, RET_SUCCESS
3450990Sbostic  */
3550990Sbostic int
3650990Sbostic __bt_close(dbp)
3750990Sbostic 	DB *dbp;
3850990Sbostic {
3950990Sbostic 	BTREE *t;
4050990Sbostic 	int fd;
4150990Sbostic 
4250990Sbostic 	t = dbp->internal;
4350990Sbostic 
4450990Sbostic 	/*
4550990Sbostic 	 * Delete any already deleted record that we've been saving
4650990Sbostic 	 * because the cursor pointed to it.
4750990Sbostic 	 */
4850990Sbostic 	if (ISSET(t, BTF_DELCRSR) && __bt_crsrdel(t, &t->bt_bcursor))
4950990Sbostic 		return (RET_ERROR);
5050990Sbostic 
5150990Sbostic 	if (__bt_sync(dbp) == RET_ERROR)
5250990Sbostic 		return (RET_ERROR);
5350990Sbostic 
5450990Sbostic 	if (mpool_close(t->bt_mp) == RET_ERROR)
5550990Sbostic 		return (RET_ERROR);
5650990Sbostic 
5750990Sbostic 	if (t->bt_stack)
5850990Sbostic 		free(t->bt_stack);
5950990Sbostic 	if (t->bt_kbuf)
6050990Sbostic 		free(t->bt_kbuf);
6150990Sbostic 	if (t->bt_dbuf)
6250990Sbostic 		free(t->bt_dbuf);
6350990Sbostic 
6450990Sbostic 	fd = t->bt_fd;
6550990Sbostic 	free(t);
6650990Sbostic 	free(dbp);
6750990Sbostic 	return (close(fd) ? RET_ERROR : RET_SUCCESS);
6850990Sbostic }
6950990Sbostic 
7050990Sbostic /*
7150990Sbostic  * BT_SYNC -- sync the btree to disk.
7250990Sbostic  *
7350990Sbostic  * Parameters:
7450990Sbostic  *	dbp:	pointer to access method
7550990Sbostic  *
7650990Sbostic  * Returns:
7750990Sbostic  *	RET_SUCCESS, RET_ERROR.
7850990Sbostic  */
7950990Sbostic int
8050990Sbostic __bt_sync(dbp)
8150990Sbostic 	const DB *dbp;
8250990Sbostic {
8350990Sbostic 	BTREE *t;
8450990Sbostic 	int status;
8551097Sbostic 	PAGE *h;
8651097Sbostic 	void *p;
8750990Sbostic 
8850990Sbostic 	t = dbp->internal;
8950990Sbostic 
9051097Sbostic 	if (ISSET(t, BTF_INMEM) || ISSET(t, BTF_RDONLY))
9150990Sbostic 		return (RET_SUCCESS);
9250990Sbostic 
9350990Sbostic 	if (ISSET(t, BTF_METADIRTY) && bt_meta(t) == RET_ERROR)
9450990Sbostic 		return (RET_ERROR);
9550990Sbostic 
9651097Sbostic 	/*
9751097Sbostic 	 * Nastiness.  If the cursor has been marked for deletion, but not
9851097Sbostic 	 * actually deleted, we have to make a copy of the page, delete the
9951097Sbostic 	 * key/data item, sync the file, and then restore the original page
10051097Sbostic 	 * contents.
10151097Sbostic 	 */
10251097Sbostic 	if (ISSET(t, BTF_DELCRSR)) {
10351097Sbostic 		if ((h = mpool_get(t->bt_mp, t->bt_bcursor.pgno, 0)) == NULL)
10451097Sbostic 			return (RET_ERROR);
10551097Sbostic 		if ((p = malloc(t->bt_psize)) == NULL) {
10651097Sbostic 			mpool_put(t->bt_mp, h, 0);
10751097Sbostic 			return (RET_ERROR);
10851097Sbostic 		}
10951097Sbostic 		bcopy(h, p, t->bt_psize);
11051097Sbostic 		if (__bt_dleaf(t, h, t->bt_bcursor.index) == RET_ERROR)
11151097Sbostic 			goto ecrsr;
11251097Sbostic 	}
11351097Sbostic 
11451097Sbostic 	if ((status = mpool_sync(t->bt_mp)) == RET_SUCCESS)
11550990Sbostic 		UNSET(t, BTF_MODIFIED);
11651097Sbostic ecrsr:	if (ISSET(t, BTF_DELCRSR)) {
11751097Sbostic 		bcopy(p, h, t->bt_psize);
11851097Sbostic 		free(p);
11951097Sbostic 		mpool_put(t->bt_mp, h, 0);
12050990Sbostic 	}
12150990Sbostic 	return (status);
12250990Sbostic }
12350990Sbostic 
12450990Sbostic /*
12550990Sbostic  * BT_META -- write the tree meta data to disk.
12650990Sbostic  *
12750990Sbostic  * Parameters:
12850990Sbostic  *	t:	tree
12950990Sbostic  *
13050990Sbostic  * Returns:
13150990Sbostic  *	RET_ERROR, RET_SUCCESS
13250990Sbostic  */
13350990Sbostic static int
13450990Sbostic bt_meta(t)
13550990Sbostic 	BTREE *t;
13650990Sbostic {
13750990Sbostic 	BTMETA m;
13850990Sbostic 	void *p;
13950990Sbostic 
14050990Sbostic 	if ((p = mpool_get(t->bt_mp, P_META, 0)) == NULL)
14150990Sbostic 		return (RET_ERROR);
14250990Sbostic 
14351097Sbostic 	/* Fill in metadata -- lorder is host-independent. */
14450990Sbostic 	m.m_magic = BTREEMAGIC;
14550990Sbostic 	m.m_version = BTREEVERSION;
14650990Sbostic 	m.m_psize = t->bt_psize;
14751097Sbostic 	m.m_free = 0;           		/* XXX */
14850990Sbostic 	m.m_nrecs = t->bt_nrecs;
14950990Sbostic 	m.m_flags = t->bt_flags & SAVEMETA;
150*51970Sbostic 	m.m_lorder = htonl((u_long)t->bt_lorder);
15150990Sbostic 
15250990Sbostic 	if (t->bt_lorder != BYTE_ORDER) {
15350990Sbostic 		BLSWAP(m.m_magic);
15450990Sbostic 		BLSWAP(m.m_version);
15550990Sbostic 		BLSWAP(m.m_psize);
15650990Sbostic 		BLSWAP(m.m_free);
15750990Sbostic 		BLSWAP(m.m_nrecs);
15850990Sbostic 		BLSWAP(m.m_flags);
15950990Sbostic 	}
16050990Sbostic 
16150990Sbostic 	bcopy(&m, p, sizeof(BTMETA));
16250990Sbostic 	mpool_put(t->bt_mp, p, MPOOL_DIRTY);
16350990Sbostic 	return (RET_SUCCESS);
16450990Sbostic }
165