150995Sbostic /*-
261207Sbostic * Copyright (c) 1990, 1993
361207Sbostic * The Regents of the University of California. All rights reserved.
450995Sbostic *
550995Sbostic * %sccs.include.redist.c%
650995Sbostic */
750995Sbostic
850995Sbostic #if defined(LIBC_SCCS) && !defined(lint)
9*66195Sbostic static char sccsid[] = "@(#)rec_close.c 8.3 (Berkeley) 02/21/94";
1050995Sbostic #endif /* LIBC_SCCS and not lint */
1150995Sbostic
1257462Sbostic #include <sys/types.h>
1350995Sbostic #include <sys/uio.h>
1458748Sbostic #include <sys/mman.h>
1556754Sbostic
1650995Sbostic #include <errno.h>
1757462Sbostic #include <limits.h>
1856754Sbostic #include <stdio.h>
1950995Sbostic #include <unistd.h>
2056754Sbostic
2157933Sbostic #include <db.h>
2251087Sbostic #include "recno.h"
2350995Sbostic
2450995Sbostic /*
2550995Sbostic * __REC_CLOSE -- Close a recno tree.
2650995Sbostic *
2750995Sbostic * Parameters:
2850995Sbostic * dbp: pointer to access method
2950995Sbostic *
3050995Sbostic * Returns:
3150995Sbostic * RET_ERROR, RET_SUCCESS
3250995Sbostic */
3350995Sbostic int
__rec_close(dbp)3450995Sbostic __rec_close(dbp)
3550995Sbostic DB *dbp;
3650995Sbostic {
3754280Sbostic BTREE *t;
38*66195Sbostic int status;
3954280Sbostic
4064461Sbostic t = dbp->internal;
4164461Sbostic
4264461Sbostic /* Toss any page pinned across calls. */
4364461Sbostic if (t->bt_pinned != NULL) {
4464461Sbostic mpool_put(t->bt_mp, t->bt_pinned, 0);
4564461Sbostic t->bt_pinned = NULL;
4664461Sbostic }
4764461Sbostic
4860056Sbostic if (__rec_sync(dbp, 0) == RET_ERROR)
4950995Sbostic return (RET_ERROR);
5054280Sbostic
5154280Sbostic /* Committed to closing. */
52*66195Sbostic status = RET_SUCCESS;
5360056Sbostic if (ISSET(t, R_MEMMAPPED) && munmap(t->bt_smap, t->bt_msize))
54*66195Sbostic status = RET_ERROR;
5558748Sbostic
5660056Sbostic if (!ISSET(t, R_INMEM))
5760056Sbostic if (ISSET(t, R_CLOSEFP)) {
5858812Sbostic if (fclose(t->bt_rfp))
59*66195Sbostic status = RET_ERROR;
6058812Sbostic } else
6158812Sbostic if (close(t->bt_rfd))
62*66195Sbostic status = RET_ERROR;
6358748Sbostic
6454280Sbostic if (__bt_close(dbp) == RET_ERROR)
65*66195Sbostic status = RET_ERROR;
6654280Sbostic
67*66195Sbostic return (status);
6850995Sbostic }
6950995Sbostic
7050995Sbostic /*
7150995Sbostic * __REC_SYNC -- sync the recno tree to disk.
7250995Sbostic *
7350995Sbostic * Parameters:
7450995Sbostic * dbp: pointer to access method
7550995Sbostic *
7650995Sbostic * Returns:
7750995Sbostic * RET_SUCCESS, RET_ERROR.
7850995Sbostic */
7950995Sbostic int
__rec_sync(dbp,flags)8060056Sbostic __rec_sync(dbp, flags)
8150995Sbostic const DB *dbp;
8260056Sbostic u_int flags;
8350995Sbostic {
8450995Sbostic struct iovec iov[2];
8550995Sbostic BTREE *t;
8650995Sbostic DBT data, key;
8751087Sbostic off_t off;
8855312Sbostic recno_t scursor, trec;
8950995Sbostic int status;
9050995Sbostic
9150995Sbostic t = dbp->internal;
9250995Sbostic
9364461Sbostic /* Toss any page pinned across calls. */
9464461Sbostic if (t->bt_pinned != NULL) {
9564461Sbostic mpool_put(t->bt_mp, t->bt_pinned, 0);
9664461Sbostic t->bt_pinned = NULL;
9764461Sbostic }
9864461Sbostic
9960056Sbostic if (flags == R_RECNOSYNC)
10060056Sbostic return (__bt_sync(dbp, 0));
10160056Sbostic
10260056Sbostic if (ISSET(t, R_RDONLY | R_INMEM) || !ISSET(t, R_MODIFIED))
10350995Sbostic return (RET_SUCCESS);
10450995Sbostic
10556702Sbostic /* Read any remaining records into the tree. */
10660056Sbostic if (!ISSET(t, R_EOF) && t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
10750995Sbostic return (RET_ERROR);
10850995Sbostic
10950995Sbostic /* Rewind the file descriptor. */
11056702Sbostic if (lseek(t->bt_rfd, (off_t)0, SEEK_SET) != 0)
11150995Sbostic return (RET_ERROR);
11250995Sbostic
11350995Sbostic iov[1].iov_base = "\n";
11450995Sbostic iov[1].iov_len = 1;
11550995Sbostic scursor = t->bt_rcursor;
11650995Sbostic
11755312Sbostic key.size = sizeof(recno_t);
11855312Sbostic key.data = &trec;
11955312Sbostic
12050995Sbostic status = (dbp->seq)(dbp, &key, &data, R_FIRST);
12150995Sbostic while (status == RET_SUCCESS) {
12250995Sbostic iov[0].iov_base = data.data;
12350995Sbostic iov[0].iov_len = data.size;
12450995Sbostic if (writev(t->bt_rfd, iov, 2) != data.size + 1)
12550995Sbostic return (RET_ERROR);
12650995Sbostic status = (dbp->seq)(dbp, &key, &data, R_NEXT);
12750995Sbostic }
12850995Sbostic t->bt_rcursor = scursor;
12951087Sbostic if (status == RET_ERROR)
13051087Sbostic return (RET_ERROR);
13158748Sbostic if ((off = lseek(t->bt_rfd, (off_t)0, SEEK_CUR)) == -1)
13251087Sbostic return (RET_ERROR);
13351087Sbostic if (ftruncate(t->bt_rfd, off))
13451087Sbostic return (RET_ERROR);
13560056Sbostic CLR(t, R_MODIFIED);
13651087Sbostic return (RET_SUCCESS);
13750995Sbostic }
138