1 19 package org.netbeans.mdr.persistence.btreeimpl.btreeindex; 20 21 import org.netbeans.mdr.persistence.*; 22 import org.netbeans.mdr.persistence.btreeimpl.btreestorage.*; 23 import java.io.*; 24 import org.openide.ErrorManager; 25 26 30 53 public class VarKeyPage extends BtreePage { 54 55 private int[] offsets; 56 private int nextOffset; private static final int SIZE_OF_OFFSET = SIZE_OF_SHORT; 58 59 69 public void init(Btree btree, byte[] pageId, byte[] pageBuffer, 70 boolean isNew) throws StorageException { 71 72 int maxOffsets; 73 74 if (initialized) { 75 76 return; 77 } 78 79 super.init(btree, pageId, pageBuffer, isNew); 80 81 88 if (offsets == null) { 89 maxOffsets = (btree.pageSize - headerLength)/SIZE_OF_OFFSET; 90 offsets = new int[maxOffsets]; 91 } 92 initOffsets(isNew); 93 } 94 95 private void initOffsets(boolean isNew) { 96 97 int pageOffset = headerLength; 98 99 if (isNew) { 100 nextOffset = 0; 101 } else { 102 nextOffset = (freeStart - headerLength)/SIZE_OF_OFFSET; 103 for (int i = 0; i < nextOffset; i++) { 104 offsets[i] = (int) Converter.readShort(pageBuffer, 105 pageOffset); 106 pageOffset += 2; 107 } 108 } 109 offsets[nextOffset] = btree.pageSize; 110 } 111 112 115 public void store() { 116 117 int pageOffset = headerLength; 118 119 super.store(); 120 121 if (nextOffset > 0) { 122 for (int i = 0; i < nextOffset; i++) { 123 Converter.writeShort(pageBuffer, pageOffset, (short)offsets[i]); 124 pageOffset += 2; 125 } 126 } 127 } 128 129 134 int numEntries() { 135 return nextOffset; 136 } 137 138 145 int keyOffset(int entryNum) { 146 return offsets[entryNum]; 147 } 148 149 156 int keyLength(int entryNum) { 157 if (entryNum != nextOffset) { 158 return offsets[entryNum+1] - offsets[entryNum] - dataLength; 159 } else { 160 return 0; 162 } 163 } 164 165 172 byte[] getData(int entryNum) { 173 174 byte[] data = new byte[dataLength]; 175 try { 176 System.arraycopy(pageBuffer, offsets[entryNum+1] - dataLength, 177 data, 0, dataLength); 178 } catch (ArrayIndexOutOfBoundsException e) { 179 String msg = "mdr.btreestorage.VarKeyPage.getData, ArrayIndexOutOfBoundsException occured\n" + "buffer length: " + pageBuffer.length + ", offset: " + offsets[entryNum+1] + ", dataLength: " + dataLength + ", data length: " + data.length; ErrorManager.getDefault().log(ErrorManager.EXCEPTION, msg); 184 throw e; 185 } 186 return data; 187 } 188 189 196 byte[] getKey(int entryNum) { 197 198 byte[] key = new byte[keyLength(entryNum)]; 199 System.arraycopy(pageBuffer, offsets[entryNum], key, 0, key.length); 200 return key; 201 } 202 203 212 213 BtreeEntry replace(BtreeEntry entry, int entryNum, SearchResult resultPosition) throws StorageException { 214 215 pageSource.dirtyPage(this); 216 System.arraycopy(entry.data, 0, 217 pageBuffer, offsets[entryNum+1] - entry.data.length, 218 entry.data.length); 219 220 if (resultPosition != null) { 222 resultPosition.matched = true; 223 resultPosition.skipCount = 0; 224 resultPosition.page = this; 225 resultPosition.entryNum = entryNum; 226 } 227 228 return null; 230 } 231 232 241 BtreeEntry insert(BtreeEntry entry, int entryNum, SearchResult resultPosition) 242 throws StorageException { 243 244 int entriesStart; 245 int entriesSplit; 246 247 pageSource.dirtyPage(this); 248 249 if (!haveSpaceForInsert(entry)) { 250 return split(entry, entryNum, resultPosition); 251 } else { 252 entriesStart = offsets[0]; 253 entriesSplit = offsets[entryNum]; 254 shiftOffsets(this, entryNum, entry.length()); 255 if (entryNum != 0) { 256 System.arraycopy(pageBuffer, entriesStart, 257 pageBuffer, entriesStart - entry.length(), 258 entriesSplit - entriesStart); 259 } 260 System.arraycopy(entry.key, 0, pageBuffer, offsets[entryNum], 261 entry.key.length); 262 System.arraycopy(entry.data, 0, pageBuffer, 263 offsets[entryNum] + entry.key.length, 264 entry.data.length); 265 freeStart += SIZE_OF_OFFSET; 266 267 if (resultPosition != null) { 268 resultPosition.entryNum = entryNum; 269 resultPosition.matched = true; 270 resultPosition.page = this; 271 resultPosition.skipCount = 0; 272 } 273 return null; 274 } 275 } 276 277 283 284 void delete(int first, int last) throws StorageException { 285 286 int startOffset, endOffset; 287 int bytesDeleted; 288 int numDeleted; 289 290 pageSource.dirtyPage(this); 291 292 startOffset = offsets[first]; 293 endOffset = offsets[last+1]; 294 bytesDeleted = endOffset - startOffset; 295 numDeleted = last - first + 1; 296 297 if (first != 0) { 298 System.arraycopy(pageBuffer, offsets[0], 299 pageBuffer, offsets[0] + bytesDeleted, 300 startOffset - offsets[0]); 301 } 302 for (int i = last + 1; i <= nextOffset; i++) { 304 offsets[i - numDeleted] = offsets[i]; 305 } 306 nextOffset -= numDeleted; 307 freeStart -= numDeleted*SIZE_OF_OFFSET; 308 309 if (first != 0) { 311 for (int i = 0; i < first; i++) { 312 offsets[i] += bytesDeleted; 313 } 314 } 315 } 316 317 330 byte[] splitEntries(BtreePage leftBP, BtreePage rightBP, BtreeEntry entry, 331 int newEntryNum, SearchResult resultPosition) throws StorageException { 332 333 int halfBytes; 334 int splitEntryNum; 335 int rightNewEntryNum; 336 int spaceAvailable; 337 int spaceNeeded; 338 boolean insertLeft; 339 int pageSize; VarKeyPage left, right; 341 int rightKeyLength; 342 byte[] rightKey; 343 344 left = (VarKeyPage) leftBP; 345 right = (VarKeyPage) rightBP; 346 pageSize = btree.pageSize; 347 348 spaceAvailable = pageSize - headerLength; 350 halfBytes = (spaceAvailable - nextOffset*SIZE_OF_OFFSET)/2; 351 splitEntryNum = 0; 352 while ((offsets[splitEntryNum] < halfBytes) 353 && (splitEntryNum < nextOffset)) { 354 splitEntryNum++; 355 } 356 357 if (newEntryNum < splitEntryNum) { 360 do { 361 spaceNeeded = splitEntryNum*SIZE_OF_OFFSET 362 + offsets[splitEntryNum] - offsets[0] 363 + entry.length() + SIZE_OF_OFFSET; 364 if (spaceNeeded > spaceAvailable) { 365 splitEntryNum--; 366 } 367 } while ((spaceNeeded > spaceAvailable) 368 && (newEntryNum < splitEntryNum)); 369 } 370 insertLeft = newEntryNum < splitEntryNum ? true : false; 371 372 if (resultPosition != null) { 374 resultPosition.matched = true; 375 resultPosition.skipCount = 0; 376 if (insertLeft) { 377 resultPosition.page = left; 378 resultPosition.entryNum = newEntryNum; 379 } else { 380 resultPosition.page = right; 381 resultPosition.entryNum = newEntryNum - splitEntryNum; 382 } 383 } 384 385 if (!insertLeft) { 386 spaceNeeded = splitEntryNum*SIZE_OF_OFFSET 387 + pageSize - offsets[splitEntryNum] 388 + entry.length() + SIZE_OF_OFFSET; 389 } 390 391 for (int from = splitEntryNum, to = 0; from < nextOffset; 395 from++, to++) { 396 right.offsets[to] = this.offsets[from]; 397 } 398 right.nextOffset = this.nextOffset - splitEntryNum; 399 right.offsets[right.nextOffset] = btree.pageSize; 400 right.freeStart = headerLength + right.nextOffset*SIZE_OF_OFFSET; 401 402 if (insertLeft) { 403 System.arraycopy(this.pageBuffer, offsets[splitEntryNum], 405 right.pageBuffer, offsets[splitEntryNum], 406 pageSize - offsets[splitEntryNum]); 407 } else { 408 rightNewEntryNum = newEntryNum - splitEntryNum; 410 shiftOffsets(right, rightNewEntryNum, entry.length()); 411 right.freeStart += SIZE_OF_OFFSET; 412 413 if (newEntryNum != splitEntryNum) { 415 System.arraycopy(this.pageBuffer, this.offsets[splitEntryNum], 416 right.pageBuffer, right.offsets[0], 417 this.offsets[newEntryNum] - this.offsets[splitEntryNum]); 418 } 419 System.arraycopy(entry.key, 0, right.pageBuffer, 421 right.offsets[rightNewEntryNum], entry.key.length); 422 System.arraycopy(entry.data, 0, right.pageBuffer, 423 right.offsets[rightNewEntryNum] + entry.key.length, 424 dataLength); 425 426 if (newEntryNum != nextOffset) { 428 System.arraycopy(this.pageBuffer, this.offsets[newEntryNum], 429 right.pageBuffer, right.offsets[rightNewEntryNum + 1], 430 pageSize - this.offsets[newEntryNum]); 431 } 432 } 433 434 441 int bytesRemoved = pageSize - this.offsets[splitEntryNum]; 443 int splitPoint = this.offsets[splitEntryNum]; 444 int entriesStart = this.offsets[0]; 445 int insertPoint = this.offsets[newEntryNum]; 446 447 for (int i = 0; i < splitEntryNum; i++) { 448 left.offsets[i] = this.offsets[i] + bytesRemoved; 449 } 450 left.nextOffset = splitEntryNum; 451 left.offsets[left.nextOffset] = pageSize; 452 left.freeStart = headerLength + left.nextOffset*SIZE_OF_OFFSET; 453 454 if (!insertLeft) { 455 System.arraycopy(this.pageBuffer, entriesStart, left.pageBuffer, 456 left.offsets[0], splitPoint - entriesStart); 457 } else { 458 shiftOffsets(left, newEntryNum, entry.length()); 460 left.freeStart += SIZE_OF_OFFSET; 461 462 465 if (insertPoint != splitPoint) { 467 System.arraycopy(this.pageBuffer, insertPoint, 468 left.pageBuffer, left.offsets[newEntryNum + 1], 469 splitPoint - insertPoint); 470 } 471 if (insertPoint != entriesStart) { 475 System.arraycopy(this.pageBuffer, entriesStart, 476 left.pageBuffer, left.offsets[0], 477 insertPoint - entriesStart); 478 } 479 480 System.arraycopy(entry.key, 0, left.pageBuffer, 482 left.offsets[newEntryNum], entry.key.length); 483 System.arraycopy(entry.data, 0, left.pageBuffer, 484 left.offsets[newEntryNum] + entry.key.length, 485 dataLength); 486 } 487 488 if (left != this) { 489 this.nextOffset = 0; 490 this.freeStart = headerLength; 491 this.offsets[0] = pageSize; 492 } 493 494 rightKeyLength = right.keyLength(0); 496 rightKey = new byte[rightKeyLength]; 497 System.arraycopy(right.pageBuffer, right.offsets[0], rightKey, 0, 498 rightKeyLength); 499 return rightKey; 500 } 501 502 private void shiftOffsets(VarKeyPage page, int entryNum, int entryLength) { 503 504 if (entryNum != page.nextOffset) { 505 for (int i = page.nextOffset; i > entryNum; i--) { 508 page.offsets[i] = page.offsets[i-1]; 509 } 510 } 511 page.nextOffset++; 512 page.offsets[page.nextOffset] = btree.pageSize; 513 514 518 for (int i = entryNum; i >= 0; i--) { 519 page.offsets[i] -= entryLength; 520 } 521 } 522 523 boolean haveSpaceForInsert(BtreeEntry entry) { 524 525 int freeSpace = offsets[0] - freeStart; 526 527 if ((entry.length() + SIZE_OF_OFFSET) <= freeSpace) { 528 return true; 529 } else { 530 return false; 531 } 532 } 533 534 public void dumpPageHeader(PrintWriter out) { 535 536 super.dumpPageHeader(out); 537 538 out.println("\nOffsets table:\n"); 539 540 for (int i = 0; i < nextOffset; i++) { 541 out.print(offsets[i] + " "); 542 } 543 out.println(); 544 } 545 } 546 | Popular Tags |