Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00031 #include <config.h>
00032 #include <drizzled/plugin/function.h>
00033 #include <drizzled/item/func.h>
00034 #include <drizzled/function/str/strfunc.h>
00035 #include <drizzled/error.h>
00036 #include <drizzled/algorithm/crc32.h>
00037 #include <drizzled/internal/my_sys.h>
00038 #include <drizzled/charset.h>
00039 #include <drizzled/errmsg_print.h>
00040 #include <drizzled/gettext.h>
00041
00042 #include <fcntl.h>
00043 #include <errno.h>
00044
00045 #include "transaction_log.h"
00046 #include "hexdump_transaction_message.h"
00047
00048 #include <drizzled/message/transaction.pb.h>
00049 #include <drizzled/util/convert.h>
00050 #include <google/protobuf/io/zero_copy_stream.h>
00051 #include <google/protobuf/io/zero_copy_stream_impl.h>
00052 #include <google/protobuf/io/coded_stream.h>
00053 #include <google/protobuf/text_format.h>
00054
00055 using namespace std;
00056 using namespace drizzled;
00057 using namespace google;
00058
00060 extern TransactionLog *transaction_log;
00061
00062 plugin::Create_function<HexdumpTransactionMessageFunction> *hexdump_transaction_message_func_factory= NULL;
00063
00064 void HexdumpTransactionMessageFunction::fix_length_and_dec()
00065 {
00066 max_length= 2 * 1024 * 1024;
00067 args[0]->collation.set(
00068 get_charset_by_csname(args[0]->collation.collation->csname,
00069 MY_CS_BINSORT), DERIVATION_COERCIBLE);
00070 }
00071
00072 String *HexdumpTransactionMessageFunction::val_str(String *str)
00073 {
00074 assert(fixed == true);
00075
00076 String *filename_arg= args[0]->val_str(str);
00077 off_t offset_arg= static_cast<int64_t>(args[1]->val_int());
00078
00079 if (filename_arg == NULL || args[1]->null_value == true)
00080 {
00081 my_error(ER_INVALID_NULL_ARGUMENT, MYF(0), func_name());
00082 null_value= true;
00083 return NULL;
00084 }
00085
00086 if (transaction_log == NULL)
00087 {
00088 my_error(ER_INVALID_NULL_ARGUMENT, MYF(0), func_name());
00089 null_value= true;
00090 return NULL;
00091 }
00092
00093 null_value= false;
00094
00095 message::Transaction transaction_message;
00096
00103 const string &filename= transaction_log->getLogFilename();
00104 int log_file= open(filename.c_str(), O_RDONLY);
00105 if (log_file == -1)
00106 {
00107 drizzled::sql_perror(_("Failed to open transaction log file"), filename);
00108 null_value= true;
00109
00110 return NULL;
00111 }
00112
00113 (void) lseek(log_file, offset_arg, SEEK_SET);
00114
00115 protobuf::io::FileInputStream *file_input= new protobuf::io::FileInputStream(log_file);
00116 file_input->SetCloseOnDelete(true);
00117
00118 protobuf::io::CodedInputStream *coded_input= new protobuf::io::CodedInputStream(file_input);
00119
00120
00121 uint32_t message_type;
00122 if (! coded_input->ReadLittleEndian32(&message_type))
00123 {
00124 delete file_input;
00125
00127 null_value= true;
00128 return NULL;
00129 }
00130
00131 uint32_t message_size;
00132 if (! coded_input->ReadLittleEndian32(&message_size))
00133 {
00134 delete file_input;
00135
00137 null_value= true;
00138 return NULL;
00139 }
00140
00141 uint8_t *buffer= (uint8_t *) malloc(message_size);
00142
00143 bool result= coded_input->ReadRaw(buffer, message_size);
00144 if (result == false)
00145 {
00146 char errmsg[STRERROR_MAX];
00147 strerror_r(errno, errmsg, sizeof(errmsg));
00148 fprintf(stderr, _("Could not read transaction message.\n"));
00149 fprintf(stderr, _("GPB ERROR: %s.\n"), errmsg);
00150 fprintf(stderr, _("Raw buffer read: %s.\n"), buffer);
00151 }
00152
00153
00154
00155
00156
00157 string hexdump;
00158 hexdump.reserve(message_size * 4);
00159 bytesToHexdumpFormat(hexdump, reinterpret_cast<const unsigned char *>(buffer), message_size);
00160
00161
00162
00163
00164
00165 result= transaction_message.ParseFromArray(buffer, static_cast<int32_t>(message_size));
00166 if (result == false)
00167 {
00168 fprintf(stderr, _("Unable to parse transaction. Got error: %s.\n"), transaction_message.InitializationErrorString().c_str());
00169 if (buffer != NULL)
00170 fprintf(stderr, _("BUFFER: %s\n"), buffer);
00171 }
00172
00173 if (str->alloc(message_size * 4))
00174 {
00175 null_value= true;
00176 return NULL;
00177 }
00178
00179 strncpy(str->ptr(), hexdump.c_str(), hexdump.length());
00180 str->length(hexdump.length());
00181
00182 free(buffer);
00183
00184 delete coded_input;
00185 delete file_input;
00186
00187 return str;
00188 }