*** empty log message ***
authornavid <navid>
Wed, 21 Jan 2009 19:53:59 +0000 (19:53 +0000)
committernavid <navid>
Wed, 21 Jan 2009 19:53:59 +0000 (19:53 +0000)
38 files changed:
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/DualFileTable.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/FlatIndex.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/HashedTable.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/IndexedTableReader.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/MemoryIndex.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/PagedIndex.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/Row.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/RowMatcher.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/Table.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/TableIndex.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/TableIndexEntry.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/TableIndexNode.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/TableIndexPage.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/TupleStream.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/TupleStreamMerger.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/Value.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/filter/Conditional.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/filter/HeapSort.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/filter/JavaSort.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/filter/Join.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/filter/MergeSort.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/filter/MergeSort2.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/filter/QuickSort.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/filter/RadixSort.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/filter/RowBuffer.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/filter/Sort.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/filter/SortComparator.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/filter/SortRule.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/test/BasicTest.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/test/ComparisonTest.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/test/CoreTest.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/test/ParallelPerformanceTest.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/test/ParallelThread.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/test/PerformanceTest.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/test/RowTest.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/test/SortTest.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/test/TableTest.java [new file with mode: 0644]
Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/test/ValueTest.java [new file with mode: 0644]

diff --git a/Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/DualFileTable.java b/Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/DualFileTable.java
new file mode 100644 (file)
index 0000000..e26cfda
--- /dev/null
@@ -0,0 +1,596 @@
+/*
+ * 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
+     */
+    public DualFileTable(String title,String location) throws IOException{
+        this.title=title;
+        this.location=location;
+        if(!this.location.endsWith(File.separator))this.location+=File.separator;
+        index=new FlatIndex(getFileName(INDEX));
+        indexcachefirst=null;
+        indexcachelast=null;
+        indexcacheusage=0;
+        indexcache=new Hashtable<String,TableIndexNode>();
+    }
+    
+    /**
+     * 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;
+             case FLAT   : index=new FlatIndex(getFileName(INDEX));
+                break;
+             case MEMORY : index=new MemoryIndex(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){
+                                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){
+                                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){
+              synchronized(indexcache){
+                  entry=getCacheEntry(id);
+                   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;
+              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/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/FlatIndex.java b/Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/FlatIndex.java
new file mode 100644 (file)
index 0000000..d133616
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * 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.*;
+import java.nio.channels.*;
+
+public class FlatIndex implements TableIndex{
+    private DataOutputStream out=null;
+    private String filename;
+    
+    private long stat_read=0;
+    private long stat_write=0;
+    private long stat_scan=0;
+    public FlatIndex(String filename) throws IOException{
+        this.filename=filename;
+        File ftest=new File(filename);
+        if(!ftest.exists())ftest.createNewFile();
+    }
+    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_scan",stat_scan);
+        stat_read=0;
+        stat_write=0;
+        stat_scan=0;
+        return hash;
+    }
+    public void close(){
+     try{
+         out.close();
+     }catch(Exception e){}
+    }
+    
+    public List<TableIndexEntry> scanIndex() throws IOException{
+        ArrayList<TableIndexEntry> lst=new ArrayList<TableIndexEntry>();
+        DataInputStream data=new DataInputStream(new BufferedInputStream(new FileInputStream(filename)));
+          try{
+              while(true){
+                  TableIndexEntry entry=TableIndexEntry.readData(data);
+                  stat_read++;
+                  if(entry!=null){
+                          if(entry.getLocation()!=Table.DELETE){
+                              lst.add(entry);
+                          }
+                    }
+              }
+          }catch(EOFException eofe){
+          }
+        return lst;
+    }
+
+    private long getOffset(String id) throws IOException{
+        DataInputStream in=new DataInputStream(new BufferedInputStream(new FileInputStream(filename)));
+        long offset=TableIndexEntry.scanForOffset(id,in);
+        stat_scan++;
+        in.close();
+        return offset;
+    }
+    
+    public synchronized void updateEntry(String id,int rowsize,int location,long position) throws IOException{
+        if(out!=null){
+            out.close();
+            out=null;
+        }
+        long offset=getOffset(id);
+        RandomAccessFile data=new RandomAccessFile(filename,"rw");
+        data.seek(offset);
+        TableIndexEntry entry=new TableIndexEntry(id,rowsize,location,position);
+        entry.writeData(data);
+        stat_write++;
+        FileChannel fc=data.getChannel();
+        fc.force(false);
+        data.close();
+    }
+
+    public synchronized void addEntry(String id,int rowsize,int location,long position) throws IOException{
+     if(out==null)out=new DataOutputStream(new FileOutputStream(filename,true));
+     TableIndexEntry entry=new TableIndexEntry(id,rowsize,location,position);
+     entry.writeData(out);
+     stat_write++;
+     out.flush();
+    }
+
+    public TableIndexEntry scanIndex(String id) throws IOException{
+     DataInputStream data=new DataInputStream(new BufferedInputStream(new FileInputStream(filename)));
+     while(true){
+         try{
+             TableIndexEntry entry=TableIndexEntry.lookForData(id,data);
+             stat_read++;
+             if(entry!=null){
+                 data.close();
+                 return entry;
+             }
+         }catch(EOFException eofe){
+             data.close();
+             return null;
+         }
+     }
+    }
+    
+    public List<TableIndexEntry> scanIndex(List<String> rows) throws IOException{
+     HashSet<String>rowhash=new HashSet<String>();
+      for(int i=0;i<rows.size();i++){
+          rowhash.add(rows.get(i));
+      }
+      Hashtable<String,TableIndexEntry> entries=new Hashtable<String,TableIndexEntry>();
+      DataInputStream data=new DataInputStream(new BufferedInputStream(new FileInputStream(filename)));
+      try{
+          while(true){
+              TableIndexEntry entry=TableIndexEntry.readData(data);
+              stat_read++;
+              if(entry!=null){
+                  if(rowhash.contains(entry.getId())){
+                      if(entry.getLocation()!=Table.DELETE){
+                          entries.put(entry.getId(),entry);
+                      }
+                  }
+                }
+          }
+      }catch(EOFException eofe){
+      }
+      List<TableIndexEntry> result=new ArrayList<TableIndexEntry>();
+      Iterator<String>it=rows.iterator();
+       while(it.hasNext()){
+           String id=it.next();
+           if(entries.containsKey(id)){
+               result.add(entries.get(id));
+           }
+       }
+       return result;
+    }
+}
\ No newline at end of file
diff --git a/Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/HashedTable.java b/Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/HashedTable.java
new file mode 100644 (file)
index 0000000..6316dff
--- /dev/null
@@ -0,0 +1,235 @@
+
+/*
+ * 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=16;
+    private List<Table> tableset;
+    private String title;
+    private String location;
+    
+    /**
+     * Create a new table object with the default flat index model
+     */
+    public HashedTable(String title,String location) 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));
+        }
+    }
+    
+    /**
+     * 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/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/IndexedTableReader.java b/Robust/Transactions/origtuplesoup/tuplesoup/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/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/MemoryIndex.java b/Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/MemoryIndex.java
new file mode 100644 (file)
index 0000000..87f7016
--- /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.core;
+
+import java.util.*;
+import java.io.*;
+
+public class MemoryIndex implements TableIndex{
+    private DataOutputStream out=null;
+    private String filename;
+    private Hashtable<String,TableIndexEntry> cache;
+    
+    private long stat_write=0;
+    public MemoryIndex(String filename) throws IOException{
+        this.filename=filename;
+        File ftest=new File(filename);
+        if(!ftest.exists())ftest.createNewFile();
+        cache=new Hashtable<String,TableIndexEntry>();
+        DataInputStream in=new DataInputStream(new BufferedInputStream(new FileInputStream(filename)));
+        try{
+            while(true){
+                TableIndexEntry entry=TableIndexEntry.readData(in);
+                if(entry.getLocation()==Table.DELETE){
+                    cache.remove(entry.getId());
+                }else{
+                    cache.put(entry.getId(),entry);
+                }
+            }
+        }catch(EOFException e){}
+        out=new DataOutputStream(new BufferedOutputStream(new FileOutputStream(filename,true)));
+    }
+    
+    public Hashtable<String,Long> readStatistics(){
+        Hashtable<String,Long> hash=new Hashtable<String,Long>();
+        hash.put("stat_index_write",stat_write);
+        stat_write=0;
+        return hash;
+    }
+    public void close(){
+     try{
+         out.close();
+     }catch(Exception e){}
+    }
+    
+    public synchronized List<TableIndexEntry> scanIndex() throws IOException{
+        ArrayList<TableIndexEntry> lst=new ArrayList<TableIndexEntry>();
+        Iterator<TableIndexEntry> it=cache.values().iterator();
+        while(it.hasNext()){
+            TableIndexEntry entry=it.next();
+            if(entry.getLocation()!=Table.DELETE)lst.add(entry);
+        }
+        return lst;
+    }
+    
+    public synchronized void updateEntry(String id,int rowsize,int location,long position) throws IOException{
+        TableIndexEntry entry=new TableIndexEntry(id,rowsize,location,position);
+        entry.writeData(out);
+        out.flush();
+        stat_write++;
+        cache.put(entry.getId(),entry);
+    }
+
+    public synchronized void addEntry(String id,int rowsize,int location,long position) throws IOException{
+        TableIndexEntry entry=new TableIndexEntry(id,rowsize,location,position);
+        entry.writeData(out);
+        out.flush();
+        stat_write++;
+        cache.put(entry.getId(),entry);
+    }
+
+    public synchronized TableIndexEntry scanIndex(String id) throws IOException{
+        if(!cache.containsKey(id))return null;
+        return cache.get(id);
+    }
+    
+    public synchronized List<TableIndexEntry> scanIndex(List<String> rows) throws IOException{
+        List<TableIndexEntry> result=new ArrayList<TableIndexEntry>();
+        for(int i=0;i<rows.size();i++){
+            if(cache.containsKey(rows.get(i))){
+                TableIndexEntry entry=cache.get(rows.get(i));
+                if(entry!=null)result.add(entry);
+            }
+        }
+        return result;
+    }
+}
\ No newline at end of file
diff --git a/Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/PagedIndex.java b/Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/PagedIndex.java
new file mode 100644 (file)
index 0000000..f200fa9
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * 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.*;
+
+public class PagedIndex implements TableIndex{
+    protected static final int INITIALPAGEHASH=1024;
+    protected static final int PAGESIZE=2048;
+    
+    private RandomAccessFile out=null;
+    private String filename;
+    private TableIndexPage[] 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];
+        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/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/Row.java b/Robust/Transactions/origtuplesoup/tuplesoup/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/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/RowMatcher.java b/Robust/Transactions/origtuplesoup/tuplesoup/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/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/Table.java b/Robust/Transactions/origtuplesoup/tuplesoup/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/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/TableIndex.java b/Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/TableIndex.java
new file mode 100644 (file)
index 0000000..ba8b76f
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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.*;
+
+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/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/TableIndexEntry.java b/Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/TableIndexEntry.java
new file mode 100644 (file)
index 0000000..229d5f4
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ * 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 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();
+        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/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/TableIndexNode.java b/Robust/Transactions/origtuplesoup/tuplesoup/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/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/TableIndexPage.java b/Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/TableIndexPage.java
new file mode 100644 (file)
index 0000000..3754921
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * 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();
+        if(offset>0)starthash=file.readInt();
+    }
+    
+    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();
+        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{
+        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){
+            TableIndexEntry entry=TableIndexEntry.lookForData(id,file);
+            if(entry!=null)return entry;
+        }
+        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);
+    }
+    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/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/TupleStream.java b/Robust/Transactions/origtuplesoup/tuplesoup/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/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/TupleStreamMerger.java b/Robust/Transactions/origtuplesoup/tuplesoup/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/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/core/Value.java b/Robust/Transactions/origtuplesoup/tuplesoup/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/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/filter/Conditional.java b/Robust/Transactions/origtuplesoup/tuplesoup/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/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/filter/HeapSort.java b/Robust/Transactions/origtuplesoup/tuplesoup/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/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/filter/JavaSort.java b/Robust/Transactions/origtuplesoup/tuplesoup/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/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/filter/Join.java b/Robust/Transactions/origtuplesoup/tuplesoup/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/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/filter/MergeSort.java b/Robust/Transactions/origtuplesoup/tuplesoup/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/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/filter/MergeSort2.java b/Robust/Transactions/origtuplesoup/tuplesoup/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/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/filter/QuickSort.java b/Robust/Transactions/origtuplesoup/tuplesoup/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/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/filter/RadixSort.java b/Robust/Transactions/origtuplesoup/tuplesoup/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/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/filter/RowBuffer.java b/Robust/Transactions/origtuplesoup/tuplesoup/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/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/filter/Sort.java b/Robust/Transactions/origtuplesoup/tuplesoup/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/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/filter/SortComparator.java b/Robust/Transactions/origtuplesoup/tuplesoup/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/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/filter/SortRule.java b/Robust/Transactions/origtuplesoup/tuplesoup/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/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/test/BasicTest.java b/Robust/Transactions/origtuplesoup/tuplesoup/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/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/test/ComparisonTest.java b/Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/test/ComparisonTest.java
new file mode 100644 (file)
index 0000000..cef72e1
--- /dev/null
@@ -0,0 +1,339 @@
+/*
+ * 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.*;
+import java.sql.*;
+
+
+public class ComparisonTest{
+    public int DATASET=50000;
+    public List<List<Long>>results;
+    public List<String>testnames;
+    public List<String>idlist;
+    
+    
+    public String generateId(int i){
+        return "user.number."+i+"@testdomain.lan";
+    }
+    
+    public void testTupleSoup() throws Exception{
+        System.out.println(" + Running TupleSoup test");
+        Table tbl=new DualFileTable("CoreTestData",".");
+        tbl.deleteFiles();
+        tbl=new DualFileTable("CoreTestData",".",Table.PAGED);
+        //tbl.setIndexCacheSize(DATASET/10);
+        tbl.setIndexCacheSize(50000);
+        long pre=System.currentTimeMillis();
+
+        for(int i=0;i<DATASET;i++){
+            Row row=new Row(idlist.get(i));
+            row.put("name","Kasper J. Jeppesen");
+            row.put("age",(int)(Math.random()*60f)+20);
+            row.put("sex","male");
+            row.put("www","http://syntacticsirup.blogspot.com/");
+            row.put("tcreated",new java.util.Date());
+            tbl.addRow(row);
+        }
+        long post=System.currentTimeMillis();
+        long addtime=post-pre;
+        System.out.println("   - Add "+addtime+"ms");
+        
+        pre=System.currentTimeMillis();
+        for(int i=0;i<DATASET/10;i++){
+            Row row=tbl.getRow(idlist.get((int)(Math.random()*DATASET)));
+        }
+        post=System.currentTimeMillis();
+        long fetchtime=post-pre;
+        System.out.println("   - Fetch "+fetchtime+"ms");
+        
+        pre=System.currentTimeMillis();
+        for(int i=0;i<DATASET/10;i++){
+            Row row=tbl.getRow(idlist.get((int)(Math.random()*DATASET)));
+            row.put("age",row.getInt("age")+1);
+            tbl.updateRow(row);
+        }
+        post=System.currentTimeMillis();
+        long updatetime=post-pre;
+        System.out.println("   - Update "+updatetime+"ms");
+        
+        // pre=System.currentTimeMillis();
+        // MergeSort msort=new MergeSort(8192000);
+        // msort.initialize("./tmpsort",tbl.getRows(),"age",SortRule.ASC);
+        // while(msort.hasNext()){
+        //    Row row=msort.next();
+        // }
+        // post=System.currentTimeMillis();
+        // long sorttime=post-pre;
+        // System.out.println("   - Sort "+sorttime+"ms");
+        
+        // addResults(addtime,fetchtime,updatetime,sorttime,0);
+        testnames.add("TupleSoup");
+    }
+    
+    public void testGreedyTupleSoup() throws Exception{
+        System.out.println(" + Running Greedy TupleSoup test");
+        Table tbl=new DualFileTable("CoreTestData",".");
+        tbl.deleteFiles();
+        tbl=new DualFileTable("CoreTestData",".",Table.MEMORY);
+        tbl.setIndexCacheSize(0);
+        long pre=System.currentTimeMillis();
+
+        for(int i=0;i<DATASET;i++){
+            Row row=new Row(idlist.get(i));
+            row.put("name","Kasper J. Jeppesen");
+            row.put("age",(int)(Math.random()*60f)+20);
+            row.put("sex","male");
+            row.put("www","http://syntacticsirup.blogspot.com/");
+            row.put("tcreated",new java.util.Date());
+            tbl.addRow(row);
+        }
+        long post=System.currentTimeMillis();
+        long addtime=post-pre;
+        System.out.println("   - Add "+addtime+"ms");
+        
+        pre=System.currentTimeMillis();
+        for(int i=0;i<DATASET/10;i++){
+            Row row=tbl.getRow(idlist.get((int)(Math.random()*DATASET)));
+        }
+        post=System.currentTimeMillis();
+        long fetchtime=post-pre;
+        System.out.println("   - Fetch "+fetchtime+"ms");
+        
+        pre=System.currentTimeMillis();
+        for(int i=0;i<DATASET/10;i++){
+            Row row=tbl.getRow(idlist.get((int)(Math.random()*DATASET)));
+            row.put("age",row.getInt("age")+1);
+            tbl.updateRow(row);
+        }
+        post=System.currentTimeMillis();
+        long updatetime=post-pre;
+        System.out.println("   - Update "+updatetime+"ms");
+        
+        pre=System.currentTimeMillis();
+        JavaSort msort=new JavaSort();
+        msort.initialize("./tmpsort",tbl.getRows(),"age",SortRule.ASC);
+        while(msort.hasNext()){
+            Row row=msort.next();
+        }
+        post=System.currentTimeMillis();
+        long sorttime=post-pre;
+        System.out.println("   - Sort "+sorttime+"ms");
+        
+        addResults(addtime,fetchtime,updatetime,sorttime,0);
+        testnames.add("TupleSoup");
+    }
+    
+    public void testPostgreSQL() throws Exception{
+        System.out.println(" + Running PostgreSQL test");
+        Class.forName("org.postgresql.Driver");
+        Connection con=DriverManager.getConnection("jdbc:postgresql:tupledb","tuple", "1234");
+        Statement st=con.createStatement();
+        try{
+            st.executeUpdate("DROP TABLE tbl_user");
+        }catch(Exception e){}
+        st.executeUpdate("CREATE TABLE tbl_user (id VARCHAR, name VARCHAR, age INT, sex VARCHAR, www VARCHAR, tcreated TIMESTAMP)");
+        st.executeUpdate("CREATE INDEX ndx_user ON tbl_user(id)");
+        st.executeUpdate("VACUUM FULL");
+        // con.setAutoCommit(false);
+        PreparedStatement pst=con.prepareStatement("INSERT INTO tbl_user (id,name,age,sex,www,tcreated) VALUES(?,?,?,?,?,?)");
+        long pre=System.currentTimeMillis();
+        for(int i=0;i<DATASET;i++){
+            // st.executeUpdate("INSERT INTO tbl_user (id,name,age,sex,www,tcreated) VALUES('"+generateId(i)+"','Kasper J. Jeppesen',"+((int)(Math.random()*60f)+20)+",'male','http://syntacticsirup.blogspot.com/',now())");
+            pst.setString(1,idlist.get(i));
+            pst.setString(2,"Kasper J. Jeppesen");
+            pst.setInt(3,((int)(Math.random()*60f)+20));
+            pst.setString(4,"male");
+            pst.setString(5,"http://syntacticsirup.blogspot.com/");
+            pst.setDate(6,new java.sql.Date(System.currentTimeMillis()));
+            pst.executeUpdate();
+        }
+        // con.commit();
+        long post=System.currentTimeMillis();
+        st.executeUpdate("ANALYZE");
+        long addtime=post-pre;
+        System.out.println("   - Add "+addtime+"ms");
+        
+        pst=con.prepareStatement("SELECT name,age,sex,www,tcreated FROM tbl_user WHERE id=?");
+        pre=System.currentTimeMillis();
+        for(int i=0;i<DATASET/10;i++){
+            pst.setString(1,idlist.get((int)(Math.random()*DATASET)));
+            ResultSet rs=pst.executeQuery();
+            rs.next();
+        }
+        post=System.currentTimeMillis();
+        long fetchtime=post-pre;
+        System.out.println("   - Fetch "+fetchtime+"ms");
+        
+        pst=con.prepareStatement("SELECT age FROM tbl_user WHERE id=?");
+        PreparedStatement pst2=con.prepareStatement("UPDATE tbl_user SET age=? WHERE id=?");
+        pre=System.currentTimeMillis();
+        for(int i=0;i<DATASET/10;i++){
+            pst.setString(1,idlist.get((int)(Math.random()*DATASET)));
+            ResultSet rs=pst.executeQuery();
+            rs.next();
+            pst2.setInt(1,rs.getInt(1)+1);
+            pst2.setString(2,idlist.get(i));
+            pst2.executeUpdate();
+        }
+        post=System.currentTimeMillis();
+        long updatetime=post-pre;
+        System.out.println("   - Update "+updatetime+"ms");
+        
+        pre=System.currentTimeMillis();
+        ResultSet rs=st.executeQuery("SELECT id,name,age,sex,www,tcreated FROM tbl_user ORDER BY age");
+        while(rs.next()){
+            rs.getString(1);
+        }
+        post=System.currentTimeMillis();
+        long sorttime=post-pre;
+        System.out.println("   - Sort "+sorttime+"ms");
+        
+        
+        addResults(addtime,fetchtime,0,sorttime,0);
+        testnames.add("TupleSoup");
+    }
+    
+    public void testMySQL() throws Exception{
+        System.out.println(" + Running MySQL test");
+        Class.forName("com.mysql.jdbc.Driver");
+        Connection con=DriverManager.getConnection("jdbc:mysql://localhost:3306/tupledb","tuple", "1234");
+        Statement st=con.createStatement();
+        try{
+            st.executeUpdate("DROP TABLE tbl_user");
+        }catch(Exception e){}
+        st.executeUpdate("CREATE TABLE tbl_user (id VARCHAR(128), name VARCHAR(128), age INT, sex VARCHAR(16), www VARCHAR(128), tcreated TIMESTAMP)");
+        st.executeUpdate("CREATE INDEX ndx_user ON tbl_user(id)");
+        // st.executeUpdate("VACUUM FULL");
+        // con.setAutoCommit(false);
+        PreparedStatement pst=con.prepareStatement("INSERT INTO tbl_user (id,name,age,sex,www,tcreated) VALUES(?,?,?,?,?,?)");
+        long pre=System.currentTimeMillis();
+        for(int i=0;i<DATASET;i++){
+            // st.executeUpdate("INSERT INTO tbl_user (id,name,age,sex,www,tcreated) VALUES('"+generateId(i)+"','Kasper J. Jeppesen',"+((int)(Math.random()*60f)+20)+",'male','http://syntacticsirup.blogspot.com/',now())");
+            pst.setString(1,idlist.get(i));
+            pst.setString(2,"Kasper J. Jeppesen");
+            pst.setInt(3,((int)(Math.random()*60f)+20));
+            pst.setString(4,"male");
+            pst.setString(5,"http://syntacticsirup.blogspot.com/");
+            pst.setDate(6,new java.sql.Date(System.currentTimeMillis()));
+            pst.executeUpdate();
+        }
+        // con.commit();
+        long post=System.currentTimeMillis();
+        // st.executeUpdate("ANALYZE");
+        long addtime=post-pre;
+        System.out.println("   - Add "+addtime+"ms");
+        
+        pst=con.prepareStatement("SELECT name,age,sex,www,tcreated FROM tbl_user WHERE id=?");
+        pre=System.currentTimeMillis();
+        for(int i=0;i<DATASET/10;i++){
+            pst.setString(1,idlist.get((int)(Math.random()*DATASET)));
+            ResultSet rs=pst.executeQuery();
+            rs.next();
+        }
+        post=System.currentTimeMillis();
+        long fetchtime=post-pre;
+        System.out.println("   - Fetch "+fetchtime+"ms");
+        
+        pst=con.prepareStatement("SELECT age FROM tbl_user WHERE id=?");
+        PreparedStatement pst2=con.prepareStatement("UPDATE tbl_user SET age=? WHERE id=?");
+        pre=System.currentTimeMillis();
+        for(int i=0;i<DATASET/10;i++){
+            pst.setString(1,idlist.get((int)(Math.random()*DATASET)));
+            ResultSet rs=pst.executeQuery();
+            rs.next();
+            pst2.setInt(1,rs.getInt(1)+1);
+            pst2.setString(2,idlist.get(i));
+            pst2.executeUpdate();
+        }
+        post=System.currentTimeMillis();
+        long updatetime=post-pre;
+        System.out.println("   - Update "+updatetime+"ms");
+        
+        pre=System.currentTimeMillis();
+        ResultSet rs=st.executeQuery("SELECT id,name,age,sex,www,tcreated FROM tbl_user ORDER BY age");
+        while(rs.next()){
+            rs.getString(1);
+        }
+        post=System.currentTimeMillis();
+        long sorttime=post-pre;
+        System.out.println("   - Sort "+sorttime+"ms");
+        
+        
+        addResults(addtime,fetchtime,0,sorttime,0);
+        testnames.add("TupleSoup");
+    }
+    public void addResults(long add,long fetch,long update,long sort,long sum){
+        List<Long> lst=new ArrayList<Long>();
+        lst.add(add);
+        lst.add(fetch);
+        lst.add(update);
+        lst.add(sort);
+        lst.add(sum);
+        results.add(lst);
+    }
+    
+    public ComparisonTest(){
+        try{
+            for(int n=1;n<=20;n++){
+                DATASET=n*10000;
+                System.out.println("Running for "+DATASET);
+                idlist=new ArrayList<String>();
+                for(int i=0;i<DATASET;i++){
+                    idlist.add(generateId(i));
+                }
+                Collections.shuffle(idlist);
+                results=new ArrayList<List<Long>>();
+                testnames=new ArrayList<String>();
+                // testGreedyTupleSoup();
+                testTupleSoup();
+                // testMySQL();
+                // testPostgreSQL();
+            }
+            // calcScores();
+        }catch(Exception e){
+            e.printStackTrace();
+        }
+    }
+    
+    public void calcScores(){
+        System.out.println("Compared results");
+    }
+    
+    public static void main(String[] args){
+        new ComparisonTest();
+    }
+}
\ No newline at end of file
diff --git a/Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/test/CoreTest.java b/Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/test/CoreTest.java
new file mode 100644 (file)
index 0000000..935a0ab
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ * 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.*;
+ public class CoreTest{
+     public static void main(String[] args){
+         try{
+             System.out.println("TupleSoup Core Data Test");
+             System.out.println(" + Preparing data");
+             Date dt=new Date();
+         
+             Table tbl=new DualFileTable("CoreTestData",".");
+             tbl.deleteFiles();
+             tbl=new DualFileTable("CoreTestData",".");
+             Row row1=new Row("1");
+             row1.put("string","Hello World!");
+             row1.put("int",42);
+             row1.put("long",314l);
+             row1.put("float",3.14f);
+             row1.put("double",3.1415d);
+             row1.put("timestamp",dt);
+             row1.put("boolean",true);
+             tbl.addRow(row1);
+             Row row2=new Row("2");
+             row2.put("name","Kasper J");
+             row2.put("int",43);
+             tbl.addRow(row2);
+             Row row3=new Row("3");
+             row3.put("name","Kasper L");
+             row3.put("int",44);
+             tbl.addRow(row3);
+             Row row4=new Row("4");
+             row4.put("name","Christer");
+             row4.put("int",45);
+             tbl.addRow(row4);
+             
+             System.out.print(" + Testing basic row storage ... ");
+             TupleStream it=tbl.getRows();
+             int cnt=0;
+             while(it.hasNext()){
+                 it.next();
+                 cnt++;
+             }
+             if(cnt!=4)die("Wrong number of rows in table after adding 4 rows");
+             Row tmp=tbl.getRow("1");
+             if(tmp==null)die("Could not fetch the first row");
+             if(!tmp.getString("string").equals("Hello World!"))die("String value incorrect after storage");
+             if(tmp.getInt("int")!=42)die("Int value incorrect after storage");
+             if(tmp.getLong("long")!=314l)die("Long value incorrect after storage");
+             if(tmp.getFloat("float")!=3.14f)die("Float value incorrect after storage");
+             if(tmp.getDouble("double")!=3.1415d)die("Double value incorrect after storage");
+             if(!tmp.getTimestamp("timestamp").equals(dt))die("Timestamp value incorrect after storage");
+             if(!tmp.getBoolean("boolean"))die("Boolean value incorrect after storage");
+             System.out.println("OK");
+             
+             System.out.print(" + Testing bulk fetch order ... ");
+             List<String> lst=new ArrayList<String>();
+             lst.add("3");
+             lst.add("1");
+             lst.add("2");
+             lst.add("4");
+             lst.add("2");
+             it=tbl.getRows(lst);
+             tmp=it.next();
+             if(!tmp.getId().equals("3"))die("Elements returned in wrong order");
+             tmp=it.next();
+             if(!tmp.getId().equals("1"))die("Elements returned in wrong order");
+             tmp=it.next();
+             if(!tmp.getId().equals("2"))die("Elements returned in wrong order");
+             tmp=it.next();
+             if(!tmp.getId().equals("4"))die("Elements returned in wrong order");
+             System.out.println("OK");
+             
+             System.out.print(" + Testing RowMatcher ... ");
+             RowMatcher m=new RowMatcher("name",RowMatcher.STARTSWITH,new Value("Kasper"));
+             it=tbl.getRows(m);
+             cnt=0;
+             while(it.hasNext()){
+                 it.next();
+                 cnt++;
+             }
+             if(cnt!=2)die("String based RowMatcher failed using STARTSWITH");
+             m=new RowMatcher("int",RowMatcher.GREATERTHAN,new Value(44));
+             it=tbl.getRows(m);
+             tmp=it.next();
+             if(!tmp.getId().equals("4"))die("Int based RowMatcher failed using GREATERTHAN");
+             // TODO: Add full test of all types and comparison types in RowMatcher
+             System.out.println("OK");
+             
+             System.out.print(" + Testing row updates and deletes ... ");
+             tbl.deleteRow(row2);
+             row4.put("int",8192);
+             tbl.updateRow(row4);
+             it=tbl.getRows();
+             cnt=0;
+             while(it.hasNext()){
+                 it.next();
+                 cnt++;
+             }
+             if(cnt!=3)die("Wrong number of rows returned");
+             tmp=tbl.getRow("4");
+             if(tmp.getInt("int")!=8192)die("Wrong int value returned after update");
+             
+             row1.put("longtext","Hello world again and again and again and again.....");
+             tbl.updateRow(row1);
+             tmp=tbl.getRow("1");
+             if(!tmp.getString("longtext").equals("Hello world again and again and again and again....."))die("Wrong string value returned after update");
+             
+             System.out.println("OK");
+             
+             System.out.print(" + Testing close and reopen ... ");
+             tbl.close();
+             tbl=new DualFileTable("CoreTestData",".");
+             it=tbl.getRows();
+             cnt=0;
+             while(it.hasNext()){
+                it.next();
+                cnt++;
+             }
+             if(cnt!=3)die("Wrong number of rows returned");
+             tmp=tbl.getRow("4");
+             if(tmp.getInt("int")!=8192)die("Wrong int value returned after close");
+             tmp=tbl.getRow("1");
+             if(!tmp.getString("longtext").equals("Hello world again and again and again and again....."))die("Wrong string value returned after update");
+
+             System.out.println("OK");
+              
+             System.out.print(" + Testing large data sets ... ");
+             tbl.deleteFiles();
+             tbl=new DualFileTable("CoreTestData",".");
+             for(int i=0;i<50000;i++){
+                 tmp=new Row(i+"_"+Math.random());
+                 tmp.put("data1",Math.random());
+                 tmp.put("one",1);
+                 tbl.addRow(tmp);
+             }
+             tbl.close();
+             tbl=new DualFileTable("CoreTestData",".");
+             it=tbl.getRows();
+             cnt=0;
+             while(it.hasNext()){
+                it.next();
+                cnt++;
+             }
+             if(cnt!=50000)die("Wrong number of rows returned");
+             it=tbl.getRows();
+             cnt=0;
+             while(it.hasNext()){
+                tmp=it.next();
+                cnt+=tmp.getInt("one");
+             }
+             if(cnt!=50000)die("Wrong numeric data returned");
+             
+             tmp=new Row("foo");
+             tmp.put("bar","baz");
+             tbl.addRow(tmp);
+             tbl.close();
+             tbl=new DualFileTable("CoreTestData",".");
+             tmp=tbl.getRow("foo");
+             if(!tmp.getString("bar").equals("baz"))die("Wrong string data returned");
+             
+             it=tbl.getRows();
+              cnt=0;
+              while(it.hasNext()){
+                 it.next();
+                 cnt++;
+              }
+              if(cnt!=50001)die("Wrong number of rows returned");
+             System.out.println("OK");
+             
+             System.exit(0);
+             tbl.close();
+             tbl.deleteFiles();
+        }catch(Exception e){
+            e.printStackTrace();
+        }   
+     }
+     public static void die(String reason){
+         System.out.println("ERR");
+         System.out.println(" ! "+reason);
+         System.exit(0);
+     }
+ }
\ No newline at end of file
diff --git a/Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/test/ParallelPerformanceTest.java b/Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/test/ParallelPerformanceTest.java
new file mode 100644 (file)
index 0000000..8fb5a53
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * 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 ParallelPerformanceTest extends BasicTest implements Runnable{
+    
+    long writetime;
+    long readtime;
+    long randomtime;
+    
+    public ParallelPerformanceTest(){
+        String path="/Volumes/My Book/test/";
+        try{
+            int records=50000;
+            for(int i=1;i<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=new DualFileTable("Performance-test",path,Table.PAGED);
+                benchmark(table,i,(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 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){
+        new ParallelPerformanceTest();
+    }
+    
+    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 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(Table table,int records, String id) throws IOException{
+        long pre=System.currentTimeMillis();
+        for(int i=0;i<records;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();
+        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));
+        }
+        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/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/test/ParallelThread.java b/Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/test/ParallelThread.java
new file mode 100644 (file)
index 0000000..2183470
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * 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;
+    
+    public ParallelThread(ParallelPerformanceTest 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=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/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/test/PerformanceTest.java b/Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/test/PerformanceTest.java
new file mode 100644 (file)
index 0000000..e8640e6
--- /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.test;
+ import com.solidosystems.tuplesoup.core.*;
+ import com.solidosystems.tuplesoup.filter.*;
+  
+ import java.util.*;
+ import java.io.*;
+
+
+public class PerformanceTest extends BasicTest{
+    public PerformanceTest(){
+        try{
+            outbr("Running DualFileTable Performance test");
+            outbr(1,"10000 small records");
+            
+            outbr(2,"Memory index");
+            Table table=new DualFileTable("Performance-test","./",Table.MEMORY);
+            benchmarkSmall(table,10000);
+            table.close();
+            table.deleteFiles();
+            
+            outbr(2,"Flat index");
+            table=new DualFileTable("Performance-test","./",Table.FLAT);
+            benchmarkSmall(table,10000);
+            table.close();
+            table.deleteFiles();
+            
+            outbr(2,"Paged index");
+            table=new DualFileTable("Performance-test","./",Table.PAGED);
+            benchmarkSmall(table,10000);
+            table.close();
+            table.deleteFiles();
+            
+            outbr(1,"20000 large records");
+            
+            outbr(2,"Memory index");
+            table=new DualFileTable("Performance-test","./",Table.MEMORY);
+            benchmarkLarge(table,20000);
+            table.close();
+            table.deleteFiles();
+            
+            outbr(2,"Flat index");
+            table=new DualFileTable("Performance-test","./",Table.FLAT);
+            benchmarkLarge(table,20000);
+            table.close();
+            table.deleteFiles();
+            
+            outbr(2,"Paged index");
+            table=new DualFileTable("Performance-test","./",Table.PAGED);
+            benchmarkLarge(table,20000);
+            table.close();
+            table.deleteFiles();
+            
+            outbr(1,"30000 large records");
+            
+            outbr(2,"Memory index");
+            table=new DualFileTable("Performance-test","./",Table.MEMORY);
+            benchmarkLarge(table,30000);
+            table.close();
+            table.deleteFiles();
+            
+            outbr(2,"Flat index");
+            table=new DualFileTable("Performance-test","./",Table.FLAT);
+            benchmarkLarge(table,30000);
+            table.close();
+            table.deleteFiles();
+            
+            outbr(2,"Paged index");
+            table=new DualFileTable("Performance-test","./",Table.PAGED);
+            benchmarkLarge(table,30000);
+            table.close();
+            table.deleteFiles();
+            
+            outbr("Running HashedTable Performance test");
+            outbr(1,"10000 small records");
+            
+            outbr(2,"Memory index");
+            table=new HashedTable("Performance-test","./",Table.MEMORY);
+            benchmarkSmall(table,10000);
+            table.close();
+            table.deleteFiles();
+            
+            outbr(2,"Flat index");
+            table=new HashedTable("Performance-test","./",Table.FLAT);
+            benchmarkSmall(table,10000);
+            table.close();
+            table.deleteFiles();
+            
+            outbr(2,"Paged index");
+            table=new HashedTable("Performance-test","./",Table.PAGED);
+            benchmarkSmall(table,10000);
+            table.close();
+            table.deleteFiles();
+            
+            outbr(1,"20000 large records");
+            
+            outbr(2,"Memory index");
+            table=new HashedTable("Performance-test","./",Table.MEMORY);
+            benchmarkLarge(table,20000);
+            table.close();
+            table.deleteFiles();
+            
+            outbr(2,"Flat index");
+            table=new HashedTable("Performance-test","./",Table.FLAT);
+            benchmarkLarge(table,20000);
+            table.close();
+            table.deleteFiles();
+            
+            outbr(2,"Paged index");
+            table=new HashedTable("Performance-test","./",Table.PAGED);
+            benchmarkLarge(table,20000);
+            table.close();
+            table.deleteFiles();
+            
+            outbr(1,"30000 large records");
+            
+            outbr(2,"Memory index");
+            table=new HashedTable("Performance-test","./",Table.MEMORY);
+            benchmarkLarge(table,30000);
+            table.close();
+            table.deleteFiles();
+            
+            outbr(2,"Flat index");
+            table=new HashedTable("Performance-test","./",Table.FLAT);
+            benchmarkLarge(table,30000);
+            table.close();
+            table.deleteFiles();
+            
+            outbr(2,"Paged index");
+            table=new HashedTable("Performance-test","./",Table.PAGED);
+            benchmarkLarge(table,30000);
+            table.close();
+            table.deleteFiles();
+            
+            
+        }catch(Exception e){
+            e.printStackTrace();
+        }
+    }
+    public static void main(String[] args){
+        new PerformanceTest();
+    }
+    
+    public void benchmarkSmall(Table table,int records) throws IOException{
+        long pre=System.currentTimeMillis();
+        for(int i=0;i<records;i++){
+            Row row=new Row(""+i);
+            row.put("key1","foo");
+            table.addRow(row);
+        }
+        long post=System.currentTimeMillis();
+        outbr(3,"Write "+(post-pre)+" ms");
+        pre=System.currentTimeMillis();
+        TupleStream stream=table.getRows();
+        while(stream.hasNext()){
+            stream.next();
+        }
+        post=System.currentTimeMillis();
+        outbr(3,"Read "+(post-pre)+" ms");
+        pre=System.currentTimeMillis();
+        for(int i=0;i<records;i++){
+            Row row=table.getRow(""+(int)(Math.random()*records));
+        }
+        post=System.currentTimeMillis();
+        outbr(3,"Random read "+(post-pre)+" ms");
+        
+        // printStats(table.readStatistics());
+    }
+    
+    public void benchmarkLarge(Table table,int records) throws IOException{
+        long pre=System.currentTimeMillis();
+        for(int i=0;i<records;i++){
+            Row row=new Row(""+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();
+        outbr(3,"Write "+(post-pre)+" ms");
+        pre=System.currentTimeMillis();
+        TupleStream stream=table.getRows();
+        while(stream.hasNext()){
+            stream.next();
+        }
+        post=System.currentTimeMillis();
+        outbr(3,"Read "+(post-pre)+" ms");
+        pre=System.currentTimeMillis();
+        for(int i=0;i<records;i++){
+            Row row=table.getRow(""+(int)(Math.random()*records));
+        }
+        post=System.currentTimeMillis();
+        outbr(3,"Random read "+(post-pre)+" ms");
+        
+        // printStats(table.readStatistics());
+    }
+    
+    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/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/test/RowTest.java b/Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/test/RowTest.java
new file mode 100644 (file)
index 0000000..0616357
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * 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 java.util.*;
+import java.io.*;
+
+public class RowTest extends BasicTest{
+    public RowTest(){
+        
+    }
+    public void runTest(){
+        outbr("Running core Row functionality test");
+        outbr(1,"Constructor initializers");
+        
+        out(2,"String");
+        Row row=new Row("FooBarBaz");
+        if(!row.getId().equals("FooBarBaz")){
+            err("Id value not correct");
+        }else if(row.getKeyCount()!=0){
+            err("Key count not correct");
+        }else ok();
+        
+        outbr(1,"Setting and getting values");
+        
+        out(2,"Setting values");
+        row.put("key1",new Value(3.1415f));
+        row.put("key2","FooBar");
+        row.put("key3",1234);
+        row.put("key4",5123456789l);
+        row.put("key5",3.1415f);
+        row.put("key6",3.141592653689793284626433d);
+        row.put("key7",true);
+        row.put("key8",new java.util.Date(5));
+        if(row.getKeyCount()!=8){
+            err("Key count not correct");
+        }else ok();
+        
+        out(2,"Getting values");
+        Value val1=new Value("FooBar");
+        Value val2=new Value(1234);
+        Value val3=new Value(5123456789l);
+        Value val4=new Value(3.1415f);
+        Value val5=new Value(3.141592653689793284626433d);
+        Value val6=new Value(true);
+        Value val7=new Value(new java.util.Date(5));
+        if(!row.get("key1").equals(val4)){
+            err("Wrong Value value returned");
+        }else if(!row.get("key2").equals(val1)){
+            err("Wrong Value value returned");
+        }else if(!row.get("key3").equals(val2)){
+            err("Wrong Value value returned");
+        }else if(!row.get("key4").equals(val3)){
+            err("Wrong Value value returned");
+        }else if(!row.get("key5").equals(val4)){
+            err("Wrong Value value returned");
+        }else if(!row.get("key6").equals(val5)){
+            err("Wrong Value value returned");
+        }else if(!row.get("key7").equals(val6)){
+            err("Wrong Value value returned");
+        }else if(row.getKeyCount()!=8){
+            err("Wrong key count returned");
+        }else if(row.getFloat("key1")!=3.1415f){
+            err("Wrong value returned from getFloat");
+        }else if(!row.getString("key2").equals("FooBar")){
+            err("Wrong value returned from getString");
+        }else if(row.getInt("key3")!=1234){
+            err("Wrong value returned from getInt");
+        }else if(row.getLong("key4")!=5123456789l){
+            err("Wrong value returned from getLong");
+        }else if(row.getFloat("key5")!=3.1415f){
+            err("Wrong value returned from getFloat");
+        }else if(row.getDouble("key6")!=3.141592653689793284626433d){
+            err("Wrong value returned from getDouble");
+        }else if(!row.getBoolean("key7")){
+            err("Wrong value returned from getBoolean");
+        }else if(row.getTimestamp("key8").getTime()!=5){
+            err("Wrong value returned from getTimestamp");
+        }else ok();
+        
+        outbr(1,"Stream reading and writing");
+        try{
+             out(2,"Writing to stream");
+             ByteArrayOutputStream bout=new ByteArrayOutputStream();
+             DataOutputStream dout=new DataOutputStream(bout);
+             
+             row.writeToStream(dout);
+             row.put("key9","ExtraBonusValue");
+             row.writeToStream(dout);
+             dout.flush();
+             ok();
+             
+             out(2,"Reading from stream");
+             byte[] buf=bout.toByteArray();
+             DataInputStream din=new DataInputStream(new ByteArrayInputStream(buf));
+             row=Row.readFromStream(din);
+             if(row.getKeyCount()!=8){
+                 err("Wrong key count returned");
+             }else if(row.getFloat("key1")!=3.1415f){
+                  err("Wrong value returned from getFloat");
+             }else if(!row.getString("key2").equals("FooBar")){
+                  err("Wrong value returned from getString");
+             }else if(row.getInt("key3")!=1234){
+                  err("Wrong value returned from getInt");
+             }else if(row.getLong("key4")!=5123456789l){
+                  err("Wrong value returned from getLong");
+             }else if(row.getFloat("key5")!=3.1415f){
+                  err("Wrong value returned from getFloat");
+             }else if(row.getDouble("key6")!=3.141592653689793284626433d){
+                  err("Wrong value returned from getDouble");
+             }else if(!row.getBoolean("key7")){
+                  err("Wrong value returned from getBoolean");
+             }else if(row.getTimestamp("key8").getTime()!=5){
+                 err("Wrong value returned from getTimestamp");
+             }else{
+                 row=Row.readFromStream(din);
+                 if(!row.getString("key9").equals("ExtraBonusValue")){
+                     err("Wrong value returned on second row written");
+                 }else ok();
+             }
+              
+        }catch(Exception e){
+            err("Exception occured "+e);
+        }
+        
+        printErrorSummary();
+    }
+    public static void main(String args[]){
+        RowTest rowt=new RowTest();
+        rowt.runTest();
+    }
+}
\ No newline at end of file
diff --git a/Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/test/SortTest.java b/Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/test/SortTest.java
new file mode 100644 (file)
index 0000000..28ccfa7
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * 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 SortTest{
+    public static void main(String[] args){
+        String[] first_names={"Adolf","Anders","Bo","Christer","Daniel","Erik","Frederik","Georg","Hans","Hans-Christian","Ingolf","Jens","Kasper","Lars","Mads","Niels","Ole","Per","Rasmus","Søren","Tue","Ulrik"};
+        String[] last_names={"Jeppesen","Andersen","Hansen","Nielsen","Langer","Sørensen","Shore","Crane","Saustrup"};
+        String[] domains={"email.lan","mymail.lan","lukewarmmail.lan","lessthanfree.lan","devnull.lan"};
+        try{
+            System.out.println("TupleSoup Performance Test");
+            System.out.println(" + Simple user data");
+            Table tbl=new DualFileTable("CoreTestData",".");
+            tbl.deleteFiles();
+            tbl=new DualFileTable("CoreTestData",".",Table.PAGED);
+            tbl.setIndexCacheSize(10000);
+            int rows=100000;
+            System.out.print("   - Adding "+rows+" tuples in random order ... ");
+            long pre=System.currentTimeMillis();
+            long size=0;
+            List<String>flst=new ArrayList<String>();
+            for(int i=0;i<rows;i++){
+                flst.add(""+i);
+            }
+            Collections.shuffle(flst);
+            
+            for(int i=0;i<rows;i++){
+                Row tmp=new Row(flst.get(i));
+                // Row tmp=new Row(""+i);
+                tmp.put("name",first_names[(int)(Math.random()*first_names.length)]+" "+last_names[(int)(Math.random()*last_names.length)]);
+                tmp.put("age",(float)(Math.random()*60f)+20f);
+                // tmp.put("age",i);
+                tmp.put("sex","male");
+                tmp.put("zipcode",(int)(Math.random()*8200f)+1000);
+                tmp.put("email",first_names[(int)(Math.random()*first_names.length)].toLowerCase()+"@"+domains[(int)(Math.random()*domains.length)]);
+                tbl.addRow(tmp);
+                size+=tmp.getSize();
+            }
+            long post=System.currentTimeMillis();
+            System.out.println((post-pre)+"ms avg:"+((post-pre)/((float)rows))+"ms "+(size/1024)+"kb "+((size/1024)/((post-pre)/1000f))+"kb/s "+(size/rows)+"b/row");
+            
+            size=0;
+            System.out.print("   - Adding "+rows+" tuples to RowBuffer ... ");
+            RowBuffer buf=new RowBuffer("./foobarbaz");
+            buf.setCacheSize(1024000);
+            pre=System.currentTimeMillis();
+            for(int i=0;i<rows;i++){
+                Row tmp=new Row(flst.get(i));
+                // Row tmp=new Row(""+i);
+                tmp.put("name",first_names[(int)(Math.random()*first_names.length)]+" "+last_names[(int)(Math.random()*last_names.length)]);
+                tmp.put("age",(float)(Math.random()*60f)+20f);
+                // tmp.put("age",i);
+                tmp.put("sex","male");
+                tmp.put("zipcode",(int)(Math.random()*8200f)+1000);
+                tmp.put("email",first_names[(int)(Math.random()*first_names.length)].toLowerCase()+"@"+domains[(int)(Math.random()*domains.length)]);
+                buf.addRow(tmp);
+                size+=tmp.getSize();
+            }
+            post=System.currentTimeMillis();
+            System.out.println((post-pre)+"ms avg:"+((post-pre)/((float)rows))+"ms "+(size/1024)+"kb "+((size/1024)/((post-pre)/1000f))+"kb/s "+(size/rows)+"b/row");
+            
+            
+            
+            System.out.print("   - Fetching all rows from RowBuffer sequentially in bulk ... ");
+            pre=System.currentTimeMillis();
+            buf.prepare();
+            while(buf.hasNext()){
+                Row r2=buf.next();
+            }
+            post=System.currentTimeMillis();
+            System.out.println((post-pre)+"ms "+((post-pre)/(float)rows)+"ms/row");
+            
+            
+            System.out.print("   - Fetching all rows from table sequentially in bulk ... ");
+            pre=System.currentTimeMillis();
+            TupleStream it=tbl.getRows();
+            while(it.hasNext()){
+                Row r2=it.next();
+            }
+            post=System.currentTimeMillis();
+            System.out.println((post-pre)+"ms "+((post-pre)/(float)rows)+"ms/row");
+            long fetchtime=post-pre;
+            
+            System.out.print("   - Fetching all rows sorted in bulk (JavaSort) ... ");
+            pre=System.currentTimeMillis();
+            JavaSort sort=new JavaSort();
+            sort.initialize("./tmpsort",tbl.getRows(),"age",SortRule.ASC);
+            while(sort.hasNext()){
+                Row r2=sort.next();
+                // System.out.println(r2.getString("age"));
+            }
+            post=System.currentTimeMillis();
+            System.out.println(((post-pre)-fetchtime)+"ms "+(((post-pre)-fetchtime)/(float)rows)+"ms/row");
+           
+            System.out.print("   - Fetching all rows sorted in bulk (MergeSort 4mb cache) ... ");
+            pre=System.currentTimeMillis();
+            MergeSort msort=new MergeSort(4096000);
+            msort.initialize("./tmpsort",tbl.getRows(),"age",SortRule.ASC);
+            while(msort.hasNext()){
+                Row r2=msort.next();
+            }
+            post=System.currentTimeMillis();
+            System.out.println(((post-pre)-fetchtime)+"ms "+(((post-pre)-fetchtime)/(float)rows)+"ms/row ");
+
+            System.out.print("   - Fetching all rows sorted in bulk (MergeSort 2mb cache) ... ");
+            pre=System.currentTimeMillis();
+            msort=new MergeSort(2048000);
+            msort.initialize("./tmpsort",tbl.getRows(),"age",SortRule.ASC);
+            while(msort.hasNext()){
+                Row r2=msort.next();
+                // System.out.println(r2.getString("age"));
+            }
+            post=System.currentTimeMillis();
+            System.out.println(((post-pre)-fetchtime)+"ms "+(((post-pre)-fetchtime)/(float)rows)+"ms/row ");
+
+            System.out.print("   - Fetching all rows sorted in bulk (MergeSort 1mb cache) ... ");
+            pre=System.currentTimeMillis();
+            msort=new MergeSort(1024000);
+            msort.initialize("./tmpsort",tbl.getRows(),"age",SortRule.ASC);
+            while(msort.hasNext()){
+                Row r2=msort.next();
+                // System.out.println(r2.getString("age"));
+            }
+            post=System.currentTimeMillis();
+            System.out.println(((post-pre)-fetchtime)+"ms "+(((post-pre)-fetchtime)/(float)rows)+"ms/row ");
+            
+            
+            System.out.print("   - Fetching all rows sorted in bulk (MergeSort 512kb cache) ... ");
+            pre=System.currentTimeMillis();
+            msort=new MergeSort(512000);
+            msort.initialize("./tmpsort",tbl.getRows(),"age",SortRule.ASC);
+            while(msort.hasNext()){
+                Row r2=msort.next();
+                // System.out.println(r2.getString("age"));
+            }
+            post=System.currentTimeMillis();
+            System.out.println(((post-pre)-fetchtime)+"ms "+(((post-pre)-fetchtime)/(float)rows)+"ms/row");
+            
+            
+            tbl.deleteFiles();
+        }catch(Exception e){
+            e.printStackTrace();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/test/TableTest.java b/Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/test/TableTest.java
new file mode 100644 (file)
index 0000000..e9f009d
--- /dev/null
@@ -0,0 +1,396 @@
+/*
+ * 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 java.util.*;
+import java.io.*;
+
+public class TableTest extends BasicTest{
+    public TableTest(){
+        
+    }
+    
+    public void runTest(){
+        outbr("Running core DualFileTable functionality test");
+        try{
+            outbr(1,"Creating new table");
+            
+            out(2,"Default index");
+            Table table=new DualFileTable("TableTest-test","./");
+            if(!table.getTitle().equals("TableTest-test")){
+                err("Wrong table title returned");
+            }else if(!table.getLocation().equals("./")){
+                err("Wrong table location returned");
+            }else{
+                table.close();
+                table.deleteFiles();
+                ok();
+            }
+            out(2,"Memory index");
+            table=new DualFileTable("TableTest-test","./",Table.MEMORY);
+            table.close();
+            table.deleteFiles();
+            ok();
+            
+            out(2,"Flat index");
+            table=new DualFileTable("TableTest-test","./",Table.FLAT);
+            table.close();
+            table.deleteFiles();
+            ok();
+            
+            out(2,"Paged index");
+            table=new DualFileTable("TableTest-test","./",Table.PAGED);
+            table.close();
+            table.deleteFiles();
+            ok();
+            
+            outbr(1,"Testing add, update, delete and read of data");
+            
+            
+            
+            outbr(2,"Memory index");
+            table=new DualFileTable("TableTest-test","./",Table.MEMORY);
+            testIndex(table);
+            table.close();
+            table.deleteFiles();
+            
+            outbr(2,"Flat index");
+            table=new DualFileTable("TableTest-test","./",Table.FLAT);
+            testIndex(table);
+            table.close();
+            table.deleteFiles();
+            
+            outbr(2,"Paged index");
+            table=new DualFileTable("TableTest-test","./",Table.PAGED);
+            testIndex(table);
+            table.close();
+            table.deleteFiles();
+            
+            outbr(1,"Close and reopen tables after bulk operations");
+            out(2,"Memory index");
+            table=new DualFileTable("TableTest-test","./",Table.MEMORY);
+            bulkOperate(table);
+            table.close();
+            table=new DualFileTable("TableTest-test","./",Table.MEMORY);
+            boolean bad=false;
+            TupleStream stream=table.getRows();
+            int count=0;
+            while(stream.hasNext()){
+                Row row=stream.next();
+                if(row.getDouble("key3")!=3.1415)bad=true;
+                count++;
+            }
+            if(bad){
+                err("Bad values returned after reopening table");
+            }else if(count!=5000){
+                err("Wrong number of rows returned after reopening table");
+            }else ok();
+            table.close();
+            table.deleteFiles();
+            
+            out(2,"Flat index");
+            table=new DualFileTable("TableTest-test","./",Table.FLAT);
+            bulkOperate(table);
+            table.close();
+            table=new DualFileTable("TableTest-test","./",Table.FLAT);
+             bad=false;
+             stream=table.getRows();
+             count=0;
+            while(stream.hasNext()){
+                Row row=stream.next();
+                if(row.getDouble("key3")!=3.1415)bad=true;
+                count++;
+            }
+            if(bad){
+                err("Bad values returned after reopening table");
+            }else if(count!=5000){
+                err("Wrong number of rows returned after reopening table");
+            }else ok();
+            table.close();
+            table.deleteFiles();
+            
+            out(2,"Paged index");
+            table=new DualFileTable("TableTest-test","./",Table.PAGED);
+            bulkOperate(table);
+            table.close();
+            table=new DualFileTable("TableTest-test","./",Table.PAGED);
+             bad=false;
+             stream=table.getRows();
+             count=0;
+            while(stream.hasNext()){
+                Row row=stream.next();
+                if(row.getDouble("key3")!=3.1415)bad=true;
+                count++;
+            }
+            if(bad){
+                err("Bad values returned after reopening table");
+            }else if(count!=5000){
+                err("Wrong number of rows returned after reopening table");
+            }else ok();
+            table.close();
+            table.deleteFiles();
+            
+        }catch(Exception e){
+            err("Exception occured while testing "+e);
+        }
+        outbr("Running core HashedTable functionality test");
+        try{
+            outbr(1,"Creating new table");
+            
+            out(2,"Default index");
+            Table table=new HashedTable("TableTest-test","./");
+            if(!table.getTitle().equals("TableTest-test")){
+                err("Wrong table title returned");
+            }else if(!table.getLocation().equals("./")){
+                err("Wrong table location returned");
+            }else{
+                table.close();
+                table.deleteFiles();
+                ok();
+            }
+            out(2,"Memory index");
+            table=new HashedTable("TableTest-test","./",Table.MEMORY);
+            table.close();
+            table.deleteFiles();
+            ok();
+            
+            out(2,"Flat index");
+            table=new HashedTable("TableTest-test","./",Table.FLAT);
+            table.close();
+            table.deleteFiles();
+            ok();
+            
+            out(2,"Paged index");
+            table=new HashedTable("TableTest-test","./",Table.PAGED);
+            table.close();
+            table.deleteFiles();
+            ok();
+            
+            outbr(1,"Testing add, update, delete and read of data");
+            
+            
+            
+            outbr(2,"Memory index");
+            table=new HashedTable("TableTest-test","./",Table.MEMORY);
+            testIndex(table);
+            table.close();
+            table.deleteFiles();
+            
+            outbr(2,"Flat index");
+            table=new HashedTable("TableTest-test","./",Table.FLAT);
+            testIndex(table);
+            table.close();
+            table.deleteFiles();
+            
+            outbr(2,"Paged index");
+            table=new HashedTable("TableTest-test","./",Table.PAGED);
+            testIndex(table);
+            table.close();
+            table.deleteFiles();
+            
+            outbr(1,"Close and reopen tables after bulk operations");
+            out(2,"Memory index");
+            table=new HashedTable("TableTest-test","./",Table.MEMORY);
+            bulkOperate(table);
+            table.close();
+            table=new HashedTable("TableTest-test","./",Table.MEMORY);
+            boolean bad=false;
+            TupleStream stream=table.getRows();
+            int count=0;
+            while(stream.hasNext()){
+                Row row=stream.next();
+                if(row.getDouble("key3")!=3.1415)bad=true;
+                count++;
+            }
+            if(bad){
+                err("Bad values returned after reopening table");
+            }else if(count!=5000){
+                err("Wrong number of rows returned after reopening table");
+            }else ok();
+            table.close();
+            table.deleteFiles();
+            
+            out(2,"Flat index");
+            table=new HashedTable("TableTest-test","./",Table.FLAT);
+            bulkOperate(table);
+            table.close();
+            table=new HashedTable("TableTest-test","./",Table.FLAT);
+             bad=false;
+             stream=table.getRows();
+             count=0;
+            while(stream.hasNext()){
+                Row row=stream.next();
+                if(row.getDouble("key3")!=3.1415)bad=true;
+                count++;
+            }
+            if(bad){
+                err("Bad values returned after reopening table");
+            }else if(count!=5000){
+                err("Wrong number of rows returned after reopening table");
+            }else ok();
+            table.close();
+            table.deleteFiles();
+            
+            out(2,"Paged index");
+            table=new HashedTable("TableTest-test","./",Table.PAGED);
+            bulkOperate(table);
+            table.close();
+            table=new HashedTable("TableTest-test","./",Table.PAGED);
+             bad=false;
+             stream=table.getRows();
+             count=0;
+            while(stream.hasNext()){
+                Row row=stream.next();
+                if(row.getDouble("key3")!=3.1415)bad=true;
+                count++;
+            }
+            if(bad){
+                err("Bad values returned after reopening table");
+            }else if(count!=5000){
+                err("Wrong number of rows returned after reopening table");
+            }else ok();
+            table.close();
+            table.deleteFiles();
+            
+        }catch(Exception e){
+            err("Exception occured while testing "+e);
+        }
+    }
+    
+    public void bulkOperate(Table table) throws IOException{
+        for(int i=0;i<10000;i++){
+            Row row=new Row(""+i);
+            row.put("key1","foo");
+            row.put("key2",i);
+            table.addRow(row);
+        }
+        for(int i=0;i<5000;i++){
+            Row row=table.getRow(""+i);
+            table.deleteRow(row);
+        }
+        for(int i=5000;i<10000;i++){
+            Row row=table.getRow(""+i);
+            row.put("key3",3.1415);
+            row.put("key2",row.getInt("key2")+1);
+            table.updateRow(row);
+        }
+    }
+    
+    public void testIndex(Table table) throws IOException{
+        Row row1=new Row("1");
+        row1.put("key1",1);
+        row1.put("key2","foo");
+        
+        Row row2=new Row("2");
+        row2.put("key1",2);
+        row2.put("key2","foo");
+        
+        Row row3=new Row("3");
+        row3.put("key1",3);
+        row3.put("key2","foo");
+        
+        Row row4=new Row("4");
+        row4.put("key1",4);
+        row4.put("key2","foo");
+        
+        Row row5=new Row("5");
+        row5.put("key1",5);
+        row5.put("key2","foo");
+        
+        out(3,"Adding rows");
+        table.addRow(row1);
+        table.addRow(row2);
+        table.addRow(row3);
+        table.addRow(row4);
+        table.addRow(row5);
+        ok();
+        
+        out(3,"Reading rows");
+        TupleStream stream=table.getRows();
+        int count=0;
+        while(stream.hasNext()){
+            Row tmp=stream.next();
+            count++;
+        }
+        if(count!=5){
+            err("Wrong number of rows returned");
+        }else{
+            Row tmp=table.getRow("1");
+            if(tmp==null){
+                err("Row not found");
+            }else{
+                if(tmp.getInt("key1")!=1){
+                    err("Wrong value in returned row");
+                }else{
+                    tmp=table.getRow("5");
+                    if(tmp==null){
+                        err("Row not found");
+                    }else{
+                        if(tmp.getInt("key1")!=5){
+                            err("Wrong value in returned row");
+                        }else{
+                            ok();
+                        }
+                    }
+                }
+            }
+        }
+        
+        out(3,"Updating rows");
+        Row tmp=table.getRow("1");
+        tmp.put("key3","bar");
+        table.updateRow(tmp);
+        tmp=table.getRow("1");
+        if(!tmp.getString("key3").equals("bar")){
+            err("Wrong value returned after update");
+        }else ok();
+        
+        out(3,"Deleting rows");
+        tmp=table.getRow("1");
+        table.deleteRow(tmp);
+        stream=table.getRows();
+        count=0;
+        while(stream.hasNext()){
+            tmp=stream.next();
+            count++;
+        }
+        if(count!=4){
+            err("Wrong number of rows returned");
+        }else ok();
+    }
+    
+    public static void main(String args[]){
+        TableTest tablet=new TableTest();
+        tablet.runTest();
+    }
+}
\ No newline at end of file
diff --git a/Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/test/ValueTest.java b/Robust/Transactions/origtuplesoup/tuplesoup/src/com/solidosystems/tuplesoup/test/ValueTest.java
new file mode 100644 (file)
index 0000000..7d66702
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+ * 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 java.util.*;
+import java.io.*;
+
+public class ValueTest extends BasicTest{
+    private Value val=null;
+    
+    public ValueTest(){
+    }
+    public void runTest(){
+        outbr("Running core Value functionality test");
+        
+        outbr(1,"Constructor initializers");
+        
+        out(2,"String");
+        val=new Value("FooBar");
+        if(val.getType()!=Value.STRING){
+            err("Numerical type incorrect");
+        }else{
+            if(!val.getTypeName().equals("string")){
+                err("Type name incorrect");
+            }else{
+                if(!val.getString().equals("FooBar")){
+                    err("Returned value incorrect");
+                }else ok();
+            }
+        }
+        
+        out(2,"Timestamp");
+        val=new Value(new java.util.Date(5));
+        if(val.getType()!=Value.TIMESTAMP){
+            err("Numerical type incorrect");
+        }else{
+            if(!val.getTypeName().equals("timestamp")){
+                err("Type name incorrect");
+            }else{
+                if(val.getTimestamp().getTime()!=5){
+                    err("Returned value incorrect");
+                }else ok();
+            }
+        }
+        
+        out(2,"Null");
+        val=new Value();
+        if(val.getType()!=Value.NULL){
+            err("Numerical type incorrect");
+        }else{
+            if(!val.getTypeName().equals("null")){
+                err("Type name incorrect");
+            }else ok();
+        }
+        
+        out(2,"Int");
+        val=new Value(123456789);
+        if(val.getType()!=Value.INT){
+            err("Numerical type incorrect");
+        }else{
+            if(!val.getTypeName().equals("int")){
+                err("Type name incorrect");
+            }else{
+                if(val.getInt()!=123456789){
+                    err("Returned value incorrect");
+                }else ok();
+            }
+        }
+        
+        out(2,"Long");
+        val=new Value(5123456789l);
+        if(val.getType()!=Value.LONG){
+            err("Numerical type incorrect");
+        }else{
+            if(!val.getTypeName().equals("long")){
+                err("Type name incorrect");
+            }else{
+                if(val.getLong()!=5123456789l){
+                    err("Returned value incorrect");
+                }else ok();
+            }
+        }
+        
+        out(2,"Float");
+        val=new Value(3.141592f);
+        if(val.getType()!=Value.FLOAT){
+            err("Numerical type incorrect");
+        }else{
+            if(!val.getTypeName().equals("float")){
+                err("Type name incorrect");
+            }else{
+                if(val.getFloat()!=3.141592f){
+                    err("Returned value incorrect");
+                }else ok();
+            }
+        }
+
+        out(2,"Double");
+        val=new Value(3.141592653689793284626433d);
+        if(val.getType()!=Value.DOUBLE){
+            err("Numerical type incorrect");
+        }else{
+            if(!val.getTypeName().equals("double")){
+                err("Type name incorrect");
+            }else{
+                if(val.getDouble()!=3.141592653689793284626433d){
+                    err("Returned value incorrect");
+                }else ok();
+            }
+        }
+        
+        out(2,"Boolean");
+        val=new Value(true);
+        if(val.getType()!=Value.BOOLEAN){
+            err("Numerical type incorrect");
+        }else{
+            if(!val.getTypeName().equals("boolean")){
+                err("Type name incorrect");
+            }else{
+                if(val.getBoolean()!=true){
+                    err("Returned value incorrect");
+                }else ok();
+            }
+        }
+        
+        out(2,"Binary");
+        byte[] abuf=new byte[10];
+        abuf[0]=0;
+        abuf[1]=1;
+        abuf[2]=2;
+        abuf[3]=3;
+        abuf[4]=4;
+        abuf[5]=5;
+        abuf[6]=6;
+        abuf[7]=7;
+        abuf[8]=8;
+        abuf[9]=9;
+        val=new Value(abuf);
+        if(val.getType()!=Value.BINARY){
+            err("Numerical type incorrect");
+        }else{
+            if(!val.getTypeName().equals("binary")){
+                err("Type name incorrect");
+            }else{
+                if(val.getBinary()[9]!=9){
+                    err("Returned value incorrect");
+                }else ok();
+            }
+        }
+        
+        outbr(1,"Stream reading and writing");
+        try{
+             out(2,"Writing to stream");
+             ByteArrayOutputStream bout=new ByteArrayOutputStream();
+             DataOutputStream dout=new DataOutputStream(bout);
+             
+             Value val1=new Value();
+             Value val2=new Value("foo");
+             Value val3=new Value(1234);
+             Value val4=new Value(5123456789l);
+             Value val5=new Value(3.1415f);
+             Value val6=new Value(3.141592653689793284626433d);
+             Value val7=new Value(true);
+             Value val8=new Value(abuf);
+             
+             val1.writeToStream(dout);
+             val2.writeToStream(dout);
+             val3.writeToStream(dout);
+             val4.writeToStream(dout);
+             val5.writeToStream(dout);
+             val6.writeToStream(dout);
+             val7.writeToStream(dout);
+             val8.writeToStream(dout);
+             dout.flush();
+             
+             ok();
+             
+             out(2,"Reading from stream");
+             byte[] buf=bout.toByteArray();
+             DataInputStream din=new DataInputStream(new ByteArrayInputStream(buf));
+             val1=Value.readFromStream(din);
+             val2=Value.readFromStream(din);
+             val3=Value.readFromStream(din);
+             val4=Value.readFromStream(din);
+             val5=Value.readFromStream(din);
+             val6=Value.readFromStream(din);
+             val7=Value.readFromStream(din);
+             val8=Value.readFromStream(din);
+             ok();
+             
+             out(2,"Verifying values");
+             if(val1.getType()!=Value.NULL){
+                 err("Wrong value returned for null");
+             }else{
+                 if(!val2.getString().equals("foo")){
+                      err("Wrong value returned for string");
+                  }else{
+                      if(val3.getInt()!=1234){
+                          err("Wrong value returned for int");
+                      }else{
+                          if(val4.getLong()!=5123456789l){
+                              err("Wrong value returned for long");
+                          }else{
+                              if(val5.getFloat()!=3.1415f){
+                                  err("Wrong value returned for float");
+                              }else{
+                                  if(val6.getDouble()!=3.141592653689793284626433d){
+                                      err("Wrong value returned for double");
+                                  }else{
+                                      if(val7.getBoolean()!=true){
+                                          err("Wrong value returned for boolean");
+                                      }else{
+                                          if(val8.getBinary()[9]!=9){
+                                              err("Wrong value returned for binary");
+                                          }else ok();
+                                      }
+                                  }
+                              }
+                          }
+                      }
+                  }
+             }
+        }catch(Exception e){
+            err("Failed with exception "+e);
+        }
+        
+        outbr(1,"Value comparisons");
+        out(2,"Equals");
+        Value val1a=new Value();
+        Value val2a=new Value("foo");
+        Value val3a=new Value(1234);
+        Value val4a=new Value(5123456789l);
+        Value val5a=new Value(3.1415f);
+        Value val6a=new Value(3.141592653689793284626433d);
+        Value val7a=new Value(true);
+        
+        Value val1b=new Value();
+        Value val2b=new Value("foo");
+        Value val3b=new Value(1234);
+        Value val4b=new Value(5123456789l);
+        Value val5b=new Value(3.1415f);
+        Value val6b=new Value(3.141592653689793284626433d);
+        Value val7b=new Value(true);
+        
+        if(!val1a.equals(val1b)){
+            err("Null values not compared correctly");
+        }else if(!val2a.equals(val2b)){
+            err("String values not compared correctly");
+        }else if(!val3a.equals(val3b)){
+            err("Int values not compared correctly");
+        }else if(!val4a.equals(val4b)){
+            err("Long values not compared correctly");
+        }else if(!val5a.equals(val5b)){
+            err("Float values not compared correctly");
+        }else if(!val6a.equals(val6b)){
+            err("Double values not compared correctly");
+        }else if(!val7a.equals(val7b)){
+            err("Boolean values not compared correctly");
+        }else ok();
+        
+        out(2,"Greater than");
+        val3b=new Value(2234);
+        val4b=new Value(6123456789l);
+        val5b=new Value(4.1415f);
+        val6b=new Value(4.141592653689793284626433d);
+        if(val3a.greaterThan(val3b)){
+            err("Int values not compared correctly");
+        }else if(val4a.greaterThan(val4b)){
+            err("Long values not compared correctly");
+        }else if(val5a.greaterThan(val5b)){
+            err("Float values not compared correctly");
+        }else if(val6a.greaterThan(val6b)){
+            err("Double values not compared correctly");
+        }else ok();
+        
+        out(2,"Less than");
+        val3b=new Value(2234);
+        val4b=new Value(6123456789l);
+        val5b=new Value(4.1415f);
+        val6b=new Value(4.141592653689793284626433d);
+        if(!val3a.lessThan(val3b)){
+            err("Int values not compared correctly");
+        }else if(!val4a.lessThan(val4b)){
+            err("Long values not compared correctly");
+        }else if(!val5a.lessThan(val5b)){
+            err("Float values not compared correctly");
+        }else if(!val6a.lessThan(val6b)){
+            err("Double values not compared correctly");
+        }else ok();
+        
+        out(2,"Contains");
+        val1a=new Value("FooBarBaz");
+        val2a=new Value("Bar");
+        if(!val1a.contains(val2a)){
+            err("String values not compared correctly");
+        }else ok();
+        
+        out(2,"Starts with");
+        val1a=new Value("FooBarBaz");
+        val2a=new Value("Foo");
+        if(!val1a.startsWith(val2a)){
+            err("String values not compared correctly");
+        }else ok();
+        
+        out(2,"Ends with");
+        val1a=new Value("FooBarBaz");
+        val2a=new Value("Baz");
+        if(!val1a.endsWith(val2a)){
+            err("String values not compared correctly");
+        }else ok();
+        
+        out(2,"CompareTo");
+        val1a=new Value(1);
+        val2a=new Value(2);
+        if(val1a.compareTo(val2a)!=-1){
+            err("CompareTo did not return -1");
+        }else if(val2a.compareTo(val1a)!=1){
+            err("CompareTo did not return 1");
+        }else{
+            val2a=new Value(1);
+            if(val1a.compareTo(val2a)!=0){
+                err("CompareTo did not return 0");
+            }else ok();
+        }
+        
+        
+        printErrorSummary();
+    }
+    
+    public static void main(String args[]){
+        ValueTest valuet=new ValueTest();
+        valuet.runTest();
+    }
+}
\ No newline at end of file