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 00022 public class CentralizedCommunicator extends Communicator 00023 { 00024 protected Map<String,Engine> m_sites; 00025 00026 protected List<Relation> m_results; 00027 00028 protected static final int MAX_LOOPS = 100; 00029 00030 public CentralizedCommunicator() 00031 { 00032 super(); 00033 m_sites = new HashMap<String,Engine>(); 00034 m_results = new LinkedList<Relation>(); 00035 } 00036 00037 public void run() 00038 { 00039 // Do nothing 00040 } 00041 00042 public void addSite(Engine e) 00043 { 00044 m_sites.put(e.m_siteName, e); 00045 } 00046 00047 public Engine getSite(String name) 00048 { 00049 if (!m_sites.containsKey(name)) 00050 return null; 00051 return m_sites.get(name); 00052 } 00053 00060 protected boolean loop() 00061 { 00062 Set<Relation> processed = new HashSet<Relation>(); 00063 for (String s_name : m_sites.keySet()) 00064 { 00065 // Have every site process any pending queries 00066 Engine e = m_sites.get(s_name); 00067 Set<Relation> pq = e.processPendingQueries(); 00068 processed.addAll(pq); 00069 } 00070 for (Relation r : processed) 00071 { 00072 // This site has produced new results: dispatch any 00073 // of them to other sites as needed 00074 if (r.isFragment()) 00075 { 00076 VariableTable vt = (VariableTable) r; 00077 String destination_name = vt.getSite(); 00078 Engine destination = m_sites.get(destination_name); 00079 destination.addQuery(vt); 00080 } 00081 else 00082 { 00083 // The result is not topped with a placeholder: 00084 m_results.add(r); 00085 } 00086 } 00087 // Return true if any site has created new data in this cycle 00088 return processed.size() > 0; 00089 } 00090 00091 public QueryProcessor getQueryProcessor(Relation query) 00092 { 00093 // Pick a site 00094 return getQueryProcessor(query, "Site 1"); 00095 } 00096 00097 public QueryProcessor getQueryProcessor(Relation query, String site) 00098 { 00099 Engine source = m_sites.get(site); 00100 QueryPlan qp = source.getQueryPlan(query); 00101 return getQueryProcessor(qp); 00102 } 00103 00104 public QueryProcessor getQueryProcessor(QueryPlan qp) 00105 { 00106 return new CentralizedQueryProcessor(qp); 00107 } 00108 00109 protected class CentralizedQueryProcessor extends QueryProcessor 00110 { 00111 protected QueryPlan m_queryPlan; 00112 00113 protected Relation m_result; 00114 00115 public CentralizedQueryProcessor(QueryPlan qp) 00116 { 00117 super(); 00118 m_result = null; 00119 m_queryPlan = qp; 00120 } 00121 00122 @Override 00123 public synchronized void run() 00124 { 00125 // Dispatch pieces of the plan to their respective site 00126 assert m_queryPlan != null; 00127 for (String site_name : m_queryPlan.keySet()) 00128 { 00129 Set<Relation> queries = m_queryPlan.get(site_name); 00130 Engine e = m_sites.get(site_name); 00131 e.addQuery(queries); 00132 } 00133 00134 // Loop until result comes back to target site 00135 // This is why the run method for this processor is declared 00136 // synchronized: we disallow concurrent accesses to the 00137 // underlying CentralizedCommunicator 00138 for (int i = 1; loop() && i < MAX_LOOPS; i++) 00139 { 00140 // Do nothing 00141 } 00142 assert m_results.size() > 0; 00143 m_result = m_results.get(0); 00144 } 00145 00146 @Override 00147 public Relation getResult() 00148 { 00149 return m_result; 00150 } 00151 00152 } 00153 }