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 HEXDUMP_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>
36
#include <drizzled/hash/crc32.h>
38
#include "transaction_log.h"
39
#include "hexdump_transaction_message.h"
41
#include <drizzled/message/transaction.pb.h>
42
#include <drizzled/util/convert.h>
43
#include <google/protobuf/io/zero_copy_stream.h>
44
#include <google/protobuf/io/zero_copy_stream_impl.h>
45
#include <google/protobuf/io/coded_stream.h>
46
#include <google/protobuf/text_format.h>
49
using namespace drizzled;
50
using namespace google;
52
/** Defined in transaction_log.cc */
53
extern TransactionLog *transaction_log;
55
plugin::Create_function<HexdumpTransactionMessageFunction> *hexdump_transaction_message_func_factory= NULL;
57
void HexdumpTransactionMessageFunction::fix_length_and_dec()
59
max_length= 2 * 1024 * 1024; /* 2MB size limit seems ok... */
60
args[0]->collation.set(
61
get_charset_by_csname(args[0]->collation.collation->csname,
62
MY_CS_BINSORT), DERIVATION_COERCIBLE);
65
String *HexdumpTransactionMessageFunction::val_str(String *str)
67
assert(fixed == true);
69
String *filename_arg= args[0]->val_str(str);
70
off_t offset_arg= static_cast<int64_t>(args[1]->val_int());
72
if (filename_arg == NULL || args[1]->null_value == true)
74
my_error(ER_INVALID_NULL_ARGUMENT, MYF(0), func_name());
79
if (transaction_log == NULL)
81
my_error(ER_INVALID_NULL_ARGUMENT, MYF(0), func_name());
88
message::Transaction transaction_message;
91
* @todo Of course, this is not efficient to create a
92
* new input stream every time we call the UDF. Create
93
* a pool of TransactionLogReader objects that can be
96
const string &filename= transaction_log->getLogFilename();
97
int log_file= open(filename.c_str(), O_RDONLY);
100
errmsg_printf(ERRMSG_LVL_ERROR, _("Failed to open transaction log file %s. Got error: %s\n"),
107
(void) lseek(log_file, offset_arg, SEEK_SET);
109
protobuf::io::FileInputStream *file_input= new protobuf::io::FileInputStream(log_file);
110
file_input->SetCloseOnDelete(true);
112
protobuf::io::CodedInputStream *coded_input= new protobuf::io::CodedInputStream(file_input);
114
/* Grab our message type and length */
115
uint32_t message_type;
116
if (! coded_input->ReadLittleEndian32(&message_type))
120
/** @todo Error message for this... */
125
uint32_t message_size;
126
if (! coded_input->ReadLittleEndian32(&message_size))
130
/** @todo Error message for this... */
135
uint8_t *buffer= (uint8_t *) malloc(message_size);
137
bool result= coded_input->ReadRaw(buffer, message_size);
140
fprintf(stderr, _("Could not read transaction message.\n"));
141
fprintf(stderr, _("GPB ERROR: %s.\n"), strerror(errno));
142
fprintf(stderr, _("Raw buffer read: %s.\n"), buffer);
146
* Convert raw bytes to a hex representation and store back into
150
hexdump.reserve(message_size * 4);
151
bytesToHexdumpFormat(hexdump, reinterpret_cast<const unsigned char *>(buffer), message_size);
154
* Check that the transaction message is actually not corrupt before
155
* printing out the raw byte representation of the transaction message...
157
result= transaction_message.ParseFromArray(buffer, static_cast<int32_t>(message_size));
160
fprintf(stderr, _("Unable to parse transaction. Got error: %s.\n"), transaction_message.InitializationErrorString().c_str());
162
fprintf(stderr, _("BUFFER: %s\n"), buffer);
165
if (str->alloc(message_size * 4)) /* Hex representation is ~4 times number of bytes */
171
strncpy(str->ptr(), hexdump.c_str(), hexdump.length());
172
str->length(hexdump.length());