New way of handling block deletions: Set last-update-client-id to zero instead of increasing version number. This has the same effect (i.e. invalidates all known block versions) and it additionally allows for checking in a local list whether a block is deleted or not.
This commit is contained in:
parent
ee1f0f4d3a
commit
fd5dd2c6e1
@ -19,6 +19,7 @@ namespace blockstore {
|
||||
namespace versioncounting {
|
||||
|
||||
const string KnownBlockVersions::HEADER = "cryfs.integritydata.knownblockversions;0";
|
||||
constexpr uint32_t KnownBlockVersions::CLIENT_ID_FOR_DELETED_BLOCK;
|
||||
|
||||
KnownBlockVersions::KnownBlockVersions(const bf::path &stateFilePath)
|
||||
:_knownVersions(), _lastUpdateClientId(), _stateFilePath(stateFilePath), _myClientId(0), _mutex(), _valid(true) {
|
||||
@ -46,6 +47,7 @@ KnownBlockVersions::~KnownBlockVersions() {
|
||||
|
||||
bool KnownBlockVersions::checkAndUpdateVersion(uint32_t clientId, const Key &key, uint64_t version) {
|
||||
unique_lock<mutex> lock(_mutex);
|
||||
ASSERT(clientId != CLIENT_ID_FOR_DELETED_BLOCK, "This is not a valid client id");
|
||||
|
||||
ASSERT(version > 0, "Version has to be >0"); // Otherwise we wouldn't handle notexisting entries correctly.
|
||||
ASSERT(_valid, "Object not valid due to a std::move");
|
||||
@ -85,7 +87,9 @@ void KnownBlockVersions::_loadStateFile() {
|
||||
optional<Data> file = Data::LoadFromFile(_stateFilePath);
|
||||
if (file == none) {
|
||||
// File doesn't exist means we loaded empty state. Assign a random client id.
|
||||
do {
|
||||
_myClientId = *reinterpret_cast<uint32_t*>(Random::PseudoRandom().getFixedSize<sizeof(uint32_t)>().data());
|
||||
} while(_myClientId == CLIENT_ID_FOR_DELETED_BLOCK); // Safety check - CLIENT_ID_FOR_DELETED_BLOCK shouldn't be used by any valid client.
|
||||
return;
|
||||
}
|
||||
|
||||
@ -183,8 +187,13 @@ uint32_t KnownBlockVersions::myClientId() const {
|
||||
}
|
||||
|
||||
uint64_t KnownBlockVersions::getBlockVersion(uint32_t clientId, const Key &key) const {
|
||||
unique_lock<mutex> lock(_mutex);
|
||||
return _knownVersions.at({clientId, key});
|
||||
}
|
||||
|
||||
void KnownBlockVersions::markBlockAsDeleted(const Key &key) {
|
||||
_lastUpdateClientId[key] = CLIENT_ID_FOR_DELETED_BLOCK;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,8 @@ namespace blockstore {
|
||||
|
||||
uint64_t incrementVersion(const Key &key, uint64_t lastVersion);
|
||||
|
||||
void markBlockAsDeleted(const Key &key);
|
||||
|
||||
uint64_t getBlockVersion(uint32_t clientId, const Key &key) const;
|
||||
|
||||
uint32_t myClientId() const;
|
||||
@ -38,6 +40,8 @@ namespace blockstore {
|
||||
mutable std::mutex _mutex;
|
||||
bool _valid;
|
||||
|
||||
static constexpr uint32_t CLIENT_ID_FOR_DELETED_BLOCK = 0;
|
||||
|
||||
static const std::string HEADER;
|
||||
|
||||
void _loadStateFile();
|
||||
|
@ -41,7 +41,6 @@ public:
|
||||
size_t size() const override;
|
||||
void resize(size_t newSize) override;
|
||||
|
||||
uint64_t version() const;
|
||||
cpputils::unique_ref<Block> releaseBlock();
|
||||
|
||||
#ifndef CRYFS_NO_COMPATIBILITY
|
||||
@ -208,10 +207,6 @@ inline uint64_t VersionCountingBlock::blockSizeFromPhysicalBlockSize(uint64_t bl
|
||||
return blockSize - HEADER_LENGTH;
|
||||
}
|
||||
|
||||
inline uint64_t VersionCountingBlock::version() const {
|
||||
return _version;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,7 @@ inline void VersionCountingBlockStore::remove(cpputils::unique_ref<Block> block)
|
||||
Key key = block->key();
|
||||
auto versionCountingBlock = cpputils::dynamic_pointer_move<VersionCountingBlock>(block);
|
||||
ASSERT(versionCountingBlock != boost::none, "Block is not an VersionCountingBlock");
|
||||
_knownBlockVersions.incrementVersion(key, (*versionCountingBlock)->version());
|
||||
_knownBlockVersions.markBlockAsDeleted(key);
|
||||
auto baseBlock = (*versionCountingBlock)->releaseBlock();
|
||||
_baseBlockStore->remove(std::move(baseBlock));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user