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
00025 #include <config.h>
00026 #include "transaction_file_reader.h"
00027 #include <cstdlib>
00028 #include <cstdio>
00029 #include <cerrno>
00030 #include <fcntl.h>
00031 #include <boost/lexical_cast.hpp>
00032 #include <google/protobuf/io/coded_stream.h>
00033 #include <drizzled/definitions.h>
00034 #include <drizzled/algorithm/crc32.h>
00035 #include <drizzled/replication_services.h>
00036 #include <drizzled/gettext.h>
00037 #include <drizzled/util/convert.h>
00038
00039 using namespace std;
00040 using namespace drizzled;
00041 using namespace google;
00042
00043
00044 TransactionFileReader::TransactionFileReader()
00045 {
00046 raw_input= NULL;
00047 buffer= NULL;
00048 temp_buffer= NULL;
00049 previous_length= 0;
00050 file= -1;
00051 }
00052
00053 TransactionFileReader::~TransactionFileReader()
00054 {
00055 delete raw_input;
00056 close(file);
00057 free(buffer);
00058 }
00059
00060 bool TransactionFileReader::openFile(const string &filename, int start_pos)
00061 {
00062 file= open(filename.c_str(), O_RDONLY);
00063 if (file == -1)
00064 {
00065 error= _("Cannot open file: ") + filename;
00066 return false;
00067 }
00068
00069 raw_input= new protobuf::io::FileInputStream(file);
00070
00071 if (start_pos > 0)
00072 {
00073 if (not raw_input->Skip(start_pos))
00074 {
00075 error= _("Could not skip to position ")
00076 + boost::lexical_cast<string>(start_pos);
00077 return false;
00078 }
00079 }
00080
00081 return true;
00082 }
00083
00084 bool TransactionFileReader::getNextTransaction(message::Transaction &transaction,
00085 uint32_t *checksum)
00086 {
00087 uint32_t message_type= 0;
00088 uint32_t length= 0;
00089 bool result= true;
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 protobuf::io::CodedInputStream coded_input(raw_input);
00101
00102
00103 if (not coded_input.ReadLittleEndian32(&message_type) ||
00104 not coded_input.ReadLittleEndian32(&length))
00105 {
00106 error= "EOF";
00107 return false;
00108 }
00109
00110 if (message_type != ReplicationServices::TRANSACTION)
00111 {
00112 error= _("Found a non-transaction message in log. Currently, not supported.\n");
00113 return false;
00114 }
00115
00116 if (length > INT_MAX)
00117 {
00118 error= _("Attempted to read record bigger than INT_MAX\n");
00119 return false;
00120 }
00121
00122 if (buffer == NULL)
00123 {
00124
00125
00126
00127
00128 temp_buffer= (char *) malloc(static_cast<size_t>(length));
00129 }
00130
00131 else if (length > previous_length)
00132 {
00133 temp_buffer= (char *) realloc(buffer, static_cast<size_t>(length));
00134 }
00135
00136 if (temp_buffer == NULL)
00137 {
00138 error= _("Memory allocation failure trying to allocate ")
00139 + boost::lexical_cast<string>(length)
00140 + _(" bytes\n");
00141 return false;
00142 }
00143 else
00144 buffer= temp_buffer;
00145
00146
00147 result= coded_input.ReadRaw(buffer, (int) length);
00148
00149 if (result == false)
00150 {
00151 char errmsg[STRERROR_MAX];
00152 strerror_r(errno, errmsg, sizeof(errmsg));
00153 error= _("Could not read transaction message.\n");
00154 error += _("GPB ERROR: ") + string(errmsg) + "\n";
00155 string hexdump;
00156 hexdump.reserve(length * 4);
00157 bytesToHexdumpFormat(hexdump,
00158 reinterpret_cast<const unsigned char *>(buffer),
00159 length);
00160 error += _("HEXDUMP:\n\n") + hexdump;
00161 return false;
00162 }
00163
00164 result= transaction.ParseFromArray(buffer, static_cast<int32_t>(length));
00165
00166 if (result == false)
00167 {
00168 error= _("Unable to parse command. Got error: ")
00169 + transaction.InitializationErrorString();
00170 if (buffer != NULL)
00171 {
00172 string hexdump;
00173 hexdump.reserve(length * 4);
00174 bytesToHexdumpFormat(hexdump,
00175 reinterpret_cast<const unsigned char *>(buffer),
00176 length);
00177 error += _("\nHEXDUMP:\n\n") + hexdump + "\n";
00178 }
00179 return false;
00180 }
00181
00182
00183 coded_input.ReadLittleEndian32(checksum);
00184
00185 previous_length= length;
00186
00187 return true;
00188 }
00189
00190 uint32_t TransactionFileReader::checksumLastReadTransaction()
00191 {
00192 return drizzled::algorithm::crc32(buffer, static_cast<size_t>(previous_length));
00193 }