YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense alongwiththisprogram;ifnot,writetotheFreeSoftware
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */
#include <my_global.h>
/* This C++ file's header file */ #include"./rdb_converter.h"
/* Standard C++ header files */ #include <algorithm> #include <map> #include <string> #include <vector>
void dbug_modify_key_varchar8(String *on_disk_rec) {
std::string res; // The key starts with index number
res.append(on_disk_rec->ptr(), Rdb_key_def::INDEX_NUMBER_SIZE);
// Then, a mem-comparable form of a varchar(8) value.
res.append("ABCDE\0\0\0\xFC", 9);
on_disk_rec->length(0);
on_disk_rec->append(res.data(), res.size());
}
if (is_null) { if (decode) { // This sets the NULL-bit of this record
field->set_null(); /* Besidesthat,setthefieldvaluetodefaultvalue.CHECKSUMTABLE dependsonthis.
*/
memcpy(field->ptr, table->s->default_values + field_offset,
field->pack_length());
}
} else { if (decode) { // sets non-null bits for this record
field->set_notnull();
}
if (decode) { // set 8-byte pointer to 0, like innodb does (relevant for 32-bit // platforms)
memset(blob->ptr + length_bytes, 0, 8);
memcpy(blob->ptr + length_bytes, &blob_ptr, sizeof(uchar **));
}
return HA_EXIT_SUCCESS;
}
/* ConvertfixedlengthfieldfromrocksdbstorageformatintoMysqlRecord format @paramfieldINcurrentfield @paramfield_decINdatastructureconttainfieldencodingdata @paramreaderINrocksdbvalueslicereader @paramdecodeINwhethertodecodecurrentfield @return 0OK otherHA_ERRerrorcode(canbeSE-specific)
*/ int Rdb_convert_to_record_value_decoder::decode_fixed_length_field(
my_core::Field *const field, Rdb_field_encoder *field_dec,
Rdb_string_reader *const reader, bool decode) {
uint len = field_dec->m_pack_length_in_rec; if (len > 0) { constchar *data_bytes; if ((data_bytes = reader->read(len)) == nullptr) { return HA_ERR_ROCKSDB_CORRUPT_DATA;
}
if (decode) {
memcpy(field->ptr, data_bytes, len);
}
}
// Iterate each requested field and decode one by one template <typename value_field_decoder> int Rdb_value_field_iterator<value_field_decoder>::next() { int err = HA_EXIT_SUCCESS; while (m_field_iter != m_field_end) {
m_field_dec = m_field_iter->m_field_enc; bool decode = m_field_iter->m_decode; bool maybe_null = m_field_dec->maybe_null(); // This is_null value is binded to how storage format stores its value
m_is_null = maybe_null && ((m_null_bytes[m_field_dec->m_null_offset] &
m_field_dec->m_null_mask) != 0);
// Skip the bytes we need to skip int skip = m_field_iter->m_skip; if (skip && !m_value_slice_reader->read(skip)) { return HA_ERR_ROCKSDB_CORRUPT_DATA;
}
m_field = m_table->field[m_field_dec->m_field_index]; // Decode each field
err = value_field_decoder::decode(m_buf, &m_offset, m_table, m_field,
m_field_dec, m_value_slice_reader, decode,
m_is_null); if (err != HA_EXIT_SUCCESS) { return err;
}
m_field_iter++; // Only break for the field that are actually decoding rather than skipping if (decode) { break;
}
} return err;
}
Rdb_converter::~Rdb_converter() {
my_free(m_encoder_arr);
m_encoder_arr = nullptr; // These are needed to suppress valgrind errors in rocksdb.partition
m_storage_record.free();
}
for (uint i = 0; i < m_table->s->fields; i++) { // bitmap is cleared on index merge, but it still needs to decode columns bool field_requested =
decode_all_fields || m_verify_row_debug_checksums ||
bitmap_is_clear_all(field_map) ||
bitmap_is_set(field_map, m_table->field[i]->field_index);
// We only need the decoder if the whole record is stored. if (m_encoder_arr[i].m_storage_type != Rdb_field_encoder::STORE_ALL) { // the field potentially needs unpacking if (field_requested) { // the field is in the read set
m_key_requested = true;
} continue;
}
if (field_requested) { // We will need to decode this field
m_decoders_vect.push_back({&m_encoder_arr[i], true, skip_size});
last_useful = m_decoders_vect.size();
skip_size = 0;
} else { if (m_encoder_arr[i].uses_variable_len_encoding() ||
m_encoder_arr[i].maybe_null()) { // For variable-length field, we need to read the data and skip it
m_decoders_vect.push_back({&m_encoder_arr[i], false, skip_size});
skip_size = 0;
} else { // Fixed-width field can be skipped without looking at it. // Add appropriate skip_size to the next field.
skip_size += m_encoder_arr[i].m_pack_length_in_rec;
}
}
}
// It could be that the last few elements are varchars that just do // skipping. Remove them.
m_decoders_vect.erase(m_decoders_vect.begin() + last_useful,
m_decoders_vect.end());
}
for (uint i = 0; i < m_table->s->fields; i++) {
Field *const field = m_table->field[i];
m_encoder_arr[i].m_storage_type = Rdb_field_encoder::STORE_ALL;
/* Decodevaluesliceheader @paramreaderINvalueslicereader @parampk_defINkeydefinitiontodecode @paramunpack_sliceOUTunpackinfoslice @return 0OK otherHA_ERRerrorcode(canbeSE-specific)
*/ int Rdb_converter::decode_value_header(
Rdb_string_reader *reader, const std::shared_ptr<Rdb_key_def> &pk_def,
rocksdb::Slice *unpack_slice) { /* If it's a TTL record, skip the 8 byte TTL value */ if (pk_def->has_ttl()) { constchar *ttl_bytes; if ((ttl_bytes = reader->read(ROCKSDB_SIZEOF_TTL_RECORD))) {
memcpy(m_ttl_bytes, ttl_bytes, ROCKSDB_SIZEOF_TTL_RECORD);
} else { return HA_ERR_ROCKSDB_CORRUPT_DATA;
}
}
/* Other fields are decoded from the value */ if (m_null_bytes_length_in_record &&
!(m_null_bytes = reader->read(m_null_bytes_length_in_record))) { return HA_ERR_ROCKSDB_CORRUPT_DATA;
}
if (m_maybe_unpack_info) { constchar *unpack_info = reader->get_current_ptr(); if (!unpack_info || !Rdb_key_def::is_unpack_data_tag(unpack_info[0]) ||
!reader->read(Rdb_key_def::get_unpack_header_size(unpack_info[0]))) { return HA_ERR_ROCKSDB_CORRUPT_DATA;
}
if (has_ttl) { /* If it's a TTL record, reserve space for 8 byte TTL value in front. */
m_storage_record.fill(
ROCKSDB_SIZEOF_TTL_RECORD + m_null_bytes_length_in_record, 0); // NOTE: is_ttl_bytes_updated is only used for update case // During update, skip update sk key/values slice iff none of sk fields // have changed and ttl bytes isn't changed. see // ha_rocksdb::update_write_sk() for more info
*is_ttl_bytes_updated = false; char *const data = const_cast<char *>(m_storage_record.ptr()); if (has_ttl_column) {
DBUG_ASSERT(pk_def->get_ttl_field_index() != UINT_MAX);
Field *const field = m_table->field[pk_def->get_ttl_field_index()];
DBUG_ASSERT(field->pack_length_in_rec() == ROCKSDB_SIZEOF_TTL_RECORD);
DBUG_ASSERT(field->real_type() == MYSQL_TYPE_LONGLONG);
uint64 ts = uint8korr(field->ptr); #ifndef DBUG_OFF
ts += rdb_dbug_set_ttl_rec_ts(); #endif
rdb_netbuf_store_uint64(reinterpret_cast<uchar *>(data), ts); if (is_update_row) {
*is_ttl_bytes_updated =
memcmp(ttl_bytes, data, ROCKSDB_SIZEOF_TTL_RECORD);
} // Also store in m_ttl_bytes to propagate to update_write_sk
memcpy(ttl_bytes, data, ROCKSDB_SIZEOF_TTL_RECORD);
} else { /* ForimplicitlygeneratedTTLrecordsweneedtocopyovertheold TTLvaluefromtheoldrecordintheeventofanupdate.Itwasstored inm_ttl_bytes.
Otherwise,generateatimestampusingthecurrenttime.
*/ if (is_update_row) {
memcpy(data, ttl_bytes, sizeof(uint64));
} else {
uint64 ts = static_cast<uint64>(std::time(nullptr)); #ifndef DBUG_OFF
ts += rdb_dbug_set_ttl_rec_ts(); #endif
rdb_netbuf_store_uint64(reinterpret_cast<uchar *>(data), ts); // Also store in m_ttl_bytes to propagate to update_write_sk
memcpy(ttl_bytes, data, ROCKSDB_SIZEOF_TTL_RECORD);
}
}
} else { /* All NULL bits are initially 0 */
m_storage_record.fill(m_null_bytes_length_in_record, 0);
}
// If a primary key may have non-empty unpack_info for certain values, // (m_maybe_unpack_info=TRUE), we write the unpack_info block. The block // itself was prepared in Rdb_key_def::pack_record. if (m_maybe_unpack_info) {
m_storage_record.append(reinterpret_cast<char *>(pk_unpack_info->ptr()),
pk_unpack_info->get_current_pos());
} for (uint i = 0; i < m_table->s->fields; i++) {
Rdb_field_encoder &encoder = m_encoder_arr[i]; /* Don't pack decodable PK key parts */ if (encoder.m_storage_type != Rdb_field_encoder::STORE_ALL) { continue;
}
Field *const field = m_table->field[i]; if (encoder.maybe_null()) { char *data = const_cast<char *>(m_storage_record.ptr()); if (has_ttl) {
data += ROCKSDB_SIZEOF_TTL_RECORD;
}
if (field->is_null()) {
data[encoder.m_null_offset] |= encoder.m_null_mask; /* Don't write anything for NULL values */ continue;
}
}
if (encoder.m_field_type == MYSQL_TYPE_BLOB) {
my_core::Field_blob *blob = reinterpret_cast<my_core::Field_blob *>(field); /* Get the number of bytes needed to store length*/ const uint length_bytes = blob->pack_length() - portable_sizeof_char_ptr;
/* Store the length of the value */
m_storage_record.append(reinterpret_cast<char *>(blob->ptr),
length_bytes);
/* Store the blob value itself */ char *data_ptr;
memcpy(&data_ptr, blob->ptr + length_bytes, sizeof(uchar **));
m_storage_record.append(data_ptr, blob->get_length());
} elseif (encoder.m_field_type == MYSQL_TYPE_VARCHAR) {
Field_varstring *const field_var = reinterpret_cast<Field_varstring *>(field);
uint data_len; /* field_var->length_bytes is 1 or 2 */ if (field_var->length_bytes == 1) {
data_len = field_var->ptr[0];
} else {
DBUG_ASSERT(field_var->length_bytes == 2);
data_len = uint2korr(field_var->ptr);
}
m_storage_record.append(reinterpret_cast<char *>(field_var->ptr),
field_var->length_bytes + data_len);
} else { /* Copy the field data */ const uint len = field->pack_length_in_rec();
m_storage_record.append(reinterpret_cast<char *>(field->ptr), len);
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.