Add support in log writer and reader for a user-defined timestamp size record (#11433)
Summary: This patch adds support to write and read a user-defined timestamp size record in log writer and log reader. It will be used by WAL logs to persist the user-defined timestamp format for subsequent WriteBatch records. Reading and writing UDT sizes for WAL logs are not included in this patch. It will be in a follow up. The syntax for the record is: at write time, one such record is added when log writer encountered any non-zero UDT size it hasn't recorded so far. At read time, all such records read up to a point are accumulated and applicable to all subsequent WriteBatch records. Pull Request resolved: https://github.com/facebook/rocksdb/pull/11433 Test Plan: ``` make clean && make -j32 all ./log_test --gtest_filter="*WithTimestampSize*" ``` Reviewed By: ltamasi Differential Revision: D45678708 Pulled By: jowlyzhang fbshipit-source-id: b770c8f45bb7b9383b14aac9f22af781304fb41doxigraph-8.3.2
parent
8827cd0618
commit
47235dda9e
@ -0,0 +1,77 @@ |
||||
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
||||
// This source code is licensed under both the GPLv2 (found in the
|
||||
// COPYING file in the root directory) and Apache 2.0 License
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
|
||||
#pragma once |
||||
#include <sstream> |
||||
#include <vector> |
||||
|
||||
#include "rocksdb/slice.h" |
||||
#include "rocksdb/status.h" |
||||
#include "util/coding.h" |
||||
|
||||
namespace ROCKSDB_NAMESPACE { |
||||
|
||||
// Dummy record in WAL logs signaling user-defined timestamp sizes for
|
||||
// subsequent records.
|
||||
class UserDefinedTimestampSizeRecord { |
||||
public: |
||||
UserDefinedTimestampSizeRecord() {} |
||||
explicit UserDefinedTimestampSizeRecord( |
||||
std::vector<std::pair<uint32_t, size_t>>&& cf_to_ts_sz) |
||||
: cf_to_ts_sz_(std::move(cf_to_ts_sz)) {} |
||||
|
||||
const std::vector<std::pair<uint32_t, size_t>>& GetUserDefinedTimestampSize() |
||||
const { |
||||
return cf_to_ts_sz_; |
||||
} |
||||
|
||||
inline void EncodeTo(std::string* dst) const { |
||||
assert(dst != nullptr); |
||||
for (const auto& [cf_id, ts_sz] : cf_to_ts_sz_) { |
||||
assert(ts_sz != 0); |
||||
PutFixed32(dst, cf_id); |
||||
PutFixed16(dst, static_cast<uint16_t>(ts_sz)); |
||||
} |
||||
} |
||||
|
||||
inline Status DecodeFrom(Slice* src) { |
||||
const size_t total_size = src->size(); |
||||
if ((total_size % kSizePerColumnFamily) != 0) { |
||||
std::ostringstream oss; |
||||
oss << "User-defined timestamp size record length: " << total_size |
||||
<< " is not a multiple of " << kSizePerColumnFamily << std::endl; |
||||
return Status::Corruption(oss.str()); |
||||
} |
||||
int num_of_entries = static_cast<int>(total_size / kSizePerColumnFamily); |
||||
for (int i = 0; i < num_of_entries; i++) { |
||||
uint32_t cf_id = 0; |
||||
uint16_t ts_sz = 0; |
||||
if (!GetFixed32(src, &cf_id) || !GetFixed16(src, &ts_sz)) { |
||||
return Status::Corruption( |
||||
"Error decoding user-defined timestamp size record entry"); |
||||
} |
||||
cf_to_ts_sz_.emplace_back(cf_id, static_cast<size_t>(ts_sz)); |
||||
} |
||||
return Status::OK(); |
||||
} |
||||
|
||||
inline std::string DebugString() const { |
||||
std::ostringstream oss; |
||||
|
||||
for (const auto& [cf_id, ts_sz] : cf_to_ts_sz_) { |
||||
oss << "Column family: " << cf_id |
||||
<< ", user-defined timestamp size: " << ts_sz << std::endl; |
||||
} |
||||
return oss.str(); |
||||
} |
||||
|
||||
private: |
||||
// 4 bytes for column family id, 2 bytes for user-defined timestamp size.
|
||||
static constexpr size_t kSizePerColumnFamily = 4 + 2; |
||||
|
||||
std::vector<std::pair<uint32_t, size_t>> cf_to_ts_sz_; |
||||
}; |
||||
|
||||
} // namespace ROCKSDB_NAMESPACE
|
Loading…
Reference in new issue