// Copyright (c) 2017-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). /** * The encoding of Cassandra Row Value. * * A Cassandra Row Value could either be a row tombstone, * or contains multiple columns, it has following fields: * * struct row_value { * int32_t local_deletion_time; // Time in second when the row is deleted, * // only used for Cassandra tombstone gc. * int64_t marked_for_delete_at; // Ms that marked this row is deleted. * struct column_base columns[]; // For non tombstone row, all columns * // are stored here. * } * * If the local_deletion_time and marked_for_delete_at is set, then this is * a tombstone, otherwise it contains multiple columns. * * There are three type of Columns: Normal Column, Expiring Column and Column * Tombstone, which have following fields: * * // Identify the type of the column. * enum mask { * DELETION_MASK = 0x01, * EXPIRATION_MASK = 0x02, * }; * * struct column { * int8_t mask = 0; * int8_t index; * int64_t timestamp; * int32_t value_length; * char value[value_length]; * } * * struct expiring_column { * int8_t mask = mask.EXPIRATION_MASK; * int8_t index; * int64_t timestamp; * int32_t value_length; * char value[value_length]; * int32_t ttl; * } * * struct tombstone_column { * int8_t mask = mask.DELETION_MASK; * int8_t index; * int32_t local_deletion_time; // Similar to row_value's field. * int64_t marked_for_delete_at; * } */ #pragma once #include #include #include #include "rocksdb/merge_operator.h" #include "rocksdb/slice.h" namespace ROCKSDB_NAMESPACE { namespace cassandra { // Identify the type of the column. enum ColumnTypeMask { DELETION_MASK = 0x01, EXPIRATION_MASK = 0x02, }; class ColumnBase { public: ColumnBase(int8_t mask, int8_t index); virtual ~ColumnBase() = default; virtual int64_t Timestamp() const = 0; virtual int8_t Mask() const; virtual int8_t Index() const; virtual std::size_t Size() const; virtual void Serialize(std::string* dest) const; static std::shared_ptr Deserialize(const char* src, std::size_t offset); private: int8_t mask_; int8_t index_; }; class Column : public ColumnBase { public: Column(int8_t mask, int8_t index, int64_t timestamp, int32_t value_size, const char* value); virtual int64_t Timestamp() const override; virtual std::size_t Size() const override; virtual void Serialize(std::string* dest) const override; static std::shared_ptr Deserialize(const char* src, std::size_t offset); private: int64_t timestamp_; int32_t value_size_; const char* value_; }; class Tombstone : public ColumnBase { public: Tombstone(int8_t mask, int8_t index, int32_t local_deletion_time, int64_t marked_for_delete_at); virtual int64_t Timestamp() const override; virtual std::size_t Size() const override; virtual void Serialize(std::string* dest) const override; bool Collectable(int32_t gc_grace_period) const; static std::shared_ptr Deserialize(const char* src, std::size_t offset); private: int32_t local_deletion_time_; int64_t marked_for_delete_at_; }; class ExpiringColumn : public Column { public: ExpiringColumn(int8_t mask, int8_t index, int64_t timestamp, int32_t value_size, const char* value, int32_t ttl); virtual std::size_t Size() const override; virtual void Serialize(std::string* dest) const override; bool Expired() const; std::shared_ptr ToTombstone() const; static std::shared_ptr Deserialize(const char* src, std::size_t offset); private: int32_t ttl_; std::chrono::time_point TimePoint() const; std::chrono::seconds Ttl() const; }; using Columns = std::vector>; class RowValue { public: // Create a Row Tombstone. RowValue(int32_t local_deletion_time, int64_t marked_for_delete_at); // Create a Row containing columns. RowValue(Columns columns, int64_t last_modified_time); RowValue(const RowValue& /*that*/) = delete; RowValue(RowValue&& /*that*/) noexcept = default; RowValue& operator=(const RowValue& /*that*/) = delete; RowValue& operator=(RowValue&& /*that*/) = default; std::size_t Size() const; bool IsTombstone() const; // For Tombstone this returns the marked_for_delete_at_, // otherwise it returns the max timestamp of containing columns. int64_t LastModifiedTime() const; void Serialize(std::string* dest) const; RowValue RemoveExpiredColumns(bool* changed) const; RowValue ConvertExpiredColumnsToTombstones(bool* changed) const; RowValue RemoveTombstones(int32_t gc_grace_period) const; bool Empty() const; static RowValue Deserialize(const char* src, std::size_t size); // Merge multiple rows according to their timestamp. static RowValue Merge(std::vector&& values); const Columns& get_columns() { return columns_; } private: int32_t local_deletion_time_; int64_t marked_for_delete_at_; Columns columns_; int64_t last_modified_time_; }; } // namespace cassandra } // namespace ROCKSDB_NAMESPACE