View Javadoc

1   /*
2   Copyright (c) 2008 Health Market Science, Inc.
3   
4   This library is free software; you can redistribute it and/or
5   modify it under the terms of the GNU Lesser General Public
6   License as published by the Free Software Foundation; either
7   version 2.1 of the License, or (at your option) any later version.
8   
9   This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  Lesser General Public License for more details.
13  
14  You should have received a copy of the GNU Lesser General Public
15  License along with this library; if not, write to the Free Software
16  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
17  USA
18  
19  You can contact Health Market Science at info@healthmarketscience.com
20  or at the following address:
21  
22  Health Market Science
23  2700 Horizon Drive
24  Suite 200
25  King of Prussia, PA 19406
26  */
27  
28  package com.healthmarketscience.jackcess;
29  
30  import java.io.IOException;
31  import java.util.List;
32  
33  
34  /**
35   * Simple implementation of an Access table index
36   * @author Tim McCune
37   */
38  public class SimpleIndex extends Index {
39  
40    /** data for the single index page.  if this data came from multiple pages,
41        the index is read-only. */
42    private SimpleDataPage _dataPage;
43    
44    public SimpleIndex(Table table, int uniqueEntryCount,
45                       int uniqueEntryCountOffset)
46    {
47      super(table, uniqueEntryCount, uniqueEntryCountOffset);
48    }
49  
50    @Override
51    protected void updateImpl() throws IOException {
52      writeDataPage(_dataPage);
53    }
54  
55    @Override
56    protected void readIndexEntries()
57      throws IOException
58    {
59      // find first leaf page
60      int nextPageNumber = getRootPageNumber();
61      SimpleDataPage indexPage = null;
62      while(true) {
63        indexPage = new SimpleDataPage(nextPageNumber);
64        readDataPage(indexPage);
65  
66        if(!indexPage.isLeaf()) {
67          // FIXME we can't modify this index at this point in time
68          setReadOnly();
69  
70          // found another node page
71          nextPageNumber = indexPage.getEntries().get(0).getSubPageNumber();
72          indexPage = null;
73        } else {
74          // found first leaf
75          break;
76        }
77      }
78  
79      // save the first leaf page
80      _dataPage = indexPage;
81      nextPageNumber = indexPage.getNextPageNumber();
82      _dataPage.setNextPageNumber(INVALID_INDEX_PAGE_NUMBER);
83      indexPage = null;
84      
85      // read all leaf pages.
86      while(nextPageNumber != INVALID_INDEX_PAGE_NUMBER) {
87          
88        // FIXME we can't modify this index at this point in time
89        setReadOnly();
90          
91        // found another one
92        indexPage = new SimpleDataPage(nextPageNumber);
93        readDataPage(indexPage);
94  
95        // since we read all the entries in sort order, we can insert them
96        // directly into the entries list
97        _dataPage.getEntries().addAll(indexPage.getEntries());
98        int totalSize = (_dataPage.getTotalEntrySize() +
99                         indexPage.getTotalEntrySize());
100       _dataPage.setTotalEntrySize(totalSize);
101       nextPageNumber = indexPage.getNextPageNumber();
102     }
103 
104     // check the entry order, just to be safe
105     List<Entry> entries = _dataPage.getEntries();
106     for(int i = 0; i < (entries.size() - 1); ++i) {
107       Entry e1 = entries.get(i);
108       Entry e2 = entries.get(i + 1);
109       if(e1.compareTo(e2) > 0) {
110         throw new IOException("Unexpected order in index entries, " +
111                               e1 + " is greater than " + e2);
112       }
113     }
114   }
115 
116   @Override
117   protected DataPage findDataPage(Entry entry)
118     throws IOException
119   {
120     return _dataPage;
121   }
122 
123   @Override
124   protected DataPage getDataPage(int pageNumber)
125     throws IOException
126   {
127     throw new UnsupportedOperationException();
128   }
129   
130 
131   /**
132    * Simple implementation of a DataPage
133    */
134   private static final class SimpleDataPage extends DataPage {
135     private final int _pageNumber;
136     private boolean _leaf;
137     private int _nextPageNumber;
138     private int _totalEntrySize;
139     private List<Entry> _entries;
140 
141     private SimpleDataPage(int pageNumber) {
142       _pageNumber = pageNumber;
143     }
144     
145     @Override
146     public int getPageNumber() {
147       return _pageNumber;
148     }
149     
150     @Override
151     public boolean isLeaf() {
152       return _leaf;
153     }
154     @Override
155     public void setLeaf(boolean isLeaf) {
156       _leaf = isLeaf;
157     }
158 
159     @Override
160     public int getPrevPageNumber() { return 0; }
161     @Override
162     public void setPrevPageNumber(int pageNumber) {
163       // ignored
164     }
165     @Override
166     public int getNextPageNumber() {
167       return _nextPageNumber;
168     }
169     @Override
170     public void setNextPageNumber(int pageNumber) {
171       _nextPageNumber = pageNumber;
172     }
173     @Override
174     public int getChildTailPageNumber() { return 0; }
175     @Override
176     public void setChildTailPageNumber(int pageNumber) {
177       // ignored
178     }
179     
180     @Override
181     public int getTotalEntrySize() {
182       return _totalEntrySize;
183     }
184     @Override
185     public void setTotalEntrySize(int totalSize) {
186       _totalEntrySize = totalSize;
187     }
188     @Override
189     public byte[] getEntryPrefix() {
190       return EMPTY_PREFIX;
191     }
192     @Override
193     public void setEntryPrefix(byte[] entryPrefix) {
194       // ignored
195     }
196 
197     @Override
198     public List<Entry> getEntries() {
199       return _entries;
200     }
201     
202     @Override
203     public void setEntries(List<Entry> entries) {
204       
205       _entries = entries;
206     }
207 
208     @Override
209     public void addEntry(int idx, Entry entry) {
210       _entries.add(idx, entry);
211       _totalEntrySize += entry.size();
212     }
213 
214     @Override
215     public void removeEntry(int idx) {
216       Entry oldEntry = _entries.remove(idx);
217       _totalEntrySize -= oldEntry.size();
218     }
219     
220   }
221   
222 }