xref: /csrg-svn/lib/libc/db/btree/bt_close.c (revision 57652)
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*57652Sbostic static char sccsid[] = "@(#)bt_close.c	5.8 (Berkeley) 01/22/93";
1350990Sbostic #endif /* LIBC_SCCS and not lint */
1450990Sbostic 
1550990Sbostic #include <sys/param.h>
1656742Sbostic 
1756742Sbostic #include <db.h>
1850990Sbostic #include <errno.h>
1950990Sbostic #include <stdio.h>
2050990Sbostic #include <stdlib.h>
2150990Sbostic #include <string.h>
2256742Sbostic #include <unistd.h>
2356742Sbostic 
2450990Sbostic #include "btree.h"
2550990Sbostic 
2650990Sbostic static int bt_meta __P((BTREE *));
2750990Sbostic 
2850990Sbostic /*
2950990Sbostic  * BT_CLOSE -- Close a btree.
3050990Sbostic  *
3150990Sbostic  * Parameters:
3250990Sbostic  *	dbp:	pointer to access method
3350990Sbostic  *
3450990Sbostic  * Returns:
3550990Sbostic  *	RET_ERROR, RET_SUCCESS
3650990Sbostic  */
3750990Sbostic int
3850990Sbostic __bt_close(dbp)
3950990Sbostic 	DB *dbp;
4050990Sbostic {
4150990Sbostic 	BTREE *t;
4250990Sbostic 	int fd;
4350990Sbostic 
4450990Sbostic 	t = dbp->internal;
4550990Sbostic 
4650990Sbostic 	/*
4750990Sbostic 	 * Delete any already deleted record that we've been saving
4850990Sbostic 	 * because the cursor pointed to it.
4950990Sbostic 	 */
5050990Sbostic 	if (ISSET(t, BTF_DELCRSR) && __bt_crsrdel(t, &t->bt_bcursor))
5150990Sbostic 		return (RET_ERROR);
5250990Sbostic 
5350990Sbostic 	if (__bt_sync(dbp) == RET_ERROR)
5450990Sbostic 		return (RET_ERROR);
5550990Sbostic 
5650990Sbostic 	if (mpool_close(t->bt_mp) == RET_ERROR)
5750990Sbostic 		return (RET_ERROR);
5850990Sbostic 
5950990Sbostic 	if (t->bt_stack)
6050990Sbostic 		free(t->bt_stack);
6150990Sbostic 	if (t->bt_kbuf)
6250990Sbostic 		free(t->bt_kbuf);
6350990Sbostic 	if (t->bt_dbuf)
6450990Sbostic 		free(t->bt_dbuf);
6550990Sbostic 
6650990Sbostic 	fd = t->bt_fd;
6750990Sbostic 	free(t);
6850990Sbostic 	free(dbp);
6950990Sbostic 	return (close(fd) ? RET_ERROR : RET_SUCCESS);
7050990Sbostic }
7150990Sbostic 
7250990Sbostic /*
7350990Sbostic  * BT_SYNC -- sync the btree to disk.
7450990Sbostic  *
7550990Sbostic  * Parameters:
7650990Sbostic  *	dbp:	pointer to access method
7750990Sbostic  *
7850990Sbostic  * Returns:
7950990Sbostic  *	RET_SUCCESS, RET_ERROR.
8050990Sbostic  */
8150990Sbostic int
8250990Sbostic __bt_sync(dbp)
8350990Sbostic 	const DB *dbp;
8450990Sbostic {
8550990Sbostic 	BTREE *t;
8650990Sbostic 	int status;
8751097Sbostic 	PAGE *h;
8851097Sbostic 	void *p;
8950990Sbostic 
9050990Sbostic 	t = dbp->internal;
9150990Sbostic 
9256742Sbostic 	if (ISSET(t, BTF_INMEM | BTF_RDONLY) || !ISSET(t, BTF_MODIFIED))
9350990Sbostic 		return (RET_SUCCESS);
9450990Sbostic 
9550990Sbostic 	if (ISSET(t, BTF_METADIRTY) && bt_meta(t) == RET_ERROR)
9650990Sbostic 		return (RET_ERROR);
9750990Sbostic 
9851097Sbostic 	/*
9951097Sbostic 	 * Nastiness.  If the cursor has been marked for deletion, but not
10051097Sbostic 	 * actually deleted, we have to make a copy of the page, delete the
10151097Sbostic 	 * key/data item, sync the file, and then restore the original page
10251097Sbostic 	 * contents.
10351097Sbostic 	 */
10451097Sbostic 	if (ISSET(t, BTF_DELCRSR)) {
10556742Sbostic 		if ((p = malloc(t->bt_psize)) == NULL)
10656742Sbostic 			return (RET_ERROR);
10751097Sbostic 		if ((h = mpool_get(t->bt_mp, t->bt_bcursor.pgno, 0)) == NULL)
10851097Sbostic 			return (RET_ERROR);
10951097Sbostic 		bcopy(h, p, t->bt_psize);
11056742Sbostic 		if (status =
11156742Sbostic 		    __bt_dleaf(t, h, t->bt_bcursor.index) == RET_ERROR)
11251097Sbostic 			goto ecrsr;
113*57652Sbostic 		mpool_put(t->bt_mp, h, MPOOL_DIRTY);
11451097Sbostic 	}
11551097Sbostic 
11651097Sbostic 	if ((status = mpool_sync(t->bt_mp)) == RET_SUCCESS)
11756742Sbostic 		CLR(t, BTF_MODIFIED);
11856742Sbostic 
11951097Sbostic ecrsr:	if (ISSET(t, BTF_DELCRSR)) {
120*57652Sbostic 		if ((h = mpool_get(t->bt_mp, t->bt_bcursor.pgno, 0)) == NULL)
121*57652Sbostic 			return (RET_ERROR);
12251097Sbostic 		bcopy(p, h, t->bt_psize);
12351097Sbostic 		free(p);
124*57652Sbostic 		mpool_put(t->bt_mp, h, MPOOL_DIRTY);
12550990Sbostic 	}
12650990Sbostic 	return (status);
12750990Sbostic }
12850990Sbostic 
12950990Sbostic /*
13050990Sbostic  * BT_META -- write the tree meta data to disk.
13150990Sbostic  *
13250990Sbostic  * Parameters:
13350990Sbostic  *	t:	tree
13450990Sbostic  *
13550990Sbostic  * Returns:
13650990Sbostic  *	RET_ERROR, RET_SUCCESS
13750990Sbostic  */
13850990Sbostic static int
13950990Sbostic bt_meta(t)
14050990Sbostic 	BTREE *t;
14150990Sbostic {
14250990Sbostic 	BTMETA m;
14350990Sbostic 	void *p;
14450990Sbostic 
14550990Sbostic 	if ((p = mpool_get(t->bt_mp, P_META, 0)) == NULL)
14650990Sbostic 		return (RET_ERROR);
14750990Sbostic 
14851097Sbostic 	/* Fill in metadata -- lorder is host-independent. */
14950990Sbostic 	m.m_magic = BTREEMAGIC;
15050990Sbostic 	m.m_version = BTREEVERSION;
15150990Sbostic 	m.m_psize = t->bt_psize;
15256491Sbostic 	m.m_free = t->bt_free;
15350990Sbostic 	m.m_nrecs = t->bt_nrecs;
15450990Sbostic 	m.m_flags = t->bt_flags & SAVEMETA;
15551970Sbostic 	m.m_lorder = htonl((u_long)t->bt_lorder);
15650990Sbostic 
15750990Sbostic 	if (t->bt_lorder != BYTE_ORDER) {
15850990Sbostic 		BLSWAP(m.m_magic);
15950990Sbostic 		BLSWAP(m.m_version);
16050990Sbostic 		BLSWAP(m.m_psize);
16150990Sbostic 		BLSWAP(m.m_free);
16250990Sbostic 		BLSWAP(m.m_nrecs);
16350990Sbostic 		BLSWAP(m.m_flags);
16450990Sbostic 	}
16550990Sbostic 
16650990Sbostic 	bcopy(&m, p, sizeof(BTMETA));
16750990Sbostic 	mpool_put(t->bt_mp, p, MPOOL_DIRTY);
16850990Sbostic 	return (RET_SUCCESS);
16950990Sbostic }
170