*** empty log message ***
authornavid <navid>
Tue, 27 Jan 2009 06:22:42 +0000 (06:22 +0000)
committernavid <navid>
Tue, 27 Jan 2009 06:22:42 +0000 (06:22 +0000)
46 files changed:
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/DualFileTable.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/DualFileTableTransactional.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/HashedTable.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/HashedTableTransactional.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/IndexedTableReader.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/IndexedTableReaderTransactional.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/PagedIndex.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/PagedIndexTransactional.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/Row.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/RowMatcher.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/RowMatcherTransactional.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/RowTransactional.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/Table.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TableIndex.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TableIndexEntry.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TableIndexEntryTransactional.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TableIndexNode.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TableIndexNodeTransactional.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TableIndexPage.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TableIndexPageTransactional.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TableIndexTransactional.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TableTransactional.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TupleStream.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TupleStreamMerger.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TupleStreamMergerTransactional.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TupleStreamTransactional.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/Value.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/ValueTransactional.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/Conditional.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/HeapSort.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/JavaSort.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/Join.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/MergeSort.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/MergeSort2.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/QuickSort.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/RadixSort.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/RowBuffer.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/RowBufferTransactional.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/Sort.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/SortComparator.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/SortRule.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/test/BasicTest.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/test/OrigParralelPerformanceTest.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/test/OrigParralelThread.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/test/ParallelPerformanceTest.java [new file with mode: 0644]
Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/test/ParallelThread.java [new file with mode: 0644]

diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/DualFileTable.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/DualFileTable.java
new file mode 100644 (file)
index 0000000..cbc26ac
--- /dev/null
@@ -0,0 +1,590 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.solidosystems.tuplesoup.core;
+import java.io.*;
+import java.util.*;
+import java.nio.channels.*;
+import com.solidosystems.tuplesoup.filter.*;
+
+/**
+ * The table stores a group of rows.
+ * Every row must have a unique id within a table.
+ */
+public class DualFileTable implements Table{
+
+    
+    private int INDEXCACHESIZE=8192;
+     
+    private String filealock="filea-dummy";
+    private String fileblock="fileb-dummy";
+
+    private DataOutputStream fileastream=null;
+    private DataOutputStream filebstream=null;
+    private RandomAccessFile filearandom=null;
+    private RandomAccessFile filebrandom=null;
+    FileChannel fca=null;
+    FileChannel fcb=null;
+    private TableIndex index=null;
+     
+    private long fileaposition=0;
+    private long filebposition=0;
+     
+    private boolean rowswitch=true;
+     
+    private String title;
+    private String location;
+     
+    private TableIndexNode indexcachefirst;
+    private TableIndexNode indexcachelast;
+    private int indexcacheusage;
+    private Hashtable<String,TableIndexNode> indexcache;
+    
+    // Statistic counters
+    long stat_add=0;
+    long stat_update=0;
+    long stat_delete=0;
+    long stat_add_size=0;
+    long stat_update_size=0;
+    long stat_read_size=0;
+    long stat_read=0;
+    long stat_cache_hit=0;
+    long stat_cache_miss=0;
+    long stat_cache_drop=0;
+    
+    protected String statlock="stat-dummy";
+    
+    /**
+     * Return the current values of the statistic counters and reset them.
+     * The current counters are:
+     * <ul>
+     *   <li>stat_table_add
+     *   <li>stat_table_update
+     *   <li>stat_table_delete
+     *   <li>stat_table_add_size
+     *   <li>stat_table_update_size
+     *   <li>stat_table_read_size
+     *   <li>stat_table_read
+     *   <li>stat_table_cache_hit
+     *   <li>stat_table_cache_miss
+     *   <li>stat_table_cache_drop
+     * </ul>
+     * Furthermore, the index will be asked to deliver separate index specific counters
+     */
+    public Hashtable<String,Long> readStatistics(){
+        Hashtable<String,Long> hash=new Hashtable<String,Long>();
+        synchronized(statlock){
+            hash.put("stat_table_add",stat_add);
+            hash.put("stat_table_update",stat_update);
+            hash.put("stat_table_delete",stat_delete);
+            hash.put("stat_table_add_size",stat_add_size);
+            hash.put("stat_table_update_size",stat_update_size);
+            hash.put("stat_table_read_size",stat_read_size);
+            hash.put("stat_table_read",stat_read);
+            hash.put("stat_table_cache_hit",stat_cache_hit);
+            hash.put("stat_table_cache_miss",stat_cache_miss);
+            hash.put("stat_table_cache_drop",stat_cache_drop);
+            stat_add=0;
+            stat_update=0;
+            stat_delete=0;
+            stat_add_size=0;
+            stat_update_size=0;
+            stat_read_size=0;
+            stat_read=0;
+            stat_cache_hit=0;
+            stat_cache_miss=0;
+            stat_cache_drop=0;
+            Hashtable<String,Long> ihash=index.readStatistics();
+            hash.putAll(ihash);
+        }
+        return hash;
+    }
+    
+    /**
+     * Create a new table object with the default flat index model
+     */
+
+    
+    /**
+     * Create a new table object with a specific index model
+     */
+    public DualFileTable(String title,String location, int indextype) throws IOException{
+        this.title=title;
+        this.location=location;
+        if(!this.location.endsWith(File.separator))this.location+=File.separator;
+        switch(indextype){
+             case PAGED  : index=new PagedIndex(getFileName(INDEX));
+                
+                break;
+           
+        }
+        indexcachefirst=null;
+        indexcachelast=null;
+        indexcacheusage=0;
+        indexcache=new Hashtable<String,TableIndexNode>();
+    }
+     
+    /**
+     * Set the maximal allowable size of the index cache.
+     */ 
+    public void setIndexCacheSize(int newsize){
+        INDEXCACHESIZE=newsize;
+    }
+    
+    /**
+     * Close all open file streams
+     */
+    public void close(){
+        try{
+            if(fileastream!=null)fileastream.close();
+            if(filebstream!=null)filebstream.close();
+            if(filearandom!=null)filearandom.close();
+            if(filebrandom!=null)filebrandom.close();
+            index.close();
+        }catch(Exception e){}
+    }
+    
+    /** 
+     * Returns the name of this table
+     */ 
+    public String getTitle(){
+         return title;
+    }
+    
+    /**
+     * Returns the location of this tables datafiles
+     */ 
+    public String getLocation(){
+         return location;
+    }
+     
+    protected String getFileName(int type){
+         switch(type){
+             case FILEB  :   return location+title+".a";
+             case FILEA  :   return location+title+".b";
+             case INDEX  :   return location+title+".index";
+         }
+         return null;
+    }
+    
+    /**
+     * Delete the files created by this table object.
+     * Be aware that this will delete any data stored in this table!
+     */ 
+    public void deleteFiles(){
+         try{
+             File ftest=new File(getFileName(FILEA));
+             ftest.delete();
+         }catch(Exception e){}
+         try{
+             File ftest=new File(getFileName(FILEB));
+             ftest.delete();
+         }catch(Exception e){}
+         try{
+             File ftest=new File(getFileName(INDEX));
+             ftest.delete();
+         }catch(Exception e){}
+    }
+     
+     private synchronized void openFile(int type) throws IOException{
+         switch(type){
+             case FILEA  : if(fileastream==null){
+                                System.out.println("file a " + getFileName(FILEA));
+                                fileastream=new DataOutputStream(new BufferedOutputStream(new FileOutputStream(getFileName(FILEA),true)));
+                                File ftest=new File(getFileName(FILEA));
+                                fileaposition=ftest.length();
+                           }
+                          break;
+             case FILEB  : if(filebstream==null){
+                 System.out.println("file b " + getFileName(FILEB));
+                                filebstream=new DataOutputStream(new BufferedOutputStream(new FileOutputStream(getFileName(FILEB),true)));
+                                File ftest=new File(getFileName(FILEB));
+                                filebposition=ftest.length();
+                           }
+                          break;
+         }
+     }
+     
+    /**
+     * Adds a row of data to this table.
+     */
+    public void addRow(Row row) throws IOException{
+        // Distribute new rows between the two datafiles by using the rowswitch, but don't spend time synchronizing... this does not need to be acurate!
+        if(rowswitch){
+            addRowA(row);
+        }else{
+            addRowB(row);
+        }
+        rowswitch=!rowswitch;
+    }
+     
+     private void addCacheEntry(TableIndexEntry entry){
+         synchronized(indexcache){
+             if(indexcacheusage>INDEXCACHESIZE){
+                 // remove first entry
+                 TableIndexNode node=indexcachefirst;
+                 indexcache.remove(node.getData().getId());
+                 indexcacheusage--;
+                 synchronized(statlock){
+                     stat_cache_drop++;
+                 }
+                 indexcachefirst=node.getNext();
+                 if(indexcachefirst==null){
+                    indexcachelast=null;
+                 }else{
+                    indexcachefirst.setPrevious(null);
+                 }
+             }
+             TableIndexNode node=new TableIndexNode(indexcachelast,entry);
+             if(indexcachelast!=null){
+                 indexcachelast.setNext(node);
+             }
+             if(indexcachefirst==null){
+                 indexcachefirst=node;
+             }
+             indexcachelast=node;
+             indexcache.put(entry.getId(),node);
+             indexcacheusage++;
+        }
+     }
+     
+     private void addRowA(Row row) throws IOException{
+         synchronized(filealock){
+             openFile(FILEA);
+             int pre=fileastream.size();
+             row.writeToStream(fileastream);
+             int post=fileastream.size();
+             fileastream.flush();
+             synchronized(statlock){
+                  stat_add++;
+                  stat_add_size+=row.getSize();
+              }
+             index.addEntry(row.getId(),row.getSize(),FILEA,fileaposition);
+             if(INDEXCACHESIZE>0){
+                 TableIndexEntry entry=new TableIndexEntry(row.getId(),row.getSize(),FILEA,fileaposition);
+                 addCacheEntry(entry);
+             }
+             fileaposition+=Row.calcSize(pre,post);
+         }
+     }
+     private void addRowB(Row row) throws IOException{
+         synchronized(fileblock){
+             openFile(FILEB);
+             int pre=filebstream.size();
+             row.writeToStream(filebstream);
+             int post=filebstream.size();
+             filebstream.flush();
+             synchronized(statlock){
+                  stat_add++;
+                  stat_add_size+=row.getSize();
+              }
+             index.addEntry(row.getId(),row.getSize(),FILEB,filebposition);
+             if(INDEXCACHESIZE>0){
+                 TableIndexEntry entry=new TableIndexEntry(row.getId(),row.getSize(),FILEB,filebposition);
+                 addCacheEntry(entry);
+             }
+             filebposition+=Row.calcSize(pre,post);
+         }
+     }
+     
+
+     private void updateCacheEntry(TableIndexEntry entry){
+          synchronized(indexcache){
+              if(indexcache.containsKey(entry.getId())){
+                  TableIndexNode node=indexcache.get(entry.getId());
+                  node.setData(entry);
+                  if(node!=indexcachelast){
+                      if(node==indexcachefirst){
+                          indexcachefirst=node.getNext();
+                      }
+                      node.remove();
+                      indexcachelast.setNext(node);
+                      node.setPrevious(indexcachelast);
+                      node.setNext(null);
+                      indexcachelast=node;
+                  }
+              }else{
+                  addCacheEntry(entry);
+              }
+         }
+      }
+
+      private void removeCacheEntry(String id){
+          synchronized(indexcache){
+                if(indexcache.containsKey(id)){
+                    TableIndexNode node=indexcache.get(id);
+                    indexcache.remove(id);
+                    if(indexcacheusage==1){
+                        indexcachefirst=null;
+                        indexcachelast=null;
+                        indexcacheusage=0;
+                        return;
+                    }
+                    if(node==indexcachefirst){
+                        indexcachefirst=node.getNext();
+                        indexcachefirst.setPrevious(null);
+                    }else if(node==indexcachelast){
+                        indexcachelast=node.getPrevious();
+                        indexcachelast.setNext(null);
+                    }else{
+                        node.remove();
+                    }
+                    indexcacheusage--;
+                    synchronized(statlock){
+                         stat_cache_drop++;
+                    }
+                }
+          }
+      }
+
+      private TableIndexEntry getCacheEntry(String id){
+          synchronized(indexcache){
+              if(indexcache.containsKey(id)){
+                  TableIndexNode node=indexcache.get(id);
+                  if(node!=indexcachelast){
+                      if(node==indexcachefirst){
+                            indexcachefirst=node.getNext();
+                        }
+                        node.remove();
+                        indexcachelast.setNext(node);
+                        node.setPrevious(indexcachelast);
+                        node.setNext(null);
+                        indexcachelast=node;
+                  }
+                  synchronized(statlock){
+                       stat_cache_hit++;
+                   }
+                  return node.getData();
+              }
+          }
+          synchronized(statlock){
+               stat_cache_miss++;
+           }
+          return null;
+      }
+
+     /**
+      * Adds a row to this table if it doesn't already exist, if it does it updates the row instead.
+      * This method is much slower than directly using add or update, so only use it if you don't know wether or not the row already exists.
+      */
+     public void addOrUpdateRow(Row row) throws IOException{
+         Row tmprow=getRow(row.getId());
+         if(tmprow==null){
+             addRow(row);
+         }else{
+             updateRow(row);
+         }
+     }
+
+     /**
+      * Updates a row stored in this table.
+      */
+     public void updateRow(Row row) throws IOException{
+         TableIndexEntry entry=null;
+         // Handle index entry caching
+         if(INDEXCACHESIZE>0){
+             synchronized(indexcache){
+                 entry=getCacheEntry(row.getId());
+                 if(entry==null){
+                     entry=index.scanIndex(row.getId());
+                     addCacheEntry(entry);
+                 }
+             }
+         }else{
+             entry=index.scanIndex(row.getId());
+         }
+         if(entry.getRowSize()>=row.getSize()){
+            // Add to the existing location
+            switch(entry.getLocation()){
+                case FILEA  :synchronized(filealock){
+                                if(filearandom==null){
+                                    filearandom=new RandomAccessFile(getFileName(FILEA),"rw");
+                                    fca=filearandom.getChannel();
+                                }
+                                filearandom.seek(entry.getPosition());
+                                row.writeToFile(filearandom);
+                                
+                                fca.force(false);
+                            }
+                            break;
+                case FILEB :synchronized(fileblock){
+                                if(filebrandom==null){
+                                    filebrandom=new RandomAccessFile(getFileName(FILEB),"rw");
+                                    fcb=filebrandom.getChannel();
+                                }
+                                filebrandom.seek(entry.getPosition());
+                                row.writeToFile(filebrandom);
+                                
+                                fcb.force(false);
+                            }
+                    break;
+            }
+         }else{
+             if(rowswitch){
+                  updateRowA(row);
+              }else{
+                  updateRowB(row);
+              }
+              rowswitch=!rowswitch;
+         }
+         synchronized(statlock){
+              stat_update++;
+              stat_update_size+=row.getSize();
+         }
+     }
+     
+     private void updateRowA(Row row) throws IOException{
+         synchronized(filealock){
+              openFile(FILEA);
+              int pre=fileastream.size();
+              row.writeToStream(fileastream);
+              int post=fileastream.size();
+              fileastream.flush();
+              index.updateEntry(row.getId(),row.getSize(),FILEA,fileaposition);
+              
+              // Handle index entry caching
+              if(INDEXCACHESIZE>0){
+                  updateCacheEntry(new TableIndexEntry(row.getId(),row.getSize(),FILEA,fileaposition));
+              }
+              fileaposition+=Row.calcSize(pre,post);
+          }
+     }
+
+     private void updateRowB(Row row) throws IOException{
+         synchronized(fileblock){
+              openFile(FILEB);
+              int pre=filebstream.size();
+              row.writeToStream(filebstream);
+              int post=filebstream.size();
+              filebstream.flush();
+              index.updateEntry(row.getId(),row.getSize(),FILEB,filebposition);
+              // Handle index entry caching
+              // Handle index entry caching
+                if(INDEXCACHESIZE>0){
+                    updateCacheEntry(new TableIndexEntry(row.getId(),row.getSize(),FILEB,filebposition));
+                }
+                filebposition+=Row.calcSize(pre,post);
+          }
+     }
+
+     /**
+      * Marks a row as deleted in the index.
+      * Be aware that the space consumed by the row is not actually reclaimed.
+      */
+     public void deleteRow(Row row) throws IOException{
+          // Handle index entry caching
+          if(INDEXCACHESIZE>0){
+              removeCacheEntry(row.getId());
+          }
+          index.updateEntry(row.getId(),row.getSize(),DELETE,0);
+          synchronized(statlock){
+               stat_delete++;
+          }
+     }
+     
+     /**
+      * Returns a tuplestream containing the given list of rows
+      */
+     public TupleStream getRows(List<String> rows) throws IOException{
+         return new IndexedTableReader(this,index.scanIndex(rows));
+     }
+
+     /**
+      * Returns a tuplestream containing the rows matching the given rowmatcher
+      */
+     public TupleStream getRows(RowMatcher matcher) throws IOException{
+         return new IndexedTableReader(this,index.scanIndex(),matcher);
+     }
+     
+     /**
+      * Returns a tuplestream containing those rows in the given list that matches the given RowMatcher
+      */
+     public TupleStream getRows(List<String> rows,RowMatcher matcher) throws IOException{
+          return new IndexedTableReader(this,index.scanIndex(rows),matcher);
+      }
+
+     /**
+      * Returns a tuplestream of all rows in this table.
+      */
+     public TupleStream getRows() throws IOException{
+         // return new TableReader(this);
+         return new IndexedTableReader(this,index.scanIndex());
+     }
+     
+     /**
+      * Returns a single row stored in this table.
+      * If the row does not exist in the table, null will be returned.
+      */
+     public Row getRow(String id) throws IOException{
+         TableIndexEntry entry=null;
+          // Handle index entry caching
+          if(INDEXCACHESIZE>0){
+            //  System.out.println("in h");
+              synchronized(indexcache){
+                  entry=getCacheEntry(id);
+               //   System.out.println(entry);
+                   if(entry==null){
+                       entry=index.scanIndex(id);
+                       if(entry!=null){
+                           addCacheEntry(entry);
+                       }
+                   }
+              }
+          }else{
+              entry=index.scanIndex(id);
+          }
+          if(entry!=null){
+              long dataoffset=0;
+              DataInputStream data=null;
+            //  System.out.println(entry);
+              if(entry.location==Table.FILEA){
+                  data=new DataInputStream(new BufferedInputStream(new FileInputStream(getFileName(Table.FILEA))));
+              }else if(entry.location==Table.FILEB){
+                  data=new DataInputStream(new BufferedInputStream(new FileInputStream(getFileName(Table.FILEB))));
+              }
+              if(data!=null){
+                  while(dataoffset!=entry.position){
+                      dataoffset+=data.skipBytes((int)(entry.position-dataoffset));
+                  }
+                  Row row=Row.readFromStream(data);
+                  data.close();
+                  synchronized(statlock){
+                       stat_read++;
+                       stat_read_size+=row.getSize();
+                  }
+                  return row;
+              }
+              
+          }
+          return null;
+     }
+ }
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/DualFileTableTransactional.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/DualFileTableTransactional.java
new file mode 100644 (file)
index 0000000..228c5bb
--- /dev/null
@@ -0,0 +1,777 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.solidosystems.tuplesoup.core;
+
+
+import java.io.*;
+import java.util.*;
+import java.nio.channels.*;
+import com.solidosystems.tuplesoup.filter.*;
+import dstm2.atomic;
+import dstm2.Thread;
+import dstm2.factory.Factory;
+import dstm2.util.StringKeyHashMap;
+import java.util.concurrent.Callable;
+
+/**
+ * The table stores a group of rows.
+ * Every row must have a unique id within a table.
+ */
+public class DualFileTableTransactional implements TableTransactional{
+
+    
+    private int INDEXCACHESIZE=8192;
+     
+    private String filealock="filea-dummy";
+    private String fileblock="fileb-dummy";
+
+    private DataOutputStream fileastream=null;
+    private DataOutputStream filebstream=null;
+    private RandomAccessFile filearandom=null;
+    private RandomAccessFile filebrandom=null;
+    FileChannel fca=null;
+    FileChannel fcb=null;
+    
+    private TableIndexTransactional index=null;
+     
+//    private long fileaposition=0;
+ //   private long filebposition=0;
+     
+    private boolean rowswitch=true;
+     
+    private String title;
+    private String location;
+     
+    private TableIndexNodeTransactional indexcachefirst;
+    private TableIndexNodeTransactional indexcachelast;
+    //private int indexcacheusage;
+    
+    private StringKeyHashMap<TableIndexNodeTransactional> indexcache;
+    //private Hashtable<String,TableIndexNode> indexcache;
+    
+    static Factory<DualFileTableTSInf> factory = Thread.makeFactory(DualFileTableTSInf.class);
+    // static Factory<FinancialTransactionDS> factory = Thread.makeFactory(FinancialTransactionDS.class);
+    DualFileTableTSInf atomicfields;
+    // Statistic counters
+
+    public @atomic interface DualFileTableTSInf{
+        Long getstat_add();
+        Long getstat_update();
+        Long getstat_delete();
+        Long getstat_add_size();
+        Long getstat_update_size();
+        Long getstat_read_size();
+        Long getstat_read();
+        Long getstat_cache_hit();
+        Long getstat_cache_miss();
+        Long getstat_cache_drop();
+        Long getFileaposition();
+        Long getFilebposition();
+        Integer getIndexcacheusage();
+        
+        void setstat_add(Long val);
+        void setstat_update(Long val);
+        void setstat_delete(Long val);
+        void setstat_add_size(Long val);
+        void setstat_update_size(Long val);
+        void setstat_read_size(Long val);
+        void setstat_read(Long val);
+        void setstat_cache_hit(Long val);
+        void setstat_cache_miss(Long val);
+        void setstat_cache_drop(Long val);
+        void setIndexcacheusage(Integer val);
+        void setFileaposition(Long val);
+        void setFilebposition(Long val);
+    }
+  
+    /*long stat_add=0;
+    long stat_update=0;
+    long stat_delete=0;
+    long stat_add_size=0;
+    long stat_update_size=0;
+    long stat_read_size=0;
+    long stat_read=0;
+    long stat_cache_hit=0;
+    long stat_cache_miss=0;
+    long stat_cache_drop=0;*/
+    
+    protected String statlock="stat-dummy";
+    
+    /**
+     * Return the current values of the statistic counters and reset them.
+     * The current counters are:
+     * <ul>
+     *   <li>stat_table_add
+     *   <li>stat_table_update
+     *   <li>stat_table_delete
+     *   <li>stat_table_add_size
+     *   <li>stat_table_update_size
+     *   <li>stat_table_read_size
+     *   <li>stat_table_read
+     *   <li>stat_table_cache_hit
+     *   <li>stat_table_cache_miss
+     *   <li>stat_table_cache_drop
+     * </ul>
+     * Furthermore, the index will be asked to deliver separate index specific counters
+     */
+    public Hashtable<String,Long> readStatistics(){
+        
+    //    synchronized(statlock){
+        return Thread.doIt(new Callable<Hashtable<String,Long>>() {
+            public Hashtable<String,Long> call() throws Exception{
+                Hashtable<String,Long> hash=new Hashtable<String,Long>();
+                hash.put("stat_table_add",atomicfields.getstat_add());
+                hash.put("stat_table_update",atomicfields.getstat_update());
+                hash.put("stat_table_delete",atomicfields.getstat_delete());
+                hash.put("stat_table_add_size",atomicfields.getstat_add_size());
+                hash.put("stat_table_update_size",atomicfields.getstat_update_size());
+                hash.put("stat_table_read_size",atomicfields.getstat_read_size());
+                hash.put("stat_table_read",atomicfields.getstat_read());
+                hash.put("stat_table_cache_hit",atomicfields.getstat_cache_hit());
+                hash.put("stat_table_cache_miss",atomicfields.getstat_cache_miss());
+                hash.put("stat_table_cache_drop",atomicfields.getstat_cache_drop());
+                atomicfields.setstat_add(Long.valueOf(0));
+                atomicfields.setstat_update(Long.valueOf(0));
+                atomicfields.setstat_delete(Long.valueOf(0));
+                atomicfields.setstat_add_size(Long.valueOf(0));
+                atomicfields.setstat_update_size(Long.valueOf(0));
+                atomicfields.setstat_read_size(Long.valueOf(0));
+                atomicfields.getstat_read_size();
+                atomicfields.setstat_read(Long.valueOf(0));
+                atomicfields.setstat_cache_hit(Long.valueOf(0));
+                atomicfields.setstat_cache_miss(Long.valueOf(0));
+                atomicfields.setstat_cache_drop(Long.valueOf(0));
+                Hashtable<String,Long> ihash=index.readStatistics();
+                hash.putAll(ihash);
+                return hash;
+            }
+        });
+        
+    }
+    
+    /**
+     * Create a new table object with the default flat index model
+     */
+
+    
+    /**
+     * Create a new table object with a specific index model
+     */
+    public DualFileTableTransactional(String title,String location, int indextype) throws IOException{
+        atomicfields = factory.create();
+        
+        this.title=title;
+        this.location=location;
+        if(!this.location.endsWith(File.separator))this.location+=File.separator;
+        switch(indextype){
+             case PAGED  : index=new PagedIndexTransactional(getFileName(INDEX));
+                break;
+           
+        }
+        indexcachefirst=null;
+        indexcachelast=null;
+        atomicfields.setFileaposition(Long.valueOf(0));
+        atomicfields.setFilebposition(Long.valueOf(0));
+        atomicfields.setstat_update_size(Long.valueOf(0));
+        atomicfields.setstat_update(Long.valueOf(0));
+        atomicfields.setstat_read_size(Long.valueOf(0));
+        atomicfields.setstat_read(Long.valueOf(0));
+        atomicfields.setstat_delete(Long.valueOf(0));
+        atomicfields.setstat_cache_miss(Long.valueOf(0));
+        atomicfields.setstat_cache_hit(Long.valueOf(0));
+        atomicfields.setstat_cache_drop(Long.valueOf(0));
+        atomicfields.setstat_add_size(Long.valueOf(0));
+        atomicfields.setstat_add(Long.valueOf(0));
+        atomicfields.setIndexcacheusage(Integer.valueOf(0));
+        indexcache=new StringKeyHashMap<TableIndexNodeTransactional>();
+    }
+     
+    /**
+     * Set the maximal allowable size of the index cache.
+     */ 
+    public void setIndexCacheSize(int newsize){
+        INDEXCACHESIZE=newsize;
+    }
+    
+    /**
+     * Close all open file streams
+     */
+    public void close(){
+        try{
+            if(fileastream!=null)fileastream.close();
+            if(filebstream!=null)filebstream.close();
+            if(filearandom!=null)filearandom.close();
+            if(filebrandom!=null)filebrandom.close();
+            index.close();
+        }catch(Exception e){}
+    }
+    
+    /** 
+     * Returns the name of this table
+     */ 
+    public String getTitle(){
+         return title;
+    }
+    
+    /**
+     * Returns the location of this tables datafiles
+     */ 
+    public String getLocation(){
+         return location;
+    }
+     
+    protected String getFileName(int type){
+         switch(type){
+             case FILEB  :   return location+title+".a";
+             case FILEA  :   return location+title+".b";
+             case INDEX  :   return location+title+".index";
+         }
+         return null;
+    }
+    
+    /**
+     * Delete the files created by this table object.
+     * Be aware that this will delete any data stored in this table!
+     */ 
+    public void deleteFiles(){
+         try{
+             File ftest=new File(getFileName(FILEA));
+             ftest.delete();
+         }catch(Exception e){}
+         try{
+             File ftest=new File(getFileName(FILEB));
+             ftest.delete();
+         }catch(Exception e){}
+         try{
+             File ftest=new File(getFileName(INDEX));
+             ftest.delete();
+         }catch(Exception e){}
+    }
+     
+     private /*synchronized*/ void openFile(int type) throws IOException{
+         switch(type){
+            case FILEA  : if(fileastream==null){
+                                System.out.println("file a " + getFileName(FILEA));
+                                fileastream=new DataOutputStream(new BufferedOutputStream(new FileOutputStream(getFileName(FILEA),true)));
+                                File ftest=new File(getFileName(FILEA));
+                                atomicfields.setFileaposition(ftest.length());
+                           }
+                          break;
+             case FILEB  : if(filebstream==null){
+                 System.out.println("file b " + getFileName(FILEB));
+                                filebstream=new DataOutputStream(new BufferedOutputStream(new FileOutputStream(getFileName(FILEB),true)));
+                                File ftest=new File(getFileName(FILEB));
+                                atomicfields.setFilebposition(ftest.length());
+                           }
+                          break;
+         }
+         
+     }
+     
+    /**
+     * Adds a row of data to this table.
+     */
+    public void addRow(RowTransactional row) throws IOException{
+        // Distribute new rows between the two datafiles by using the rowswitch, but don't spend time synchronizing... this does not need to be acurate!
+        if(rowswitch){
+            addRowA(row);
+        }else{
+            addRowB(row);
+        }
+        rowswitch=!rowswitch;
+    }
+     
+     private void addCacheEntry(TableIndexEntryTransactional entry){
+      //   synchronized(indexcache){
+             if(atomicfields.getIndexcacheusage()>INDEXCACHESIZE){
+                 // remove first entry
+                 TableIndexNodeTransactional node=indexcachefirst;
+                 indexcache.remove(node.getData().getId());
+                 atomicfields.setIndexcacheusage(atomicfields.getIndexcacheusage()-1);
+              //   synchronized(statlock){
+                     atomicfields.setstat_cache_drop(atomicfields.getstat_cache_drop()+1);
+             //    }
+                 indexcachefirst=node.getNext();
+                 if(indexcachefirst==null){
+                    indexcachelast=null;
+                 }else{
+                    indexcachefirst.setPrevious(null);
+                 }
+             }
+             TableIndexNodeTransactional node=new TableIndexNodeTransactional(indexcachelast,entry);
+             if(indexcachelast!=null){
+                 indexcachelast.setNext(node);
+             }
+             if(indexcachefirst==null){
+                 indexcachefirst=node;
+             }
+             indexcachelast=node;
+             indexcache.put(entry.getId(),node);
+             atomicfields.setIndexcacheusage(atomicfields.getIndexcacheusage()+1);
+     //   }
+     }
+     
+     private synchronized void addRowA(RowTransactional row) throws IOException{
+         synchronized(filealock){
+             synchronized(index){
+                 final Vector args = new Vector();
+                 args.add(row);
+                 Thread.doIt(new Callable<Boolean>() {
+                     public Boolean call() throws Exception{
+                         openFile(FILEA);
+                         int pre=fileastream.size();
+                         ((RowTransactional)args.get(0)).writeToStream(fileastream);
+                         int post=fileastream.size();
+                         fileastream.flush();
+
+                     //synchronized(statlock){
+                         atomicfields.setstat_add(atomicfields.getstat_add()+1);
+                         atomicfields.setstat_add_size(atomicfields.getstat_add_size()+((RowTransactional)args.get(0)).getSize());
+                     //}
+
+                        index.addEntry(((RowTransactional)args.get(0)).getId(),((RowTransactional)args.get(0)).getSize(),FILEA,atomicfields.getFilebposition());
+                        if(INDEXCACHESIZE>0){
+                            TableIndexEntryTransactional entry=new TableIndexEntryTransactional(((RowTransactional)args.get(0)).getId(),((RowTransactional)args.get(0)).getSize(),FILEA,atomicfields.getFileaposition());
+                            addCacheEntry(entry);
+                        }
+                        atomicfields.setFileaposition(atomicfields.getFileaposition()+RowTransactional.calcSize(pre,post));
+                        return true;
+                    }
+                 });
+             }
+        }
+     }
+     private synchronized void addRowB(RowTransactional row) throws IOException{
+         synchronized(fileblock){
+             synchronized(index){
+                 
+                 final Vector args = new Vector();
+                 args.add(row);
+                 Thread.doIt(new Callable<Boolean>() {
+                     public Boolean call() throws Exception{
+                         openFile(FILEB);
+                         int pre=filebstream.size();
+                         ((RowTransactional)args.get(0)).writeToStream(filebstream);
+                         int post=filebstream.size();
+                         filebstream.flush();
+                     //int post=filebstream.size();
+                     //filebstream.flush();
+                     //synchronized(statlock){
+                        atomicfields.setstat_add(atomicfields.getstat_add()+1);
+                        atomicfields.setstat_add_size(atomicfields.getstat_add_size()+((RowTransactional)args.get(0)).getSize());
+                     // }
+                        index.addEntry(((RowTransactional)args.get(0)).getId(),((RowTransactional)args.get(0)).getSize(),FILEB,atomicfields.getFilebposition());
+                        if(INDEXCACHESIZE>0){
+                          TableIndexEntryTransactional entry=new TableIndexEntryTransactional(((RowTransactional)args.get(0)).getId(),((RowTransactional)args.get(0)).getSize(),FILEB,atomicfields.getFilebposition());
+                          addCacheEntry(entry);
+                        }
+                        atomicfields.setFilebposition(atomicfields.getFilebposition()+RowTransactional.calcSize(pre,post));
+                        return true;
+                    }
+                 });
+             }
+        }
+     }
+     
+
+     private void updateCacheEntry(TableIndexEntryTransactional entry){
+        
+          //synchronized(indexcache){
+              if(indexcache.containsKey(entry.getId())){
+                  TableIndexNodeTransactional node=indexcache.get(entry.getId());
+                  node.setData(entry);
+                  if(node!=indexcachelast){
+                      if(node==indexcachefirst){
+                          indexcachefirst=node.getNext();
+                      }
+                      node.remove();
+                      indexcachelast.setNext(node);
+                      node.setPrevious(indexcachelast);
+                      node.setNext(null);
+                      indexcachelast=node;
+                  }
+              }else{
+                  addCacheEntry(entry);
+              }
+           //   return true;
+         //   }
+       // });
+      }
+
+      private void removeCacheEntry(String id){
+          //synchronized(indexcache){
+          final Vector args = new Vector();
+          args.add(id);
+          Thread.doIt(new Callable<Boolean>() {
+             public Boolean call() throws Exception{
+          
+                if(indexcache.containsKey((String)(args.get(0)))){
+                    TableIndexNodeTransactional node=indexcache.get((String)(args.get(0)));
+                    indexcache.remove((String)(args.get(0)));
+                    if(atomicfields.getIndexcacheusage()==1){
+                        indexcachefirst=null;
+                        indexcachelast=null;
+                        atomicfields.setIndexcacheusage(0);
+                        return true;
+                    }
+                    if(node==indexcachefirst){
+                        indexcachefirst=node.getNext();
+                        indexcachefirst.setPrevious(null);
+                    }else if(node==indexcachelast){
+                        indexcachelast=node.getPrevious();
+                        indexcachelast.setNext(null);
+                    }else{
+                        node.remove();
+                    }
+                    atomicfields.setIndexcacheusage(atomicfields.getIndexcacheusage()-1);
+              //      synchronized(statlock){
+                     atomicfields.setstat_cache_drop(atomicfields.getstat_cache_drop()+1);
+                     
+              //      }
+                }
+                return true;
+            }
+          });
+      }
+
+      private TableIndexEntryTransactional getCacheEntry(String id){
+         
+          //synchronized(indexcache){
+              if(indexcache.containsKey(id)){
+                  TableIndexNodeTransactional node=indexcache.get(id);
+                  if(node!=indexcachelast){
+                      if(node==indexcachefirst){
+                            indexcachefirst=node.getNext();
+                        }
+                        node.remove();
+                        indexcachelast.setNext(node);
+                        node.setPrevious(indexcachelast);
+                        node.setNext(null);
+                        indexcachelast=node;
+                  }
+                //  synchronized(statlock){
+                       atomicfields.setstat_cache_hit(atomicfields.getstat_cache_hit()+1);
+                //   }
+                  return node.getData();
+              }
+
+          //synchronized(statlock){
+               atomicfields.setstat_cache_miss(atomicfields.getstat_cache_miss()+1);
+
+           //}
+          return null;
+      }
+
+     /**
+      * Adds a row to this table if it doesn't already exist, if it does it updates the row instead.
+      * This method is much slower than directly using add or update, so only use it if you don't know wether or not the row already exists.
+      */
+     public void addOrUpdateRow(RowTransactional row) throws IOException{
+         RowTransactional tmprow=getRow(row.getId());
+         if(tmprow==null){
+             addRow(row);
+         }else{
+             updateRow(row);
+         }
+     }
+
+     /**
+      * Updates a row stored in this table.
+      */
+     public void updateRow(RowTransactional row) throws IOException{
+         TableIndexEntryTransactional entry=null;
+         final Vector args = new Vector();
+         args.add(row);
+         
+         // Handle index entry caching
+         if(INDEXCACHESIZE>0){
+             synchronized (index){
+                 entry = Thread.doIt(new Callable<TableIndexEntryTransactional>() {
+                    public TableIndexEntryTransactional call() throws Exception {
+                        TableIndexEntryTransactional entry;// = (TableIndexEntryTransactional) (args.get(1));
+                        RowTransactional row = (RowTransactional) (args.get(0));
+                        entry = getCacheEntry(row.getId());
+                        if(entry==null){
+                           entry=index.scanIndex(row.getId());
+                           addCacheEntry(entry);
+                        }
+                        return entry;
+                    }
+                 });
+             }
+          /*   synchronized(indexcache){
+                 entry=getCacheEntry(row.getId());
+                 if(entry==null){
+                     entry=index.scanIndex(row.getId());
+                     addCacheEntry(entry);
+                 }
+             }*/
+         }else{
+             entry=index.scanIndexTransactional(row.getId());
+         }
+         args.add(entry);
+         if(entry.getRowSize()>=row.getSize()){
+            // Add to the existing location
+            switch(entry.getLocation()){
+                case FILEA  :
+                     synchronized(filealock){
+                         Thread.doIt(new Callable<Boolean>() {
+                            public Boolean call() throws Exception {
+                                if(filearandom==null){
+                                    filearandom=new RandomAccessFile(getFileName(FILEA),"rw");
+                                   // fca=filearandom.getChannel();
+                                }
+                                filearandom.seek(((TableIndexEntryTransactional) (args.get(1))).getPosition());
+                                ((RowTransactional) (args.get(0))).writeToFile(filearandom);
+                                fca.force(false);
+                                return true;
+                                
+                            }
+                        });    
+                    }
+                    break;
+                case FILEB :
+                    synchronized(fileblock){
+                        Thread.doIt(new Callable<Boolean>() {
+                            public Boolean call() throws Exception {
+                                    if(filebrandom==null){
+                                        filebrandom=new RandomAccessFile(getFileName(FILEB),"rw");
+                                        fcb=filebrandom.getChannel();
+                                    }
+                                    filebrandom.seek(((TableIndexEntryTransactional) (args.get(1))).getPosition());
+                                    ((RowTransactional) (args.get(0))).writeToFile(filebrandom);
+                                    fcb.force(false);
+                                    return true;
+                            }
+                        });
+                    }
+                    break;
+            }
+         }else{
+             if(rowswitch){
+                  updateRowA(row);
+              }else{
+                  updateRowB(row);
+              }
+              rowswitch=!rowswitch;
+         }
+         //synchronized(statlock){
+         Thread.doIt(new Callable<Boolean>() {
+              public Boolean call() throws Exception{ 
+                atomicfields.setstat_update(atomicfields.getstat_update()+1);
+                atomicfields.setstat_update_size(atomicfields.getstat_update_size()+((RowTransactional) (args.get(0))).getSize());
+                return true;
+              }
+         });
+     }
+     
+     private synchronized void updateRowA(RowTransactional row) throws IOException{
+         final Vector args = new Vector();
+         args.add(row);
+         System.out.println("b");
+         synchronized(filealock){
+            synchronized (index){ 
+               // synchronized (index){
+                    Thread.doIt(new Callable<Boolean>() {
+                          public Boolean call() throws Exception{ 
+
+                              System.out.println("add a");
+                              openFile(FILEA);
+                              int pre=filebstream.size();
+                              ((RowTransactional)(args.get(0))).writeToStream(fileastream);
+                              int post=filebstream.size();
+                              fileastream.flush();
+                              index.updateEntry(((RowTransactional)(args.get(0))).getId(),((RowTransactional)(args.get(0))).getSize(),FILEA,atomicfields.getFileaposition());
+
+                              // Handle index entry caching
+                              if(INDEXCACHESIZE>0){
+                                  updateCacheEntry(new TableIndexEntryTransactional(((RowTransactional)(args.get(0))).getId(),((RowTransactional)(args.get(0))).getSize(),FILEA,atomicfields.getFileaposition()));
+                              }
+                              atomicfields.setFileaposition(atomicfields.getFilebposition()+RowTransactional.calcSize(pre,post));
+                              return true;
+                          }
+                    });
+           //     }
+            }
+         }
+     }
+
+     private synchronized void updateRowB(RowTransactional row) throws IOException{
+         final Vector args = new Vector();
+         System.out.println("b");
+         args.add(row);
+         synchronized(fileblock){
+             synchronized (index){ 
+                 //synchronized (index){
+                     Thread.doIt(new Callable<Boolean>() {
+                         public Boolean call() throws Exception{ 
+                         System.out.println("add b");
+
+                            openFile(FILEB);
+                            int pre=filebstream.size();
+                            ((RowTransactional)(args.get(0))).writeToStream(filebstream);
+                            int post=filebstream.size();
+                            filebstream.flush();
+                            index.updateEntry(((RowTransactional)(args.get(0))).getId(),((RowTransactional)(args.get(0))).getSize(),FILEB,atomicfields.getFilebposition());
+                          // Handle index entry caching
+                          // Handle index entry caching
+                            if(INDEXCACHESIZE>0){
+                                updateCacheEntry(new TableIndexEntryTransactional(((RowTransactional)(args.get(0))).getId(),((RowTransactional)(args.get(0))).getSize(),FILEB,atomicfields.getFilebposition()));
+                            }
+                            atomicfields.setFilebposition(atomicfields.getFilebposition()+RowTransactional.calcSize(pre,post));
+                            return true;
+                        }
+                    });
+              //   }
+             }
+         }
+     }
+
+     /**
+      * Marks a row as deleted in the index.
+      * Be aware that the space consumed by the row is not actually reclaimed.
+      */
+     public void deleteRow(RowTransactional row) throws IOException{
+          // Handle index entry caching
+          if(INDEXCACHESIZE>0){
+              removeCacheEntry(row.getId());
+          }
+          index.updateEntryTransactional(row.getId(),row.getSize(),DELETE,0);
+          Thread.doIt(new Callable<Boolean>() {
+             public Boolean call() throws Exception{
+          //synchronized(statlock){
+                atomicfields.setstat_delete(atomicfields.getstat_delete()+1);
+                return true;
+             }
+          });
+         // }
+     }
+     
+     /**
+      * Returns a tuplestream containing the given list of rows
+      */
+     public TupleStreamTransactional getRows(List<String> rows) throws IOException{
+         return new IndexedTableReaderTransactional(this,index.scanIndex(rows));
+     }
+
+     /**
+      * Returns a tuplestream containing the rows matching the given rowmatcher
+      */
+     public TupleStreamTransactional getRows(RowMatcherTransactional matcher) throws IOException{
+         return new IndexedTableReaderTransactional(this,index.scanIndex(),matcher);
+     }
+     
+     /**
+      * Returns a tuplestream containing those rows in the given list that matches the given RowMatcher
+      */
+     public TupleStreamTransactional getRows(List<String> rows,RowMatcherTransactional matcher) throws IOException{
+          return new IndexedTableReaderTransactional(this,index.scanIndex(rows),matcher);
+      }
+
+     /**
+      * Returns a tuplestream of all rows in this table.
+      */
+     public TupleStreamTransactional getRows() throws IOException{
+         // return new TableReader(this);
+         return new IndexedTableReaderTransactional(this,index.scanIndex());
+     }
+     
+     /**
+      * Returns a single row stored in this table.
+      * If the row does not exist in the table, null will be returned.
+      */
+     public RowTransactional getRow(String id) throws IOException{
+         TableIndexEntryTransactional entry=null;
+          final Vector args = new Vector();
+              args.add(id);
+             // args.add(entry);
+          // Handle index entry caching
+          if(INDEXCACHESIZE>0){
+             
+              //synchronized(indexcache){
+              synchronized (index){
+                  entry = Thread.doIt(new Callable<TableIndexEntryTransactional>() {
+                    public TableIndexEntryTransactional call() throws Exception{
+                      TableIndexEntryTransactional entry;// = (TableIndexEntryTransactional) (args.get(1));
+                      String id = (String) (args.get(0));  
+                      entry=getCacheEntry(id);
+                     //  System.out.println("presalam " + (TableIndexEntryTransactional) (args.get(1)));
+                       if(entry==null){
+                           entry=index.scanIndex(id);
+                           if(entry!=null){
+                               addCacheEntry(entry);
+                           }
+                       }
+                      return entry;
+                    }
+                  });
+              }
+              
+          }else{
+              entry=index.scanIndexTransactional(id);
+          }
+//          entry = (TableIndexEntryTransactional) (args.get(1));
+  //        args.clear();
+          
+          if(entry!=null){
+              long dataoffset=0;
+              DataInputStream data=null;
+
+              if(entry.getLocation()==TableTransactional.FILEA){
+                  data=new DataInputStream(new BufferedInputStream(new FileInputStream(getFileName(TableTransactional.FILEA))));
+              }else if(entry.getLocation()==TableTransactional.FILEB){
+                  data=new DataInputStream(new BufferedInputStream(new FileInputStream(getFileName(TableTransactional.FILEB))));
+              }
+              if(data!=null){
+                  while(dataoffset!=entry.getPosition()){
+                      dataoffset+=data.skipBytes((int)(entry.getPosition()-dataoffset));
+                  }
+                  RowTransactional row=RowTransactional.readFromStream(data);
+                  data.close();
+                  final Vector args2 = new Vector();
+                  args2.add(row);
+                  Thread.doIt(new Callable<Boolean>() {
+                      public Boolean call() throws Exception{
+                  //synchronized(statlock){
+                          atomicfields.setstat_read(atomicfields.getstat_read()+1);
+                          atomicfields.setstat_read_size(atomicfields.getstat_read_size()+((RowTransactional)args2.get(0)).getSize());
+                          return true;
+                      }
+                  });
+                  return row;
+              }
+              
+          }
+          return null;
+     }
+ }
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/HashedTable.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/HashedTable.java
new file mode 100644 (file)
index 0000000..c0588cd
--- /dev/null
@@ -0,0 +1,225 @@
+
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.solidosystems.tuplesoup.core;
+import java.io.*;
+import java.util.*;
+import java.nio.channels.*;
+import com.solidosystems.tuplesoup.filter.*;
+
+/**
+ * The table stores a group of rows.
+ * Every row must have a unique id within a table.
+ */
+public class HashedTable implements Table{
+    private int TABLESETSIZE=5;
+    private List<Table> tableset;
+    private String title;
+    private String location;
+    
+
+    
+    /**
+     * Create a new table object with a specific index model
+     */
+    public HashedTable(String title,String location, int indextype) throws IOException{
+        this.title=title;
+        this.location=location;
+        tableset=new ArrayList<Table>();
+        for(int i=0;i<TABLESETSIZE;i++){
+            tableset.add(new DualFileTable(title+"_"+i,location,indextype));
+        }
+    }
+    
+    
+    public Hashtable<String,Long> readStatistics(){
+        Hashtable<String,Long> results=new Hashtable<String,Long>();
+        for(int i=0;i<TABLESETSIZE;i++){
+            Hashtable<String,Long> tmp=tableset.get(i).readStatistics();
+            Set<String> keys=tmp.keySet();
+            Iterator<String> it=keys.iterator();
+            while(it.hasNext()){
+                String key=it.next();
+                long value=tmp.get(key);
+                if(results.containsKey(key)){
+                    results.put(key,results.get(key)+value);
+                }else{
+                    results.put(key,value);
+                }
+            }
+        }
+        return results;
+    }
+    
+    /** 
+     * Returns the name of this table
+     */ 
+    public String getTitle(){
+         return title;
+    }
+    
+    /**
+     * Returns the location of this tables datafiles
+     */ 
+    public String getLocation(){
+         return location;
+    }
+    
+    /**
+     * Delete the files created by this table object.
+     * Be aware that this will delete any data stored in this table!
+     */ 
+    public void deleteFiles(){
+        for(int i=0;i<TABLESETSIZE;i++){
+            tableset.get(i).deleteFiles();
+        }
+    }
+    
+    public void close(){
+        for(int i=0;i<TABLESETSIZE;i++){
+            tableset.get(i).close();
+        }
+    }
+    
+    public void setIndexCacheSize(int size){
+        for(int i=0;i<TABLESETSIZE;i++){
+            tableset.get(i).setIndexCacheSize(size/TABLESETSIZE);
+        }
+    }
+    
+    private Table getTableForId(String id){
+        return tableset.get(id.hashCode() & (TABLESETSIZE-1));
+    }
+    
+    /**
+      * Returns a single row stored in this table.
+      * If the row does not exist in the table, null will be returned.
+      */
+     public Row getRow(String id) throws IOException{
+        Table tbl=getTableForId(id);
+        return tbl.getRow(id);
+     }
+    
+    /**
+      * Returns a tuplestream of all rows in this table.
+      */
+     public TupleStream getRows() throws IOException{
+        TupleStreamMerger merge=new TupleStreamMerger();
+        for(int i=0;i<TABLESETSIZE;i++){
+            merge.addStream(tableset.get(i).getRows());
+        }
+        return merge;
+     }
+     /**
+       * Returns a tuplestream containing the given list of rows
+       */
+      public TupleStream getRows(List<String> rows) throws IOException{
+          List<List<String>> listset=new ArrayList<List<String>>();
+          for(int i=0;i<TABLESETSIZE;i++){
+              listset.add(new ArrayList<String>());
+          }
+          for(int i=0;i<rows.size();i++){
+              String id=rows.get(i);
+              listset.get(id.hashCode() & TABLESETSIZE).add(id);
+          }
+          TupleStreamMerger merge=new TupleStreamMerger();
+          for(int i=0;i<TABLESETSIZE;i++){
+              if(listset.get(i).size()>0){
+                  merge.addStream(tableset.get(i).getRows(listset.get(i)));
+              }
+          }
+          return merge;
+      }
+
+      /**
+       * Returns a tuplestream containing the rows matching the given rowmatcher
+       */
+      public TupleStream getRows(RowMatcher matcher) throws IOException{
+          TupleStreamMerger merge=new TupleStreamMerger();
+          for(int i=0;i<TABLESETSIZE;i++){
+              merge.addStream(tableset.get(i).getRows(matcher));
+          }
+          return merge;
+      }  
+        
+      /**
+       * Returns a tuplestream containing those rows in the given list that matches the given RowMatcher
+       */
+      public TupleStream getRows(List<String> rows,RowMatcher matcher) throws IOException{
+          List<List<String>> listset=new ArrayList<List<String>>();
+            for(int i=0;i<TABLESETSIZE;i++){
+                listset.add(new ArrayList<String>());
+            }
+            for(int i=0;i<rows.size();i++){
+                String id=rows.get(i);
+                listset.get(id.hashCode() & TABLESETSIZE).add(id);
+            }
+            TupleStreamMerger merge=new TupleStreamMerger();
+            for(int i=0;i<TABLESETSIZE;i++){
+                if(listset.get(i).size()>0){
+                    merge.addStream(tableset.get(i).getRows(listset.get(i),matcher));
+                }
+            }
+            return merge;
+      }
+      
+      /**
+        * Marks a row as deleted in the index.
+        * Be aware that the space consumed by the row is not actually reclaimed.
+        */
+       public void deleteRow(Row row) throws IOException{
+           getTableForId(row.getId()).deleteRow(row);
+       }
+       
+       /**
+        * Adds a row of data to this table.
+        */
+       public void addRow(Row row) throws IOException{
+           getTableForId(row.getId()).addRow(row);
+       }
+
+        /**
+         * Adds a row to this table if it doesn't already exist, if it does it updates the row instead.
+         * This method is much slower than directly using add or update, so only use it if you don't know wether or not the row already exists.
+         */
+        public void addOrUpdateRow(Row row) throws IOException{
+            getTableForId(row.getId()).addOrUpdateRow(row);
+        }
+
+        /**
+         * Updates a row stored in this table.
+         */
+        public void updateRow(Row row) throws IOException{
+            getTableForId(row.getId()).updateRow(row);
+        }
+}
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/HashedTableTransactional.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/HashedTableTransactional.java
new file mode 100644 (file)
index 0000000..e9b229c
--- /dev/null
@@ -0,0 +1,225 @@
+
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.solidosystems.tuplesoup.core;
+import java.io.*;
+import java.util.*;
+import java.nio.channels.*;
+import com.solidosystems.tuplesoup.filter.*;
+
+/**
+ * The table stores a group of rows.
+ * Every row must have a unique id within a table.
+ */
+public class HashedTableTransactional implements TableTransactional{
+    private int TABLESETSIZE=5;
+    private List<TableTransactional> tableset;
+    private String title;
+    private String location;
+    
+
+    
+    /**
+     * Create a new table object with a specific index model
+     */
+    public HashedTableTransactional(String title,String location, int indextype) throws IOException{
+        this.title=title;
+        this.location=location;
+        tableset=new ArrayList<TableTransactional>();
+        for(int i=0;i<TABLESETSIZE;i++){
+            tableset.add(new DualFileTableTransactional(title+"_"+i,location,indextype));
+        }
+    }
+    
+    
+    public Hashtable<String,Long> readStatistics(){
+        Hashtable<String,Long> results=new Hashtable<String,Long>();
+        for(int i=0;i<TABLESETSIZE;i++){
+            Hashtable<String,Long> tmp=tableset.get(i).readStatistics();
+            Set<String> keys=tmp.keySet();
+            Iterator<String> it=keys.iterator();
+            while(it.hasNext()){
+                String key=it.next();
+                long value=tmp.get(key);
+                if(results.containsKey(key)){
+                    results.put(key,results.get(key)+value);
+                }else{
+                    results.put(key,value);
+                }
+            }
+        }
+        return results;
+    }
+    
+    /** 
+     * Returns the name of this table
+     */ 
+    public String getTitle(){
+         return title;
+    }
+    
+    /**
+     * Returns the location of this tables datafiles
+     */ 
+    public String getLocation(){
+         return location;
+    }
+    
+    /**
+     * Delete the files created by this table object.
+     * Be aware that this will delete any data stored in this table!
+     */ 
+    public void deleteFiles(){
+        for(int i=0;i<TABLESETSIZE;i++){
+            tableset.get(i).deleteFiles();
+        }
+    }
+    
+    public void close(){
+        for(int i=0;i<TABLESETSIZE;i++){
+            tableset.get(i).close();
+        }
+    }
+    
+    public void setIndexCacheSize(int size){
+        for(int i=0;i<TABLESETSIZE;i++){
+            tableset.get(i).setIndexCacheSize(size/TABLESETSIZE);
+        }
+    }
+    
+    private TableTransactional getTableForId(String id){
+        return tableset.get(id.hashCode() & (TABLESETSIZE-1));
+    }
+    
+    /**
+      * Returns a single row stored in this table.
+      * If the row does not exist in the table, null will be returned.
+      */
+     public RowTransactional getRow(String id) throws IOException{
+        TableTransactional tbl=getTableForId(id);
+        return tbl.getRow(id);
+     }
+    
+    /**
+      * Returns a tuplestream of all rows in this table.
+      */
+     public TupleStreamTransactional getRows() throws IOException{
+        TupleStreamMergerTransactional merge=new TupleStreamMergerTransactional();
+        for(int i=0;i<TABLESETSIZE;i++){
+            merge.addStream(tableset.get(i).getRows());
+        }
+        return merge;
+     }
+     /**
+       * Returns a tuplestream containing the given list of rows
+       */
+      public TupleStreamTransactional getRows(List<String> rows) throws IOException{
+          List<List<String>> listset=new ArrayList<List<String>>();
+          for(int i=0;i<TABLESETSIZE;i++){
+              listset.add(new ArrayList<String>());
+          }
+          for(int i=0;i<rows.size();i++){
+              String id=rows.get(i);
+              listset.get(id.hashCode() & TABLESETSIZE).add(id);
+          }
+          TupleStreamMergerTransactional merge=new TupleStreamMergerTransactional();
+          for(int i=0;i<TABLESETSIZE;i++){
+              if(listset.get(i).size()>0){
+                  merge.addStream(tableset.get(i).getRows(listset.get(i)));
+              }
+          }
+          return merge;
+      }
+
+      /**
+       * Returns a tuplestream containing the rows matching the given rowmatcher
+       */
+      public TupleStreamTransactional getRows(RowMatcherTransactional matcher) throws IOException{
+          TupleStreamMergerTransactional merge=new TupleStreamMergerTransactional();
+          for(int i=0;i<TABLESETSIZE;i++){
+              merge.addStream(tableset.get(i).getRows(matcher));
+          }
+          return merge;
+      }  
+        
+      /**
+       * Returns a tuplestream containing those rows in the given list that matches the given RowMatcher
+       */
+      public TupleStreamTransactional getRows(List<String> rows,RowMatcherTransactional matcher) throws IOException{
+          List<List<String>> listset=new ArrayList<List<String>>();
+            for(int i=0;i<TABLESETSIZE;i++){
+                listset.add(new ArrayList<String>());
+            }
+            for(int i=0;i<rows.size();i++){
+                String id=rows.get(i);
+                listset.get(id.hashCode() & TABLESETSIZE).add(id);
+            }
+            TupleStreamMergerTransactional merge=new TupleStreamMergerTransactional();
+            for(int i=0;i<TABLESETSIZE;i++){
+                if(listset.get(i).size()>0){
+                    merge.addStream(tableset.get(i).getRows(listset.get(i),matcher));
+                }
+            }
+            return merge;
+      }
+      
+      /**
+        * Marks a row as deleted in the index.
+        * Be aware that the space consumed by the row is not actually reclaimed.
+        */
+       public void deleteRow(RowTransactional row) throws IOException{
+           getTableForId(row.getId()).deleteRow(row);
+       }
+       
+       /**
+        * Adds a row of data to this table.
+        */
+       public void addRow(RowTransactional row) throws IOException{
+           getTableForId(row.getId()).addRow(row);
+       }
+
+        /**
+         * Adds a row to this table if it doesn't already exist, if it does it updates the row instead.
+         * This method is much slower than directly using add or update, so only use it if you don't know wether or not the row already exists.
+         */
+        public void addOrUpdateRow(RowTransactional row) throws IOException{
+            getTableForId(row.getId()).addOrUpdateRow(row);
+        }
+
+        /**
+         * Updates a row stored in this table.
+         */
+        public void updateRow(RowTransactional row) throws IOException{
+            getTableForId(row.getId()).updateRow(row);
+        }
+}
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/IndexedTableReader.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/IndexedTableReader.java
new file mode 100644 (file)
index 0000000..0684c3b
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+ package com.solidosystems.tuplesoup.core;
+ import com.solidosystems.tuplesoup.filter.*;
+ import java.io.*;
+ import java.util.*;
+
+public class IndexedTableReader extends TupleStream{
+    private DataInputStream fileastream=null;
+    private DataInputStream filebstream=null;
+    private long fileaposition=0;
+    private long filebposition=0;
+
+    private List<TableIndexEntry>fileaentries;
+    private List<TableIndexEntry>filebentries;
+    
+    private List<TableIndexEntry>entries;
+
+    private Hashtable<String,Row>fileabuffer;
+    private Hashtable<String,Row>filebbuffer;
+
+    private List<String>rows;
+    private int rowpointer;
+    private Row next=null;
+    
+    private DualFileTable table;
+    
+    private RowMatcher matcher=null;
+    
+    public IndexedTableReader(DualFileTable table,List<TableIndexEntry>entries) throws IOException{
+        this.table=table;
+        this.rows=rows;
+        rowpointer=0;
+        
+        this.entries=entries;
+        fileaentries=new ArrayList<TableIndexEntry>();
+        filebentries=new ArrayList<TableIndexEntry>();
+        
+        Iterator<TableIndexEntry> it=entries.iterator();
+        while(it.hasNext()){
+            TableIndexEntry entry=it.next();
+            // TODO: we really shouldn't get nulls here
+            if(entry!=null){
+                if(entry.location==Table.FILEA){
+                    fileaentries.add(entry);
+                }else if(entry.location==Table.FILEB){
+                    filebentries.add(entry);
+                }
+            }
+        }
+        
+        Collections.sort(fileaentries);
+        Collections.sort(filebentries);
+        
+        fileabuffer=new Hashtable<String,Row>();
+        filebbuffer=new Hashtable<String,Row>();
+        
+        readNext();   
+    }
+    
+    
+    public IndexedTableReader(DualFileTable table,List<TableIndexEntry>entries,RowMatcher matcher) throws IOException{
+        this.table=table;
+        this.rows=rows;
+        rowpointer=0;
+        this.matcher=matcher;
+        
+        this.entries=entries;
+        fileaentries=new ArrayList<TableIndexEntry>();
+        filebentries=new ArrayList<TableIndexEntry>();
+        
+        Iterator<TableIndexEntry> it=entries.iterator();
+        while(it.hasNext()){
+            TableIndexEntry entry=it.next();
+            // TODO: we really shouldn't get nulls here
+            if(entry!=null){
+                if(entry.location==Table.FILEA){
+                    fileaentries.add(entry);
+                }else if(entry.location==Table.FILEB){
+                    filebentries.add(entry);
+                }
+            }
+        }
+        
+        Collections.sort(fileaentries);
+        Collections.sort(filebentries);
+        
+        fileabuffer=new Hashtable<String,Row>();
+        filebbuffer=new Hashtable<String,Row>();
+        
+        readNext();   
+    }
+    
+    private void readNextFromFileA(TableIndexEntry entry) throws IOException{
+        if(fileabuffer.containsKey(entry.id)){
+            next=fileabuffer.remove(entry.id);
+            return;
+        }
+        while(true){
+            if(fileaentries.size()>0){
+                TableIndexEntry nextfilea=fileaentries.remove(0);
+                if(fileastream==null){
+                    fileastream=new DataInputStream(new BufferedInputStream(new FileInputStream(table.getFileName(Table.FILEA))));
+                    fileaposition=0;
+                }
+                if(fileaposition>nextfilea.position){
+                    // We have already read this entry... skip it
+                    // readNextFromFileA(entry);
+                    // return;
+                }else{
+                    while(fileaposition!=nextfilea.position){
+                        fileaposition+=fileastream.skipBytes((int)(nextfilea.position-fileaposition));
+                    }
+                    Row row=Row.readFromStream(fileastream);
+                    synchronized(table.statlock){
+                        table.stat_read_size+=row.getSize();
+                        table.stat_read++;
+                    }
+                    fileaposition+=row.getSize();
+                    if(row.getId().equals(entry.id)){
+                        next=row;
+                        return;
+                    }else{
+                        fileabuffer.put(row.getId(),row);
+                        // readNextFromFileA(entry);
+                    }
+                }
+            }else{
+                next=null;
+                return;
+            }
+        }
+    }
+    
+    private void readNextFromFileB(TableIndexEntry entry) throws IOException{
+        if(filebbuffer.containsKey(entry.id)){
+            next=filebbuffer.remove(entry.id);
+            return;
+        }
+        while(true){
+            if(filebentries.size()>0){
+                TableIndexEntry nextfileb=filebentries.remove(0);
+                if(filebstream==null){
+                    filebstream=new DataInputStream(new BufferedInputStream(new FileInputStream(table.getFileName(Table.FILEB))));
+                    filebposition=0;
+                }
+                if(filebposition>nextfileb.position){
+                    // We have already read this entry... skip it
+                    // readNextFromFileB(entry);
+                    // return;
+                }else{
+                    while(filebposition!=nextfileb.position){
+                        filebposition+=filebstream.skipBytes((int)(nextfileb.position-filebposition));
+                    }
+                    Row row=Row.readFromStream(filebstream);
+                    synchronized(table.statlock){
+                        table.stat_read_size+=row.getSize();
+                        table.stat_read++;
+                    }
+                    filebposition+=row.getSize();
+                    if(row.getId().equals(entry.id)){
+                        next=row;
+                        return;
+                    }else{
+                        filebbuffer.put(row.getId(),row);
+                        // readNextFromFileB(entry);
+                    }
+                }
+            }else{
+                next=null;
+                return;
+            }
+        }
+    }
+    
+    private void readNext() throws IOException{
+        if(entries.size()>rowpointer){
+            TableIndexEntry entry=entries.get(rowpointer++);
+            if(entry!=null){
+                   switch(entry.location){
+                    case Table.FILEA    : readNextFromFileA(entry);
+                                        // return;
+                                        break;
+                    case Table.FILEB : readNextFromFileB(entry);
+                                        // return;
+                                        break;
+                }
+                if(next!=null){
+                    if(matcher!=null){
+                        if(!matcher.matches(next)){
+                             readNext();
+                        }
+                    }
+                }
+                return;
+            }else{
+                readNext();
+                return;
+            }
+        }
+        try{
+            if(fileastream!=null)fileastream.close();
+        }catch(Exception e){}
+        try{
+            if(filebstream!=null)filebstream.close();
+        }catch(Exception e){}
+        next=null;
+    }
+    
+    public boolean hasNext(){
+        if(next!=null)return true;
+        return false;
+    }
+    
+    public Row next(){
+        try{
+            if(next!=null){
+                Row tmp=next;
+                readNext();
+                return tmp;
+            }
+        }catch(Exception e){
+            e.printStackTrace();
+        }
+        return null;
+    }
+    
+    public void remove(){
+        
+    }
+}
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/IndexedTableReaderTransactional.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/IndexedTableReaderTransactional.java
new file mode 100644 (file)
index 0000000..db2b16c
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+ package com.solidosystems.tuplesoup.core;
+
+ import com.solidosystems.tuplesoup.filter.*;
+ import java.io.*;
+ import java.util.*;
+ import java.util.concurrent.Callable;
+ import dstm2.Thread;
+
+
+public class IndexedTableReaderTransactional extends TupleStreamTransactional{
+
+    
+    
+    
+    private DataInputStream fileastream=null;
+    private DataInputStream filebstream=null;
+    private long fileaposition=0;
+    private long filebposition=0;
+
+    private List<TableIndexEntryTransactional>fileaentries;
+    private List<TableIndexEntryTransactional>filebentries;
+    
+    private List<TableIndexEntryTransactional>entries;
+
+    private Hashtable<String,RowTransactional>fileabuffer;
+    private Hashtable<String,RowTransactional>filebbuffer;
+
+    private List<String>rows;
+    private int rowpointer;
+    private RowTransactional next=null;
+    
+    private DualFileTableTransactional table;
+    
+    private RowMatcherTransactional matcher=null;
+    
+    public IndexedTableReaderTransactional(DualFileTableTransactional table,List<TableIndexEntryTransactional>entries) throws IOException{
+        this.table=table;
+        this.rows=rows;
+        rowpointer=0;
+        
+        this.entries=entries;
+        fileaentries=new ArrayList<TableIndexEntryTransactional>();
+        filebentries=new ArrayList<TableIndexEntryTransactional>();
+        
+        Iterator<TableIndexEntryTransactional> it=entries.iterator();
+        while(it.hasNext()){
+            TableIndexEntryTransactional entry=it.next();
+            // TODO: we really shouldn't get nulls here
+            if(entry!=null){
+                if(entry.getLocation()==TableTransactional.FILEA){
+                    fileaentries.add(entry);
+                }else if(entry.getLocation()==TableTransactional.FILEB){
+                    filebentries.add(entry);
+                }
+            }
+        }
+        
+        Collections.sort(fileaentries);
+        Collections.sort(filebentries);
+        
+        fileabuffer=new Hashtable<String,RowTransactional>();
+        filebbuffer=new Hashtable<String,RowTransactional>();
+        
+        readNext();   
+    }
+    
+    
+    public IndexedTableReaderTransactional(DualFileTableTransactional table,List<TableIndexEntryTransactional>entries,RowMatcherTransactional matcher) throws IOException{
+        this.table=table;
+        this.rows=rows;
+        rowpointer=0;
+        this.matcher=matcher;
+        
+        this.entries=entries;
+        fileaentries=new ArrayList<TableIndexEntryTransactional>();
+        filebentries=new ArrayList<TableIndexEntryTransactional>();
+        
+        Iterator<TableIndexEntryTransactional> it=entries.iterator();
+        while(it.hasNext()){
+            TableIndexEntryTransactional entry=it.next();
+            // TODO: we really shouldn't get nulls here
+            if(entry!=null){
+                if(entry.getLocation()==TableTransactional.FILEA){
+                    fileaentries.add(entry);
+                }else if(entry.getLocation()==TableTransactional.FILEB){
+                    filebentries.add(entry);
+                }
+            }
+        }
+        
+        Collections.sort(fileaentries);
+        Collections.sort(filebentries);
+        
+        fileabuffer=new Hashtable<String,RowTransactional>();
+        filebbuffer=new Hashtable<String,RowTransactional>();
+        
+        readNext();   
+    }
+    
+    private void readNextFromFileA(TableIndexEntryTransactional entry) throws IOException{
+        if(fileabuffer.containsKey(entry.getId())){
+            next=fileabuffer.remove(entry.getId());
+            return;
+        }
+        while(true){
+            if(fileaentries.size()>0){
+                TableIndexEntryTransactional nextfilea=fileaentries.remove(0);
+                if(fileastream==null){
+                  //  fileastream=new TransactionalFile(table.getFileName(TableTransactional.FILEA), "rw");
+                    fileastream=new DataInputStream(new BufferedInputStream(new FileInputStream(table.getFileName(TableTransactional.FILEA))));
+                    fileaposition=0;
+                }
+                if(fileaposition>nextfilea.getPosition()){
+                    // We have already read this entry... skip it
+                    // readNextFromFileA(entry);
+                    // return;
+                }else{
+                    while(fileaposition!=nextfilea.getPosition()){
+                        fileaposition+=fileastream.skipBytes((int)(nextfilea.getPosition()-fileaposition));
+                    }
+                    
+                    RowTransactional row=RowTransactional.readFromStream(fileastream);
+                    final Vector args = new Vector();
+                    args.add(row);
+                    Thread.doIt(new Callable<Boolean>() {
+                       public Boolean call() throws Exception{
+                    //synchronized(table.statlock){
+                        table.atomicfields.setstat_read_size(table.atomicfields.getstat_read_size()+((RowTransactional)(args.get(0))).getSize());
+                        table.atomicfields.setstat_read(table.atomicfields.getstat_read()+1);
+                        return true;
+                      }
+                      //}
+                    });
+                    
+                    fileaposition+=row.getSize();
+                    if(row.getId().equals(entry.getId())){
+                        next=row;
+                        return;
+                    }else{
+                        fileabuffer.put(row.getId(),row);
+                        // readNextFromFileA(entry);
+                    }
+                }
+            }else{
+                next=null;
+                return;
+            }
+        }
+    }
+    
+    private void readNextFromFileB(TableIndexEntryTransactional entry) throws IOException{
+        if(filebbuffer.containsKey(entry.getId())){
+            next=filebbuffer.remove(entry.getId());
+            return;
+        }
+        while(true){
+            if(filebentries.size()>0){
+                TableIndexEntryTransactional nextfileb=filebentries.remove(0);
+                if(filebstream==null){
+                    filebstream=new DataInputStream(new BufferedInputStream(new FileInputStream(table.getFileName(TableTransactional.FILEB))));
+                    filebposition=0;
+                }
+                if(filebposition>nextfileb.getPosition()){
+                    // We have already read this entry... skip it
+                    // readNextFromFileB(entry);
+                    // return;
+                }else{
+                    while(filebposition!=nextfileb.getPosition()){
+                        filebposition+=filebstream.skipBytes((int)(nextfileb.getPosition()-filebposition));
+                    }
+                    RowTransactional row=RowTransactional.readFromStream(filebstream);
+                    
+                    final Vector args = new Vector();
+                    args.add(row);
+                    Thread.doIt(new Callable<Boolean>() {
+                       public Boolean call() throws Exception{
+                    //synchronized(table.statlock){
+                            table.atomicfields.setstat_read_size(table.atomicfields.getstat_read_size()+((RowTransactional)(args.get(0))).getSize());
+                            table.atomicfields.setstat_read(table.atomicfields.getstat_read()+1);
+                            return true;
+                        }
+                    });
+                    
+                    filebposition+=row.getSize();
+                    if(row.getId().equals(entry.getId())){
+                        next=row;
+                        return;
+                    }else{
+                        filebbuffer.put(row.getId(),row);
+                        // readNextFromFileB(entry);
+                    }
+                }
+            }else{
+                next=null;
+                return;
+            }
+        }
+    }
+    
+    private void readNext() throws IOException{
+        if(entries.size()>rowpointer){
+            TableIndexEntryTransactional entry=entries.get(rowpointer++);
+            if(entry!=null){
+                   switch(entry.getLocation()){
+                    case TableTransactional.FILEA    : readNextFromFileA(entry);
+                                        // return;
+                                        break;
+                    case TableTransactional.FILEB : readNextFromFileB(entry);
+                                        // return;
+                                        break;
+                }
+                if(next!=null){
+                    if(matcher!=null){
+                        if(!matcher.matches(next)){
+                             readNext();
+                        }
+                    }
+                }
+                return;
+            }else{
+                readNext();
+                return;
+            }
+        }
+        try{
+            if(fileastream!=null)fileastream.close();
+        }catch(Exception e){}
+        try{
+            if(filebstream!=null)filebstream.close();
+        }catch(Exception e){}
+        next=null;
+    }
+    
+    public boolean hasNext(){
+        if(next!=null)return true;
+        return false;
+    }
+    
+    public RowTransactional next(){
+        try{
+            if(next!=null){
+                RowTransactional tmp=next;
+                readNext();
+                return tmp;
+            }
+        }catch(Exception e){
+            e.printStackTrace();
+        }
+        return null;
+    }
+    
+    public void remove(){
+        
+    }
+}
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/PagedIndex.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/PagedIndex.java
new file mode 100644 (file)
index 0000000..6614435
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.solidosystems.tuplesoup.core;
+
+import dstm2.AtomicArray;
+import dstm2.atomic;
+import java.io.*;
+import java.util.*;
+import java.nio.channels.*;
+
+public class PagedIndex implements TableIndex{
+    
+//protected static final int INITIALPAGEHASH=1024;
+  //  protected static final int PAGESIZE=2048;
+    
+    protected static final int INITIALPAGEHASH=32;
+    protected static final int PAGESIZE=64;
+    
+    private RandomAccessFile out=null;
+    private String filename;
+    private TableIndexPage[] root=null;
+   // private TableIndexPageTransactional[] root=null;
+    
+    private long stat_read=0;
+    private long stat_write=0;
+    protected long stat_create_page=0;
+    protected long stat_page_next=0;
+    protected long stat_page_branch=0;
+    public PagedIndex(String filename) throws IOException{
+        this.filename=filename;
+        File ftest=new File(filename);
+        if(!ftest.exists())ftest.createNewFile();
+        out=new RandomAccessFile(filename,"rw");
+        root=new TableIndexPage[INITIALPAGEHASH];
+        System.out.println(filename);
+        System.out.println(out.length());
+        if(out.length()>0){
+            for(int i=0;i<INITIALPAGEHASH;i++){
+                root[i]=new TableIndexPage(this,out);
+                root[i].setFirst();
+                out.seek(root[i].getEndLocation());
+            }
+        }else{
+            for(int i=0;i<INITIALPAGEHASH;i++){
+                root[i]=TableIndexPage.createNewPage(this,out,PAGESIZE);
+                root[i].setFirst();
+            }
+        }
+    }
+    
+    public Hashtable<String,Long> readStatistics(){
+        Hashtable<String,Long> hash=new Hashtable<String,Long>();
+        hash.put("stat_index_read",stat_read);
+        hash.put("stat_index_write",stat_write);
+        hash.put("stat_index_create_page",stat_create_page);
+        hash.put("stat_index_page_next",stat_page_next);
+        hash.put("stat_index_page_branch",stat_page_branch);
+        stat_read=0;
+        stat_write=0;
+        stat_create_page=0;
+        stat_page_next=0;
+        stat_page_branch=0;
+        return hash;
+    }
+    
+    private int rootHash(String id){
+        return id.hashCode() & (INITIALPAGEHASH-1);
+    }
+    
+    private synchronized TableIndexPage getFirstFreePage(String id) throws IOException{
+        return root[rootHash(id)].getFirstFreePage(id,id.hashCode());
+    }
+    
+    private synchronized long getOffset(String id) throws IOException{
+        if(root==null)return -1;
+        return root[rootHash(id)].getOffset(id,id.hashCode());
+    }
+    
+    public synchronized void updateEntry(String id,int rowsize,int location,long position) throws IOException{
+        long offset=getOffset(id);
+        out.seek(offset);
+        TableIndexEntry entry=new TableIndexEntry(id,rowsize,location,position);
+        entry.updateData(out);
+        stat_write++;
+    }
+    public synchronized void addEntry(String id,int rowsize,int location,long position) throws IOException{
+        TableIndexPage page=getFirstFreePage(id);
+        page.addEntry(id,rowsize,location,position);
+        stat_write++;
+    }
+    public synchronized TableIndexEntry scanIndex(String id) throws IOException{
+        if(root==null)return null;
+        return root[rootHash(id)].scanIndex(id,id.hashCode());
+    }
+    public synchronized List<TableIndexEntry> scanIndex(List<String> rows) throws IOException{
+        List<TableIndexEntry> lst=new ArrayList<TableIndexEntry>();
+        for(int i=0;i<rows.size();i++){
+            String id=rows.get(i);
+            TableIndexEntry entry=scanIndex(id);
+            if(entry!=null){
+                if(entry.getLocation()!=Table.DELETE)lst.add(entry);
+            }
+        }
+        return lst;
+    }
+    public synchronized List<TableIndexEntry> scanIndex() throws IOException{
+        ArrayList<TableIndexEntry> lst=new ArrayList<TableIndexEntry>();
+        for(int i=0;i<INITIALPAGEHASH;i++){
+            root[i].addEntriesToList(lst);
+        }
+        return lst;
+    }
+    public void close(){
+        try{
+            if(out!=null){
+                out.close();
+            }
+        }catch(Exception e){}
+    }
+}
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/PagedIndexTransactional.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/PagedIndexTransactional.java
new file mode 100644 (file)
index 0000000..0900988
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package com.solidosystems.tuplesoup.core;
+
+
+import dstm2.AtomicArray;
+import dstm2.atomic;
+import dstm2.Thread;
+import dstm2.factory.Factory;
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Vector;
+import java.util.concurrent.Callable;
+
+/**
+ *
+ * @author navid
+ */
+public class PagedIndexTransactional implements TableIndexTransactional{
+
+    static Factory<PageIndexTSInf> factory = Thread.makeFactory(PageIndexTSInf.class);
+    
+    PageIndexTSInf atomicfields;
+   
+
+    
+    public @atomic interface PageIndexTSInf{
+       String getFilename();
+       Long getStat_read();
+       Long getStat_write();
+       Long getStat_create_page();
+       Long getStat_page_next();
+       Long getStat_page_branch();
+       AtomicArray<TableIndexPageTransactional> getRoots();
+       
+       void setFilename(String val);
+       void setRoots(AtomicArray<TableIndexPageTransactional> roots);
+       void setStat_read(Long val);
+       void setStat_write(Long val);
+       void setStat_create_page(Long val);
+       void setStat_page_next(Long val);
+       void setStat_page_branch(Long val);
+    }
+    
+    
+    private RandomAccessFile out=null;
+    
+    //protected static final int INITIALPAGEHASH=1024;
+    //protected static final int PAGESIZE=2048;
+    
+    protected static final int INITIALPAGEHASH=32;
+    protected static final int PAGESIZE=64;
+    
+        public PagedIndexTransactional(String filename) throws IOException{
+        atomicfields = factory.create();
+        
+        atomicfields.setStat_create_page(Long.valueOf(0));
+        atomicfields.setStat_page_branch(Long.valueOf(0));
+        atomicfields.setStat_page_next(Long.valueOf(0));
+        atomicfields.setStat_read(Long.valueOf(0));
+        atomicfields.setStat_write(Long.valueOf(0));
+        
+        this.atomicfields.setFilename(filename);
+        File ftest=new File(filename);
+        if(!ftest.exists())ftest.createNewFile();
+        out=new RandomAccessFile(filename,"rw");
+        atomicfields.setRoots(new AtomicArray<TableIndexPageTransactional>(TableIndexPageTransactional.class, INITIALPAGEHASH));
+       // System.out.println(filename);
+       // System.out.println(out.length());
+        if(out.length()>0){
+            for(int i=0;i<INITIALPAGEHASH;i++){
+                atomicfields.getRoots().set(i, new TableIndexPageTransactional(this,out));
+                atomicfields.getRoots().get(i).setFirst();
+               // System.out.println("In loop " + atomicfields.getRoots().get(i).getEndLocation());
+                out.seek(atomicfields.getRoots().get(i).getEndLocation());
+            }
+        }else{
+            for(int i=0;i<INITIALPAGEHASH;i++){
+                atomicfields.getRoots().set(i, TableIndexPageTransactional.createNewPage(this,out,PAGESIZE));
+                //     System.out.println("In Othe loop " + atomicfields.getRoots().get(i).getEndLocation());
+                atomicfields.getRoots().get(i).setFirst();
+            }
+        }
+    }
+    
+    public Hashtable<String,Long> readStatistics(){
+        Hashtable<String,Long> hash=new Hashtable<String,Long>();
+        hash.put("stat_index_read",atomicfields.getStat_read());
+        hash.put("stat_index_write",atomicfields.getStat_write());
+        hash.put("stat_index_create_page",atomicfields.getStat_create_page());
+        hash.put("stat_index_page_next",atomicfields.getStat_page_next());
+        hash.put("stat_index_page_branch",atomicfields.getStat_page_branch());
+        atomicfields.setStat_read((long)0);
+        atomicfields.setStat_write((long)0);
+        atomicfields.setStat_create_page((long)0);
+        atomicfields.setStat_page_next((long)0);
+        atomicfields.setStat_page_branch((long)0);
+        return hash;
+    }
+    
+    private int rootHash(String id){
+        return id.hashCode() & (INITIALPAGEHASH-1);
+    }
+    
+    private /*synchronized*/ TableIndexPageTransactional getFirstFreePage(String id) throws IOException{
+        return atomicfields.getRoots().get(rootHash(id)).getFirstFreePage(id, id.hashCode());
+    }
+    
+    private /*synchronized*/ long getOffset(String id) throws IOException{
+        if(atomicfields.getRoots()==null)return -1;
+        return atomicfields.getRoots().get(rootHash(id)).getOffset(id,id.hashCode());
+    }
+    
+    public /*synchronized*/ void updateEntry(String id,int rowsize,int location,long position) throws IOException{
+        long offset=getOffset(id);
+        out.seek(offset);
+        TableIndexEntryTransactional entry=new TableIndexEntryTransactional(id,rowsize,location,position);
+        entry.updateData(out);
+        atomicfields.setStat_write(atomicfields.getStat_write()+1);
+    }
+    
+    public synchronized void updateEntryTransactional(String id,int rowsize,int location,long position) throws IOException{
+        final String id2 = id;
+        final int rowsize2 = rowsize;
+        final int location2 = location;
+        final long position2 = position;
+        
+        Thread.doIt(new Callable<Boolean>() {
+           public Boolean call() throws Exception{
+                long offset=getOffset(id2);
+                out.seek(offset);
+                TableIndexEntryTransactional entry=new TableIndexEntryTransactional(id2,rowsize2,location2,position2);
+                entry.updateData(out);
+                atomicfields.setStat_write(atomicfields.getStat_write()+1);
+                return true;
+           }
+        });
+    }
+    
+    public /*synchronized*/ void addEntry(String id,int rowsize,int location,long position) throws IOException{
+        TableIndexPageTransactional page=getFirstFreePage(id);
+        page.addEntry(id,rowsize,location,position);
+        atomicfields.setStat_write(atomicfields.getStat_write()+1);
+    }
+    public /*synchronized*/ TableIndexEntryTransactional scanIndex(String id) throws IOException{
+        if(atomicfields.getRoots()==null)return null;
+        return atomicfields.getRoots().get(rootHash(id)).scanIndex(id,id.hashCode());
+    }
+    
+    public synchronized TableIndexEntryTransactional scanIndexTransactional(String id) throws IOException{
+        final String id2 = id;
+        return Thread.doIt(new Callable<TableIndexEntryTransactional>() {
+           public TableIndexEntryTransactional call() throws Exception{
+                if(atomicfields.getRoots()==null)return null;
+                    return atomicfields.getRoots().get(rootHash(id2)).scanIndex(id2,id2.hashCode());
+            }
+        });
+    }
+    
+    public synchronized List<TableIndexEntryTransactional> scanIndex(List<String> rows) throws IOException{
+        final List<String> rows2 = rows;
+        return Thread.doIt(new Callable<List<TableIndexEntryTransactional>>() {
+           public List<TableIndexEntryTransactional> call() throws Exception{
+                List<TableIndexEntryTransactional> lst=new ArrayList<TableIndexEntryTransactional>();
+                for(int i=0;i<rows2.size();i++){
+                    String id=rows2.get(i);
+                    TableIndexEntryTransactional entry=scanIndex(id);
+                    if(entry!=null){
+                        if(entry.getLocation()!=TableTransactional.DELETE)lst.add(entry);
+                    }
+                }
+                return lst;
+           }
+        });
+    }
+    public synchronized List<TableIndexEntryTransactional> scanIndex() throws IOException{
+        return Thread.doIt(new Callable<List<TableIndexEntryTransactional>>() {
+           public List<TableIndexEntryTransactional> call() throws Exception{
+                ArrayList<TableIndexEntryTransactional> lst=new ArrayList<TableIndexEntryTransactional>();
+                System.out.println(Thread.currentThread() + " start");
+                for(int i=0;i<INITIALPAGEHASH;i++){
+                    atomicfields.getRoots().get(i).addEntriesToList(lst);
+                }
+                System.out.println(Thread.currentThread() +" done");
+                return lst;
+           }
+        });
+    }
+    public void close(){
+        try{
+            if(out!=null){
+                out.close();
+            }
+        }catch(Exception e){}
+    }
+}
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/Row.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/Row.java
new file mode 100644 (file)
index 0000000..52b9bbf
--- /dev/null
@@ -0,0 +1,400 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.solidosystems.tuplesoup.core;
+import java.io.*;
+import java.util.*;
+import java.nio.channels.*;
+
+/**
+ * Holds a row of data
+ */
+public class Row{
+     private String id;
+     private int size;
+     private Hashtable<String,Value> values;
+    
+     /**
+      * Creates a new empty row with the given row id.
+      */
+     public Row(String id){
+         this.id=id;
+         size=-1;
+         values=new Hashtable<String,Value>();
+     }
+     
+     /**
+      * Returns the number of keys in this row.
+      */
+     public int getKeyCount(){
+         return values.size();
+     }
+     
+     public Set<String> keySet(){
+         return values.keySet();
+     }
+     
+     /**
+      * Returns the actual size in bytes this row will take when written to a stream.
+      */
+     public int getSize(){
+         if(size==-1)recalcSize();
+         return size;
+     }
+
+     /**
+      * Returns a hashcode for this row. This hashcode will be based purely on the id of the row.
+      */
+     public int hashCode(){
+         return id.hashCode();
+     }
+     public boolean equals(Object obj){
+         try{
+             Row r=(Row)obj;
+             return r.id.equals(id);
+         }catch(Exception e){}
+         return false;
+     }
+     /**
+      * Returns the id of this row.
+      */
+     public String getId(){
+         return id;
+     }
+     /**
+      * Stores the given value for the given key.
+      */
+     public void put(String key,Value value){
+         size=-1;
+         values.put(key,value);
+     }
+     
+     /**
+      * Stores the given string wrapped in a value object for the given key.
+      */
+     public void put(String key,String value){
+         size=-1;
+         values.put(key,new Value(value));
+     }
+     
+     /**
+      * Stores the given int wrapped in a value object for the given key.
+      */
+     public void put(String key,int value){
+         size=-1;
+         values.put(key,new Value(value));
+     }
+     
+     /**
+      * Stores the given long wrapped in a value object for the given key.
+      */
+     public void put(String key,long value){
+         size=-1;
+         values.put(key,new Value(value));
+     }
+     
+     /**
+      * Stores the given float wrapped in a value object for the given key.
+      */
+     public void put(String key,float value){
+         size=-1;
+         values.put(key,new Value(value));
+     }
+     
+     /**
+      * Stores the given double wrapped in a value object for the given key.
+      */
+     public void put(String key,double value){
+         size=-1;
+         values.put(key,new Value(value));
+     }
+     
+     /**
+      * Stores the given boolean wrapped in a value object for the given key.
+      */
+     public void put(String key,boolean value){
+         size=-1;
+         values.put(key,new Value(value));
+     }
+     
+     /**
+      * Stores the given Date wrapped in a value object for the given key.
+      */
+     public void put(String key,Date value){
+         size=-1;
+         values.put(key,new Value(value));
+     }
+     
+     /**
+      * Returns the value stored for the current key, or a null value (not null) if the key does not exist.
+      */
+     public Value get(String key){
+         if(!values.containsKey(key))return new Value();
+         return values.get(key);
+     }
+     
+     /**
+      * Returns a string representation of the value stored for the current key.
+      * If the key does not exist, an empty string will be returned.
+      * See the documentation for Value to learn how the string value is generated.
+      */
+     public String getString(String key){
+         if(!values.containsKey(key))return "";
+         return values.get(key).getString();
+     }
+     
+     /**
+      * Returns an int representation of the value stored for the current key.
+      * If the key does not exist, 0 will be returned.
+      * See the documentation for Value to learn how the string value is generated.
+      */
+     public int getInt(String key){
+         if(!values.containsKey(key))return 0;
+          return values.get(key).getInt();
+     }
+     
+     /**
+      * Returns a long representation of the value stored for the current key.
+      * If the key does not exist, 0 will be returned.
+      * See the documentation for Value to learn how the string value is generated.
+      */
+     public long getLong(String key){
+         if(!values.containsKey(key))return 0;
+          return values.get(key).getLong();
+     }
+     
+     /**
+      * Returns a float representation of the value stored for the current key.
+      * If the key does not exist, 0 will be returned.
+      * See the documentation for Value to learn how the string value is generated.
+      */
+     public float getFloat(String key){
+         if(!values.containsKey(key))return 0f;
+          return values.get(key).getFloat();
+     }
+     
+     /**
+      * Returns a double representation of the value stored for the current key.
+      * If the key does not exist, 0 will be returned.
+      * See the documentation for Value to learn how the string value is generated.
+      */
+     public double getDouble(String key){
+         if(!values.containsKey(key))return 0d;
+          return values.get(key).getDouble();
+     }
+     
+     /**
+      * Returns a boolean representation of the value stored for the current key.
+      * If the key does not exist, false will be returned.
+      * See the documentation for Value to learn how the string value is generated.
+      */
+     public boolean getBoolean(String key){
+         if(!values.containsKey(key))return false;
+          return values.get(key).getBoolean();
+     }
+     
+     /**
+      * Returns a Date representation of the value stored for the current key.
+      * If the key does not exist, the date initialized with 0 will be returned.
+      * See the documentation for Value to learn how the string value is generated.
+      */
+     public Date getTimestamp(String key){
+         if(!values.containsKey(key))return new Date(0);
+          return values.get(key).getTimestamp();
+      }
+     /**
+      * Utility function to calculate the distance between ints, allowing for a single wraparound.
+      */
+     protected static int calcSize(int pre,int post){
+         if(post>pre)return post-pre;
+         return (Integer.MAX_VALUE-pre)+post;
+     }
+    
+     /**
+      * Recalculate the size of the row. Be aware that this method will actually write the full row to a buffer to calculate the size.
+      * Its a slow and memory consuming method to call!
+      */
+     private void recalcSize(){
+         try{
+             ByteArrayOutputStream bout=new ByteArrayOutputStream();
+             DataOutputStream dout=new DataOutputStream(bout);
+             writeToStream(dout);
+             size=bout.size();
+             dout.close();
+             bout.close();
+         }catch(Exception e){}
+     }
+    
+     /**
+      * Writes the contents of this row to the given RandomAccessFile
+      */
+     public void writeToFile(RandomAccessFile out) throws IOException{
+          long pre=out.getFilePointer();
+          
+          out.writeUTF(id);
+          
+          Set<String> keys=values.keySet();
+          out.writeInt(keys.size());
+          Iterator<String> it=keys.iterator();
+          while(it.hasNext()){
+              String key=it.next();
+             Value value=values.get(key);
+              out.writeUTF(key);
+              value.writeToFile(out);
+          }
+          long post=out.getFilePointer();
+          int size=(int)(post-pre);
+          this.size=size+4;
+          out.writeInt(this.size);
+      }
+      /**
+       * Writes the contents of this row to the given DataOutputStream.
+       */
+      public void writeToStream(DataOutputStream out) throws IOException{
+         int pre=out.size();
+         out.writeUTF(id);
+         Set<String> keys=values.keySet();
+         out.writeInt(keys.size());
+         Iterator<String> it=keys.iterator();
+         while(it.hasNext()){
+             String key=it.next();
+             Value value=values.get(key);
+             out.writeUTF(key);
+             value.writeToStream(out);
+         }
+         int post=out.size();
+         int size=calcSize(pre,post);
+         this.size=size+4;
+         out.writeInt(this.size);
+     }
+     /**
+      * Reads a full row from the given DataInputStream and returns it.
+      */
+     public static Row readFromStream(DataInputStream in) throws IOException{
+         String id=in.readUTF();
+         Row row=new Row(id);
+         int size=in.readInt();
+         for(int i=0;i<size;i++){
+             String key=in.readUTF();
+             Value value=Value.readFromStream(in);
+             row.put(key,value);
+         }
+         size=in.readInt();
+         row.size=size;
+         return row;
+     }
+     /**
+      * Returns a string representing this row formatted as the following example:
+      * (1732)=>{"name":string:"Kasper J. Jeppesen","age":int:31}
+      *
+      * @return a string representation of this row
+      */
+     public String toString(){
+         StringBuffer buf=new StringBuffer();
+         buf.append("("+id+")=>{");
+         Iterator<String> it=values.keySet().iterator();
+         boolean first=true;
+         while(it.hasNext()){
+             if(!first){
+                 buf.append(",");
+             }else{
+                 first=false;
+             }
+             String key=it.next();
+             buf.append("\"");
+             buf.append(key);
+             buf.append("\":");
+             Value value=values.get(key);
+             buf.append(value.getTypeName());
+             buf.append(":");
+             if(value.getType()==Value.STRING){
+                buf.append("\"");
+                // TODO: This string should be escaped properly
+                buf.append(value.getString());
+                buf.append("\"");
+             }else{
+                 buf.append(value.getString());
+             }
+         }
+         buf.append("}");
+         return buf.toString();
+     }
+     
+     /**
+      * Shorthand for calling toBasicXMLString("")
+      */
+     public String toBasicXMLString(){
+         return toBasicXMLString("");
+     }
+     
+     /**
+      * Creates an indentation of the given size and calls toBasicXMLString(String) with the indentation string as parameter.
+      */
+     public String toBasicXMLString(int indentation){
+         StringBuffer buf=new StringBuffer();
+         for(int i=0;i<indentation;i++){
+             buf.append(" ");
+         }
+         return toBasicXMLString(buf.toString());
+     }
+     
+     /**
+      * Creates a basic xml representation of the row as shown in the following sample:
+      * &lt;row id="1"&gt;
+      *   &lt;value name="foo" type="string"&gt;Bar&lt;/value&gt;
+      * &lt;/row&gt;
+      */
+     public String toBasicXMLString(String indentation){
+         StringBuffer buf=new StringBuffer();
+         buf.append(indentation);
+         buf.append("<row id=\""+id+"\">\n");
+         Iterator<String> it=values.keySet().iterator();
+         while(it.hasNext()){
+             String key=it.next();
+             Value value=values.get(key);
+             buf.append(indentation);
+             buf.append("   ");
+             buf.append(value.toBasicXMLString(key));
+             buf.append("\n");
+         }
+         buf.append(indentation);
+         buf.append("</row>\n");
+         return buf.toString();
+     }
+ }
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/RowMatcher.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/RowMatcher.java
new file mode 100644 (file)
index 0000000..1debd7b
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+ package com.solidosystems.tuplesoup.core;
+ import java.io.*;
+ import java.util.*;
+
+public class RowMatcher{
+    public final static int LESSTHAN=0;
+    public final static int EQUALS=1;
+    public final static int GREATERTHAN=2;
+    public final static int STARTSWITH=3;
+    public final static int ENDSWITH=4;
+    public final static int CONTAINS=5;
+    public final static int ISNULL=6;
+    
+    public final static int NOT=7;
+    public final static int OR=8;
+    public final static int AND=9;
+    public final static int XOR=10;
+    
+    private String key=null;
+    private Value value=null;
+    private int type=-1;
+    
+    private RowMatcher match1=null;
+    private RowMatcher match2=null;
+    
+    public RowMatcher(String key,int type,Value value){
+        this.key=key;
+        this.type=type;
+        this.value=value;
+    }
+    
+    public RowMatcher(String key,int type){
+        this.key=key;
+        this.type=type;
+    }
+    
+    public RowMatcher(RowMatcher match1,int type,RowMatcher match2){
+        this.match1=match1;
+        this.type=type;
+        this.match2=match2;
+    }
+    
+    public RowMatcher(int type,RowMatcher match1){
+        this.match1=match1;
+        this.type=type;
+    }
+
+    /**
+     * This method needs to be seriously optimized... especially the XOR method
+     */
+    public boolean matches(Row row){
+        if(value!=null){
+            Value compare=row.get(key);
+            switch(type){
+                case LESSTHAN   : return compare.lessThan(value);
+                case EQUALS     : return compare.equals(value);
+                case GREATERTHAN: return compare.greaterThan(value);
+                case STARTSWITH : return compare.startsWith(value);
+                case ENDSWITH   : return compare.endsWith(value);
+                case CONTAINS   : return compare.contains(value);
+            }
+        }else if(type==ISNULL){
+            Value compare=row.get(key);
+            return compare.isNull();
+        }else if((type==AND)||(type==OR)||(type==XOR)){
+            switch(type){
+                case AND        : return match1.matches(row)&&match2.matches(row);
+                case OR         : return match1.matches(row)||match2.matches(row);
+                case XOR        : return (match1.matches(row)||match2.matches(row))&&(!(match1.matches(row)&&match2.matches(row)));
+            }
+        }else if(type==NOT){
+            return !match1.matches(row);
+        }
+        return false;
+    }
+}
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/RowMatcherTransactional.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/RowMatcherTransactional.java
new file mode 100644 (file)
index 0000000..5cd94a5
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+ package com.solidosystems.tuplesoup.core;
+ import java.io.*;
+ import java.util.*;
+
+public class RowMatcherTransactional{
+    public final static int LESSTHAN=0;
+    public final static int EQUALS=1;
+    public final static int GREATERTHAN=2;
+    public final static int STARTSWITH=3;
+    public final static int ENDSWITH=4;
+    public final static int CONTAINS=5;
+    public final static int ISNULL=6;
+    
+    public final static int NOT=7;
+    public final static int OR=8;
+    public final static int AND=9;
+    public final static int XOR=10;
+    
+    private String key=null;
+    private ValueTransactional value=null;
+    private int type=-1;
+    
+    private RowMatcherTransactional match1=null;
+    private RowMatcherTransactional match2=null;
+    
+    public RowMatcherTransactional(String key,int type,ValueTransactional value){
+        this.key=key;
+        this.type=type;
+        this.value=value;
+    }
+    
+    public RowMatcherTransactional(String key,int type){
+        this.key=key;
+        this.type=type;
+    }
+    
+    public RowMatcherTransactional(RowMatcherTransactional match1,int type,RowMatcherTransactional match2){
+        this.match1=match1;
+        this.type=type;
+        this.match2=match2;
+    }
+    
+    public RowMatcherTransactional(int type,RowMatcherTransactional match1){
+        this.match1=match1;
+        this.type=type;
+    }
+
+    /**
+     * This method needs to be seriously optimized... especially the XOR method
+     */
+    public boolean matches(RowTransactional row){
+        if(value!=null){
+            ValueTransactional compare=row.get(key);
+            switch(type){
+                case LESSTHAN   : return compare.lessThan(value);
+                case EQUALS     : return compare.equals(value);
+                case GREATERTHAN: return compare.greaterThan(value);
+                case STARTSWITH : return compare.startsWith(value);
+                case ENDSWITH   : return compare.endsWith(value);
+                case CONTAINS   : return compare.contains(value);
+            }
+        }else if(type==ISNULL){
+            ValueTransactional compare=row.get(key);
+            return compare.isNull();
+        }else if((type==AND)||(type==OR)||(type==XOR)){
+            switch(type){
+                case AND        : return match1.matches(row)&&match2.matches(row);
+                case OR         : return match1.matches(row)||match2.matches(row);
+                case XOR        : return (match1.matches(row)||match2.matches(row))&&(!(match1.matches(row)&&match2.matches(row)));
+            }
+        }else if(type==NOT){
+            return !match1.matches(row);
+        }
+        return false;
+    }
+}
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/RowTransactional.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/RowTransactional.java
new file mode 100644 (file)
index 0000000..1fc84a0
--- /dev/null
@@ -0,0 +1,398 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package com.solidosystems.tuplesoup.core;
+
+import dstm2.atomic;
+import dstm2.Thread;
+import dstm2.factory.Factory;
+import dstm2.util.StringKeyHashMap;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+/**
+ *
+ * @author navid
+ */
+public class RowTransactional {
+     Factory<RowTSInf> factory = Thread.makeFactory(RowTSInf.class);
+     
+     private String id;
+    // private int size;
+     RowTSInf atomicfields;
+     private StringKeyHashMap<ValueTransactional> values;
+     
+     public @atomic interface RowTSInf{
+        int getSize();
+        void setSize(int val);
+     }
+     
+     public RowTransactional(String id){
+         atomicfields = factory.create();
+         
+         this.id=id;
+         atomicfields.setSize(-1);
+         values=new StringKeyHashMap<ValueTransactional>();
+     }
+     
+     /**
+      * Returns the number of keys in this row.
+      */
+     public int getKeyCount(){
+         return values.size();
+     }
+     
+     public Set keySet(){
+         return values.entrySet();
+     }
+     
+     /**
+      * Returns the actual size in bytes this row will take when written to a stream.
+      */
+     public int getSize(){
+         if(atomicfields.getSize()==-1)recalcSize();
+         return atomicfields.getSize();
+     }
+
+     /**
+      * Returns a hashcode for this row. This hashcode will be based purely on the id of the row.
+      */
+     public int hashCode(){
+         return id.hashCode();
+     }
+     public boolean equals(Object obj){
+         try{
+             RowTransactional r=(RowTransactional)obj;
+             return r.id.equals(id);
+         }catch(Exception e){}
+         return false;
+     }
+     /**
+      * Returns the id of this row.
+      */
+     public String getId(){
+         return id;
+     }
+     /**
+      * Stores the given value for the given key.
+      */
+     public void put(String key,ValueTransactional value){
+         atomicfields.setSize(-1);
+         values.put(key,value);
+     }
+     
+     /**
+      * Stores the given string wrapped in a value object for the given key.
+      */
+     public void put(String key,String value){
+         atomicfields.setSize(-1);
+         values.put(key,new ValueTransactional(value));
+     }
+     
+     /**
+      * Stores the given int wrapped in a value object for the given key.
+      */
+     public void put(String key,int value){
+         atomicfields.setSize(-1);
+         values.put(key,new ValueTransactional(value));
+     }
+     
+     /**
+      * Stores the given long wrapped in a value object for the given key.
+      */
+     public void put(String key,long value){
+         atomicfields.setSize(-1);
+         values.put(key,new ValueTransactional(value));
+     }
+     
+     /**
+      * Stores the given float wrapped in a value object for the given key.
+      */
+     public void put(String key,float value){
+         atomicfields.setSize(-1);
+         values.put(key,new ValueTransactional(value));
+     }
+     
+     /**
+      * Stores the given double wrapped in a value object for the given key.
+      */
+     public void put(String key,double value){
+         atomicfields.setSize(-1);
+         values.put(key,new ValueTransactional(value));
+     }
+     
+     /**
+      * Stores the given boolean wrapped in a value object for the given key.
+      */
+     public void put(String key,boolean value){
+         atomicfields.setSize(-1);
+         values.put(key,new ValueTransactional(value));
+     }
+     
+     /**
+      * Stores the given Date wrapped in a value object for the given key.
+      */
+     public void put(String key,Date value){
+         atomicfields.setSize(-1);
+         values.put(key,new ValueTransactional(value));
+     }
+     
+     /**
+      * Returns the value stored for the current key, or a null value (not null) if the key does not exist.
+      */
+     public ValueTransactional get(String key){
+         if(!values.containsKey(key))return new ValueTransactional();
+         return values.get(key.hashCode());
+     }
+     
+     /**
+      * Returns a string representation of the value stored for the current key.
+      * If the key does not exist, an empty string will be returned.
+      * See the documentation for Value to learn how the string value is generated.
+      */
+     public String getString(String key){
+         if(!values.containsKey(key))return "";
+         return values.get(key.hashCode()).getString();
+     }
+     
+     /**
+      * Returns an int representation of the value stored for the current key.
+      * If the key does not exist, 0 will be returned.
+      * See the documentation for Value to learn how the string value is generated.
+      */
+     public int getInt(String key){
+         if(!values.containsKey(key))return 0;
+          return values.get(key.hashCode()).getInt();
+     }
+     
+     /**
+      * Returns a long representation of the value stored for the current key.
+      * If the key does not exist, 0 will be returned.
+      * See the documentation for Value to learn how the string value is generated.
+      */
+     public long getLong(String key){
+         if(!values.containsKey(key))return 0;
+          return values.get(key.hashCode()).getLong();
+     }
+     
+     /**
+      * Returns a float representation of the value stored for the current key.
+      * If the key does not exist, 0 will be returned.
+      * See the documentation for Value to learn how the string value is generated.
+      */
+     public float getFloat(String key){
+         if(!values.containsKey(key))return 0f;
+          return values.get(key.hashCode()).getFloat();
+     }
+     
+     /**
+      * Returns a double representation of the value stored for the current key.
+      * If the key does not exist, 0 will be returned.
+      * See the documentation for Value to learn how the string value is generated.
+      */
+     public double getDouble(String key){
+         if(!values.containsKey(key))return 0d;
+          return values.get(key.hashCode()).getDouble();
+     }
+     
+     /**
+      * Returns a boolean representation of the value stored for the current key.
+      * If the key does not exist, false will be returned.
+      * See the documentation for Value to learn how the string value is generated.
+      */
+     public boolean getBoolean(String key){
+         if(!values.containsKey(key))return false;
+          return values.get(key.hashCode()).getBoolean();
+     }
+     
+     /**
+      * Returns a Date representation of the value stored for the current key.
+      * If the key does not exist, the date initialized with 0 will be returned.
+      * See the documentation for Value to learn how the string value is generated.
+      */
+     public Date getTimestamp(String key){
+         if(!values.containsKey(key))return new Date(0);
+          return values.get(key.hashCode()).getTimestamp();
+      }
+     /**
+      * Utility function to calculate the distance between ints, allowing for a single wraparound.
+      */
+     protected static int calcSize(int pre,int post){
+         if(post>pre)return post-pre;
+         return (Integer.MAX_VALUE-pre)+post;
+     }
+    
+     /**
+      * Recalculate the size of the row. Be aware that this method will actually write the full row to a buffer to calculate the size.
+      * Its a slow and memory consuming method to call!
+      */
+     private void recalcSize(){
+         try{
+             ByteArrayOutputStream bout=new ByteArrayOutputStream();
+             DataOutputStream dout=new DataOutputStream(bout);
+             writeToStream(dout);
+             this.atomicfields.setSize(bout.size());
+             dout.close();
+             bout.close();
+         }catch(Exception e){}
+     }
+    
+     /**
+      * Writes the contents of this row to the given RandomAccessFile
+      */
+     public void writeToFile(RandomAccessFile out) throws IOException{
+          long pre=out.getFilePointer();
+          
+          out.writeUTF(id);
+          
+          Set<StringKeyHashMap.TEntry<ValueTransactional>> pairs=values.entrySet(); 
+          out.writeInt(pairs.size());
+          Iterator<StringKeyHashMap.TEntry<ValueTransactional>> it= pairs.iterator();
+          while(it.hasNext()){
+             String key= it.next().getKey();
+             ValueTransactional value= values.get(key);
+             out.writeUTF(key);
+             value.writeToFile(out);
+          }
+          
+          long post=out.getFilePointer();
+          int size=(int)(post-pre);
+          this.atomicfields.setSize(size+4);
+          out.writeInt(this.atomicfields.getSize());
+      }
+      /**
+       * Writes the contents of this row to the given DataOutputStream.
+       */
+      public void writeToStream(DataOutputStream out) throws IOException{
+         int pre=out.size();
+         out.writeUTF(id);
+         Set<StringKeyHashMap.TEntry<ValueTransactional>> pairs=values.entrySet();
+         out.writeInt(pairs.size());
+         
+         Iterator<StringKeyHashMap.TEntry<ValueTransactional>> it=pairs.iterator();
+         while(it.hasNext()){
+             String key=it.next().getKey();
+             ValueTransactional value=values.get(key);
+             out.writeUTF(key);
+             value.writeToStream(out);
+         }
+         int post=out.size();
+         int size=calcSize(pre,post);
+         this.atomicfields.setSize(size+4);
+         out.writeInt(this.atomicfields.getSize());
+     }
+     /**
+      * Reads a full row from the given DataInputStream and returns it.
+      */
+     public static RowTransactional readFromStream(DataInputStream in) throws IOException{
+         String id=in.readUTF();
+         //System.out.println("id " + id);
+         RowTransactional row=new RowTransactional(id);
+         int size=in.readInt();
+         for(int i=0;i<size;i++){
+             String key=in.readUTF();
+             ValueTransactional value=ValueTransactional.readFromStream(in);
+             row.put(key,value);
+         }
+         size=in.readInt();
+         row.atomicfields.setSize(size);
+         return row;
+     }
+     
+     
+     /**
+      * Returns a string representing this row formatted as the following example:
+      * (1732)=>{"name":string:"Kasper J. Jeppesen","age":int:31}
+      *
+      * @return a string representation of this row
+      */
+     public String toString(){
+         StringBuffer buf=new StringBuffer();
+         buf.append("("+id+")=>{");
+         Iterator<StringKeyHashMap.TEntry<ValueTransactional>> it=values.entrySet().iterator();
+         boolean first=true;
+         while(it.hasNext()){
+             if(!first){
+                 buf.append(",");
+             }else{
+                 first=false;
+             }
+             String key=it.next().getKey();
+             buf.append("\"");
+             buf.append(key);
+             buf.append("\":");
+             ValueTransactional value=values.get(key);
+             buf.append(value.getTypeName());
+             buf.append(":");
+             if(value.getType()==Value.STRING){
+                buf.append("\"");
+                // TODO: This string should be escaped properly
+                buf.append(value.getString());
+                buf.append("\"");
+             }else{
+                 buf.append(value.getString());
+             }
+         }
+         buf.append("}");
+         return buf.toString();
+     }
+     
+     /**
+      * Shorthand for calling toBasicXMLString("")
+      */
+     public String toBasicXMLString(){
+         return toBasicXMLString("");
+     }
+     
+     /**
+      * Creates an indentation of the given size and calls toBasicXMLString(String) with the indentation string as parameter.
+      */
+     public String toBasicXMLString(int indentation){
+         StringBuffer buf=new StringBuffer();
+         for(int i=0;i<indentation;i++){
+             buf.append(" ");
+         }
+         return toBasicXMLString(buf.toString());
+     }
+     
+     /**
+      * Creates a basic xml representation of the row as shown in the following sample:
+      * &lt;row id="1"&gt;
+      *   &lt;value name="foo" type="string"&gt;Bar&lt;/value&gt;
+      * &lt;/row&gt;
+      */
+     public String toBasicXMLString(String indentation){
+         StringBuffer buf=new StringBuffer();
+         buf.append(indentation);
+         buf.append("<row id=\""+id+"\">\n");
+         Iterator<StringKeyHashMap.TEntry<ValueTransactional>> it=values.entrySet().iterator();
+         while(it.hasNext()){
+             String key=it.next().getKey();
+             ValueTransactional value=values.get(key);
+             buf.append(indentation);
+             buf.append("   ");
+             buf.append(value.toBasicXMLString(key));
+             buf.append("\n");
+         }
+         buf.append(indentation);
+         buf.append("</row>\n");
+         return buf.toString();
+     }
+
+}
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/Table.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/Table.java
new file mode 100644 (file)
index 0000000..5ff49fa
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.solidosystems.tuplesoup.core;
+import java.io.*;
+import java.util.*;
+import java.nio.channels.*;
+import com.solidosystems.tuplesoup.filter.*;
+
+/**
+ * The table stores a group of rows.
+ * Every row must have a unique id within a table.
+ */
+public interface Table{
+    // Index type constants
+    public static final int MEMORY=0;
+    public static final int FLAT=1;
+    public static final int PAGED=2;
+     
+    // Row location constants
+    public static final int FILEA=0;
+    public static final int FILEB=1;
+    public static final int DELETE=2;
+    public static final int INDEX=3;
+     
+    /**
+     * Return the current values of the statistic counters and reset them.
+     * The current counters are:
+     * <ul>
+     *   <li>stat_table_add
+     *   <li>stat_table_update
+     *   <li>stat_table_delete
+     *   <li>stat_table_add_size
+     *   <li>stat_table_update_size
+     *   <li>stat_table_read_size
+     *   <li>stat_table_read
+     *   <li>stat_table_cache_hit
+     *   <li>stat_table_cache_miss
+     *   <li>stat_table_cache_drop
+     * </ul>
+     * Furthermore, the index will be asked to deliver separate index specific counters
+     */
+    public Hashtable<String,Long> readStatistics();
+
+    /**
+     * Set the maximal allowable size of the index cache.
+     */ 
+    public void setIndexCacheSize(int newsize);
+
+    /**
+     * Close all open file streams
+     */
+    public void close();
+
+    /** 
+     * Returns the name of this table
+     */ 
+    public String getTitle();
+    
+    /**
+     * Returns the location of this tables datafiles
+     */ 
+    public String getLocation();
+    
+    /**
+     * Delete the files created by this table object.
+     * Be aware that this will delete any data stored in this table!
+     */ 
+    public void deleteFiles();
+     
+    /**
+     * Adds a row of data to this table.
+     */
+    public void addRow(Row row) throws IOException;
+    
+     /**
+      * Adds a row to this table if it doesn't already exist, if it does it updates the row instead.
+      * This method is much slower than directly using add or update, so only use it if you don't know wether or not the row already exists.
+      */
+     public void addOrUpdateRow(Row row) throws IOException;
+     
+     /**
+      * Updates a row stored in this table.
+      */
+     public void updateRow(Row row) throws IOException;
+     
+     /**
+      * Marks a row as deleted in the index.
+      * Be aware that the space consumed by the row is not actually reclaimed.
+      */
+     public void deleteRow(Row row) throws IOException;
+     
+     /**
+      * Returns a tuplestream containing the given list of rows
+      */
+     public TupleStream getRows(List<String> rows) throws IOException;
+     
+     /**
+      * Returns a tuplestream containing the rows matching the given rowmatcher
+      */
+     public TupleStream getRows(RowMatcher matcher) throws IOException;
+     
+     /**
+      * Returns a tuplestream containing those rows in the given list that matches the given RowMatcher
+      */
+     public TupleStream getRows(List<String> rows,RowMatcher matcher) throws IOException;
+     
+     /**
+      * Returns a tuplestream of all rows in this table.
+      */
+     public TupleStream getRows() throws IOException;
+     
+     /**
+      * Returns a single row stored in this table.
+      * If the row does not exist in the table, null will be returned.
+      */
+     public Row getRow(String id) throws IOException;
+ }
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TableIndex.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TableIndex.java
new file mode 100644 (file)
index 0000000..242f20a
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.solidosystems.tuplesoup.core;
+
+import dstm2.AtomicSuperClass;
+import java.util.*;
+import java.io.*;
+
+public interface TableIndex{
+    public Hashtable<String,Long> readStatistics();
+    public void updateEntry(String id,int rowsize,int location,long position) throws IOException;
+    public void addEntry(String id,int rowsize,int location,long position) throws IOException;
+    public TableIndexEntry scanIndex(String id) throws IOException;
+    public List<TableIndexEntry> scanIndex(List<String> rows) throws IOException;
+    public List<TableIndexEntry> scanIndex() throws IOException;
+    public void close();
+}
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TableIndexEntry.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TableIndexEntry.java
new file mode 100644 (file)
index 0000000..a944a6c
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.solidosystems.tuplesoup.core;
+
+import dstm2.atomic;
+import java.io.*;
+
+public class TableIndexEntry implements Comparable<TableIndexEntry>{
+    public String id;
+    public int location;
+    public long position;
+    private int size;
+    private int rowsize;
+    
+  
+    
+    public TableIndexEntry(String id,int rowsize,int location,long position){
+        this.id=id;
+        this.location=location;
+        this.position=position;
+        this.rowsize=rowsize;
+        size=-1;
+    }
+    public String getId(){
+        return id;
+    }
+    public void setPosition(long position){
+        this.position=position;
+    }
+    public long getPosition(){
+        return position;
+    }
+    public void setLocation(int location){
+        this.location=location;
+    }
+    public int getLocation(){
+        return location;
+    }
+    
+    public int getRowSize(){
+        return rowsize;
+    }
+    
+    public int compareTo(TableIndexEntry obj) throws ClassCastException{
+        TableIndexEntry ent=(TableIndexEntry)obj;
+        if(position<ent.position)return -1;
+        if(position==ent.position)return 0;
+        return 1;
+    }
+    
+    public boolean equals(Object obj){
+        try{
+            TableIndexEntry ent=(TableIndexEntry)obj;
+            if(ent.location==location){
+                if(ent.position==position){
+                    if(ent.id.equals(id)){
+                        return true;
+                    }
+                }
+            }
+        }catch(ClassCastException e){}
+        return false;
+    }
+    
+    public int getSize(){
+        if(size<0)calcSize();
+        return size;
+    }
+    public void setSize(int size){
+        this.size=size;
+    }
+    private void calcSize(){
+        try{
+            ByteArrayOutputStream bout=new ByteArrayOutputStream();
+            DataOutputStream dout=new DataOutputStream(bout);
+            dout.writeInt(id.hashCode());
+            dout.writeShort(id.length());
+            dout.writeChars(id);
+            dout.writeInt(rowsize);
+            dout.writeByte(location);
+            dout.writeLong(position);
+            setSize(bout.size());
+            dout.close();
+            bout.close();
+        }catch(Exception e){
+            e.printStackTrace();
+        }
+    }
+    
+    protected void writeData(RandomAccessFile out) throws IOException{
+        long pre=out.getFilePointer();
+        out.writeInt(id.hashCode());
+        out.writeShort(id.length());
+        out.writeChars(id);
+        out.writeInt(rowsize);
+        out.writeByte(location);
+        out.writeLong(position);
+        setSize((int)(out.getFilePointer()-pre));
+    }
+    protected void updateData(RandomAccessFile out) throws IOException{
+        long pre=out.getFilePointer();
+        out.skipBytes(4+2+id.length()*2);
+        out.writeInt(rowsize);
+        out.writeByte(location);
+        out.writeLong(position);
+        setSize((int)(out.getFilePointer()-pre));
+    }
+    protected void writeData(DataOutputStream out) throws IOException{
+        out.writeInt(id.hashCode());
+        out.writeShort(id.length());
+        out.writeChars(id);
+        out.writeInt(rowsize);
+        out.writeByte(location);
+        out.writeLong(position);
+    }
+    protected static TableIndexEntry readData(RandomAccessFile in) throws IOException{
+        long pre=in.getFilePointer();
+        in.readInt();
+        int num=in.readShort();
+        StringBuilder buf=new StringBuilder(num);
+        for(int i=0;i<num;i++){
+            buf.append(in.readChar());
+        }
+        String id=buf.toString();
+        int rowsize=in.readInt();
+        int location=in.readByte();
+        long position=in.readLong();
+        TableIndexEntry tmp=new TableIndexEntry(id,rowsize,location,position);
+        tmp.setSize((int)(in.getFilePointer()-pre));
+        return tmp;
+    }
+    
+    protected static TableIndexEntry readData(DataInputStream in) throws IOException{
+        in.readInt();
+        int num=in.readShort();
+        System.out.println("num=444444444444444444444444 " + num);
+        StringBuilder buf=new StringBuilder(num);
+        for(int i=0;i<num;i++){
+            buf.append(in.readChar());
+        }
+        String id=buf.toString();
+        int rowsize=in.readInt();
+        int location=in.readByte();
+        long position=in.readLong();
+        TableIndexEntry tmp=new TableIndexEntry(id,rowsize,location,position);
+        return tmp;
+    }
+    
+    protected static long scanForOffset(String id,DataInputStream in) throws IOException{
+        long offset=0;
+        int scanhash=id.hashCode();
+        try{
+            int datahash=in.readInt();
+            while(scanhash!=datahash){
+                int num=in.readShort();
+                in.skipBytes(1+4+8+num*2);
+                offset+=4+4+1+2+8+num*2;
+                datahash=in.readInt();
+            }
+            return offset;
+        }catch(EOFException e){}
+        return -1;
+    }
+    protected static TableIndexEntry lookForData(String id,DataInputStream in) throws IOException{
+        int scanhash=id.hashCode();
+        int datahash=in.readInt();
+        int num=in.readShort();
+        if(scanhash!=datahash){
+            in.skipBytes(4+1+8+num*2);
+            return null;
+        }
+        StringBuilder buf=new StringBuilder(num);
+        for(int i=0;i<num;i++){
+            buf.append(in.readChar());
+        }
+        String readid=buf.toString();
+        if(!readid.equals(id)){
+            in.skipBytes(4+1+8);
+            return null;
+        }
+        int rowsize=in.readInt();
+        int location=in.readByte();
+        long position=in.readLong();
+        TableIndexEntry tmp=new TableIndexEntry(id,rowsize,location,position);
+        return tmp;
+    }
+    protected static TableIndexEntry lookForData(String id,RandomAccessFile in) throws IOException{
+        int scanhash=id.hashCode();
+        int datahash=in.readInt();
+        int num=in.readShort();
+        if(scanhash!=datahash){
+            in.skipBytes(4+1+8+num*2);
+            return null;
+        }
+        StringBuilder buf=new StringBuilder(num);
+        for(int i=0;i<num;i++){
+            buf.append(in.readChar());
+        }
+        String readid=buf.toString();
+        if(!readid.equals(id)){
+            in.skipBytes(4+1+8);
+            return null;
+        }
+        int rowsize=in.readInt();
+        int location=in.readByte();
+        long position=in.readLong();
+        TableIndexEntry tmp=new TableIndexEntry(id,rowsize,location,position);
+        return tmp;
+    }
+}
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TableIndexEntryTransactional.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TableIndexEntryTransactional.java
new file mode 100644 (file)
index 0000000..8082d6f
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package com.solidosystems.tuplesoup.core;
+
+import dstm2.AtomicSuperClass;
+import dstm2.atomic;
+import dstm2.Thread;
+import dstm2.factory.Factory;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+/**
+ *
+ * @author navid
+ */
+public class TableIndexEntryTransactional implements AtomicSuperClass, Comparable<TableIndexEntryTransactional>{
+     
+    static Factory<TableIndexEntryTSInf> factory = Thread.makeFactory(TableIndexEntryTSInf.class);
+    
+    TableIndexEntryTSInf atomicfields;
+    public @atomic interface TableIndexEntryTSInf{
+        String getId();
+        Integer getLocation();
+        Long getPosition();
+        Integer getSize();
+        Integer getRowsize();
+        
+        void setId(String val);
+        void setLocation(Integer val);
+        void setPosition(Long val);
+        void setSize(Integer val);
+        void setRowsize(Integer val);
+    }
+       
+         
+    public TableIndexEntryTransactional(String id,int rowsize,int location,long position){
+        atomicfields = factory.create();
+        
+        this.atomicfields.setId(id);
+        this.atomicfields.setLocation(location);
+        this.atomicfields.setPosition(position);
+        this.atomicfields.setRowsize(rowsize);
+        this.atomicfields.setSize(-1);
+    }
+    public String getId(){
+        return atomicfields.getId();
+    }
+    public void setPosition(long position){
+        this.atomicfields.setPosition(position);
+    }
+    public long getPosition(){
+        return atomicfields.getPosition();
+    }
+    public void setLocation(int location){
+        this.atomicfields.setLocation(location);
+    }
+    public int getLocation(){
+        return atomicfields.getLocation();
+    }
+    
+    public int getRowSize(){
+        return atomicfields.getRowsize().intValue();
+    }
+    
+    public int compareTo(TableIndexEntryTransactional obj) throws ClassCastException{
+        TableIndexEntryTransactional ent=(TableIndexEntryTransactional)obj;
+        if(atomicfields.getPosition()<ent.atomicfields.getPosition()) return -1;
+        if(atomicfields.getPosition()==ent.atomicfields.getPosition()) return 0;
+        return 1;
+    }
+    
+    public boolean equals(Object obj){
+        try{
+            TableIndexEntryTransactional ent=(TableIndexEntryTransactional)obj;
+            if(ent.atomicfields.getLocation()==atomicfields.getLocation()){
+                if(ent.atomicfields.getPosition()==atomicfields.getPosition()){
+                    if(ent.atomicfields.getId().equals(atomicfields.getId())){
+                        return true;
+                    }
+                }
+            }
+        }catch(ClassCastException e){}
+        return false;
+    }
+    
+    public int getSize(){
+        if(atomicfields.getSize()<0) calcSize();
+        return atomicfields.getSize().intValue();
+    }
+    public void setSize(int size){
+        this.atomicfields.setSize(size);
+    }
+    private void calcSize(){
+        try{
+            ByteArrayOutputStream bout=new ByteArrayOutputStream();
+            DataOutputStream dout=new DataOutputStream(bout);
+            dout.writeInt(atomicfields.getId().hashCode());
+            dout.writeShort(atomicfields.getId().length());
+            dout.writeChars(atomicfields.getId());
+            dout.writeInt(atomicfields.getRowsize().intValue());
+            dout.writeByte(atomicfields.getLocation());
+            dout.writeLong(atomicfields.getPosition());
+            setSize(bout.size());
+            dout.close();
+            bout.close();
+        }catch(Exception e){
+            e.printStackTrace();
+        }
+    }
+    
+    protected void writeData(RandomAccessFile out) throws IOException{
+        long pre=out.getFilePointer();
+        out.writeInt(atomicfields.getId().hashCode());
+        out.writeShort(atomicfields.getId().length());
+        out.writeChars(atomicfields.getId());
+        out.writeInt(atomicfields.getRowsize().intValue());
+        out.writeByte(atomicfields.getLocation());
+        out.writeLong(atomicfields.getPosition());
+        setSize((int)(out.getFilePointer()-pre));
+    }
+    protected void updateData(RandomAccessFile out) throws IOException{
+        long pre=out.getFilePointer();
+        out.skipBytes(4+2+atomicfields.getId().length()*2);
+        out.writeInt(atomicfields.getRowsize().intValue());
+        out.writeByte(atomicfields.getLocation());
+        out.writeLong(atomicfields.getPosition());
+        setSize((int)(out.getFilePointer()-pre));
+    }
+    protected void writeData(DataOutputStream out) throws IOException{
+        out.writeInt(atomicfields.getId().hashCode());
+        out.writeShort(atomicfields.getId().length());
+        out.writeChars(atomicfields.getId());
+        out.writeInt(atomicfields.getRowsize().intValue());
+        out.writeByte(atomicfields.getLocation());
+        out.writeLong(atomicfields.getPosition());
+    }
+    protected static TableIndexEntryTransactional readData(RandomAccessFile in) throws IOException{
+        long pre=in.getFilePointer();
+        in.readInt();
+        //short num=in.readShort();
+        int num=in.readShort();
+        //System.out.println("num= " + num);
+        StringBuilder buf=new StringBuilder(num);
+        for(int i=0;i<num;i++){
+            buf.append(in.readChar());
+        }
+        String id=buf.toString();
+        int rowsize=in.readInt();
+        int location=in.readByte();
+        long position=in.readLong();
+        TableIndexEntryTransactional tmp=new TableIndexEntryTransactional(id,rowsize,location,position);
+        tmp.setSize((int)(in.getFilePointer()-pre));
+        return tmp;
+    }
+    
+    protected static TableIndexEntryTransactional readData(DataInputStream in) throws IOException{
+        in.readInt();
+        int num=in.readShort();
+        StringBuilder buf=new StringBuilder(num);
+        for(int i=0;i<num;i++){
+            buf.append(in.readChar());
+        }
+        String id=buf.toString();
+        int rowsize=in.readInt();
+        int location=in.readByte();
+        long position=in.readLong();
+        TableIndexEntryTransactional tmp=new TableIndexEntryTransactional(id,rowsize,location,position);
+        return tmp;
+    }
+    
+    protected static long scanForOffset(String id,DataInputStream in) throws IOException{
+        long offset=0;
+        int scanhash=id.hashCode();
+        try{
+            int datahash=in.readInt();
+            while(scanhash!=datahash){
+                int num=in.readShort();
+                in.skipBytes(1+4+8+num*2);
+                offset+=4+4+1+2+8+num*2;
+                datahash=in.readInt();
+            }
+            return offset;
+        }catch(EOFException e){}
+        return -1;
+    }
+    protected static TableIndexEntryTransactional lookForData(String id,DataInputStream in) throws IOException{
+        int scanhash=id.hashCode();
+        int datahash=in.readInt();
+        int num=in.readShort();
+        if(scanhash!=datahash){
+            in.skipBytes(4+1+8+num*2);
+            return null;
+        }
+        StringBuilder buf=new StringBuilder(num);
+        for(int i=0;i<num;i++){
+            buf.append(in.readChar());
+        }
+        String readid=buf.toString();
+        if(!readid.equals(id)){
+            in.skipBytes(4+1+8);
+            return null;
+        }
+        int rowsize=in.readInt();
+        int location=in.readByte();
+        long position=in.readLong();
+        TableIndexEntryTransactional tmp=new TableIndexEntryTransactional(id,rowsize,location,position);
+        return tmp;
+    }
+    protected static TableIndexEntryTransactional lookForData(String id,RandomAccessFile in) throws IOException{
+        int scanhash=id.hashCode();
+        int datahash=in.readInt();
+        int num=in.readShort();
+        if(scanhash!=datahash){
+            in.skipBytes(4+1+8+num*2);
+            return null;
+        }
+        StringBuilder buf=new StringBuilder(num);
+        for(int i=0;i<num;i++){
+            buf.append(in.readChar());
+        }
+        String readid=buf.toString();
+        if(!readid.equals(id)){
+            in.skipBytes(4+1+8);
+            return null;
+        }
+        int rowsize=in.readInt();
+        int location=in.readByte();
+        long position=in.readLong();
+        TableIndexEntryTransactional tmp=new TableIndexEntryTransactional(id,rowsize,location,position);
+        return tmp;
+    }
+}
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TableIndexNode.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TableIndexNode.java
new file mode 100644 (file)
index 0000000..c093219
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.solidosystems.tuplesoup.core;
+
+public class TableIndexNode{
+    private TableIndexNode previous;
+    private TableIndexEntry data;
+    private TableIndexNode next;
+    
+    public TableIndexNode(){
+        previous=null;
+        data=null;
+        next=null;
+    }
+    
+    public TableIndexNode(TableIndexEntry entry){
+        previous=null;
+        data=entry;
+        next=null;
+    }
+    public TableIndexNode(TableIndexNode prev,TableIndexEntry entry){
+        previous=prev;
+        data=entry;
+        next=null;
+    }
+    public TableIndexNode(TableIndexNode prev,TableIndexEntry entry,TableIndexNode nex){
+        previous=prev;
+        data=entry;
+        next=nex;
+    }
+    
+    public TableIndexEntry getData(){
+        return data;
+    }
+    public TableIndexNode getPrevious(){
+        return previous;
+    }
+    public TableIndexNode getNext(){
+        return next;
+    }
+    public void setNext(TableIndexNode node){
+        next=node;
+    }
+    public void setPrevious(TableIndexNode node){
+        previous=node;
+    }
+    public void setData(TableIndexEntry entry){
+        data=entry;
+    }
+    public void remove(){
+        if(previous!=null){
+            previous.setNext(next);
+        }
+        if(next!=null){
+            next.setPrevious(previous);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TableIndexNodeTransactional.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TableIndexNodeTransactional.java
new file mode 100644 (file)
index 0000000..9de2294
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package com.solidosystems.tuplesoup.core;
+
+import dstm2.AtomicSuperClass;
+import dstm2.atomic;
+import dstm2.Thread;
+import dstm2.factory.Factory;
+
+/**
+ *
+ * @author navid
+ */
+public class TableIndexNodeTransactional implements AtomicSuperClass{
+
+    //private TableIndexNodeTransactional previous;
+    //private TableIndexEntryTransactional data;
+    //private TableIndexNodeTransactional next;
+    static Factory<TableIndexInodeTSInf> factory = Thread.makeFactory(TableIndexInodeTSInf.class);
+    TableIndexInodeTSInf atomicfields;
+    
+    public @atomic interface TableIndexInodeTSInf{
+        TableIndexNodeTransactional getPrevious(); 
+        TableIndexEntryTransactional getData(); 
+        TableIndexNodeTransactional getNext(); 
+        
+        void setPrevious(TableIndexNodeTransactional val); 
+        void setData(TableIndexEntryTransactional val); 
+        void setNext(TableIndexNodeTransactional val);
+    }
+    
+    public TableIndexNodeTransactional(){
+        atomicfields = factory.create();
+        
+        atomicfields.setPrevious(null);
+        atomicfields.setData(null);
+        atomicfields.setNext(null);
+    }
+    
+    public TableIndexNodeTransactional(TableIndexEntryTransactional entry){
+        atomicfields = factory.create();
+        
+        atomicfields.setPrevious(null);
+        atomicfields.setData(entry);
+        atomicfields.setNext(null);
+        
+    }
+    
+    public TableIndexNodeTransactional(TableIndexNodeTransactional prev,TableIndexEntryTransactional entry){
+        atomicfields = factory.create();
+        
+        atomicfields.setPrevious(prev);
+        atomicfields.setData(entry);
+        atomicfields.setNext(null);
+    }
+    
+    public TableIndexNodeTransactional(TableIndexNodeTransactional prev,TableIndexEntryTransactional entry,TableIndexNodeTransactional nex){
+        atomicfields = factory.create();
+        
+        atomicfields.setPrevious(prev);
+        atomicfields.setData(entry);
+        atomicfields.setNext(nex);
+    }
+    
+    public TableIndexEntryTransactional getData(){
+        return atomicfields.getData();
+    }
+    public TableIndexNodeTransactional getPrevious(){
+        return atomicfields.getPrevious();
+    }
+    public TableIndexNodeTransactional getNext(){
+        return atomicfields.getNext();
+    }
+    public void setNext(TableIndexNodeTransactional node){
+        atomicfields.setNext(node);
+    }
+    public void setPrevious(TableIndexNodeTransactional node){
+        atomicfields.setPrevious(node);
+    }
+    public void setData(TableIndexEntryTransactional entry){
+        atomicfields.setData(entry);
+    }
+    public void remove(){
+        if(atomicfields.getPrevious()!=null){
+            atomicfields.getPrevious().setNext(atomicfields.getNext());
+        }
+        if(atomicfields.getNext()!=null){
+            atomicfields.getNext().setPrevious(atomicfields.getPrevious());
+        }
+    }
+}
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TableIndexPage.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TableIndexPage.java
new file mode 100644 (file)
index 0000000..f260cf2
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.solidosystems.tuplesoup.core;
+
+import java.io.*;
+import java.util.*;
+
+public class TableIndexPage{
+    private final static int BASEOFFSET=4+8+8+4+4;
+    private RandomAccessFile file=null;
+    
+    private long location=-1;
+    private int size=-1;
+    private long next=-1;
+    private long lower=-1;
+    private int offset=0;
+    
+    private int starthash=-1;
+    private int endhash=-1;
+    private boolean first=false;
+    
+    private TableIndexPage nextpage=null;
+    private TableIndexPage lowerpage=null;
+    
+    private PagedIndex index=null;
+    
+    public TableIndexPage(PagedIndex index,RandomAccessFile file) throws IOException{
+           this.file=file;
+        this.index=index;
+        first=false;
+        location=file.getFilePointer();
+        size=file.readInt();
+        next=file.readLong();
+        lower=file.readLong();
+        offset=file.readInt();
+        endhash=file.readInt();
+   //     System.out.println("si " + size);
+  //      System.out.println("next "  + next);
+   //     System.out.println("lower " + lower);
+   //     System.out.println("offset " + offset);
+   //     System.out.println("endhash " + endhash);
+        if(offset>0)starthash=file.readInt();
+   //     System.out.println("here tav;eindepage");
+        
+        
+    }
+    
+    public static TableIndexPage createNewPage(PagedIndex index,RandomAccessFile file,int size) throws IOException{
+        long pre=file.length();
+
+        file.setLength(file.length()+size+BASEOFFSET);
+        file.seek(pre);
+     
+        
+        file.writeInt(size); 
+        file.writeLong(-1l);
+        file.writeLong(-1l);
+        file.writeInt(0);
+        file.writeInt(-1);
+        file.seek(pre);
+        index.stat_create_page++;
+        return new TableIndexPage(index,file);
+    }
+    
+    public void setFirst(){
+        first=true;
+    }
+    
+    public long getLocation(){
+        return location;
+    }
+    public long getEndLocation(){
+        return location+size+BASEOFFSET;
+    }
+    
+    public String toString(){
+        StringBuffer buf=new StringBuffer();
+        buf.append("{\n");
+        buf.append("  location  "+location+"\n");
+        buf.append("  size      "+size+"\n");
+        buf.append("  next      "+next+"\n");
+        buf.append("  lower     "+lower+"\n");
+        buf.append("  offset    "+offset+"\n");
+        buf.append("  starthash "+starthash+"\n");
+        buf.append("  endhash "+endhash+"\n");
+        buf.append("}\n");
+        return buf.toString();
+    }
+    
+    private void updateMeta() throws IOException{
+        file.seek(location);
+        file.writeInt(size);
+        file.writeLong(next);
+        file.writeLong(lower);
+        file.writeInt(offset);
+        file.writeInt(endhash);
+    }
+    
+    public void addEntriesToList(List<TableIndexEntry> lst) throws IOException{
+        if(lower>-1){
+            if(lowerpage==null){
+                file.seek(lower);
+                lowerpage=new TableIndexPage(index,file);
+            }
+            lowerpage.addEntriesToList(lst);
+        }
+        if(next>-1){
+            if(nextpage==null){
+                file.seek(next);
+                nextpage=new TableIndexPage(index,file);
+            }
+            nextpage.addEntriesToList(lst);
+        }
+        file.seek(location+BASEOFFSET);
+        long pre=file.getFilePointer();
+        System.out.println(Thread.currentThread() + " " +offset + " " + pre);
+        while(file.getFilePointer()<pre+offset){
+            TableIndexEntry entry=TableIndexEntry.readData(file);
+            if(entry!=null){
+                if(entry.getLocation()!=Table.DELETE)lst.add(entry);
+            }
+        }
+    }
+    
+    public TableIndexEntry scanIndex(String id,int hashcode) throws IOException{
+        System.out.println("sacn index");
+        if(!first){
+              
+            if(hashcode<starthash){
+                if(lower==-1)return null;
+                if(lowerpage==null){
+                    file.seek(lower);
+                    lowerpage=new TableIndexPage(index,file);
+                }
+                index.stat_page_branch++;
+                return lowerpage.scanIndex(id,hashcode);
+            }
+        }
+        if(hashcode>endhash){
+            
+            if(next==-1)return null;
+            if(nextpage==null){
+                file.seek(next);
+                nextpage=new TableIndexPage(index,file);
+            }
+            index.stat_page_next++;
+            return nextpage.scanIndex(id,hashcode);
+        }
+        file.seek(location+BASEOFFSET);
+        long pre=file.getFilePointer();
+        while(file.getFilePointer()<pre+offset){
+            System.out.println("neddddxtex " + next);
+            TableIndexEntry entry=TableIndexEntry.lookForData(id,file);
+            if(entry!=null)return entry;
+        }
+        System.out.println("neddddxt " + next);
+        if(next==-1)return null;
+      
+        if(nextpage==null){
+            System.out.println("next " + next);
+            file.seek(next);
+            nextpage=new TableIndexPage(index,file);
+        }
+        index.stat_page_next++;
+        return nextpage.scanIndex(id,hashcode);
+    }
+    protected long getOffset(String id,int hashcode) throws IOException{
+        if(!first){
+            if(hashcode<starthash){
+                if(lower==-1)return -1;
+                if(lowerpage==null){
+                    file.seek(lower);
+                    lowerpage=new TableIndexPage(index,file);
+                }
+                index.stat_page_branch++;
+                return lowerpage.getOffset(id,hashcode);
+            }
+        }
+        if(hashcode>endhash){
+            if(next==-1)return -1;
+            if(nextpage==null){
+                file.seek(next);
+                nextpage=new TableIndexPage(index,file);
+            }
+            index.stat_page_next++;
+            return nextpage.getOffset(id,hashcode);
+        }
+        file.seek(location+BASEOFFSET);
+        long pre=file.getFilePointer();
+        while(file.getFilePointer()<pre+offset){
+            long prescan=file.getFilePointer();
+            TableIndexEntry entry=TableIndexEntry.lookForData(id,file);
+            if(entry!=null)return prescan;
+        }
+        if(next==-1)return -1;
+        if(nextpage==null){
+            file.seek(next);
+            nextpage=new TableIndexPage(index,file);
+        }
+        index.stat_page_next++;
+        return nextpage.getOffset(id,hashcode);
+    }
+    
+    protected TableIndexPage getFirstFreePage(String id,int hashcode) throws IOException{
+        // Is this an empty page?
+        if(offset==0){
+            return this;
+        }
+        // Is this hash lower than the starthash
+        if(!first){
+            if(hashcode<starthash){
+                if(lower==-1){
+                    lower=file.length();
+                    updateMeta();
+                    return createNewPage(index,file,PagedIndex.PAGESIZE);
+                }
+                if(lowerpage==null){
+                    file.seek(lower);
+                    lowerpage=new TableIndexPage(index,file);
+                }
+                index.stat_page_branch++;
+                return lowerpage.getFirstFreePage(id,hashcode);
+            }
+        }
+        // Do we have space in this page
+        if(size-offset>id.length()*2+4+4+8+1+2)return this;
+        // Check next
+        if(next==-1){
+            next=file.length();
+            updateMeta();
+            return createNewPage(index,file,PagedIndex.PAGESIZE);
+        }
+        if(nextpage==null){
+            file.seek(next);
+            nextpage=new TableIndexPage(index,file);
+        }
+        index.stat_page_next++;
+        return nextpage.getFirstFreePage(id,hashcode);
+    }
+    
+    public void addEntry(String id,int rowsize,int location,long position) throws IOException{
+        if(offset==0)starthash=id.hashCode();
+        file.seek(this.location+BASEOFFSET+offset);
+        TableIndexEntry entry=new TableIndexEntry(id,rowsize,location,position);
+        entry.writeData(file);
+        offset+=entry.getSize();
+        if(id.hashCode()>endhash)endhash=id.hashCode();
+        updateMeta();
+    }
+}
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TableIndexPageTransactional.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TableIndexPageTransactional.java
new file mode 100644 (file)
index 0000000..9e57fb6
--- /dev/null
@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.solidosystems.tuplesoup.core;
+
+import dstm2.AtomicSuperClass;
+import dstm2.atomic;
+import dstm2.Thread;
+import dstm2.factory.Factory;
+import java.io.*;
+import java.util.*;
+
+public class TableIndexPageTransactional implements AtomicSuperClass{
+    static Factory<TableIndexPageTSInf> factory = Thread.makeFactory(TableIndexPageTSInf.class);
+    
+    /*static*/ TableIndexPageTSInf atomicfields = null;
+    private final static int BASEOFFSET=4+8+8+4+4;
+    private RandomAccessFile file=null;
+    
+    
+    
+    public @atomic interface TableIndexPageTSInf{
+        Long getLocation();
+        Integer getSize();
+        Long getNext();
+        Long getLower();
+        Integer getOffset();
+        Integer getStarthash();
+        Integer getEndhash();
+        Boolean getFirst();
+        TableIndexPageTransactional getNextpage();
+        TableIndexPageTransactional getLowerpage();
+        PagedIndexTransactional getIndex(); 
+        
+     
+        void setLowerpage(TableIndexPageTransactional lowerpage);   
+        void setNextpage(TableIndexPageTransactional nextpage);
+        void setFirst(Boolean val);
+        void setEndhash(Integer val);
+        void setStarthash(Integer val);
+        void setOffset(Integer offset);
+        void setNext(Long next);
+        void setSize(Integer size);
+        void setLocation(Long location);
+        void setLower(Long val);
+        void setIndex(PagedIndexTransactional val);
+    }
+  
+    
+    
+    public TableIndexPageTransactional(PagedIndexTransactional index,RandomAccessFile file) throws IOException{
+        this.file=file;
+        atomicfields = factory.create();
+        this.atomicfields.setIndex(index);
+        this.atomicfields.setFirst(false);
+        this.atomicfields.setLocation(file.getFilePointer());
+      //  System.out.println(file.getFilePointer());
+        this.atomicfields.setSize(file.readInt());
+      //   System.out.println(file.getFilePointer());
+        this.atomicfields.setNext(file.readLong());
+      //   System.out.println(file.getFilePointer());
+        this.atomicfields.setLower(file.readLong());
+      //   System.out.println(file.getFilePointer());
+      //    System.out.println(file.getFilePointer());
+        this.atomicfields.setOffset(file.readInt());
+      //   System.out.println(file.getFilePointer());
+        this.atomicfields.setEndhash(file.readInt());
+       //      System.out.println("size " + atomicfields.getSize());
+        System.out.println("next "  + atomicfields.getNext());
+        System.out.println("lower " + atomicfields.getLower());
+        System.out.println("offset " + atomicfields.getOffset());
+        System.out.println("endhash " + atomicfields.getEndhash());
+        if(this.atomicfields.getOffset()>0)
+            this.atomicfields.setStarthash(file.readInt());
+        else 
+            this.atomicfields.setStarthash(-1);
+    }
+    
+    public static TableIndexPageTransactional createNewPage(PagedIndexTransactional index,RandomAccessFile file,int size) throws IOException{
+    
+         long pre=file.length();
+
+        file.setLength(file.length()+size+BASEOFFSET);
+        file.seek(pre);
+      
+       // System.out.println("pointer2 " + file.getFilePointer());
+        file.writeInt(size);
+       //  System.out.println("pointer2 " + file.getFilePointer());
+        file.writeLong(-1l);
+       //  System.out.println("pointer2 " + file.getFilePointer());
+        file.writeLong(-1l);
+       //  System.out.println("pointer2 " + file.getFilePointer());
+        file.writeInt(0);
+      //   System.out.println("pointer2 " + file.getFilePointer());
+        file.writeInt(-1);
+        file.seek(pre);
+      //  file.readInt();
+      //  file.readLong();
+       // file.readLong();
+       // file.readInt();
+       // file.readInt();
+       // file.seek(pre);
+        
+        //index.atomicfields.setStat_create_page((long)2);
+        index.atomicfields.setStat_create_page(index.atomicfields.getStat_create_page()+1);
+        return new TableIndexPageTransactional(index,file);
+    }
+    
+    public void setFirst(){
+        this.atomicfields.setFirst(true);
+    }
+    
+    public long getLocation(){
+        return atomicfields.getLocation();
+    }
+    public long getEndLocation(){
+        return this.atomicfields.getLocation()+atomicfields.getSize()+BASEOFFSET;
+    }
+    
+    public String toString(){
+        StringBuffer buf=new StringBuffer();
+        buf.append("{\n");
+        buf.append("  location  "+this.atomicfields.getLocation()+"\n");
+        buf.append("  size      "+this.atomicfields.getSize()+"\n");
+        buf.append("  next      "+this.atomicfields.getNext()+"\n");
+        buf.append("  lower     "+this.atomicfields.getLower()+"\n");
+        buf.append("  offset    "+this.atomicfields.getOffset()+"\n");
+        buf.append("  starthash "+this.atomicfields.getStarthash()+"\n");
+        buf.append("  endhash "+this.atomicfields.getEndhash()+"\n");
+        buf.append("}\n");
+        return buf.toString();
+    }
+    
+    private void updateMeta() throws IOException{
+        file.seek(this.atomicfields.getLocation());
+        file.writeInt(this.atomicfields.getSize());
+        file.writeLong(this.atomicfields.getNext());
+        file.writeLong(this.atomicfields.getLower());
+        file.writeInt(this.atomicfields.getOffset());
+        file.writeInt(this.atomicfields.getEndhash());
+    }
+    
+    public void addEntriesToList(List<TableIndexEntryTransactional> lst) throws IOException{
+        if(this.atomicfields.getLower()>-1){
+            if(this.atomicfields.getLowerpage()==null){
+                file.seek(this.atomicfields.getLower());
+                this.atomicfields.setLowerpage(new TableIndexPageTransactional(this.atomicfields.getIndex(),file));
+            }
+            this.atomicfields.getLowerpage().addEntriesToList(lst);
+        }
+        if(this.atomicfields.getNext()>-1){
+            if(this.atomicfields.getNextpage()==null){
+                file.seek(this.atomicfields.getNext());
+                this.atomicfields.setNextpage(new TableIndexPageTransactional(this.atomicfields.getIndex(),file));
+            }
+            this.atomicfields.getNextpage().addEntriesToList(lst);
+        }
+        file.seek(this.atomicfields.getLocation()+BASEOFFSET);
+        long pre=file.getFilePointer();
+    //    System.out.println(Thread.currentThread() + " " +this.atomicfields.getOffset() + " " + pre);
+        while(file.getFilePointer()<pre+this.atomicfields.getOffset()){
+            
+            TableIndexEntryTransactional entry=TableIndexEntryTransactional.readData(file);
+            if(entry!=null){
+                if(entry.getLocation()!=TableTransactional.DELETE)lst.add(entry);
+            }
+        }
+    }
+    
+    public TableIndexEntryTransactional scanIndex(String id,int hashcode) throws IOException{
+        if(!atomicfields.getFirst()){
+            if(hashcode<atomicfields.getStarthash()){
+                if(atomicfields.getLower()==-1) return null;
+                if(this.atomicfields.getLowerpage()==null){
+                    file.seek(this.atomicfields.getLower());
+                    this.atomicfields.setLowerpage(new TableIndexPageTransactional(this.atomicfields.getIndex(),file));
+                }
+                atomicfields.getIndex().atomicfields.setStat_page_branch(atomicfields.getIndex().atomicfields.getStat_page_branch()+1);
+                return this.atomicfields.getLowerpage().scanIndex(id,hashcode);
+            }
+        }
+        if(hashcode>this.atomicfields.getEndhash()){
+            if(this.atomicfields.getNext()==-1)return null;
+            if(this.atomicfields.getNextpage()==null){
+                file.seek(this.atomicfields.getNext());
+                this.atomicfields.setNextpage(new TableIndexPageTransactional(this.atomicfields.getIndex(),file));
+            }
+            atomicfields.getIndex().atomicfields.setStat_page_next(atomicfields.getIndex().atomicfields.getStat_page_next()+1);
+            return this.atomicfields.getNextpage().scanIndex(id,hashcode);
+        }
+        file.seek(this.atomicfields.getLocation()+BASEOFFSET);
+        long pre=file.getFilePointer();
+        while(file.getFilePointer()<pre+this.atomicfields.getOffset()){
+            //System.out.println("neddddxtex " + atomicfields.getNext());
+            TableIndexEntryTransactional entry=TableIndexEntryTransactional.lookForData(id,file);
+            if(entry!=null)return entry;
+        }
+        if(this.atomicfields.getNext()==-1)return null;
+        if(this.atomicfields.getNextpage()==null){
+            file.seek(this.atomicfields.getNext());
+            this.atomicfields.setNextpage(new TableIndexPageTransactional(this.atomicfields.getIndex(),file));
+        }
+        atomicfields.getIndex().atomicfields.setStat_page_next(atomicfields.getIndex().atomicfields.getStat_page_next()+1);
+        return this.atomicfields.getNextpage().scanIndex(id,hashcode);
+    }
+    protected long getOffset(String id,int hashcode) throws IOException{
+        if(!this.atomicfields.getFirst()){
+            if(hashcode<this.atomicfields.getStarthash()){
+                if(this.atomicfields.getLower()==-1)return -1;
+                if(this.atomicfields.getLowerpage()==null){
+                    file.seek(atomicfields.getLower());
+                    this.atomicfields.setLowerpage(new TableIndexPageTransactional(this.atomicfields.getIndex(),file));
+                }
+                atomicfields.getIndex().atomicfields.setStat_page_branch(atomicfields.getIndex().atomicfields.getStat_page_branch()+1);
+                return this.atomicfields.getLowerpage().getOffset(id,hashcode);
+            }
+        }
+        if(hashcode>this.atomicfields.getEndhash()){
+            if(this.atomicfields.getNext()==-1)return -1;
+            if(this.atomicfields.getNextpage()==null){
+                file.seek(this.atomicfields.getNext());
+                this.atomicfields.setNextpage(new TableIndexPageTransactional(this.atomicfields.getIndex(),file));
+            }
+            atomicfields.getIndex().atomicfields.setStat_page_next(atomicfields.getIndex().atomicfields.getStat_page_next()+1);
+            return this.atomicfields.getNextpage().getOffset(id,hashcode);
+        }
+        file.seek(this.atomicfields.getLocation()+BASEOFFSET);
+        long pre=file.getFilePointer();
+        while(file.getFilePointer()<pre+this.atomicfields.getOffset()){
+            long prescan=file.getFilePointer();
+            TableIndexEntryTransactional entry=TableIndexEntryTransactional.lookForData(id,file);
+            if(entry!=null)return prescan;
+        }
+        if(this.atomicfields.getNext()==-1)return -1;
+        if(this.atomicfields.getNextpage()==null){
+            file.seek(this.atomicfields.getNext());
+            this.atomicfields.setNextpage(new TableIndexPageTransactional(this.atomicfields.getIndex(),file));
+        }
+        atomicfields.getIndex().atomicfields.setStat_page_next(atomicfields.getIndex().atomicfields.getStat_page_next()+1);
+        return this.atomicfields.getNextpage().getOffset(id,hashcode);
+    }
+    
+    protected TableIndexPageTransactional getFirstFreePage(String id,int hashcode) throws IOException{
+        // Is this an empty page?
+        if(this.atomicfields.getOffset()==0){
+            return this;
+        }
+        // Is this hash lower than the starthash
+        if(!this.atomicfields.getFirst()){
+            if(hashcode<this.atomicfields.getStarthash()){
+                if(this.atomicfields.getLower()==-1){
+                    this.atomicfields.setLower(file.length());
+                    updateMeta();
+                    return createNewPage(this.atomicfields.getIndex(),file,PagedIndexTransactional.PAGESIZE);
+                }
+                if(this.atomicfields.getLowerpage()==null){
+                    file.seek(this.atomicfields.getLower());
+                    this.atomicfields.setLowerpage(new TableIndexPageTransactional(this.atomicfields.getIndex(),file));
+                }
+                atomicfields.getIndex().atomicfields.setStat_page_branch(atomicfields.getIndex().atomicfields.getStat_page_branch()+1);
+                return this.atomicfields.getLowerpage().getFirstFreePage(id,hashcode);
+            }
+        }
+        // Do we have space in this page
+        if(this.atomicfields.getSize()-this.atomicfields.getOffset()>id.length()*2+4+4+8+1+2)return this;
+        // Check next
+        if(this.atomicfields.getNext()==-1){
+            this.atomicfields.setNext(file.length());
+            updateMeta();
+            return createNewPage(this.atomicfields.getIndex(),file,PagedIndexTransactional.PAGESIZE);
+        }
+        if(this.atomicfields.getNextpage()==null){
+            file.seek(this.atomicfields.getNext());
+            this.atomicfields.setNextpage(new TableIndexPageTransactional(this.atomicfields.getIndex(),file));
+        }
+        atomicfields.getIndex().atomicfields.setStat_page_next(atomicfields.getIndex().atomicfields.getStat_page_next()+1);
+        return this.atomicfields.getNextpage().getFirstFreePage(id,hashcode);
+    }
+    
+    public void addEntry(String id,int rowsize,int location,long position) throws IOException{
+        if(atomicfields.getOffset()==0)this.atomicfields.setStarthash(id.hashCode());
+        file.seek(this.atomicfields.getLocation()+BASEOFFSET+this.atomicfields.getOffset());
+        TableIndexEntryTransactional entry=new TableIndexEntryTransactional(id,rowsize,location,position);
+        entry.writeData(file);
+        this.atomicfields.setOffset(this.atomicfields.getOffset()+entry.getSize());
+        if(id.hashCode()>this.atomicfields.getEndhash()) this.atomicfields.setEndhash(id.hashCode());
+        updateMeta();
+    }
+}
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TableIndexTransactional.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TableIndexTransactional.java
new file mode 100644 (file)
index 0000000..b859cc2
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package com.solidosystems.tuplesoup.core;
+
+import dstm2.AtomicSuperClass;
+import java.util.*;
+import java.io.*;
+
+public interface TableIndexTransactional extends AtomicSuperClass{
+    public Hashtable<String,Long> readStatistics();
+    public void updateEntry(String id,int rowsize,int location,long position) throws IOException;
+    public void updateEntryTransactional(String id,int rowsize,int location,long position) throws IOException;
+    public void addEntry(String id,int rowsize,int location,long position) throws IOException;
+    public TableIndexEntryTransactional scanIndex(String id) throws IOException;
+    public TableIndexEntryTransactional scanIndexTransactional(String id) throws IOException;
+    public List<TableIndexEntryTransactional> scanIndex(List<String> rows) throws IOException;
+    public List<TableIndexEntryTransactional> scanIndex() throws IOException;
+    public void close();
+}
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TableTransactional.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TableTransactional.java
new file mode 100644 (file)
index 0000000..7f7ba77
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package com.solidosystems.tuplesoup.core;
+
+/**
+ *
+ * @author navid
+ */
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+import java.io.*;
+import java.util.*;
+import java.nio.channels.*;
+import com.solidosystems.tuplesoup.filter.*;
+
+/**
+ * The table stores a group of rows.
+ * Every row must have a unique id within a table.
+ */
+public interface TableTransactional{
+    // Index type constants
+    public static final int MEMORY=0;
+    public static final int FLAT=1;
+    public static final int PAGED=2;
+     
+    // Row location constants
+    public static final int FILEA=0;
+    public static final int FILEB=1;
+    public static final int DELETE=2;
+    public static final int INDEX=3;
+     
+    /**
+     * Return the current values of the statistic counters and reset them.
+     * The current counters are:
+     * <ul>
+     *   <li>stat_table_add
+     *   <li>stat_table_update
+     *   <li>stat_table_delete
+     *   <li>stat_table_add_size
+     *   <li>stat_table_update_size
+     *   <li>stat_table_read_size
+     *   <li>stat_table_read
+     *   <li>stat_table_cache_hit
+     *   <li>stat_table_cache_miss
+     *   <li>stat_table_cache_drop
+     * </ul>
+     * Furthermore, the index will be asked to deliver separate index specific counters
+     */
+    public Hashtable<String,Long> readStatistics();
+
+    /**
+     * Set the maximal allowable size of the index cache.
+     */ 
+    public void setIndexCacheSize(int newsize);
+
+    /**
+     * Close all open file streams
+     */
+    public void close();
+
+    /** 
+     * Returns the name of this table
+     */ 
+    public String getTitle();
+    
+    /**
+     * Returns the location of this tables datafiles
+     */ 
+    public String getLocation();
+    
+    /**
+     * Delete the files created by this table object.
+     * Be aware that this will delete any data stored in this table!
+     */ 
+    public void deleteFiles();
+     
+    /**
+     * Adds a row of data to this table.
+     */
+    public void addRow(RowTransactional row) throws IOException;
+    
+     /**
+      * Adds a row to this table if it doesn't already exist, if it does it updates the row instead.
+      * This method is much slower than directly using add or update, so only use it if you don't know wether or not the row already exists.
+      */
+     public void addOrUpdateRow(RowTransactional row) throws IOException;
+     
+     /**
+      * Updates a row stored in this table.
+      */
+     public void updateRow(RowTransactional row) throws IOException;
+     
+     /**
+      * Marks a row as deleted in the index.
+      * Be aware that the space consumed by the row is not actually reclaimed.
+      */
+     public void deleteRow(RowTransactional row) throws IOException;
+     
+     /**
+      * Returns a tuplestream containing the given list of rows
+      */
+     public TupleStreamTransactional getRows(List<String> rows) throws IOException;
+     
+     /**
+      * Returns a tuplestream containing the rows matching the given rowmatcher
+      */
+     public TupleStreamTransactional getRows(RowMatcherTransactional matcher) throws IOException;
+     
+     /**
+      * Returns a tuplestream containing those rows in the given list that matches the given RowMatcher
+      */
+     public TupleStreamTransactional getRows(List<String> rows,RowMatcherTransactional matcher) throws IOException;
+     
+     /**
+      * Returns a tuplestream of all rows in this table.
+      */
+     public TupleStreamTransactional getRows() throws IOException;
+     
+     /**
+      * Returns a single row stored in this table.
+      * If the row does not exist in the table, null will be returned.
+      */
+     public RowTransactional getRow(String id) throws IOException;
+ }
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TupleStream.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TupleStream.java
new file mode 100644 (file)
index 0000000..f6a7e81
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.solidosystems.tuplesoup.core;
+
+import java.io.*;
+
+public abstract class TupleStream{
+    public abstract boolean hasNext() throws IOException;
+    public abstract Row next() throws IOException;
+}
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TupleStreamMerger.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TupleStreamMerger.java
new file mode 100644 (file)
index 0000000..8d71ce4
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.solidosystems.tuplesoup.core;
+
+import java.io.*;
+import java.util.*;
+
+public class TupleStreamMerger extends TupleStream{
+    private List<TupleStream> streams;
+    private TupleStream current=null;
+    private Row next=null;
+    
+    public TupleStreamMerger(){
+        streams=new ArrayList<TupleStream>();
+    }
+    
+    public void addStream(TupleStream stream){
+        streams.add(stream);
+    }
+
+    public boolean hasNext() throws IOException{
+        if(next!=null)return true;
+        if(current==null){
+            if(streams.size()>0){
+                current=streams.remove(0);
+            }else return false;
+        }
+        if(current.hasNext()){
+            next=current.next();
+            return true;
+        }else{
+            current=null;
+            return hasNext();
+        }
+    }
+
+    public Row next() throws IOException{
+        if(next==null)hasNext();
+        Row tmp=next;
+        next=null;
+        return tmp;
+    }
+
+
+}
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TupleStreamMergerTransactional.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TupleStreamMergerTransactional.java
new file mode 100644 (file)
index 0000000..3070f9e
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.solidosystems.tuplesoup.core;
+
+import java.io.*;
+import java.util.*;
+
+public class TupleStreamMergerTransactional extends TupleStreamTransactional{
+    private List<TupleStreamTransactional> streams;
+    private TupleStreamTransactional current=null;
+    private RowTransactional next=null;
+    
+    public TupleStreamMergerTransactional(){
+        streams=new ArrayList<TupleStreamTransactional>();
+    }
+    
+    public void addStream(TupleStreamTransactional stream){
+        streams.add(stream);
+    }
+
+    public boolean hasNext() throws IOException{
+        if(next!=null)return true;
+        if(current==null){
+            if(streams.size()>0){
+                current=streams.remove(0);
+            }else return false;
+        }
+        if(current.hasNext()){
+            next=current.next();
+            return true;
+        }else{
+            current=null;
+            return hasNext();
+        }
+    }
+
+    public RowTransactional next() throws IOException{
+        if(next==null)hasNext();
+        RowTransactional tmp=next;
+        next=null;
+        return tmp;
+    }
+
+
+}
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TupleStreamTransactional.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/TupleStreamTransactional.java
new file mode 100644 (file)
index 0000000..d65dd22
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package com.solidosystems.tuplesoup.core;
+
+import java.io.IOException;
+
+/**
+ *
+ * @author navid
+ */
+public abstract class TupleStreamTransactional {
+    public abstract boolean hasNext() throws IOException;
+    public abstract RowTransactional next() throws IOException;
+}
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/Value.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/Value.java
new file mode 100644 (file)
index 0000000..0da4452
--- /dev/null
@@ -0,0 +1,639 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+ package com.solidosystems.tuplesoup.core;
+ import java.util.*;
+ import java.io.*;
+ /**
+  * The Value class holds a single data value.
+  * Current size estimate without string data: 8+4+4+8+8 = 32 bytes pr value in mem
+  */
+ public class Value{
+     public final static int NULL=0;
+     public final static int STRING=1;
+     public final static int INT=2;
+     public final static int LONG=3;
+     public final static int FLOAT=4;
+     public final static int DOUBLE=5;
+     public final static int BOOLEAN=6;
+     public final static int TIMESTAMP=7;
+     public final static int BINARY=8;
+
+     private byte type=NULL; // The type of the value being held
+     private String str_value=null;
+     private long int_value=0;
+     private double float_value=0.0;
+     private byte[] binary=null;
+
+     /**
+      * Returns the numerical type id for this value.
+      */
+     public int getType(){
+         return type;
+     }
+     
+     /**
+      * Returns the name this value's type.
+      */
+     public String getTypeName(){
+         switch(type){
+              case STRING     : return "string";
+              case INT        : return "int";
+              case LONG       : return "long";
+              case FLOAT      : return "float";
+              case DOUBLE     : return "double";
+              case BOOLEAN    : return "boolean";
+              case TIMESTAMP  : return "timestamp";
+              case BINARY     : return "binary";
+          }
+          return "null";
+     }
+
+     /**
+      * An implementation of the hashCode method as defined in java.lang.Object
+      * 
+      * @return a hash code value for this object
+      */
+     public int hashCode(){
+         int hash=0;
+         switch(type){
+             case STRING     : hash+=str_value.hashCode();
+             case INT        : hash+=(int)int_value;
+             case LONG       : hash+=(int)int_value;
+             case FLOAT      : hash+=(int)float_value;
+             case DOUBLE     : hash+=(int)float_value;
+             case BOOLEAN    : hash+=(int)int_value;
+             case TIMESTAMP  : hash+=(int)int_value;
+             case BINARY     : hash+=binary.hashCode();
+         }
+         return hash;
+     }
+
+     /**
+      * Returns true only if this Value has specifically been set to null.
+      *
+      * @return true if the data being held is null, false otherwise
+      */
+     public boolean isNull(){
+         return type==NULL;
+     }
+
+     /**
+      * Returns -1, 0 or 1 if this value is smaller, equal or larger than the value given as a parameter.
+      */
+     public int compareTo(Value value){
+         if(type==STRING){
+             return str_value.compareTo(value.getString());
+         }
+         if(lessThan(value))return -1;
+         if(greaterThan(value))return 1;
+         return 0;
+     }
+
+     /**
+      * Attempts to compare this Value to the value given as parameter and returns true if this value is less than the value given as a parameter.
+      * The types used for the comparison will always be based on the type of this Value based on the following rules.
+      * <ul>
+      *   <li>If this Value is a numeric type, then the other Value will be asked to deliver the same numeric type for the comparison.
+      *   <li>If this Value is a string, then both values will be asked to deliver a double value for the comparison.
+      *   <li>If this Value is a timestamp, then both values will be asked to deliver a long value for the comparison.
+      *   <li>If this Value is a boolean, false will be returned.
+      * </ul>
+      *
+      * @param value the value this value should be compared to
+      * @return true if this value is less than the value given as a parameter, false otherwise
+      */
+     public boolean lessThan(Value value){
+         switch(type){
+             case STRING     : return getDouble()<value.getDouble();
+             case INT        : return getInt()<value.getInt();
+             case LONG       : return getLong()<value.getLong();
+             case FLOAT      : return getFloat()<value.getFloat();
+             case DOUBLE     : return getDouble()<value.getDouble();
+             case TIMESTAMP  : return getLong()<value.getLong();
+         }
+         return false;
+     }
+
+     /**
+      * Attempts to compare this Value to the value given as parameter and returns true if this value is greater than the value given as a parameter.
+      * The types used for the comparison will always be based on the type of this Value based on the following rules.
+      * <ul>
+      *   <li>If this Value is a numeric type, then the other Value will be asked to deliver the same numeric type for the comparison.
+      *   <li>If this Value is a string, then both values will be asked to deliver a double value for the comparison.
+      *   <li>If this Value is a timestamp, then both values will be asked to deliver a long value for the comparison.
+      *   <li>If this Value is a boolean, false will be returned.
+      * </ul>
+      *
+      * @param value the value this value should be compared to
+      * @return true if this value is greater than the value given as a parameter, false otherwise
+      */
+     public boolean greaterThan(Value value){
+         switch(type){
+             case STRING     : return getDouble()>value.getDouble();
+             case INT        : return getInt()>value.getInt();
+             case LONG       : return getLong()>value.getLong();
+             case FLOAT      : return getFloat()>value.getFloat();
+             case DOUBLE     : return getDouble()>value.getDouble();
+             case TIMESTAMP  : return getLong()>value.getLong();
+         }
+         return false;
+     }
+
+     /**
+      * Returns true if the string representation of this value starts with the string representation of the value given as parameter.
+      */
+     public boolean startsWith(Value value){
+         return getString().startsWith(value.getString());
+     }
+
+     /**
+      * Returns true if the string representation of this value ends with the string representation of the value given as parameter.
+      */
+     public boolean endsWith(Value value){
+         return getString().endsWith(value.getString());
+     }
+
+     /**
+      * Returns true if the string representation of this value contains the string representation of the value given as parameter.
+      */
+     public boolean contains(Value value){
+         return getString().indexOf(value.getString())>-1;
+     }
+
+     /**
+      * Returns true if the contents of this value equals the contents of the value given as parameter.
+      */
+     public boolean equals(Object obj){
+         try{
+             Value val=(Value)obj;
+             if(val.type==type){
+                 switch(type){
+                     case NULL       : return true;
+                     case STRING     : return str_value.equals(val.str_value);
+                     case INT        : return int_value==val.int_value;
+                     case LONG       : return int_value==val.int_value;
+                     case FLOAT      : return float_value==val.float_value;
+                     case DOUBLE     : return float_value==val.float_value;
+                     case BOOLEAN    : return int_value==val.int_value;
+                     case TIMESTAMP  : return int_value==val.int_value;
+                     case BINARY     : if(binary.length==val.binary.length){
+                                          for(int i=0;i<binary.length;i++){
+                                              if(binary[i]!=val.binary[i])return false;
+                                          }
+                                       }
+                                       return true;
+                 }
+             }
+         }catch(Exception e){}
+         return false;
+     }
+
+     /**
+      * Returns a string representation of this object.
+      */
+     public String toString(){
+         return getString();
+     }
+
+     /**
+      * Returns a string representation of this object (identical to toString)
+      */
+     public String get(){
+         return getString();
+     }
+
+     /**
+      * Returns this value as an xml tag with the given key set as an attribute called name.
+      * The following string is an example of the int value 1234 created with the key foo &lt;value name="foo" type="int"&gt;1234&lt;/value&gt;
+      */
+     public String toBasicXMLString(String key){
+         switch(type){
+             case STRING     : return "<value name=\""+key+"\" type=\"string\">"+str_value+"</value>";
+             case INT        : return "<value name=\""+key+"\"  type=\"int\">"+int_value+"</value>";
+             case LONG       : return "<value name=\""+key+"\"  type=\"long\">"+int_value+"</value>";
+             case FLOAT      : return "<value name=\""+key+"\"  type=\"float\">"+float_value+"</value>";
+             case DOUBLE     : return "<value name=\""+key+"\"  type=\"double\">"+float_value+"</value>";
+             case BOOLEAN    : if(int_value==1){
+                                     return "<value name=\""+key+"\"  type=\"boolean\">TRUE</value>";
+                               }else{
+                                     return "<value name=\""+key+"\"  type=\"boolean\">FALSE</value>";
+                               }
+             case TIMESTAMP  : return "<value name=\""+key+"\"  type=\"timestamp\">"+new Date(int_value).toString()+"</value>";
+             case BINARY     : return "<value name=\""+key+"\" type=\"binary\">"+getString()+"</value>";
+         }
+         return "<value name=\""+key+"\"  type=\"null\"></value>";
+     }
+     
+     /**
+       * Returns this value as an xml tag.
+       * The following string is an example of the int value 1234 &lt;value type="int"&gt;1234&lt;/value&gt;
+       */
+     public String toBasicXMLString(){
+          switch(type){
+              case STRING     : return "<value type=\"string\">"+str_value+"</value>";
+              case INT        : return "<value type=\"int\">"+int_value+"</value>";
+              case LONG       : return "<value type=\"long\">"+int_value+"</value>";
+              case FLOAT      : return "<value type=\"float\">"+float_value+"</value>";
+              case DOUBLE     : return "<value type=\"double\">"+float_value+"</value>";
+              case BOOLEAN    : if(int_value==1){
+                                      return "<value type=\"boolean\">TRUE</value>";
+                                }else{
+                                      return "<value type=\"boolean\">FALSE</value>";
+                                }
+              case TIMESTAMP  : return "<value type=\"timestamp\">"+new Date(int_value).toString()+"</value>";
+              case BINARY     : return "<value type=\"binary\">"+getString()+"</value>";
+          }
+          return "<value type=\"null\"></value>";
+      }
+
+     /**
+      * Returns a string representation of this value
+      */
+     public String getString(){
+         switch(type){
+             case STRING     : return str_value;
+             case INT        : return ""+int_value;
+             case LONG       : return ""+int_value;
+             case FLOAT      : return ""+float_value;
+             case DOUBLE     : return ""+float_value;
+             case BOOLEAN    : if(int_value==1){
+                                     return "TRUE";
+                               }else{
+                                     return "FALSE";
+                               }
+             case TIMESTAMP  : return new Date(int_value).toString();
+             case BINARY     : StringBuffer buf=new StringBuffer();
+                               for(int i=0;i<binary.length;i++){
+                                  byte b=binary[i];
+                                  buf.append(Integer.toHexString((b & 0xFF) | 0x100).substring(1,3));
+                               }
+                               return buf.toString();
+         }
+         return "";
+     }
+
+     /**
+      * Attempts to return an integer representation of this value.
+      * Numerical values will be returned directly (demoted if necessary).
+      * Boolean values will be returned as 1 or 0.
+      * Timestamp values will be returned as a unix timestamp representation divided by 1000.
+      * String values will be atempted to be converted into an int, if that fails, 0 will be returned.
+      * Everything else will return 0.
+      */
+     public int getInt(){
+         try{
+             switch(type){
+                 case STRING     : return Integer.parseInt(str_value);
+                 case INT        : return (int)int_value;
+                 case LONG       : return (int)int_value;
+                 case FLOAT      : return (int)float_value;
+                 case DOUBLE     : return (int)float_value;
+                 case BOOLEAN    : return (int)int_value;
+                 case TIMESTAMP  : return (int)(int_value/1000);
+             }
+         }catch(Exception e){}
+         return 0;
+     }
+
+     /**
+       * Attempts to return a long representation of this value.
+       * Numerical values will be returned directly.
+       * Boolean values will be returned as 1 or 0.
+       * Timestamp values will be returned as a unix timestamp representation.
+       * String values will be atempted to be converted into an int, if that fails, 0 will be returned.
+       * Everything else will return 0.
+       */
+     public long getLong(){
+         try{
+             switch(type){
+                 case STRING     : return Long.parseLong(str_value);
+                 case INT        : return int_value;
+                 case LONG       : return int_value;
+                 case FLOAT      : return (long)float_value;
+                 case DOUBLE     : return (long)float_value;
+                 case BOOLEAN    : return int_value;
+                 case TIMESTAMP  : return int_value;
+             }
+         }catch(Exception e){}
+         return 0;
+     }
+
+     /**
+      * Attempts to return a float representation of this value.
+      * Numerical values will be returned directly (demoted if necessary).
+      * Boolean values will be returned as 1 or 0.
+      * Timestamp values will be returned as a unix timestamp representation divided by 1000.
+      * String values will be atempted to be converted into a float, if that fails, 0 will be returned.
+      * Everything else will return 0.
+      */
+     public float getFloat(){
+         try{
+             switch(type){
+                 case STRING     : return Float.parseFloat(str_value);
+                 case INT        : return (float)int_value;
+                 case LONG       : return (float)int_value;
+                 case FLOAT      : return (float)float_value;
+                 case DOUBLE     : return (float)float_value;
+                 case BOOLEAN    : return (float)int_value;
+                 case TIMESTAMP  : return (float)(int_value/1000);
+             }
+         }catch(Exception e){}
+         return 0.0f;
+     }
+
+     /**
+      * Attempts to return a double representation of this value.
+      * Numerical values will be returned directly.
+      * Boolean values will be returned as 1 or 0.
+      * Timestamp values will be returned as a unix timestamp representation divided by 1000.
+      * String values will be atempted to be converted into a float, if that fails, 0 will be returned.
+      * Everything else will return 0.
+      */
+     public double getDouble(){
+         try{
+             switch(type){
+                 case STRING     : return Double.parseDouble(str_value);
+                 case INT        : return (double)int_value;
+                 case LONG       : return (double)int_value;
+                 case FLOAT      : return (double)float_value;
+                 case DOUBLE     : return (double)float_value;
+                 case BOOLEAN    : return (double)int_value;
+                 case TIMESTAMP  : return (double)(int_value);
+             }
+         }catch(Exception e){}
+         return 0.0;
+     }
+
+     /**
+      * Returns a boolean representation of this value.
+      * Boolean values will be returned directly.
+      * Integer values equalling 1 will be returned as true.
+      * String values equalling true,1,t,yes,on will be returned as true (case insensitive).
+      * Everything else will be returned as false.
+      *
+      * @return a boolean representation of this value.
+      */
+     public boolean getBoolean(){
+         try{
+             switch(type){
+                 case STRING     : if(str_value.toLowerCase().trim().equals("true"))return true;
+                                   if(str_value.trim().equals("1"))return true;
+                                   if(str_value.toLowerCase().trim().equals("t"))return true;
+                                   if(str_value.toLowerCase().trim().equals("yes"))return true;
+                                   if(str_value.toLowerCase().trim().equals("on"))return true;
+                 case INT        : if(int_value==1)return true;
+                 case LONG       : if(int_value==1)return true;
+                 case FLOAT      : if(float_value==1.0f)return true;
+                 case DOUBLE     : if(float_value==1.0)return true;
+                 case BOOLEAN    : if(int_value==1)return true;
+             }
+         }catch(Exception e){}
+         return false;
+     }
+
+     /**
+      * Attempts to return this value as a Date object.
+      * For non date numerical values, the following rules will be used for conversion:
+      * int and float will be multiplied by 1000 and used as a unix timestamp.
+      * long and double will be used directly as a unix timestamp.
+      * Any other type will result in a Date object initialized with 0.
+      *
+      * @return a Date object representation of this value
+      */
+     public Date getTimestamp(){
+         try{
+             switch(type){
+                 case INT        : return new Date(int_value*1000l);
+                 case LONG       : return new Date(int_value);
+                 case FLOAT      : return new Date((long)(float_value*1000l));
+                 case DOUBLE     : return new Date((long)float_value);
+                 case TIMESTAMP  : return new Date(int_value);
+             }
+         }catch(Exception e){}
+         return new Date(0);
+     }
+
+     public byte[] getBinary(){
+         switch(type){
+             case BINARY        : return binary;
+         }
+         return null;
+     }
+
+     /**
+      * Attempts to write this Value to the given DataOutputStream.
+      * The Value will be written as a byte signifying the type of the Value, followed by the actual Value in the native format used by DataOutput.
+      * The exception to this is the string which is written as an integer followed by each character as a single char.
+      * 
+      * @param out the DataOutputStream the Value should be written to
+      */
+     public void writeToStream(DataOutputStream out) throws IOException{
+         out.writeByte(type);
+         switch(type){
+             case STRING :   out.writeInt(str_value.length());
+                             for(int i=0;i<str_value.length();i++){
+                                 out.writeChar(str_value.charAt(i));
+                             }
+                         break;
+             case INT    :   out.writeInt((int)int_value);
+                         break;
+             case LONG   :   out.writeLong(int_value);
+                         break;
+             case FLOAT  :   out.writeFloat((float)float_value);
+                         break;
+             case DOUBLE :   out.writeDouble(float_value);
+                         break;
+             case BOOLEAN:   out.writeBoolean(int_value==1);
+                         break;
+             case TIMESTAMP: out.writeLong(int_value);
+                         break;
+             case BINARY : out.writeInt(binary.length);
+                           out.write(binary,0,binary.length);
+                         break;
+         }
+     }
+     
+     /**
+       * Attempts to write this Value to the given DataOutputStream.
+       * The Value will be written as a byte signifying the type of the Value, followed by the actual Value in the native format used by DataOutput.
+       * The exception to this is the string which is written as an integer followed by each character as a single char.
+       * 
+       * @param out the DataOutputStream the Value should be written to
+       */
+      public void writeToFile(DataOutput out) throws IOException{
+          out.writeByte(type);
+          switch(type){
+              case STRING :   out.writeInt(str_value.length());
+                              for(int i=0;i<str_value.length();i++){
+                                  out.writeChar(str_value.charAt(i));
+                              }
+                          break;
+              case INT    :   out.writeInt((int)int_value);
+                          break;
+              case LONG   :   out.writeLong(int_value);
+                          break;
+              case FLOAT  :   out.writeFloat((float)float_value);
+                          break;
+              case DOUBLE :   out.writeDouble(float_value);
+                          break;
+              case BOOLEAN:   out.writeBoolean(int_value==1);
+                          break;
+              case TIMESTAMP: out.writeLong(int_value);
+                          break;
+              case BINARY : out.writeInt(binary.length);
+                            out.write(binary,0,binary.length);
+          }
+      }
+
+     /**
+      * Attempts to read a new Value from the given DataInputStream.
+      * The Value should be in the format delivered by writeToStream.
+      *
+      * @param in the DataInputStream the Value should be read from
+      * @return the Value read from the stream
+      */
+     public static Value readFromStream(DataInputStream in) throws IOException{
+         byte type=in.readByte();
+         switch(type){
+             case STRING :   int size=in.readInt();
+                             StringBuffer buf=new StringBuffer();
+                             for(int i=0;i<size;i++){
+                                 buf.append(in.readChar());
+                             }
+                             return new Value(buf.toString());
+             case INT    :   return new Value(in.readInt());
+             case LONG   :   return new Value(in.readLong());
+             case FLOAT  :   return new Value(in.readFloat());
+             case DOUBLE :   return new Value(in.readDouble());
+             case BOOLEAN:   return new Value(in.readBoolean());
+             case TIMESTAMP: return new Value(new Date(in.readLong()));
+             case BINARY : int length=in.readInt();
+                           byte[] abuf=new byte[length];
+                           int read=0;
+                           while(read<length){
+                               read+=in.read(abuf,read,length-read);
+                           }
+                           return new Value(abuf);
+
+         }
+         return new Value();
+     }
+
+    /**
+     * Initializes this Value with the given String.
+     * 
+     * @param val the value this Value object should represent
+     */
+     public Value(String val){
+         str_value=val;
+         type=STRING;
+     }
+     
+     public Value(byte[] val){
+          binary=val;
+          type=BINARY;
+      }
+
+     /**
+      * Initializes this Value with the given Date.
+      * The Dates internal long value delivered by the getTime() method will be used.
+      * 
+      * @param val the value this Value object should represent
+      */
+     public Value(Date val){
+         int_value=val.getTime();
+         type=TIMESTAMP;
+     }
+
+     /**
+      * Initializes this Value as null.
+      */
+     public Value(){
+         type=NULL;
+     }
+
+     /**
+      * Initializes this Value with the given int.
+      * 
+      * @param val the value this Value object should represent
+      */
+     public Value(int val){
+         int_value=val;
+         type=INT;
+     }
+
+     /**
+      * Initializes this Value with the given long.
+      * 
+      * @param val the value this Value object should represent
+      */
+     public Value(long val){
+         int_value=val;
+         type=LONG;
+     }
+
+     /**
+      * Initializes this Value with the given float.
+      * 
+      * @param val the value this Value object should represent
+      */
+     public Value(float val){
+         float_value=val;
+         type=FLOAT;
+     }
+
+     /**
+      * Initializes this Value with the given double.
+      * 
+      * @param val the value this Value object should represent
+      */
+     public Value(double val){
+         float_value=val;
+         type=DOUBLE;
+     }
+
+     /**
+      * Initializes this Value with the given boolean.
+      * 
+      * @param val the value this Value object should represent
+      */
+     public Value(boolean val){
+         if(val){
+             int_value=1;
+         }else{
+             int_value=0;
+         }
+         type=BOOLEAN;
+     }  
+ }
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/ValueTransactional.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/core/ValueTransactional.java
new file mode 100644 (file)
index 0000000..2e4851b
--- /dev/null
@@ -0,0 +1,685 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package com.solidosystems.tuplesoup.core;
+
+import dstm2.AtomicByteArray;
+import dstm2.AtomicSuperClass;
+import dstm2.atomic;
+import dstm2.factory.Factory;
+import java.util.*;
+import java.io.*;
+import dstm2.Thread;
+
+/**
+ *
+ * @author navid
+ */
+public class ValueTransactional implements AtomicSuperClass{
+
+     ValueTSInf atomicfields;
+     static Factory<ValueTSInf> factory = Thread.makeFactory(ValueTSInf.class);
+     
+     public @atomic interface ValueTSInf{
+         Byte getType();
+         String getStr_value();
+         Long getInt_value();
+         Double getFloat_value();
+         AtomicByteArray getBinary();
+         
+         void setType(Byte val);
+         void setStr_value(String val);
+         void setInt_value(Long val);
+         void setFloat_value(Double val);
+         void setBinary(AtomicByteArray bytes);
+     }   
+     
+     
+     public final static int NULL=0;
+     public final static int STRING=1;
+     public final static int INT=2;
+     public final static int LONG=3;
+     public final static int FLOAT=4;
+     public final static int DOUBLE=5;
+     public final static int BOOLEAN=6;
+     public final static int TIMESTAMP=7;
+     public final static int BINARY=8;
+
+  /*   private byte type=NULL; // The type of the value being held
+     private String str_value=null;
+     private long int_value=0;
+     private double float_value=0.0;
+     private byte[] binary=null;*/
+
+     /**
+      * Returns the numerical type id for this value.
+      */
+     public int getType(){
+         return atomicfields.getType();
+     }
+     
+     /**
+      * Returns the name this value's type.
+      */
+     public String getTypeName(){
+         switch(atomicfields.getType()){
+              case STRING     : return "string";
+              case INT        : return "int";
+              case LONG       : return "long";
+              case FLOAT      : return "float";
+              case DOUBLE     : return "double";
+              case BOOLEAN    : return "boolean";
+              case TIMESTAMP  : return "timestamp";
+              case BINARY     : return "binary";
+          }
+          return "null";
+     }
+
+     /**
+      * An implementation of the hashCode method as defined in java.lang.Object
+      * 
+      * @return a hash code value for this object
+      */
+     public int hashCode(){
+         int hash=0;
+         switch(atomicfields.getType()){
+             case STRING     : hash+=atomicfields.getStr_value().hashCode();
+             case INT        : hash+=atomicfields.getInt_value();
+             case LONG       : hash+=atomicfields.getInt_value();
+             case FLOAT      : hash+=atomicfields.getFloat_value();
+             case DOUBLE     : hash+=atomicfields.getFloat_value();
+             case BOOLEAN    : hash+=atomicfields.getInt_value();
+             case TIMESTAMP  : hash+=atomicfields.getInt_value();
+             case BINARY     : hash+=atomicfields.getBinary().hashCode();
+         }
+         return hash;
+     }
+
+     /**
+      * Returns true only if this Value has specifically been set to null.
+      *
+      * @return true if the data being held is null, false otherwise
+      */
+     public boolean isNull(){
+         return atomicfields.getType()==NULL;
+     }
+
+     /**
+      * Returns -1, 0 or 1 if this value is smaller, equal or larger than the value given as a parameter.
+      */
+     public int compareTo(ValueTransactional value){
+         if(atomicfields.getType()==STRING){
+             return atomicfields.getStr_value().compareTo(value.getString());
+         }
+         if(lessThan(value))return -1;
+         if(greaterThan(value))return 1;
+         return 0;
+     }
+
+     /**
+      * Attempts to compare this Value to the value given as parameter and returns true if this value is less than the value given as a parameter.
+      * The types used for the comparison will always be based on the type of this Value based on the following rules.
+      * <ul>
+      *   <li>If this Value is a numeric type, then the other Value will be asked to deliver the same numeric type for the comparison.
+      *   <li>If this Value is a string, then both values will be asked to deliver a double value for the comparison.
+      *   <li>If this Value is a timestamp, then both values will be asked to deliver a long value for the comparison.
+      *   <li>If this Value is a boolean, false will be returned.
+      * </ul>
+      *
+      * @param value the value this value should be compared to
+      * @return true if this value is less than the value given as a parameter, false otherwise
+      */
+     public boolean lessThan(ValueTransactional value){
+         switch(atomicfields.getType()){
+             case STRING     : return getDouble()<value.getDouble();
+             case INT        : return getInt()<value.getInt();
+             case LONG       : return getLong()<value.getLong();
+             case FLOAT      : return getFloat()<value.getFloat();
+             case DOUBLE     : return getDouble()<value.getDouble();
+             case TIMESTAMP  : return getLong()<value.getLong();
+         }
+         return false;
+     }
+
+     /**
+      * Attempts to compare this Value to the value given as parameter and returns true if this value is greater than the value given as a parameter.
+      * The types used for the comparison will always be based on the type of this Value based on the following rules.
+      * <ul>
+      *   <li>If this Value is a numeric type, then the other Value will be asked to deliver the same numeric type for the comparison.
+      *   <li>If this Value is a string, then both values will be asked to deliver a double value for the comparison.
+      *   <li>If this Value is a timestamp, then both values will be asked to deliver a long value for the comparison.
+      *   <li>If this Value is a boolean, false will be returned.
+      * </ul>
+      *
+      * @param value the value this value should be compared to
+      * @return true if this value is greater than the value given as a parameter, false otherwise
+      */
+     public boolean greaterThan(ValueTransactional value){
+         switch(atomicfields.getType()){
+             case STRING     : return getDouble()>value.getDouble();
+             case INT        : return getInt()>value.getInt();
+             case LONG       : return getLong()>value.getLong();
+             case FLOAT      : return getFloat()>value.getFloat();
+             case DOUBLE     : return getDouble()>value.getDouble();
+             case TIMESTAMP  : return getLong()>value.getLong();
+         }
+         return false;
+     }
+
+     /**
+      * Returns true if the string representation of this value starts with the string representation of the value given as parameter.
+      */
+     public boolean startsWith(ValueTransactional value){
+         return getString().startsWith(value.getString());
+     }
+
+     /**
+      * Returns true if the string representation of this value ends with the string representation of the value given as parameter.
+      */
+     public boolean endsWith(ValueTransactional value){
+         return getString().endsWith(value.getString());
+     }
+
+     /**
+      * Returns true if the string representation of this value contains the string representation of the value given as parameter.
+      */
+     public boolean contains(ValueTransactional value){
+         return getString().indexOf(value.getString())>-1;
+     }
+
+     /**
+      * Returns true if the contents of this value equals the contents of the value given as parameter.
+      */
+     public boolean equals(Object obj){
+         try{
+             ValueTransactional val=(ValueTransactional)obj;
+             if(val.atomicfields.getType()==atomicfields.getType()){
+                 switch(atomicfields.getType()){
+                     case NULL       : return true;
+                     case STRING     : return atomicfields.getStr_value().equals(val.atomicfields.getStr_value());
+                     case INT        : return atomicfields.getInt_value()==atomicfields.getInt_value();
+                     case LONG       : return atomicfields.getInt_value()==atomicfields.getInt_value();
+                     case FLOAT      : return atomicfields.getFloat_value()==atomicfields.getFloat_value();
+                     case DOUBLE     : return atomicfields.getFloat_value()==atomicfields.getFloat_value();
+                     case BOOLEAN    : return atomicfields.getInt_value()==atomicfields.getInt_value();
+                     case TIMESTAMP  : return atomicfields.getInt_value()==atomicfields.getInt_value();
+                     case BINARY     : if(atomicfields.getBinary().length()==val.atomicfields.getBinary().length()){
+                                          for(int i=0;i<atomicfields.getBinary().length();i++){
+                                              if(atomicfields.getBinary().get(i)!=val.atomicfields.getBinary().get(i))return false;
+                                          }
+                                       }
+                                       return true;
+                 }
+             }
+         }catch(Exception e){}
+         return false;
+     }
+
+     /**
+      * Returns a string representation of this object.
+      */
+     public String toString(){
+         return getString();
+     }
+
+     /**
+      * Returns a string representation of this object (identical to toString)
+      */
+     public String get(){
+         return getString();
+     }
+
+     /**
+      * Returns this value as an xml tag with the given key set as an attribute called name.
+      * The following string is an example of the int value 1234 created with the key foo &lt;value name="foo" type="int"&gt;1234&lt;/value&gt;
+      */
+     public String toBasicXMLString(String key){
+         switch(atomicfields.getType()){
+             case STRING     : return "<value name=\""+key+"\" type=\"string\">"+atomicfields.getStr_value()+"</value>";
+             case INT        : return "<value name=\""+key+"\"  type=\"int\">"+atomicfields.getInt_value()+"</value>";
+             case LONG       : return "<value name=\""+key+"\"  type=\"long\">"+atomicfields.getInt_value()+"</value>";
+             case FLOAT      : return "<value name=\""+key+"\"  type=\"float\">"+atomicfields.getFloat_value()+"</value>";
+             case DOUBLE     : return "<value name=\""+key+"\"  type=\"double\">"+atomicfields.getFloat_value()+"</value>";
+             case BOOLEAN    : if(atomicfields.getInt_value()==1){
+                                     return "<value name=\""+key+"\"  type=\"boolean\">TRUE</value>";
+                               }else{
+                                     return "<value name=\""+key+"\"  type=\"boolean\">FALSE</value>";
+                               }
+             case TIMESTAMP  : return "<value name=\""+key+"\"  type=\"timestamp\">"+new Date(atomicfields.getInt_value()).toString()+"</value>";
+             case BINARY     : return "<value name=\""+key+"\" type=\"binary\">"+getString()+"</value>";
+         }
+         return "<value name=\""+key+"\"  type=\"null\"></value>";
+     }
+     
+     /**
+       * Returns this value as an xml tag.
+       * The following string is an example of the int value 1234 &lt;value type="int"&gt;1234&lt;/value&gt;
+       */
+     public String toBasicXMLString(){
+          switch(atomicfields.getType()){
+              case STRING     : return "<value type=\"string\">"+atomicfields.getStr_value()+"</value>";
+              case INT        : return "<value type=\"int\">"+atomicfields.getInt_value()+"</value>";
+              case LONG       : return "<value type=\"long\">"+atomicfields.getInt_value()+"</value>";
+              case FLOAT      : return "<value type=\"float\">"+atomicfields.getFloat_value()+"</value>";
+              case DOUBLE     : return "<value type=\"double\">"+atomicfields.getFloat_value()+"</value>";
+              case BOOLEAN    : if(atomicfields.getInt_value()==1){
+                                      return "<value type=\"boolean\">TRUE</value>";
+                                }else{
+                                      return "<value type=\"boolean\">FALSE</value>";
+                                }
+              case TIMESTAMP  : return "<value type=\"timestamp\">"+new Date(atomicfields.getInt_value()).toString()+"</value>";
+              case BINARY     : return "<value type=\"binary\">"+getString()+"</value>";
+          }
+          return "<value type=\"null\"></value>";
+      }
+
+     /**
+      * Returns a string representation of this value
+      */
+     public String getString(){
+         switch(atomicfields.getType()){
+             case STRING     : return atomicfields.getStr_value();
+             case INT        : return ""+atomicfields.getInt_value();
+             case LONG       : return ""+atomicfields.getInt_value();
+             case FLOAT      : return ""+atomicfields.getFloat_value();
+             case DOUBLE     : return ""+atomicfields.getFloat_value();
+             case BOOLEAN    : if(atomicfields.getInt_value()==1){
+                                     return "TRUE";
+                               }else{
+                                     return "FALSE";
+                               }
+             case TIMESTAMP  : return new Date(atomicfields.getInt_value()).toString();
+             case BINARY     : StringBuffer buf=new StringBuffer();
+                               for(int i=0;i<atomicfields.getBinary().length();i++){
+                                  byte b=atomicfields.getBinary().get(i);
+                                  buf.append(Integer.toHexString((b & 0xFF) | 0x100).substring(1,3));
+                               }
+                               return buf.toString();
+         }
+         return "";
+     }
+
+     /**
+      * Attempts to return an integer representation of this value.
+      * Numerical values will be returned directly (demoted if necessary).
+      * Boolean values will be returned as 1 or 0.
+      * Timestamp values will be returned as a unix timestamp representation divided by 1000.
+      * String values will be atempted to be converted into an int, if that fails, 0 will be returned.
+      * Everything else will return 0.
+      */
+     public int getInt(){
+         try{
+             switch(atomicfields.getType()){
+                 case STRING     : return Integer.parseInt(atomicfields.getStr_value());
+                 case INT        : return atomicfields.getInt_value().intValue();
+                 case LONG       : return (int)atomicfields.getInt_value().intValue();
+                 case FLOAT      : return (int)atomicfields.getFloat_value().intValue();
+                 case DOUBLE     : return (int)atomicfields.getFloat_value().intValue();
+                 case BOOLEAN    : return (int)atomicfields.getInt_value().intValue();
+                 case TIMESTAMP  : return (int)(atomicfields.getInt_value()/1000);
+             }
+         }catch(Exception e){}
+         return 0;
+     }
+
+     /**
+       * Attempts to return a long representation of this value.
+       * Numerical values will be returned directly.
+       * Boolean values will be returned as 1 or 0.
+       * Timestamp values will be returned as a unix timestamp representation.
+       * String values will be atempted to be converted into an int, if that fails, 0 will be returned.
+       * Everything else will return 0.
+       */
+     public long getLong(){
+         try{
+             switch(atomicfields.getType()){
+                 case STRING     : return Long.parseLong(atomicfields.getStr_value());
+                 case INT        : return atomicfields.getInt_value();
+                 case LONG       : return atomicfields.getInt_value();
+                 case FLOAT      : return (long)atomicfields.getFloat_value().longValue();
+                 case DOUBLE     : return (long)atomicfields.getFloat_value().longValue();
+                 case BOOLEAN    : return atomicfields.getInt_value();
+                 case TIMESTAMP  : return atomicfields.getInt_value();
+             }
+         }catch(Exception e){}
+         return 0;
+     }
+
+     /**
+      * Attempts to return a float representation of this value.
+      * Numerical values will be returned directly (demoted if necessary).
+      * Boolean values will be returned as 1 or 0.
+      * Timestamp values will be returned as a unix timestamp representation divided by 1000.
+      * String values will be atempted to be converted into a float, if that fails, 0 will be returned.
+      * Everything else will return 0.
+      */
+     public float getFloat(){
+         try{
+             switch(atomicfields.getType()){
+                 case STRING     : return Float.parseFloat(atomicfields.getStr_value());
+                 case INT        : return (float)atomicfields.getInt_value().floatValue();
+                 case LONG       : return (float)atomicfields.getInt_value().floatValue();
+                 case FLOAT      : return (float)atomicfields.getFloat_value().floatValue();
+                 case DOUBLE     : return (float)atomicfields.getFloat_value().floatValue();
+                 case BOOLEAN    : return (float)atomicfields.getInt_value().floatValue();
+                 case TIMESTAMP  : return (float)(atomicfields.getInt_value()/1000);
+             }
+         }catch(Exception e){}
+         return 0.0f;
+     }
+
+     /**
+      * Attempts to return a double representation of this value.
+      * Numerical values will be returned directly.
+      * Boolean values will be returned as 1 or 0.
+      * Timestamp values will be returned as a unix timestamp representation divided by 1000.
+      * String values will be atempted to be converted into a float, if that fails, 0 will be returned.
+      * Everything else will return 0.
+      */
+     public double getDouble(){
+         try{
+             switch(atomicfields.getType()){
+                 case STRING     : return Double.parseDouble(atomicfields.getStr_value());
+                 case INT        : return (double)atomicfields.getInt_value();
+                 case LONG       : return (double)atomicfields.getInt_value();
+                 case FLOAT      : return (double)atomicfields.getFloat_value();
+                 case DOUBLE     : return (double)atomicfields.getFloat_value();
+                 case BOOLEAN    : return (double)atomicfields.getInt_value();
+                 case TIMESTAMP  : return (double)(atomicfields.getInt_value());
+             }
+         }catch(Exception e){}
+         return 0.0;
+     }
+
+     /**
+      * Returns a boolean representation of this value.
+      * Boolean values will be returned directly.
+      * Integer values equalling 1 will be returned as true.
+      * String values equalling true,1,t,yes,on will be returned as true (case insensitive).
+      * Everything else will be returned as false.
+      *
+      * @return a boolean representation of this value.
+      */
+     public boolean getBoolean(){
+         try{
+             switch(atomicfields.getType()){
+                 case STRING     : if(atomicfields.getStr_value().toLowerCase().trim().equals("true"))return true;
+                                   if(atomicfields.getStr_value().trim().equals("1"))return true;
+                                   if(atomicfields.getStr_value().toLowerCase().trim().equals("t"))return true;
+                                   if(atomicfields.getStr_value().toLowerCase().trim().equals("yes"))return true;
+                                   if(atomicfields.getStr_value().toLowerCase().trim().equals("on"))return true;
+                 case INT        : if(atomicfields.getInt_value()==1)return true;
+                 case LONG       : if(atomicfields.getInt_value()==1)return true;
+                 case FLOAT      : if(atomicfields.getFloat_value()==1.0f)return true;
+                 case DOUBLE     : if(atomicfields.getFloat_value()==1.0)return true;
+                 case BOOLEAN    : if(atomicfields.getInt_value()==1)return true;
+             }
+         }catch(Exception e){}
+         return false;
+     }
+
+     /**
+      * Attempts to return this value as a Date object.
+      * For non date numerical values, the following rules will be used for conversion:
+      * int and float will be multiplied by 1000 and used as a unix timestamp.
+      * long and double will be used directly as a unix timestamp.
+      * Any other type will result in a Date object initialized with 0.
+      *
+      * @return a Date object representation of this value
+      */
+     public Date getTimestamp(){
+         try{
+             switch(atomicfields.getType()){
+                 case INT        : return new Date(atomicfields.getInt_value()*1000l);
+                 case LONG       : return new Date(atomicfields.getInt_value());
+                 case FLOAT      : return new Date((long)(atomicfields.getFloat_value()*1000l));
+                 case DOUBLE     : return new Date((long)atomicfields.getFloat_value().longValue());
+                 case TIMESTAMP  : return new Date(atomicfields.getInt_value());
+             }
+         }catch(Exception e){}
+         return new Date(0);
+     }
+
+     public AtomicByteArray getBinary(){
+         switch(atomicfields.getType()){
+             case BINARY        : return atomicfields.getBinary();
+         }
+         return null;
+     }
+
+     /**
+      * Attempts to write this Value to the given DataOutputStream.
+      * The Value will be written as a byte signifying the type of the Value, followed by the actual Value in the native format used by DataOutput.
+      * The exception to this is the string which is written as an integer followed by each character as a single char.
+      * 
+      * @param out the DataOutputStream the Value should be written to
+      */
+     public void writeToStream(DataOutputStream out) throws IOException{
+         out.writeByte(atomicfields.getType());
+         switch(atomicfields.getType()){
+             case STRING :   out.writeInt(atomicfields.getStr_value().length());
+                             for(int i=0;i<atomicfields.getStr_value().length();i++){
+                                 out.writeChar(atomicfields.getStr_value().charAt(i));
+                             }
+                         break;
+             case INT    :   out.writeInt((int)atomicfields.getInt_value().intValue());
+                         break;
+             case LONG   :   out.writeLong(atomicfields.getInt_value());
+                         break;
+             case FLOAT  :   out.writeFloat((float)atomicfields.getFloat_value().intValue());
+                         break;
+             case DOUBLE :   out.writeDouble(atomicfields.getFloat_value());
+                         break;
+             case BOOLEAN:   out.writeBoolean(atomicfields.getInt_value()==1);
+                         break;
+             case TIMESTAMP: out.writeLong(atomicfields.getInt_value());
+                         break;
+             case BINARY : out.writeInt(atomicfields.getBinary().length());
+                         for (int i=0; i<atomicfields.getBinary().length(); i++) 
+                             out.write(atomicfields.getBinary().get(i));
+                         break;
+         }
+     }
+     
+     /**
+       * Attempts to write this Value to the given DataOutputStream.
+       * The Value will be written as a byte signifying the type of the Value, followed by the actual Value in the native format used by DataOutput.
+       * The exception to this is the string which is written as an integer followed by each character as a single char.
+       * 
+       * @param out the DataOutputStream the Value should be written to
+       */
+      public void writeToFile(RandomAccessFile out) throws IOException{
+          out.writeByte(atomicfields.getType());
+          switch(atomicfields.getType()){
+              case STRING :   out.writeInt(atomicfields.getStr_value().length());
+                              for(int i=0;i<atomicfields.getStr_value().length();i++){
+                                  out.writeChar(atomicfields.getStr_value().charAt(i));
+                              }
+                          break;
+              case INT    :   out.writeInt((int)atomicfields.getInt_value().intValue());
+                          break;
+              case LONG   :   out.writeLong(atomicfields.getInt_value());
+                          break;
+              case FLOAT  :   out.writeFloat((float)atomicfields.getFloat_value().intValue());
+                          break;
+              case DOUBLE :   out.writeDouble(atomicfields.getFloat_value());
+                          break;
+              case BOOLEAN:   out.writeBoolean(atomicfields.getInt_value()==1);
+                          break;
+              case TIMESTAMP: out.writeLong(atomicfields.getInt_value());
+                          break;
+              case BINARY : out.writeInt(atomicfields.getBinary().length());
+                            for (int i=0; i<atomicfields.getBinary().length(); i++) 
+                                out.writeByte(atomicfields.getBinary().get(i));
+                            
+          }
+      }
+
+     /**
+      * Attempts to read a new Value from the given DataInputStream.
+      * The Value should be in the format delivered by writeToStream.
+      *
+      * @param in the DataInputStream the Value should be read from
+      * @return the Value read from the stream
+      */
+     public static ValueTransactional readFromStream(DataInputStream in) throws IOException{
+         byte type=in.readByte();
+         switch(type){
+             case STRING :   int size=in.readInt();
+                             StringBuffer buf=new StringBuffer();
+                             for(int i=0;i<size;i++){
+                                 buf.append(in.readChar());
+                             }
+                             return new ValueTransactional(buf.toString());
+             case INT    :   return new ValueTransactional(in.readInt());
+             case LONG   :   return new ValueTransactional(in.readLong());
+             case FLOAT  :   return new ValueTransactional(in.readFloat());
+             case DOUBLE :   return new ValueTransactional(in.readDouble());
+             case BOOLEAN:   return new ValueTransactional(in.readBoolean());
+             case TIMESTAMP: return new ValueTransactional(new Date(in.readLong()));
+             case BINARY : int length=in.readInt();
+                           byte[] abuf=new byte[length];
+                           int read=0;
+                           while(read<length){
+                               read+=in.read(abuf,read,length-read);
+                           }
+                           return new ValueTransactional(abuf);
+
+         }
+         return new ValueTransactional();
+     }
+     
+    /*    public static ValueTransactional readFromStream(TransactionalFile in) throws IOException{
+         byte type=in.readByte();
+         switch(type){
+             case STRING :   int size=in.readInt();
+                             StringBuffer buf=new StringBuffer();
+                             for(int i=0;i<size;i++){
+                                 buf.append(in.readChar());
+                             }
+                             return new ValueTransactional(buf.toString());
+             case INT    :   return new ValueTransactional(in.readInt());
+             case LONG   :   return new ValueTransactional(in.readLong());
+             case FLOAT  :   return new ValueTransactional(in.readFloat());
+             case DOUBLE :   return new ValueTransactional(in.readDouble());
+             case BOOLEAN:   return new ValueTransactional(in.readBoolean());
+             case TIMESTAMP: return new ValueTransactional(new Date(in.readLong()));
+             case BINARY : int length=in.readInt();
+                           byte[] abuf=new byte[length];
+                           int read=0;
+                           while(read<length){
+                               read+=in.read(abuf);//,read,length-read);
+                           }
+                           return new ValueTransactional(abuf);
+
+         }
+         return new ValueTransactional();
+     }*/
+
+    /**
+     * Initializes this Value with the given String.
+     * 
+     * @param val the value this Value object should represent
+     */
+     public ValueTransactional(String val){
+         this();
+         atomicfields.setStr_value(val);
+         atomicfields.setType((byte)STRING);
+     }
+     
+     public ValueTransactional(byte[] val){
+         this();
+         atomicfields.setBinary(new AtomicByteArray(Byte.class, val.length));
+         for (int i=0; i<val.length; i++) 
+                 atomicfields.getBinary().set(i, val[i]);
+         
+         atomicfields.setType((byte)BINARY);
+      }
+
+     /**
+      * Initializes this Value with the given Date.
+      * The Dates internal long value delivered by the getTime() method will be used.
+      * 
+      * @param val the value this Value object should represent
+      */
+     public ValueTransactional(Date val){
+         atomicfields.setInt_value(val.getTime());
+         atomicfields.setType((byte)TIMESTAMP);
+     }
+
+     /**
+      * Initializes this Value as null.
+      */
+     public ValueTransactional(){
+         atomicfields = factory.create();
+         atomicfields.setStr_value(null);
+         atomicfields.setInt_value(Long.valueOf(0));
+         atomicfields.setFloat_value(0.0);
+         atomicfields.setBinary(new AtomicByteArray(Byte.class, NULL));
+         atomicfields.setType((byte)NULL);
+     }
+
+     /**
+      * Initializes this Value with the given int.
+      * 
+      * @param val the value this Value object should represent
+      */
+     public ValueTransactional(int val){
+         this();
+         atomicfields.setInt_value(Long.valueOf(val));
+         atomicfields.setType((byte)INT);
+     }
+
+     /**
+      * Initializes this Value with the given long.
+      * 
+      * @param val the value this Value object should represent
+      */
+     public ValueTransactional(long val){
+         this();
+         atomicfields.setInt_value(val);
+         atomicfields.setType((byte)LONG);
+     }
+
+     /**
+      * Initializes this Value with the given float.
+      * 
+      * @param val the value this Value object should represent
+      */
+     public ValueTransactional(float val){
+         this();
+         atomicfields.setFloat_value(Double.valueOf(val));
+         atomicfields.setType((byte)FLOAT);
+     }
+
+     /**
+      * Initializes this Value with the given double.
+      * 
+      * @param val the value this Value object should represent
+      */
+     public ValueTransactional(double val){
+         this();
+         atomicfields.setFloat_value(val);
+         atomicfields.setType((byte)DOUBLE);
+     }
+
+     /**
+      * Initializes this Value with the given boolean.
+      * 
+      * @param val the value this Value object should represent
+      */
+     public ValueTransactional(boolean val){
+         this();
+         if(val){
+             atomicfields.setInt_value(Long.valueOf(1));
+         }else{
+             atomicfields.setInt_value(Long.valueOf(0));
+         }
+         atomicfields.setType((byte)BOOLEAN);
+     }  
+     
+     
+
+}
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/Conditional.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/Conditional.java
new file mode 100644 (file)
index 0000000..9cf2fd7
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.solidosystems.tuplesoup.filter;
+
+import com.solidosystems.tuplesoup.core.*;
+import java.util.*;
+import java.io.*;
+
+public class Conditional extends TupleStream{
+    private TupleStream stream;
+    private RowMatcher matcher;
+    private Row next;
+    
+    public Conditional(TupleStream stream, RowMatcher matcher) throws IOException{
+        this.stream=stream;
+        this.matcher=matcher;
+        next=null;
+        readNext();
+    }
+    
+    private void readNext() throws IOException{
+        next=null;
+        while(next==null){
+            if(!stream.hasNext())return;
+            Row row=stream.next();
+            if(matcher.matches(row)){
+                next=row;
+            }
+        }
+    }
+    
+    public boolean hasNext() throws IOException{
+        if(next!=null)return true;
+        return false;
+    }
+    
+    public Row next() throws IOException{
+        Row tmp=next;
+        readNext();
+        return tmp;
+    }
+}
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/HeapSort.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/HeapSort.java
new file mode 100644 (file)
index 0000000..6da0421
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.solidosystems.tuplesoup.filter;
+
+import com.solidosystems.tuplesoup.core.*;
+import java.util.*;
+
+public abstract class HeapSort extends TupleStream{
+    public HeapSort(){
+        
+    }
+    public void initialize(TupleStream source,List<SortRule> lst){
+        
+    }
+    public abstract boolean hasNext();
+    public abstract Row next();
+}
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/JavaSort.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/JavaSort.java
new file mode 100644 (file)
index 0000000..1dfb4a1
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.solidosystems.tuplesoup.filter;
+
+import com.solidosystems.tuplesoup.core.*;
+import java.util.*;
+import java.io.*;
+
+public class JavaSort extends Sort{
+    private List<Row> sortlst;
+    private int offset;
+    private int datasize;
+    
+    public JavaSort(){
+    }
+    public void initialize(String filename,TupleStream source,List<SortRule> lst) throws IOException{
+        sortlst=new ArrayList<Row>();
+        offset=0;
+        while(source.hasNext()){
+            sortlst.add(source.next());
+        }
+        Collections.sort(sortlst,new SortComparator(lst));
+        datasize=sortlst.size();
+    }
+    public boolean hasNext(){
+        if(offset<datasize)return true;
+        return false;
+    }
+    public Row next(){
+        return sortlst.get(offset++);
+    }
+}
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/Join.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/Join.java
new file mode 100644 (file)
index 0000000..9588f86
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.solidosystems.tuplesoup.filter;
+
+import com.solidosystems.tuplesoup.core.*;
+import java.util.*;
+import java.io.*;
+
+public class Join extends TupleStream{
+    public final static int INNER=0;
+    
+    private int type;
+    private TupleStream left;
+    private TupleStream right;
+    private String key;
+    private RowBuffer buf;
+    private String filename;
+    
+    public Join(String filename,TupleStream left, TupleStream right, String key) throws IOException{
+        this.filename=filename;
+        this.left=left;
+        this.right=right;
+        this.key=key;
+        this.type=INNER;
+        joinData();
+    }
+    
+    public Join(String filename,TupleStream left, TupleStream right, String key,int type) throws IOException{
+        this.filename=filename;
+        this.left=left;
+        this.right=right;
+        this.key=key;
+        this.type=type;
+        joinData();
+    }
+    
+    private void joinData() throws IOException{
+        buf=new RowBuffer(filename);
+        // Raw nested loop operation
+        
+        buf.prepare();
+    }
+    
+    public Row next() throws IOException{
+        return buf.next();
+    }
+    
+    public boolean hasNext() throws IOException{
+        return buf.hasNext();
+    }
+}
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/MergeSort.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/MergeSort.java
new file mode 100644 (file)
index 0000000..7760acc
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.solidosystems.tuplesoup.filter;
+
+import com.solidosystems.tuplesoup.core.*;
+import java.util.*;
+import java.io.*;
+
+public class MergeSort extends Sort{
+    private int MEMLIMIT=65536;
+    private int BUFFERCACHE=65536;
+    private int BUFFERLIMIT=8192;
+    
+    private RowBuffer result;
+    
+    private int bufnum=0;
+    
+    private String filename;
+    
+    private SortComparator compare;
+    
+    
+    public MergeSort(int cachesize){
+        if(cachesize<32768){
+            MEMLIMIT=32768;
+            BUFFERCACHE=0;
+            BUFFERLIMIT=0;
+        }else if(cachesize<65536){
+            MEMLIMIT=32768;
+            BUFFERCACHE=cachesize-MEMLIMIT;
+            BUFFERLIMIT=BUFFERCACHE/4;
+        }else{
+            MEMLIMIT=cachesize/2;
+            BUFFERCACHE=MEMLIMIT;
+            BUFFERLIMIT=BUFFERCACHE/16;
+        }
+        if(BUFFERLIMIT<8192)BUFFERLIMIT=8192;
+    }
+    
+    public void mergeSort(RowBuffer result,RowBuffer a,RowBuffer b) throws IOException{
+        a.prepare();
+        b.prepare();
+        Row rowb=null;
+        Row rowa=null;
+        while(a.hasNext()&&b.hasNext()){
+            if(rowa==null)rowa=a.next();
+            if(rowb==null)rowb=b.next();
+            int cmp=compare.compare(rowa,rowb);
+            if(cmp<=0){
+                result.addRow(rowa);
+                rowa=null;
+            }else{
+                result.addRow(rowb);
+                rowb=null;
+            }
+        }
+        if(rowa!=null)result.addRow(rowa);
+        if(rowb!=null)result.addRow(rowb);
+        while(a.hasNext()){
+            result.addRow(a.next());
+        }
+        while(b.hasNext()){
+            result.addRow(b.next());
+        }
+    }
+    
+    public void mergeSort(List<RowBuffer> buffers) throws IOException{
+        while(buffers.size()>2){
+            RowBuffer tmp=new RowBuffer(filename+"."+(bufnum++));
+            tmp.setCacheSize(allocBuffer());
+            // Grab two and sort to buf
+            RowBuffer a=buffers.remove(0);
+            RowBuffer b=buffers.remove(0);
+            mergeSort(tmp,a,b);
+            a.close();
+            freeBuffer(a);
+            b.close();
+            freeBuffer(b);
+            buffers.add(tmp);
+        }
+        if(buffers.size()==1){
+            result.close();
+            result=buffers.get(0);
+            result.prepare();
+            return;
+        }
+        if(buffers.size()==2){
+            RowBuffer a=buffers.get(0);
+            RowBuffer b=buffers.get(1);
+            mergeSort(result,a,b);
+            a.close();
+            freeBuffer(a);
+            b.close();
+            freeBuffer(b);
+            result.prepare();
+            return;
+        }
+    }
+    
+    private int allocBuffer(){
+        if(BUFFERCACHE>=BUFFERLIMIT){
+            BUFFERCACHE-=BUFFERLIMIT;
+            return BUFFERLIMIT;
+        }
+        int tmp=BUFFERCACHE;
+        BUFFERCACHE=0;
+        return tmp;
+    }
+    private void freeBuffer(RowBuffer buf){
+        BUFFERCACHE+=buf.getCacheSize();
+    }
+    
+    public void initialize(String filename,TupleStream source,List<SortRule> lst) throws IOException{
+        this.filename=filename;
+        compare=new SortComparator(lst);
+        bufnum=0;
+        result=new RowBuffer(filename+".result");
+        result.setCacheSize(BUFFERLIMIT);
+        List<RowBuffer> buffers=new ArrayList<RowBuffer>();
+        int usage=0;
+        List<Row> sortlst=new ArrayList<Row>();
+        while(source.hasNext()){
+            Row row=source.next();
+            if(usage+row.getSize()>MEMLIMIT){
+                RowBuffer buf=new RowBuffer(filename+"."+(bufnum++));
+                buf.setCacheSize(allocBuffer());
+                Collections.sort(sortlst,new SortComparator(lst));
+                for(int i=0;i<sortlst.size();i++){
+                    buf.addRow(sortlst.get(i));
+                }
+                buffers.add(buf);
+                usage=0;
+                sortlst=new ArrayList<Row>();
+            }
+            sortlst.add(row);
+            usage+=row.getSize();
+        }
+        RowBuffer buf=new RowBuffer(filename+"."+(bufnum++));
+        buf.setCacheSize(allocBuffer());
+        Collections.sort(sortlst,new SortComparator(lst));
+        for(int i=0;i<sortlst.size();i++){
+            buf.addRow(sortlst.get(i));
+        }
+        buffers.add(buf);
+        mergeSort(buffers);
+    }
+    public boolean hasNext() throws IOException{
+        return result.hasNext();
+    }
+    public Row next() throws IOException{
+        return result.next();
+    }
+}
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/MergeSort2.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/MergeSort2.java
new file mode 100644 (file)
index 0000000..754a3d1
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.solidosystems.tuplesoup.filter;
+
+import com.solidosystems.tuplesoup.core.*;
+import java.util.*;
+import java.io.*;
+
+public class MergeSort2 extends Sort{
+    private int MEMLIMIT=65536;
+    private int BUFFERCACHE=65536;
+    private int BUFFERLIMIT=8192;
+    
+    private int PREBUFFERS=256;
+    
+    private RowBuffer result;
+    
+    private int bufnum=0;
+    
+    private String filename;
+    
+    private SortComparator compare;
+    
+    
+    public MergeSort2(int cachesize){
+        if(cachesize<32768){
+            MEMLIMIT=32768;
+            BUFFERCACHE=0;
+            BUFFERLIMIT=0;
+        }else if(cachesize<65536){
+            MEMLIMIT=32768;
+            BUFFERCACHE=cachesize-MEMLIMIT;
+            BUFFERLIMIT=BUFFERCACHE/4;
+        }else{
+            MEMLIMIT=cachesize/2;
+            BUFFERCACHE=MEMLIMIT;
+            BUFFERLIMIT=BUFFERCACHE/16;
+        }
+        if(BUFFERLIMIT<8192)BUFFERLIMIT=8192;
+    }
+    
+    public void mergeSort(RowBuffer result,RowBuffer a,RowBuffer b) throws IOException{
+        a.prepare();
+        b.prepare();
+        Row rowb=null;
+        Row rowa=null;
+        while(a.hasNext()&&b.hasNext()){
+            if(rowa==null)rowa=a.next();
+            if(rowb==null)rowb=b.next();
+            int cmp=compare.compare(rowa,rowb);
+            if(cmp<=0){
+                result.addRow(rowa);
+                rowa=null;
+            }else{
+                result.addRow(rowb);
+                rowb=null;
+            }
+        }
+        if(rowa!=null)result.addRow(rowa);
+        if(rowb!=null)result.addRow(rowb);
+        while(a.hasNext()){
+            result.addRow(a.next());
+        }
+        while(b.hasNext()){
+            result.addRow(b.next());
+        }
+    }
+    
+    public void mergeSort(List<RowBuffer> buffers) throws IOException{
+        while(buffers.size()>2){
+            RowBuffer tmp=new RowBuffer(filename+"."+(bufnum++));
+            tmp.setCacheSize(allocBuffer());
+            // Grab two and sort to buf
+            RowBuffer a=buffers.remove(0);
+            RowBuffer b=buffers.remove(0);
+            mergeSort(tmp,a,b);
+            a.close();
+            freeBuffer(a);
+            b.close();
+            freeBuffer(b);
+            buffers.add(tmp);
+        }
+        if(buffers.size()==1){
+            result.close();
+            result=buffers.get(0);
+            result.prepare();
+            return;
+        }
+        if(buffers.size()==2){
+            RowBuffer a=buffers.get(0);
+            RowBuffer b=buffers.get(1);
+            mergeSort(result,a,b);
+            a.close();
+            freeBuffer(a);
+            b.close();
+            freeBuffer(b);
+            result.prepare();
+            return;
+        }
+    }
+    
+    private int allocBuffer(){
+        if(BUFFERCACHE>=BUFFERLIMIT){
+            BUFFERCACHE-=BUFFERLIMIT;
+            return BUFFERLIMIT;
+        }
+        int tmp=BUFFERCACHE;
+        BUFFERCACHE=0;
+        return tmp;
+    }
+    private void freeBuffer(RowBuffer buf){
+        BUFFERCACHE+=buf.getCacheSize();
+    }
+    
+    public void initialize(String filename,TupleStream source,List<SortRule> lst) throws IOException{
+        long prepart=System.currentTimeMillis();
+        this.filename=filename;
+        compare=new SortComparator(lst);
+        bufnum=0;
+        result=new RowBuffer(filename+".result");
+        result.setCacheSize(BUFFERLIMIT);
+        List<RowBuffer> buffers=new ArrayList<RowBuffer>();
+        int usage=0;
+        
+        List<RowBuffer> prebuffers=new ArrayList<RowBuffer>();
+        List<Row> prebufferends=new ArrayList<Row>();
+        for(int i=0;i<PREBUFFERS;i++){
+            RowBuffer buf=new RowBuffer(filename+"."+(bufnum++));
+            buf.setCacheSize(allocBuffer());
+            prebuffers.add(buf);
+        }
+        int over=0;
+        RowBuffer overflow=new RowBuffer(filename+"."+(bufnum++));
+        overflow.setCacheSize(allocBuffer());
+        while(source.hasNext()){
+            Row rowa=source.next();
+            for(int i=0;(i<PREBUFFERS)&&(rowa!=null);i++){
+                if(i<prebufferends.size()){
+                    Row rowb=prebufferends.get(i);
+                    if(compare.compare(rowa,rowb)>0){
+                        RowBuffer tmp=prebuffers.get(i);
+                        tmp.addRow(rowa);
+                        prebufferends.set(i,rowa);
+                        rowa=null;
+                    }
+                }else{
+                    prebufferends.add(rowa);
+                    RowBuffer tmp=prebuffers.get(i);
+                    tmp.addRow(rowa);
+                    rowa=null;
+                }
+            }
+            if(rowa!=null){
+                overflow.addRow(rowa);
+                over++;
+            }
+        }
+        for(int i=0;i<prebufferends.size();i++){
+            buffers.add(prebuffers.get(i));
+        }
+        long postpart=System.currentTimeMillis();
+        System.out.println("preprocess in "+(postpart-prepart)+" ms overflow:"+over);
+        source=overflow;
+        overflow.prepare();
+        
+        List<Row> sortlst=new ArrayList<Row>();
+        while(source.hasNext()){
+            Row row=source.next();
+            if(usage+row.getSize()>MEMLIMIT){
+                RowBuffer buf=new RowBuffer(filename+"."+(bufnum++));
+                buf.setCacheSize(allocBuffer());
+                Collections.sort(sortlst,new SortComparator(lst));
+                for(int i=0;i<sortlst.size();i++){
+                    buf.addRow(sortlst.get(i));
+                }
+                buffers.add(buf);
+                usage=0;
+                sortlst=new ArrayList<Row>();
+            }
+            sortlst.add(row);
+            usage+=row.getSize();
+        }
+        RowBuffer buf=new RowBuffer(filename+"."+(bufnum++));
+        buf.setCacheSize(allocBuffer());
+        Collections.sort(sortlst,new SortComparator(lst));
+        for(int i=0;i<sortlst.size();i++){
+            buf.addRow(sortlst.get(i));
+        }
+        buffers.add(buf);
+        mergeSort(buffers);
+    }
+    public boolean hasNext() throws IOException{
+        return result.hasNext();
+    }
+    public Row next() throws IOException{
+        return result.next();
+    }
+}
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/QuickSort.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/QuickSort.java
new file mode 100644 (file)
index 0000000..5b3fba8
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.solidosystems.tuplesoup.filter;
+
+import com.solidosystems.tuplesoup.core.*;
+import java.util.*;
+
+public abstract class QuickSort extends TupleStream{
+    public QuickSort(){
+        
+    }
+    public void initialize(TupleStream source,List<SortRule> lst){
+        
+    }
+    public abstract boolean hasNext();
+    public abstract Row next();
+}
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/RadixSort.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/RadixSort.java
new file mode 100644 (file)
index 0000000..b64f208
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.solidosystems.tuplesoup.filter;
+
+import com.solidosystems.tuplesoup.core.*;
+import java.util.*;
+
+public abstract class RadixSort extends TupleStream{
+    public RadixSort(){
+        
+    }
+    public void initialize(TupleStream source,List<SortRule> lst){
+        
+    }
+    public abstract boolean hasNext();
+    public abstract Row next();
+}
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/RowBuffer.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/RowBuffer.java
new file mode 100644 (file)
index 0000000..3635c2b
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.solidosystems.tuplesoup.filter;
+
+import java.util.*;
+import java.io.*;
+import com.solidosystems.tuplesoup.core.*;
+
+public class RowBuffer extends TupleStream{
+    private int CACHESIZE=32768;
+    private int cacheusage=0;
+    
+    private int mempointer=0;
+    private boolean diskused=false;
+    
+    private List<Row> membuffer;
+    private String diskbuffer;
+    private DataOutputStream out;
+    private DataInputStream in;
+    
+    private Row next=null;
+    
+    public RowBuffer(String filename){
+        membuffer=new ArrayList<Row>();
+        diskbuffer=filename;
+        out=null;
+        in=null;
+    }
+    
+    public void setCacheSize(int size){
+        CACHESIZE=size;
+    }
+    public int getCacheSize(){
+        return CACHESIZE;
+    }
+    
+    public void addRow(Row row) throws IOException{
+        if(cacheusage+row.getSize()<=CACHESIZE){
+            membuffer.add(row);
+            cacheusage+=row.getSize();
+        }else{
+            cacheusage=CACHESIZE;
+            if(out==null)out=new DataOutputStream(new BufferedOutputStream(new FileOutputStream(diskbuffer),2048));
+            row.writeToStream(out);
+            diskused=true;
+        }
+    }
+    
+    public void prepare() throws IOException{
+        if(out!=null){
+            out.flush();
+            out.close();
+        }
+        mempointer=0;
+        if(diskused)in=new DataInputStream(new BufferedInputStream(new FileInputStream(diskbuffer),2048));
+        readNext();
+    }
+    
+    public void close(){
+        try{
+            File ftest=new File(diskbuffer);
+            if(ftest.exists()){
+                if(out!=null)out.close();
+                if(in!=null)in.close();
+                ftest.delete();
+            }
+        }catch(Exception e){
+            
+        }
+    }
+    
+    private void readNext() throws IOException{
+        if(mempointer<membuffer.size()){
+            next=membuffer.get(mempointer++);
+        }else{
+            if(diskused){
+                try{
+                    next=Row.readFromStream(in);
+                }catch(EOFException e){
+                    next=null;
+                }
+            }else next=null;
+        }
+    }
+    
+    public boolean hasNext() throws IOException{
+        if(next!=null)return true;
+        return false;
+    }
+    
+    public Row next() throws IOException{
+        try{
+            if(next!=null){
+                Row tmp=next;
+                readNext();
+                return tmp;
+            }
+        }catch(Exception e){
+            e.printStackTrace();
+        }
+        return null;
+    }
+}
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/RowBufferTransactional.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/RowBufferTransactional.java
new file mode 100644 (file)
index 0000000..1767f71
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.solidosystems.tuplesoup.filter;
+
+import java.util.*;
+import java.io.*;
+import com.solidosystems.tuplesoup.core.*;
+
+public class RowBufferTransactional extends TupleStreamTransactional{
+    private int CACHESIZE=32768;
+    private int cacheusage=0;
+    
+    private int mempointer=0;
+    private boolean diskused=false;
+    
+    private List<RowTransactional> membuffer;
+    private String diskbuffer;
+    private DataOutputStream out;
+    private DataInputStream in;
+    
+    private RowTransactional next=null;
+    
+    public RowBufferTransactional(String filename){
+        membuffer=new ArrayList<RowTransactional>();
+        diskbuffer=filename;
+        out=null;
+        in=null;
+    }
+    
+    public void setCacheSize(int size){
+        CACHESIZE=size;
+    }
+    public int getCacheSize(){
+        return CACHESIZE;
+    }
+    
+    public void addRow(RowTransactional row) throws IOException{
+        if(cacheusage+row.getSize()<=CACHESIZE){
+            membuffer.add(row);
+            cacheusage+=row.getSize();
+        }else{
+            cacheusage=CACHESIZE;
+            if(out==null)out=new DataOutputStream(new BufferedOutputStream(new FileOutputStream(diskbuffer),2048));
+            row.writeToStream(out);
+            diskused=true;
+        }
+    }
+    
+    public void prepare() throws IOException{
+        if(out!=null){
+            out.flush();
+            out.close();
+        }
+        mempointer=0;
+        if(diskused)in=new DataInputStream(new BufferedInputStream(new FileInputStream(diskbuffer),2048));
+        readNext();
+    }
+    
+    public void close(){
+        try{
+            File ftest=new File(diskbuffer);
+            if(ftest.exists()){
+                if(out!=null)out.close();
+                if(in!=null)in.close();
+                ftest.delete();
+            }
+        }catch(Exception e){
+            
+        }
+    }
+    
+    private void readNext() throws IOException{
+        if(mempointer<membuffer.size()){
+            next=membuffer.get(mempointer++);
+        }else{
+            if(diskused){
+                try{
+                    next=RowTransactional.readFromStream(in);
+                }catch(EOFException e){
+                    next=null;
+                }
+            }else next=null;
+        }
+    }
+    
+    public boolean hasNext() throws IOException{
+        if(next!=null)return true;
+        return false;
+    }
+    
+    public RowTransactional next() throws IOException{
+        try{
+            if(next!=null){
+                RowTransactional tmp=next;
+                readNext();
+                return tmp;
+            }
+        }catch(Exception e){
+            e.printStackTrace();
+        }
+        return null;
+    }
+}
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/Sort.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/Sort.java
new file mode 100644 (file)
index 0000000..3ec03e8
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.solidosystems.tuplesoup.filter;
+
+import com.solidosystems.tuplesoup.core.*;
+import java.util.*;
+import java.io.*;
+
+public abstract class Sort extends TupleStream{
+    public void initialize(String filename,TupleStream source,String key,int direction) throws IOException{
+        List<SortRule> lst=new ArrayList<SortRule>();
+        lst.add(new SortRule(key,direction));
+        initialize(filename,source,lst);
+    }
+    public void initialize(String filename,TupleStream source,String key,int direction,String key2,int direction2) throws IOException{
+        List<SortRule> lst=new ArrayList<SortRule>();
+        lst.add(new SortRule(key,direction));
+        lst.add(new SortRule(key2,direction2));
+        initialize(filename,source,lst);
+    }
+    public abstract void initialize(String filename,TupleStream source,List<SortRule> lst) throws IOException;
+    public abstract boolean hasNext() throws IOException;
+    public abstract Row next() throws IOException;
+}
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/SortComparator.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/SortComparator.java
new file mode 100644 (file)
index 0000000..33fe909
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.solidosystems.tuplesoup.filter;
+
+import com.solidosystems.tuplesoup.core.*;
+import java.util.*;
+
+public class SortComparator implements Comparator<Row>{
+    private List<SortRule> rules;
+    
+    public SortComparator(List<SortRule> rules){
+        this.rules=rules;
+    }
+    
+    private int compare(int rulenum,Row rowa,Row rowb){
+        if(rules.size()<=rulenum)return 0;
+        SortRule rule=rules.get(rulenum);
+        Value a=rowa.get(rule.getKey());
+        Value b=rowb.get(rule.getKey());
+        int result=a.compareTo(b);
+        // TODO: add direction switcher here
+        if(result==0){
+            rulenum++;
+            return compare(rulenum,rowa,rowb);
+        }else{
+             if(rule.getDirection()==SortRule.DESC){
+                 if(result==-1){
+                     result=1;
+                 }else if(result==1)result=-1;
+             }
+             return result;
+        }
+    }
+    
+    public int compare(Row rowa,Row rowb){
+        return compare(0,rowa,rowb);
+    }
+}
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/SortRule.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/filter/SortRule.java
new file mode 100644 (file)
index 0000000..206ae8d
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.solidosystems.tuplesoup.filter;
+
+import com.solidosystems.tuplesoup.core.*;
+
+public class SortRule{
+    public static final int ASC=0;
+    public static final int DESC=1;
+    
+    private String key;
+    private int direction;
+    
+    public SortRule(String key, int direction){
+        this.key=key;
+        this.direction=direction;
+    }
+    
+    public int getDirection(){
+        return direction;
+    }
+    
+    public String getKey(){
+        return key;
+    }
+}
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/test/BasicTest.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/test/BasicTest.java
new file mode 100644 (file)
index 0000000..dabbf7b
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.solidosystems.tuplesoup.test;
+
+import java.util.*;
+
+public class BasicTest{
+    public List<String>errors=new ArrayList<String>();
+    private int lastlength=0;
+    
+    public void err(String str){
+        while(lastlength<40){
+            System.out.print(" ");
+            lastlength++;
+        }
+        outbr(" ERR");
+        outbr(" ! "+str);
+        errors.add(str);
+    }
+    
+    public void printErrorSummary(){
+        outbr("");
+        if(errors.size()==0){
+            outbr("All tests passed!");
+        }else if(errors.size()==1){
+            outbr("1 test failed!");
+        }else{
+            outbr(errors.size()+" tests failed!");
+        }
+    }
+    
+    public static void die(String reason){
+         System.out.println("ERR");
+         System.out.println(" ! "+reason);
+         System.exit(0);
+    }
+    
+    public void ok(){
+        while(lastlength<40){
+            System.out.print(" ");
+            lastlength++;
+        }
+        outbr(" OK");
+    }
+
+    public void outbr(String str){
+        outbr(0,str);
+    }
+    
+    public void out(String str){
+        out(0,str);
+    }
+    
+    public void outbr(int level, String str){
+        switch(level){
+            case 0:System.out.print("");
+                break;
+            case 1:System.out.print(" + ");
+                break;
+            case 2:System.out.print("   * ");
+                break;
+            case 3:System.out.print("     - ");
+                break;
+            case 4:System.out.print("       + ");
+                break;
+        }
+        System.out.println(str);
+    }
+    
+    public void out(int level, String str){
+        lastlength=0;
+        switch(level){
+            case 0: System.out.print("");
+                break;
+            case 1: System.out.print(" + ");
+                    lastlength+=3;
+                break;
+            case 2: System.out.print("   * ");
+                    lastlength+=5;
+                break;
+            case 3: System.out.print("     - ");
+                    lastlength+=7;
+                break;
+        }
+        System.out.print(str);
+        lastlength+=str.length();
+    }
+}
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/test/OrigParralelPerformanceTest.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/test/OrigParralelPerformanceTest.java
new file mode 100644 (file)
index 0000000..b2ece8f
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+ package com.solidosystems.tuplesoup.test;
+ import com.solidosystems.tuplesoup.core.*;
+ import com.solidosystems.tuplesoup.filter.*;
+  
+import dstm2.Init;
+ import java.util.*;
+ import java.io.*;
+
+
+public class OrigParralelPerformanceTest extends BasicTest implements Runnable{
+    
+    long writetime;
+    long readtime;
+    long randomtime;
+    
+    public OrigParralelPerformanceTest(){
+              String path="/home/navid/Volumes/My Book/test/";
+        try{
+            //int records=50000;
+            int records=5;
+            for(int i=1;i<2/*11*/;i++){
+                outbr("Running Parallel DualFileTable Performance test");
+                outbr(1,i+" x "+(records/i)+" Large records");
+            
+               // outbr(2,"Memory index");
+             /*   Table table=new DualFileTable("Performance-test",path,Table.MEMORY);
+                benchmark(table,i,(records/i));
+                table.close();
+                table.deleteFiles();*/
+            
+              /*  outbr(2,"Flat index");
+                table=new DualFileTable("Performance-test",path,Table.FLAT);
+                benchmark(table,i,(records/i));
+                table.close();
+                table.deleteFiles();*/
+            
+                outbr(2,"Paged index");
+                Table table=new DualFileTable("Performance-test",path,Table.PAGED);
+                //TableTransactional table=new DualFileTableTransactional("Performance-test",path,TableTransactional.PAGED);
+                benchmark(table,5,(records/i));
+                table.close();
+             //   table.deleteFiles();
+            
+                outbr("Running Parallel HashedTable Performance test");
+                outbr(1,i+" x "+(records/i)+" Large records");
+            
+            /*    outbr(2,"Memory index");
+                table=new HashedTable("Performance-test",path,Table.MEMORY);
+                benchmark(table,i,(records/i));
+                table.close();
+                table.deleteFiles();
+            
+                outbr(2,"Flat index");
+                table=new HashedTable("Performance-test",path,Table.FLAT);
+                benchmark(table,i,(records/i));
+                table.close();
+                table.deleteFiles();*/
+            
+            //    outbr(2,"Paged index");
+                //table=new HashedTableTransactional("Performance-test",path,TableTransactional.PAGED);
+            //    table=new HashedTable("Performance-test",path,Table.PAGED);
+            //    benchmark(table,i,(records/i));
+            //    table.close();
+              //  table.deleteFiles();*/
+            }
+            
+            
+        }catch(Exception e){
+            e.printStackTrace();
+        }
+    }
+    public static void main(String[] args){
+        Init.init();
+        new OrigParralelPerformanceTest();
+    }
+    
+    public void benchmark(Table table,int threadcount, int records) throws Exception{
+        writetime=0;
+        readtime=0;
+        randomtime=0;
+        List<Thread> lst=new ArrayList<Thread>();
+        for(int i=0;i<threadcount;i++){
+            Thread thr=new Thread(new OrigParralelThread(this,table,i+"",records));
+            thr.start();
+            lst.add(thr);
+        }
+        for(int i=0;i<threadcount;i++){
+            lst.get(i).join();
+        }
+        outbr(3,"Write "+writetime+" ms");
+        outbr(3,"Read "+readtime+" ms");
+        outbr(3,"Random "+randomtime+" ms");
+    }
+    
+    public void run(){
+        
+    }
+    
+    public long benchmarkLargeWrite(Table table,int records, String id) throws IOException{
+        long pre=System.currentTimeMillis();
+        for(int i=0;i<records;i++){
+           // RowTransactional row=new RowTransactional(id+i);
+            Row row=new Row(id+i);
+            row.put("key1","foobarbaz");
+            row.put("key2",123456);
+            row.put("key3",3.141592);
+            row.put("key4",true);
+            row.put("key5",new Value(new byte[]{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}));
+            table.addRow(row);
+        }
+        long post=System.currentTimeMillis();
+        return post-pre;
+    }
+    public long benchmarkLargeRead(Table table,int records, String id) throws IOException{
+        long pre=System.currentTimeMillis();
+        TupleStream stream=table.getRows();
+        //TupleStreamTransactional stream=table.getRows();
+        while(stream.hasNext()){
+            stream.next();
+        }
+        long post=System.currentTimeMillis();
+        return post-pre;
+    }
+    public long benchmarkLargeRandomRead(Table table,int records, String id) throws IOException{
+        long pre=System.currentTimeMillis();
+        for(int i=0;i<records;i++){
+            Row row=table.getRow(id+(int)(Math.random()*records));
+            System.out.println(row);
+            //RowTransactional row=table.getRow(id+(int)(Math.random()*records));
+        }
+        long post=System.currentTimeMillis();
+        return post-pre;
+    }
+
+    public void printStats(Hashtable<String,Long> hash){
+        Set<String> keys=hash.keySet();
+        Iterator<String> it=keys.iterator();
+        while(it.hasNext()){
+            String key=it.next();
+            outbr(4,key+" "+hash.get(key));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/test/OrigParralelThread.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/test/OrigParralelThread.java
new file mode 100644 (file)
index 0000000..fb1ca67
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+ package com.solidosystems.tuplesoup.test;
+ import com.solidosystems.tuplesoup.core.*;
+ import com.solidosystems.tuplesoup.filter.*;
+  
+ import java.util.*;
+ import java.io.*;
+
+
+public class OrigParralelThread implements Runnable{
+    String id;
+    int records;
+    OrigParralelPerformanceTest app;
+    Table table;
+    //TableTransactional table;
+    
+    public OrigParralelThread(OrigParralelPerformanceTest app,Table table,String id,int records){
+        this.id=id;
+        this.records=records;
+        this.app=app;
+        this.table=table;
+    }
+    
+    public void run(){
+        try{
+            long time;
+             time=app.benchmarkLargeWrite(table,records,id);
+            synchronized(app){
+                app.writetime+=time;
+            }
+            time=app.benchmarkLargeRead(table,records,id);
+            synchronized(app){
+                app.readtime+=time;
+           }
+            time=app.benchmarkLargeRandomRead(table,records,id);
+            synchronized(app){
+               app.randomtime+=time;
+           }
+        }catch(Exception e){
+            e.printStackTrace();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/test/ParallelPerformanceTest.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/test/ParallelPerformanceTest.java
new file mode 100644 (file)
index 0000000..5f53131
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+ package com.solidosystems.tuplesoup.test;
+ import com.solidosystems.tuplesoup.core.*;
+ import com.solidosystems.tuplesoup.filter.*;
+  
+import dstm2.Init;
+ import java.util.*;
+ import java.io.*;
+
+
+public class ParallelPerformanceTest extends BasicTest implements Runnable{
+    
+    long writetime;
+    long readtime;
+    long randomtime;
+    
+    public ParallelPerformanceTest(){
+              String path="/home/navid/Volumes/My Book/test/";
+        try{
+            //int records=10;
+            int records=5;
+            for(int i=1;i<2;i++){
+                outbr("Running Parallel DualFileTable Performance test");
+                outbr(1,i+" x "+(records/i)+" Large records");
+            
+               // outbr(2,"Memory index");
+             /*   Table table=new DualFileTable("Performance-test",path,Table.MEMORY);
+                benchmark(table,i,(records/i));
+                table.close();
+                table.deleteFiles();*/
+            
+              /*  outbr(2,"Flat index");
+                table=new DualFileTable("Performance-test",path,Table.FLAT);
+                benchmark(table,i,(records/i));
+                table.close();
+                table.deleteFiles();*/
+            
+                outbr(2,"Paged index");
+                //Table table=new DualFileTable("Performance-test",path,Table.PAGED);
+                TableTransactional table=new DualFileTableTransactional("Performance-test",path,TableTransactional.PAGED);
+                benchmark(table,5,(records/i));
+                table.close();
+             //   table.deleteFiles();
+            
+               // outbr("Running Parallel HashedTable Performance test");
+                //outbr(1,i+" x "+(records/i)+" Large records");
+            
+            /*    outbr(2,"Memory index");
+                table=new HashedTable("Performance-test",path,Table.MEMORY);
+                benchmark(table,i,(records/i));
+                table.close();
+                table.deleteFiles();
+            
+                outbr(2,"Flat index");
+                table=new HashedTable("Performance-test",path,Table.FLAT);
+                benchmark(table,i,(records/i));
+                table.close();
+                table.deleteFiles();*/
+            
+             //   outbr(2,"Paged index");
+                //table=new HashedTableTransactional("Performance-test",path,TableTransactional.PAGED);
+             //   table=new HashedTableTransactional("Performance-test",path,TableTransactional.PAGED);
+            //    benchmark(table,i,(records/i));
+             //   table.close();
+              //  table.deleteFiles();*/
+            }
+            
+            
+        }catch(Exception e){
+            e.printStackTrace();
+        }
+    }
+    public static void main(String[] args){
+        Init.init();
+        new ParallelPerformanceTest();
+    }
+    
+    public void benchmark(TableTransactional table/*Table table*/,int threadcount, int records) throws Exception{
+        writetime=0;
+        readtime=0;
+        randomtime=0;
+        List<Thread> lst=new ArrayList<Thread>();
+        for(int i=0;i<threadcount;i++){
+            Thread thr=new Thread(new ParallelThread(this,table,i+"",records));
+            thr.start();
+            lst.add(thr);
+        }
+        for(int i=0;i<threadcount;i++){
+            lst.get(i).join();
+        }
+        outbr(3,"Write "+writetime+" ms");
+        outbr(3,"Read "+readtime+" ms");
+        outbr(3,"Random "+randomtime+" ms");
+    }
+    
+    public void run(){
+        
+    }
+    
+    public long benchmarkLargeWrite(TableTransactional table,int records, String id) throws IOException{
+        long pre=System.currentTimeMillis();
+        for(int i=0;i<records;i++){
+            RowTransactional row=new RowTransactional(id+i);
+            //Row row=new Row(id+i);
+            row.put("key1","foobarbaz");
+            row.put("key2",123456);
+            row.put("key3",3.141592);
+            row.put("key4",true);
+            row.put("key5",new ValueTransactional(new byte[]{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}));
+            table.addRow(row);
+        }
+        long post=System.currentTimeMillis();
+        return post-pre;
+    }
+    public long benchmarkLargeRead(TableTransactional table,int records, String id) throws IOException{
+        long pre=System.currentTimeMillis();
+        //TupleStream stream=table.getRows();
+        TupleStreamTransactional stream=table.getRows();
+        while(stream.hasNext()){
+            stream.next();
+           // System.out.println(stream);
+        }
+        long post=System.currentTimeMillis();
+        return post-pre;
+    }
+    public long benchmarkLargeRandomRead(TableTransactional table/*Table table*/,int records, String id) throws IOException{
+        long pre=System.currentTimeMillis();
+        for(int i=0;i<records;i++){
+            //Row row=table.getRow(id+(int)(Math.random()*records));
+            RowTransactional row=table.getRow(id+(int)(Math.random()*records));
+            System.out.println("row " + row);
+        }
+        long post=System.currentTimeMillis();
+        return post-pre;
+    }
+
+    public void printStats(Hashtable<String,Long> hash){
+        Set<String> keys=hash.keySet();
+        Iterator<String> it=keys.iterator();
+        while(it.hasNext()){
+            String key=it.next();
+            outbr(4,key+" "+hash.get(key));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/test/ParallelThread.java b/Robust/Transactions/tuplesoupdstm2version/src/com/solidosystems/tuplesoup/test/ParallelThread.java
new file mode 100644 (file)
index 0000000..13a1e69
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2007, Solido Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of Solido Systems nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+ package com.solidosystems.tuplesoup.test;
+ import com.solidosystems.tuplesoup.core.*;
+ import com.solidosystems.tuplesoup.filter.*;
+  
+ import java.util.*;
+ import java.io.*;
+
+
+public class ParallelThread implements Runnable{
+    String id;
+    int records;
+    ParallelPerformanceTest app;
+    //Table table;
+    TableTransactional table;
+    
+    public ParallelThread(ParallelPerformanceTest app,TableTransactional table/*Table table*/,String id,int records){
+        this.id=id;
+        this.records=records;
+        this.app=app;
+        this.table=table;
+    }
+    
+    public void run(){
+        try{
+          long time=app.benchmarkLargeWrite(table,records,id);
+            synchronized(app){
+                app.writetime+=time;
+           }
+           time=app.benchmarkLargeRead(table,records,id);
+            synchronized(app){
+                app.readtime+=time;
+          }
+          time=app.benchmarkLargeRandomRead(table,records,id);
+            synchronized(app){
+                app.randomtime+=time;
+          }
+        }catch(Exception e){
+            e.printStackTrace();
+        }
+        
+    }
+}
\ No newline at end of file