Skip to content

Commit

Permalink
Support read timestamp in ldb (#12641)
Browse files Browse the repository at this point in the history
Summary:
As titled. Also updated sst_dump to print out user-defined timestamp separately and in human readable format.

Pull Request resolved: #12641

Test Plan:
manually tested:
Example success run:
./ldb --db=$TEST_DB multi_get_entity 0x00000000000000950000000000000120 --key_hex --column_family=7  --read_timestamp=1115613683797942 --value_hex
0x00000000000000950000000000000120 ==> :0x0E0000000A0B080906070405020300011E1F1C1D1A1B181916171415121310112E2F2C2D2A2B282926272425222320213E3F3C3D3A3B383936373435323330314E4F4C4D4A4B484946474445424340415E5F5C5D5A5B58595657545552535051
Example failed run:
Failed: GetEntity failed: Invalid argument: column family enables user-defined timestamp while --read_timestamp is not a valid uint64 value.

sst_dump print out:
'000000000000015D000000000000012B000000000000013B|timestamp:1113554493256671' seq:2330405, type:1 => 010000000504070609080B0A0D0C0F0E111013121514171619181B1A1D1C1F1E212023222524272629282B2A2D2C2F2E313033323534373639383B3A3D3C3F3E

Reviewed By: ltamasi

Differential Revision: D57297006

Pulled By: jowlyzhang

fbshipit-source-id: 8486d91468e4f6c0d42dca3c9629f1c45a92bf5a
  • Loading branch information
jowlyzhang authored and facebook-github-bot committed May 13, 2024
1 parent 20213d0 commit c110091
Show file tree
Hide file tree
Showing 10 changed files with 178 additions and 37 deletions.
4 changes: 2 additions & 2 deletions db/db_impl/db_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -2992,9 +2992,9 @@ inline Status DBImpl::FailIfReadCollapsedHistory(const ColumnFamilyData* cfd,
if (!full_history_ts_low.empty() &&
ucmp->CompareTimestamp(ts, full_history_ts_low) < 0) {
std::stringstream oss;
oss << "Read timestamp: " << ts.ToString(true)
oss << "Read timestamp: " << ucmp->TimestampToString(ts)
<< " is smaller than full_history_ts_low: "
<< Slice(full_history_ts_low).ToString(true) << std::endl;
<< ucmp->TimestampToString(full_history_ts_low) << std::endl;
return Status::InvalidArgument(oss.str());
}
return Status::OK();
Expand Down
7 changes: 6 additions & 1 deletion db/db_impl/db_impl_compaction_flush.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1094,7 +1094,12 @@ Status DBImpl::IncreaseFullHistoryTsLowImpl(ColumnFamilyData* cfd,
assert(ucmp->timestamp_size() == ts_low.size() && !ts_low.empty());
if (!current_ts_low.empty() &&
ucmp->CompareTimestamp(ts_low, current_ts_low) < 0) {
return Status::InvalidArgument("Cannot decrease full_history_ts_low");
std::stringstream oss;
oss << "Current full_history_ts_low: "
<< ucmp->TimestampToString(current_ts_low)
<< " is higher than provided ts: " << ucmp->TimestampToString(ts_low)
<< std::endl;
return Status::InvalidArgument(oss.str());
}

Status s = versions_->LogAndApply(cfd, *cfd->GetLatestMutableCFOptions(),
Expand Down
21 changes: 17 additions & 4 deletions db/dbformat.cc
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,23 @@ void ReplaceInternalKeyWithMinTimestamp(std::string* result, const Slice& key,
result->append(key.data() + key_sz - kNumInternalBytes, kNumInternalBytes);
}

std::string ParsedInternalKey::DebugString(bool log_err_key, bool hex) const {
std::string ParsedInternalKey::DebugString(bool log_err_key, bool hex,
const Comparator* ucmp) const {
std::string result = "'";
size_t ts_sz_for_debug = ucmp == nullptr ? 0 : ucmp->timestamp_size();
if (log_err_key) {
result += user_key.ToString(hex);
if (ts_sz_for_debug == 0) {
result += user_key.ToString(hex);
} else {
assert(user_key.size() >= ts_sz_for_debug);
Slice user_key_without_ts = user_key;
user_key_without_ts.remove_suffix(ts_sz_for_debug);
result += user_key_without_ts.ToString(hex);
Slice ts = Slice(user_key.data() + user_key.size() - ts_sz_for_debug,
ts_sz_for_debug);
result += "|timestamp:";
result += ucmp->TimestampToString(ts);
}
} else {
result += "<redacted>";
}
Expand All @@ -171,11 +184,11 @@ std::string ParsedInternalKey::DebugString(bool log_err_key, bool hex) const {
return result;
}

std::string InternalKey::DebugString(bool hex) const {
std::string InternalKey::DebugString(bool hex, const Comparator* ucmp) const {
std::string result;
ParsedInternalKey parsed;
if (ParseInternalKey(rep_, &parsed, false /* log_err_key */).ok()) {
result = parsed.DebugString(true /* log_err_key */, hex); // TODO
result = parsed.DebugString(true /* log_err_key */, hex, ucmp); // TODO
} else {
result = "(bad)";
result.append(EscapeString(rep_));
Expand Down
5 changes: 3 additions & 2 deletions db/dbformat.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,8 @@ struct ParsedInternalKey {
// u contains timestamp if user timestamp feature is enabled.
ParsedInternalKey(const Slice& u, const SequenceNumber& seq, ValueType t)
: user_key(u), sequence(seq), type(t) {}
std::string DebugString(bool log_err_key, bool hex) const;
std::string DebugString(bool log_err_key, bool hex,
const Comparator* ucmp = nullptr) const;

void clear() {
user_key.clear();
Expand Down Expand Up @@ -503,7 +504,7 @@ class InternalKey {
AppendInternalKeyFooter(&rep_, s, t);
}

std::string DebugString(bool hex) const;
std::string DebugString(bool hex, const Comparator* ucmp = nullptr) const;
};

inline int InternalKeyComparator::Compare(const InternalKey& a,
Expand Down
5 changes: 5 additions & 0 deletions include/rocksdb/comparator.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,11 @@ class Comparator : public Customizable, public CompareInterface {
return Slice();
}

// Return a human readable user-defined timestamp for debugging.
virtual std::string TimestampToString(const Slice& /*timestamp*/) const {
return "";
}

int CompareWithoutTimestamp(const Slice& a, const Slice& b) const {
return CompareWithoutTimestamp(a, /*a_has_ts=*/true, b, /*b_has_ts=*/true);
}
Expand Down
8 changes: 8 additions & 0 deletions include/rocksdb/utilities/ldb_cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ class LDBCommand {
static const std::string ARG_PREPOPULATE_BLOB_CACHE;
static const std::string ARG_DECODE_BLOB_INDEX;
static const std::string ARG_DUMP_UNCOMPRESSED_BLOBS;
static const std::string ARG_READ_TIMESTAMP;

struct ParsedParams {
std::string cmd;
Expand Down Expand Up @@ -190,6 +191,9 @@ class LDBCommand {

bool create_if_missing_;

/** Encoded user provided uint64_t read timestamp. */
std::string read_timestamp_;

/**
* Map of options passed on the command-line.
*/
Expand Down Expand Up @@ -275,6 +279,10 @@ class LDBCommand {
bool ParseBooleanOption(const std::map<std::string, std::string>& options,
const std::string& option, bool default_val);

/* Populate `ropts.timestamp` from command line flag --read_timestamp */
Status MaybePopulateReadTimestamp(ColumnFamilyHandle* cfh, ReadOptions& ropts,
Slice* read_timestamp);

Options options_;
std::vector<ColumnFamilyDescriptor> column_families_;
ConfigOptions config_options_;
Expand Down
12 changes: 6 additions & 6 deletions table/sst_file_dumper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -521,22 +521,22 @@ Status SstFileDumper::ReadSequential(bool print_kv, uint64_t read_num_limit,
iter->value(), oss, output_hex_);
if (!s.ok()) {
fprintf(stderr, "%s => error deserializing wide columns\n",
ikey.DebugString(true, output_hex_).c_str());
ikey.DebugString(true, output_hex_, ucmp).c_str());
continue;
}
fprintf(stdout, "%s => %s\n",
ikey.DebugString(true, output_hex_).c_str(),
ikey.DebugString(true, output_hex_, ucmp).c_str(),
oss.str().c_str());
} else if (ikey.type == kTypeValuePreferredSeqno) {
auto [unpacked_value, preferred_seqno] =
ParsePackedValueWithSeqno(value);
fprintf(stdout, "%s => %s, %llu\n",
ikey.DebugString(true, output_hex_).c_str(),
ikey.DebugString(true, output_hex_, ucmp).c_str(),
unpacked_value.ToString(output_hex_).c_str(),
static_cast<unsigned long long>(preferred_seqno));
} else {
fprintf(stdout, "%s => %s\n",
ikey.DebugString(true, output_hex_).c_str(),
ikey.DebugString(true, output_hex_, ucmp).c_str(),
value.ToString(output_hex_).c_str());
}
} else {
Expand All @@ -545,12 +545,12 @@ Status SstFileDumper::ReadSequential(bool print_kv, uint64_t read_num_limit,
const Status s = blob_index.DecodeFrom(value);
if (!s.ok()) {
fprintf(stderr, "%s => error decoding blob index\n",
ikey.DebugString(true, output_hex_).c_str());
ikey.DebugString(true, output_hex_, ucmp).c_str());
continue;
}

fprintf(stdout, "%s => %s\n",
ikey.DebugString(true, output_hex_).c_str(),
ikey.DebugString(true, output_hex_, ucmp).c_str(),
blob_index.DebugString(output_hex_).c_str());
}
}
Expand Down
Loading

0 comments on commit c110091

Please sign in to comment.