00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <config.h>
00026 #include "zeromq_log.h"
00027 #include <drizzled/message/transaction.pb.h>
00028 #include <google/protobuf/io/coded_stream.h>
00029 #include <stdio.h>
00030 #include <drizzled/module/registry.h>
00031 #include <drizzled/plugin.h>
00032 #include <stdint.h>
00033 #include <boost/program_options.hpp>
00034 #include <drizzled/module/option_map.h>
00035 #include <zmq.h>
00036
00037 namespace po= boost::program_options;
00038
00039 using namespace std;
00040 using namespace drizzled;
00041 using namespace google;
00042
00043 namespace drizzle_plugin
00044 {
00045
00046 ZeroMQLog::ZeroMQLog(const string &name, const string &endpoint) :
00047 plugin::TransactionApplier(name)
00048 {
00049 void *context= zmq_init(1);
00050 _socket= zmq_socket (context, ZMQ_PUB);
00051 assert (_socket);
00052 int rc= zmq_bind (_socket, endpoint.c_str());
00053 assert (rc == 0);
00054 pthread_mutex_init(&publishLock, NULL);
00055 }
00056
00057 ZeroMQLog::~ZeroMQLog()
00058 {
00059 zmq_close(_socket);
00060 pthread_mutex_destroy(&publishLock);
00061 }
00062
00063 plugin::ReplicationReturnCode
00064 ZeroMQLog::apply(Session &, const message::Transaction &to_apply)
00065 {
00066 size_t message_byte_length= to_apply.ByteSize();
00067 uint8_t* buffer= new uint8_t[message_byte_length];
00068 if(buffer == NULL)
00069 {
00070 errmsg_printf(error::ERROR, _("Failed to allocate enough memory to transaction message\n"));
00071 deactivate();
00072 return plugin::UNKNOWN_ERROR;
00073 }
00074
00075 string schema= getSchemaName(to_apply);
00076 zmq_msg_t schemamsg;
00077 int rc= zmq_msg_init_size(&schemamsg, schema.length());
00078 memcpy(zmq_msg_data(&schemamsg), schema.c_str(), schema.length());
00079
00080 to_apply.SerializeWithCachedSizesToArray(buffer);
00081 zmq_msg_t msg;
00082 rc= zmq_msg_init_size(&msg, message_byte_length);
00083 assert (rc == 0);
00084 memcpy(zmq_msg_data(&msg), buffer, message_byte_length);
00085
00086
00087 pthread_mutex_lock(&publishLock);
00088 rc= zmq_send(_socket, &schemamsg, ZMQ_SNDMORE);
00089 rc= zmq_send(_socket, &msg, 0);
00090 pthread_mutex_unlock(&publishLock);
00091
00092 zmq_msg_close(&msg);
00093 zmq_msg_close(&schemamsg);
00094 delete[] buffer;
00095 return plugin::SUCCESS;
00096 }
00097
00098 string ZeroMQLog::getSchemaName(const message::Transaction &txn) {
00099 if(txn.statement_size() == 0) return "";
00100
00101 const message::Statement &statement= txn.statement(0);
00102
00103 switch(statement.type())
00104 {
00105 case message::Statement::INSERT:
00106 return statement.insert_header().table_metadata().schema_name();
00107 case message::Statement::UPDATE:
00108 return statement.update_header().table_metadata().schema_name();
00109 case message::Statement::DELETE:
00110 return statement.delete_header().table_metadata().schema_name();
00111 case message::Statement::CREATE_TABLE:
00112 return statement.create_table_statement().table().schema();
00113 case message::Statement::TRUNCATE_TABLE:
00114 return statement.truncate_table_statement().table_metadata().schema_name();
00115 case message::Statement::DROP_TABLE:
00116 return statement.drop_table_statement().table_metadata().schema_name();
00117 case message::Statement::CREATE_SCHEMA:
00118 return statement.create_schema_statement().schema().name();
00119 case message::Statement::DROP_SCHEMA:
00120 return statement.drop_schema_statement().schema_name();
00121 default:
00122 return "";
00123 }
00124 }
00125
00126 static ZeroMQLog *zeromqLogger;
00127
00131 static int init(drizzled::module::Context &context)
00132 {
00133 const module::option_map &vm= context.getOptions();
00134 zeromqLogger= new ZeroMQLog("zeromq_log_applier", vm["endpoint"].as<string>());
00135 context.add(zeromqLogger);
00136 ReplicationServices::attachApplier(zeromqLogger, vm["use-replicator"].as<string>());
00137 context.registerVariable(new sys_var_const_string_val("endpoint", vm["endpoint"].as<string>()));
00138 return 0;
00139 }
00140
00141
00142 static void init_options(drizzled::module::option_context &context)
00143 {
00144 context("endpoint",
00145 po::value<string>()->default_value("tcp://*:9999"),
00146 _("End point to bind to"));
00147 context("use-replicator",
00148 po::value<string>()->default_value("default_replicator"),
00149 _("Name of the replicator plugin to use (default='default_replicator')"));
00150
00151 }
00152
00153 }
00154
00155 DRIZZLE_PLUGIN(drizzle_plugin::init, NULL, drizzle_plugin::init_options);