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