Skip to content

Commit

Permalink
Support providing the default column separately when serializing colu…
Browse files Browse the repository at this point in the history
…mns (#10839)

Summary:
The patch makes it possible to provide the value of the default column
separately when calling `WideColumnSerialization::Serialize`. This eliminates
the need to construct a new `WideColumns` vector in certain cases
(for example, it will come in handy when implementing `Merge`).

Pull Request resolved: facebook/rocksdb#10839

Test Plan: `make check`

Reviewed By: riversand963

Differential Revision: D40561448

Pulled By: ltamasi

fbshipit-source-id: 69becdd510e6a83ab1feb956c12772110e1040d6
  • Loading branch information
ltamasi authored and facebook-github-bot committed Oct 20, 2022
1 parent 33ceea9 commit 865d557
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 6 deletions.
35 changes: 29 additions & 6 deletions db/wide/wide_column_serialization.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,32 @@

namespace ROCKSDB_NAMESPACE {

Status WideColumnSerialization::Serialize(const WideColumns& columns,
std::string& output) {
if (columns.size() >
static_cast<size_t>(std::numeric_limits<uint32_t>::max())) {
Status WideColumnSerialization::SerializeImpl(const Slice* value_of_default,
const WideColumns& columns,
std::string& output) {
const size_t num_columns =
value_of_default ? columns.size() + 1 : columns.size();

if (num_columns > static_cast<size_t>(std::numeric_limits<uint32_t>::max())) {
return Status::InvalidArgument("Too many wide columns");
}

PutVarint32(&output, kCurrentVersion);

PutVarint32(&output, static_cast<uint32_t>(columns.size()));
PutVarint32(&output, static_cast<uint32_t>(num_columns));

const Slice* prev_name = nullptr;
if (value_of_default) {
if (value_of_default->size() >
static_cast<size_t>(std::numeric_limits<uint32_t>::max())) {
return Status::InvalidArgument("Wide column value too long");
}

PutLengthPrefixedSlice(&output, kDefaultWideColumnName);
PutVarint32(&output, static_cast<uint32_t>(value_of_default->size()));

prev_name = &kDefaultWideColumnName;
}

for (size_t i = 0; i < columns.size(); ++i) {
const WideColumn& column = columns[i];
Expand All @@ -34,7 +50,8 @@ Status WideColumnSerialization::Serialize(const WideColumns& columns,
static_cast<size_t>(std::numeric_limits<uint32_t>::max())) {
return Status::InvalidArgument("Wide column name too long");
}
if (i > 0 && columns[i - 1].name().compare(name) >= 0) {

if (prev_name && prev_name->compare(name) >= 0) {
return Status::Corruption("Wide columns out of order");
}

Expand All @@ -46,6 +63,12 @@ Status WideColumnSerialization::Serialize(const WideColumns& columns,

PutLengthPrefixedSlice(&output, name);
PutVarint32(&output, static_cast<uint32_t>(value.size()));

prev_name = &name;
}

if (value_of_default) {
output.append(value_of_default->data(), value_of_default->size());
}

for (const auto& column : columns) {
Expand Down
21 changes: 21 additions & 0 deletions db/wide/wide_column_serialization.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,34 @@ class Slice;
class WideColumnSerialization {
public:
static Status Serialize(const WideColumns& columns, std::string& output);
static Status Serialize(const Slice& value_of_default,
const WideColumns& other_columns,
std::string& output);

static Status Deserialize(Slice& input, WideColumns& columns);

static WideColumns::const_iterator Find(const WideColumns& columns,
const Slice& column_name);
static Status GetValueOfDefaultColumn(Slice& input, Slice& value);

static constexpr uint32_t kCurrentVersion = 1;

private:
static Status SerializeImpl(const Slice* value_of_default,
const WideColumns& columns, std::string& output);
};

inline Status WideColumnSerialization::Serialize(const WideColumns& columns,
std::string& output) {
constexpr Slice* value_of_default = nullptr;

return SerializeImpl(value_of_default, columns, output);
}

inline Status WideColumnSerialization::Serialize(
const Slice& value_of_default, const WideColumns& other_columns,
std::string& output) {
return SerializeImpl(&value_of_default, other_columns, output);
}

} // namespace ROCKSDB_NAMESPACE
29 changes: 29 additions & 0 deletions db/wide/wide_column_serialization_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,25 @@ TEST(WideColumnSerializationTest, SerializeDeserialize) {
}
}

TEST(WideColumnSerializationTest, SerializeWithPrepend) {
Slice value_of_default("baz");
WideColumns other_columns{{"foo", "bar"}, {"hello", "world"}};

std::string output;
ASSERT_OK(WideColumnSerialization::Serialize(value_of_default, other_columns,
output));

Slice input(output);

WideColumns deserialized_columns;
ASSERT_OK(WideColumnSerialization::Deserialize(input, deserialized_columns));

WideColumns expected_columns{{kDefaultWideColumnName, value_of_default},
other_columns[0],
other_columns[1]};
ASSERT_EQ(deserialized_columns, expected_columns);
}

TEST(WideColumnSerializationTest, SerializeDuplicateError) {
WideColumns columns{{"foo", "bar"}, {"foo", "baz"}};
std::string output;
Expand All @@ -132,6 +151,16 @@ TEST(WideColumnSerializationTest, SerializeDuplicateError) {
WideColumnSerialization::Serialize(columns, output).IsCorruption());
}

TEST(WideColumnSerializationTest, SerializeWithPrependDuplicateError) {
Slice value_of_default("baz");
WideColumns other_columns{{kDefaultWideColumnName, "dup"}, {"foo", "bar"}};

std::string output;
ASSERT_TRUE(WideColumnSerialization::Serialize(value_of_default,
other_columns, output)
.IsCorruption());
}

TEST(WideColumnSerializationTest, SerializeOutOfOrderError) {
WideColumns columns{{"hello", "world"}, {"foo", "bar"}};
std::string output;
Expand Down

0 comments on commit 865d557

Please sign in to comment.