mirror of
https://github.com/kvazar-network/kevacoin.git
synced 2025-01-13 00:28:03 +00:00
Started to work.
This commit is contained in:
parent
64a6a1701e
commit
ef08cbe7ff
@ -111,10 +111,16 @@ void
|
|||||||
CCacheKeyIterator::advanceBaseIterator()
|
CCacheKeyIterator::advanceBaseIterator()
|
||||||
{
|
{
|
||||||
assert (baseHasMore);
|
assert (baseHasMore);
|
||||||
|
if (isAssociation) {
|
||||||
|
do {
|
||||||
|
baseHasMore = base->next(baseKey, baseData);
|
||||||
|
} while (baseHasMore && cache.isDisassociated(nameSpace, baseKey));
|
||||||
|
} else {
|
||||||
do {
|
do {
|
||||||
baseHasMore = base->next(baseKey, baseData);
|
baseHasMore = base->next(baseKey, baseData);
|
||||||
} while (baseHasMore && cache.isDeleted(nameSpace, baseKey));
|
} while (baseHasMore && cache.isDeleted(nameSpace, baseKey));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CCacheKeyIterator::seek(const valtype& start)
|
CCacheKeyIterator::seek(const valtype& start)
|
||||||
@ -186,7 +192,7 @@ bool CCacheKeyIterator::next(valtype& key, CKevaData& data)
|
|||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
/* CKevaCache. */
|
/* CKevaCache. */
|
||||||
|
|
||||||
const std::string CKevaCache::associatePrefix = "_f:";
|
const std::string CKevaCache::associatePrefix = "_g:";
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CKevaCache::get(const valtype& nameSpace, const valtype& key, CKevaData& data) const
|
CKevaCache::get(const valtype& nameSpace, const valtype& key, CKevaData& data) const
|
||||||
@ -215,8 +221,6 @@ 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);
|
||||||
printf("set name is: %s\n", (EncodeBase58Check(nameSpace) + ValtypeToString(key)).c_str());
|
|
||||||
printf("set, this is: %p, data value is: %s\n", this, ValtypeToString(data.getValue()).c_str());
|
|
||||||
const std::set<NamespaceKeyType>::iterator di = deleted.find(name);
|
const std::set<NamespaceKeyType>::iterator di = deleted.find(name);
|
||||||
if (di != deleted.end()) {
|
if (di != deleted.end()) {
|
||||||
deleted.erase(di);
|
deleted.erase(di);
|
||||||
@ -260,9 +264,6 @@ void
|
|||||||
CKevaCache::associateNamespaces(const valtype& nameSpace, const valtype& nameSpaceOther, const CKevaData& data)
|
CKevaCache::associateNamespaces(const valtype& nameSpace, const valtype& nameSpaceOther, const CKevaData& data)
|
||||||
{
|
{
|
||||||
auto name = std::make_tuple(nameSpaceOther, nameSpace);
|
auto name = std::make_tuple(nameSpaceOther, nameSpace);
|
||||||
printf("associateNamespaces, name is: %s\n", (EncodeBase58Check(nameSpaceOther) + EncodeBase58Check(nameSpace)).c_str());
|
|
||||||
printf("associateNamespaces, this is: %p, data value is: %s\n", this, ValtypeToString(data.getValue()).c_str());
|
|
||||||
|
|
||||||
const std::set<NamespaceKeyType>::iterator di = disassociations.find(name);
|
const std::set<NamespaceKeyType>::iterator di = disassociations.find(name);
|
||||||
if (di != disassociations.end()) {
|
if (di != disassociations.end()) {
|
||||||
disassociations.erase(di);
|
disassociations.erase(di);
|
||||||
@ -270,10 +271,8 @@ CKevaCache::associateNamespaces(const valtype& nameSpace, const valtype& nameSpa
|
|||||||
|
|
||||||
const NamespaceMap::iterator ei = associations.find(name);
|
const NamespaceMap::iterator ei = associations.find(name);
|
||||||
if (ei != associations.end()) {
|
if (ei != associations.end()) {
|
||||||
printf("CKevaCache::associateNamespaces, REPLACE !!!\n");
|
|
||||||
ei->second = data;
|
ei->second = data;
|
||||||
} else {
|
} else {
|
||||||
printf("CKevaCache::associateNamespaces, INSERT !!!\n");
|
|
||||||
associations.insert(std::make_pair(name, data));
|
associations.insert(std::make_pair(name, data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -283,9 +282,7 @@ CKevaCache::disassociateNamespaces(const valtype& nameSpace, const valtype& name
|
|||||||
{
|
{
|
||||||
auto name = std::make_tuple(nameSpaceOther, nameSpace);
|
auto name = std::make_tuple(nameSpaceOther, nameSpace);
|
||||||
const NamespaceMap::iterator ei = associations.find(name);
|
const NamespaceMap::iterator ei = associations.find(name);
|
||||||
printf("CKevaCache::disassociateNamespaces, name is: %s\n", (EncodeBase58Check(nameSpaceOther) + EncodeBase58Check(nameSpace)).c_str());
|
|
||||||
if (ei != associations.end()) {
|
if (ei != associations.end()) {
|
||||||
printf("CKevaCache::disassociateNamespaces, erase!!!\n");
|
|
||||||
associations.erase(ei);
|
associations.erase(ei);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -314,13 +311,12 @@ CKevaCache::updateNamesForHeight (unsigned nHeight,
|
|||||||
|
|
||||||
void CKevaCache::apply(const CKevaCache& cache)
|
void CKevaCache::apply(const CKevaCache& cache)
|
||||||
{
|
{
|
||||||
printf("CKevaCache::apply!!!!\n");
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (NamespaceMap::const_iterator i = associations.begin(); i != associations.end(); ++i) {
|
for (NamespaceMap::const_iterator i = cache.associations.begin(); i != cache.associations.end(); ++i) {
|
||||||
associateNamespaces(std::get<0>(i->first), std::get<1>(i->first), i->second);
|
associateNamespaces(std::get<1>(i->first), std::get<0>(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) {
|
||||||
@ -328,6 +324,6 @@ void CKevaCache::apply(const CKevaCache& cache)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (std::set<NamespaceKeyType>::const_iterator i = cache.disassociations.begin(); i != cache.disassociations.end(); ++i) {
|
for (std::set<NamespaceKeyType>::const_iterator i = cache.disassociations.begin(); i != cache.disassociations.end(); ++i) {
|
||||||
disassociateNamespaces(std::get<0>(*i), std::get<1>(*i));
|
disassociateNamespaces(std::get<1>(*i), std::get<0>(*i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -376,7 +376,7 @@ public:
|
|||||||
inline bool
|
inline bool
|
||||||
empty() const
|
empty() const
|
||||||
{
|
{
|
||||||
if (entries.empty() && deleted.empty() && associations.empty()) {
|
if (entries.empty() && deleted.empty() && associations.empty() && disassociations.empty()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -391,6 +391,14 @@ public:
|
|||||||
return (deleted.count(name) > 0);
|
return (deleted.count(name) > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* See if the given namespaces are disassociated. */
|
||||||
|
inline bool
|
||||||
|
isDisassociated(const valtype& nameSpace, const valtype& nameSpaceOther) const
|
||||||
|
{
|
||||||
|
auto name = std::make_tuple(nameSpace, nameSpaceOther);
|
||||||
|
return (disassociations.count(name) > 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Try to get a name's associated data. This looks only
|
/* Try to get a name's associated data. This looks only
|
||||||
in entries, and doesn't care about deleted data. */
|
in entries, and doesn't care about deleted data. */
|
||||||
bool get(const valtype& nameSpace, const valtype& key, CKevaData& data) const;
|
bool get(const valtype& nameSpace, const valtype& key, CKevaData& data) const;
|
||||||
|
@ -300,11 +300,151 @@ UniValue keva_filter(const JSONRPCRequest& request)
|
|||||||
return keys;
|
return keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UniValue keva_group(const JSONRPCRequest& request)
|
||||||
|
{
|
||||||
|
if (request.fHelp || request.params.size() > 6 || request.params.size() == 0)
|
||||||
|
throw std::runtime_error(
|
||||||
|
"keva_filter (\"namespaceId\" (\"regexp\" (\"from\" (\"nb\" (\"stat\")))))\n"
|
||||||
|
"\nScan and list keys matching a regular expression.\n"
|
||||||
|
"\nArguments:\n"
|
||||||
|
"1. \"namespace\" (string) namespace Id\n"
|
||||||
|
"2. \"regexp\" (string, optional) filter keys with this regexp\n"
|
||||||
|
"3. \"maxage\" (numeric, optional, default=96000) only consider names updated in the last \"maxage\" blocks; 0 means all names\n"
|
||||||
|
"4. \"from\" (numeric, optional, default=0) return from this position onward; index starts at 0\n"
|
||||||
|
"5. \"nb\" (numeric, optional, default=0) return only \"nb\" entries; 0 means all\n"
|
||||||
|
"6. \"stat\" (string, optional) if set to the string \"stat\", print statistics instead of returning the names\n"
|
||||||
|
"\nResult:\n"
|
||||||
|
"[\n"
|
||||||
|
+ getKevaInfoHelp (" ", ",") +
|
||||||
|
" ...\n"
|
||||||
|
"]\n"
|
||||||
|
"\nExamples:\n"
|
||||||
|
+ HelpExampleCli ("keva_filter", "\"^id/\"")
|
||||||
|
+ HelpExampleCli ("keva_filter", "\"^id/\" 96000 0 0 \"stat\"")
|
||||||
|
+ HelpExampleRpc ("keva_filter", "\"^d/\"")
|
||||||
|
);
|
||||||
|
|
||||||
|
RPCTypeCheck(request.params, {
|
||||||
|
UniValue::VSTR, UniValue::VSTR, UniValue::VNUM,
|
||||||
|
UniValue::VNUM, UniValue::VNUM, UniValue::VSTR
|
||||||
|
});
|
||||||
|
|
||||||
|
if (IsInitialBlockDownload()) {
|
||||||
|
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD,
|
||||||
|
"Kevacoin is downloading blocks...");
|
||||||
|
}
|
||||||
|
|
||||||
|
ObserveSafeMode();
|
||||||
|
|
||||||
|
/* ********************** */
|
||||||
|
/* Interpret parameters. */
|
||||||
|
|
||||||
|
bool haveRegexp(false);
|
||||||
|
boost::xpressive::sregex regexp;
|
||||||
|
|
||||||
|
valtype nameSpace;
|
||||||
|
int maxage(96000), from(0), nb(0);
|
||||||
|
bool stats(false);
|
||||||
|
|
||||||
|
if (request.params.size() >= 1) {
|
||||||
|
const std::string namespaceStr = request.params[0].get_str();
|
||||||
|
if (!DecodeKevaNamespace(namespaceStr, Params(), nameSpace)) {
|
||||||
|
throw JSONRPCError (RPC_INVALID_PARAMETER, "invalid namespace id");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.params.size() >= 2) {
|
||||||
|
haveRegexp = true;
|
||||||
|
regexp = boost::xpressive::sregex::compile (request.params[1].get_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.params.size() >= 3)
|
||||||
|
maxage = request.params[2].get_int();
|
||||||
|
if (maxage < 0)
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER,
|
||||||
|
"'maxage' should be non-negative");
|
||||||
|
|
||||||
|
if (request.params.size() >= 4)
|
||||||
|
from = request.params[3].get_int ();
|
||||||
|
|
||||||
|
if (from < 0)
|
||||||
|
throw JSONRPCError (RPC_INVALID_PARAMETER, "'from' should be non-negative");
|
||||||
|
|
||||||
|
if (request.params.size() >= 5)
|
||||||
|
nb = request.params[4].get_int ();
|
||||||
|
|
||||||
|
if (nb < 0)
|
||||||
|
throw JSONRPCError (RPC_INVALID_PARAMETER, "'nb' should be non-negative");
|
||||||
|
|
||||||
|
if (request.params.size() >= 6) {
|
||||||
|
if (request.params[5].get_str() != "stat")
|
||||||
|
throw JSONRPCError (RPC_INVALID_PARAMETER,
|
||||||
|
"fifth argument must be the literal string 'stat'");
|
||||||
|
stats = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ******************************************* */
|
||||||
|
/* Iterate over names to build up the result. */
|
||||||
|
|
||||||
|
UniValue keys(UniValue::VARR);
|
||||||
|
unsigned count(0);
|
||||||
|
|
||||||
|
LOCK (cs_main);
|
||||||
|
|
||||||
|
valtype key;
|
||||||
|
CKevaData data;
|
||||||
|
std::unique_ptr<CKevaIterator> iter(pcoinsTip->IterateAssociatedNamespaces(nameSpace));
|
||||||
|
while (iter->next(key, data)) {
|
||||||
|
const int age = chainActive.Height() - data.getHeight();
|
||||||
|
assert(age >= 0);
|
||||||
|
if (maxage != 0 && age >= maxage)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (haveRegexp) {
|
||||||
|
const std::string keyStr = ValtypeToString(key);
|
||||||
|
boost::xpressive::smatch matches;
|
||||||
|
if (!boost::xpressive::regex_search(keyStr, matches, regexp))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (from > 0) {
|
||||||
|
--from;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
assert(from == 0);
|
||||||
|
|
||||||
|
if (stats) {
|
||||||
|
++count;
|
||||||
|
} else {
|
||||||
|
keys.push_back(getKevaInfo(ValtypeFromString(EncodeBase58Check(key)), data));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nb > 0) {
|
||||||
|
--nb;
|
||||||
|
if (nb == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ********************************************************** */
|
||||||
|
/* Return the correct result (take stats mode into account). */
|
||||||
|
|
||||||
|
if (stats) {
|
||||||
|
UniValue res(UniValue::VOBJ);
|
||||||
|
res.pushKV("blocks", chainActive.Height());
|
||||||
|
res.pushKV("count", static_cast<int>(count));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return keys;
|
||||||
|
}
|
||||||
|
|
||||||
static const CRPCCommand commands[] =
|
static const CRPCCommand commands[] =
|
||||||
{ // category name actor (function) argNames
|
{ // category name actor (function) argNames
|
||||||
// --------------------- ------------------------ ----------------------- ----------
|
// --------------------- ------------------------ ----------------------- ----------
|
||||||
{ "kevacoin", "keva_get", &keva_get, {"namespace", "key"} },
|
{ "kevacoin", "keva_get", &keva_get, {"namespace", "key"} },
|
||||||
{ "kevacoin", "keva_filter", &keva_filter, {"namespace", "regexp", "from", "nb", "stat"} }
|
{ "kevacoin", "keva_filter", &keva_filter, {"namespace", "regexp", "from", "nb", "stat"} },
|
||||||
|
{ "kevacoin", "keva_group", &keva_group, {"namespace", "regexp", "from", "nb", "stat"} }
|
||||||
};
|
};
|
||||||
|
|
||||||
void RegisterKevaRPCCommands(CRPCTable &t)
|
void RegisterKevaRPCCommands(CRPCTable &t)
|
||||||
|
Loading…
Reference in New Issue
Block a user