blob: 72f73ebeff104727282770a73e9041d81a450c78 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#pragma once
#include <string_view>
#include "meta-store/txn_kv.h"
#include "meta-store/txn_kv_error.h"
#include "meta-store/versionstamp.h"
namespace doris::cloud {
// The options for getting a range of versioned value.
struct VersionedRangeGetOptions {
// Whether to read the snapshot.
bool snapshot = false;
// The number of keys returned in the underlying range request.
int batch_limit = 0; // 0 means no limit
// The versionstamp to get the document keys.
Versionstamp snapshot_version = Versionstamp::max();
// The begin key selector for the range get operation.
//
// Since versioned keys are stored as "key_prefix + versionstamp", we need to determine
// the exact range boundaries. The selector controls which versionstamp is appended
// to the key prefix to form the complete range boundary key:
// - LAST_LESS_THAN/FIRST_GREATER_OR_EQUAL: appends Versionstamp::min() (earliest version)
// - LAST_LESS_OR_EQUAL/FIRST_GREATER_THAN: appends Versionstamp::max() (latest version)
RangeKeySelector begin_key_selector = RangeKeySelector::FIRST_GREATER_THAN;
// The end key selector for the range get operation.
//
// Works the same way as begin_key_selector, determining the end boundary of the range
// by appending the appropriate versionstamp to the end key prefix.
RangeKeySelector end_key_selector = RangeKeySelector::FIRST_GREATER_OR_EQUAL;
};
// Get a range of versioned value from the transaction.
//
// The key values are returned in reverse order, meaning the bigger key is returned first.
class VersionedRangeGetIterator {
public:
using Element = std::tuple<std::string_view, Versionstamp, std::string_view>;
VersionedRangeGetIterator(std::unique_ptr<FullRangeGetIterator> iter,
Versionstamp snapshot_version)
: snapshot_version_(snapshot_version), iter_(std::move(iter)) {}
VersionedRangeGetIterator(const VersionedRangeGetIterator&) = delete;
VersionedRangeGetIterator& operator=(const VersionedRangeGetIterator&) = delete;
VersionedRangeGetIterator(VersionedRangeGetIterator&& other) noexcept
: snapshot_version_(other.snapshot_version_),
error_code_(other.error_code_),
has_find_(other.has_find_),
current_version_(other.current_version_),
current_key_(other.current_key_),
current_value_(other.current_value_),
iter_(std::move(other.iter_)) {}
VersionedRangeGetIterator& operator=(VersionedRangeGetIterator&& other) noexcept {
if (this != &other) {
iter_ = std::move(other.iter_);
error_code_ = other.error_code_;
has_find_ = other.has_find_;
current_version_ = other.current_version_;
current_key_ = other.current_key_;
current_value_ = other.current_value_;
snapshot_version_ = other.snapshot_version_;
}
return *this;
}
bool has_next();
bool is_valid() const { return error_code_ == TxnErrorCode::TXN_OK && iter_->is_valid(); }
TxnErrorCode error_code() const {
return error_code_ == TxnErrorCode::TXN_OK ? iter_->error_code() : error_code_;
}
std::optional<Element> next();
std::optional<Element> peek();
private:
std::tuple<std::string_view, Versionstamp> parse_key(std::string_view key);
Versionstamp snapshot_version_;
TxnErrorCode error_code_ = TxnErrorCode::TXN_OK;
bool has_find_ = false; // Whether we have found a valid key in the current iteration.
Versionstamp current_version_;
std::string_view current_key_;
std::string_view current_value_;
std::unique_ptr<FullRangeGetIterator> iter_;
};
// Get a range of versioned value from the transaction.
//
// This function performs a range query on versioned documents stored with key format
// "key + versionstamp". It returns an iterator that can traverse through all matching
// documents within the specified key range (in reverse order).
//
// It returns a iterator. The iterator returns documents in reverse order (latest first)
// and automatically filters out documents newer than the snapshot_version.
std::unique_ptr<VersionedRangeGetIterator> versioned_get_range(
Transaction* txn, std::string_view begin, std::string_view end,
const VersionedRangeGetOptions& opts);
// Remove a versioned document from the transaction by key and versionstamp.
//
// The key is the encode_xxx_keys function result. The versionstamp is the specific
// version of the document to remove.
void versioned_remove(Transaction* txn, std::string_view key, Versionstamp v);
// Remove a versioned document from the transaction by key with versionstamp.
void versioned_remove(Transaction* txn, std::string_view key_with_versionstamp);
// Remove all versioned documents from the transaction by key.
void versioned_remove_all(Transaction* txn, std::string_view key);
// Put a versioned value into the transaction with a specific versionstamp.
void versioned_put(Transaction* txn, std::string_view key, Versionstamp v, std::string_view value);
// Put a versioned value, the versionstamp will be generated automatically.
//
// The generated versionstamp will be the largest versionstamp in the underlying storage.
void versioned_put(Transaction* txn, std::string_view key, std::string_view value);
// Get a versioned value from the transaction by key and versionstamp.
//
// Only the document values which versionstamp is less than the given `snapshot_version` will be
// returned. If `snapshot_version` is Versionstamp::max(), it will return the latest version of
// the document for the given key.
//
// The versionstamp of the document will be returned in `value_version`.
TxnErrorCode versioned_get(Transaction* txn, std::string_view key, Versionstamp snapshot_version,
Versionstamp* value_version, std::string* value, bool snapshot = false);
// Get a versioned value from the transaction by key and the latest versionstamp.
//
// It returns the latest version of the document for the given key, which is equivalent to
// calling `versioned_get` with `snapshot_version` set to Versionstamp::max().
//
// The versionstamp of the document will be returned in `value_version`.
static inline TxnErrorCode versioned_get(Transaction* txn, std::string_view key,
Versionstamp* value_version, std::string* value,
bool snapshot = false) {
return versioned_get(txn, key, Versionstamp::max(), value_version, value, snapshot);
}
// Get a batch of versioned values from the transaction by keys and versionstamp.
//
// For each key, it returns the latest version of the document for the given key.
//
// The value and versionstamp for each key will be returned in `values`, in the same order likes keys.
TxnErrorCode versioned_batch_get(
Transaction* txn, const std::vector<std::string>& keys, Versionstamp snapshot_version,
std::vector<std::optional<std::pair<std::string, Versionstamp>>>* values,
bool snapshot = false);
// Get a batch of versioned values from the transaction by keys and versionstamp.
//
// For each key, it returns the latest version of the document for the given key,
// which is equivalent to calling `versioned_batch_get` with `snapshot_version` set to Versionstamp::max().
//
// The value and versionstamp for each key will be returned in `values`, in the same order likes keys.
static inline TxnErrorCode versioned_batch_get(
Transaction* txn, const std::vector<std::string>& keys,
std::vector<std::optional<std::pair<std::string, Versionstamp>>>* values,
bool snapshot = false) {
return versioned_batch_get(txn, keys, Versionstamp::max(), values, snapshot);
}
// Encode a versioned key with the given versionstamp.
//
// The key is the original key, and the versionstamp is appended to the key.
// The resulting key will be in the format: "key + versionstamp + VERSIONSTAMP_END_TAG".
std::string encode_versioned_key(std::string_view key, Versionstamp v);
// Decode a versioned key to extract the versionstamp.
//
// The key should be in the format: "key + versionstamp + VERSIONSTAMP_END_TAG".
// If the key is valid, it returns true and sets `v` to the extracted versionstamp.
// If the key is invalid or does not contain a versionstamp, it returns false.
//
// The key is modified to remove the versionstamp and end tag.
bool decode_versioned_key(std::string_view* key, Versionstamp* v);
} // namespace doris::cloud