1
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2009 Sun Microsystems
8
* Jay Pipes <joinfu@sun.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
28
* Implements the PRINT_TRANSACTION_MESSAGE(filename, offset) UDF.
31
#include <drizzled/server_includes.h>
32
#include <drizzled/plugin/function.h>
33
#include <drizzled/item/func.h>
34
#include <drizzled/function/str/strfunc.h>
35
#include <drizzled/error.h>
37
#include "transaction_log.h"
38
#include "print_transaction_message.h"
40
#include <drizzled/message/transaction.pb.h>
41
#include <google/protobuf/io/zero_copy_stream.h>
42
#include <google/protobuf/io/zero_copy_stream_impl.h>
43
#include <google/protobuf/io/coded_stream.h>
44
#include <google/protobuf/text_format.h>
47
using namespace drizzled;
48
using namespace google;
50
/** Defined in transaction_log.cc */
51
extern TransactionLog *transaction_log;
53
plugin::Create_function<PrintTransactionMessageFunction> *print_transaction_message_func_factory= NULL;
55
void PrintTransactionMessageFunction::fix_length_and_dec()
57
max_length= 2 * 1024 * 1024; /* 2MB size limit seems ok... */
58
args[0]->collation.set(
59
get_charset_by_csname(args[0]->collation.collation->csname,
60
MY_CS_BINSORT), DERIVATION_COERCIBLE);
63
String *PrintTransactionMessageFunction::val_str(String *str)
65
assert(fixed == true);
67
String *filename_arg= args[0]->val_str(str);
68
off_t offset_arg= static_cast<int64_t>(args[1]->val_int());
70
if (filename_arg == NULL || args[1]->null_value == true)
72
my_error(ER_INVALID_NULL_ARGUMENT, MYF(0), func_name());
77
if (transaction_log == NULL)
79
my_error(ER_INVALID_NULL_ARGUMENT, MYF(0), func_name());
86
message::Transaction transaction_message;
89
* @todo Of course, this is not efficient to create a
90
* new input stream every time we call the UDF. Create
91
* a pool of TransactionLogReader objects that can be
94
const string &filename= transaction_log->getLogFilename();
95
int log_file= open(filename.c_str(), O_RDONLY);
98
errmsg_printf(ERRMSG_LVL_ERROR, _("Failed to open transaction log file %s. Got error: %s\n"),
105
(void) lseek(log_file, offset_arg, SEEK_SET);
107
protobuf::io::FileInputStream *file_input= new protobuf::io::FileInputStream(log_file);
108
file_input->SetCloseOnDelete(true);
110
protobuf::io::CodedInputStream *coded_input= new protobuf::io::CodedInputStream(file_input);
112
/* Grab our message type and length */
113
uint32_t message_type;
114
if (! coded_input->ReadLittleEndian32(&message_type))
118
/** @todo Error message for this... */
123
uint32_t message_size;
124
if (! coded_input->ReadLittleEndian32(&message_size))
128
/** @todo Error message for this... */
133
uint8_t *buffer= (uint8_t *) malloc(message_size);
135
bool result= coded_input->ReadRaw(buffer, message_size);
138
fprintf(stderr, _("Could not read transaction message.\n"));
139
fprintf(stderr, _("GPB ERROR: %s.\n"), strerror(errno));
140
fprintf(stderr, _("Raw buffer read: %s.\n"), buffer);
143
result= transaction_message.ParseFromArray(buffer, static_cast<int32_t>(message_size));
146
fprintf(stderr, _("Unable to parse transaction. Got error: %s.\n"), transaction_message.InitializationErrorString().c_str());
148
fprintf(stderr, _("BUFFER: %s\n"), buffer);
153
string transaction_text;
154
protobuf::TextFormat::PrintToString(transaction_message, &transaction_text);
156
if (str->alloc(transaction_text.length()))
162
str->length(transaction_text.length());
164
strncpy(str->ptr(), transaction_text.c_str(), transaction_text.length());