Drizzled Public API Documentation

replication_services.cc
00001 /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
00002  *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00003  *
00004  *  Copyright (C) 2008-2009 Sun Microsystems, Inc.
00005  *  Copyright (C) 2009-2010 Jay Pipes <jaypipes@gmail.com>
00006  *
00007  *  Authors:
00008  *
00009  *    Jay Pipes <jaypipes@gmail.com>
00010  *
00011  *  This program is free software; you can redistribute it and/or modify
00012  *  it under the terms of the GNU General Public License as published by
00013  *  the Free Software Foundation; version 2 of the License.
00014  *
00015  *  This program is distributed in the hope that it will be useful,
00016  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  *  GNU General Public License for more details.
00019  *
00020  *  You should have received a copy of the GNU General Public License
00021  *  along with this program; if not, write to the Free Software
00022  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00023  */
00024 
00037 #include <config.h>
00038 #include <drizzled/replication_services.h>
00039 #include <drizzled/plugin/transaction_replicator.h>
00040 #include <drizzled/plugin/transaction_applier.h>
00041 #include <drizzled/message/transaction.pb.h>
00042 #include <drizzled/gettext.h>
00043 #include <drizzled/session.h>
00044 #include <drizzled/error.h>
00045 #include <drizzled/errmsg_print.h>
00046 
00047 #include <string>
00048 #include <vector>
00049 #include <algorithm>
00050 
00051 using namespace std;
00052 
00053 namespace drizzled {
00054 
00055 typedef std::vector<plugin::TransactionReplicator*> Replicators;
00056 typedef std::vector<std::pair<std::string, plugin::TransactionApplier*> > Appliers;
00057 
00062 static bool is_active= false;
00067 static atomic<uint64_t> last_applied_timestamp;
00069 static Replicators replicators;
00071 static Appliers appliers;
00073 static ReplicationServices::ReplicationStreams replication_streams;
00074 
00079 static void normalizeReplicatorName(string &name)
00080 {
00081   boost::to_lower(name);
00082   if (name.find("replicator") == string::npos)
00083     name.append("replicator");
00084   {
00085     size_t found_underscore= name.find('_');
00086     while (found_underscore != string::npos)
00087     {
00088       name.erase(found_underscore, 1);
00089       found_underscore= name.find('_');
00090     }
00091   }
00092 }
00093 
00094 bool ReplicationServices::evaluateRegisteredPlugins()
00095 {
00096   /* 
00097    * We loop through appliers that have registered with us
00098    * and attempts to pair the applier with its requested
00099    * replicator.  If an applier has requested a replicator
00100    * that has either not been built or has not registered
00101    * with the replication services, we print an error and
00102    * return false
00103    */
00104   if (appliers.empty())
00105     return true;
00106 
00107   if (replicators.empty() && not appliers.empty())
00108   {
00109     errmsg_printf(error::ERROR,
00110                   N_("You registered a TransactionApplier plugin but no "
00111                      "TransactionReplicator plugins were registered.\n"));
00112     return false;
00113   }
00114 
00115   BOOST_FOREACH(Appliers::reference appl_iter, appliers)
00116   {
00117     plugin::TransactionApplier *applier= appl_iter.second;
00118     string requested_replicator_name= appl_iter.first;
00119     normalizeReplicatorName(requested_replicator_name);
00120 
00121     bool found= false;
00122     Replicators::iterator repl_iter;
00123     for (repl_iter= replicators.begin(); repl_iter != replicators.end(); ++repl_iter)
00124     {
00125       string replicator_name= (*repl_iter)->getName();
00126       normalizeReplicatorName(replicator_name);
00127 
00128       if (requested_replicator_name.compare(replicator_name) == 0)
00129       {
00130         found= true;
00131         break;
00132       }
00133     }
00134     if (not found)
00135     {
00136       errmsg_printf(error::ERROR,
00137                     N_("You registered a TransactionApplier plugin but no "
00138                        "TransactionReplicator plugins were registered that match the "
00139                        "requested replicator name of '%s'.\n"
00140                        "We have deactivated the TransactionApplier '%s'.\n"),
00141                        requested_replicator_name.c_str(),
00142                        applier->getName().c_str());
00143       applier->deactivate();
00144       return false;
00145     }
00146     else
00147     {
00148       replication_streams.push_back(make_pair(*repl_iter, applier));
00149     }
00150   }
00151   is_active= true;
00152   return true;
00153 }
00154 
00155 void ReplicationServices::attachReplicator(plugin::TransactionReplicator *in_replicator)
00156 {
00157   replicators.push_back(in_replicator);
00158 }
00159 
00160 void ReplicationServices::detachReplicator(plugin::TransactionReplicator *in_replicator)
00161 {
00162   replicators.erase(std::find(replicators.begin(), replicators.end(), in_replicator));
00163 }
00164 
00165 void ReplicationServices::attachApplier(plugin::TransactionApplier *in_applier, const string &requested_replicator_name)
00166 {
00167   appliers.push_back(make_pair(requested_replicator_name, in_applier));
00168 }
00169 
00170 void ReplicationServices::detachApplier(plugin::TransactionApplier *)
00171 {
00172 }
00173 
00174 bool ReplicationServices::isActive()
00175 {
00176   return is_active;
00177 }
00178 
00179 plugin::ReplicationReturnCode ReplicationServices::pushTransactionMessage(Session &in_session,
00180                                                                           message::Transaction &to_push)
00181 {
00182   plugin::ReplicationReturnCode result= plugin::SUCCESS;
00183 
00184   BOOST_FOREACH(ReplicationStreams::reference iter, replication_streams)
00185   {
00186     plugin::TransactionReplicator *cur_repl= iter.first;
00187     plugin::TransactionApplier *cur_appl= iter.second;
00188 
00189     result= cur_repl->replicate(cur_appl, in_session, to_push);
00190 
00191     if (result == plugin::SUCCESS)
00192     {
00193       /* 
00194        * We update the timestamp for the last applied Transaction so that
00195        * publisher plugins can ask the replication services when the
00196        * last known applied Transaction was using the getLastAppliedTimestamp()
00197        * method.
00198        */
00199       last_applied_timestamp.fetch_and_store(to_push.transaction_context().end_timestamp());
00200     }
00201     else
00202       return result;
00203   }
00204   return result;
00205 }
00206 
00207 ReplicationServices::ReplicationStreams &ReplicationServices::getReplicationStreams()
00208 {
00209   return replication_streams;
00210 }
00211 
00212 } /* namespace drizzled */