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.BufferedReader;
00042
import java.io.InputStreamReader;
00043
import java.io.IOException;
00044
00045
import java.util.Properties;
00046
00047
import com.quadcap.sql.file.Block;
00048
import com.quadcap.sql.file.BlockFile;
00049
import com.quadcap.sql.file.ByteUtil;
00050
import com.quadcap.sql.file.SubPageManager;
00051
00052
import com.quadcap.sql.lock.PooledObject;
00053
import com.quadcap.sql.lock.ObjectPool;
00054
00055
import com.quadcap.util.Debug;
00056
import com.quadcap.util.Util;
00057
00058
00059
00060
00061
00062
00063 public class BtreeCursor extends PooledObject implements
BCursor {
00064 Object
fileLock;
00065
00066 Btree tree;
00067 Bnode root = null;
00068 Comparator compare = null;
00069
00070 Block[]
blocks =
new Block[16];
00071 int[]
pointers =
new int[16];
00072
00073 byte[]
curKey =
new byte[4096];
00074 byte[]
curVal =
new byte[4096];
00075 int[]
lengths =
new int[2];
00076
00077 int depth = -1;
00078 long size = -1;
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 static final long posUNKNOWN = -2;
00090 static final long posAFTER_LAST = -1;
00091 static final long posBEFORE_FIRST = 0;
00092
00093 long position =
posUNKNOWN;
00094
00095
00096
00097
00098 private BtreeCursor() {}
00099
00100 static final boolean noPool =
false;
00101 static ObjectPool
pool =
new ObjectPool(
new BtreeCursor());
00102
00103 static BtreeCursor get(
Btree tree,
boolean skipSetup)
throws IOException {
00104
BtreeCursor c = null;
00105
if (
noPool) {
00106 c =
new BtreeCursor();
00107 }
else {
00108
synchronized (
tree.
lock) {
00109 c = (
BtreeCursor)
pool.get();
00110 }
00111 }
00112
if (c != null) {
00113 c.
init(
tree, skipSetup);
00114 }
00115
return c;
00116 }
00117
00118 public void release() {
00119
unsetup();
00120
synchronized (
fileLock) {
00121
Btree theTree =
tree;
00122 tree = null;
00123
fileLock = null;
00124 theTree.
releaseCursor(
this);
00125
if (!
noPool) {
00126
pool.release(
this);
00127 }
00128 }
00129 }
00130
00131
00132
00133
00134 public PooledObject
create() {
00135
return new BtreeCursor();
00136 }
00137
00138
00139
00140
00141 public void init(
Btree tree,
boolean skipSetup)
throws IOException {
00142
this.tree =
tree;
00143
this.fileLock =
tree.
lock;
00144
if (!skipSetup) {
00145
beforeFirst();
00146 }
00147 }
00148
00149
00150
00151
00152
00153 protected void setup(
boolean restoreKey)
throws IOException {
00154
if (
depth < 0) {
00155
synchronized (
fileLock) {
00156
this.root =
tree.
getRoot();
00157
this.compare =
tree.
compare;
00158
if (restoreKey) {
00159
if (
lengths[0] > 0) {
00160
seek(
curKey,
lengths[0]);
00161 }
else {
00162
beforeFirst();
00163 }
00164 }
00165 }
00166 }
00167 }
00168
00169
00170
00171
00172 public void unsetup() {
00173
for (
int i = 0; i <
blocks.length; i++) {
00174
setBlock(i, null);
00175 }
00176
this.root = null;
00177
this.depth = -1;
00178
this.size = -1;
00179
if (
position > 0)
position =
posUNKNOWN;
00180 }
00181
00182
00183
00184
00185
00186 public final boolean seek(byte[] key)
throws IOException {
00187
return seek(key, key.length);
00188 }
00189
00190
00191
00192
00193 public boolean seek(byte[] key,
int len)
throws IOException {
00194
synchronized (
fileLock) {
00195
position =
posUNKNOWN;
00196 setup(
false);
00197
setBlock(0,
root.
getBlock());
00198
boolean ret =
seek1(0, key, len);
00199
if (ret) {
00200
holdKey(0);
00201 }
00202
00203
if (
Trace.bit(6)) {
00204
Debug.println(
toString() +
".seek(" +
00205
Util.hexBytes(key, 0, len) +
") = " + ret);
00206 }
00207
00208
return ret;
00209 }
00210 }
00211
00212
00213 final String
id() {
00214
return tree.
getFile().
getName().substring(0, 1) +
00215
" " +
SubPageManager.toString(
tree.
getRootBlock());
00216 }
00217 final String
dr() {
00218
return !
Trace.bit(12) ?
00219
", val = " + (
lengths[1] > 0 ?
Util.hexBytes(
getVal()) :
"null") :
00220
"";
00221 }
00222
00223
00224
00225
00226
00227 boolean seek1(
int level, byte[] key,
int len)
throws IOException {
00228 Block b =
blocks[level];
00229
int bs;
00230 bs =
Bnode.bsearch(b,
compare, key, len, 0,
Bnode.getCount(b)-1);
00231
int index = bs < 0 ? (-1-bs) : bs;
00232
if (!
Bnode.isLeaf(b)) {
00233
if (bs < 0) {
00234 index = index - 1;
00235
if (index < 0) index = 0;
00236 }
00237
pointers[level] = index;
00238 Block c =
root.
getBlock(
Bnode.blockRef(b, index));
00239
setBlock(++level, c);
00240
return seek1(level, key, len);
00241 }
else {
00242
pointers[level] = index;
00243
depth = level+1;
00244
return bs >= 0;
00245 }
00246 }
00247
00248
00249
00250
00251
00252 final void setBlock(
int i, Block b) {
00253
if (
blocks[i] != null)
blocks[i].decrRefCount();
00254
blocks[i] = b;
00255 }
00256
00257
00258
00259
00260 public void beforeFirst() throws IOException {
00261
synchronized (
fileLock) {
00262
this.root =
tree.
getRoot();
00263
this.compare =
tree.
compare;
00264
lengths[0] =
lengths[1] = 0;
00265 Block b =
root.
getBlock();
00266
for (
int level = 0; b != null; level++) {
00267 setBlock(level, b);
00268
pointers[level] = 0;
00269
if (!
Bnode.isLeaf(b)) {
00270 b =
root.
getBlock(
Bnode.blockRef(b, 0));
00271 }
else {
00272
depth = level + 1;
00273 b = null;
00274 }
00275 }
00276
position =
posBEFORE_FIRST;
00277
00278
00279
if (
Trace.bit(1)) {
00280
Debug.println(
toString() +
".beforeFirst()");
00281 }
00282
00283 }
00284 }
00285
00286
00287
00288
00289
00290 public void afterLast() throws IOException {
00291
synchronized (
fileLock) {
00292 setup(
false);
00293 Block b =
root.
getBlock();
00294
for (
int level = 0; b != null; level++) {
00295 setBlock(level, b);
00296
int count =
Bnode.getCount(b);
00297
pointers[level] = count;
00298
if (!
Bnode.isLeaf(b)) {
00299 b =
root.
getBlock(
Bnode.blockRef(b,
pointers[level]-1));
00300 }
else {
00301 b = null;
00302 }
00303 }
00304
position =
posAFTER_LAST;
00305
00306
if (
Trace.bit(1)) {
00307
Debug.println(
toString() +
".afterLast()");
00308 }
00309
00310 }
00311 }
00312
00313
00314
00315
00316 public boolean absolute(
int x)
throws IOException {
00317
synchronized (
fileLock) {
00318
if (x > 0) {
00319
00320
beforeFirst();
00321
int cur = 1;
00322
int cnt =
Bnode.getCount(
blocks[
depth-1]);
00323
while (cur + cnt < x) {
00324 cur += cnt;
00325
if (!
getNextBlock())
return false;
00326 cnt =
Bnode.getCount(
blocks[depth-1]);
00327 }
00328
int p = x - cur;
00329
if (p < 0 || p >= cnt)
return false;
00330
pointers[depth-1] = p;
00331
holdKey(0);
00332
pointers[depth-1]++;
00333
position = x;
00334
00335
if (
Trace.bit(1)) {
00336
Debug.println(
toString() +
".absolute(" + x +
") = true");
00337 }
00338
00339
return true;
00340 }
else if (x < 0) {
00341
int absx = 0 - x;
00342
00343
afterLast();
00344
int cnt =
Bnode.getCount(
blocks[
depth-1]);
00345
while (cnt < absx) {
00346 absx -= cnt;
00347
if (!
getPrevBlock())
return false;
00348 cnt =
Bnode.getCount(
blocks[depth-1]);
00349 }
00350
pointers[depth-1] -= absx;
00351
holdKey(0);
00352
00353
if (
Trace.bit(1)) {
00354
Debug.println(
toString() +
".absolute(" + x +
") = true");
00355 }
00356
00357
if (
size > 0)
position =
size + x;
00358
return true;
00359 }
else {
00360
throw new IOException(
"absolute 0");
00361 }
00362 }
00363 }
00364
00365
00366
00367
00368
00369 public boolean next() throws IOException {
00370
synchronized (
fileLock) {
00371 setup(
true);
00372
if (
depth <= 0)
return false;
00373
int p =
pointers[
depth-1];
00374
int cnt =
Bnode.getCount(
blocks[
depth-1]);
00375
if (p >= cnt) {
00376
if (cnt == 0 || !
getNextBlock()) {
00377
00378
if (
Trace.bit(1)) {
00379
Debug.println(
toString() +
".next() false");
00380 }
00381
00382
return false;
00383 }
00384 p = pointers[depth-1];
00385 cnt =
Bnode.getCount(
blocks[depth-1]);
00386
if (p >= cnt) {
00387
00388
if (
Trace.bit(1)) {
00389
Debug.println(
toString() +
".next() false");
00390 }
00391
00392
return false;
00393 }
00394 }
00395
holdKey(0);
00396 pointers[depth-1]++;
00397
if (
position >= 0)
position++;
00398
00399
if (
Trace.bit(1)) {
00400
Debug.println(
toString() +
".next(): " +
00401
Util.hexBytes(
getKeyBuf(), 0,
getKeyLen()) +
00402
" = " +
dr());
00403 }
00404
00405
return true;
00406 }
00407 }
00408
00409
00410
00411
00412
00413 public boolean prev() throws IOException {
00414
synchronized (
fileLock) {
00415 setup(
true);
00416
if (
depth < 0)
return false;
00417
int p =
pointers[
depth-1] - 1;
00418
int cnt =
Bnode.getCount(
blocks[
depth-1]);
00419
if (p < 0 || cnt <= 0) {
00420
if (cnt <= 0 || !
getPrevBlock())
return false;
00421 p = pointers[depth-1];
00422
if (p < 0 || cnt <= 0)
return false;
00423 }
00424 pointers[depth-1] = p;
00425
holdKey(0);
00426
if (
position > 0) {
00427
position--;
00428 }
else if (
position ==
posAFTER_LAST) {
00429
if (
size < 0) {
00430
position =
posUNKNOWN;
00431 }
else {
00432
position =
size;
00433 }
00434 }
00435
00436
if (
Trace.bit(1)) {
00437
Debug.println(
toString() +
".prev() true");
00438 }
00439
00440
return true;
00441 }
00442 }
00443
00444
00445
00446
00447
00448 public boolean delete()
throws IOException {
00449
synchronized (
fileLock) {
00450
boolean ret =
false;
00451 setup(
true);
00452
if (
depth >= 0) {
00453
int p =
pointers[
depth-1];
00454
int cnt =
Bnode.getCount(
blocks[
depth-1]);
00455
if (p >= 0 && p < cnt) {
00456
root.
deleteKeyAtPos(
blocks[depth-1], p,
false);
00457
tree.
notifyUpdate(
this);
00458 ret =
true;
00459 }
00460 }
00461
00462
if (
Trace.bit(9)) {
00463
Debug.println(
toString() +
".delete() = " + ret);
00464 }
00465
00466
return ret;
00467 }
00468 }
00469
00470
00471
00472
00473
00474
00475
00476 public boolean insert(byte[] key,
int klen,
00477 byte[] data,
int doff,
int dlen)
throws IOException {
00478
synchronized (
fileLock) {
00479 setup(
true);
00480
00481
int p =
pointers[
depth-1];
00482
final Block b =
blocks[
depth-1];
00483
final int cnt =
Bnode.getCount(b);
00484
00485
if (p < 0 || p > cnt)
throw new IOException(
"bad tree");
00486
00487
boolean ret =
true;
00488
if (p >= 0 && p < cnt) {
00489
int r =
Bnode.keyCompareAtPos(
compare, key, klen, b, p);
00490
if (r != -1) ret =
false;
00491 }
else if (p > 0 && cnt > 0) {
00492
int r =
Bnode.keyCompareAtPos(
compare, key, klen, b, p-1);
00493
if (r != 1) ret =
false;
00494 }
00495
if (ret) {
00496
root.
setKey(b, p, key, klen, data, doff, dlen,
false);
00497
tree.
notifyUpdate(
this);
00498 }
00499
00500
if (
Trace.bit(7)) {
00501
Debug.println(
toString() +
".insert(" +
k(key, 0, klen) +
00502 (!
Trace.bit(12) ? (
", " +
k(data, doff, dlen)) :
"") +
00503
") = " + ret);
00504 }
00505
00506
return ret;
00507 }
00508 }
00509
00510 public boolean insert(byte[] key, byte[] data)
throws IOException {
00511
return insert(key, key.length, data, 0, data.length);
00512 }
00513
00514
00515
00516
00517 public boolean replace(byte[] data,
int doff,
int dlen)
00518
throws IOException
00519 {
00520
synchronized (
fileLock) {
00521 setup(
true);
00522
00523
int p =
pointers[
depth-1];
00524
final Block b =
blocks[
depth-1];
00525
final int cnt =
Bnode.getCount(b);
00526
00527
if (p < 0 || p > cnt) {
00528
throw new IOException(
"bad tree");
00529 }
00530
00531
root.
setKey(b, p,
curKey,
lengths[0], data, doff, dlen,
true);
00532
tree.
notifyUpdate(
this);
00533
00534
if (
Trace.bit(8)) {
00535
Debug.println(
toString() +
".replace(" +
k(
curKey, 0,
lengths[0]) +
") = true");
00536 }
00537
00538
return true;
00539 }
00540 }
00541
00542 public boolean replace(byte[] data)
throws IOException {
00543
return replace(data, 0, data.length);
00544 }
00545
00546
00547
00548
00549 public long size() throws IOException {
00550
synchronized (
fileLock) {
00551 setup(
true);
00552
if (size < 0) {
00553 size =
subtreeSize(
root,
root.
getBlock());
00554 }
00555
return size;
00556 }
00557 }
00558
00559
00560
00561
00562 public long position() throws IOException {
00563
synchronized (
fileLock) {
00564 setup(
true);
00565
if (position < 0) {
00566
long total = 0;
00567
boolean r =
false;
00568
for (
int d = 0; d <
depth-1; d++) {
00569 Block b =
blocks[d];
00570
int p =
pointers[d];
00571
int c =
Bnode.getCount(b);
00572
if (d == 0) r = (c / 2) <= p;
00573
if (r) p++;
00574
else { c = p; p = 0; }
00575
if (
Bnode.isLeaf(b)) {
00576 total += (c - p);
00577 }
else {
00578
for (
int i = p; i < c; i++) {
00579 Block s =
root.
getBlock(
Bnode.blockRef(b, i));
00580
try {
00581 total +=
subtreeSize(
root, s);
00582 } finally {
00583 s.decrRefCount();
00584 }
00585 }
00586 }
00587 }
00588 position = r ?
size() - total : total + 1;
00589 }
00590
return position;
00591 }
00592 }
00593
00594
00595
00596
00597 public void close() {
00598
unsetup();
00599 }
00600
00601 public int getKey(byte[] buf) {
00602 System.arraycopy(
curKey, 0, buf, 0,
lengths[0]);
00603
return lengths[0];
00604 }
00605
00606 public byte[]
getKeyBuf() {
return curKey; }
00607
00608 public void setKeyBuf(byte[] buf) {
curKey = buf; }
00609
00610 public int getKeyLen() {
return lengths[0]; }
00611
00612 public byte[]
getKey() {
00613 byte[] ret =
new byte[
lengths[0]];
00614 System.arraycopy(
curKey, 0, ret, 0, ret.length);
00615
return ret;
00616 }
00617
00618 public int getVal(byte[] buf) {
00619 System.arraycopy(
curVal, 0, buf, 0,
lengths[1]);
00620
return lengths[1];
00621 }
00622
00623 public byte[]
getValBuf() {
return curVal; }
00624
00625 public void setValBuf(byte[] buf) {
curVal = buf; }
00626
00627 public int getValLen() {
return lengths[1]; }
00628
00629 public byte[]
getVal() {
00630 byte[] ret =
new byte[
lengths[1]];
00631 System.arraycopy(
curVal, 0, ret, 0, ret.length);
00632
return ret;
00633 }
00634
00635 public long getValAsLong() {
00636
return ByteUtil.getLong(
curVal, 0);
00637 }
00638
00639
00640
00641 final boolean getNextBlock() throws IOException {
00642
int d =
depth - 2;
00643
while (d >= 0 &&
pointers[d]+1 >=
Bnode.getCount(
blocks[d])) {
00644 d--;
00645 }
00646
00647
if (d < 0)
return false;
00648 Block b =
root.
getBlock(
Bnode.blockRef(
blocks[d],
00649 ++pointers[d]));
00650
00651 setBlock(d+1, b);
00652 pointers[d+1] = 0;
00653
00654
for (
int i = d+2; i < depth; i++) {
00655 pointers[i] = 0;
00656 Block c =
root.
getBlock(
Bnode.blockRef(
blocks[i-1],
00657 pointers[i-1]));
00658 setBlock(i, c);
00659 }
00660
return true;
00661 }
00662
00663 final boolean getPrevBlock() throws IOException {
00664
int d =
depth - 2;
00665
while (d >= 0 &&
pointers[d] <= 0) {
00666 d--;
00667 }
00668
00669
if (d < depth-1) {
00670
if (d < 0) {
00671
return false;
00672 }
00673 Block b =
root.
getBlock(
Bnode.blockRef(
blocks[d],
00674 --pointers[d]));
00675 setBlock(d+1, b);
00676 pointers[d+1] = 0;
00677
00678
for (
int i = d+2; i < depth; i++) {
00679 Block c =
root.
getBlock(
Bnode.blockRef(
blocks[i-1],
00680 pointers[i-1]));
00681 setBlock(i, c);
00682 pointers[i] =
Bnode.getCount(c)-1;
00683 }
00684 }
00685
return true;
00686 }
00687
00688 final void holdKey(
int off) {
00689
int p =
pointers[
depth-1] - off;
00690 Block b =
blocks[
depth-1];
00691
if (p >= 0 && p <
Bnode.getCount(b)) {
00692
if (!
Bnode.getKeyAndData(b, p,
curKey,
curVal,
lengths)) {
00693
throw new RuntimeException(
"holdKey: getKeyAndData failed");
00694 }
00695 }
else {
00696
00697
00698
00699
throw new RuntimeException(
"Hold what, mate?");
00700 }
00701
00702
00703 }
00704
00705 static long subtreeSize(
Bnode root, Block b)
throws IOException {
00706
int count =
Bnode.getCount(b);
00707
if (
Bnode.isLeaf(b))
return count;
00708
else {
00709
long total = 0;
00710
for (
int i = 0; i < count; i++) {
00711 Block c =
root.
getBlock(
Bnode.blockRef(b, i));
00712
try {
00713 total += subtreeSize(
root, c);
00714 } finally {
00715 c.decrRefCount();
00716 }
00717 }
00718
return total;
00719 }
00720 }
00721
00722
00723
00724 public String
toString() {
00725
return "BtreeCursor[" +
tree +
"]";
00726 }
00727
00728 String
k(byte[] b,
int off,
int len) {
00729
return tree.
compare.
toString(b, off, len);
00730 }
00731
00732 String
t() {
00733 StringBuffer sb =
new StringBuffer();
00734
for (
int i = 0; i <
depth; i++) {
00735
if (i > 0) sb.append(
' ');
00736 sb.append(String.valueOf(
pointers[i]));
00737 sb.append(
'/');
00738 sb.append(String.valueOf(
Bnode.getCount(
blocks[i])));
00739 }
00740
return sb.toString();
00741 }
00742
00743 static int lastCount = -1;
00744 static StringBuffer
lastBuf =
new StringBuffer();
00745
00746 private static final int countNext(
BCursor c)
throws IOException {
00747
int cnt = 0;
00748
while (c.next()) cnt++;
00749
lastCount = cnt;
00750
return cnt;
00751 }
00752
00753 private static final int countPrev(
BCursor c)
throws IOException {
00754
int cnt = 0;
00755 StringBuffer sb =
lastBuf;
00756 sb.setLength(0);
00757 sb.append(
"{");
00758 byte[] buf =
new byte[111];
00759
while (c.prev()) {
00760 cnt++;
00761
int len = c.getKey(buf);
00762
if (cnt > 0) sb.append(
',');
00763 sb.append(
new String(buf, 0, len));
00764 }
00765 sb.append(
"}");
00766
lastCount = cnt;
00767
return cnt;
00768 }
00769
00770 final static String
r(
boolean b) {
00771
return b ?
"{true}" :
"{false}";
00772 }
00773 static void itest(
BCursor bc)
throws IOException {
00774 InputStreamReader ir =
new InputStreamReader(System.in);
00775 BufferedReader r =
new BufferedReader(ir);
00776 String ret =
"";
00777
while (
true) {
00778 System.out.print(
"BC" + ret +
" (" + ((
BtreeCursor)bc).
t() +
"): ");
00779 System.out.flush();
00780 String line = r.readLine();
00781
if (line == null)
break;
00782
try {
00783 ret =
doLine(bc, line);
00784
if (ret == null)
break;
00785 }
catch (Throwable t) {
00786 t.printStackTrace(System.out);
00787 System.out.println(
"-------------------------");
00788 }
00789 }
00790 }
00791
00792 static String
doLine(
BCursor bc, String line)
throws Exception {
00793 String ks = line.toLowerCase().substring(1).trim();
00794 byte[] k = ks.getBytes();
00795 byte[] d = ks.toUpperCase().getBytes();
00796 String ret =
"";
00797
if (line.startsWith(
"g")) {
00798 ret = r(bc.seek(k));
00799 }
else if (line.equals(
"<")) {
00800 bc.beforeFirst();
00801 }
else if (line.equals(
">")) {
00802 bc.afterLast();
00803 }
else if (line.equals(
"n")) {
00804 ret = r(bc.next());
00805 }
else if (line.equals(
"p")) {
00806 ret = r(bc.prev());
00807 }
else if (line.equals(
"d")) {
00808 ret = r(bc.delete());
00809 }
else if (line.startsWith(
"i")) {
00810 ret = r(bc.insert(k, k.length, d, 0, d.length));
00811 }
else if (line.startsWith(
"r")) {
00812 ret = r(bc.replace(d, 0, d.length));
00813 }
else if (line.equals(
"c")) {
00814 bc.close();
00815 }
else if (line.equals(
"s")) {
00816
show(
"position = " + bc.position() +
" of " +
00817 bc.size() +
" records");
00818 }
else if (line.equals(
"k")) {
00819
show(
"current key = " +
new String(bc.getKeyBuf(), 0,
00820 bc.getKeyLen()));
00821
show(
"current val = " +
new String(bc.getValBuf(), 0,
00822 bc.getValLen()));
00823
show(
"current val as long: " + bc.getValAsLong());
00824
00825 }
else if (line.equals(
"p")) {
00826
show(
"position = " + bc.position() +
" of " +
00827 bc.size() +
" records");
00828 }
else if (line.equals(
"q")) {
00829
return null;
00830 }
else {
00831
int row = 0;
00832
boolean bad =
true;
00833
try {
00834 row = Integer.parseInt(line);
00835 bad =
false;
00836 }
catch (Throwable t) {}
00837
if (!bad) {
00838 ret = r(bc.absolute(row));
00839 }
else {
00840
show(
"g <key> seek(key)");
00841
show(
"i <key> insert(key,KEY)");
00842
show(
"r <key> replace(KEY)");
00843
show(
"< beforeFirst()");
00844
show(
"> afterLast()");
00845
show(
"n next()");
00846
show(
"p prev()");
00847
show(
"c close()");
00848
show(
"d delete()");
00849
show(
"s position / size");
00850 }
00851 }
00852
return ret;
00853 }
00854
00855 static void show(String s) {
00856 System.out.println(s);
00857 }
00858
00859 static final long tick() {
return System.currentTimeMillis(); }
00860
00861 static final void mkey(
int i, byte[] b) {
00862
int x = b.length;
00863
while (x > 0 && i > 0) {
00864 b[--x] = (byte)(
'0' + (i % 10));
00865 i /= 10;
00866 }
00867
while (x > 0) b[--x] =
'0';
00868 }
00869
00870 static void ktest(
BCursor c)
throws IOException {
00871
long s =
tick();
00872 byte[] k =
new byte[8];
00873
for (
int i = 0; i < k.length; i++) k[i] =
'0';
00874
for (
int ki = 0; ki < 100000; ki++) {
00875
int i = (ki * 2003) % 100000;
00876 mkey(i, k);
00877
if (c.seek(k))
throw new IOException(
"*** Error, found " + i);
00878
if (!c.insert(k, k.length, k, 0, k.length)) {
00879
throw new IOException(
"*** Error insert: " + i);
00880 }
00881 }
00882
long elap =
tick() - s;
00883 System.out.println(
"insert: " + elap +
" ms");
00884
kshow(c);
00885 }
00886
00887 static void kshow(
BCursor c)
throws IOException {
00888
long s =
tick();
00889
int count = 0;
00890
int total = 0;
00891
int etotal = 0;
00892 c.beforeFirst();
00893
while (c.next()) {
00894 etotal += count;
00895 count++;
00896 total += Integer.parseInt(
new String(c.getValBuf(), 0,
00897 c.getValLen()));
00898 }
00899
long elap =
tick() - s;
00900 show(
"seek: " + elap +
" ms");
00901 show(
"Count: " + count +
", total/etotal = " + total +
"/" + etotal);
00902 }
00903
00904 static void ktest(
Btree t)
throws IOException {
00905
long s =
tick();
00906 byte[] k =
new byte[8];
00907
for (
int i = 0; i < k.length; i++) k[i] =
'0';
00908
for (
int ki = 0; ki < 100000; ki++) {
00909
int i = (ki * 2003) % 100000;
00910 mkey(i, k);
00911 t.set(k, k);
00912 }
00913
long elap =
tick() - s;
00914 System.out.println(
"insert: " + elap +
" ms");
00915 kshow(t.getCursor());
00916 }
00917
00918
00919
00920
00921 public static void main(String[] args) {
00922
try {
00923 String name =
"test.db";
00924
int blocksize = 4096;
00925
int cachesize = 256;
00926
BlockFile f =
new BlockFile(name,
"rw",
00927
new Properties(),
00928 blocksize, cachesize);
00929
long rootBlock = f.
newPage();
00930
Btree t =
new Btree(f, rootBlock,
true);
00931
00932
00933
00934
00935
BCursor c = t.
getCursor();
00936
00937
00938
00939 ktest(c);
00940 }
catch (Throwable t) {
00941 t.printStackTrace(System.out);
00942 }
00943 }
00944
00945 static void jtest(
BCursor c)
throws Exception {
00946 c.seek(
"abc".getBytes());
00947 c.insert(
"abc".getBytes(), 3,
"def".getBytes(), 0, 3);
00948 c.seek(
"ahc".getBytes());
00949 c.insert(
"ahc".getBytes(), 3,
"deh".getBytes(), 0, 3);
00950 c.seek(
"bbc".getBytes());
00951 c.insert(
"bbc".getBytes(), 3,
"jej".getBytes(), 0, 3);
00952
00953
int cSize = countNext(c);
00954
if (c.size() != cSize) {
00955 System.out.println(
"Bad size: " + cSize +
" vs " + c.size());
00956 }
00957
for (
int i = 1; i <= cSize; i++) {
00958
if (i == 0) c.beforeFirst();
else c.absolute(i);
00959
if (c.position() != i) {
00960 System.out.println(
"Bad position " + i +
" vs " +
00961 c.position());
00962 }
00963
if (countNext(c) != cSize - i) {
00964 System.out.println(
"Bad count next: " +
lastCount +
00965
" vs " + (cSize - i));
00966 }
00967
if (i == 0) c.beforeFirst();
else c.absolute(i);
00968
if (c.position() != i) {
00969 System.out.println(
"Bad position " + i +
" vs " +
00970 c.position());
00971 }
00972
if (countPrev(c) != i) {
00973 System.out.println(
"Bad count prev: " + i +
" vs " +
00974
lastCount +
" " +
lastBuf);
00975 }
00976
if (i == 0) c.afterLast();
else c.absolute(0 - i);
00977
if (c.position() != cSize - i) {
00978 System.out.println(
"Bad position " + (cSize-i) +
" vs " +
00979 c.position());
00980 }
00981
if (countNext(c) != i-1) {
00982 System.out.println(
"Bad count next: " +
lastCount +
00983
" vs " + (i-1));
00984 }
00985
if (i == 0) c.afterLast();
else c.absolute(0 - i);
00986
if (c.position() != (cSize-i)) {
00987 System.out.println(
"Bad position " + (cSize-i) +
" vs " +
00988 c.position());
00989 }
00990
if (countPrev(c) != cSize - i + 1) {
00991 System.out.println(
"Bad count prev: " + (cSize-i+1) +
00992
" vs " +
00993
lastCount +
" " +
lastBuf);
00994 }
00995 }
00996
00997 System.out.println(
"seek(abc) = " + c.seek(
"abc".getBytes()) +
00998
": " + c.position() +
"/" + c.size());
00999 System.out.println(
"c.next() = " + c.next());
01000 System.out.println(
"c.next() = " + c.next());
01001
01002 System.out.println(
"seek(abb) = " + c.seek(
"abb".getBytes()));
01003 System.out.println(
"c.next() = " + c.next());
01004 System.out.println(
"c.next() = " + c.next());
01005
01006 System.out.println(
"seek(abd) = " + c.seek(
"abd".getBytes()));
01007 System.out.println(
"c.next() = " + c.next());
01008 System.out.println(
"c.next() = " + c.next());
01009
01010 System.out.println(
"seek(zzz) = " + c.seek(
"zzz".getBytes()));
01011 System.out.println(
"c.next() = " + c.next());
01012 System.out.println(
"c.next() = " + c.next());
01013 }
01014
01015 }