diff --git a/src/keva/common.cpp b/src/keva/common.cpp index 636e3e6e5..576808eda 100644 --- a/src/keva/common.cpp +++ b/src/keva/common.cpp @@ -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 { - /* A special case is when both iterators are equal. In this case, + } 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; diff --git a/src/keva/common.h b/src/keva/common.h index e3d669c09..9c5065f58 100644 --- a/src/keva/common.h +++ b/src/keva/common.h @@ -309,12 +309,20 @@ private: inline bool operator() (const std::tuple a, const std::tuple 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 aKeySize < bKeySize; } - return a < b; + return nsA < nsB; } }; diff --git a/src/txdb.cpp b/src/txdb.cpp index 61f7c6a4f..4fbf89548 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -157,36 +157,7 @@ bool CCoinsViewDB::GetName(const valtype &nameSpace, const valtype &key, CKevaDa } bool CCoinsViewDB::GetNamesForHeight(unsigned nHeight, std::set& 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 pcursor(const_cast(&db)->NewIterator()); - - const CKevaCache::ExpireEntry seekEntry(nHeight, valtype ()); - pcursor->Seek(std::make_pair(DB_NAME_EXPIRY, seekEntry)); - - for (; pcursor->Valid(); pcursor->Next()) - { - std::pair 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) {