00001
package com.quadcap.sql.index;
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
import java.io.IOException;
00042
import java.io.PrintWriter;
00043
00044
import java.util.HashSet;
00045
import java.util.Iterator;
00046
import java.util.Set;
00047
00048
import com.quadcap.sql.file.BlockFile;
00049
00050
import com.quadcap.util.Debug;
00051
import com.quadcap.util.Util;
00052
00053
00054
00055
00056
00057
00058
00059 public class Btree implements BIndex {
00060 BlockFile
file;
00061 Comparator compare;
00062 long rootBlock;
00063 Bnode root;
00064 Object
lock;
00065 byte[]
tbuf =
new byte[16];
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 public Btree(BlockFile file,
Comparator compare,
00080
long rootBlock,
boolean create)
00081
throws IOException
00082 {
00083
00084
if (
Trace.bit(0)) {
00085
Debug.println(
"Btree(" +
file +
", " +
rootBlock +
", " +
00086 create +
")");
00087 }
00088
00089
this.file =
file;
00090
this.lock =
file.getLock();
00091
this.compare =
compare;
00092
this.rootBlock =
rootBlock;
00093
this.root =
getNode(
rootBlock);
00094
if (create) {
00095
root.
init(
true);
00096 }
else {
00097
root.
checkMagic();
00098 }
00099 }
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 public Btree(BlockFile file,
long rootBlock,
boolean create)
00113
throws IOException
00114 {
00115
this(
file,
Comparator.compare,
rootBlock, create);
00116 }
00117
00118 public int size() throws IOException {
00119
return getRoot().
size();
00120 }
00121
00122 final private BCursor getMyCursor() throws IOException {
00123
return BtreeCursor.get(
this,
true);
00124
00125 }
00126
00127
00128
00129
00130
00131
00132
00133 public int get(byte[] key,
int klen, byte[] data)
throws IOException {
00134
synchronized (
lock) {
00135
BCursor cursor =
getMyCursor();
00136
try {
00137
if (!cursor.
seek(key))
return -1;
00138
return cursor.
getVal(data);
00139 } finally {
00140 cursor.
release();
00141 }
00142 }
00143 }
00144
00145 public byte[] get(byte[] key)
throws IOException {
00146
synchronized (
lock) {
00147
BCursor cursor =
getMyCursor();
00148
try {
00149
if (!cursor.
seek(key, key.length))
return null;
00150
int len = cursor.
getValLen();
00151 byte[] ret =
new byte[len];
00152
if (cursor.
getVal(ret) != len) {
00153
throw new IOException(
"What the hella?");
00154 }
00155
return ret;
00156 } finally {
00157 cursor.
release();
00158 }
00159 }
00160 }
00161
00162 public boolean delete(byte[] key)
throws IOException {
00163
synchronized (
lock) {
00164
BCursor cursor =
getMyCursor();
00165
try {
00166
boolean ret = cursor.
seek(key, key.length);
00167
if (ret) ret = cursor.
delete();
00168
return ret;
00169 } finally {
00170 cursor.
release();
00171 }
00172 }
00173 }
00174
00175 public boolean deleteObs(byte[] key)
throws IOException {
00176
synchronized (
lock) {
00177
00178
if (
Trace.bit(0)) {
00179
Debug.println(0,
"BTree[" +
rootBlock +
"].delete(" +
00180
Util.hexBytes(key) +
")");
00181 }
00182
00183
return getRoot().
delete(key);
00184 }
00185 }
00186
00187 public void set(byte[] key, byte[] val)
throws IOException {
00188 set(key, key.length, val, 0, val.length);
00189 }
00190
00191 public void insert(byte[] key,
int klen,
00192 byte[] val,
int off,
int len)
throws IOException {
00193
synchronized (
lock) {
00194
00195
if (
Trace.bit(0)) {
00196
Debug.println(
"Btree[" +
rootBlock +
"].insert(" +
00197
Util.hexBytes(key, 0, klen) +
", " +
00198
Util.hexBytes(val, off, len) +
")");
00199 }
00200
00201
getRoot().
set(key, klen, val, off, len,
true,
false);
00202
notifyUpdate(null);
00203 }
00204 }
00205
00206 public void update(byte[] key,
int klen,
00207 byte[] val,
int off,
int len)
throws IOException {
00208
synchronized (
lock) {
00209
00210
if (
Trace.bit(0)) {
00211
Debug.println(
"Btree[" +
rootBlock +
"].update(" +
00212
Util.hexBytes(key, 0, klen) +
", " +
00213
Util.hexBytes(val, off, len) +
")");
00214 }
00215
00216
getRoot().
set(key, klen, val, off, len,
false,
true);
00217
notifyUpdate(null);
00218 }
00219 }
00220
00221 public boolean set(byte[] key,
int klen,
00222 byte[] val,
int off,
int len)
throws IOException {
00223
synchronized (
lock) {
00224
00225
if (
Trace.bit(0)) {
00226
Debug.println(
"Btree[" +
rootBlock +
"].set(" +
00227
Util.hexBytes(key) +
", " +
00228
Util.hexBytes(val) +
")");
00229 }
00230
00231
boolean ret =
getRoot().
set(key, klen, val, off, len,
true,
true);
00232
notifyUpdate(null);
00233
return ret;
00234 }
00235 }
00236
00237 Bnode getNode(
long ref) {
00238
return new Bnode(
this, ref);
00239 }
00240
00241 Bnode getRoot() {
return root; }
00242
00243 public long getRootBlock() {
00244
return rootBlock;
00245 }
00246
00247 void setRoot(
long ref) {
00248
root = getNode(
rootBlock = ref);
00249 }
00250
00251
00252
00253
00254 public BlockFile
getFile() {
return file; }
00255
00256
00257
00258
00259 public Comparator getComparator() {
00260
return compare;
00261 }
00262
00263
00264
00265
00266 public BCursor getCursor() throws IOException {
00267
return getCursor(
false);
00268 }
00269
00270 Set
activeCursors =
new HashSet();
00271
00272
00273
00274
00275 public BCursor getCursor(
boolean skipSetup)
throws IOException {
00276
BCursor bc = null;
00277
synchronized (
lock) {
00278 bc =
BtreeCursor.get(
this, skipSetup);
00279
activeCursors.add(bc);
00280 }
00281
return bc;
00282 }
00283
00284 public void releaseCursor(
BCursor c) {
00285
synchronized (
lock) {
00286
try {
00287 c.
close();
00288 }
catch (Throwable t) {}
00289
activeCursors.remove(c);
00290 }
00291 }
00292
00293 public void notifyUpdate(
BCursor notMe) {
00294
final Iterator iter =
activeCursors.iterator();
00295
while (iter.hasNext()) {
00296
BtreeCursor bc = (
BtreeCursor)iter.next();
00297
if (bc != notMe) bc.
unsetup();
00298 }
00299 }
00300
00301
00302
00303
00304 public void free() throws IOException {
00305
00306
if (
activeCursors.size() > 0) {
00307
final Iterator iter =
activeCursors.iterator();
00308
while (iter.hasNext()) {
00309
BtreeCursor ac = (
BtreeCursor)iter.next();
00310
Debug.println(
"Active cursor: " + ac);
00311
Debug.println(
"Error detected at: " +
Util.stackTrace());
00312
try {
00313 ac.
release();
00314 }
catch (Throwable t) {
00315 }
00316 }
00317
throw new IOException(
"Btree.free() called with active cursors");
00318 }
00319
if (
Trace.bit(0)) {
00320
Debug.println(
"Btree[" +
rootBlock +
"].free()");
00321
00322 }
00323
00324
getRoot().
free();
00325 }
00326
00327
00328 public String
toString() {
00329
return "Btree[" +
rootBlock +
"]";
00330 }
00331
00332 public void display(PrintWriter w)
throws IOException {
00333
BCursor bc =
getCursor(
false);
00334
try {
00335
while (bc.
next()) {
00336 w.println(
"[" +
new String(bc.
getKey()) +
"] = " +
00337
new String(bc.
getVal()));
00338 }
00339 } finally {
00340 bc.
release();
00341 }
00342
00343 }
00344
00345 }
00346