e2bebd1b70c07cee973822ab426e010700694e53
[IRC.git] /
1 /*
2  * Copyright (c) 2007, Solido Systems
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * Redistributions of source code must retain the above copyright notice, this
9  * list of conditions and the following disclaimer.
10  *
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.
14  *
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.
18  *
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.
30  */
31  
32 package com.solidosystems.tuplesoup.core;
33
34 import TransactionalIO.core.TransactionalFile;
35 import dstm2.AtomicSuperClass;
36 import dstm2.atomic;
37 import dstm2.Thread;
38 import dstm2.factory.Factory;
39 import java.io.*;
40 import java.util.*;
41
42 public class TableIndexPageTransactional implements AtomicSuperClass{
43     static Factory<TableIndexPageTSInf> factory = Thread.makeFactory(TableIndexPageTSInf.class);
44     
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;
49     
50     
51     public @atomic interface TableIndexPageTSInf{
52         Long getLocation();
53         Integer getSize();
54         Long getNext();
55         Long getLower();
56         Integer getOffset();
57         Integer getStarthash();
58         Integer getEndhash();
59         Boolean getFirst();
60         TableIndexPageTransactional getNextpage();
61         TableIndexPageTransactional getLowerpage();
62         PagedIndexTransactional getIndex(); 
63         
64      
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);
76     }
77   
78     
79     
80     public TableIndexPageTransactional(PagedIndexTransactional index,TransactionalFile file) throws IOException{
81         this.file=file;
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());
104         else 
105             this.atomicfields.setStarthash(-1);
106     }
107     
108     public static TableIndexPageTransactional createNewPage(PagedIndexTransactional index,TransactionalFile file,int size) throws IOException{
109     
110         long pre=file.length();
111         System.out.println("pre " + pre);
112 //        file.setLength(file.length()+size+BASEOFFSET);
113         file.seek(pre);
114         byte[] dummy = new byte[size+BASEOFFSET];
115         file.write(dummy);
116         System.out.println("pointer " + file.getFilePointer());
117         
118         file.seek(pre);
119         System.out.println("pointer2 " + file.getFilePointer());
120         file.writeInt(size);
121  
122          System.out.println("pointer2 " + file.getFilePointer());
123         file.writeLong(-1l);
124          System.out.println("pointer2 " + file.getFilePointer());
125         file.writeLong(-1l);
126          System.out.println("pointer2 " + file.getFilePointer());
127         file.writeInt(0);
128          System.out.println("pointer2 " + file.getFilePointer());
129         file.writeInt(-1);
130         file.seek(pre);
131         file.readInt();
132         file.readLong();
133         file.readLong();
134         file.readInt();
135         file.readInt();
136         file.seek(pre);
137         
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);
141     }
142     
143     public void setFirst(){
144         this.atomicfields.setFirst(true);
145     }
146     
147     public long getLocation(){
148         return atomicfields.getLocation();
149     }
150     public long getEndLocation(){
151         return this.atomicfields.getLocation()+atomicfields.getSize()+BASEOFFSET;
152     }
153     
154     public String toString(){
155         StringBuffer buf=new StringBuffer();
156         buf.append("{\n");
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");
164         buf.append("}\n");
165         return buf.toString();
166     }
167     
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());
175     }
176     
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));
182             }
183             this.atomicfields.getLowerpage().addEntriesToList(lst);
184         }
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));
189             }
190             this.atomicfields.getNextpage().addEntriesToList(lst);
191         }
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);
196             if(entry!=null){
197                 if(entry.getLocation()!=Table.DELETE)lst.add(entry);
198             }
199         }
200     }
201     
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));
209                 }
210                 atomicfields.getIndex().atomicfields.setStat_page_branch(atomicfields.getIndex().atomicfields.getStat_page_branch()+1);
211                 return this.atomicfields.getLowerpage().scanIndex(id,hashcode);
212             }
213         }
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));
219             }
220             atomicfields.getIndex().atomicfields.setStat_page_next(atomicfields.getIndex().atomicfields.getStat_page_next()+1);
221             return this.atomicfields.getNextpage().scanIndex(id,hashcode);
222         }
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;
229         }
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));
234         }
235         atomicfields.getIndex().atomicfields.setStat_page_next(atomicfields.getIndex().atomicfields.getStat_page_next()+1);
236         return this.atomicfields.getNextpage().scanIndex(id,hashcode);
237     }
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));
245                 }
246                 atomicfields.getIndex().atomicfields.setStat_page_branch(atomicfields.getIndex().atomicfields.getStat_page_branch()+1);
247                 return this.atomicfields.getLowerpage().getOffset(id,hashcode);
248             }
249         }
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));
255             }
256             atomicfields.getIndex().atomicfields.setStat_page_next(atomicfields.getIndex().atomicfields.getStat_page_next()+1);
257             return this.atomicfields.getNextpage().getOffset(id,hashcode);
258         }
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;
265         }
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));
270         }
271         atomicfields.getIndex().atomicfields.setStat_page_next(atomicfields.getIndex().atomicfields.getStat_page_next()+1);
272         return this.atomicfields.getNextpage().getOffset(id,hashcode);
273     }
274     
275     protected TableIndexPageTransactional getFirstFreePage(String id,int hashcode) throws IOException{
276         // Is this an empty page?
277         if(this.atomicfields.getOffset()==0){
278             return this;
279         }
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());
285                     updateMeta();
286                     return createNewPage(this.atomicfields.getIndex(),file,PagedIndexTransactional.PAGESIZE);
287                 }
288                 if(this.atomicfields.getLowerpage()==null){
289                     file.seek(this.atomicfields.getLower());
290                     this.atomicfields.setLowerpage(new TableIndexPageTransactional(this.atomicfields.getIndex(),file));
291                 }
292                 atomicfields.getIndex().atomicfields.setStat_page_branch(atomicfields.getIndex().atomicfields.getStat_page_branch()+1);
293                 return this.atomicfields.getLowerpage().getFirstFreePage(id,hashcode);
294             }
295         }
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;
298         // Check next
299         if(this.atomicfields.getNext()==-1){
300             this.atomicfields.setNext(file.length());
301             updateMeta();
302             return createNewPage(this.atomicfields.getIndex(),file,PagedIndexTransactional.PAGESIZE);
303         }
304         if(this.atomicfields.getNextpage()==null){
305             file.seek(this.atomicfields.getNext());
306             this.atomicfields.setNextpage(new TableIndexPageTransactional(this.atomicfields.getIndex(),file));
307         }
308         atomicfields.getIndex().atomicfields.setStat_page_next(atomicfields.getIndex().atomicfields.getStat_page_next()+1);
309         return this.atomicfields.getNextpage().getFirstFreePage(id,hashcode);
310     }
311     
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());
319         updateMeta();
320     }
321 }