sapling/cstore/uniondatapackstore.cpp

143 lines
3.9 KiB
C++
Raw Normal View History

// Copyright (c) 2004-present, Facebook, Inc.
// All Rights Reserved.
//
// This software may be used and distributed according to the terms of the
// GNU General Public License version 2 or any later version.
// uniondatapackstore.cpp - implementation of a union datapack store
// no-check-code
#include "cstore/uniondatapackstore.h"
#include <algorithm>
#include <memory>
extern "C" {
#include "cstore/mpatch.h"
}
UnionDatapackStore::UnionDatapackStore(std::vector<DataStore*> stores) :
_stores(stores) {
}
UnionDatapackStore::~UnionDatapackStore() {
// TODO: we should manage the substore lifetimes here, but because they are
// also controlled by Python, we need to let python handle it and manage the
// refcount in the py_uniondatapackstore type.
}
mpatch_flist* getNextLink(void* container, ssize_t index) {
std::vector<DeltaChainLink> *links = (std::vector<DeltaChainLink>*)container;
if (index < 0 || (size_t)index >= links->size()) {
return NULL;
}
DeltaChainLink link = links->at(index);
struct mpatch_flist *res;
if ((mpatch_decode((const char*)link.delta(),
(ssize_t)link.deltasz(), &res)) < 0) {
throw std::logic_error("invalid patch during patch application");
}
return res;
}
ConstantStringRef UnionDatapackStore::get(const Key &key) {
UnionDeltaChainIterator chain = this->getDeltaChain(key);
std::vector<DeltaChainLink> links;
for (DeltaChainLink link = chain.next(); !link.isdone(); link = chain.next()) {
links.push_back(link);
}
DeltaChainLink fulltextLink = links.back();
links.pop_back();
// Short circuit and just return the full text if it's one long
if (links.size() == 0) {
return ConstantStringRef((const char*)fulltextLink.delta(),
(size_t)fulltextLink.deltasz());
}
std::reverse(links.begin(), links.end());
mpatch_flist *patch = mpatch_fold(&links, getNextLink, 0, links.size());
if (!patch) { /* error already set or memory error */
throw std::logic_error("mpatch failed to fold patches");
}
ssize_t outlen = mpatch_calcsize((ssize_t)fulltextLink.deltasz(), patch);
if (outlen < 0) {
mpatch_lfree(patch);
throw std::logic_error("mpatch failed to calculate size");
}
treemanifest: ConstantStringRef -> shared_ptr<string> Summary: this simplifies the code and resolves a `new[]/delete` allocator/deallocator mismatch that I tripped over in D4929693 I think this is pretty straight forward. The diff is made a little larger than I would have liked because there were some missing `const` qualifiers that had to be propagated out to various callers. Test Plan: ran the tests: ``` 11:23 $ rt .................................s.........s.s.s......s..sss............s.....s................................................................................................................... Skipped test-p4fastimport-import-incremental.t: missing feature: Perforce server and client Skipped test-p4fastimport-criss-cross.t: missing feature: Perforce server and client Skipped test-p4fastimport-case-insensitive-rename.t: missing feature: Perforce server and client Skipped test-p4fastimport-import-modes.t: missing feature: Perforce server and client Skipped test-p4fastimport-import.t: missing feature: Perforce server and client Skipped test-p4fastimport-import-deletes.t: missing feature: Perforce server and client Skipped test-p4fastimport-case-insensitivity.t: missing feature: Perforce server and client Skipped test-p4fastimport-import-parallel.t: missing feature: Perforce server and client Skipped test-infinitepush-backup-sql.t: missing getdb.sh Skipped test-infinitepush-sql.t: missing getdb.sh # Ran 184 tests, 10 skipped, 0 warned, 0 failed. ``` Reviewers: simpkins, durham Reviewed By: durham Subscribers: net-systems-diffs@fb.com, mjpieters, #mercurial Differential Revision: https://phabricator.intern.facebook.com/D4930821 Signature: t1:4930821:1493160075:5ee1d452b394c4d6f347029b0ff3fd89377624c5
2017-04-26 01:44:55 +03:00
auto result = std::make_shared<std::string>(outlen, '\0');
if (mpatch_apply(&(*result)[0], (const char*)fulltextLink.delta(),
(ssize_t)fulltextLink.deltasz(), patch) < 0) {
mpatch_lfree(patch);
throw std::logic_error("mpatch failed to apply patches");
}
mpatch_lfree(patch);
treemanifest: ConstantStringRef -> shared_ptr<string> Summary: this simplifies the code and resolves a `new[]/delete` allocator/deallocator mismatch that I tripped over in D4929693 I think this is pretty straight forward. The diff is made a little larger than I would have liked because there were some missing `const` qualifiers that had to be propagated out to various callers. Test Plan: ran the tests: ``` 11:23 $ rt .................................s.........s.s.s......s..sss............s.....s................................................................................................................... Skipped test-p4fastimport-import-incremental.t: missing feature: Perforce server and client Skipped test-p4fastimport-criss-cross.t: missing feature: Perforce server and client Skipped test-p4fastimport-case-insensitive-rename.t: missing feature: Perforce server and client Skipped test-p4fastimport-import-modes.t: missing feature: Perforce server and client Skipped test-p4fastimport-import.t: missing feature: Perforce server and client Skipped test-p4fastimport-import-deletes.t: missing feature: Perforce server and client Skipped test-p4fastimport-case-insensitivity.t: missing feature: Perforce server and client Skipped test-p4fastimport-import-parallel.t: missing feature: Perforce server and client Skipped test-infinitepush-backup-sql.t: missing getdb.sh Skipped test-infinitepush-sql.t: missing getdb.sh # Ran 184 tests, 10 skipped, 0 warned, 0 failed. ``` Reviewers: simpkins, durham Reviewed By: durham Subscribers: net-systems-diffs@fb.com, mjpieters, #mercurial Differential Revision: https://phabricator.intern.facebook.com/D4930821 Signature: t1:4930821:1493160075:5ee1d452b394c4d6f347029b0ff3fd89377624c5
2017-04-26 01:44:55 +03:00
return ConstantStringRef(result);
}
std::shared_ptr<DeltaChain> UnionDeltaChainIterator::getNextChain(const Key &key) {
for(std::vector<DataStore*>::iterator it = _store._stores.begin();
it != _store._stores.end();
it++) {
DataStore *substore = *it;
std::shared_ptr<DeltaChain> chain = substore->getDeltaChainRaw(key);
if (chain->status() == GET_DELTA_CHAIN_OK) {
return chain;
}
}
throw MissingKeyError("unable to find delta chain");
}
UnionDeltaChainIterator UnionDatapackStore::getDeltaChain(const Key &key) {
return UnionDeltaChainIterator(*this, key);
}
Key* UnionDatapackStoreKeyIterator::next() {
Key* key;
while ((key = _missing.next()) != NULL) {
if (!_store.contains(*key)) {
return key;
}
}
return NULL;
}
bool UnionDatapackStore::contains(const Key &key) {
for(std::vector<DataStore*>::iterator it = _stores.begin();
it != _stores.end();
it++) {
DataStore *substore = *it;
if (substore->contains(key)) {
return true;
}
}
return false;
}
UnionDatapackStoreKeyIterator UnionDatapackStore::getMissing(KeyIterator &missing) {
return UnionDatapackStoreKeyIterator(*this, missing);
}
void UnionDatapackStore::markForRefresh() {
for(std::vector<DataStore*>::iterator it = _stores.begin();
it != _stores.end();
it++) {
DataStore *substore = *it;
substore->markForRefresh();
}
}