mirror of
https://github.com/kvazar-network/kevacoin.git
synced 2025-01-13 16:48:08 +00:00
Started implementing namespace association.
This commit is contained in:
parent
5e412845ec
commit
76c50bc850
@ -14,6 +14,7 @@ bool CCoinsView::GetNamespace(const valtype &nameSpace, CKevaData &data) const {
|
|||||||
bool CCoinsView::GetName(const valtype &nameSpace, const valtype &key, CKevaData &data) const { return false; }
|
bool CCoinsView::GetName(const valtype &nameSpace, const valtype &key, CKevaData &data) const { return false; }
|
||||||
bool CCoinsView::GetNamesForHeight(unsigned nHeight, std::set<valtype>& names) const { return false; }
|
bool CCoinsView::GetNamesForHeight(unsigned nHeight, std::set<valtype>& names) const { return false; }
|
||||||
CKevaIterator* CCoinsView::IterateKeys(const valtype& nameSpace) const { assert (false); }
|
CKevaIterator* CCoinsView::IterateKeys(const valtype& nameSpace) const { assert (false); }
|
||||||
|
CKevaIterator* CCoinsView::IterateAssociatedNamespaces(const valtype& nameSpace) const { assert (false); }
|
||||||
bool CCoinsView::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, const CKevaCache &names) { return false; }
|
bool CCoinsView::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, const CKevaCache &names) { return false; }
|
||||||
CCoinsViewCursor *CCoinsView::Cursor() const { return nullptr; }
|
CCoinsViewCursor *CCoinsView::Cursor() const { return nullptr; }
|
||||||
bool CCoinsView::ValidateKevaDB() const {
|
bool CCoinsView::ValidateKevaDB() const {
|
||||||
@ -43,6 +44,7 @@ bool CCoinsViewBacked::GetNamesForHeight(unsigned nHeight, std::set<valtype>& na
|
|||||||
return base->GetNamesForHeight(nHeight, names);
|
return base->GetNamesForHeight(nHeight, names);
|
||||||
}
|
}
|
||||||
CKevaIterator* CCoinsViewBacked::IterateKeys(const valtype& nameSpace) const { return base->IterateKeys(nameSpace); }
|
CKevaIterator* CCoinsViewBacked::IterateKeys(const valtype& nameSpace) const { return base->IterateKeys(nameSpace); }
|
||||||
|
CKevaIterator* CCoinsViewBacked::IterateAssociatedNamespaces(const valtype& nameSpace) const { return base->IterateAssociatedNamespaces(nameSpace); }
|
||||||
void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; }
|
void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; }
|
||||||
bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, const CKevaCache &names) {
|
bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, const CKevaCache &names) {
|
||||||
return base->BatchWrite(mapCoins, hashBlock, names);
|
return base->BatchWrite(mapCoins, hashBlock, names);
|
||||||
@ -198,6 +200,10 @@ CKevaIterator* CCoinsViewCache::IterateKeys(const valtype& nameSpace) const {
|
|||||||
return cacheNames.iterateKeys(base->IterateKeys(nameSpace));
|
return cacheNames.iterateKeys(base->IterateKeys(nameSpace));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CKevaIterator* CCoinsViewCache::IterateAssociatedNamespaces(const valtype& nameSpace) const {
|
||||||
|
return cacheNames.IterateAssociatedNamespaces(base->IterateAssociatedNamespaces(nameSpace));
|
||||||
|
}
|
||||||
|
|
||||||
/* undo is set if the change is due to disconnecting blocks / going back in
|
/* undo is set if the change is due to disconnecting blocks / going back in
|
||||||
time. The ordinary case (!undo) means that we update the name normally,
|
time. The ordinary case (!undo) means that we update the name normally,
|
||||||
going forward in time. This is important for keeping track of the
|
going forward in time. This is important for keeping track of the
|
||||||
@ -210,6 +216,18 @@ void CCoinsViewCache::SetName(const valtype &nameSpace, const valtype &key, cons
|
|||||||
cacheNames.setNamespace(nameSpace, namespaceData);
|
cacheNames.setNamespace(nameSpace, namespaceData);
|
||||||
}
|
}
|
||||||
cacheNames.set(nameSpace, key, data);
|
cacheNames.set(nameSpace, key, data);
|
||||||
|
|
||||||
|
// Handle namespace association.
|
||||||
|
valtype associdateNamespace;
|
||||||
|
if (!cacheNames.getAssociateNamespaces(data.getValue(), associdateNamespace)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CKevaData dummyData;
|
||||||
|
if (!GetNamespace(associdateNamespace, dummyData)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cacheNames.associateNamespaces(nameSpace, associdateNamespace);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCoinsViewCache::DeleteName(const valtype &nameSpace, const valtype &key) {
|
void CCoinsViewCache::DeleteName(const valtype &nameSpace, const valtype &key) {
|
||||||
@ -218,6 +236,18 @@ void CCoinsViewCache::DeleteName(const valtype &nameSpace, const valtype &key) {
|
|||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
cacheNames.remove(nameSpace, key);
|
cacheNames.remove(nameSpace, key);
|
||||||
|
|
||||||
|
// Handle namespace association.
|
||||||
|
valtype associdateNamespace;
|
||||||
|
if (!cacheNames.getAssociateNamespaces(oldData.getValue(), associdateNamespace)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CKevaData dummyData;
|
||||||
|
if (!GetNamespace(associdateNamespace, dummyData)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cacheNames.disassociateNamespaces(nameSpace, associdateNamespace);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn, const CKevaCache &names) {
|
bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn, const CKevaCache &names) {
|
||||||
|
@ -176,6 +176,9 @@ public:
|
|||||||
// Get a key iterator.
|
// Get a key iterator.
|
||||||
virtual CKevaIterator* IterateKeys(const valtype& nameSpace) const;
|
virtual CKevaIterator* IterateKeys(const valtype& nameSpace) const;
|
||||||
|
|
||||||
|
// Get the associated namespace iterator.
|
||||||
|
virtual CKevaIterator* IterateAssociatedNamespaces(const valtype& nameSpace) const;
|
||||||
|
|
||||||
//! Do a bulk modification (multiple Coin changes + BestBlock change).
|
//! Do a bulk modification (multiple Coin changes + BestBlock change).
|
||||||
//! The passed mapCoins can be modified.
|
//! The passed mapCoins can be modified.
|
||||||
virtual bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, const CKevaCache &names);
|
virtual bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, const CKevaCache &names);
|
||||||
@ -210,6 +213,7 @@ public:
|
|||||||
bool GetName(const valtype& nameSpace, const valtype& key, CKevaData& data) const override;
|
bool GetName(const valtype& nameSpace, const valtype& key, CKevaData& data) const override;
|
||||||
bool GetNamesForHeight(unsigned nHeight, std::set<valtype>& names) const override;
|
bool GetNamesForHeight(unsigned nHeight, std::set<valtype>& names) const override;
|
||||||
CKevaIterator* IterateKeys(const valtype& nameSpace) const override;
|
CKevaIterator* IterateKeys(const valtype& nameSpace) const override;
|
||||||
|
virtual CKevaIterator* IterateAssociatedNamespaces(const valtype& nameSpace) const override;
|
||||||
void SetBackend(CCoinsView &viewIn);
|
void SetBackend(CCoinsView &viewIn);
|
||||||
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, const CKevaCache &names) override;
|
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, const CKevaCache &names) override;
|
||||||
CCoinsViewCursor *Cursor() const override;
|
CCoinsViewCursor *Cursor() const override;
|
||||||
@ -252,6 +256,7 @@ public:
|
|||||||
bool GetName(const valtype &nameSpace, const valtype &key, CKevaData& data) const override;
|
bool GetName(const valtype &nameSpace, const valtype &key, CKevaData& data) const override;
|
||||||
bool GetNamesForHeight(unsigned nHeight, std::set<valtype>& names) const override;
|
bool GetNamesForHeight(unsigned nHeight, std::set<valtype>& names) const override;
|
||||||
CKevaIterator* IterateKeys(const valtype& nameSpace) const override;
|
CKevaIterator* IterateKeys(const valtype& nameSpace) const override;
|
||||||
|
CKevaIterator* IterateAssociatedNamespaces(const valtype& nameSpace) const override;
|
||||||
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, const CKevaCache &names) override;
|
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, const CKevaCache &names) override;
|
||||||
CCoinsViewCursor* Cursor() const override {
|
CCoinsViewCursor* Cursor() const override {
|
||||||
throw std::logic_error("CCoinsViewCache cursor iteration not supported.");
|
throw std::logic_error("CCoinsViewCache cursor iteration not supported.");
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
#include <keva/common.h>
|
#include <keva/common.h>
|
||||||
|
#include <base58.h>
|
||||||
#include <script/keva.h>
|
#include <script/keva.h>
|
||||||
|
|
||||||
|
|
||||||
@ -55,6 +55,9 @@ private:
|
|||||||
/** Base iterator to combine with the cache. */
|
/** Base iterator to combine with the cache. */
|
||||||
CKevaIterator* base;
|
CKevaIterator* base;
|
||||||
|
|
||||||
|
/** Whether or not it is for namespace association. */
|
||||||
|
bool isAssociation;
|
||||||
|
|
||||||
/** Whether or not the base iterator has more entries. */
|
/** Whether or not the base iterator has more entries. */
|
||||||
bool baseHasMore;
|
bool baseHasMore;
|
||||||
|
|
||||||
@ -79,7 +82,7 @@ public:
|
|||||||
* @param c The cache object to use.
|
* @param c The cache object to use.
|
||||||
* @param b The base iterator.
|
* @param b The base iterator.
|
||||||
*/
|
*/
|
||||||
CCacheKeyIterator(const CKevaCache& c, CKevaIterator* b);
|
CCacheKeyIterator(const CKevaCache& c, CKevaIterator* b, bool association=false);
|
||||||
|
|
||||||
/* Destruct, this deletes also the base iterator. */
|
/* Destruct, this deletes also the base iterator. */
|
||||||
~CCacheKeyIterator();
|
~CCacheKeyIterator();
|
||||||
@ -90,8 +93,8 @@ public:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
CCacheKeyIterator::CCacheKeyIterator(const CKevaCache& c, CKevaIterator* b)
|
CCacheKeyIterator::CCacheKeyIterator(const CKevaCache& c, CKevaIterator* b, bool association)
|
||||||
: CKevaIterator(b->getNamespace()), cache(c), base(b)
|
: CKevaIterator(b->getNamespace()), cache(c), base(b), isAssociation(association)
|
||||||
{
|
{
|
||||||
/* Add a seek-to-start to ensure that everything is consistent. This call
|
/* Add a seek-to-start to ensure that everything is consistent. This call
|
||||||
may be superfluous if we seek to another position afterwards anyway,
|
may be superfluous if we seek to another position afterwards anyway,
|
||||||
@ -116,7 +119,8 @@ CCacheKeyIterator::advanceBaseIterator()
|
|||||||
void
|
void
|
||||||
CCacheKeyIterator::seek(const valtype& start)
|
CCacheKeyIterator::seek(const valtype& start)
|
||||||
{
|
{
|
||||||
cacheIter = cache.entries.lower_bound(std::make_tuple(nameSpace, start));
|
auto &entries = isAssociation ? cache.associations : cache.entries;
|
||||||
|
cacheIter = entries.lower_bound(std::make_tuple(nameSpace, start));
|
||||||
base->seek(start);
|
base->seek(start);
|
||||||
|
|
||||||
baseHasMore = true;
|
baseHasMore = true;
|
||||||
@ -127,15 +131,15 @@ bool CCacheKeyIterator::next(valtype& key, CKevaData& data)
|
|||||||
{
|
{
|
||||||
/* Exit early if no more data is available in either the cache
|
/* Exit early if no more data is available in either the cache
|
||||||
nor the base iterator. */
|
nor the base iterator. */
|
||||||
|
auto &entries = isAssociation ? cache.associations : cache.entries;
|
||||||
bool endOfCacheNamespace = false;
|
bool endOfCacheNamespace = false;
|
||||||
if (cacheIter != cache.entries.end()) {
|
if (cacheIter != entries.end()) {
|
||||||
valtype curNameSpace = std::get<0>(cacheIter->first);
|
valtype curNameSpace = std::get<0>(cacheIter->first);
|
||||||
if (curNameSpace != nameSpace) {
|
if (curNameSpace != nameSpace) {
|
||||||
endOfCacheNamespace = true;
|
endOfCacheNamespace = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool noMoreCache = (cacheIter == cache.entries.end()) || endOfCacheNamespace;
|
bool noMoreCache = (cacheIter == entries.end()) || endOfCacheNamespace;
|
||||||
if (!baseHasMore && noMoreCache) {
|
if (!baseHasMore && noMoreCache) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -144,7 +148,7 @@ bool CCacheKeyIterator::next(valtype& key, CKevaData& data)
|
|||||||
bool useBase = false;
|
bool useBase = false;
|
||||||
if (!baseHasMore) {
|
if (!baseHasMore) {
|
||||||
useBase = false;
|
useBase = false;
|
||||||
} else if (cacheIter == cache.entries.end()) {
|
} else if (cacheIter == entries.end()) {
|
||||||
useBase = true;
|
useBase = true;
|
||||||
} else {
|
} else {
|
||||||
if (baseKey == std::get<1>(cacheIter->first)) {
|
if (baseKey == std::get<1>(cacheIter->first)) {
|
||||||
@ -182,6 +186,8 @@ bool CCacheKeyIterator::next(valtype& key, CKevaData& data)
|
|||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
/* CKevaCache. */
|
/* CKevaCache. */
|
||||||
|
|
||||||
|
const std::string CKevaCache::associatePrefix = "_A_";
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CKevaCache::get(const valtype& nameSpace, const valtype& key, CKevaData& data) const
|
CKevaCache::get(const valtype& nameSpace, const valtype& key, CKevaData& data) const
|
||||||
{
|
{
|
||||||
@ -233,12 +239,55 @@ CKevaCache::remove(const valtype& nameSpace, const valtype& key)
|
|||||||
deleted.insert(name);
|
deleted.insert(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If the value is an associated namespace (_A_N...), return the namespace */
|
||||||
|
bool
|
||||||
|
CKevaCache::getAssociateNamespaces(const valtype& value, valtype& nameSpace)
|
||||||
|
{
|
||||||
|
std::string valueStr = ValtypeToString(value);
|
||||||
|
if (valueStr.rfind(associatePrefix, 0) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
valueStr.erase(0, associatePrefix.length());
|
||||||
|
if (!DecodeKevaNamespace(valueStr, Params(), nameSpace)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CKevaCache::associateNamespaces(const valtype& nameSpace, const valtype& nameSpaceOther)
|
||||||
|
{
|
||||||
|
auto name = std::make_tuple(nameSpaceOther, nameSpace);
|
||||||
|
const NamespaceMap::iterator ei = associations.find(name);
|
||||||
|
CKevaData data;
|
||||||
|
if (ei != entries.end())
|
||||||
|
ei->second = data;
|
||||||
|
else
|
||||||
|
associations.insert(std::make_pair(name, data));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CKevaCache::disassociateNamespaces(const valtype& nameSpace, const valtype& nameSpaceOther)
|
||||||
|
{
|
||||||
|
auto name = std::make_tuple(nameSpaceOther, nameSpace);
|
||||||
|
const NamespaceMap::iterator ei = entries.find(name);
|
||||||
|
if (ei != entries.end()) {
|
||||||
|
associations.erase(ei);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CKevaIterator*
|
CKevaIterator*
|
||||||
CKevaCache::iterateKeys(CKevaIterator* base) const
|
CKevaCache::iterateKeys(CKevaIterator* base) const
|
||||||
{
|
{
|
||||||
return new CCacheKeyIterator(*this, base);
|
return new CCacheKeyIterator(*this, base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CKevaIterator*
|
||||||
|
CKevaCache::IterateAssociatedNamespaces(CKevaIterator* base) const
|
||||||
|
{
|
||||||
|
return new CCacheKeyIterator(*this, base, true);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CKevaCache::updateNamesForHeight (unsigned nHeight,
|
CKevaCache::updateNamesForHeight (unsigned nHeight,
|
||||||
std::set<valtype>& names) const
|
std::set<valtype>& names) const
|
||||||
@ -253,6 +302,10 @@ void CKevaCache::apply(const CKevaCache& cache)
|
|||||||
set(std::get<0>(i->first), std::get<1>(i->first), i->second);
|
set(std::get<0>(i->first), std::get<1>(i->first), i->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (NamespaceMap::const_iterator i = associations.begin(); i != associations.end(); ++i) {
|
||||||
|
set(std::get<0>(i->first), std::get<1>(i->first), i->second);
|
||||||
|
}
|
||||||
|
|
||||||
for (std::set<NamespaceKeyType>::const_iterator i = cache.deleted.begin(); i != cache.deleted.end(); ++i) {
|
for (std::set<NamespaceKeyType>::const_iterator i = cache.deleted.begin(); i != cache.deleted.end(); ++i) {
|
||||||
remove(std::get<0>(*i), std::get<1>(*i));
|
remove(std::get<0>(*i), std::get<1>(*i));
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
// Distributed under the MIT software license, see the accompanying
|
// Distributed under the MIT software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
// Copyright (c) 2018
|
// Copyright (c) 2018-2020 The Kevacoin Core Developers
|
||||||
// Distributed under the MIT software license, see the accompanying
|
// Distributed under the MIT software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
@ -298,6 +298,8 @@ class CKevaCache
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
const static std::string associatePrefix;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Special comparator class for names that compares by length first.
|
* Special comparator class for names that compares by length first.
|
||||||
* This is used to sort the cache entry map in the same way as the
|
* This is used to sort the cache entry map in the same way as the
|
||||||
@ -336,6 +338,8 @@ public:
|
|||||||
|
|
||||||
typedef std::tuple<valtype, valtype> NamespaceKeyType;
|
typedef std::tuple<valtype, valtype> NamespaceKeyType;
|
||||||
|
|
||||||
|
typedef std::map<std::tuple<valtype, valtype>, CKevaData, KeyComparator> NamespaceMap;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/** New or updated names. */
|
/** New or updated names. */
|
||||||
@ -344,15 +348,19 @@ private:
|
|||||||
/** Deleted names. */
|
/** Deleted names. */
|
||||||
std::set<NamespaceKeyType> deleted;
|
std::set<NamespaceKeyType> deleted;
|
||||||
|
|
||||||
|
/** Namespace association. */
|
||||||
|
NamespaceMap associations;
|
||||||
|
|
||||||
friend class CCacheKeyIterator;
|
friend class CCacheKeyIterator;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
clear ()
|
clear()
|
||||||
{
|
{
|
||||||
entries.clear ();
|
entries.clear();
|
||||||
deleted.clear ();
|
deleted.clear();
|
||||||
|
associations.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -362,9 +370,9 @@ public:
|
|||||||
* @return True iff no changes are cached.
|
* @return True iff no changes are cached.
|
||||||
*/
|
*/
|
||||||
inline bool
|
inline bool
|
||||||
empty () const
|
empty() const
|
||||||
{
|
{
|
||||||
if (entries.empty() && deleted.empty()) {
|
if (entries.empty() && deleted.empty() && associations.empty()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,11 +402,23 @@ public:
|
|||||||
/* Delete a name. If it is in the "entries" set also, remove it there. */
|
/* Delete a name. If it is in the "entries" set also, remove it there. */
|
||||||
void remove(const valtype& nameSpace, const valtype& key);
|
void remove(const valtype& nameSpace, const valtype& key);
|
||||||
|
|
||||||
|
/* If the value is an associated namespace (_A_N...), return the namespace */
|
||||||
|
bool getAssociateNamespaces(const valtype& value, valtype& nameSpace);
|
||||||
|
|
||||||
|
/* Associate nameSpace with nameSpaceOther */
|
||||||
|
void associateNamespaces(const valtype& nameSpace, const valtype& nameSpaceOther);
|
||||||
|
|
||||||
|
/* Disassociate nameSpace with nameSpaceOther */
|
||||||
|
void disassociateNamespaces(const valtype& nameSpace, const valtype& nameSpaceOther);
|
||||||
|
|
||||||
/* Return a name iterator that combines a "base" iterator with the changes
|
/* Return a name iterator that combines a "base" iterator with the changes
|
||||||
made to it according to the cache. The base iterator is taken
|
made to it according to the cache. The base iterator is taken
|
||||||
ownership of. */
|
ownership of. */
|
||||||
CKevaIterator* iterateKeys(CKevaIterator* base) const;
|
CKevaIterator* iterateKeys(CKevaIterator* base) const;
|
||||||
|
|
||||||
|
// Get the associated namespace iterator.
|
||||||
|
CKevaIterator* IterateAssociatedNamespaces(CKevaIterator* base) const;
|
||||||
|
|
||||||
/* Query the cached changes to the expire index. In particular,
|
/* Query the cached changes to the expire index. In particular,
|
||||||
for a given height and a given set of names that were indexed to
|
for a given height and a given set of names that were indexed to
|
||||||
this update height, apply possible changes to the set that
|
this update height, apply possible changes to the set that
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
// Copyright (c) 2018 the Kevacoin Core Developers
|
// Copyright (c) 2018-2020 the Kevacoin Core Developers
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
25
src/txdb.cpp
25
src/txdb.cpp
@ -26,6 +26,7 @@ static const char DB_TXINDEX = 't';
|
|||||||
static const char DB_BLOCK_INDEX = 'b';
|
static const char DB_BLOCK_INDEX = 'b';
|
||||||
|
|
||||||
static const char DB_NAME = 'n';
|
static const char DB_NAME = 'n';
|
||||||
|
static const char DB_NS_ASSOC = 'a';
|
||||||
|
|
||||||
static const char DB_BEST_BLOCK = 'B';
|
static const char DB_BEST_BLOCK = 'B';
|
||||||
static const char DB_HEAD_BLOCKS = 'H';
|
static const char DB_HEAD_BLOCKS = 'H';
|
||||||
@ -92,6 +93,9 @@ private:
|
|||||||
/* The backing LevelDB iterator. */
|
/* The backing LevelDB iterator. */
|
||||||
CDBIterator* iter;
|
CDBIterator* iter;
|
||||||
|
|
||||||
|
/* This iterator is for namespace association search. */
|
||||||
|
bool isAssociation;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
~CDbKeyIterator();
|
~CDbKeyIterator();
|
||||||
@ -100,7 +104,7 @@ public:
|
|||||||
* Construct a new name iterator for the database.
|
* Construct a new name iterator for the database.
|
||||||
* @param db The database to create the iterator for.
|
* @param db The database to create the iterator for.
|
||||||
*/
|
*/
|
||||||
CDbKeyIterator(const CDBWrapper& db, const valtype& nameSpace);
|
CDbKeyIterator(const CDBWrapper& db, const valtype& nameSpace, bool association=false);
|
||||||
|
|
||||||
/* Implement iterator methods. */
|
/* Implement iterator methods. */
|
||||||
void seek(const valtype& start);
|
void seek(const valtype& start);
|
||||||
@ -112,22 +116,24 @@ CDbKeyIterator::~CDbKeyIterator() {
|
|||||||
delete iter;
|
delete iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
CDbKeyIterator::CDbKeyIterator(const CDBWrapper& db, const valtype& ns)
|
CDbKeyIterator::CDbKeyIterator(const CDBWrapper& db, const valtype& ns, bool association)
|
||||||
: CKevaIterator(ns), iter(const_cast<CDBWrapper*>(&db)->NewIterator())
|
: CKevaIterator(ns), iter(const_cast<CDBWrapper*>(&db)->NewIterator()), isAssociation(association)
|
||||||
{
|
{
|
||||||
seek(valtype());
|
seek(valtype());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDbKeyIterator::seek(const valtype& start) {
|
void CDbKeyIterator::seek(const valtype& start) {
|
||||||
iter->Seek(std::make_pair(DB_NAME, std::make_pair(nameSpace, start)));
|
auto &prefix = isAssociation ? DB_NS_ASSOC : DB_NAME;
|
||||||
|
iter->Seek(std::make_pair(prefix, std::make_pair(nameSpace, start)));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CDbKeyIterator::next(valtype& key, CKevaData& data) {
|
bool CDbKeyIterator::next(valtype& key, CKevaData& data) {
|
||||||
if (!iter->Valid())
|
if (!iter->Valid())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
auto &prefix = isAssociation ? DB_NS_ASSOC : DB_NAME;
|
||||||
std::pair<char, std::pair<valtype, valtype>> curKey;
|
std::pair<char, std::pair<valtype, valtype>> curKey;
|
||||||
if (!iter->GetKey(curKey) || curKey.first != DB_NAME)
|
if (!iter->GetKey(curKey) || curKey.first != prefix)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
valtype curNameSpace = std::get<0>(curKey.second);
|
valtype curNameSpace = std::get<0>(curKey.second);
|
||||||
@ -148,6 +154,10 @@ CKevaIterator* CCoinsViewDB::IterateKeys(const valtype& nameSpace) const {
|
|||||||
return new CDbKeyIterator(db, nameSpace);
|
return new CDbKeyIterator(db, nameSpace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CKevaIterator* CCoinsViewDB::IterateAssociatedNamespaces(const valtype& nameSpace) const {
|
||||||
|
return new CDbKeyIterator(db, nameSpace, true);
|
||||||
|
}
|
||||||
|
|
||||||
bool CCoinsViewDB::GetNamespace(const valtype &nameSpace, CKevaData &data) const {
|
bool CCoinsViewDB::GetNamespace(const valtype &nameSpace, CKevaData &data) const {
|
||||||
return db.Read(std::make_pair(DB_NAME, std::make_pair(nameSpace, CKevaScript::KEVA_DISPLAY_NAME_KEY)), data);
|
return db.Read(std::make_pair(DB_NAME, std::make_pair(nameSpace, CKevaScript::KEVA_DISPLAY_NAME_KEY)), data);
|
||||||
}
|
}
|
||||||
@ -324,6 +334,11 @@ void CKevaCache::writeBatch (CDBBatch& batch) const
|
|||||||
batch.Write(std::make_pair(DB_NAME, name), i->second);
|
batch.Write(std::make_pair(DB_NAME, name), i->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (NamespaceMap::const_iterator i = associations.begin(); i != associations.end(); ++i) {
|
||||||
|
std::pair<valtype, valtype> name = std::make_pair(std::get<0>(i->first), std::get<1>(i->first));
|
||||||
|
batch.Write(std::make_pair(DB_NS_ASSOC, name), i->second);
|
||||||
|
}
|
||||||
|
|
||||||
for (std::set<NamespaceKeyType>::const_iterator i = deleted.begin(); i != deleted.end(); ++i) {
|
for (std::set<NamespaceKeyType>::const_iterator i = deleted.begin(); i != deleted.end(); ++i) {
|
||||||
std::pair<valtype, valtype> name = std::make_pair(std::get<0>(*i), std::get<1>(*i));
|
std::pair<valtype, valtype> name = std::make_pair(std::get<0>(*i), std::get<1>(*i));
|
||||||
batch.Erase(std::make_pair(DB_NAME, name));
|
batch.Erase(std::make_pair(DB_NAME, name));
|
||||||
|
@ -80,6 +80,7 @@ public:
|
|||||||
bool GetName(const valtype &nameSpace, const valtype &key, CKevaData &data) const override;
|
bool GetName(const valtype &nameSpace, const valtype &key, CKevaData &data) const override;
|
||||||
bool GetNamesForHeight(unsigned nHeight, std::set<valtype>& names) const override;
|
bool GetNamesForHeight(unsigned nHeight, std::set<valtype>& names) const override;
|
||||||
CKevaIterator* IterateKeys(const valtype& nameSpace) const override;
|
CKevaIterator* IterateKeys(const valtype& nameSpace) const override;
|
||||||
|
CKevaIterator* IterateAssociatedNamespaces(const valtype& nameSpace) const override;
|
||||||
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, const CKevaCache &names) override;
|
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, const CKevaCache &names) override;
|
||||||
CCoinsViewCursor *Cursor() const override;
|
CCoinsViewCursor *Cursor() const override;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user