Browse Source

Made sure to delete the entries from the db is they are new (i.e. no namespace and key combo before).

TODO: add keva test.
cn
Jianping Wu 6 years ago
parent
commit
eb9ea1b9dd
  1. 51
      src/coins.cpp
  2. 93
      src/keva/common.cpp
  3. 133
      src/keva/common.h
  4. 2
      src/rpc/mining.cpp
  5. 22
      src/txdb.cpp
  6. 6
      src/validation.cpp

51
src/coins.cpp

@ -200,68 +200,19 @@ CNameIterator* CCoinsViewCache::IterateNames() const {
name history. */ name history. */
void CCoinsViewCache::SetName(const valtype &nameSpace, const valtype &key, const CKevaData& data, bool undo) void CCoinsViewCache::SetName(const valtype &nameSpace, const valtype &key, const CKevaData& data, bool undo)
{ {
#if 0
CKevaData oldData;
if (GetName(nameSpace, key, oldData)) {
cacheNames.removeExpireIndex(name, oldData.getHeight());
/* Update the name history. If we are undoing, we expect that
the top history item matches the data being set now. If we
are not undoing, push the overwritten data onto the history stack.
Note that we only have to do this if the name already existed
in the database. Otherwise, no special action is required
for the name history. */
if (fNameHistory)
{
CNameHistory history;
if (!GetNameHistory(name, history))
{
/* Ensure that the history stack is indeed (still) empty
and was not modified by the failing GetNameHistory call. */
assert(history.empty());
}
if (undo)
history.pop(data);
else
history.push(oldData);
cacheNames.setHistory(name, history);
}
} else {
assert (!undo);
}
#endif
CKevaData namespaceData; CKevaData namespaceData;
if (GetNamespace(nameSpace, namespaceData)) { if (GetNamespace(nameSpace, namespaceData)) {
namespaceData.setUpdateOutpoint(data.getUpdateOutpoint()); namespaceData.setUpdateOutpoint(data.getUpdateOutpoint());
cacheNames.setNamespace(nameSpace, namespaceData); cacheNames.setNamespace(nameSpace, namespaceData);
} }
cacheNames.set(nameSpace, key, data); cacheNames.set(nameSpace, key, data);
#if 0
cacheNames.addExpireIndex(name, data.getHeight());
#endif
} }
void CCoinsViewCache::DeleteName(const valtype &nameSpace, const valtype &key) { void CCoinsViewCache::DeleteName(const valtype &nameSpace, const valtype &key) {
CKevaData oldData; CKevaData oldData;
if (GetName(nameSpace, key, oldData)) { if (!GetName(nameSpace, key, oldData)) {
#if 0
cacheNames.removeExpireIndex(name, oldData.getHeight());
#endif
}
else
assert(false); assert(false);
#if 0
if (fNameHistory)
{
/* When deleting a name, the history should already be clean. */
CNameHistory history;
assert (!GetNameHistory(name, history) || history.empty());
} }
#endif
cacheNames.remove(nameSpace, key); cacheNames.remove(nameSpace, key);
} }

93
src/keva/common.cpp

@ -210,11 +210,10 @@ void
CKevaCache::set(const valtype& nameSpace, const valtype& key, const CKevaData& data) CKevaCache::set(const valtype& nameSpace, const valtype& key, const CKevaData& data)
{ {
auto name = std::make_tuple(nameSpace, key); auto name = std::make_tuple(nameSpace, key);
#if 0 const std::set<NamespaceKeyType>::iterator di = deleted.find(name);
const std::set<valtype>::iterator di = deleted.find(name); if (di != deleted.end()) {
if (di != deleted.end ())
deleted.erase (di); deleted.erase (di);
#endif }
const EntryMap::iterator ei = entries.find(name); const EntryMap::iterator ei = entries.find(name);
if (ei != entries.end ()) if (ei != entries.end ())
@ -227,15 +226,11 @@ void
CKevaCache::remove(const valtype& nameSpace, const valtype& key) CKevaCache::remove(const valtype& nameSpace, const valtype& key)
{ {
auto name = std::make_tuple(nameSpace, key); auto name = std::make_tuple(nameSpace, key);
const EntryMap::iterator ei = entries.find (name); const EntryMap::iterator ei = entries.find(name);
if (ei != entries.end ()) if (ei != entries.end())
entries.erase (ei); entries.erase(ei);
//JWU TODO: make sure to remove namespace registration when
// the corresponding block is disconnected!!!
#if 0
deleted.insert(name); deleted.insert(name);
#endif
} }
CNameIterator* CNameIterator*
@ -244,91 +239,21 @@ CKevaCache::iterateNames(CNameIterator* base) const
return new CCacheNameIterator (*this, base); return new CCacheNameIterator (*this, base);
} }
#if 0
bool
CKevaCache::getHistory (const valtype& name, CNameHistory& res) const
{
assert (fNameHistory);
const std::map<valtype, CNameHistory>::const_iterator i = history.find (name);
if (i == history.end ())
return false;
res = i->second;
return true;
}
void
CKevaCache::setHistory (const valtype& name, const CNameHistory& data)
{
assert (fNameHistory);
const std::map<valtype, CNameHistory>::iterator ei = history.find (name);
if (ei != history.end ())
ei->second = data;
else
history.insert (std::make_pair (name, data));
}
#endif
void void
CKevaCache::updateNamesForHeight (unsigned nHeight, CKevaCache::updateNamesForHeight (unsigned nHeight,
std::set<valtype>& names) const std::set<valtype>& names) const
{ {
/* Seek in the map of cached entries to the first one corresponding /* Seek in the map of cached entries to the first one corresponding
to our height. */ to our height. */
#if 0
const ExpireEntry seekEntry(nHeight, valtype ());
std::map<ExpireEntry, bool>::const_iterator it;
for (it = expireIndex.lower_bound (seekEntry); it != expireIndex.end (); ++it)
{
const ExpireEntry& cur = it->first;
assert (cur.nHeight >= nHeight);
if (cur.nHeight > nHeight)
break;
if (it->second)
names.insert (cur.name);
else
names.erase (cur.name);
}
#endif
} }
#if 0
void
CKevaCache::addExpireIndex (const valtype& name, unsigned height)
{
const ExpireEntry entry(height, name);
expireIndex[entry] = true;
}
void
CKevaCache::removeExpireIndex (const valtype& name, unsigned height)
{
const ExpireEntry entry(height, name);
expireIndex[entry] = false;
}
#endif
void CKevaCache::apply(const CKevaCache& cache) void CKevaCache::apply(const CKevaCache& cache)
{ {
for (EntryMap::const_iterator i = cache.entries.begin(); i != cache.entries.end(); ++i) { for (EntryMap::const_iterator i = cache.entries.begin(); i != cache.entries.end(); ++i) {
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);
} }
#if 0
for (std::set<valtype>::const_iterator i = cache.deleted.begin(); i != cache.deleted.end(); ++i) {
remove(*i);
}
for (std::map<valtype, CNameHistory>::const_iterator i
= cache.history.begin (); i != cache.history.end (); ++i)
setHistory (i->first, i->second);
for (std::map<ExpireEntry, bool>::const_iterator i for (std::set<NamespaceKeyType>::const_iterator i = cache.deleted.begin(); i != cache.deleted.end(); ++i) {
= cache.expireIndex.begin (); i != cache.expireIndex.end (); ++i) remove(std::get<0>(*i), std::get<1>(*i));
expireIndex[i->first] = i->second; }
#endif
} }

133
src/keva/common.h

@ -310,107 +310,21 @@ private:
public: public:
/**
* Type for expire-index entries. We have to make sure that
* it is serialised in such a way that ordering is done correctly
* by height. This is not true if we use a std::pair, since then
* the height is serialised as byte-array with little-endian order,
* which does not correspond to the ordering by actual value.
*/
#if 0
class ExpireEntry
{
public:
unsigned nHeight;
valtype name;
inline ExpireEntry ()
: nHeight(0), name()
{}
inline ExpireEntry (unsigned h, const valtype& n)
: nHeight(h), name(n)
{}
/* Default copy and assignment. */
template<typename Stream>
inline void
Serialize (Stream& s) const
{
/* Flip the byte order of nHeight to big endian. */
const uint32_t nHeightFlipped = htobe32 (nHeight);
::Serialize (s, nHeightFlipped);
::Serialize (s, name);
}
template<typename Stream>
inline void
Unserialize (Stream& s)
{
uint32_t nHeightFlipped;
::Unserialize (s, nHeightFlipped);
::Unserialize (s, name);
/* Unflip the byte order. */
nHeight = be32toh (nHeightFlipped);
}
friend inline bool
operator== (const ExpireEntry& a, const ExpireEntry& b)
{
return a.nHeight == b.nHeight && a.name == b.name;
}
friend inline bool
operator!= (const ExpireEntry& a, const ExpireEntry& b)
{
return !(a == b);
}
friend inline bool
operator< (const ExpireEntry& a, const ExpireEntry& b)
{
if (a.nHeight != b.nHeight)
return a.nHeight < b.nHeight;
return a.name < b.name;
}
};
#endif
/** /**
* Type of name entry map. This is public because it is also used * Type of name entry map. This is public because it is also used
* by the unit tests. * by the unit tests.
*/ */
typedef std::map<std::tuple<valtype, valtype>, CKevaData, NameComparator> EntryMap; typedef std::map<std::tuple<valtype, valtype>, CKevaData, NameComparator> EntryMap;
typedef std::tuple<valtype, valtype> NamespaceKeyType;
private: private:
/** New or updated names. */ /** New or updated names. */
EntryMap entries; EntryMap entries;
/** Deleted names. */
std::set<valtype> deleted;
#if 0
/**
* New or updated history stacks. If they are empty, the corresponding
* database entry is deleted instead.
*/
std::map<valtype, CNameHistory> history;
#endif
#if 0 /** Deleted names. */
/** std::set<NamespaceKeyType> deleted;
* Changes to be performed to the expire index. The entry is mapped
* to either "true" (meaning to add it) or "false" (delete).
*/
std::map<ExpireEntry, bool> expireIndex;
#endif
friend class CCacheNameIterator; friend class CCacheNameIterator;
@ -421,10 +335,6 @@ public:
{ {
entries.clear (); entries.clear ();
deleted.clear (); deleted.clear ();
#if 0
history.clear ();
expireIndex.clear ();
#endif
} }
/** /**
@ -436,10 +346,7 @@ public:
inline bool inline bool
empty () const empty () const
{ {
if (entries.empty () && deleted.empty ()) { if (entries.empty() && deleted.empty()) {
#if 0
assert (history.empty () && expireIndex.empty ());
#endif
return true; return true;
} }
@ -450,11 +357,8 @@ public:
inline bool inline bool
isDeleted (const valtype& nameSpace, const valtype& key) const isDeleted (const valtype& nameSpace, const valtype& key) const
{ {
#if 0 auto name = std::make_tuple(nameSpace, key);
return (deleted.count(name) > 0); return (deleted.count(name) > 0);
#else
return false;
#endif
} }
/* Try to get a name's associated data. This looks only /* Try to get a name's associated data. This looks only
@ -477,37 +381,12 @@ public:
ownership of. */ ownership of. */
CNameIterator* iterateNames (CNameIterator* base) const; CNameIterator* iterateNames (CNameIterator* base) const;
#if 0
/**
* Query for an history entry.
* @param name The name to look up.
* @param res Put the resulting history entry here.
* @return True iff the name was found in the cache.
*/
bool getHistory (const valtype& name, CNameHistory& res) const;
/**
* Set a name history entry.
* @param name The name to modify.
* @param data The new history entry.
*/
void setHistory (const valtype& name, const CNameHistory& data);
#endif
/* 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
are represented by the cached expire index changes. */ are represented by the cached expire index changes. */
void updateNamesForHeight (unsigned nHeight, std::set<valtype>& names) const; void updateNamesForHeight (unsigned nHeight, std::set<valtype>& names) const;
#if 0
/* Add an expire-index entry. */
void addExpireIndex (const valtype& name, unsigned height);
/* Remove an expire-index entry. */
void removeExpireIndex (const valtype& name, unsigned height);
#endif
/* Apply all the changes in the passed-in record on top of this one. */ /* Apply all the changes in the passed-in record on top of this one. */
void apply (const CKevaCache& cache); void apply (const CKevaCache& cache);

2
src/rpc/mining.cpp

@ -441,11 +441,13 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
if(!g_connman) if(!g_connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
#if 0
if (g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) == 0) if (g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) == 0)
throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Kevacoin is not connected!"); throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Kevacoin is not connected!");
if (IsInitialBlockDownload()) if (IsInitialBlockDownload())
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Kevacoin is downloading blocks..."); throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Kevacoin is downloading blocks...");
#endif
static unsigned int nTransactionsUpdatedLast; static unsigned int nTransactionsUpdatedLast;

22
src/txdb.cpp

@ -348,26 +348,10 @@ 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);
} }
#if 0 for (std::set<NamespaceKeyType>::const_iterator i = deleted.begin(); i != deleted.end(); ++i) {
for (std::set<valtype>::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));
batch.Erase(std::make_pair (DB_NAME, *i)); batch.Erase(std::make_pair(DB_NAME, name));
} }
assert (fNameHistory || history.empty ());
for (std::map<valtype, CNameHistory>::const_iterator i = history.begin ();
i != history.end (); ++i)
if (i->second.empty ())
batch.Erase (std::make_pair (DB_NAME_HISTORY, i->first));
else
batch.Write (std::make_pair (DB_NAME_HISTORY, i->first), i->second);
for (std::map<ExpireEntry, bool>::const_iterator i = expireIndex.begin ();
i != expireIndex.end (); ++i)
if (i->second)
batch.Write (std::make_pair (DB_NAME_EXPIRY, i->first));
else
batch.Erase (std::make_pair (DB_NAME_EXPIRY, i->first));
#endif
} }
bool CBlockTreeDB::ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) { bool CBlockTreeDB::ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) {

6
src/validation.cpp

@ -1654,9 +1654,9 @@ DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockI
} }
// undo keva operations in reverse order // undo keva operations in reverse order
std::vector<CKevaTxUndo>::const_reverse_iterator nameUndoIter; std::vector<CKevaTxUndo>::const_reverse_iterator kevaUndoIter;
for (nameUndoIter = blockUndo.vkevaundo.rbegin (); nameUndoIter != blockUndo.vkevaundo.rend (); ++nameUndoIter) { for (kevaUndoIter = blockUndo.vkevaundo.rbegin(); kevaUndoIter != blockUndo.vkevaundo.rend(); ++kevaUndoIter) {
nameUndoIter->apply (view); kevaUndoIter->apply(view);
} }
// move best block pointer to prevout block // move best block pointer to prevout block

Loading…
Cancel
Save