TurtleDB
A mini distributed database system
src/ca/uqac/dim/turtledb/Engine.java
Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002     Simple distributed database engine
00003     Copyright (C) 2012  Sylvain Hallé
00004 
00005     This program is free software: you can redistribute it and/or modify
00006     it under the terms of the GNU General Public License as published by
00007     the Free Software Foundation, either version 3 of the License, or
00008     (at your option) any later version.
00009 
00010     This program is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013     GNU General Public License for more details.
00014 
00015     You should have received a copy of the GNU General Public License
00016     along with this program.  If not, see <http://www.gnu.org/licenses/>.
00017  -------------------------------------------------------------------------*/
00018 package ca.uqac.dim.turtledb;
00019 
00020 import java.util.*;
00021 import java.util.Map.Entry;
00022 
00023 import org.w3c.dom.Document;
00024 
00025 import ca.uqac.dim.turtledb.QueryVisitor.VisitorException;
00026 
00038 public class Engine
00039 {
00040   protected Map<String,Relation> m_tables;
00041   
00045   protected List<Relation> m_pendingQueries;
00046   
00050   protected int m_numTuplesReceived;
00051   
00055   protected String m_siteName;
00056   
00060   public Engine(String name)
00061   {
00062     super();
00063     m_tables = new HashMap<String,Relation>();
00064     m_pendingQueries = new LinkedList<Relation>();
00065     m_numTuplesReceived = 0;
00066     m_siteName = name;
00067   }
00068   
00076   public void putRelation(String name, Relation r)
00077   {
00078     m_tables.put(name, r);
00079   }
00080   
00085   public void addQuery(Relation query)
00086   {
00087     // Update count of received tuples from the outside world
00088     m_numTuplesReceived += query.tupleCount();
00089     if (query.isFragment())
00090     {
00091       assert query instanceof VariableTable;
00092       VariableTable vt = (VariableTable) query;
00093       if (vt.getSite().compareTo(m_siteName) != 0)
00094       {
00095         // The fragment is not destined to this site: therefore it is a query
00096         // plan. Connect plan's leaves to any local tables...
00097         TableLinkVisitor tlv = new TableLinkVisitor(m_tables);
00098         try
00099         {
00100           query.accept(tlv);
00101         }
00102         catch (EmptyQueryVisitor.VisitorException e)
00103         {
00104           e.printStackTrace();
00105         }
00106         // Add plan to pending queries        
00107         m_pendingQueries.add(query);
00108       }
00109       else
00110       {
00111         // The fragment is destined to this site: iterate over pending queries and
00112         // check if fragment can be connected to some of their leaves
00113         for (Relation r : m_pendingQueries)
00114         {
00115           TableLinkVisitor tlv = new TableLinkVisitor((VariableTable) query);
00116           try
00117           {
00118             r.accept(tlv);
00119           }
00120           catch (EmptyQueryVisitor.VisitorException e)
00121           {
00122             e.printStackTrace();
00123           }
00124         }
00125       }
00126     }
00127     else
00128     {
00129       // Not a fragment; connect plan's leaves to any local tables...
00130       TableLinkVisitor tlv = new TableLinkVisitor(m_tables);
00131       try
00132       {
00133         query.accept(tlv);
00134       }
00135       catch (EmptyQueryVisitor.VisitorException e)
00136       {
00137         e.printStackTrace();
00138       }
00139       // Add plan to pending queries        
00140       m_pendingQueries.add(query);
00141     }
00142   }
00143   
00149   public void addQuery(Collection<Relation> queries)
00150   {
00151     for (Relation q : queries)
00152       addQuery(q);
00153   }
00154   
00159   public Set<Relation> processPendingQueries()
00160   {
00161     Set<Relation> processed = new HashSet<Relation>();
00162     Iterator<Relation> it = m_pendingQueries.iterator();
00163     while (it.hasNext())
00164     {
00165       Relation pq = it.next();
00166       ReadyToProcessVisitor rtv = new ReadyToProcessVisitor();
00167       try
00168       {
00169         pq.accept(rtv);
00170       }
00171       catch (VisitorException e)
00172       {
00173         // This should not happen anyway
00174         e.printStackTrace();
00175       }
00176       if (!rtv.isReady())
00177         continue;
00178       // Query is ready
00179       it.remove(); // Remove from list of pending queries
00180       // Computes the result and copies it into a new table
00181       Relation to_add;
00182       Table result = new Table();
00183       result.copy(pq);
00184       to_add = result;
00185       // If relation is a fragment, affix the fragment's label to the computed result
00186       if (pq.isFragment())
00187       {
00188         VariableTable vt = (VariableTable) pq;
00189         VariableTable head = new VariableTable(vt.m_name, vt.m_site);
00190         head.setRelation(result);
00191         to_add = head;
00192       }
00193       // Put that table into list of computed results
00194       processed.add(to_add);
00195     }
00196     return processed;
00197   }
00198   
00204   public QueryPlan getQueryPlan(Relation query)
00205   {
00206     // TODO
00207     return null;
00208   }
00209   
00215   public Table evaluate(Relation query)
00216   {  
00217     // Update count of received tuples from the outside world
00218     m_numTuplesReceived += query.tupleCount();
00219     // Connect leaves to actual tables
00220     TableLinkVisitor tlv = new TableLinkVisitor(m_tables);
00221     try
00222     {
00223       query.accept(tlv);
00224     }
00225     catch (EmptyQueryVisitor.VisitorException e)
00226     {
00227       e.printStackTrace();
00228     }
00229     // Computes the result and copies it into a new table
00230     Table out = new Table();
00231     out.copy(query);
00232     return out;
00233   }
00234   
00240   public Table evaluate(String s)
00241   {
00242     try
00243     {
00244       Relation q = XmlQueryParser.parse(s);
00245       return evaluate(q);
00246     }
00247     catch (XmlQueryParser.ParseException e)
00248     {
00249       e.printStackTrace();
00250     }
00251     return null;
00252   }
00253   
00254   public Table evaluate(Document d)
00255   {
00256     try
00257     {
00258       Relation q = XmlQueryParser.parse(d);
00259       return evaluate(q);
00260     }
00261     catch (XmlQueryParser.ParseException e)
00262     {
00263       e.printStackTrace();
00264     }
00265     return null;
00266   }
00267   
00274   public int getStorageSize()
00275   {
00276     int size = 0;
00277     for (Entry<String,Relation> e : m_tables.entrySet())
00278     {
00279       Relation r = e.getValue();
00280       size += r.getCardinality();
00281     }
00282     return size;
00283   }
00284   
00291   public int getTuplesReceived()
00292   {
00293     return m_numTuplesReceived;
00294   }
00295 }