1 /*- 2 * Copyright (c) 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Mike Olson. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #if defined(LIBC_SCCS) && !defined(lint) 12 static char sccsid[] = "@(#)bt_close.c 8.2 (Berkeley) 09/07/93"; 13 #endif /* LIBC_SCCS and not lint */ 14 15 #include <sys/param.h> 16 17 #include <errno.h> 18 #include <stdio.h> 19 #include <stdlib.h> 20 #include <string.h> 21 #include <unistd.h> 22 23 #include <db.h> 24 #include "btree.h" 25 26 static int bt_meta __P((BTREE *)); 27 28 /* 29 * BT_CLOSE -- Close a btree. 30 * 31 * Parameters: 32 * dbp: pointer to access method 33 * 34 * Returns: 35 * RET_ERROR, RET_SUCCESS 36 */ 37 int 38 __bt_close(dbp) 39 DB *dbp; 40 { 41 BTREE *t; 42 int fd; 43 44 t = dbp->internal; 45 46 /* Toss any page pinned across calls. */ 47 if (t->bt_pinned != NULL) { 48 mpool_put(t->bt_mp, t->bt_pinned, 0); 49 t->bt_pinned = NULL; 50 } 51 52 /* 53 * Delete any already deleted record that we've been saving 54 * because the cursor pointed to it. 55 */ 56 if (ISSET(t, B_DELCRSR) && __bt_crsrdel(t, &t->bt_bcursor)) 57 return (RET_ERROR); 58 59 if (__bt_sync(dbp, 0) == RET_ERROR) 60 return (RET_ERROR); 61 62 if (mpool_close(t->bt_mp) == RET_ERROR) 63 return (RET_ERROR); 64 65 if (t->bt_stack) 66 free(t->bt_stack); 67 if (t->bt_kbuf) 68 free(t->bt_kbuf); 69 if (t->bt_dbuf) 70 free(t->bt_dbuf); 71 72 fd = t->bt_fd; 73 free(t); 74 free(dbp); 75 return (close(fd) ? RET_ERROR : RET_SUCCESS); 76 } 77 78 /* 79 * BT_SYNC -- sync the btree to disk. 80 * 81 * Parameters: 82 * dbp: pointer to access method 83 * 84 * Returns: 85 * RET_SUCCESS, RET_ERROR. 86 */ 87 int 88 __bt_sync(dbp, flags) 89 const DB *dbp; 90 u_int flags; 91 { 92 BTREE *t; 93 int status; 94 PAGE *h; 95 void *p; 96 97 t = dbp->internal; 98 99 /* Toss any page pinned across calls. */ 100 if (t->bt_pinned != NULL) { 101 mpool_put(t->bt_mp, t->bt_pinned, 0); 102 t->bt_pinned = NULL; 103 } 104 105 /* Sync doesn't currently take any flags. */ 106 if (flags != 0) { 107 errno = EINVAL; 108 return (RET_ERROR); 109 } 110 111 if (ISSET(t, B_INMEM | B_RDONLY) || !ISSET(t, B_MODIFIED)) 112 return (RET_SUCCESS); 113 114 if (ISSET(t, B_METADIRTY) && bt_meta(t) == RET_ERROR) 115 return (RET_ERROR); 116 117 /* 118 * Nastiness. If the cursor has been marked for deletion, but not 119 * actually deleted, we have to make a copy of the page, delete the 120 * key/data item, sync the file, and then restore the original page 121 * contents. 122 */ 123 if (ISSET(t, B_DELCRSR)) { 124 if ((p = malloc(t->bt_psize)) == NULL) 125 return (RET_ERROR); 126 if ((h = mpool_get(t->bt_mp, t->bt_bcursor.pgno, 0)) == NULL) 127 return (RET_ERROR); 128 memmove(p, h, t->bt_psize); 129 if ((status = 130 __bt_dleaf(t, h, t->bt_bcursor.index)) == RET_ERROR) 131 goto ecrsr; 132 mpool_put(t->bt_mp, h, MPOOL_DIRTY); 133 } 134 135 if ((status = mpool_sync(t->bt_mp)) == RET_SUCCESS) 136 CLR(t, B_MODIFIED); 137 138 ecrsr: if (ISSET(t, B_DELCRSR)) { 139 if ((h = mpool_get(t->bt_mp, t->bt_bcursor.pgno, 0)) == NULL) 140 return (RET_ERROR); 141 memmove(h, p, t->bt_psize); 142 free(p); 143 mpool_put(t->bt_mp, h, MPOOL_DIRTY); 144 } 145 return (status); 146 } 147 148 /* 149 * BT_META -- write the tree meta data to disk. 150 * 151 * Parameters: 152 * t: tree 153 * 154 * Returns: 155 * RET_ERROR, RET_SUCCESS 156 */ 157 static int 158 bt_meta(t) 159 BTREE *t; 160 { 161 BTMETA m; 162 void *p; 163 164 if ((p = mpool_get(t->bt_mp, P_META, 0)) == NULL) 165 return (RET_ERROR); 166 167 /* Fill in metadata. */ 168 m.m_magic = BTREEMAGIC; 169 m.m_version = BTREEVERSION; 170 m.m_psize = t->bt_psize; 171 m.m_free = t->bt_free; 172 m.m_nrecs = t->bt_nrecs; 173 m.m_flags = t->bt_flags & SAVEMETA; 174 175 memmove(p, &m, sizeof(BTMETA)); 176 mpool_put(t->bt_mp, p, MPOOL_DIRTY); 177 return (RET_SUCCESS); 178 } 179