TurtleDB
A mini distributed database system
src/ca/uqac/dim/turtledb/CentralizedCommunicator.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 
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 }