Browse Source

Fixed key comparator for kevacache.

cn
Jianping Wu 6 years ago
parent
commit
53d29e5690
  1. 27
      src/keva/common.cpp
  2. 18
      src/keva/common.h
  3. 31
      src/txdb.cpp

27
src/keva/common.cpp

@ -127,27 +127,38 @@ bool CCacheKeyIterator::next(valtype& key, CKevaData& data) @@ -127,27 +127,38 @@ bool CCacheKeyIterator::next(valtype& key, CKevaData& data)
{
/* Exit early if no more data is available in either the cache
nor the base iterator. */
if (!baseHasMore && cacheIter == cache.entries.end())
bool endOfCacheNamespace = false;
if (cacheIter != cache.entries.end()) {
valtype curNameSpace = std::get<0>(cacheIter->first);
if (curNameSpace != nameSpace) {
endOfCacheNamespace = true;
}
}
bool noMoreCache = (cacheIter == cache.entries.end()) || endOfCacheNamespace;
if (!baseHasMore && noMoreCache) {
return false;
}
/* Determine which source to use for the next. */
bool useBase;
if (!baseHasMore)
bool useBase = false;
if (!baseHasMore) {
useBase = false;
else if (cacheIter == cache.entries.end())
} else if (cacheIter == cache.entries.end()) {
useBase = true;
else {
} else {
if (baseKey == std::get<1>(cacheIter->first)) {
/* A special case is when both iterators are equal. In this case,
we want to use the cached version. We also have to advance
the base iterator. */
if (baseKey == std::get<1>(cacheIter->first))
advanceBaseIterator ();
}
/* Due to advancing the base iterator above, it may happen that
no more base entries are present. Handle this gracefully. */
if (!baseHasMore)
if (!baseHasMore) {
useBase = false;
else {
} else {
assert(baseKey != std::get<1>(cacheIter->first));
CKevaCache::KeyComparator cmp;

18
src/keva/common.h

@ -309,12 +309,20 @@ private: @@ -309,12 +309,20 @@ private:
inline bool operator() (const std::tuple<valtype, valtype> a,
const std::tuple<valtype, valtype> b) const
{
unsigned int aSize = std::get<0>(a).size() + std::get<1>(a).size();
unsigned int bSize = std::get<0>(b).size() + std::get<1>(b).size();
if (aSize != bSize) {
return aSize < bSize;
// This is how namespace/key pairs are sorted in database.
auto nsA = std::get<0>(a);
auto nsB = std::get<0>(b);
if (nsA == nsB) {
auto aKey = std::get<1>(a);
auto bKey = std::get<1>(b);
uint32_t aKeySize = aKey.size();
uint32_t bKeySize = bKey.size();
if (aKeySize == bKeySize) {
return aKey < bKey;
}
return a < b;
return aKeySize < bKeySize;
}
return nsA < nsB;
}
};

31
src/txdb.cpp

@ -157,36 +157,7 @@ bool CCoinsViewDB::GetName(const valtype &nameSpace, const valtype &key, CKevaDa @@ -157,36 +157,7 @@ bool CCoinsViewDB::GetName(const valtype &nameSpace, const valtype &key, CKevaDa
}
bool CCoinsViewDB::GetNamesForHeight(unsigned nHeight, std::set<valtype>& names) const {
names.clear();
#if 0
/* It seems that there are no "const iterators" for LevelDB. Since we
only need read operations on it, use a const-cast to get around
that restriction. */
boost::scoped_ptr<CDBIterator> pcursor(const_cast<CDBWrapper*>(&db)->NewIterator());
const CKevaCache::ExpireEntry seekEntry(nHeight, valtype ());
pcursor->Seek(std::make_pair(DB_NAME_EXPIRY, seekEntry));
for (; pcursor->Valid(); pcursor->Next())
{
std::pair<char, CKevaCache::ExpireEntry> key;
if (!pcursor->GetKey(key) || key.first != DB_NAME_EXPIRY)
break;
const CKevaCache::ExpireEntry& entry = key.second;
assert (entry.nHeight >= nHeight);
if (entry.nHeight > nHeight)
break;
const valtype& name = entry.name;
if (names.count(name) > 0) {
return error("%s : duplicate name '%s' in expire index",
__func__, ValtypeToString(name).c_str());
}
names.insert(name);
}
#endif
return true;
return false;
}
bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, const CKevaCache &names) {

Loading…
Cancel
Save