2020-04-10 07:55:56 +08:00
|
|
|
/*
|
|
|
|
* TagThrottle.h
|
|
|
|
*
|
|
|
|
* This source file is part of the FoundationDB open source project
|
|
|
|
*
|
|
|
|
* Copyright 2013-2020 Apple Inc. and the FoundationDB project authors
|
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef FDBCLIENT_TAG_THROTTLE_H
|
|
|
|
#define FDBCLIENT_TAG_THROTTLE_H
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "flow/Error.h"
|
|
|
|
#include "flow/flow.h"
|
|
|
|
#include "flow/network.h"
|
|
|
|
#include "fdbclient/FDBTypes.h"
|
|
|
|
|
|
|
|
#include <set>
|
|
|
|
|
|
|
|
class Database;
|
|
|
|
|
2020-04-17 23:07:01 +08:00
|
|
|
namespace ThrottleApi {
|
2020-04-10 07:55:56 +08:00
|
|
|
enum class Priority {
|
|
|
|
BATCH,
|
|
|
|
DEFAULT,
|
|
|
|
IMMEDIATE
|
|
|
|
};
|
|
|
|
|
2020-04-17 23:07:01 +08:00
|
|
|
const char* priorityToString(Priority priority, bool capitalize=true);
|
|
|
|
Priority priorityFromReadVersionFlags(int flags);
|
|
|
|
}
|
2020-04-10 07:55:56 +08:00
|
|
|
|
2020-04-17 23:07:01 +08:00
|
|
|
typedef StringRef TransactionTagRef;
|
|
|
|
typedef Standalone<TransactionTagRef> TransactionTag;
|
2020-04-10 07:55:56 +08:00
|
|
|
|
2020-04-17 23:07:01 +08:00
|
|
|
struct TagThrottleInfo {
|
2020-04-17 05:43:22 +08:00
|
|
|
double tpsRate;
|
2020-04-10 07:55:56 +08:00
|
|
|
double expiration;
|
|
|
|
bool autoThrottled;
|
2020-04-17 23:07:01 +08:00
|
|
|
ThrottleApi::Priority priority;
|
2020-04-10 07:55:56 +08:00
|
|
|
|
|
|
|
bool serializeExpirationAsDuration;
|
|
|
|
|
2020-04-17 23:07:01 +08:00
|
|
|
TagThrottleInfo() : tpsRate(0), expiration(0), autoThrottled(false), priority(ThrottleApi::Priority::DEFAULT), serializeExpirationAsDuration(true) {}
|
|
|
|
TagThrottleInfo(double tpsRate, double expiration, bool autoThrottled, ThrottleApi::Priority priority, bool serializeExpirationAsDuration)
|
2020-04-17 05:43:22 +08:00
|
|
|
: tpsRate(tpsRate), expiration(expiration), autoThrottled(autoThrottled), priority(priority),
|
2020-04-10 07:55:56 +08:00
|
|
|
serializeExpirationAsDuration(serializeExpirationAsDuration) {}
|
|
|
|
|
|
|
|
template<class Ar>
|
|
|
|
void serialize(Ar& ar) {
|
|
|
|
if(ar.isDeserializing) {
|
2020-04-17 05:43:22 +08:00
|
|
|
serializer(ar, tpsRate, expiration, autoThrottled, priority, serializeExpirationAsDuration);
|
2020-04-10 07:55:56 +08:00
|
|
|
if(serializeExpirationAsDuration) {
|
|
|
|
expiration += now();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
double serializedExpiration = expiration;
|
|
|
|
if(serializeExpirationAsDuration) {
|
|
|
|
serializedExpiration = std::max(expiration - now(), 0.0);
|
|
|
|
}
|
|
|
|
|
2020-04-17 05:43:22 +08:00
|
|
|
serializer(ar, tpsRate, serializedExpiration, autoThrottled, priority, serializeExpirationAsDuration);
|
2020-04-10 07:55:56 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class TagSet {
|
|
|
|
public:
|
2020-04-17 05:43:22 +08:00
|
|
|
typedef std::set<TransactionTagRef>::const_iterator const_iterator;
|
2020-04-10 07:55:56 +08:00
|
|
|
|
|
|
|
TagSet() : bytes(0) {}
|
|
|
|
|
2020-04-17 05:43:22 +08:00
|
|
|
void addTag(TransactionTagRef tag);
|
2020-04-10 07:55:56 +08:00
|
|
|
size_t size();
|
|
|
|
|
|
|
|
const_iterator begin() const {
|
|
|
|
return tags.begin();
|
|
|
|
}
|
|
|
|
|
|
|
|
const_iterator end() const {
|
|
|
|
return tags.end();
|
|
|
|
}
|
|
|
|
|
|
|
|
//private:
|
|
|
|
Arena arena; // TODO: where to hold this memory?
|
2020-04-17 05:43:22 +08:00
|
|
|
std::set<TransactionTagRef> tags;
|
2020-04-10 07:55:56 +08:00
|
|
|
size_t bytes;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct dynamic_size_traits<TagSet> : std::true_type {
|
|
|
|
// May be called multiple times during one serialization
|
|
|
|
template <class Context>
|
|
|
|
static size_t size(const TagSet& t, Context&) {
|
|
|
|
return t.tags.size() + t.bytes;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Guaranteed to be called only once during serialization
|
|
|
|
template <class Context>
|
|
|
|
static void save(uint8_t* out, const TagSet& t, Context&) {
|
|
|
|
for (const auto& tag : t.tags) {
|
|
|
|
*out = (uint8_t)tag.size();
|
|
|
|
++out;
|
|
|
|
|
|
|
|
std::copy(tag.begin(), tag.end(), out);
|
|
|
|
out += tag.size();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Context is an arbitrary type that is plumbed by reference throughout the
|
|
|
|
// load call tree.
|
|
|
|
template <class Context>
|
|
|
|
static void load(const uint8_t* data, size_t size, TagSet& t, Context& context) {
|
|
|
|
const uint8_t *end = data + size;
|
|
|
|
while(data < end) {
|
|
|
|
uint8_t len = *data;
|
|
|
|
++data;
|
2020-04-17 05:43:22 +08:00
|
|
|
TransactionTagRef tag(context.tryReadZeroCopy(data, len), len);
|
2020-04-10 07:55:56 +08:00
|
|
|
data += len;
|
|
|
|
|
|
|
|
t.tags.insert(tag);
|
|
|
|
t.bytes += tag.size();
|
|
|
|
}
|
|
|
|
|
2020-04-11 04:29:28 +08:00
|
|
|
t.arena = context.arena(); // TODO: this arena could be big
|
2020-04-10 07:55:56 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
namespace ThrottleApi {
|
2020-04-11 01:12:26 +08:00
|
|
|
// Currently, only 1 tag in a key is supported
|
2020-04-17 05:43:22 +08:00
|
|
|
Key throttleKeyForTags(std::set<TransactionTagRef> const& tags);
|
|
|
|
TransactionTagRef tagFromThrottleKey(KeyRef key);
|
2020-04-11 01:12:26 +08:00
|
|
|
|
2020-04-17 05:43:22 +08:00
|
|
|
Future<std::map<TransactionTag, TagThrottleInfo>> getTags(Database const& db, int const& limit);
|
2020-04-10 07:55:56 +08:00
|
|
|
|
2020-04-17 05:43:22 +08:00
|
|
|
Future<Void> throttleTag(Database const& db, TransactionTagRef const& tag, double const& tpsRate, double const& expiration,
|
2020-04-10 07:55:56 +08:00
|
|
|
bool const& serializeExpirationAsDuration, bool const& autoThrottled); // TODO: priorities
|
|
|
|
|
2020-04-17 05:43:22 +08:00
|
|
|
Future<bool> unthrottleTag(Database const& db, TransactionTagRef const& tag);
|
2020-04-10 07:55:56 +08:00
|
|
|
|
|
|
|
Future<uint64_t> unthrottleManual(Database db);
|
|
|
|
Future<uint64_t> unthrottleAuto(Database db);
|
|
|
|
Future<uint64_t> unthrottleAll(Database db);
|
|
|
|
|
|
|
|
Future<Void> enableAuto(Database const& db, bool const& enabled);
|
|
|
|
|
|
|
|
TagThrottleInfo decodeTagThrottleValue(const ValueRef& value);
|
|
|
|
};
|
|
|
|
|
2020-04-17 23:07:01 +08:00
|
|
|
BINARY_SERIALIZABLE(ThrottleApi::Priority);
|
|
|
|
|
|
|
|
template<class Value>
|
|
|
|
using TagThrottleMap = std::unordered_map<TransactionTag, Value, std::hash<TransactionTagRef>>;
|
|
|
|
|
|
|
|
template<class Value>
|
|
|
|
using PrioritizedTagThrottleMap = std::map<ThrottleApi::Priority, TagThrottleMap<Value>>;
|
|
|
|
|
2020-04-10 07:55:56 +08:00
|
|
|
#endif
|