📄 hashdatabase.cpp
字号:
//
// HashDatabase.cpp
//
// Copyright (c) Shareaza Development Team, 2002-2004.
// This file is part of SHAREAZA (www.shareaza.com)
//
// Shareaza is free software; you can redistribute it
// and/or modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Shareaza is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Shareaza; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
#include "StdAfx.h"
#include "Shareaza.h"
#include "Settings.h"
#include "HashDatabase.h"
#include "TigerTree.h"
#include "ED2K.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
CHashDatabase LibraryHashDB;
//////////////////////////////////////////////////////////////////////
// CHashDatabase construction
CHashDatabase::CHashDatabase()
{
m_bOpen = FALSE;
m_nOffset = 0;
m_pIndex = NULL;
m_nIndex = 0;
m_nBuffer = 0;
}
CHashDatabase::~CHashDatabase()
{
Close();
}
//////////////////////////////////////////////////////////////////////
// CHashDatabase create
BOOL CHashDatabase::Create()
{
CSingleLock pLock( &m_pSection, TRUE );
Close();
m_sPath = Settings.General.Path + _T("\\Data\\TigerTree.dat");
if ( m_pFile.Open( m_sPath, CFile::modeReadWrite ) )
{
CHAR szID[8];
m_pFile.Read( szID, 8 );
if ( memcmp( szID, "HFDB1000", 8 ) && memcmp( szID, "HFDB1001", 8 ) )
{
m_pFile.Close();
return FALSE;
}
m_pFile.Read( &m_nOffset, 4 );
m_pFile.Read( &m_nIndex, 4 );
m_pFile.Seek( m_nOffset, 0 );
for ( m_nBuffer = m_nIndex ; m_nBuffer & 63 ; m_nBuffer++ );
m_pIndex = new HASHDB_INDEX[ m_nBuffer ];
if ( memcmp( szID, "HFDB1001", 8 ) == 0 )
{
m_pFile.Read( m_pIndex, sizeof(HASHDB_INDEX) * m_nIndex );
}
else if ( memcmp( szID, "HFDB1000", 8 ) == 0 )
{
HASHDB_INDEX_1000 pIndex1;
for ( DWORD nIndex = 0 ; nIndex < m_nIndex ; nIndex++ )
{
m_pFile.Read( &pIndex1, sizeof(pIndex1) );
m_pIndex[ nIndex ].nIndex = pIndex1.nIndex;
m_pIndex[ nIndex ].nType = HASH_TIGERTREE;
m_pIndex[ nIndex ].nOffset = pIndex1.nOffset;
m_pIndex[ nIndex ].nLength = pIndex1.nLength;
}
}
else
{
ASSERT( FALSE );
}
}
else
{
if ( ! m_pFile.Open( m_sPath, CFile::modeReadWrite | CFile::modeCreate ) )
{
return FALSE;
}
m_nOffset = 16;
m_pFile.Write( "HFDB1001", 8 );
m_pFile.Write( &m_nOffset, 4 );
m_pFile.Write( &m_nIndex, 4 );
}
m_bOpen = TRUE;
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CHashDatabase close
void CHashDatabase::Close()
{
CSingleLock pLock( &m_pSection, TRUE );
if ( m_pIndex != NULL ) delete [] m_pIndex;
if ( m_pFile.m_hFile != CFile::hFileNull ) m_pFile.Close();
m_bOpen = FALSE;
m_nOffset = 0;
m_pIndex = NULL;
m_nIndex = 0;
m_nBuffer = 0;
}
//////////////////////////////////////////////////////////////////////
// CHashDatabase lookup
HASHDB_INDEX* CHashDatabase::Lookup(DWORD nIndex, DWORD nType)
{
ASSERT( m_bOpen );
HASHDB_INDEX* pIndex = m_pIndex;
for ( DWORD nCount = m_nIndex ; nCount ; nCount--, pIndex++ )
{
if ( pIndex->nIndex == nIndex && pIndex->nType == nType ) return pIndex;
}
return NULL;
}
//////////////////////////////////////////////////////////////////////
// CHashDatabase prepare to store
HASHDB_INDEX* CHashDatabase::PrepareToStore(DWORD nIndex, DWORD nType, DWORD nLength)
{
ASSERT( m_bOpen );
HASHDB_INDEX* pIndex = Lookup( nIndex, nType );
if ( pIndex != NULL && pIndex->nLength != nLength )
{
pIndex->nIndex = 0;
pIndex = NULL;
}
if ( pIndex != NULL ) return pIndex;
HASHDB_INDEX* pBestIndex = NULL;
DWORD nBestOverhead = 0xFFFFFFFF;
DWORD nCount;
for ( pIndex = m_pIndex, nCount = m_nIndex ; nCount ; nCount--, pIndex++ )
{
if ( pIndex->nIndex == 0 && pIndex->nLength >= nLength )
{
DWORD nOverhead = pIndex->nLength - nLength;
if ( nOverhead < nBestOverhead )
{
pBestIndex = pIndex;
nBestOverhead = nOverhead;
if ( nOverhead == 0 ) break;
}
}
}
if ( pBestIndex != NULL )
{
pIndex = pBestIndex;
}
else
{
if ( m_nIndex >= m_nBuffer )
{
m_nBuffer += 64;
HASHDB_INDEX* pNew = new HASHDB_INDEX[ m_nBuffer ];
if ( m_nIndex ) CopyMemory( pNew, m_pIndex, sizeof(HASHDB_INDEX) * m_nIndex );
if ( m_pIndex ) delete [] m_pIndex;
m_pIndex = pNew;
}
pIndex = m_pIndex + m_nIndex++;
pIndex->nOffset = m_nOffset;
pIndex->nLength = nLength;
m_nOffset += nLength;
}
pIndex->nIndex = nIndex;
pIndex->nType = nType;
return pIndex;
}
//////////////////////////////////////////////////////////////////////
// CHashDatabase erase
BOOL CHashDatabase::Erase(DWORD nIndex, DWORD nType)
{
ASSERT( m_bOpen );
HASHDB_INDEX* pIndex = Lookup( nIndex, nType );
if ( pIndex == NULL ) return FALSE;
pIndex->nIndex = 0;
Commit();
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CHashDatabase commit the changes and flush
void CHashDatabase::Commit()
{
ASSERT( m_bOpen );
m_pFile.SetLength( m_nOffset + sizeof(HASHDB_INDEX) * m_nIndex );
m_pFile.Seek( 0, 0 );
m_pFile.Write( "HFDB1001", 8 );
m_pFile.Write( &m_nOffset, 4 );
m_pFile.Write( &m_nIndex, 4 );
m_pFile.Seek( m_nOffset, 0 );
m_pFile.Write( m_pIndex, sizeof(HASHDB_INDEX) * m_nIndex );
m_pFile.Flush();
}
//////////////////////////////////////////////////////////////////////
// CHashDatabase delete all (irrespective of type)
BOOL CHashDatabase::DeleteAll(DWORD nIndex)
{
CSingleLock pLock( &m_pSection, TRUE );
if ( m_bOpen == FALSE ) return FALSE;
if ( nIndex == 0 ) return FALSE;
HASHDB_INDEX* pIndex = m_pIndex;
DWORD nChanged = 0;
for ( DWORD nCount = m_nIndex ; nCount ; nCount--, pIndex++ )
{
if ( pIndex->nIndex == nIndex )
{
pIndex->nIndex = 0;
nChanged++;
}
}
if ( nChanged != 0 ) Commit();
return nChanged != 0;
}
//////////////////////////////////////////////////////////////////////
// CHashDatabase tiger-tree access
BOOL CHashDatabase::GetTiger(DWORD nIndex, CTigerTree* pTree)
{
pTree->Clear();
CSingleLock pLock( &m_pSection, TRUE );
if ( m_bOpen == FALSE ) return FALSE;
HASHDB_INDEX* pIndex = Lookup( nIndex, HASH_TIGERTREE );
if ( pIndex == NULL ) return FALSE;
try
{
m_pFile.Seek( pIndex->nOffset, 0 );
CArchive ar( &m_pFile, CArchive::load );
pTree->Serialize( ar );
}
catch ( CException* pException )
{
pException->Delete();
return FALSE;
}
return TRUE;
}
BOOL CHashDatabase::StoreTiger(DWORD nIndex, CTigerTree* pTree)
{
CSingleLock pLock( &m_pSection, TRUE );
if ( m_bOpen == FALSE ) return FALSE;
DWORD nLength = pTree->GetSerialSize();
HASHDB_INDEX* pIndex = PrepareToStore( nIndex, HASH_TIGERTREE, nLength );
if ( pIndex == NULL ) return FALSE;
try
{
m_pFile.Seek( pIndex->nOffset, 0 );
CArchive ar( &m_pFile, CArchive::store );
pTree->Serialize( ar );
}
catch ( CException* pException )
{
pException->Delete();
}
Commit();
return TRUE;
}
BOOL CHashDatabase::DeleteTiger(DWORD nIndex)
{
CSingleLock pLock( &m_pSection, TRUE );
if ( m_bOpen == FALSE ) return FALSE;
return Erase( nIndex, HASH_TIGERTREE );
}
//////////////////////////////////////////////////////////////////////
// CHashDatabase ED2K hashset access
BOOL CHashDatabase::GetED2K(DWORD nIndex, CED2K* pSet)
{
pSet->Clear();
CSingleLock pLock( &m_pSection, TRUE );
if ( m_bOpen == FALSE ) return FALSE;
HASHDB_INDEX* pIndex = Lookup( nIndex, HASH_ED2K );
if ( pIndex == NULL ) return FALSE;
try
{
m_pFile.Seek( pIndex->nOffset, 0 );
CArchive ar( &m_pFile, CArchive::load );
pSet->Serialize( ar );
}
catch ( CException* pException )
{
pException->Delete();
return FALSE;
}
return TRUE;
}
BOOL CHashDatabase::StoreED2K(DWORD nIndex, CED2K* pSet)
{
CSingleLock pLock( &m_pSection, TRUE );
if ( m_bOpen == FALSE ) return FALSE;
DWORD nLength = pSet->GetSerialSize();
HASHDB_INDEX* pIndex = PrepareToStore( nIndex, HASH_ED2K, nLength );
if ( pIndex == NULL ) return FALSE;
try
{
m_pFile.Seek( pIndex->nOffset, 0 );
CArchive ar( &m_pFile, CArchive::store );
pSet->Serialize( ar );
}
catch ( CException* pException )
{
pException->Delete();
}
Commit();
return TRUE;
}
BOOL CHashDatabase::DeleteED2K(DWORD nIndex)
{
CSingleLock pLock( &m_pSection, TRUE );
if ( m_bOpen == FALSE ) return FALSE;
return Erase( nIndex, HASH_ED2K );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -