📄 indexed.cpp
字号:
{
// FIXME: There should never be an entry in the map which does have an empty 'entryList'
// We now ownly let the clean method remove entries. This should be fixed.
if (currSource->entryList.GetCount() > 0)
{
delete currSource->entryList.GetHead();
currSource->entryList.RemoveHead();
}
currSource->entryList.AddHead(entry);
return true;
}
else
{
currSource = new Source;
currSource->sourceID.setValue(sourceID);
currSource->entryList.AddHead(entry);
currKeyHash->m_Source_map.SetAt(CCKey(currSource->sourceID.getData()), currSource);
return true;
}
}
}
catch(...)
{
CKademlia::debugLine("Exception in CIndexed::writeFile");
ASSERT(0);
}
return false;
}
bool CIndexed::AddSources(const CUInt128& keyID, const CUInt128& sourceID, Kademlia::CEntry* entry)
{
try
{
KeyHash* currKeyHash;
if(!m_Sources_map.Lookup(CCKey(keyID.getData()), currKeyHash))
{
Source* currSource = new Source;
currSource->sourceID.setValue(sourceID);
currSource->entryList.AddHead(entry);
currKeyHash = new KeyHash;
currKeyHash->keyID.setValue(keyID);
currKeyHash->m_Source_map.SetAt(CCKey(currSource->sourceID.getData()), currSource);
m_Sources_map.SetAt(CCKey(currKeyHash->keyID.getData()), currKeyHash);
return true;
}
else
{
Source* currSource;
if(currKeyHash->m_Source_map.Lookup(CCKey(sourceID.getData()), currSource))
{
for(POSITION pos5 = currSource->entryList.GetHeadPosition(); pos5 != NULL; )
{
POSITION pos6 = pos5;
Kademlia::CEntry* currName = currSource->entryList.GetNext(pos5);
if(currName->ip == entry->ip && currName->tcpport == entry->tcpport)
{
currSource->entryList.RemoveAt(pos6);
delete currName;
currSource->entryList.AddHead(entry);
return true;
}
}
//New entry
if( currSource->entryList.GetCount() > KADEMLIAMAXSOUCEPERFILE )
{
CKademlia::debugMsg("Rotating sources");
Kademlia::CEntry* toremove = currSource->entryList.GetTail();
currSource->entryList.RemoveTail();
delete toremove;
}
Kademlia::CEntry* toadd = entry;
currSource->entryList.AddHead(toadd);
return true;
}
else
{
currSource = new Source;
currSource->sourceID.setValue(sourceID);
currSource->entryList.AddHead(entry);
currKeyHash->m_Source_map.SetAt(CCKey(currSource->sourceID.getData()), currSource);
return true;
}
}
}
catch(...)
{
CKademlia::debugLine("Exception in CIndexed::AddSource");
}
return false;
}
bool SearchTermsMatch(const SSearchTerm* pSearchTerm, const Kademlia::CEntry* item, CStringArray& astrFileNameTokens)
{
// boolean operators
if (pSearchTerm->type == SSearchTerm::AND)
return SearchTermsMatch(pSearchTerm->left, item, astrFileNameTokens) && SearchTermsMatch(pSearchTerm->right, item, astrFileNameTokens);
if (pSearchTerm->type == SSearchTerm::OR)
return SearchTermsMatch(pSearchTerm->left, item, astrFileNameTokens) || SearchTermsMatch(pSearchTerm->right, item, astrFileNameTokens);
if (pSearchTerm->type == SSearchTerm::NAND)
return SearchTermsMatch(pSearchTerm->left, item, astrFileNameTokens) && !SearchTermsMatch(pSearchTerm->right, item, astrFileNameTokens);
// word which is to be searched in the file name (and in additional meta data as done by some ed2k servers???)
if (pSearchTerm->type == SSearchTerm::String)
{
int iStrSearchTerms = pSearchTerm->astr->GetCount();
if (iStrSearchTerms == 0)
return false;
#if 0
//TODO: Use a pre-tokenized list for better performance.
// tokenize the filename (very expensive) only once per search expression and only if really needed
if (astrFileNameTokens.GetCount() == 0)
{
int iPosTok = 0;
CString strTok(item->fileName.Tokenize(" ()[]{}<>,._-!?", iPosTok));
while (!strTok.IsEmpty())
{
astrFileNameTokens.Add(strTok);
strTok = item->fileName.Tokenize(" ()[]{}<>,._-!?", iPosTok);
}
}
if (astrFileNameTokens.GetCount() == 0)
return false;
// if there are more than one search strings specified (e.g. "aaa bbb ccc") the entire string is handled
// like "aaa AND bbb AND ccc". search all strings from the string search term in the tokenized list of
// the file name. all strings of string search term have to be found (AND)
for (int iSearchTerm = 0; iSearchTerm < iStrSearchTerms; iSearchTerm++)
{
bool bFoundSearchTerm = false;
for (int i = 0; i < astrFileNameTokens.GetCount(); i++)
{
// the file name string was already stored in lowercase
// the string search term was already stored in lowercase
if (strcmp(astrFileNameTokens.GetAt(i), pSearchTerm->astr->GetAt(iSearchTerm)) == 0)
{
bFoundSearchTerm = true;
break;
}
}
if (!bFoundSearchTerm)
return false;
}
#else
// if there are more than one search strings specified (e.g. "aaa bbb ccc") the entire string is handled
// like "aaa AND bbb AND ccc". search all strings from the string search term in the tokenized list of
// the file name. all strings of string search term have to be found (AND)
for (int iSearchTerm = 0; iSearchTerm < iStrSearchTerms; iSearchTerm++)
{
// this will not give the same results as when tokenizing the filename string, but it is 20 times faster.
if (strstr(item->fileName, pSearchTerm->astr->GetAt(iSearchTerm)) == NULL)
return false;
}
#endif
return true;
// search string value in all string meta tags (this includes also the filename)
// although this would work, I am no longer sure if it's the correct way to process the search requests..
/*const Kademlia::CTag *tag;
TagList::const_iterator it;
for (it = item->taglist.begin(); it != item->taglist.end(); it++)
{
tag = *it;
if (tag->m_type == 2)
{
//TODO: Use a pre-tokenized list for better performance.
int iPos = 0;
CString strTok(static_cast<const CTagStr *>(tag)->m_value.Tokenize(" ()[]{}<>,._-!?", iPos));
while (!strTok.IsEmpty()){
if (stricmp(strTok, *(pSearchTerm->str)) == 0)
return true;
strTok = static_cast<const CTagStr *>(tag)->m_value.Tokenize(" ()[]{}<>,._-!?", iPos);
}
}
}
return false;*/
}
if (pSearchTerm->type == SSearchTerm::MetaTag)
{
if (pSearchTerm->tag->m_type == 2) // meta tags with string values
{
TagList::const_iterator it;
for (it = item->taglist.begin(); it != item->taglist.end(); it++)
{
const Kademlia::CTag* tag = *it;
if (tag->IsStr() && pSearchTerm->tag->m_name.Compare(tag->m_name) == 0)
return tag->GetStr().CompareNoCase(pSearchTerm->tag->GetStr()) == 0;
}
}
}
else if (pSearchTerm->type == SSearchTerm::OpGreaterEqual)
{
if (pSearchTerm->tag->IsInt()) // meta tags with integer values
{
TagList::const_iterator it;
for (it = item->taglist.begin(); it != item->taglist.end(); it++)
{
const Kademlia::CTag* tag = *it;
if (tag->IsInt() && pSearchTerm->tag->m_name.Compare(tag->m_name) == 0)
return tag->GetInt() >= pSearchTerm->tag->GetInt();
}
}
else if (pSearchTerm->tag->IsFloat()) // meta tags with float values
{
TagList::const_iterator it;
for (it = item->taglist.begin(); it != item->taglist.end(); it++)
{
const Kademlia::CTag* tag = *it;
if (tag->IsFloat() && pSearchTerm->tag->m_name.Compare(tag->m_name) == 0)
return tag->GetFloat() >= pSearchTerm->tag->GetFloat();
}
}
}
else if (pSearchTerm->type == SSearchTerm::OpLessEqual)
{
if (pSearchTerm->tag->IsInt()) // meta tags with integer values
{
TagList::const_iterator it;
for (it = item->taglist.begin(); it != item->taglist.end(); it++)
{
const Kademlia::CTag* tag = *it;
if (tag->IsInt() && pSearchTerm->tag->m_name.Compare(tag->m_name) == 0)
return tag->GetInt() <= pSearchTerm->tag->GetInt();
}
}
else if (pSearchTerm->tag->IsFloat()) // meta tags with float values
{
TagList::const_iterator it;
for (it = item->taglist.begin(); it != item->taglist.end(); it++)
{
const Kademlia::CTag* tag = *it;
if (tag->IsFloat() && pSearchTerm->tag->m_name.Compare(tag->m_name) == 0)
return tag->GetFloat() <= pSearchTerm->tag->GetFloat();
}
}
}
else if (pSearchTerm->type == SSearchTerm::OpGreater)
{
if (pSearchTerm->tag->IsInt()) // meta tags with integer values
{
TagList::const_iterator it;
for (it = item->taglist.begin(); it != item->taglist.end(); it++)
{
const Kademlia::CTag* tag = *it;
if (tag->IsInt() && pSearchTerm->tag->m_name.Compare(tag->m_name) == 0)
return tag->GetInt() > pSearchTerm->tag->GetInt();
}
}
else if (pSearchTerm->tag->IsFloat()) // meta tags with float values
{
TagList::const_iterator it;
for (it = item->taglist.begin(); it != item->taglist.end(); it++)
{
const Kademlia::CTag* tag = *it;
if (tag->IsFloat() && pSearchTerm->tag->m_name.Compare(tag->m_name) == 0)
return tag->GetFloat() > pSearchTerm->tag->GetFloat();
}
}
}
else if (pSearchTerm->type == SSearchTerm::OpLess)
{
if (pSearchTerm->tag->IsInt()) // meta tags with integer values
{
TagList::const_iterator it;
for (it = item->taglist.begin(); it != item->taglist.end(); it++)
{
const Kademlia::CTag* tag = *it;
if (tag->IsInt() && pSearchTerm->tag->m_name.Compare(tag->m_name) == 0)
return tag->GetInt() < pSearchTerm->tag->GetInt();
}
}
else if (pSearchTerm->tag->IsFloat()) // meta tags with float values
{
TagList::const_iterator it;
for (it = item->taglist.begin(); it != item->taglist.end(); it++)
{
const Kademlia::CTag* tag = *it;
if (tag->IsFloat() && pSearchTerm->tag->m_name.Compare(tag->m_name) == 0)
return tag->GetFloat() < pSearchTerm->tag->GetFloat();
}
}
}
else if (pSearchTerm->type == SSearchTerm::OpEqual)
{
if (pSearchTerm->tag->IsInt()) // meta tags with integer values
{
TagList::const_iterator it;
for (it = item->taglist.begin(); it != item->taglist.end(); it++)
{
const Kademlia::CTag* tag = *it;
if (tag->IsInt() && pSearchTerm->tag->m_name.Compare(tag->m_name) == 0)
return tag->GetInt() == pSearchTerm->tag->GetInt();
}
}
else if (pSearchTerm->tag->IsFloat()) // meta tags with float values
{
TagList::const_iterator it;
for (it = item->taglist.begin(); it != item->taglist.end(); it++)
{
const Kademlia::CTag* tag = *it;
if (tag->IsFloat() && pSearchTerm->tag->m_name.Compare(tag->m_name) == 0)
return tag->GetFloat() == pSearchTerm->tag->GetFloat();
}
}
}
else if (pSearchTerm->type == SSearchTerm::OpNotEqual)
{
if (pSearchTerm->tag->IsInt()) // meta tags with integer values
{
TagList::const_iterator it;
for (it = item->taglist.begin(); it != item->taglist.end(); it++)
{
const Kademlia::CTag* tag = *it;
if (tag->IsInt() && pSearchTerm->tag->m_name.Compare(tag->m_name) == 0)
return tag->GetInt() != pSearchTerm->tag->GetInt();
}
}
else if (pSearchTerm->tag->IsFloat()) // meta tags with float values
{
TagList::const_iterator it;
for (it = item->taglist.begin(); it != item->taglist.end(); it++)
{
const Kademlia::CTag* tag = *it;
if (tag->IsFloat() && pSearchTerm->tag->m_name.Compare(tag->m_name) == 0)
return tag->GetFloat() != pSearchTerm->tag->GetFloat();
}
}
}
return false;
}
bool SearchTermsMatch(const SSearchTerm* pSearchTerm, const Kademlia::CEntry* item)
{
// tokenize the filename (very expensive) only once per search expression and only if really needed
CStringArray astrFileNameTokens;
return SearchTermsMatch(pSearchTerm, item, astrFileNameTokens);
}
void CIndexed::SendValidKeywordResult(const CUInt128& keyID, const SSearchTerm* pSearchTerms, uint32 ip, uint16 port)
{
try
{
KeyHash* currKeyHash;
if(m_Keyword_map.Lookup(CCKey(keyID.getData()), currKeyHash))
{
CKademliaUDPListener *udpListner = CKademlia::getUDPListener();
ASSERT(udpListner != NULL);
byte packet[1024*50];
CByteIO bio(packet,sizeof(packet));
bio.writeByte(OP_KADEMLIAHEADER);
bio.writeByte(KADEMLIA_SEARCH_RES);
bio.writeUInt128(keyID);
bio.writeUInt16(50);
uint16 maxResults = 300;
uint16 count = 0;
POSITION pos2 = currKeyHash->m_Source_map.GetStartPosition();
while( pos2 != NULL )
{
Source* currSource;
CCKey key2;
currKeyHash->m_Source_map.GetNextAssoc( pos2, key2, currSource );
for(POSITION pos5 = currSource->entryList.GetHeadPosition(); pos5 != NULL; )
{
POSITION pos6 = pos5;
Kademlia::CEntry* currName = currSource->entryList.GetNext(pos5);
if ( !pSearchTerms || SearchTermsMatch(pSearchTerms, currName) )
{
if( count < maxResults ){
bio.writeUInt128(currName->sourceID);
bio.writeTagList(currName->taglist);
count++;
if( count % 50 == 0 )
{
uint32 len = sizeof(packet)-bio.getAvailable();
if (thePrefs.GetDebugClientKadUDPLevel() > 0)
DebugSend("KadSearchRes", ip, port);
udpListner->sendPacket(packet, len, ip, port);
bio.reset();
bio.writeByte(OP_KADEMLIAHEADER);
bio.writeByte(KADEMLIA_SEARCH_RES);
bio.writeUInt128(keyID);
bio.writeUInt16(50);
}
}
}
}
}
uint16 ccount = count % 50;
if( ccount )
{
uint32 len = sizeof(packet)-bio.getAvailable();
memcpy(packet+18, &ccount, 2);
if (thePrefs.GetDebugClientKadUDPLevel() > 0)
DebugSend("KadSearchRes", ip, port);
udpListner->sendPacket(packet, len, ip, port);
}
clean();
}
}
catch(...)
{
CKademlia::debugLine("Exception in CIndexed::SendValidKeywordResult");
}
}
void CIndexed::SendValidSourceResult(const CUInt128& keyID, uint32 ip, uint16 port)
{
try
{
KeyHash* currKeyHash;
if(m_Sources_map.Lookup(CCKey(keyID.getData()), currKeyHash))
{
CKademliaUDPListener *udpListner = CKademlia::getUDPListener();
ASSERT(udpListner != NULL);
byte packet[1024*50];
CByteIO bio(packet,sizeof(packet));
bio.writeByte(OP_KADEMLIAHEADER);
bio.writeByte(KADEMLIA_SEARCH_RES);
bio.writeUInt128(keyID);
bio.writeUInt16(50);
uint16 maxResults = 300;
uint16 count = 0;
POSITION pos2 = currKeyHash->m_Source_map.GetStartPosition();
while( pos2 != NULL )
{
Source* currSource;
CCKey key2;
currKeyHash->m_Source_map.GetNextAssoc( pos2, key2, currSource );
for(POSITION pos5 = currSource->entryList.GetHeadPosition(); pos5 != NULL; )
{
POSITION pos6 = pos5;
Kademlia::CEntry* currName = currSource->entryList.GetNext(pos5);
if( count < maxResults )
{
bio.writeUInt128(currName->sourceID);
bio.writeTagList(currName->taglist);
count++;
if( count % 50 == 0 )
{
uint32 len = sizeof(packet)-bio.getAvailable();
if (thePrefs.GetDebugClientKadUDPLevel() > 0)
DebugSend("KadSearchRes", ip, port);
udpListner->sendPacket(packet, len, ip, port);
bio.reset();
bio.writeByte(OP_KADEMLIAHEADER);
bio.writeByte(KADEMLIA_SEARCH_RES);
bio.writeUInt128(keyID);
bio.writeUInt16(50);
}
}
}
}
uint16 ccount = count % 50;
if( ccount )
{
uint32 len = sizeof(packet)-bio.getAvailable();
memcpy(packet+18, &ccount, 2);
if (thePrefs.GetDebugClientKadUDPLevel() > 0)
DebugSend("KadSearchRes", ip, port);
udpListner->sendPacket(packet, len, ip, port);
}
clean();
}
}
catch(...)
{
CKademlia::debugLine("Exception in CIndexed::SendValidSourceResult");
}
}
SSearchTerm::SSearchTerm()
{
type = AND;
tag = NULL;
left = NULL;
right = NULL;
}
SSearchTerm::~SSearchTerm()
{
if (type == String)
delete astr;
delete tag;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -