Browse Source

implement index of partial usernames so search-as-you-type can work as expected with listusernamespartial

miguelfreitas
Miguel Freitas 11 years ago
parent
commit
fb0802449c
  1. 8
      src/main.cpp
  2. 23
      src/twister.cpp
  3. 45
      src/txdb.cpp
  4. 5
      src/txdb.h

8
src/main.cpp

@ -1175,6 +1175,8 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size())); CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size()));
std::vector<std::pair<uint256, CDiskTxPos> > vPos; std::vector<std::pair<uint256, CDiskTxPos> > vPos;
vPos.reserve(block.vtx.size()-1); vPos.reserve(block.vtx.size()-1);
std::vector<std::string> vUsernames;
vUsernames.reserve(block.vtx.size()-1);
for (unsigned int i = 0; i < block.vtx.size(); i++) for (unsigned int i = 0; i < block.vtx.size(); i++)
{ {
const CTransaction &tx = block.vtx[i]; const CTransaction &tx = block.vtx[i];
@ -1184,6 +1186,7 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
blockundo.vtxundo.push_back(txundo); blockundo.vtxundo.push_back(txundo);
uint256 txid = SerializeHash(make_pair(tx.GetUsername(),-1)); uint256 txid = SerializeHash(make_pair(tx.GetUsername(),-1));
vPos.push_back(std::make_pair(txid, pos)); vPos.push_back(std::make_pair(txid, pos));
vUsernames.push_back(tx.GetUsername());
CDiskTxPos oldPos; CDiskTxPos oldPos;
if( pblocktree->ReadTxIndex(txid, oldPos) && pos != oldPos ) { if( pblocktree->ReadTxIndex(txid, oldPos) && pos != oldPos ) {
@ -1228,6 +1231,11 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
if (!pblocktree->WriteTxIndex(vPos)) if (!pblocktree->WriteTxIndex(vPos))
return state.Abort(_("Failed to write transaction index")); return state.Abort(_("Failed to write transaction index"));
for (size_t i=0; i<vUsernames.size(); i++) {
if (!pblocktree->AddNameToPartialNameTree(vUsernames.at(i)))
return state.Abort(_("Failed to write partial name index"));
}
// add this block to the view's block chain // add this block to the view's block chain
assert(view.SetBestBlock(pindex)); assert(view.SetBestBlock(pindex));

23
src/twister.cpp

@ -5,6 +5,7 @@
#include "main.h" #include "main.h"
#include "init.h" #include "init.h"
#include "bitcoinrpc.h" #include "bitcoinrpc.h"
#include "txdb.h"
using namespace json_spirit; using namespace json_spirit;
using namespace std; using namespace std;
@ -1695,27 +1696,7 @@ Value listusernamespartial(const Array& params, bool fHelp)
} }
} }
// now the rest, the entire block chain pblocktree->GetNamesFromPartial(userStartsWith, retStrings, count);
for(CBlockIndex* pindex = pindexBest; pindex && retStrings.size() < count; pindex = pindex->pprev ) {
CBlock block;
if( !ReadBlockFromDisk(block, pindex) )
continue;
BOOST_FOREACH(const CTransaction&tx, block.vtx) {
if( !tx.IsSpamMessage() ) {
string txUsername = tx.userName.ExtractSmallString();
if( (exact_match && userStartsWith.size() != txUsername.size()) ||
userStartsWith.size() > txUsername.size() ) {
continue;
}
int toCompare = userStartsWith.size();
if( memcmp( txUsername.data(), userStartsWith.data(), toCompare ) == 0 )
retStrings.insert( txUsername );
if( retStrings.size() >= count )
break;
}
}
}
Array ret; Array ret;
BOOST_FOREACH(string username, retStrings) { BOOST_FOREACH(string username, retStrings) {

45
src/txdb.cpp

@ -189,6 +189,51 @@ bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) {
return true; return true;
} }
bool CBlockTreeDB::WritePartialNameTree(const std::string &partialName, const std::string &nextChars) {
return Write(std::make_pair('n', partialName), nextChars);
}
bool CBlockTreeDB::ReadPartialNameTree(const std::string &partialName, std::string &nextChars) {
return Read(std::make_pair('n', partialName), nextChars);
}
bool CBlockTreeDB::AddCharToPartialNameTree(const std::string &partialName, char ch) {
std::string nextChars;
if (ReadPartialNameTree(partialName, nextChars)) {
if (nextChars.find(ch) == string::npos) {
nextChars.push_back(ch);
return WritePartialNameTree(partialName, nextChars);
}
} else {
return WritePartialNameTree(partialName, std::string(1,ch));
}
return true;
}
bool CBlockTreeDB::AddNameToPartialNameTree(const std::string &name) {
std::string partial;
for (size_t i=0; i<name.size()-1; i++) {
partial.push_back(name.at(i));
if (!AddCharToPartialNameTree( partial, name.at(i+1) ))
return false;
}
return AddCharToPartialNameTree( name, '.' ); // mark end of name
}
void CBlockTreeDB::GetNamesFromPartial(const std::string &partial, std::set< std::string > &names, size_t count) {
std::string nextChars;
if (ReadPartialNameTree(partial, nextChars)) {
for(size_t i=0; i<nextChars.size() && names.size()<count; i++) {
if (nextChars.at(i) == '.') {
names.insert(partial);
} else {
GetNamesFromPartial(partial+nextChars.substr(i,1), names, count);
}
}
}
}
bool CBlockTreeDB::LoadBlockIndexGuts() bool CBlockTreeDB::LoadBlockIndexGuts()
{ {
leveldb::Iterator *pcursor = NewIterator(); leveldb::Iterator *pcursor = NewIterator();

5
src/txdb.h

@ -51,6 +51,11 @@ public:
bool WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> > &list); bool WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> > &list);
bool WriteFlag(const std::string &name, bool fValue); bool WriteFlag(const std::string &name, bool fValue);
bool ReadFlag(const std::string &name, bool &fValue); bool ReadFlag(const std::string &name, bool &fValue);
bool WritePartialNameTree(const std::string &partialName, const std::string &nextChars);
bool ReadPartialNameTree(const std::string &partialName, std::string &nextChars);
bool AddCharToPartialNameTree(const std::string &partialName, char ch);
bool AddNameToPartialNameTree(const std::string &name);
void GetNamesFromPartial(const std::string &partial, std::set< std::string > &names, size_t count);
bool LoadBlockIndexGuts(); bool LoadBlockIndexGuts();
}; };

Loading…
Cancel
Save