rec_close.c revision 56698
1280461Sdim/*- 2280461Sdim * Copyright (c) 1990, 1993, 1994 3353358Sdim * The Regents of the University of California. All rights reserved. 4353358Sdim * 5353358Sdim * Redistribution and use in source and binary forms, with or without 6280461Sdim * modification, are permitted provided that the following conditions 7280461Sdim * are met: 8280461Sdim * 1. Redistributions of source code must retain the above copyright 9341825Sdim * notice, this list of conditions and the following disclaimer. 10280461Sdim * 2. Redistributions in binary form must reproduce the above copyright 11280461Sdim * notice, this list of conditions and the following disclaimer in the 12280461Sdim * documentation and/or other materials provided with the distribution. 13292934Sdim * 3. All advertising materials mentioning features or use of this software 14280461Sdim * must display the following acknowledgement: 15280461Sdim * This product includes software developed by the University of 16292934Sdim * California, Berkeley and its contributors. 17327952Sdim * 4. Neither the name of the University nor the names of its contributors 18280461Sdim * may be used to endorse or promote products derived from this software 19280461Sdim * without specific prior written permission. 20280461Sdim * 21280461Sdim * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22280461Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23280461Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24280461Sdim * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25321369Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26314564Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27280461Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28280461Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29280461Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30280461Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31280461Sdim * SUCH DAMAGE. 32280461Sdim * 33280461Sdim * $FreeBSD: head/lib/libc/db/recno/rec_close.c 56698 2000-01-27 23:07:25Z jasone $ 34303239Sdim */ 35280461Sdim 36280461Sdim#if defined(LIBC_SCCS) && !defined(lint) 37280461Sdimstatic char sccsid[] = "@(#)rec_close.c 8.6 (Berkeley) 8/18/94"; 38280461Sdim#endif /* LIBC_SCCS and not lint */ 39280461Sdim 40280461Sdim#include <sys/types.h> 41280461Sdim#include <sys/uio.h> 42280461Sdim#include <sys/mman.h> 43280461Sdim 44280461Sdim#include <errno.h> 45280461Sdim#include <limits.h> 46280461Sdim#include <stdio.h> 47280461Sdim#include <unistd.h> 48280461Sdim 49280461Sdim#include <db.h> 50280461Sdim#include "recno.h" 51280461Sdim 52280461Sdim/* 53280461Sdim * __REC_CLOSE -- Close a recno tree. 54280461Sdim * 55280461Sdim * Parameters: 56280461Sdim * dbp: pointer to access method 57280461Sdim * 58280461Sdim * Returns: 59280461Sdim * RET_ERROR, RET_SUCCESS 60280461Sdim */ 61280461Sdimint 62280461Sdim__rec_close(dbp) 63280461Sdim DB *dbp; 64280461Sdim{ 65280461Sdim BTREE *t; 66280461Sdim int status; 67280461Sdim 68280461Sdim t = dbp->internal; 69280461Sdim 70280461Sdim /* Toss any page pinned across calls. */ 71280461Sdim if (t->bt_pinned != NULL) { 72280461Sdim mpool_put(t->bt_mp, t->bt_pinned, 0); 73280461Sdim t->bt_pinned = NULL; 74280461Sdim } 75303239Sdim 76303239Sdim if (__rec_sync(dbp, 0) == RET_ERROR) 77303239Sdim return (RET_ERROR); 78303239Sdim 79303239Sdim /* Committed to closing. */ 80303239Sdim status = RET_SUCCESS; 81303239Sdim if (F_ISSET(t, R_MEMMAPPED) && munmap(t->bt_smap, t->bt_msize)) 82303239Sdim status = RET_ERROR; 83303239Sdim 84303239Sdim if (!F_ISSET(t, R_INMEM)) 85303239Sdim if (F_ISSET(t, R_CLOSEFP)) { 86303239Sdim if (fclose(t->bt_rfp)) 87303239Sdim status = RET_ERROR; 88303239Sdim } else 89303239Sdim if (_close(t->bt_rfd)) 90303239Sdim status = RET_ERROR; 91303239Sdim 92303239Sdim if (__bt_close(dbp) == RET_ERROR) 93303239Sdim status = RET_ERROR; 94303239Sdim 95303239Sdim return (status); 96303239Sdim} 97303239Sdim 98303239Sdim/* 99303239Sdim * __REC_SYNC -- sync the recno tree to disk. 100303239Sdim * 101303239Sdim * Parameters: 102303239Sdim * dbp: pointer to access method 103303239Sdim * 104280461Sdim * Returns: 105280461Sdim * RET_SUCCESS, RET_ERROR. 106280461Sdim */ 107280461Sdimint 108280461Sdim__rec_sync(dbp, flags) 109280461Sdim const DB *dbp; 110280461Sdim u_int flags; 111280461Sdim{ 112280461Sdim struct iovec iov[2]; 113280461Sdim BTREE *t; 114280461Sdim DBT data, key; 115280461Sdim off_t off; 116280461Sdim recno_t scursor, trec; 117280461Sdim int status; 118280461Sdim 119280461Sdim t = dbp->internal; 120280461Sdim 121280461Sdim /* Toss any page pinned across calls. */ 122280461Sdim if (t->bt_pinned != NULL) { 123280461Sdim mpool_put(t->bt_mp, t->bt_pinned, 0); 124280461Sdim t->bt_pinned = NULL; 125280461Sdim } 126280461Sdim 127280461Sdim if (flags == R_RECNOSYNC) 128280461Sdim return (__bt_sync(dbp, 0)); 129280461Sdim 130280461Sdim if (F_ISSET(t, R_RDONLY | R_INMEM) || !F_ISSET(t, R_MODIFIED)) 131280461Sdim return (RET_SUCCESS); 132280461Sdim 133280461Sdim /* Read any remaining records into the tree. */ 134280461Sdim if (!F_ISSET(t, R_EOF) && t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR) 135280461Sdim return (RET_ERROR); 136280461Sdim 137280461Sdim /* Rewind the file descriptor. */ 138280461Sdim if (lseek(t->bt_rfd, (off_t)0, SEEK_SET) != 0) 139280461Sdim return (RET_ERROR); 140280461Sdim 141280461Sdim /* Save the cursor. */ 142280461Sdim scursor = t->bt_cursor.rcursor; 143280461Sdim 144280461Sdim key.size = sizeof(recno_t); 145280461Sdim key.data = &trec; 146280461Sdim 147280461Sdim if (F_ISSET(t, R_FIXLEN)) { 148280461Sdim /* 149280461Sdim * We assume that fixed length records are all fixed length. 150280461Sdim * Any that aren't are either EINVAL'd or corrected by the 151280461Sdim * record put code. 152280461Sdim */ 153280461Sdim status = (dbp->seq)(dbp, &key, &data, R_FIRST); 154280461Sdim while (status == RET_SUCCESS) { 155280461Sdim if (_write(t->bt_rfd, data.data, data.size) != 156280461Sdim data.size) 157280461Sdim return (RET_ERROR); 158280461Sdim status = (dbp->seq)(dbp, &key, &data, R_NEXT); 159280461Sdim } 160280461Sdim } else { 161280461Sdim iov[1].iov_base = (char *)&t->bt_bval; 162280461Sdim iov[1].iov_len = 1; 163292934Sdim 164280461Sdim status = (dbp->seq)(dbp, &key, &data, R_FIRST); 165280461Sdim while (status == RET_SUCCESS) { 166280461Sdim iov[0].iov_base = data.data; 167280461Sdim iov[0].iov_len = data.size; 168303239Sdim if (writev(t->bt_rfd, iov, 2) != data.size + 1) 169280461Sdim return (RET_ERROR); 170303239Sdim status = (dbp->seq)(dbp, &key, &data, R_NEXT); 171303239Sdim } 172303239Sdim } 173303239Sdim 174303239Sdim /* Restore the cursor. */ 175303239Sdim t->bt_cursor.rcursor = scursor; 176303239Sdim 177303239Sdim if (status == RET_ERROR) 178303239Sdim return (RET_ERROR); 179303239Sdim if ((off = lseek(t->bt_rfd, (off_t)0, SEEK_CUR)) == -1) 180303239Sdim return (RET_ERROR); 181303239Sdim if (ftruncate(t->bt_rfd, off)) 182303239Sdim return (RET_ERROR); 183280461Sdim F_CLR(t, R_MODIFIED); 184280461Sdim return (RET_SUCCESS); 185303239Sdim} 186303239Sdim