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;
34 import TransactionalIO.core.TransactionalFile;
35 import dstm2.AtomicSuperClass;
38 import dstm2.factory.Factory;
42 public class TableIndexPageTransactional implements AtomicSuperClass{
43 static Factory<TableIndexPageTSInf> factory = Thread.makeFactory(TableIndexPageTSInf.class);
45 /*static*/ TableIndexPageTSInf atomicfields = null;
46 private final static int BASEOFFSET=4+8+8+4+4;
47 //private RandomAccessFile file=null;
48 private TransactionalFile file = null;
51 public @atomic interface TableIndexPageTSInf{
57 Integer getStarthash();
60 TableIndexPageTransactional getNextpage();
61 TableIndexPageTransactional getLowerpage();
62 PagedIndexTransactional getIndex();
65 void setLowerpage(TableIndexPageTransactional lowerpage);
66 void setNextpage(TableIndexPageTransactional nextpage);
67 void setFirst(Boolean val);
68 void setEndhash(Integer val);
69 void setStarthash(Integer val);
70 void setOffset(Integer offset);
71 void setNext(Long next);
72 void setSize(Integer size);
73 void setLocation(Long location);
74 void setLower(Long val);
75 void setIndex(PagedIndexTransactional val);
80 public TableIndexPageTransactional(PagedIndexTransactional index,TransactionalFile file) throws IOException{
82 atomicfields = factory.create();
83 this.atomicfields.setIndex(index);
84 this.atomicfields.setFirst(false);
85 this.atomicfields.setLocation(file.getFilePointer());
86 System.out.println(file.getFilePointer());
87 this.atomicfields.setSize(file.readInt());
88 System.out.println(file.getFilePointer());
89 this.atomicfields.setNext(file.readLong());
90 System.out.println(file.getFilePointer());
91 this.atomicfields.setLower(file.readLong());
92 System.out.println(file.getFilePointer());
93 System.out.println(file.getFilePointer());
94 this.atomicfields.setOffset(file.readInt());
95 System.out.println(file.getFilePointer());
96 this.atomicfields.setEndhash(file.readInt());
97 System.out.println("size " + atomicfields.getSize());
98 System.out.println("next " + atomicfields.getNext());
99 System.out.println("lower " + atomicfields.getLower());
100 System.out.println("offset " + atomicfields.getOffset());
101 System.out.println("endhash " + atomicfields.getEndhash());
102 if(this.atomicfields.getOffset()>0)
103 this.atomicfields.setStarthash(file.readInt());
105 this.atomicfields.setStarthash(-1);
108 public static TableIndexPageTransactional createNewPage(PagedIndexTransactional index,TransactionalFile file,int size) throws IOException{
110 long pre=file.length();
111 System.out.println("pre " + pre);
112 // file.setLength(file.length()+size+BASEOFFSET);
114 byte[] dummy = new byte[size+BASEOFFSET];
116 System.out.println("pointer " + file.getFilePointer());
119 System.out.println("pointer2 " + file.getFilePointer());
122 System.out.println("pointer2 " + file.getFilePointer());
124 System.out.println("pointer2 " + file.getFilePointer());
126 System.out.println("pointer2 " + file.getFilePointer());
128 System.out.println("pointer2 " + file.getFilePointer());
138 //index.atomicfields.setStat_create_page((long)2);
139 index.atomicfields.setStat_create_page(index.atomicfields.getStat_create_page()+1);
140 return new TableIndexPageTransactional(index,file);
143 public void setFirst(){
144 this.atomicfields.setFirst(true);
147 public long getLocation(){
148 return atomicfields.getLocation();
150 public long getEndLocation(){
151 return this.atomicfields.getLocation()+atomicfields.getSize()+BASEOFFSET;
154 public String toString(){
155 StringBuffer buf=new StringBuffer();
157 buf.append(" location "+this.atomicfields.getLocation()+"\n");
158 buf.append(" size "+this.atomicfields.getSize()+"\n");
159 buf.append(" next "+this.atomicfields.getNext()+"\n");
160 buf.append(" lower "+this.atomicfields.getLower()+"\n");
161 buf.append(" offset "+this.atomicfields.getOffset()+"\n");
162 buf.append(" starthash "+this.atomicfields.getStarthash()+"\n");
163 buf.append(" endhash "+this.atomicfields.getEndhash()+"\n");
165 return buf.toString();
168 private void updateMeta() throws IOException{
169 file.seek(this.atomicfields.getLocation());
170 file.writeInt(this.atomicfields.getSize());
171 file.writeLong(this.atomicfields.getNext());
172 file.writeLong(this.atomicfields.getLower());
173 file.writeInt(this.atomicfields.getOffset());
174 file.writeInt(this.atomicfields.getEndhash());
177 public void addEntriesToList(List<TableIndexEntryTransactional> lst) throws IOException{
178 if(this.atomicfields.getLower()>-1){
179 if(this.atomicfields.getLowerpage()==null){
180 file.seek(this.atomicfields.getLower());
181 this.atomicfields.setLowerpage(new TableIndexPageTransactional(this.atomicfields.getIndex(),file));
183 this.atomicfields.getLowerpage().addEntriesToList(lst);
185 if(this.atomicfields.getNext()>-1){
186 if(this.atomicfields.getNextpage()==null){
187 file.seek(this.atomicfields.getNext());
188 this.atomicfields.setNextpage(new TableIndexPageTransactional(this.atomicfields.getIndex(),file));
190 this.atomicfields.getNextpage().addEntriesToList(lst);
192 file.seek(this.atomicfields.getLocation()+BASEOFFSET);
193 long pre=file.getFilePointer();
194 while(file.getFilePointer()<pre+this.atomicfields.getOffset()){
195 TableIndexEntryTransactional entry=TableIndexEntryTransactional.readData(file);
197 if(entry.getLocation()!=Table.DELETE)lst.add(entry);
202 public TableIndexEntryTransactional scanIndex(String id,int hashcode) throws IOException{
203 if(!atomicfields.getFirst()){
204 if(hashcode<atomicfields.getStarthash()){
205 if(atomicfields.getLower()==-1) return null;
206 if(this.atomicfields.getLowerpage()==null){
207 file.seek(this.atomicfields.getLower());
208 this.atomicfields.setLowerpage(new TableIndexPageTransactional(this.atomicfields.getIndex(),file));
210 atomicfields.getIndex().atomicfields.setStat_page_branch(atomicfields.getIndex().atomicfields.getStat_page_branch()+1);
211 return this.atomicfields.getLowerpage().scanIndex(id,hashcode);
214 if(hashcode>this.atomicfields.getEndhash()){
215 if(this.atomicfields.getNext()==-1)return null;
216 if(this.atomicfields.getNextpage()==null){
217 file.seek(this.atomicfields.getNext());
218 this.atomicfields.setNextpage(new TableIndexPageTransactional(this.atomicfields.getIndex(),file));
220 atomicfields.getIndex().atomicfields.setStat_page_next(atomicfields.getIndex().atomicfields.getStat_page_next()+1);
221 return this.atomicfields.getNextpage().scanIndex(id,hashcode);
223 file.seek(this.atomicfields.getLocation()+BASEOFFSET);
224 long pre=file.getFilePointer();
225 while(file.getFilePointer()<pre+this.atomicfields.getOffset()){
226 System.out.println("neddddxtex " + atomicfields.getNext());
227 TableIndexEntryTransactional entry=TableIndexEntryTransactional.lookForData(id,file);
228 if(entry!=null)return entry;
230 if(this.atomicfields.getNext()==-1)return null;
231 if(this.atomicfields.getNextpage()==null){
232 file.seek(this.atomicfields.getNext());
233 this.atomicfields.setNextpage(new TableIndexPageTransactional(this.atomicfields.getIndex(),file));
235 atomicfields.getIndex().atomicfields.setStat_page_next(atomicfields.getIndex().atomicfields.getStat_page_next()+1);
236 return this.atomicfields.getNextpage().scanIndex(id,hashcode);
238 protected long getOffset(String id,int hashcode) throws IOException{
239 if(!this.atomicfields.getFirst()){
240 if(hashcode<this.atomicfields.getStarthash()){
241 if(this.atomicfields.getLower()==-1)return -1;
242 if(this.atomicfields.getLowerpage()==null){
243 file.seek(atomicfields.getLower());
244 this.atomicfields.setLowerpage(new TableIndexPageTransactional(this.atomicfields.getIndex(),file));
246 atomicfields.getIndex().atomicfields.setStat_page_branch(atomicfields.getIndex().atomicfields.getStat_page_branch()+1);
247 return this.atomicfields.getLowerpage().getOffset(id,hashcode);
250 if(hashcode>this.atomicfields.getEndhash()){
251 if(this.atomicfields.getNext()==-1)return -1;
252 if(this.atomicfields.getNextpage()==null){
253 file.seek(this.atomicfields.getNext());
254 this.atomicfields.setNextpage(new TableIndexPageTransactional(this.atomicfields.getIndex(),file));
256 atomicfields.getIndex().atomicfields.setStat_page_next(atomicfields.getIndex().atomicfields.getStat_page_next()+1);
257 return this.atomicfields.getNextpage().getOffset(id,hashcode);
259 file.seek(this.atomicfields.getLocation()+BASEOFFSET);
260 long pre=file.getFilePointer();
261 while(file.getFilePointer()<pre+this.atomicfields.getOffset()){
262 long prescan=file.getFilePointer();
263 TableIndexEntryTransactional entry=TableIndexEntryTransactional.lookForData(id,file);
264 if(entry!=null)return prescan;
266 if(this.atomicfields.getNext()==-1)return -1;
267 if(this.atomicfields.getNextpage()==null){
268 file.seek(this.atomicfields.getNext());
269 this.atomicfields.setNextpage(new TableIndexPageTransactional(this.atomicfields.getIndex(),file));
271 atomicfields.getIndex().atomicfields.setStat_page_next(atomicfields.getIndex().atomicfields.getStat_page_next()+1);
272 return this.atomicfields.getNextpage().getOffset(id,hashcode);
275 protected TableIndexPageTransactional getFirstFreePage(String id,int hashcode) throws IOException{
276 // Is this an empty page?
277 if(this.atomicfields.getOffset()==0){
280 // Is this hash lower than the starthash
281 if(!this.atomicfields.getFirst()){
282 if(hashcode<this.atomicfields.getStarthash()){
283 if(this.atomicfields.getLower()==-1){
284 this.atomicfields.setLower(file.length());
286 return createNewPage(this.atomicfields.getIndex(),file,PagedIndexTransactional.PAGESIZE);
288 if(this.atomicfields.getLowerpage()==null){
289 file.seek(this.atomicfields.getLower());
290 this.atomicfields.setLowerpage(new TableIndexPageTransactional(this.atomicfields.getIndex(),file));
292 atomicfields.getIndex().atomicfields.setStat_page_branch(atomicfields.getIndex().atomicfields.getStat_page_branch()+1);
293 return this.atomicfields.getLowerpage().getFirstFreePage(id,hashcode);
296 // Do we have space in this page
297 if(this.atomicfields.getSize()-this.atomicfields.getOffset()>id.length()*2+4+4+8+1+2)return this;
299 if(this.atomicfields.getNext()==-1){
300 this.atomicfields.setNext(file.length());
302 return createNewPage(this.atomicfields.getIndex(),file,PagedIndexTransactional.PAGESIZE);
304 if(this.atomicfields.getNextpage()==null){
305 file.seek(this.atomicfields.getNext());
306 this.atomicfields.setNextpage(new TableIndexPageTransactional(this.atomicfields.getIndex(),file));
308 atomicfields.getIndex().atomicfields.setStat_page_next(atomicfields.getIndex().atomicfields.getStat_page_next()+1);
309 return this.atomicfields.getNextpage().getFirstFreePage(id,hashcode);
312 public void addEntry(String id,int rowsize,int location,long position) throws IOException{
313 if(atomicfields.getOffset()==0)this.atomicfields.setStarthash(id.hashCode());
314 file.seek(this.atomicfields.getLocation()+BASEOFFSET+this.atomicfields.getOffset());
315 TableIndexEntryTransactional entry=new TableIndexEntryTransactional(id,rowsize,location,position);
316 entry.writeData(file);
317 this.atomicfields.setOffset(this.atomicfields.getOffset()+entry.getSize());
318 if(id.hashCode()>this.atomicfields.getEndhash()) this.atomicfields.setEndhash(id.hashCode());