1 /*- 2 * Copyright (c) 1990 The Regents of the University of California. 3 * 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 5.4 (Berkeley) 12/16/91"; 13 #endif /* LIBC_SCCS and not lint */ 14 15 #include <sys/param.h> 16 #include <errno.h> 17 #include <db.h> 18 #include <unistd.h> 19 #include <stdio.h> 20 #include <stdlib.h> 21 #include <string.h> 22 #include "btree.h" 23 24 static int bt_meta __P((BTREE *)); 25 26 /* 27 * BT_CLOSE -- Close a btree. 28 * 29 * Parameters: 30 * dbp: pointer to access method 31 * 32 * Returns: 33 * RET_ERROR, RET_SUCCESS 34 */ 35 int 36 __bt_close(dbp) 37 DB *dbp; 38 { 39 BTREE *t; 40 int fd; 41 42 t = dbp->internal; 43 44 /* 45 * Delete any already deleted record that we've been saving 46 * because the cursor pointed to it. 47 */ 48 if (ISSET(t, BTF_DELCRSR) && __bt_crsrdel(t, &t->bt_bcursor)) 49 return (RET_ERROR); 50 51 if (__bt_sync(dbp) == RET_ERROR) 52 return (RET_ERROR); 53 54 if (mpool_close(t->bt_mp) == RET_ERROR) 55 return (RET_ERROR); 56 57 if (t->bt_stack) 58 free(t->bt_stack); 59 if (t->bt_kbuf) 60 free(t->bt_kbuf); 61 if (t->bt_dbuf) 62 free(t->bt_dbuf); 63 64 fd = t->bt_fd; 65 free(t); 66 free(dbp); 67 return (close(fd) ? RET_ERROR : RET_SUCCESS); 68 } 69 70 /* 71 * BT_SYNC -- sync the btree to disk. 72 * 73 * Parameters: 74 * dbp: pointer to access method 75 * 76 * Returns: 77 * RET_SUCCESS, RET_ERROR. 78 */ 79 int 80 __bt_sync(dbp) 81 const DB *dbp; 82 { 83 BTREE *t; 84 int status; 85 PAGE *h; 86 void *p; 87 88 t = dbp->internal; 89 90 if (ISSET(t, BTF_INMEM) || ISSET(t, BTF_RDONLY)) 91 return (RET_SUCCESS); 92 93 if (ISSET(t, BTF_METADIRTY) && bt_meta(t) == RET_ERROR) 94 return (RET_ERROR); 95 96 /* 97 * Nastiness. If the cursor has been marked for deletion, but not 98 * actually deleted, we have to make a copy of the page, delete the 99 * key/data item, sync the file, and then restore the original page 100 * contents. 101 */ 102 if (ISSET(t, BTF_DELCRSR)) { 103 if ((h = mpool_get(t->bt_mp, t->bt_bcursor.pgno, 0)) == NULL) 104 return (RET_ERROR); 105 if ((p = malloc(t->bt_psize)) == NULL) { 106 mpool_put(t->bt_mp, h, 0); 107 return (RET_ERROR); 108 } 109 bcopy(h, p, t->bt_psize); 110 if (__bt_dleaf(t, h, t->bt_bcursor.index) == RET_ERROR) 111 goto ecrsr; 112 } 113 114 if ((status = mpool_sync(t->bt_mp)) == RET_SUCCESS) 115 UNSET(t, BTF_MODIFIED); 116 ecrsr: if (ISSET(t, BTF_DELCRSR)) { 117 bcopy(p, h, t->bt_psize); 118 free(p); 119 mpool_put(t->bt_mp, h, 0); 120 } 121 return (status); 122 } 123 124 /* 125 * BT_META -- write the tree meta data to disk. 126 * 127 * Parameters: 128 * t: tree 129 * 130 * Returns: 131 * RET_ERROR, RET_SUCCESS 132 */ 133 static int 134 bt_meta(t) 135 BTREE *t; 136 { 137 BTMETA m; 138 void *p; 139 140 if ((p = mpool_get(t->bt_mp, P_META, 0)) == NULL) 141 return (RET_ERROR); 142 143 /* Fill in metadata -- lorder is host-independent. */ 144 m.m_magic = BTREEMAGIC; 145 m.m_version = BTREEVERSION; 146 m.m_psize = t->bt_psize; 147 m.m_free = 0; /* XXX */ 148 m.m_nrecs = t->bt_nrecs; 149 m.m_flags = t->bt_flags & SAVEMETA; 150 m.m_lorder = htonl((u_long)t->bt_lorder); 151 152 if (t->bt_lorder != BYTE_ORDER) { 153 BLSWAP(m.m_magic); 154 BLSWAP(m.m_version); 155 BLSWAP(m.m_psize); 156 BLSWAP(m.m_free); 157 BLSWAP(m.m_nrecs); 158 BLSWAP(m.m_flags); 159 } 160 161 bcopy(&m, p, sizeof(BTMETA)); 162 mpool_put(t->bt_mp, p, MPOOL_DIRTY); 163 return (RET_SUCCESS); 164 } 165