1 /*-
2 * Copyright (c) 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8 #if defined(LIBC_SCCS) && !defined(lint)
9 static char sccsid[] = "@(#)rec_close.c 8.3 (Berkeley) 02/21/94";
10 #endif /* LIBC_SCCS and not lint */
11
12 #include <sys/types.h>
13 #include <sys/uio.h>
14 #include <sys/mman.h>
15
16 #include <errno.h>
17 #include <limits.h>
18 #include <stdio.h>
19 #include <unistd.h>
20
21 #include <db.h>
22 #include "recno.h"
23
24 /*
25 * __REC_CLOSE -- Close a recno tree.
26 *
27 * Parameters:
28 * dbp: pointer to access method
29 *
30 * Returns:
31 * RET_ERROR, RET_SUCCESS
32 */
33 int
__rec_close(dbp)34 __rec_close(dbp)
35 DB *dbp;
36 {
37 BTREE *t;
38 int status;
39
40 t = dbp->internal;
41
42 /* Toss any page pinned across calls. */
43 if (t->bt_pinned != NULL) {
44 mpool_put(t->bt_mp, t->bt_pinned, 0);
45 t->bt_pinned = NULL;
46 }
47
48 if (__rec_sync(dbp, 0) == RET_ERROR)
49 return (RET_ERROR);
50
51 /* Committed to closing. */
52 status = RET_SUCCESS;
53 if (ISSET(t, R_MEMMAPPED) && munmap(t->bt_smap, t->bt_msize))
54 status = RET_ERROR;
55
56 if (!ISSET(t, R_INMEM))
57 if (ISSET(t, R_CLOSEFP)) {
58 if (fclose(t->bt_rfp))
59 status = RET_ERROR;
60 } else
61 if (close(t->bt_rfd))
62 status = RET_ERROR;
63
64 if (__bt_close(dbp) == RET_ERROR)
65 status = RET_ERROR;
66
67 return (status);
68 }
69
70 /*
71 * __REC_SYNC -- sync the recno tree to disk.
72 *
73 * Parameters:
74 * dbp: pointer to access method
75 *
76 * Returns:
77 * RET_SUCCESS, RET_ERROR.
78 */
79 int
__rec_sync(dbp,flags)80 __rec_sync(dbp, flags)
81 const DB *dbp;
82 u_int flags;
83 {
84 struct iovec iov[2];
85 BTREE *t;
86 DBT data, key;
87 off_t off;
88 recno_t scursor, trec;
89 int status;
90
91 t = dbp->internal;
92
93 /* Toss any page pinned across calls. */
94 if (t->bt_pinned != NULL) {
95 mpool_put(t->bt_mp, t->bt_pinned, 0);
96 t->bt_pinned = NULL;
97 }
98
99 if (flags == R_RECNOSYNC)
100 return (__bt_sync(dbp, 0));
101
102 if (ISSET(t, R_RDONLY | R_INMEM) || !ISSET(t, R_MODIFIED))
103 return (RET_SUCCESS);
104
105 /* Read any remaining records into the tree. */
106 if (!ISSET(t, R_EOF) && t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
107 return (RET_ERROR);
108
109 /* Rewind the file descriptor. */
110 if (lseek(t->bt_rfd, (off_t)0, SEEK_SET) != 0)
111 return (RET_ERROR);
112
113 iov[1].iov_base = "\n";
114 iov[1].iov_len = 1;
115 scursor = t->bt_rcursor;
116
117 key.size = sizeof(recno_t);
118 key.data = &trec;
119
120 status = (dbp->seq)(dbp, &key, &data, R_FIRST);
121 while (status == RET_SUCCESS) {
122 iov[0].iov_base = data.data;
123 iov[0].iov_len = data.size;
124 if (writev(t->bt_rfd, iov, 2) != data.size + 1)
125 return (RET_ERROR);
126 status = (dbp->seq)(dbp, &key, &data, R_NEXT);
127 }
128 t->bt_rcursor = scursor;
129 if (status == RET_ERROR)
130 return (RET_ERROR);
131 if ((off = lseek(t->bt_rfd, (off_t)0, SEEK_CUR)) == -1)
132 return (RET_ERROR);
133 if (ftruncate(t->bt_rfd, off))
134 return (RET_ERROR);
135 CLR(t, R_MODIFIED);
136 return (RET_SUCCESS);
137 }
138