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*66214Sbostic static char sccsid[] = "@(#)bt_close.c 8.3 (Berkeley) 02/21/94";
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
__bt_close(dbp)3850990Sbostic __bt_close(dbp)
3950990Sbostic DB *dbp;
4050990Sbostic {
4150990Sbostic BTREE *t;
4250990Sbostic int fd;
4350990Sbostic
4450990Sbostic t = dbp->internal;
4550990Sbostic
4664460Sbostic /* Toss any page pinned across calls. */
4764460Sbostic if (t->bt_pinned != NULL) {
4864460Sbostic mpool_put(t->bt_mp, t->bt_pinned, 0);
4964460Sbostic t->bt_pinned = NULL;
5064460Sbostic }
5164460Sbostic
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
__bt_sync(dbp,flags)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
9764460Sbostic t = dbp->internal;
9864460Sbostic
9964460Sbostic /* Toss any page pinned across calls. */
10064460Sbostic if (t->bt_pinned != NULL) {
10164460Sbostic mpool_put(t->bt_mp, t->bt_pinned, 0);
10264460Sbostic t->bt_pinned = NULL;
10364460Sbostic }
10464460Sbostic
10564460Sbostic /* 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)) {
124*66214Sbostic if ((p = (void *)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
bt_meta(t)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