#include <util/Tokenizer.hpp>
#include <util/XXH3_64.hpp>
#include <util/expected.hpp>
+#include <util/file.hpp>
#include <util/string.hpp>
#include <third_party/url.hpp>
m_secondary_storages.end(),
[](const auto& entry) { return !entry->config.read_only; });
if (should_put_in_secondary_storage) {
- std::string value;
- try {
- value = Util::read_file(*path);
- } catch (const core::Error& e) {
- LOG("Failed to read {}: {}", *path, e.what());
+ const auto value = util::read_file<util::Blob>(*path);
+ if (!value) {
+ LOG("Failed to read {}: {}", *path, value.error());
return path; // Don't indicate failure since primary storage was OK.
}
- put_in_secondary_storage(key, value, true);
+ put_in_secondary_storage(key, *value, true);
}
}
TemporaryFile tmp_file(FMT("{}/tmp.get", m_config.temporary_dir()));
m_tmp_files.push_back(tmp_file.path);
try {
- Util::write_file(tmp_file.path, value);
+ util::write_file(tmp_file.path, value);
} catch (const core::Error& e) {
throw core::Fatal("Error writing to {}: {}", tmp_file.path, e.what());
}
m_secondary_storages.end(),
[](const auto& entry) { return !entry->config.read_only; });
if (should_put_in_secondary_storage) {
- std::string value;
- try {
- value = Util::read_file(*path);
- } catch (const core::Error& e) {
- LOG("Failed to read {}: {}", *path, e.what());
+ const auto value = util::read_file<util::Blob>(*path);
+ if (!value) {
+ LOG("Failed to read {}: {}", *path, value.error());
return true; // Don't indicate failure since primary storage was OK.
}
- put_in_secondary_storage(key, value, false);
+ put_in_secondary_storage(key, *value, false);
}
return true;
}
}
-std::optional<std::pair<std::string, bool>>
+std::optional<std::pair<util::Blob, bool>>
Storage::get_from_secondary_storage(const Digest& key)
{
MTR_SCOPE("secondary_storage", "get");
void
Storage::put_in_secondary_storage(const Digest& key,
- const std::string& value,
+ const util::Blob& value,
bool only_if_missing)
{
MTR_SCOPE("secondary_storage", "put");
#include <storage/primary/PrimaryStorage.hpp>
#include <storage/secondary/SecondaryStorage.hpp>
#include <storage/types.hpp>
+#include <util/types.hpp>
#include <functional>
#include <memory>
const Digest& key,
std::string_view operation_description,
const bool for_writing);
- std::optional<std::pair<std::string, bool>>
+ std::optional<std::pair<util::Blob, bool>>
get_from_secondary_storage(const Digest& key);
void put_in_secondary_storage(const Digest& key,
- const std::string& value,
+ const util::Blob& value,
bool only_if_missing);
void remove_from_secondary_storage(const Digest& key);
public:
FileStorageBackend(const Params& params);
- nonstd::expected<std::optional<std::string>, Failure>
+ nonstd::expected<std::optional<util::Blob>, Failure>
get(const Digest& key) override;
nonstd::expected<bool, Failure> put(const Digest& key,
- const std::string& value,
+ const util::Blob& value,
bool only_if_missing) override;
nonstd::expected<bool, Failure> remove(const Digest& key) override;
}
}
-nonstd::expected<std::optional<std::string>, SecondaryStorage::Backend::Failure>
+nonstd::expected<std::optional<util::Blob>, SecondaryStorage::Backend::Failure>
FileStorageBackend::get(const Digest& key)
{
const auto path = get_entry_path(key);
util::set_timestamps(path);
}
- try {
- LOG("Reading {}", path);
- return Util::read_file(path);
- } catch (const core::Error& e) {
- LOG("Failed to read {}: {}", path, e.what());
+ auto value = util::read_file<util::Blob>(path);
+ if (!value) {
+ LOG("Failed to read {}: {}", path, value.error());
return nonstd::make_unexpected(Failure::error);
}
+ return std::move(*value);
}
nonstd::expected<bool, SecondaryStorage::Backend::Failure>
FileStorageBackend::put(const Digest& key,
- const std::string& value,
+ const util::Blob& value,
const bool only_if_missing)
{
const auto path = get_entry_path(key);
#include <fmtmacros.hpp>
#include <util/expected.hpp>
#include <util/string.hpp>
+#include <util/types.hpp>
#include <third_party/httplib.h>
#include <third_party/url.hpp>
public:
HttpStorageBackend(const Params& params);
- nonstd::expected<std::optional<std::string>, Failure>
+ nonstd::expected<std::optional<util::Blob>, Failure>
get(const Digest& key) override;
nonstd::expected<bool, Failure> put(const Digest& key,
- const std::string& value,
+ const util::Blob& value,
bool only_if_missing) override;
nonstd::expected<bool, Failure> remove(const Digest& key) override;
m_http_client.set_write_timeout(operation_timeout);
}
-nonstd::expected<std::optional<std::string>, SecondaryStorage::Backend::Failure>
+nonstd::expected<std::optional<util::Blob>, SecondaryStorage::Backend::Failure>
HttpStorageBackend::get(const Digest& key)
{
const auto url_path = get_entry_path(key);
return std::nullopt;
}
- return result->body;
+ return util::Blob(result->body.begin(), result->body.end());
}
nonstd::expected<bool, SecondaryStorage::Backend::Failure>
HttpStorageBackend::put(const Digest& key,
- const std::string& value,
+ const util::Blob& value,
const bool only_if_missing)
{
const auto url_path = get_entry_path(key);
static const auto content_type = "application/octet-stream";
const auto result =
- m_http_client.Put(url_path, value.data(), value.size(), content_type);
+ m_http_client.Put(url_path,
+ reinterpret_cast<const char*>(value.data()),
+ value.size(),
+ content_type);
if (result.error() != httplib::Error::Success || !result) {
LOG("Failed to put {} to http storage: {} ({})",
public:
RedisStorageBackend(const SecondaryStorage::Backend::Params& params);
- nonstd::expected<std::optional<std::string>, Failure>
+ nonstd::expected<std::optional<util::Blob>, Failure>
get(const Digest& key) override;
nonstd::expected<bool, Failure> put(const Digest& key,
- const std::string& value,
+ const util::Blob& value,
bool only_if_missing) override;
nonstd::expected<bool, Failure> remove(const Digest& key) override;
#endif
}
-nonstd::expected<std::optional<std::string>, SecondaryStorage::Backend::Failure>
+nonstd::expected<std::optional<util::Blob>, SecondaryStorage::Backend::Failure>
RedisStorageBackend::get(const Digest& key)
{
const auto key_string = get_key_string(key);
if (!reply) {
return nonstd::make_unexpected(reply.error());
} else if ((*reply)->type == REDIS_REPLY_STRING) {
- return std::string((*reply)->str, (*reply)->len);
+ return util::Blob((*reply)->str, (*reply)->str + (*reply)->len);
} else if ((*reply)->type == REDIS_REPLY_NIL) {
return std::nullopt;
} else {
nonstd::expected<bool, SecondaryStorage::Backend::Failure>
RedisStorageBackend::put(const Digest& key,
- const std::string& value,
+ const util::Blob& value,
bool only_if_missing)
{
const auto key_string = get_key_string(key);
#pragma once
#include <storage/types.hpp>
+#include <util/types.hpp>
#include <third_party/nonstd/expected.hpp>
#include <third_party/url.hpp>
// Get the value associated with `key`. Returns the value on success or
// std::nullopt if the entry is not present.
- virtual nonstd::expected<std::optional<std::string>, Failure>
+ virtual nonstd::expected<std::optional<util::Blob>, Failure>
get(const Digest& key) = 0;
// Put `value` associated to `key` in the storage. A true `only_if_missing`
// Returns true if the entry was stored, otherwise false.
virtual nonstd::expected<bool, Failure>
put(const Digest& key,
- const std::string& value,
+ const util::Blob& value,
bool only_if_missing = false) = 0;
// Remove `key` and its associated value. Returns true if the entry was