1 package com.quadcap.sql.index; 2 3 40 41 import java.io.IOException ; 42 import java.io.PrintWriter ; 43 44 import java.util.HashSet ; 45 import java.util.Iterator ; 46 import java.util.Set ; 47 48 import com.quadcap.sql.file.BlockFile; 49 50 import com.quadcap.util.Debug; 51 import com.quadcap.util.Util; 52 53 59 public class Btree implements BIndex { 60 BlockFile file; 61 Comparator compare; 62 long rootBlock; 63 Bnode root; 64 Object lock; 65 byte[] tbuf = new byte[16]; 66 67 79 public Btree(BlockFile file, Comparator compare, 80 long rootBlock, boolean create) 81 throws IOException 82 { 83 if (Trace.bit(0)) { 85 Debug.println("Btree(" + file + ", " + rootBlock + ", " + 86 create + ")"); 87 } 88 this.file = file; 90 this.lock = file.getLock(); 91 this.compare = compare; 92 this.rootBlock = rootBlock; 93 this.root = getNode(rootBlock); 94 if (create) { 95 root.init(true); 96 } else { 97 root.checkMagic(); 98 } 99 } 100 101 112 public Btree(BlockFile file, long rootBlock, boolean create) 113 throws IOException 114 { 115 this(file, Comparator.compare, rootBlock, create); 116 } 117 118 public int size() throws IOException { 119 return getRoot().size(); 120 } 121 122 final private BCursor getMyCursor() throws IOException { 123 return BtreeCursor.get(this, true); 124 } 126 127 133 public int get(byte[] key, int klen, byte[] data) throws IOException { 134 synchronized (lock) { 135 BCursor cursor = getMyCursor(); 136 try { 137 if (!cursor.seek(key)) return -1; 138 return cursor.getVal(data); 139 } finally { 140 cursor.release(); 141 } 142 } 143 } 144 145 public byte[] get(byte[] key) throws IOException { 146 synchronized (lock) { 147 BCursor cursor = getMyCursor(); 148 try { 149 if (!cursor.seek(key, key.length)) return null; 150 int len = cursor.getValLen(); 151 byte[] ret = new byte[len]; 152 if (cursor.getVal(ret) != len) { 153 throw new IOException ("What the hella?"); 154 } 155 return ret; 156 } finally { 157 cursor.release(); 158 } 159 } 160 } 161 162 public boolean delete(byte[] key) throws IOException { 163 synchronized (lock) { 164 BCursor cursor = getMyCursor(); 165 try { 166 boolean ret = cursor.seek(key, key.length); 167 if (ret) ret = cursor.delete(); 168 return ret; 169 } finally { 170 cursor.release(); 171 } 172 } 173 } 174 175 public boolean deleteObs(byte[] key) throws IOException { 176 synchronized (lock) { 177 if (Trace.bit(0)) { 179 Debug.println(0, "BTree[" + rootBlock + "].delete(" + 180 Util.hexBytes(key) + ")"); 181 } 182 return getRoot().delete(key); 184 } 185 } 186 187 public void set(byte[] key, byte[] val) throws IOException { 188 set(key, key.length, val, 0, val.length); 189 } 190 191 public void insert(byte[] key, int klen, 192 byte[] val, int off, int len) throws IOException { 193 synchronized (lock) { 194 if (Trace.bit(0)) { 196 Debug.println("Btree[" + rootBlock + "].insert(" + 197 Util.hexBytes(key, 0, klen) + ", " + 198 Util.hexBytes(val, off, len) + ")"); 199 } 200 getRoot().set(key, klen, val, off, len, true, false); 202 notifyUpdate(null); 203 } 204 } 205 206 public void update(byte[] key, int klen, 207 byte[] val, int off, int len) throws IOException { 208 synchronized (lock) { 209 if (Trace.bit(0)) { 211 Debug.println("Btree[" + rootBlock + "].update(" + 212 Util.hexBytes(key, 0, klen) + ", " + 213 Util.hexBytes(val, off, len) + ")"); 214 } 215 getRoot().set(key, klen, val, off, len, false, true); 217 notifyUpdate(null); 218 } 219 } 220 221 public boolean set(byte[] key, int klen, 222 byte[] val, int off, int len) throws IOException { 223 synchronized (lock) { 224 if (Trace.bit(0)) { 226 Debug.println("Btree[" + rootBlock + "].set(" + 227 Util.hexBytes(key) + ", " + 228 Util.hexBytes(val) + ")"); 229 } 230 boolean ret = getRoot().set(key, klen, val, off, len, true, true); 232 notifyUpdate(null); 233 return ret; 234 } 235 } 236 237 Bnode getNode(long ref) { 238 return new Bnode(this, ref); 239 } 240 241 Bnode getRoot() { return root; } 242 243 public long getRootBlock() { 244 return rootBlock; 245 } 246 247 void setRoot(long ref) { 248 root = getNode(rootBlock = ref); 249 } 250 251 254 public BlockFile getFile() { return file; } 255 256 259 public Comparator getComparator() { 260 return compare; 261 } 262 263 266 public BCursor getCursor() throws IOException { 267 return getCursor(false); 268 } 269 270 Set activeCursors = new HashSet (); 271 272 275 public BCursor getCursor(boolean skipSetup) throws IOException { 276 BCursor bc = null; 277 synchronized (lock) { 278 bc = BtreeCursor.get(this, skipSetup); 279 activeCursors.add(bc); 280 } 281 return bc; 282 } 283 284 public void releaseCursor(BCursor c) { 285 synchronized (lock) { 286 try { 287 c.close(); 288 } catch (Throwable t) {} 289 activeCursors.remove(c); 290 } 291 } 292 293 public void notifyUpdate(BCursor notMe) { 294 final Iterator iter = activeCursors.iterator(); 295 while (iter.hasNext()) { 296 BtreeCursor bc = (BtreeCursor)iter.next(); 297 if (bc != notMe) bc.unsetup(); 298 } 299 } 300 301 304 public void free() throws IOException { 305 if (activeCursors.size() > 0) { 307 final Iterator iter = activeCursors.iterator(); 308 while (iter.hasNext()) { 309 BtreeCursor ac = (BtreeCursor)iter.next(); 310 Debug.println("Active cursor: " + ac); 311 Debug.println("Error detected at: " + Util.stackTrace()); 312 try { 313 ac.release(); 314 } catch (Throwable t) { 315 } 316 } 317 throw new IOException ("Btree.free() called with active cursors"); 318 } 319 if (Trace.bit(0)) { 320 Debug.println("Btree[" + rootBlock + "].free()"); 321 } 323 getRoot().free(); 325 } 326 327 public String toString() { 329 return "Btree[" + rootBlock + "]"; 330 } 331 332 public void display(PrintWriter w) throws IOException { 333 BCursor bc = getCursor(false); 334 try { 335 while (bc.next()) { 336 w.println("[" + new String (bc.getKey()) + "] = " + 337 new String (bc.getVal())); 338 } 339 } finally { 340 bc.release(); 341 } 342 343 } 344 } 346 347 | Popular Tags |