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.11 (Berkeley) 05/01/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 /* 47 * Delete any already deleted record that we've been saving 48 * because the cursor pointed to it. 49 */ 50 if (ISSET(t, BTF_DELCRSR) && __bt_crsrdel(t, &t->bt_bcursor)) 51 return (RET_ERROR); 52 53 if (__bt_sync(dbp) == RET_ERROR) 54 return (RET_ERROR); 55 56 if (mpool_close(t->bt_mp) == RET_ERROR) 57 return (RET_ERROR); 58 59 if (t->bt_stack) 60 free(t->bt_stack); 61 if (t->bt_kbuf) 62 free(t->bt_kbuf); 63 if (t->bt_dbuf) 64 free(t->bt_dbuf); 65 66 fd = t->bt_fd; 67 free(t); 68 free(dbp); 69 return (close(fd) ? RET_ERROR : RET_SUCCESS); 70 } 71 72 /* 73 * BT_SYNC -- sync the btree to disk. 74 * 75 * Parameters: 76 * dbp: pointer to access method 77 * 78 * Returns: 79 * RET_SUCCESS, RET_ERROR. 80 */ 81 int 82 __bt_sync(dbp) 83 const DB *dbp; 84 { 85 BTREE *t; 86 int status; 87 PAGE *h; 88 void *p; 89 90 t = dbp->internal; 91 92 if (ISSET(t, BTF_INMEM | BTF_RDONLY) || !ISSET(t, BTF_MODIFIED)) 93 return (RET_SUCCESS); 94 95 if (ISSET(t, BTF_METADIRTY) && bt_meta(t) == RET_ERROR) 96 return (RET_ERROR); 97 98 /* 99 * Nastiness. If the cursor has been marked for deletion, but not 100 * actually deleted, we have to make a copy of the page, delete the 101 * key/data item, sync the file, and then restore the original page 102 * contents. 103 */ 104 if (ISSET(t, BTF_DELCRSR)) { 105 if ((p = malloc(t->bt_psize)) == NULL) 106 return (RET_ERROR); 107 if ((h = mpool_get(t->bt_mp, t->bt_bcursor.pgno, 0)) == NULL) 108 return (RET_ERROR); 109 memmove(p, h, t->bt_psize); 110 if ((status = 111 __bt_dleaf(t, h, t->bt_bcursor.index)) == RET_ERROR) 112 goto ecrsr; 113 mpool_put(t->bt_mp, h, MPOOL_DIRTY); 114 } 115 116 if ((status = mpool_sync(t->bt_mp)) == RET_SUCCESS) 117 CLR(t, BTF_MODIFIED); 118 119 ecrsr: if (ISSET(t, BTF_DELCRSR)) { 120 if ((h = mpool_get(t->bt_mp, t->bt_bcursor.pgno, 0)) == NULL) 121 return (RET_ERROR); 122 memmove(h, p, t->bt_psize); 123 free(p); 124 mpool_put(t->bt_mp, h, MPOOL_DIRTY); 125 } 126 return (status); 127 } 128 129 /* 130 * BT_META -- write the tree meta data to disk. 131 * 132 * Parameters: 133 * t: tree 134 * 135 * Returns: 136 * RET_ERROR, RET_SUCCESS 137 */ 138 static int 139 bt_meta(t) 140 BTREE *t; 141 { 142 BTMETA m; 143 void *p; 144 145 if ((p = mpool_get(t->bt_mp, P_META, 0)) == NULL) 146 return (RET_ERROR); 147 148 /* Fill in metadata. */ 149 m.m_magic = BTREEMAGIC; 150 m.m_version = BTREEVERSION; 151 m.m_psize = t->bt_psize; 152 m.m_free = t->bt_free; 153 m.m_nrecs = t->bt_nrecs; 154 m.m_flags = t->bt_flags & SAVEMETA; 155 156 memmove(p, &m, sizeof(BTMETA)); 157 mpool_put(t->bt_mp, p, MPOOL_DIRTY); 158 return (RET_SUCCESS); 159 } 160