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