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