1 24 25 package com.mckoi.database; 26 27 import java.util.ArrayList ; 28 import java.io.*; 29 import com.mckoi.util.IntegerListInterface; 30 import com.mckoi.util.ByteArrayUtil; 31 import com.mckoi.util.UserTerminal; 32 import com.mckoi.debug.*; 33 34 44 45 public final class V1MasterTableDataSource extends MasterTableDataSource { 46 47 49 52 private String file_name; 53 54 58 private VariableSizeDataStore data_store; 59 60 63 private IndexStore index_store; 64 65 68 private final DataCellSerialization data_cell_serializer = 69 new DataCellSerialization(); 70 71 74 private CellInputStream cell_in; 75 76 77 78 81 public V1MasterTableDataSource(TransactionSystem system, 82 StoreSystem store_system, 83 OpenTransactionList open_transactions) { 84 super(system, store_system, open_transactions, null); 85 cell_in = new CellInputStream(null); 86 } 87 88 92 String getFileName() { 93 return file_name; 94 } 95 96 99 File getPath() { 100 return getSystem().getDatabasePath(); 101 } 102 103 118 synchronized void create(int table_id, DataTableDef table_def, 119 int data_sector_size, int index_sector_size) 120 throws IOException { 121 122 setupDataTableDef(table_def); 124 125 this.file_name = makeTableFileName(getSystem(), table_id, getTableName()); 127 128 data_store = new VariableSizeDataStore(new File(getPath(), file_name), 130 data_sector_size, Debug()); 131 data_store.open(false); 133 134 index_store = new IndexStore( 136 new File(getPath(), file_name + ".iid"), Debug()); 137 index_store.create(index_sector_size); 139 index_store.init(); 140 index_store.addIndexLists(table_def.columnCount() + 1, (byte) 1); 142 index_store.flush(); 143 144 saveDataTableDef(table_def); 146 147 byte[] reserved_buffer = new byte[64]; 150 ByteArrayUtil.setInt(table_id, reserved_buffer, 0); 151 data_store.writeReservedBuffer(reserved_buffer, 0, 64); 152 153 this.table_id = table_id; 155 156 loadInternal(); 158 159 } 160 161 165 synchronized boolean exists(String file_name) throws IOException { 166 VariableSizeDataStore data_store = 167 new VariableSizeDataStore(new File(getPath(), file_name), Debug()); 168 return data_store.exists(); 169 } 170 171 176 synchronized void open(String file_name) throws IOException { 177 178 data_store = new VariableSizeDataStore( 180 new File(getPath(), file_name), Debug()); 181 boolean need_check = data_store.open(isReadOnly()); 182 183 byte[] reserved_buffer = new byte[64]; 187 data_store.readReservedBuffer(reserved_buffer, 0, 64); 188 table_id = ByteArrayUtil.getInt(reserved_buffer, 0); 189 190 this.file_name = file_name; 192 193 table_def = loadDataTableDef(); 195 196 column_count = table_def.columnCount(); 198 199 table_indices = new MultiVersionTableIndices(getSystem(), 201 table_def.getTableName(), table_def.columnCount()); 202 column_rid_list = new RIDList[table_def.columnCount()]; 204 205 index_store = new IndexStore( 207 new File(getPath(), file_name + ".iid"), Debug()); 208 if (!index_store.exists()) { 210 if (!isReadOnly()) { 211 File original_ijf = new File(getPath(), file_name + ".ijf"); 213 if (original_ijf.exists()) { 214 String str = "Converting index file for: " + file_name; 216 System.out.println(str); 217 Debug().write(Lvl.INFORMATION, this, str); 218 ArrayList transaction_journals = 220 ConvertUtils.convertIndexFiles1(original_ijf, index_store, 221 table_def, Debug()); 222 if (transaction_journals.size() > 0) { 223 Debug().write(Lvl.ERROR, this, 225 "There are uncommitted changes that were not " + 226 "converted because the pre 0.92 database was not closed " + 227 "cleanly."); 228 } 229 need_check = true; 231 } 232 else { 233 throw new IOException("The index file for '" + file_name + 234 "' does not exist."); 235 } 236 } 237 else { 238 throw new IOException( 239 "Can not create .iid index file in read-only mode."); 240 } 241 } 242 else { 243 index_store.open(isReadOnly()); 245 index_store.init(); 246 } 247 248 loadInternal(); 250 251 setupDataIndexSetDef(); 253 254 if (need_check) { 255 doOpeningScan(); 258 } 259 260 } 261 262 266 synchronized void dirtyOpen(String file_name) throws IOException { 267 268 data_store = new VariableSizeDataStore( 271 new File(getPath(), file_name), Debug()); 272 data_store.open(false); 273 274 byte[] reserved_buffer = new byte[64]; 278 data_store.readReservedBuffer(reserved_buffer, 0, 64); 279 table_id = ByteArrayUtil.getInt(reserved_buffer, 0); 280 281 this.file_name = file_name; 283 284 table_def = loadDataTableDef(); 286 287 } 288 289 295 synchronized void close() throws IOException { 296 if (table_indices != null) { 297 mergeJournalChanges(Integer.MAX_VALUE); 299 300 if (!isReadOnly()) { 301 index_store.flush(); 303 } 305 } 306 307 index_store.close(); 309 data_store.close(); 310 311 table_id = -1; 312 table_def = null; 314 table_indices = null; 315 column_rid_list = null; 316 is_closed = true; 317 } 318 319 324 synchronized int rawRecordSize(int row_number) throws IOException { 325 326 int size = 2; 327 328 ++row_number; 329 330 InputStream in = data_store.getRecordInputStream(row_number); 332 cell_in.setParentStream(in); 333 334 cell_in.skip(2); 335 336 for (int i = 0; i < column_count; ++i) { 337 int len = data_cell_serializer.skipSerialization(cell_in); 338 if (len <= 0) { 339 throw new Error ("Corrupt data - cell size is <= 0"); 340 } 341 cell_in.skip(len); 342 size += 4 + len; 343 } 344 345 cell_in.close(); 346 347 return size; 348 349 } 350 351 354 synchronized int rawDataSectorSize() throws IOException { 355 return data_store.sectorSize(); 356 } 357 358 366 private synchronized void rebuildAllIndices(File path, String file_name) 367 throws IOException { 368 369 File temporary_name = new File(path, file_name + ".id2"); 371 File actual_name = new File(path, file_name + ".iid"); 373 374 IndexStore temp_store = new IndexStore(temporary_name, Debug()); 376 temp_store.create(index_store.getBlockSize()); 378 temp_store.init(); 379 temp_store.addIndexLists(column_count + 1, (byte) 1); 380 381 IndexSet index_set = temp_store.getSnapshotIndexSet(); 383 384 IntegerListInterface master_index = index_set.getIndex(0); 386 387 TableDataSource table = minimalTableDataSource(master_index); 389 390 SelectableScheme[] cols = new SelectableScheme[column_count]; 392 for (int i = 0; i < column_count; ++i) { 393 cols[i] = createSelectableSchemeForColumn(index_set, table, i); 394 } 395 396 int row_count = rawRowCount(); 398 for (int i = 0 ; i < row_count; ++i) { 399 if (!recordDeleted(i)) { 401 int type = recordTypeInfo(i); 403 if (type == RawDiagnosticTable.COMMITTED_ADDED) { 406 master_index.uniqueInsertSort(i); 408 for (int n = 0; n < column_count; ++n) { 410 cols[n].insert(i); 411 } 412 } 413 } } 416 418 temp_store.commitIndexSet(index_set); 421 index_set.dispose(); 422 temp_store.flush(); 423 424 index_store.close(); 426 index_store.delete(); 427 temp_store.close(); 429 boolean b = temporary_name.renameTo(actual_name); 431 if (b == false) { 432 throw new IOException("Unable to rename " + 433 temporary_name + " to " + actual_name); 434 } 435 temp_store = null; 436 437 index_store = new IndexStore(actual_name, Debug()); 439 index_store.open(false); 440 index_store.init(); 441 442 } 443 444 450 synchronized void copyTo(File path) throws IOException { 451 data_store.copyTo(path); 452 index_store.copyTo(path); 453 } 454 455 456 457 458 460 466 public synchronized void checkAndRepair(String file_name, 467 UserTerminal terminal) throws IOException { 468 469 data_store = new VariableSizeDataStore( 471 new File(getPath(), file_name), Debug()); 472 boolean need_check = data_store.open(isReadOnly()); 473 data_store.fix(terminal); 475 477 byte[] reserved_buffer = new byte[64]; 481 data_store.readReservedBuffer(reserved_buffer, 0, 64); 482 table_id = ByteArrayUtil.getInt(reserved_buffer, 0); 483 484 this.file_name = file_name; 486 487 table_def = loadDataTableDef(); 489 490 491 492 493 table_indices = new MultiVersionTableIndices(getSystem(), 495 table_def.getTableName(), table_def.columnCount()); 496 column_rid_list = new RIDList[table_def.columnCount()]; 498 499 index_store = new IndexStore( 501 new File(getPath(), file_name + ".iid"), Debug()); 502 need_check = index_store.open(isReadOnly()); 504 boolean index_store_stable = index_store.fix(terminal); 506 507 loadInternal(); 509 510 mergeJournalChanges(Integer.MAX_VALUE); 512 513 terminal.println("+ Rebuilding all index information for table!"); 517 rebuildAllIndices(getPath(), file_name); 518 520 doOpeningScan(); 523 524 } 525 526 527 public synchronized void checkForCleanup() { 528 } 530 531 532 534 String getSourceIdent() { 535 return getFileName(); 536 } 537 538 539 synchronized void synchAll() throws IOException { 540 541 index_store.flush(); 543 544 if (!getSystem().dontSynchFileSystem()) { 546 data_store.hardSynch(); 547 } 548 549 if (!getSystem().dontSynchFileSystem()) { 553 index_store.hardSynch(); 554 } 555 556 } 557 558 559 synchronized int writeRecordType(int row_index, int row_state) 560 throws IOException { 561 return data_store.writeRecordType(row_index + 1, row_state); 562 } 563 564 565 synchronized int readRecordType(int row_index) throws IOException { 566 return data_store.readRecordType(row_index + 1); 567 } 568 569 570 synchronized boolean recordDeleted(int row_index) throws IOException { 571 return data_store.recordDeleted(row_index + 1); 572 } 573 574 575 synchronized int rawRowCount() throws IOException { 576 return data_store.rawRecordCount() - 1; 577 } 578 579 580 581 synchronized void internalDeleteRow(int row_index) throws IOException { 582 data_store.delete(row_index + 1); 584 } 585 586 587 IndexSet createIndexSet() { 588 return index_store.getSnapshotIndexSet(); 589 } 590 591 592 synchronized void commitIndexSet(IndexSet index_set) { 593 index_store.commitIndexSet(index_set); 594 index_set.dispose(); 595 } 596 597 598 synchronized DataTableDef loadDataTableDef() throws IOException { 599 600 byte[] d = new byte[65536]; 602 int read = data_store.read(0, d, 0, 65536); 603 if (read == 65536) { 604 throw new IOException( 605 "Buffer overflow when reading table definition, > 64k"); 606 } 607 ByteArrayInputStream bin = new ByteArrayInputStream(d, 0, read); 608 609 DataTableDef def; 610 611 DataInputStream din = new DataInputStream(bin); 612 int mn = din.readInt(); 613 if (mn == 0x0bebb) { 615 def = DataTableDef.read(din); 617 } 618 else { 619 throw new IOException( 621 "Couldn't find magic number for table definition data."); 622 } 623 624 return def; 625 626 } 627 628 629 synchronized void saveDataTableDef(DataTableDef def) throws IOException { 630 631 ByteArrayOutputStream bout = new ByteArrayOutputStream(); 632 DataOutputStream dout = new DataOutputStream(bout); 633 634 dout.writeInt(0x0bebb); 635 def.write(dout); 636 637 639 byte[] d = bout.toByteArray(); 640 int rindex = data_store.write(d, 0, d.length); 641 642 if (rindex != 0) { 644 throw new IOException("Couldn't write table fields to record 0."); 645 } 646 647 } 648 649 650 synchronized int internalAddRow(RowData data) throws IOException { 651 652 OutputStream out = data_store.getRecordOutputStream(); 653 DataOutputStream temp_out = new DataOutputStream(out); 654 655 temp_out.writeShort(0); 657 658 int row_cells = data.getColumnCount(); 659 660 for (int i = 0; i < row_cells; ++i) { 662 TObject cell = data.getCellData(i); 663 data_cell_serializer.setToSerialize(cell); 664 data_cell_serializer.writeSerialization(temp_out); 665 } 666 667 temp_out.close(); 669 int record_index = data_store.completeRecordStreamWrite(); 670 671 if (DATA_CELL_CACHING) { 673 for (int i = 0; i < row_cells; ++i) { 674 cache.put(table_id, record_index, i, data.getCellData(i)); 676 } 677 } 678 679 int row_number = record_index - 1; 681 682 for (int i = 0; i < column_count; ++i) { 685 RIDList rid_list = column_rid_list[i]; 686 if (rid_list != null) { 687 rid_list.insertRID(data.getCellData(i), row_number); 688 } 689 } 690 691 return row_number; 693 694 } 695 696 697 699 private short s_run_total_hits = 0; 700 private short s_run_file_hits = 0; 701 702 704 708 private int OPT_last_row = -1; 709 private int OPT_last_col = -1; 710 private int OPT_last_skip_offset = -1; 711 712 synchronized TObject internalGetCellContents(int column, int row) { 713 714 729 if (s_run_total_hits >= 1600) { 731 getSystem().stats().add(s_run_total_hits, total_hits_key); 732 getSystem().stats().add(s_run_file_hits, file_hits_key); 733 s_run_total_hits = 0; 734 s_run_file_hits = 0; 735 } 736 737 ++s_run_total_hits; 739 740 ++row; 742 743 TObject cell; 745 if (DATA_CELL_CACHING) { 746 cell = cache.get(table_id, row, column); 747 if (cell != null) { 748 return cell; 749 } 750 } 751 752 ++s_run_file_hits; 754 755 759 try { 760 761 InputStream in = data_store.getRecordInputStream(row); 763 cell_in.setParentStream(in); 764 765 772 int start_col; 773 if (OPT_last_row == row && column >= OPT_last_col) { 774 cell_in.skip(OPT_last_skip_offset); 775 start_col = OPT_last_col; 776 } 777 else { 778 cell_in.skip(2); 779 OPT_last_row = row; 780 OPT_last_skip_offset = 2; 781 OPT_last_col = 0; 782 start_col = 0; 783 } 784 785 for (int i = start_col; i < column; ++i) { 786 int len = data_cell_serializer.skipSerialization(cell_in); 787 if (len <= 0) { 788 throw new Error ("Corrupt data - cell size is <= 0"); 789 } 790 cell_in.skip(len); 791 ++OPT_last_col; 792 OPT_last_skip_offset += len + 4; } 794 Object ob = data_cell_serializer.readSerialization(cell_in); 796 TType ttype = getDataTableDef().columnAt(column).getTType(); 799 cell = new TObject(ttype, ob); 801 802 cell_in.close(); 804 805 if (DATA_CELL_CACHING) { 807 cache.put(table_id, row, column, cell); 808 } 809 return cell; 810 811 } 812 catch (IOException e) { 813 Debug().writeException(e); 814 throw new Error ("IOError getting cell at (" + column + ", " + 815 row + ")."); 816 } 817 818 } 819 820 821 synchronized long currentUniqueID() { 822 return index_store.currentUniqueID(); 823 } 824 825 synchronized long nextUniqueID() { 826 return index_store.nextUniqueID(); 827 } 828 829 synchronized void setUniqueID(long value) { 830 index_store.setUniqueID(value); 831 } 832 833 834 synchronized void dispose(boolean pending_close) throws IOException { 835 close(); 836 } 837 838 synchronized boolean drop() throws IOException { 839 if (!is_closed) { 840 close(); 841 } 842 843 Debug().write(Lvl.MESSAGE, this, "Dropping: " + getFileName()); 844 data_store.delete(); 845 index_store.delete(); 846 847 return true; 848 } 849 850 void shutdownHookCleanup() { 851 } 853 854 857 public String toString() { 858 return "[V1MasterTableDataSource: " + file_name + "]"; 859 } 860 861 } 862 863 | Popular Tags |