2 * Copyright (c) 2007, Solido Systems
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
15 * Neither the name of Solido Systems nor the names of its contributors may be
16 * used to endorse or promote products derived from this software without
17 * specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 package com.solidosystems.tuplesoup.core;
37 public class TableIndexPageTransactional{
38 public @atomic interface TableIndexPageTSInf{
44 Integer getStarthash();
47 TableIndexPageTSInf getNextpage();
48 TableIndexPageTSInf getLowerpage();
51 void setLowerpage(TableIndexPageTSInf lowerpage);
52 void setNextpage(TableIndexPageTSInf nextpage);
53 void setFirst(Boolean val);
56 void setOffset(Integer offset);
57 void setNext(Long next);
58 void setSize(Integer size);
59 void setLocation(Long location);
60 void setLower(Long val);
62 private final static int BASEOFFSET=4+8+8+4+4;
63 private RandomAccessFile file=null;
65 private long location=-1;
68 private long lower=-1;
71 private int starthash=-1;
72 private int endhash=-1;
73 private boolean first=false;
75 private TableIndexPage nextpage=null;
76 private TableIndexPage lowerpage=null;
78 private PagedIndex index=null;
80 public TableIndexPageTransactional(PagedIndex index,RandomAccessFile file) throws IOException{
84 location=file.getFilePointer();
87 lower=file.readLong();
88 offset=file.readInt();
89 endhash=file.readInt();
90 if(offset>0)starthash=file.readInt();
93 public static TableIndexPage createNewPage(PagedIndex index,RandomAccessFile file,int size) throws IOException{
94 long pre=file.length();
95 file.setLength(file.length()+size+BASEOFFSET);
103 index.stat_create_page++;
104 return new TableIndexPage(index,file);
107 public void setFirst(){
111 public long getLocation(){
114 public long getEndLocation(){
115 return location+size+BASEOFFSET;
118 public String toString(){
119 StringBuffer buf=new StringBuffer();
121 buf.append(" location "+location+"\n");
122 buf.append(" size "+size+"\n");
123 buf.append(" next "+next+"\n");
124 buf.append(" lower "+lower+"\n");
125 buf.append(" offset "+offset+"\n");
126 buf.append(" starthash "+starthash+"\n");
127 buf.append(" endhash "+endhash+"\n");
129 return buf.toString();
132 private void updateMeta() throws IOException{
135 file.writeLong(next);
136 file.writeLong(lower);
137 file.writeInt(offset);
138 file.writeInt(endhash);
141 public void addEntriesToList(List<TableIndexEntry> lst) throws IOException{
145 lowerpage=new TableIndexPage(index,file);
147 lowerpage.addEntriesToList(lst);
152 nextpage=new TableIndexPage(index,file);
154 nextpage.addEntriesToList(lst);
156 file.seek(location+BASEOFFSET);
157 long pre=file.getFilePointer();
158 while(file.getFilePointer()<pre+offset){
159 TableIndexEntry entry=TableIndexEntry.readData(file);
161 if(entry.getLocation()!=Table.DELETE)lst.add(entry);
166 public TableIndexEntry scanIndex(String id,int hashcode) throws IOException{
168 if(hashcode<starthash){
169 if(lower==-1)return null;
172 lowerpage=new TableIndexPage(index,file);
174 index.stat_page_branch++;
175 return lowerpage.scanIndex(id,hashcode);
178 if(hashcode>endhash){
179 if(next==-1)return null;
182 nextpage=new TableIndexPage(index,file);
184 index.stat_page_next++;
185 return nextpage.scanIndex(id,hashcode);
187 file.seek(location+BASEOFFSET);
188 long pre=file.getFilePointer();
189 while(file.getFilePointer()<pre+offset){
190 TableIndexEntry entry=TableIndexEntry.lookForData(id,file);
191 if(entry!=null)return entry;
193 if(next==-1)return null;
196 nextpage=new TableIndexPage(index,file);
198 index.stat_page_next++;
199 return nextpage.scanIndex(id,hashcode);
201 protected long getOffset(String id,int hashcode) throws IOException{
203 if(hashcode<starthash){
204 if(lower==-1)return -1;
207 lowerpage=new TableIndexPage(index,file);
209 index.stat_page_branch++;
210 return lowerpage.getOffset(id,hashcode);
213 if(hashcode>endhash){
214 if(next==-1)return -1;
217 nextpage=new TableIndexPage(index,file);
219 index.stat_page_next++;
220 return nextpage.getOffset(id,hashcode);
222 file.seek(location+BASEOFFSET);
223 long pre=file.getFilePointer();
224 while(file.getFilePointer()<pre+offset){
225 long prescan=file.getFilePointer();
226 TableIndexEntry entry=TableIndexEntry.lookForData(id,file);
227 if(entry!=null)return prescan;
229 if(next==-1)return -1;
232 nextpage=new TableIndexPage(index,file);
234 index.stat_page_next++;
235 return nextpage.getOffset(id,hashcode);
238 protected TableIndexPage getFirstFreePage(String id,int hashcode) throws IOException{
239 // Is this an empty page?
243 // Is this hash lower than the starthash
245 if(hashcode<starthash){
249 return createNewPage(index,file,PagedIndex.PAGESIZE);
253 lowerpage=new TableIndexPage(index,file);
255 index.stat_page_branch++;
256 return lowerpage.getFirstFreePage(id,hashcode);
259 // Do we have space in this page
260 if(size-offset>id.length()*2+4+4+8+1+2)return this;
265 return createNewPage(index,file,PagedIndex.PAGESIZE);
269 nextpage=new TableIndexPage(index,file);
271 index.stat_page_next++;
272 return nextpage.getFirstFreePage(id,hashcode);
275 public void addEntry(String id,int rowsize,int location,long position) throws IOException{
276 if(offset==0)starthash=id.hashCode();
277 file.seek(this.location+BASEOFFSET+offset);
278 TableIndexEntry entry=new TableIndexEntry(id,rowsize,location,position);
279 entry.writeData(file);
280 offset+=entry.getSize();
281 if(id.hashCode()>endhash)endhash=id.hashCode();