cachelib/navy/driver/Driver.h (84 lines of code) (raw):
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* 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.
*/
#pragma once
#include <memory>
#include <stdexcept>
#include <utility>
#include "cachelib/common/AtomicCounter.h"
#include "cachelib/navy/AbstractCache.h"
#include "cachelib/navy/admission_policy/AdmissionPolicy.h"
#include "cachelib/navy/common/Device.h"
#include "cachelib/navy/engine/Engine.h"
#include "cachelib/navy/scheduler/JobScheduler.h"
namespace facebook {
namespace cachelib {
namespace navy {
// The driver for Navy cache engines.
// This class provides the synchronous and asynchronous navy APIs to NvmCache.
class Driver final : public AbstractCache {
public:
struct Config {
std::unique_ptr<Device> device;
std::unique_ptr<JobScheduler> scheduler;
std::unique_ptr<Engine> largeItemCache;
std::unique_ptr<Engine> smallItemCache;
std::unique_ptr<AdmissionPolicy> admissionPolicy;
uint32_t smallItemMaxSize{};
// Limited by scheduler parallelism (thread), this is large enough value to
// mean "no limit".
uint32_t maxConcurrentInserts{1'000'000};
uint64_t maxParcelMemory{256 << 20}; // 256MB
size_t metadataSize{};
Config& validate();
};
// Contructor throws std::exception if config is invalid.
//
// @param config config that was validated with Config::validate
//
// @throw std::invalid_argument on bad config
explicit Driver(Config&& config);
Driver(const Driver&) = delete;
Driver& operator=(const Driver&) = delete;
~Driver() override;
// Return true if item is considered a "large item". This is meant to be
// a very fast check to verify a key & value pair will be considered as
// "small" or "large" objects.
bool isItemLarge(BufferView key, BufferView value) const override;
// synchronous fast lookup if a key probably exists in the cache,
// it can return a false positive result. this provides an optimization
// to skip the heavy lookup operation when key doesn't exist in the cache.
bool couldExist(BufferView key) override;
// insert a key and value into the cache
// @param key the item key
// @param value the item value
// @return a status indicates success or failure, and the reason for failure
Status insert(BufferView key, BufferView value) override;
// insert a key and value into the cache asynchronously.
// @param key the item key
// @param value the item value
// @param cb a callback function be triggered when the insertion complete
// @return a status indicates success or failure enqueued, and the
// reason for failure
Status insertAsync(BufferView key,
BufferView value,
InsertCallback cb) override;
// lookup a key in the cache.
// @param key the item key to lookup
// @param value the returned value for the key if found
// @return a status indicates success or failure, and the reason for
// failure
Status lookup(BufferView key, Buffer& value) override;
// lookup a key in the cache asynchronously.
// @param key the item key to lookup
// @param cb a callback function be triggered when the lookup complete,
// the result will be provided to the function.
// @return a status indicates success or failure enqueued, and the reason
// for failure
Status lookupAsync(BufferView key, LookupCallback cb) override;
// remove the key from cache
// @param key the item key to be removed
// @return a status indicates success or failure, and the reason for failure
Status remove(BufferView key) override;
// remove the key from cache asynchronously.
// @param key the item key to be removed
// @param cb a callback function be triggered when the remove complete.
// @return a status indicates success or failure enqueued, and the reason
// for failure
Status removeAsync(BufferView key, RemoveCallback cb) override;
// ensure all pending job have been completed and data has been flush to
// device(s).
void flush() override;
// Reset navy cache to the initial state.
void reset() override;
// persist the navy engines state
void persist() const override;
// recover the navy engines state
bool recover() override;
// returns the size of the device
uint64_t getSize() const override;
// returns the navy stats
void getCounters(const CounterVisitor& visitor) const override;
// This is a temporary API to update the maxWriteRate for
// DynamicRandomAdissionPolicy. The long term plan is to
// support online update to this and other cache configs.
// Returns true if update successfully
// false if AdissionPolicy is not set or not DynamicRandom.
bool updateMaxRateForDynamicRandomAP(uint64_t maxRate) override;
private:
struct ValidConfigTag {};
// Assumes that @config was validated with Config::validate
Driver(Config&& config, ValidConfigTag);
void onEviction(BufferView key, uint32_t valueSize);
// Select engine to insert key/value. Returns a pair:
// - first: engine to insert key/value
// - second: the other engine to remove key
std::pair<Engine&, Engine&> select(BufferView key, BufferView value) const;
void updateLookupStats(Status status) const;
Status removeHashedKey(HashedKey hk, bool& skipSmallItemCache);
bool admissionTest(HashedKey hk, BufferView value) const;
const uint32_t smallItemMaxSize_{};
const uint32_t maxConcurrentInserts_{};
const uint64_t maxParcelMemory_{};
const size_t metadataSize_{};
std::unique_ptr<Device> device_;
std::unique_ptr<JobScheduler> scheduler_;
// Large item cache assumed to have fast response in case entry doesn't
// exists (check metadata only).
std::unique_ptr<Engine> largeItemCache_;
// Lookup small item cache only if large item cache has no entry.
std::unique_ptr<Engine> smallItemCache_;
std::unique_ptr<AdmissionPolicy> admissionPolicy_;
// thread local counters in synchronized path
mutable TLCounter insertCount_;
mutable TLCounter lookupCount_;
mutable TLCounter removeCount_;
mutable TLCounter rejectedCount_;
mutable TLCounter rejectedConcurrentInsertsCount_;
mutable TLCounter rejectedParcelMemoryCount_;
mutable TLCounter rejectedBytes_;
mutable TLCounter acceptedCount_;
mutable TLCounter acceptedBytes_;
// atomic counters in asynchronized path
mutable AtomicCounter succInsertCount_;
mutable AtomicCounter succLookupCount_;
mutable AtomicCounter succRemoveCount_;
mutable AtomicCounter ioErrorCount_;
mutable AtomicCounter parcelMemory_; // In bytes
mutable AtomicCounter concurrentInserts_;
};
} // namespace navy
} // namespace cachelib
} // namespace facebook