TurtleDB
A mini distributed database system
|
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 }