xref: /csrg-svn/lib/libc/db/btree/bt_close.c (revision 64460)
150990Sbostic /*-
261194Sbostic  * Copyright (c) 1990, 1993
361194Sbostic  *	The Regents of the University of California.  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*64460Sbostic static char sccsid[] = "@(#)bt_close.c	8.2 (Berkeley) 09/07/93";
1350990Sbostic #endif /* LIBC_SCCS and not lint */
1450990Sbostic 
1550990Sbostic #include <sys/param.h>
1656742Sbostic 
1750990Sbostic #include <errno.h>
1850990Sbostic #include <stdio.h>
1950990Sbostic #include <stdlib.h>
2050990Sbostic #include <string.h>
2156742Sbostic #include <unistd.h>
2256742Sbostic 
2357932Sbostic #include <db.h>
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 
46*64460Sbostic 	/* Toss any page pinned across calls. */
47*64460Sbostic 	if (t->bt_pinned != NULL) {
48*64460Sbostic 		mpool_put(t->bt_mp, t->bt_pinned, 0);
49*64460Sbostic 		t->bt_pinned = NULL;
50*64460Sbostic 	}
51*64460Sbostic 
5250990Sbostic 	/*
5350990Sbostic 	 * Delete any already deleted record that we've been saving
5450990Sbostic 	 * because the cursor pointed to it.
5550990Sbostic 	 */
5660047Sbostic 	if (ISSET(t, B_DELCRSR) && __bt_crsrdel(t, &t->bt_bcursor))
5750990Sbostic 		return (RET_ERROR);
5850990Sbostic 
5960047Sbostic 	if (__bt_sync(dbp, 0) == RET_ERROR)
6050990Sbostic 		return (RET_ERROR);
6150990Sbostic 
6250990Sbostic 	if (mpool_close(t->bt_mp) == RET_ERROR)
6350990Sbostic 		return (RET_ERROR);
6450990Sbostic 
6550990Sbostic 	if (t->bt_stack)
6650990Sbostic 		free(t->bt_stack);
6750990Sbostic 	if (t->bt_kbuf)
6850990Sbostic 		free(t->bt_kbuf);
6950990Sbostic 	if (t->bt_dbuf)
7050990Sbostic 		free(t->bt_dbuf);
7150990Sbostic 
7250990Sbostic 	fd = t->bt_fd;
7350990Sbostic 	free(t);
7450990Sbostic 	free(dbp);
7550990Sbostic 	return (close(fd) ? RET_ERROR : RET_SUCCESS);
7650990Sbostic }
7750990Sbostic 
7850990Sbostic /*
7950990Sbostic  * BT_SYNC -- sync the btree to disk.
8050990Sbostic  *
8150990Sbostic  * Parameters:
8250990Sbostic  *	dbp:	pointer to access method
8350990Sbostic  *
8450990Sbostic  * Returns:
8550990Sbostic  *	RET_SUCCESS, RET_ERROR.
8650990Sbostic  */
8750990Sbostic int
8860047Sbostic __bt_sync(dbp, flags)
8950990Sbostic 	const DB *dbp;
9060047Sbostic 	u_int flags;
9150990Sbostic {
9250990Sbostic 	BTREE *t;
9350990Sbostic 	int status;
9451097Sbostic 	PAGE *h;
9551097Sbostic 	void *p;
9650990Sbostic 
97*64460Sbostic 	t = dbp->internal;
98*64460Sbostic 
99*64460Sbostic 	/* Toss any page pinned across calls. */
100*64460Sbostic 	if (t->bt_pinned != NULL) {
101*64460Sbostic 		mpool_put(t->bt_mp, t->bt_pinned, 0);
102*64460Sbostic 		t->bt_pinned = NULL;
103*64460Sbostic 	}
104*64460Sbostic 
105*64460Sbostic 	/* Sync doesn't currently take any flags. */
10660047Sbostic 	if (flags != 0) {
10760047Sbostic 		errno = EINVAL;
10860047Sbostic 		return (RET_ERROR);
10960047Sbostic 	}
11060047Sbostic 
11160047Sbostic 	if (ISSET(t, B_INMEM | B_RDONLY) || !ISSET(t, B_MODIFIED))
11250990Sbostic 		return (RET_SUCCESS);
11350990Sbostic 
11460047Sbostic 	if (ISSET(t, B_METADIRTY) && bt_meta(t) == RET_ERROR)
11550990Sbostic 		return (RET_ERROR);
11650990Sbostic 
11751097Sbostic 	/*
11851097Sbostic 	 * Nastiness.  If the cursor has been marked for deletion, but not
11951097Sbostic 	 * actually deleted, we have to make a copy of the page, delete the
12051097Sbostic 	 * key/data item, sync the file, and then restore the original page
12151097Sbostic 	 * contents.
12251097Sbostic 	 */
12360047Sbostic 	if (ISSET(t, B_DELCRSR)) {
12456742Sbostic 		if ((p = malloc(t->bt_psize)) == NULL)
12556742Sbostic 			return (RET_ERROR);
12651097Sbostic 		if ((h = mpool_get(t->bt_mp, t->bt_bcursor.pgno, 0)) == NULL)
12751097Sbostic 			return (RET_ERROR);
12858017Sbostic 		memmove(p, h, t->bt_psize);
12959630Sbostic 		if ((status =
13059630Sbostic 		    __bt_dleaf(t, h, t->bt_bcursor.index)) == RET_ERROR)
13151097Sbostic 			goto ecrsr;
13257652Sbostic 		mpool_put(t->bt_mp, h, MPOOL_DIRTY);
13351097Sbostic 	}
13451097Sbostic 
13551097Sbostic 	if ((status = mpool_sync(t->bt_mp)) == RET_SUCCESS)
13660047Sbostic 		CLR(t, B_MODIFIED);
13756742Sbostic 
13860047Sbostic ecrsr:	if (ISSET(t, B_DELCRSR)) {
13957652Sbostic 		if ((h = mpool_get(t->bt_mp, t->bt_bcursor.pgno, 0)) == NULL)
14057652Sbostic 			return (RET_ERROR);
14158017Sbostic 		memmove(h, p, t->bt_psize);
14251097Sbostic 		free(p);
14357652Sbostic 		mpool_put(t->bt_mp, h, MPOOL_DIRTY);
14450990Sbostic 	}
14550990Sbostic 	return (status);
14650990Sbostic }
14750990Sbostic 
14850990Sbostic /*
14950990Sbostic  * BT_META -- write the tree meta data to disk.
15050990Sbostic  *
15150990Sbostic  * Parameters:
15250990Sbostic  *	t:	tree
15350990Sbostic  *
15450990Sbostic  * Returns:
15550990Sbostic  *	RET_ERROR, RET_SUCCESS
15650990Sbostic  */
15750990Sbostic static int
15850990Sbostic bt_meta(t)
15950990Sbostic 	BTREE *t;
16050990Sbostic {
16150990Sbostic 	BTMETA m;
16250990Sbostic 	void *p;
16350990Sbostic 
16450990Sbostic 	if ((p = mpool_get(t->bt_mp, P_META, 0)) == NULL)
16550990Sbostic 		return (RET_ERROR);
16650990Sbostic 
16759630Sbostic 	/* Fill in metadata. */
16850990Sbostic 	m.m_magic = BTREEMAGIC;
16950990Sbostic 	m.m_version = BTREEVERSION;
17050990Sbostic 	m.m_psize = t->bt_psize;
17156491Sbostic 	m.m_free = t->bt_free;
17250990Sbostic 	m.m_nrecs = t->bt_nrecs;
17350990Sbostic 	m.m_flags = t->bt_flags & SAVEMETA;
17450990Sbostic 
17558017Sbostic 	memmove(p, &m, sizeof(BTMETA));
17650990Sbostic 	mpool_put(t->bt_mp, p, MPOOL_DIRTY);
17750990Sbostic 	return (RET_SUCCESS);
17850990Sbostic }
179