rec_close.c revision 331722
138032Speter/*-
2249729Sgshapiro * Copyright (c) 1990, 1993, 1994
364562Sgshapiro *	The Regents of the University of California.  All rights reserved.
438032Speter *
538032Speter * Redistribution and use in source and binary forms, with or without
638032Speter * modification, are permitted provided that the following conditions
738032Speter * are met:
838032Speter * 1. Redistributions of source code must retain the above copyright
938032Speter *    notice, this list of conditions and the following disclaimer.
1038032Speter * 2. Redistributions in binary form must reproduce the above copyright
1138032Speter *    notice, this list of conditions and the following disclaimer in the
1238032Speter *    documentation and/or other materials provided with the distribution.
1338032Speter * 4. Neither the name of the University nor the names of its contributors
1464562Sgshapiro *    may be used to endorse or promote products derived from this software
15168515Sgshapiro *    without specific prior written permission.
1638032Speter *
17249729Sgshapiro * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1864562Sgshapiro * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1964562Sgshapiro * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2064562Sgshapiro * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2164562Sgshapiro * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2264562Sgshapiro * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23223067Sgshapiro * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2464562Sgshapiro * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2564562Sgshapiro * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2664562Sgshapiro * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2764562Sgshapiro * SUCH DAMAGE.
2864562Sgshapiro */
2994334Sgshapiro
3064562Sgshapiro#if defined(LIBC_SCCS) && !defined(lint)
3164562Sgshapirostatic char sccsid[] = "@(#)rec_close.c	8.6 (Berkeley) 8/18/94";
3264562Sgshapiro#endif /* LIBC_SCCS and not lint */
3390792Sgshapiro#include <sys/cdefs.h>
34141858Sgshapiro__FBSDID("$FreeBSD: stable/11/lib/libc/db/recno/rec_close.c 331722 2018-03-29 02:50:57Z eadler $");
3564562Sgshapiro
3638032Speter#include "namespace.h"
3738032Speter#include <sys/types.h>
3838032Speter#include <sys/uio.h>
3938032Speter#include <sys/mman.h>
4038032Speter
4138032Speter#include <errno.h>
4238032Speter#include <limits.h>
4338032Speter#include <stdio.h>
4438032Speter#include <unistd.h>
4538032Speter#include "un-namespace.h"
4638032Speter
4738032Speter#include <db.h>
4838032Speter#include "recno.h"
4938032Speter
5038032Speter/*
5138032Speter * __REC_CLOSE -- Close a recno tree.
5238032Speter *
5338032Speter * Parameters:
5438032Speter *	dbp:	pointer to access method
5538032Speter *
5638032Speter * Returns:
5738032Speter *	RET_ERROR, RET_SUCCESS
5838032Speter */
5938032Speterint
6038032Speter__rec_close(DB *dbp)
6190792Sgshapiro{
6238032Speter	BTREE *t;
6390792Sgshapiro	int status;
6490792Sgshapiro
6538032Speter	t = dbp->internal;
6638032Speter
6738032Speter	/* Toss any page pinned across calls. */
6838032Speter	if (t->bt_pinned != NULL) {
6938032Speter		mpool_put(t->bt_mp, t->bt_pinned, 0);
7038032Speter		t->bt_pinned = NULL;
7138032Speter	}
7238032Speter
7338032Speter	if (__rec_sync(dbp, 0) == RET_ERROR)
7438032Speter		return (RET_ERROR);
7590792Sgshapiro
7690792Sgshapiro	/* Committed to closing. */
7738032Speter	status = RET_SUCCESS;
7838032Speter	if (F_ISSET(t, R_MEMMAPPED) && munmap(t->bt_smap, t->bt_msize))
7938032Speter		status = RET_ERROR;
8038032Speter
8138032Speter	if (!F_ISSET(t, R_INMEM)) {
8238032Speter		if (F_ISSET(t, R_CLOSEFP)) {
8338032Speter			if (fclose(t->bt_rfp))
8438032Speter				status = RET_ERROR;
8538032Speter		} else {
8638032Speter			if (_close(t->bt_rfd))
8738032Speter				status = RET_ERROR;
8838032Speter		}
8938032Speter	}
9038032Speter
9138032Speter	if (__bt_close(dbp) == RET_ERROR)
9290792Sgshapiro		status = RET_ERROR;
9364562Sgshapiro
9438032Speter	return (status);
9538032Speter}
9638032Speter
9738032Speter/*
9838032Speter * __REC_SYNC -- sync the recno tree to disk.
9938032Speter *
10038032Speter * Parameters:
10190792Sgshapiro *	dbp:	pointer to access method
10294334Sgshapiro *
10338032Speter * Returns:
10438032Speter *	RET_SUCCESS, RET_ERROR.
10564562Sgshapiro */
10638032Speterint
10738032Speter__rec_sync(const DB *dbp, u_int flags)
108168515Sgshapiro{
10938032Speter	struct iovec iov[2];
11038032Speter	BTREE *t;
11138032Speter	DBT data, key;
11290792Sgshapiro	off_t off;
11338032Speter	recno_t scursor, trec;
11438032Speter	int status;
11538032Speter
11638032Speter	t = dbp->internal;
117203004Sgshapiro
118223067Sgshapiro	/* Toss any page pinned across calls. */
119223067Sgshapiro	if (t->bt_pinned != NULL) {
120223067Sgshapiro		mpool_put(t->bt_mp, t->bt_pinned, 0);
121223067Sgshapiro		t->bt_pinned = NULL;
122223067Sgshapiro	}
123223067Sgshapiro
124223067Sgshapiro	if (flags == R_RECNOSYNC)
125223067Sgshapiro		return (__bt_sync(dbp, 0));
126223067Sgshapiro
127203004Sgshapiro	if (F_ISSET(t, R_RDONLY | R_INMEM) || !F_ISSET(t, R_MODIFIED))
12838032Speter		return (RET_SUCCESS);
12938032Speter
13038032Speter	/* Read any remaining records into the tree. */
13138032Speter	if (!F_ISSET(t, R_EOF) && t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
13238032Speter		return (RET_ERROR);
13338032Speter
13490792Sgshapiro	/* Rewind the file descriptor. */
13538032Speter	if (lseek(t->bt_rfd, (off_t)0, SEEK_SET) != 0)
13638032Speter		return (RET_ERROR);
13790792Sgshapiro
13838032Speter	/* Save the cursor. */
13938032Speter	scursor = t->bt_cursor.rcursor;
14090792Sgshapiro
14138032Speter	key.size = sizeof(recno_t);
14238032Speter	key.data = &trec;
14338032Speter
14438032Speter	if (F_ISSET(t, R_FIXLEN)) {
14538032Speter		/*
14690792Sgshapiro		 * We assume that fixed length records are all fixed length.
14738032Speter		 * Any that aren't are either EINVAL'd or corrected by the
14838032Speter		 * record put code.
14938032Speter		 */
15038032Speter		status = (dbp->seq)(dbp, &key, &data, R_FIRST);
151203004Sgshapiro		while (status == RET_SUCCESS) {
15290792Sgshapiro			if (_write(t->bt_rfd, data.data, data.size) !=
15390792Sgshapiro			    (ssize_t)data.size)
15490792Sgshapiro				return (RET_ERROR);
15538032Speter			status = (dbp->seq)(dbp, &key, &data, R_NEXT);
15638032Speter		}
15764562Sgshapiro	} else {
15864562Sgshapiro		iov[1].iov_base = &t->bt_bval;
15938032Speter		iov[1].iov_len = 1;
16038032Speter
16190792Sgshapiro		status = (dbp->seq)(dbp, &key, &data, R_FIRST);
16238032Speter		while (status == RET_SUCCESS) {
16364562Sgshapiro			iov[0].iov_base = data.data;
16438032Speter			iov[0].iov_len = data.size;
165168515Sgshapiro			if (_writev(t->bt_rfd, iov, 2) != (ssize_t)(data.size + 1))
166168515Sgshapiro				return (RET_ERROR);
16738032Speter			status = (dbp->seq)(dbp, &key, &data, R_NEXT);
168168515Sgshapiro		}
169168515Sgshapiro	}
17038032Speter
17138032Speter	/* Restore the cursor. */
17238032Speter	t->bt_cursor.rcursor = scursor;
17390792Sgshapiro
17438032Speter	if (status == RET_ERROR)
17538032Speter		return (RET_ERROR);
17638032Speter	if ((off = lseek(t->bt_rfd, (off_t)0, SEEK_CUR)) == -1)
17738032Speter		return (RET_ERROR);
178168515Sgshapiro	if (ftruncate(t->bt_rfd, off))
179168515Sgshapiro		return (RET_ERROR);
180168515Sgshapiro	F_CLR(t, R_MODIFIED);
181168515Sgshapiro	return (RET_SUCCESS);
18238032Speter}
18338032Speter