|                                                                                                              1
 24
 25  package com.mckoi.database;
 26
 27  import java.io.IOException
  ; 28  import java.io.File
  ; 29  import java.io.DataOutputStream
  ; 30  import java.io.ByteArrayOutputStream
  ; 31  import java.util.ArrayList
  ; 32  import com.mckoi.util.IntegerListInterface;
 33  import com.mckoi.util.AbstractBlockIntegerList;
 34  import com.mckoi.util.BlockIntegerList;
 35  import com.mckoi.util.BlockIntegerList.IntArrayListBlock;
 36  import com.mckoi.util.IntegerListBlockInterface;
 37  import com.mckoi.util.IntegerIterator;
 38  import com.mckoi.util.IndexComparator;
 39  import com.mckoi.util.ByteBuffer;
 40  import com.mckoi.util.ByteArrayUtil;
 41  import com.mckoi.util.IntegerVector;
 42  import com.mckoi.util.UserTerminal;
 43  import com.mckoi.util.Cache;
 44  import com.mckoi.debug.*;
 45
 46
 62
 63  public final class IndexStore {
 64
 65
 68    private DebugLogger debug;
 69
 70
 73    private File
  file; 74
 75
 82    private int block_size;
 83
 84
 87    private FixedSizeDataStore index_store;
 88
 89
 105   private ByteBuffer index_table_list;
 106   private byte[] index_table_list_buf;
 107
 108
 112   private int allocation_sector;
 113
 114
 117   private int allocation_length;
 118
 119
 124   private ArrayList
  memory_index_set_list; 125
 126
 130   private ArrayList
  index_set_garbage; 131
 132
 133
 137   private long unique_id;
 138
 139
 142   private Cache sector_cache;
 143
 145
 151   public IndexStore(File
  file_name, DebugLogger logger) { 152     this.debug = logger;
 153     this.file = file_name;
 154     this.memory_index_set_list = new ArrayList
  (); 155     this.index_set_garbage = new ArrayList
  (); 156     this.sector_cache = new Cache(47, 47, 10);
 157   }
 158
 159
 161
 166   private synchronized void readIndexTableList() throws IOException
  { 167         byte[] buf = new byte[32];
 169     index_store.readReservedBuffer(buf, 0, 32);
 170     allocation_sector = ByteArrayUtil.getInt(buf, 0);
 171     allocation_length = ByteArrayUtil.getInt(buf, 4);
 172     unique_id = ByteArrayUtil.getLong(buf, 8);
 173         buf = new byte[allocation_length];
 175     index_store.readAcross(allocation_sector, buf, 0, allocation_length);
 176     index_table_list_buf = new byte[allocation_length];
 177     index_table_list = new ByteBuffer(index_table_list_buf);
 178     index_table_list.put(buf);
 179   }
 180
 181
 184   private synchronized void initBlank() throws IOException
  { 185         allocation_length = 0;
 187     byte[] buf = new byte[allocation_length];
 188     allocation_sector = index_store.writeAcross(buf, 0, buf.length);
 189         buf = new byte[32];
 191     ByteArrayUtil.setInt(allocation_sector, buf, 0);
 192     ByteArrayUtil.setInt(allocation_length, buf, 4);
 193     ByteArrayUtil.setLong(1, buf, 8);
 194     index_store.writeReservedBuffer(buf, 0, 32);
 195   }
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 208
 211   public synchronized boolean exists() throws IOException
  { 212     return file.exists();
 213   }
 214
 215
 224   public synchronized void create(int block_size) throws IOException
  { 225         if (index_store != null && !index_store.isClosed()) {
 227       throw new Error
  ("Index store is already open."); 228     }
 229
 230     if (block_size > 32767) {
 231       throw new Error
  ("block_size must be less than 32768"); 232     }
 233     if (exists()) {
 234       throw new IOException
  ("Index store file '" + file + 235                             "' already exists.");
 236     }
 237
 238         unique_id = 1;
 240
 241         this.block_size = block_size;
 243         int sector_size = block_size * 4;
 245         this.index_store = new FixedSizeDataStore(file, sector_size, false, debug);
 247
 248         index_store.open(false);
 250
 251         initBlank();
 253
 254   }
 255
 256
 266   public synchronized boolean open(boolean read_only) throws IOException
  { 267         if (index_store != null && !index_store.isClosed()) {
 269       throw new Error
  ("Index store is already open."); 270     }
 271
 272     if (index_store == null) {
 273             this.index_store = new FixedSizeDataStore(file, -1, false, debug);
 275     }
 276
 277         boolean dirty_open = index_store.open(read_only);
 279
 280         int sector_size = index_store.getSectorSize();
 282         if (sector_size % 4 != 0) {
 284       throw new Error
  ("Assert failed, sector size must be divisible by 4"); 285     }
 286         this.block_size = sector_size / 4;
 288
 289     return dirty_open;
 290   }
 291
 292
 297   public synchronized void init() throws IOException
  { 298         readIndexTableList();
 300   }
 301
 302
 312   public synchronized boolean fix(UserTerminal terminal) throws IOException
  { 313
 314         index_store.fix(terminal);
 316
 317         readIndexTableList();
 319
 320         int raw_sector_count = index_store.rawSectorCount();
 322
 323         try {
 325             byte[] buf = new byte[32];
 327       index_store.readReservedBuffer(buf, 0, 32);
 328     }
 329     catch (IOException
  e) { 330       terminal.println("! Index store is irrepairable - " +
 331                        "reserved area is missing.");
 332                   throw new IOException
  ("Irrepairable index store."); 335     }
 336
 337     try {
 338       readIndexTableList();
 339
 340             long used_block_count = 0;
 342             long total_block_count = 0;
 344
 345             BlockIntegerList sector_list = new BlockIntegerList();
 347
 348             index_table_list.position(0);
 350
 351                   while (index_table_list.position() < index_table_list.limit()) {
 354         byte type = index_table_list.getByte();
 355         int block_count = index_table_list.getInt();
 356         int stat_sector = index_table_list.getInt();
 357
 358         if (stat_sector != -1) {
 359           boolean b = sector_list.uniqueInsertSort(stat_sector);
 360           if (b == false) {
 361             terminal.println("! Index store is not stable - " +
 362                              "double reference to stat_sector.");
 363             return false;
 364           }
 365
 366                     if (stat_sector < 0 || stat_sector >= raw_sector_count ||
 368               index_store.isSectorDeleted(stat_sector)) {
 369             terminal.println("! Index store is not stable - " +
 370                              "referenced sector is deleted.");
 371             return false;
 372           }
 373
 374         }
 375
 376         for (int i = 0; i < block_count; ++i) {
 377           int first_entry = index_table_list.getInt();
 378           int last_entry = index_table_list.getInt();
 379           int block_sector = index_table_list.getInt();
 380           short int_count = index_table_list.getShort();
 381
 382                     used_block_count += int_count;
 384           total_block_count += block_size;
 385
 386                     boolean b = sector_list.uniqueInsertSort(block_sector);
 388           if (b == false) {
 389             terminal.println("! Index store is not stable - " +
 390                              "double reference to block sector.");
 391             return false;
 392           }
 393
 394                     if (block_sector < 0 || block_sector >= raw_sector_count ||
 396               index_store.isSectorDeleted(block_sector)) {
 397             terminal.println("! Index store is not stable - " +
 398                              "referenced sector is deleted.");
 399             return false;
 400           }
 401
 402                     byte[] block_contents = index_store.getSector(block_sector);
 404                     if (int_count > 0) {
 406             if (ByteArrayUtil.getInt(block_contents, 0) != first_entry ||
 407                 ByteArrayUtil.getInt(block_contents, (int_count - 1) * 4) !=
 408                                                            last_entry) {
 409               terminal.println("! A block of an index list does not " +
 410                                "correctly correspond to its header info.");
 411               return false;
 412             }
 413           }
 414
 415         }
 417       }
 419             terminal.println("- Index store is stable.");
 421             terminal.println("- Total used block count = " + used_block_count);
 423             terminal.println("- Total available block count = " + total_block_count);
 425             if (total_block_count != 0) {
 427         double utilization = ((float) used_block_count /
 428                               (float) total_block_count) * 100f;
 429         terminal.println("- Index store utilization = " + utilization + "%");
 430       }
 431
 432       return true;
 433     }
 434     catch (IOException
  e) { 435       terminal.println("! IO Error scanning index store: " + e.getMessage());
 436       return false;
 437     }
 438
 439   }
 440
 441
 444   public synchronized boolean isReadOnly() {
 445     return index_store.isReadOnly();
 446   }
 447
 448
 451   public synchronized void delete() {
 452     index_store.delete();
 453   }
 454
 455
 459   public synchronized void copyTo(File
  path) throws IOException  { 460     index_store.copyTo(path);
 461   }
 462
 463
 466   public synchronized void close() throws IOException
  { 467     index_store.close();
 468     sector_cache = null;
 469     memory_index_set_list = null;
 470     index_set_garbage = null;
 471   }
 472
 473
 478   public synchronized void flush() throws IOException
  { 479         int old_sector = allocation_sector;
 481     int old_length = allocation_length;
 482         allocation_length = index_table_list_buf.length;
 484     allocation_sector =
 485         index_store.writeAcross(index_table_list_buf, 0, allocation_length);
 486
 487         ByteArrayUtil.setInt(allocation_sector, flush_buffer, 0);
 489     ByteArrayUtil.setInt(allocation_length, flush_buffer, 4);
 490     ByteArrayUtil.setLong(unique_id, flush_buffer, 8);
 491     index_store.writeReservedBuffer(flush_buffer, 0, 32);
 492
 493         index_store.deleteAcross(old_sector);
 495   }
 496
 497   private byte[] flush_buffer = new byte[32];
 498
 499
 505   public synchronized void hardSynch() throws IOException
  { 506     index_store.hardSynch();
 507   }
 508
 509
 512   long currentUniqueID() {
 513     return unique_id - 1;
 514   }
 515
 516
 519   long nextUniqueID() {
 520     return unique_id++;
 521   }
 522
 523
 528   void setUniqueID(long value) {
 529     unique_id = value + 1;
 530   }
 531
 532
 535   int getBlockSize() {
 536     return block_size;
 537   }
 538
 539
 540
 547   public synchronized void addIndexLists(int count, byte type) {
 548
 549     int add_size = count * (1 + 4 + 4);
 550     ByteBuffer old_buffer = index_table_list;
 551
 552         index_table_list_buf = new byte[old_buffer.limit() + add_size];
 554     index_table_list = new ByteBuffer(index_table_list_buf);
 555         old_buffer.position(0);
 557     index_table_list.put(old_buffer);
 558         for (int i = 0; i < count; ++i) {
 560             index_table_list.putByte(type);
 562             index_table_list.putInt(0);
 564             index_table_list.putInt(-1);
 566     }
 567   }
 568
 569
 573   private synchronized void addIndexSetToList(IndexSet index_set) {
 574     memory_index_set_list.add(index_set);
 575   }
 576
 577
 584   private synchronized void removeIndexSetFromList(IndexSet index_set) {
 585         if (index_set_garbage == null) {
 587       return;
 588     }
 589
 590     SnapshotIndexSet s_index_set = (SnapshotIndexSet) index_set;
 591         boolean b = memory_index_set_list.remove(index_set);
 593     if (!b) {
 594       throw new Error
  ("IndexSet was not in the list!"); 595     }
 596
 597         if (s_index_set.hasDeletedSectors()) {
 599       index_set_garbage.add(index_set);
 600
 601             long lowest_id = -1;       if (memory_index_set_list.size() > 0) {
 604         lowest_id = ((SnapshotIndexSet) memory_index_set_list.get(0)).getID();
 605       }
 606
 607                   boolean deleted;
 610       do {
 611         SnapshotIndexSet set = (SnapshotIndexSet) index_set_garbage.get(0);
 612         deleted = set.getID() < lowest_id;
 613         if (deleted) {
 614                     IntegerVector to_delete = set.allDeletedSectors();
 616
 617                     final int sz = to_delete.size();
 619           int n = 0;
 620           try {
 621             for (n = 0; n < sz; ++n) {
 622               int sector = to_delete.intAt(n);
 623               index_store.deleteSector(sector);
 624             }
 625
 626           }
 627           catch (IOException
  e) { 628             debug.write(Lvl.ERROR, this,
 629                       "Error deleting index " + n + " of list " + to_delete);
 630             debug.writeException(e);
 631             throw new Error
  ("IO Error: " + e.getMessage()); 632           }
 633           index_set_garbage.remove(0);
 634
 635         }
 637       } while (deleted && index_set_garbage.size() > 0);
 638
 639     }
 640
 641   }
 642
 643
 654   public synchronized IndexSet getSnapshotIndexSet() {
 655             IndexSet index_set =
 658                new SnapshotIndexSet(index_table_list_buf, allocation_length);
 659     addIndexSetToList(index_set);
 660     return index_set;
 661   }
 662
 663
 680   public synchronized void commitIndexSet(IndexSet index_set) {
 681
 682         if (memory_index_set_list.get(memory_index_set_list.size() - 1) !=
 684         index_set) {
 685       throw new Error
  ("Can not commit IndexSet because it is not current."); 686     }
 687
 688     SnapshotIndexSet iset = (SnapshotIndexSet) index_set;
 689
 690     byte[] new_buffer = iset.commit();
 691     index_table_list_buf = new_buffer;
 692     index_table_list =
 693         new ByteBuffer(index_table_list_buf, 0, index_table_list_buf.length);
 694
 695   }
 696
 697
 700   public synchronized String
  statusString() throws IOException  { 701     return index_store.statusString();
 702   }
 703
 704
 705
 706
 707
 709
 713   private long SET_ID_KEY = 0;
 714
 715
 718   private static IndexIntegerList[] EMPTY_INTEGER_LISTS =
 719                                                   new IndexIntegerList[0];
 720
 721
 722
 726   private class SnapshotIndexSet implements IndexSet {
 727
 728
 731     private long set_id;
 732
 733
 736     private ByteBuffer buf;
 737
 738
 741     private int buf_length;
 742
 743
 747     private ArrayList
  integer_lists; 748
 749
 753     private IntegerVector deleted_sectors;
 754
 755
 756
 757
 760     public SnapshotIndexSet(byte[] in_buf, int length) {
 761
 762       this.set_id = SET_ID_KEY;
 763       ++SET_ID_KEY;
 764
 765                         this.buf = new ByteBuffer(in_buf);
 769       this.buf_length = length;
 770
 771     }
 772
 773
 777     public IndexIntegerList[] getAllLists() {
 778       if (integer_lists == null) {
 779         return EMPTY_INTEGER_LISTS;
 780       }
 781       else {
 782         return (IndexIntegerList[]) integer_lists.toArray(
 783                                 new IndexIntegerList[integer_lists.size()]);
 784       }
 785     }
 786
 787
 791     private ByteBuffer getByteBuffer() {
 792       return buf;
 793     }
 794
 795
 798     long getID() {
 799       return set_id;
 800     }
 801
 802
 805     boolean hasDeletedSectors() {
 806       return (deleted_sectors != null && deleted_sectors.size() > 0);
 807     }
 808
 809
 812     IntegerVector allDeletedSectors() {
 813       return deleted_sectors;
 814     }
 815
 816
 821     byte[] commit() {
 822
 823       if (deleted_sectors != null) {
 824         throw new Error
  ("'deleted_sectors' contains sectors to delete."); 825       }
 826
 827       deleted_sectors = new IntegerVector();
 828
 829             IndexIntegerList[] lists = getAllLists();
 831
 832             int sz = lists.length;
 834       for (int i = 0; i < sz; ++i) {
 835         lists[i].setImmutable();
 836       }
 837
 838             ByteArrayOutputStream
  bout = new ByteArrayOutputStream  (); 840       DataOutputStream
  dout = new DataOutputStream  (bout); 841
 842             ByteBuffer snapshot_buf = getByteBuffer();
 844
 845       synchronized (snapshot_buf) {
 846         int buf_size = snapshot_buf.limit();
 847         snapshot_buf.position(0);
 848
 849         try {
 850
 851           int index_num = 0;
 852           while (snapshot_buf.position() < buf_size) {
 853                         byte list_type = snapshot_buf.getByte();
 855             int blocks_count = snapshot_buf.getInt();
 856             int stat_sector = snapshot_buf.getInt();
 857             byte[] buf = new byte[blocks_count * ( 4 + 4 + 4 + 2 )];
 858             snapshot_buf.get(buf, 0, buf.length);
 859
 860
 863                         IndexIntegerList list = null;
 865             for (int i = 0; i < sz && list == null; ++i) {
 866               if (lists[i].getIndexNumber() == index_num) {
 867                                 list = lists[i];
 869               }
 870             }
 871
 872                         if (list != null) {
 874
 875                             MappedListBlock[] deleted_blocks = list.getDeletedBlocks();
 877               for (int n = 0; n < deleted_blocks.length; ++n) {
 878                                 MappedListBlock block = (MappedListBlock) deleted_blocks[n];
 880                                 int sector = block.getIndexSector();
 882                 if (sector != -1) {
 883                   deleted_sectors.addInt(sector);
 884                 }
 885               }
 886
 887                                           MappedListBlock[] blocks = list.getAllBlocks();
 890               blocks_count = blocks.length;
 891               dout.writeByte(list_type);
 892               dout.writeInt(blocks_count);
 893               dout.writeInt(stat_sector);
 894                             for (int n = 0; n < blocks_count; ++n) {
 896                 MappedListBlock block = blocks[n];
 897                 int bottom_int = 0;
 898                 int top_int = 0;
 899                 short block_size = (short) block.size();
 900                 if (block_size > 0) {
 901                   bottom_int = block.bottomInt();
 902                   top_int = block.topInt();
 903                 }
 904                 int block_sector = block.getIndexSector();
 905                                 if (block_sector == -1 || block.hasChanged()) {
 907                                                       if (block_sector != -1) {
 910                     deleted_sectors.addInt(block_sector);
 911                   }
 912                                                       block_sector = block.writeToStore();
 915                 }
 916                                 dout.writeInt(bottom_int);
 918                 dout.writeInt(top_int);
 919                 dout.writeInt(block_sector);
 920                 dout.writeShort(block_size);
 921               }
 922
 923             }
 924                         else {
 926
 927                             dout.writeByte(list_type);
 929               dout.writeInt(blocks_count);
 930               dout.writeInt(stat_sector);
 931               dout.write(buf, 0, buf.length);
 932
 933             }
 934
 935             ++index_num;
 936           }
 937
 938                     dout.flush();
 940
 941         }
 942         catch (IOException
  e) { 943           debug.writeException(e);
 944           throw new Error
  (e.getMessage()); 945         }
 946
 947       }
 949             byte[] arr = bout.toByteArray();
 951
 952             return arr;
 954
 955     }
 956
 957
 958
 959
 960
 961
 962
 963
 964
 966     public IntegerListInterface getIndex(int n) {
 967       int original_n = n;
 968             synchronized(buf) {
 970
 971                 if (integer_lists == null) {
 973           integer_lists = new ArrayList
  (); 974         }
 975         else {
 976                     for (int o = 0; o < integer_lists.size(); ++o) {
 978             if (((IndexIntegerList) integer_lists.get(o)).getIndexNumber() ==
 979                 original_n) {
 980               throw new Error
  ( 981                           "IntegerListInterface already created for this n.");
 982             }
 983           }
 984         }
 985
 986         buf.position(0);
 987         while (n > 0) {
 988           byte list_type = buf.getByte();            int offset = buf.getInt();
 990           int stat_sector = buf.getInt();            buf.position(buf.position() + (offset * (4 + 4 + 4 + 2)));
 992           --n;
 993         }
 994         int list_type = buf.getByte();
 995         int list_size = buf.getInt();
 996         int list_stat_sector = buf.getInt();
 997
 998                                 MappedListBlock[] list_blocks = new MappedListBlock[list_size];
 1002
 1003        for (int i = 0; i < list_size; ++i) {
 1004          int first_entry = buf.getInt();
 1005          int last_entry = buf.getInt();
 1006          int block_sector = buf.getInt();
 1007          short block_size = buf.getShort();
 1008
 1009          list_blocks[i] = new MappedListBlock(
 1010                          first_entry, last_entry, block_sector, block_size);
 1011
 1012        }
 1013
 1014                IndexIntegerList ilist = new IndexIntegerList(original_n, list_blocks);
 1016        integer_lists.add(ilist);
 1017        return ilist;
 1018
 1019      }
 1021    }
 1022
 1023    public void dispose() {
 1024            synchronized (buf) {
 1026        if (integer_lists != null) {
 1027          for (int i = 0; i < integer_lists.size(); ++i) {
 1028            IndexIntegerList ilist = (IndexIntegerList) integer_lists.get(i);
 1029            ilist.dispose();
 1030          }
 1031          integer_lists = null;
 1032        }
 1033      }
 1034      buf = null;
 1035      removeIndexSetFromList(this);
 1036    }
 1037
 1038    public void finalize() {
 1039      if (buf != null) {
 1040        debug.write(Lvl.WARNING, this, "IndexStore was not disposed!");
 1041                removeIndexSetFromList(this);
 1043      }
 1045    }
 1046
 1047  }
 1048
 1049
 1053  private final class MappedListBlock extends IntArrayListBlock {
 1054
 1055
 1058    private int first_entry;
 1059
 1060
 1063    private int last_entry;
 1064
 1065
 1068    private int index_sector;
 1069
 1070
 1073    private Object
  lock = new Object  (); 1074
 1075
 1078    private boolean mutable_block;
 1079
 1080
 1083    public MappedListBlock(int first_int, int last_int,
 1084                           int mapped_sector, int size) {
 1085      this.first_entry = first_int;
 1086      this.last_entry = last_int;
 1087      this.index_sector = mapped_sector;
 1088      count = size;
 1089      array = null;
 1090    }
 1091
 1092
 1095    public MappedListBlock(int block_size_in) {
 1096      super(block_size_in);
 1097      this.index_sector = -1;
 1098    }
 1099
 1100
 1103    public int getIndexSector() {
 1104      return index_sector;
 1105    }
 1106
 1107
 1113    public int writeToStore() throws IOException
  { 1114            int block_count = block_size;
 1116      byte[] arr = new byte[block_count * 4];
 1117      int p = 0;
 1118      for (int i = 0; i < block_count; ++i) {
 1119        int v = array[i];
 1120        ByteArrayUtil.setInt(v, arr, p);
 1121        p += 4;
 1122      }
 1123
 1124            synchronized (IndexStore.this) {
 1126        index_sector = index_store.addSector(arr, 0, arr.length);
 1127      }
 1128
 1129            synchronized (sector_cache) {
 1131        sector_cache.put(new Integer
  (index_sector), array); 1132      }
 1133
 1134            lock = null;
 1136
 1137      return index_sector;
 1138    }
 1139
 1140
 1146    public int[] getArray(boolean immutable) {
 1147                  synchronized (lock) {
 1150
 1151        if (array != null) {
 1152          prepareMutate(immutable);
 1153          return array;
 1154        }
 1155
 1156                Object
  elem; 1158        synchronized (sector_cache) {
 1159          elem = sector_cache.get(new Integer
  (index_sector)); 1160        }
 1161        if (elem != null) {
 1162          array = (int[]) elem;
 1163          mutable_block = false;
 1164          prepareMutate(immutable);
 1165          return array;
 1166        }
 1167
 1168        int block_count = block_size;
 1169                array = new int[block_count];
 1171        synchronized (IndexStore.this) {
 1172          try {
 1173            array = index_store.getSectorAsIntArray(index_sector, array);
 1174          }
 1175          catch (IOException
  e) { 1176            debug.writeException(e);
 1177            throw new Error
  ("IO Error: " + e.getMessage()); 1178          }
 1179        }
 1180                synchronized (sector_cache) {
 1182          sector_cache.put(new Integer
  (index_sector), (int[]) array); 1183        }
 1184        mutable_block = false;
 1185        prepareMutate(immutable);
 1186        return array;
 1187
 1188      }
 1189
 1190    }
 1191
 1192
 1195    public int getArrayLength() {
 1196      return block_size;
 1197    }
 1198
 1199
 1203    private void prepareMutate(boolean immutable) {
 1204            if (!immutable && !mutable_block) {
 1206        array = (int[]) array.clone();
 1207        mutable_block = true;
 1208      }
 1209    }
 1210
 1211
 1214    public int topInt() {
 1215      if (count == 0) {
 1216        throw new Error
  ("No first int in block."); 1217      }
 1218
 1219      synchronized (lock) {
 1220        if (array == null) {
 1221          return last_entry;
 1222        }
 1223        else {
 1224          return array[count - 1];
 1225        }
 1226      }
 1227    }
 1228
 1229
 1233    public int bottomInt() {
 1234      if (count == 0) {
 1235        throw new Error
  ("No first int in block."); 1236      }
 1237
 1238      synchronized (lock) {
 1239        if (array == null) {
 1240          return first_entry;
 1241        }
 1242        else {
 1243          return array[0];
 1244        }
 1245      }
 1246    }
 1247
 1248  }
 1249
 1250
 1254  private final class IndexIntegerList extends AbstractBlockIntegerList {
 1255
 1256
 1259    private int index_num;
 1260
 1261
 1264    private boolean disposed = false;
 1265
 1266
 1269    private ArrayList
  deleted_blocks = new ArrayList  (); 1270
 1271
 1272
 1275    public IndexIntegerList(int index_num, MappedListBlock[] blocks) {
 1276      super(blocks);
 1277      this.index_num = index_num;
 1278    }
 1279
 1280
 1283    protected IntegerListBlockInterface newListBlock() {
 1284      if (!disposed) {
 1285        return new MappedListBlock(block_size);
 1286      }
 1287      throw new Error
  ("Integer list has been disposed."); 1288    }
 1289
 1290
 1293    protected void deleteListBlock(IntegerListBlockInterface list_block) {
 1294      deleted_blocks.add(list_block);
 1295    }
 1296
 1297
 1300    public int getIndexNumber() {
 1301      return index_num;
 1302    }
 1303
 1304
 1307    public MappedListBlock[] getAllBlocks() {
 1308      return (MappedListBlock[])
 1309                 block_list.toArray(new MappedListBlock[block_list.size()]);
 1310    }
 1311
 1312
 1316    public MappedListBlock[] getDeletedBlocks() {
 1317      return (MappedListBlock[])
 1318         deleted_blocks.toArray(new MappedListBlock[deleted_blocks.size()]);
 1319    }
 1320
 1321
 1322    public void dispose() {
 1323      disposed = true;
 1324      block_list = null;
 1325    }
 1326
 1327  }
 1328
 1329}
 1330
                                                                                                                                                                                                             |                                                                       
 
 
 
 
 
                                                                                   Popular Tags                                                                                                                                                                                              |