1
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2010 Marcus Eriksson
8
* Marcus Eriksson <krummas@gmail.com>
10
* This program is free software; you can redistribute it and/or modify
11
* it under the terms of the GNU General Public License as published by
12
* the Free Software Foundation; either version 2 of the License, or
13
* (at your option) any later version.
15
* This program is distributed in the hope that it will be useful,
16
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
* GNU General Public License for more details.
20
* You should have received a copy of the GNU General Public License
21
* along with this program; if not, write to the Free Software
22
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26
#include "rabbitmq_log.h"
27
#include <drizzled/message/transaction.pb.h>
28
#include <google/protobuf/io/coded_stream.h>
30
#include <drizzled/module/registry.h>
31
#include <drizzled/plugin.h>
33
#include "rabbitmq_handler.h"
34
#include <boost/program_options.hpp>
35
#include <drizzled/module/option_map.h>
37
namespace po= boost::program_options;
40
using namespace drizzled;
41
using namespace google;
43
namespace drizzle_plugin
49
static port_constraint sysvar_rabbitmq_port;
52
RabbitMQLog::RabbitMQLog(const string &name,
53
RabbitMQHandler* mqHandler) :
54
plugin::TransactionApplier(name),
55
_rabbitMQHandler(mqHandler)
58
RabbitMQLog::~RabbitMQLog()
60
_rabbitMQHandler->disconnect();
61
delete _rabbitMQHandler;
64
plugin::ReplicationReturnCode
65
RabbitMQLog::apply(Session &, const message::Transaction &to_apply)
67
size_t message_byte_length= to_apply.ByteSize();
68
uint8_t* buffer= new uint8_t[message_byte_length];
71
errmsg_printf(error::ERROR, _("Failed to allocate enough memory to transaction message\n"));
73
return plugin::UNKNOWN_ERROR;
76
to_apply.SerializeWithCachedSizesToArray(buffer);
79
while (!sent && tries > 0) {
83
_rabbitMQHandler->publish(buffer, int(message_byte_length));
88
errmsg_printf(error::ERROR, _(e.what()));
90
_rabbitMQHandler->reconnect();
91
} catch(exception &e) {
92
errmsg_printf(error::ERROR, _("Could not reconnect, trying again.. - waiting 10 seconds for server to come back"));
99
if(sent) return plugin::SUCCESS;
100
errmsg_printf(error::ERROR, _("RabbitMQ server has disappeared, failing transaction."));
102
return plugin::UNKNOWN_ERROR;
105
static RabbitMQLog *rabbitmqLogger; ///< the actual plugin
106
static RabbitMQHandler* rabbitmqHandler; ///< the rabbitmq handler
110
* Initialize the rabbitmq logger - instanciates the dependencies (the handler)
111
* and creates the log handler with the dependency - makes it easier to swap out
112
* handler implementation
114
static int init(drizzled::module::Context &context)
116
const module::option_map &vm= context.getOptions();
120
rabbitmqHandler= new RabbitMQHandler(vm["host"].as<string>(),
121
sysvar_rabbitmq_port,
122
vm["username"].as<string>(),
123
vm["password"].as<string>(),
124
vm["virtualhost"].as<string>(),
125
vm["exchange"].as<string>(),
126
vm["routingkey"].as<string>());
130
errmsg_printf(error::ERROR, _("Failed to allocate the RabbitMQHandler. Got error: %s\n"),
136
rabbitmqLogger= new RabbitMQLog("rabbit_log_applier",
141
errmsg_printf(error::ERROR, _("Failed to allocate the RabbitMQLog instance. Got error: %s\n"),
146
context.add(rabbitmqLogger);
147
ReplicationServices &replication_services= ReplicationServices::singleton();
148
replication_services.attachApplier(rabbitmqLogger, vm["use-replicator"].as<string>());
150
context.registerVariable(new sys_var_const_string_val("host", vm["host"].as<string>()));
151
context.registerVariable(new sys_var_constrained_value_readonly<in_port_t>("port", sysvar_rabbitmq_port));
152
context.registerVariable(new sys_var_const_string_val("username", vm["username"].as<string>()));
153
context.registerVariable(new sys_var_const_string_val("password", vm["password"].as<string>()));
154
context.registerVariable(new sys_var_const_string_val("virtualhost", vm["virtualhost"].as<string>()));
155
context.registerVariable(new sys_var_const_string_val("exchange", vm["exchange"].as<string>()));
156
context.registerVariable(new sys_var_const_string_val("routingkey", vm["routingkey"].as<string>()));
162
static void init_options(drizzled::module::option_context &context)
165
po::value<string>()->default_value("localhost"),
166
_("Host name to connect to"));
168
po::value<port_constraint>(&sysvar_rabbitmq_port)->default_value(5672),
169
_("Port to connect to"));
170
context("virtualhost",
171
po::value<string>()->default_value("/"),
172
_("RabbitMQ virtualhost"));
174
po::value<string>()->default_value("guest"),
175
_("RabbitMQ username"));
177
po::value<string>()->default_value("guest"),
178
_("RabbitMQ password"));
179
context("use-replicator",
180
po::value<string>()->default_value("default_replicator"),
181
_("Name of the replicator plugin to use (default='default_replicator')"));
183
po::value<string>()->default_value("ReplicationExchange"),
184
_("Name of RabbitMQ exchange to publish to"));
185
context("routingkey",
186
po::value<string>()->default_value("ReplicationRoutingKey"),
187
_("Name of RabbitMQ routing key to use"));
190
} /* namespace drizzle_plugin */
192
DRIZZLE_PLUGIN(drizzle_plugin::init, NULL, drizzle_plugin::init_options);