|                                                                                                              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                                                                                                                                                                                              |