2017-05-26 04:48:44 +08:00
|
|
|
/*
|
|
|
|
* ReadYourWrites.h
|
|
|
|
*
|
|
|
|
* This source file is part of the FoundationDB open source project
|
|
|
|
*
|
|
|
|
* Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
|
2018-02-22 02:25:11 +08:00
|
|
|
*
|
2017-05-26 04:48:44 +08:00
|
|
|
* Licensed 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
|
2018-02-22 02:25:11 +08:00
|
|
|
*
|
2017-05-26 04:48:44 +08:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2018-02-22 02:25:11 +08:00
|
|
|
*
|
2017-05-26 04:48:44 +08:00
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef FDBCLIENT_READYOURWRITES_H
|
|
|
|
#define FDBCLIENT_READYOURWRITES_H
|
|
|
|
#pragma once
|
|
|
|
|
2019-02-18 07:41:16 +08:00
|
|
|
#include "fdbclient/NativeAPI.actor.h"
|
2018-10-20 01:30:13 +08:00
|
|
|
#include "fdbclient/KeyRangeMap.h"
|
|
|
|
#include "fdbclient/RYWIterator.h"
|
2021-04-30 13:31:16 +08:00
|
|
|
#include "fdbclient/ISingleThreadTransaction.h"
|
2017-05-26 04:48:44 +08:00
|
|
|
#include <list>
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
// SOMEDAY: Optimize getKey to avoid using getRange
|
2017-05-26 04:48:44 +08:00
|
|
|
|
|
|
|
struct ReadYourWritesTransactionOptions {
|
|
|
|
bool readYourWritesDisabled : 1;
|
|
|
|
bool readAheadDisabled : 1;
|
|
|
|
bool readSystemKeys : 1;
|
|
|
|
bool writeSystemKeys : 1;
|
|
|
|
bool nextWriteDisableConflictRange : 1;
|
|
|
|
bool debugRetryLogging : 1;
|
|
|
|
bool disableUsedDuringCommitProtection : 1;
|
2020-05-06 02:41:18 +08:00
|
|
|
bool specialKeySpaceRelaxed : 1;
|
2020-07-09 06:49:34 +08:00
|
|
|
bool specialKeySpaceChangeConfiguration : 1;
|
2017-05-26 04:48:44 +08:00
|
|
|
double timeoutInSeconds;
|
|
|
|
int maxRetries;
|
|
|
|
int snapshotRywEnabled;
|
2021-04-29 07:22:34 +08:00
|
|
|
bool bypassUnreadable : 1;
|
2017-05-26 04:48:44 +08:00
|
|
|
|
|
|
|
ReadYourWritesTransactionOptions() {}
|
2019-03-22 04:47:12 +08:00
|
|
|
explicit ReadYourWritesTransactionOptions(Transaction const& tr);
|
2019-03-20 00:15:41 +08:00
|
|
|
void reset(Transaction const& tr);
|
2017-05-26 04:48:44 +08:00
|
|
|
bool getAndResetWriteConflictDisabled();
|
|
|
|
};
|
|
|
|
|
|
|
|
struct TransactionDebugInfo : public ReferenceCounted<TransactionDebugInfo> {
|
|
|
|
std::string transactionName;
|
|
|
|
double lastRetryLogTime;
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
TransactionDebugInfo() : transactionName(""), lastRetryLogTime() {}
|
2017-05-26 04:48:44 +08:00
|
|
|
};
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
// Values returned by a ReadYourWritesTransaction will contain a reference to the transaction's arena. Therefore,
|
|
|
|
// keeping a reference to a value longer than its creating transaction would hold all of the memory generated by the
|
|
|
|
// transaction
|
2020-11-28 02:10:41 +08:00
|
|
|
class ReadYourWritesTransaction final : NonCopyable,
|
2021-04-30 13:31:16 +08:00
|
|
|
public ISingleThreadTransaction,
|
2020-11-28 02:10:41 +08:00
|
|
|
public FastAllocated<ReadYourWritesTransaction> {
|
2017-05-26 04:48:44 +08:00
|
|
|
public:
|
2021-03-11 02:06:03 +08:00
|
|
|
explicit ReadYourWritesTransaction(Database const& cx);
|
2017-05-26 04:48:44 +08:00
|
|
|
~ReadYourWritesTransaction();
|
|
|
|
|
2021-06-30 01:29:33 +08:00
|
|
|
void setDatabase(Database const&) override;
|
2021-04-30 13:31:16 +08:00
|
|
|
void setVersion(Version v) override { tr.setVersion(v); }
|
|
|
|
Future<Version> getReadVersion() override;
|
2021-05-15 15:23:21 +08:00
|
|
|
Optional<Version> getCachedReadVersion() const override { return tr.getCachedReadVersion(); }
|
2021-07-17 15:11:40 +08:00
|
|
|
Future<Optional<Value>> get(const Key& key, Snapshot = Snapshot::False) override;
|
|
|
|
Future<Key> getKey(const KeySelector& key, Snapshot = Snapshot::False) override;
|
2021-07-19 05:26:15 +08:00
|
|
|
Future<RangeResult> getRange(const KeySelector& begin,
|
|
|
|
const KeySelector& end,
|
|
|
|
int limit,
|
|
|
|
Snapshot = Snapshot::False,
|
|
|
|
Reverse = Reverse::False) override;
|
|
|
|
Future<RangeResult> getRange(KeySelector begin,
|
|
|
|
KeySelector end,
|
|
|
|
GetRangeLimits limits,
|
|
|
|
Snapshot = Snapshot::False,
|
|
|
|
Reverse = Reverse::False) override;
|
|
|
|
Future<RangeResult> getRange(const KeyRange& keys,
|
|
|
|
int limit,
|
|
|
|
Snapshot snapshot = Snapshot::False,
|
|
|
|
Reverse reverse = Reverse::False) {
|
2021-03-11 02:06:03 +08:00
|
|
|
return getRange(KeySelector(firstGreaterOrEqual(keys.begin), keys.arena()),
|
|
|
|
KeySelector(firstGreaterOrEqual(keys.end), keys.arena()),
|
|
|
|
limit,
|
|
|
|
snapshot,
|
|
|
|
reverse);
|
2017-05-26 04:48:44 +08:00
|
|
|
}
|
2021-05-04 04:14:16 +08:00
|
|
|
Future<RangeResult> getRange(const KeyRange& keys,
|
|
|
|
GetRangeLimits limits,
|
2021-07-17 15:11:40 +08:00
|
|
|
Snapshot snapshot = Snapshot::False,
|
|
|
|
Reverse reverse = Reverse::False) {
|
2021-03-11 02:06:03 +08:00
|
|
|
return getRange(KeySelector(firstGreaterOrEqual(keys.begin), keys.arena()),
|
|
|
|
KeySelector(firstGreaterOrEqual(keys.end), keys.arena()),
|
|
|
|
limits,
|
|
|
|
snapshot,
|
|
|
|
reverse);
|
2017-05-26 04:48:44 +08:00
|
|
|
}
|
2021-11-10 03:07:09 +08:00
|
|
|
Future<RangeResult> getRangeAndFlatMap(KeySelector begin,
|
|
|
|
KeySelector end,
|
|
|
|
Key mapper,
|
|
|
|
GetRangeLimits limits,
|
|
|
|
Snapshot = Snapshot::False,
|
|
|
|
Reverse = Reverse::False) override;
|
2017-05-26 04:48:44 +08:00
|
|
|
|
2021-04-30 13:31:16 +08:00
|
|
|
[[nodiscard]] Future<Standalone<VectorRef<const char*>>> getAddressesForKey(const Key& key) override;
|
|
|
|
Future<Standalone<VectorRef<KeyRef>>> getRangeSplitPoints(const KeyRange& range, int64_t chunkSize) override;
|
|
|
|
Future<int64_t> getEstimatedRangeSizeBytes(const KeyRange& keys) override;
|
2017-05-26 04:48:44 +08:00
|
|
|
|
2021-11-09 02:24:45 +08:00
|
|
|
Future<Standalone<VectorRef<KeyRangeRef>>> getBlobGranuleRanges(const KeyRange& range) override;
|
|
|
|
Future<Standalone<VectorRef<BlobGranuleChunkRef>>> readBlobGranules(const KeyRange& range,
|
|
|
|
Version begin,
|
|
|
|
Optional<Version> readVersion,
|
|
|
|
Version* readVersionOut) override;
|
|
|
|
|
2021-04-30 13:31:16 +08:00
|
|
|
void addReadConflictRange(KeyRangeRef const& keys) override;
|
|
|
|
void makeSelfConflicting() override { tr.makeSelfConflicting(); }
|
2017-05-26 04:48:44 +08:00
|
|
|
|
2021-04-30 13:31:16 +08:00
|
|
|
void atomicOp(const KeyRef& key, const ValueRef& operand, uint32_t operationType) override;
|
|
|
|
void set(const KeyRef& key, const ValueRef& value) override;
|
|
|
|
void clear(const KeyRangeRef& range) override;
|
|
|
|
void clear(const KeyRef& key) override;
|
2017-05-26 04:48:44 +08:00
|
|
|
|
2021-04-30 13:31:16 +08:00
|
|
|
[[nodiscard]] Future<Void> watch(const Key& key) override;
|
2017-05-26 04:48:44 +08:00
|
|
|
|
2021-04-30 13:31:16 +08:00
|
|
|
void addWriteConflictRange(KeyRangeRef const& keys) override;
|
2017-05-26 04:48:44 +08:00
|
|
|
|
2021-04-30 13:31:16 +08:00
|
|
|
[[nodiscard]] Future<Void> commit() override;
|
2021-05-01 02:32:53 +08:00
|
|
|
Version getCommittedVersion() const override { return tr.getCommittedVersion(); }
|
|
|
|
int64_t getApproximateSize() const override { return approximateSize; }
|
2021-04-30 13:31:16 +08:00
|
|
|
[[nodiscard]] Future<Standalone<StringRef>> getVersionstamp() override;
|
2017-05-26 04:48:44 +08:00
|
|
|
|
2021-04-30 13:31:16 +08:00
|
|
|
void setOption(FDBTransactionOptions::Option option, Optional<StringRef> value = Optional<StringRef>()) override;
|
2017-05-26 04:48:44 +08:00
|
|
|
|
2021-04-30 13:31:16 +08:00
|
|
|
[[nodiscard]] Future<Void> onError(Error const& e) override;
|
2017-05-26 04:48:44 +08:00
|
|
|
|
|
|
|
// These are to permit use as state variables in actors:
|
|
|
|
ReadYourWritesTransaction() : cache(&arena), writes(&arena) {}
|
2020-06-10 08:33:41 +08:00
|
|
|
void operator=(ReadYourWritesTransaction&& r) noexcept;
|
|
|
|
ReadYourWritesTransaction(ReadYourWritesTransaction&& r) noexcept;
|
2017-05-26 04:48:44 +08:00
|
|
|
|
2021-04-30 13:31:16 +08:00
|
|
|
void cancel() override;
|
|
|
|
void reset() override;
|
|
|
|
void debugTransaction(UID dID) override { tr.debugTransaction(dID); }
|
2017-05-26 04:48:44 +08:00
|
|
|
|
2020-04-30 02:52:26 +08:00
|
|
|
Future<Void> debug_onIdle() { return reading; }
|
|
|
|
|
2020-04-29 03:44:34 +08:00
|
|
|
// Wait for all reads that are currently pending to complete
|
2020-04-30 02:52:26 +08:00
|
|
|
Future<Void> pendingReads() { return resetPromise.getFuture() || reading; }
|
2020-05-21 04:55:07 +08:00
|
|
|
// Throws before the lifetime of this transaction ends
|
|
|
|
Future<Void> resetFuture() { return resetPromise.getFuture(); }
|
2017-05-26 04:48:44 +08:00
|
|
|
|
2021-05-15 15:23:21 +08:00
|
|
|
void checkDeferredError() const override {
|
2021-03-11 02:06:03 +08:00
|
|
|
tr.checkDeferredError();
|
|
|
|
if (deferredError.code() != invalid_error_code)
|
|
|
|
throw deferredError;
|
|
|
|
}
|
2017-05-26 04:48:44 +08:00
|
|
|
|
2021-04-30 13:31:16 +08:00
|
|
|
void getWriteConflicts(KeyRangeMap<bool>* result) override;
|
2017-05-26 04:48:44 +08:00
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
Database getDatabase() const { return tr.getDatabase(); }
|
2020-04-04 07:11:20 +08:00
|
|
|
|
2021-12-18 03:57:39 +08:00
|
|
|
Reference<const TransactionState> getTransactionState() const { return tr.trState; }
|
2020-04-29 00:00:06 +08:00
|
|
|
|
2020-12-04 06:06:11 +08:00
|
|
|
void setTransactionID(uint64_t id);
|
|
|
|
void setToken(uint64_t token);
|
|
|
|
|
2020-04-30 05:43:37 +08:00
|
|
|
// Read from the special key space readConflictRangeKeysRange
|
2021-05-04 04:14:16 +08:00
|
|
|
RangeResult getReadConflictRangeIntersecting(KeyRangeRef kr);
|
2020-04-30 05:43:37 +08:00
|
|
|
// Read from the special key space writeConflictRangeKeysRange
|
2021-05-04 04:14:16 +08:00
|
|
|
RangeResult getWriteConflictRangeIntersecting(KeyRangeRef kr);
|
2020-04-29 00:00:06 +08:00
|
|
|
|
2020-05-06 02:41:18 +08:00
|
|
|
bool specialKeySpaceRelaxed() const { return options.specialKeySpaceRelaxed; }
|
2020-07-09 06:49:34 +08:00
|
|
|
bool specialKeySpaceChangeConfiguration() const { return options.specialKeySpaceChangeConfiguration; }
|
2020-05-06 02:41:18 +08:00
|
|
|
|
2020-06-28 03:22:32 +08:00
|
|
|
KeyRangeMap<std::pair<bool, Optional<Value>>>& getSpecialKeySpaceWriteMap() { return specialKeySpaceWriteMap; }
|
2020-06-24 02:21:03 +08:00
|
|
|
bool readYourWritesDisabled() const { return options.readYourWritesDisabled; }
|
2020-06-28 03:22:32 +08:00
|
|
|
const Optional<std::string>& getSpecialKeySpaceErrorMsg() { return specialKeySpaceErrorMsg; }
|
|
|
|
void setSpecialKeySpaceErrorMsg(const std::string& msg) { specialKeySpaceErrorMsg = msg; }
|
2020-07-07 02:02:48 +08:00
|
|
|
Transaction& getTransaction() { return tr; }
|
2020-05-06 02:41:18 +08:00
|
|
|
|
2021-08-12 09:39:47 +08:00
|
|
|
// used in template functions as returned Future type
|
2021-08-28 08:07:47 +08:00
|
|
|
template <typename Type>
|
|
|
|
using FutureT = Future<Type>;
|
2021-08-11 09:07:36 +08:00
|
|
|
|
2017-05-26 04:48:44 +08:00
|
|
|
private:
|
|
|
|
friend class RYWImpl;
|
|
|
|
|
|
|
|
Arena arena;
|
|
|
|
Transaction tr;
|
|
|
|
SnapshotCache cache;
|
|
|
|
WriteMap writes;
|
|
|
|
CoalescedKeyRefRangeMap<bool> readConflicts;
|
2021-03-11 02:06:03 +08:00
|
|
|
Map<Key, std::vector<Reference<Watch>>> watchMap; // Keys that are being watched in this transaction
|
2017-05-26 04:48:44 +08:00
|
|
|
Promise<Void> resetPromise;
|
|
|
|
AndFuture reading;
|
|
|
|
int retries;
|
2019-06-29 01:15:37 +08:00
|
|
|
int64_t approximateSize;
|
2017-05-26 04:48:44 +08:00
|
|
|
Future<Void> timeoutActor;
|
|
|
|
double creationTime;
|
|
|
|
bool commitStarted;
|
|
|
|
|
2020-05-04 12:43:50 +08:00
|
|
|
// For reading conflict ranges from the special key space
|
|
|
|
VectorRef<KeyRef> versionStampKeys;
|
|
|
|
Future<Standalone<StringRef>> versionStampFuture;
|
2020-05-05 00:43:20 +08:00
|
|
|
Standalone<VectorRef<KeyRangeRef>>
|
|
|
|
nativeReadRanges; // Used to read conflict ranges after committing an ryw disabled transaction
|
|
|
|
Standalone<VectorRef<KeyRangeRef>>
|
|
|
|
nativeWriteRanges; // Used to read conflict ranges after committing an ryw disabled transaction
|
2020-05-01 09:41:25 +08:00
|
|
|
|
2017-05-26 04:48:44 +08:00
|
|
|
Reference<TransactionDebugInfo> transactionDebugInfo;
|
|
|
|
|
2020-06-24 02:21:03 +08:00
|
|
|
KeyRangeMap<std::pair<bool, Optional<Value>>> specialKeySpaceWriteMap;
|
2020-06-28 03:22:32 +08:00
|
|
|
Optional<std::string> specialKeySpaceErrorMsg;
|
2020-06-24 02:21:03 +08:00
|
|
|
|
2019-03-22 02:45:43 +08:00
|
|
|
void resetTimeout();
|
2021-03-11 02:06:03 +08:00
|
|
|
void updateConflictMap(KeyRef const& key, WriteMap::iterator& it); // pre: it.segmentContains(key)
|
|
|
|
void updateConflictMap(
|
|
|
|
KeyRangeRef const& keys,
|
|
|
|
WriteMap::iterator& it); // pre: it.segmentContains(keys.begin), keys are already inside this->arena
|
2019-07-17 06:21:13 +08:00
|
|
|
void writeRangeToNativeTransaction(KeyRangeRef const& keys);
|
2017-05-26 04:48:44 +08:00
|
|
|
|
|
|
|
void resetRyow(); // doesn't reset the encapsulated transaction, or creation time/retry state
|
|
|
|
KeyRef getMaxReadKey();
|
|
|
|
KeyRef getMaxWriteKey();
|
|
|
|
|
|
|
|
bool checkUsedDuringCommit();
|
|
|
|
|
|
|
|
void debugLogRetries(Optional<Error> error = Optional<Error>());
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
void setOptionImpl(FDBTransactionOptions::Option option, Optional<StringRef> value = Optional<StringRef>());
|
2019-06-29 04:24:32 +08:00
|
|
|
void applyPersistentOptions();
|
|
|
|
|
|
|
|
std::vector<std::pair<FDBTransactionOptions::Option, Optional<Standalone<StringRef>>>> persistentOptions;
|
2017-05-26 04:48:44 +08:00
|
|
|
ReadYourWritesTransactionOptions options;
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|