Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

HashDatabase.cpp

Go to the documentation of this file.
00001 //
00002 // HashDatabase.cpp
00003 //
00004 // Copyright (c) Shareaza Development Team, 2002-2005.
00005 // This file is part of SHAREAZA (www.shareaza.com)
00006 //
00007 // Shareaza is free software; you can redistribute it
00008 // and/or modify it under the terms of the GNU General Public License
00009 // as published by the Free Software Foundation; either version 2 of
00010 // the License, or (at your option) any later version.
00011 //
00012 // Shareaza is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU General Public License
00018 // along with Shareaza; if not, write to the Free Software
00019 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 //
00021 
00022 #include "StdAfx.h"
00023 #include "Shareaza.h"
00024 #include "Settings.h"
00025 #include "HashDatabase.h"
00026 #include "TigerTree.h"
00027 #include "ED2K.h"
00028 
00029 #ifdef _DEBUG
00030 #undef THIS_FILE
00031 static char THIS_FILE[]=__FILE__;
00032 #define new DEBUG_NEW
00033 #endif
00034 
00035 CHashDatabase LibraryHashDB;
00036 
00037 
00039 // CHashDatabase construction
00040 
00041 CHashDatabase::CHashDatabase()
00042 {
00043         m_bOpen         = FALSE;
00044         m_nOffset       = 0;
00045         m_pIndex        = NULL;
00046         m_nIndex        = 0;
00047         m_nBuffer       = 0;
00048 }
00049 
00050 CHashDatabase::~CHashDatabase()
00051 {
00052         Close();
00053 }
00054 
00056 // CHashDatabase create
00057 
00058 BOOL CHashDatabase::Create()
00059 {
00060         CSingleLock pLock( &m_pSection, TRUE );
00061 
00062         Close();
00063 
00064         m_sPath = Settings.General.UserPath + _T("\\Data\\TigerTree.dat");
00065 
00066         if ( m_pFile.Open( m_sPath, CFile::modeReadWrite ) )
00067         {
00068                 CHAR szID[8];
00069                 m_pFile.Read( szID, 8 );
00070 
00071                 if ( memcmp( szID, "HFDB1000", 8 ) && memcmp( szID, "HFDB1001", 8 ) )
00072                 {
00073                         m_pFile.Close();
00074                         return FALSE;
00075                 }
00076 
00077                 m_pFile.Read( &m_nOffset, 4 );
00078                 m_pFile.Read( &m_nIndex, 4 );
00079                 m_pFile.Seek( m_nOffset, 0 );
00080 
00081                 for ( m_nBuffer = m_nIndex ; m_nBuffer & 63 ; m_nBuffer++ );
00082                 m_pIndex = new HASHDB_INDEX[ m_nBuffer ];
00083 
00084                 if ( memcmp( szID, "HFDB1001", 8 ) == 0 )
00085                 {
00086                         m_pFile.Read( m_pIndex, sizeof(HASHDB_INDEX) * m_nIndex );
00087                 }
00088                 else if ( memcmp( szID, "HFDB1000", 8 ) == 0 )
00089                 {
00090                         HASHDB_INDEX_1000 pIndex1;
00091 
00092                         for ( DWORD nIndex = 0 ; nIndex < m_nIndex ; nIndex++ )
00093                         {
00094                                 m_pFile.Read( &pIndex1, sizeof(pIndex1) );
00095                                 m_pIndex[ nIndex ].nIndex       = pIndex1.nIndex;
00096                                 m_pIndex[ nIndex ].nType        = HASH_TIGERTREE;
00097                                 m_pIndex[ nIndex ].nOffset      = pIndex1.nOffset;
00098                                 m_pIndex[ nIndex ].nLength      = pIndex1.nLength;
00099                         }
00100                 }
00101                 else
00102                 {
00103                         ASSERT( FALSE );
00104                 }
00105         }
00106         else
00107         {
00108                 if ( ! m_pFile.Open( m_sPath, CFile::modeReadWrite | CFile::modeCreate ) )
00109                 {
00110                         return FALSE;
00111                 }
00112 
00113                 m_nOffset = 16;
00114                 m_pFile.Write( "HFDB1001", 8 );
00115                 m_pFile.Write( &m_nOffset, 4 );
00116                 m_pFile.Write( &m_nIndex, 4 );
00117         }
00118 
00119         m_bOpen = TRUE;
00120 
00121         return TRUE;
00122 }
00123 
00125 // CHashDatabase close
00126 
00127 void CHashDatabase::Close()
00128 {
00129         CSingleLock pLock( &m_pSection, TRUE );
00130 
00131         if ( m_pIndex != NULL ) delete [] m_pIndex;
00132         if ( m_pFile.m_hFile != CFile::hFileNull ) m_pFile.Close();
00133 
00134         m_bOpen         = FALSE;
00135         m_nOffset       = 0;
00136         m_pIndex        = NULL;
00137         m_nIndex        = 0;
00138         m_nBuffer       = 0;
00139 }
00140 
00142 // CHashDatabase lookup
00143 
00144 HASHDB_INDEX* CHashDatabase::Lookup(DWORD nIndex, DWORD nType)
00145 {
00146         ASSERT( m_bOpen );
00147         HASHDB_INDEX* pIndex = m_pIndex;
00148 
00149         for ( DWORD nCount = m_nIndex ; nCount ; nCount--, pIndex++ )
00150         {
00151                 if ( pIndex->nIndex == nIndex && pIndex->nType == nType ) return pIndex;
00152         }
00153 
00154         return NULL;
00155 }
00156 
00158 // CHashDatabase prepare to store
00159 
00160 HASHDB_INDEX* CHashDatabase::PrepareToStore(DWORD nIndex, DWORD nType, DWORD nLength)
00161 {
00162         ASSERT( m_bOpen );
00163         HASHDB_INDEX* pIndex = Lookup( nIndex, nType );
00164 
00165         if ( pIndex != NULL && pIndex->nLength != nLength )
00166         {
00167                 pIndex->nIndex = 0;
00168                 pIndex = NULL;
00169         }
00170 
00171         if ( pIndex != NULL ) return pIndex;
00172 
00173         HASHDB_INDEX* pBestIndex        = NULL;
00174         DWORD nBestOverhead                     = 0xFFFFFFFF;
00175         DWORD nCount;
00176 
00177         for ( pIndex = m_pIndex, nCount = m_nIndex ; nCount ; nCount--, pIndex++ )
00178         {
00179                 if ( pIndex->nIndex == 0 && pIndex->nLength >= nLength )
00180                 {
00181                         DWORD nOverhead = pIndex->nLength - nLength;
00182 
00183                         if ( nOverhead < nBestOverhead )
00184                         {
00185                                 pBestIndex = pIndex;
00186                                 nBestOverhead = nOverhead;
00187                                 if ( nOverhead == 0 ) break;
00188                         }
00189                 }
00190         }
00191 
00192         if ( pBestIndex != NULL )
00193         {
00194                 pIndex = pBestIndex;
00195         }
00196         else
00197         {
00198                 if ( m_nIndex >= m_nBuffer )
00199                 {
00200                         m_nBuffer += 64;
00201                         HASHDB_INDEX* pNew = new HASHDB_INDEX[ m_nBuffer ];
00202                         if ( m_nIndex ) CopyMemory( pNew, m_pIndex, sizeof(HASHDB_INDEX) * m_nIndex );
00203                         if ( m_pIndex ) delete [] m_pIndex;
00204                         m_pIndex = pNew;
00205                 }
00206 
00207                 pIndex = m_pIndex + m_nIndex++;
00208                 pIndex->nOffset = m_nOffset;
00209                 pIndex->nLength = nLength;
00210 
00211                 m_nOffset += nLength;
00212         }
00213 
00214         pIndex->nIndex  = nIndex;
00215         pIndex->nType   = nType;
00216 
00217         return pIndex;
00218 }
00219 
00221 // CHashDatabase erase
00222 
00223 BOOL CHashDatabase::Erase(DWORD nIndex, DWORD nType)
00224 {
00225         ASSERT( m_bOpen );
00226 
00227         HASHDB_INDEX* pIndex = Lookup( nIndex, nType );
00228         if ( pIndex == NULL ) return FALSE;
00229         pIndex->nIndex = 0;
00230         Commit();
00231 
00232         return TRUE;
00233 }
00234 
00236 // CHashDatabase commit the changes and flush
00237 
00238 void CHashDatabase::Commit()
00239 {
00240         ASSERT( m_bOpen );
00241 
00242         m_pFile.SetLength( m_nOffset + sizeof(HASHDB_INDEX) * m_nIndex );
00243         m_pFile.Seek( 0, 0 );
00244         m_pFile.Write( "HFDB1001", 8 );
00245         m_pFile.Write( &m_nOffset, 4 );
00246         m_pFile.Write( &m_nIndex, 4 );
00247         m_pFile.Seek( m_nOffset, 0 );
00248         m_pFile.Write( m_pIndex, sizeof(HASHDB_INDEX) * m_nIndex );
00249 
00250         m_pFile.Flush();
00251 }
00252 
00254 // CHashDatabase delete all (irrespective of type)
00255 
00256 BOOL CHashDatabase::DeleteAll(DWORD nIndex)
00257 {
00258         CSingleLock pLock( &m_pSection, TRUE );
00259         if ( m_bOpen == FALSE ) return FALSE;
00260         if ( nIndex == 0 ) return FALSE;
00261 
00262         HASHDB_INDEX* pIndex = m_pIndex;
00263         DWORD nChanged = 0;
00264 
00265         for ( DWORD nCount = m_nIndex ; nCount ; nCount--, pIndex++ )
00266         {
00267                 if ( pIndex->nIndex == nIndex )
00268                 {
00269                         pIndex->nIndex = 0;
00270                         nChanged++;
00271                 }
00272         }
00273 
00274         if ( nChanged != 0 ) Commit();
00275         return nChanged != 0;
00276 }
00277 
00279 // CHashDatabase tiger-tree access
00280 
00281 BOOL CHashDatabase::GetTiger(DWORD nIndex, CTigerTree* pTree)
00282 {
00283         pTree->Clear();
00284 
00285         CSingleLock pLock( &m_pSection, TRUE );
00286         if ( m_bOpen == FALSE ) return FALSE;
00287 
00288         HASHDB_INDEX* pIndex = Lookup( nIndex, HASH_TIGERTREE );
00289         if ( pIndex == NULL ) return FALSE;
00290 
00291         try
00292         {
00293                 m_pFile.Seek( pIndex->nOffset, 0 );
00294                 CArchive ar( &m_pFile, CArchive::load );
00295                 pTree->Serialize( ar );
00296         }
00297         catch ( CException* pException )
00298         {
00299                 pException->Delete();
00300                 return FALSE;
00301         }
00302 
00303         return TRUE;
00304 }
00305 
00306 BOOL CHashDatabase::StoreTiger(DWORD nIndex, CTigerTree* pTree)
00307 {
00308         CSingleLock pLock( &m_pSection, TRUE );
00309         if ( m_bOpen == FALSE ) return FALSE;
00310 
00311         DWORD nLength = pTree->GetSerialSize();
00312 
00313         HASHDB_INDEX* pIndex = PrepareToStore( nIndex, HASH_TIGERTREE, nLength );
00314         if ( pIndex == NULL ) return FALSE;
00315 
00316         try
00317         {
00318                 m_pFile.Seek( pIndex->nOffset, 0 );
00319                 CArchive ar( &m_pFile, CArchive::store );
00320                 pTree->Serialize( ar );
00321         }
00322         catch ( CException* pException )
00323         {
00324                 pException->Delete();
00325         }
00326 
00327         Commit();
00328 
00329         return TRUE;
00330 }
00331 
00332 BOOL CHashDatabase::DeleteTiger(DWORD nIndex)
00333 {
00334         CSingleLock pLock( &m_pSection, TRUE );
00335         if ( m_bOpen == FALSE ) return FALSE;
00336         return Erase( nIndex, HASH_TIGERTREE );
00337 }
00338 
00340 // CHashDatabase ED2K hashset access
00341 
00342 BOOL CHashDatabase::GetED2K(DWORD nIndex, CED2K* pSet)
00343 {
00344         pSet->Clear();
00345 
00346         CSingleLock pLock( &m_pSection, TRUE );
00347         if ( m_bOpen == FALSE ) return FALSE;
00348 
00349         HASHDB_INDEX* pIndex = Lookup( nIndex, HASH_ED2K );
00350         if ( pIndex == NULL ) return FALSE;
00351 
00352         try
00353         {
00354                 m_pFile.Seek( pIndex->nOffset, 0 );
00355                 CArchive ar( &m_pFile, CArchive::load );
00356                 pSet->Serialize( ar );
00357         }
00358         catch ( CException* pException )
00359         {
00360                 pException->Delete();
00361                 return FALSE;
00362         }
00363 
00364         return TRUE;
00365 }
00366 
00367 BOOL CHashDatabase::StoreED2K(DWORD nIndex, CED2K* pSet)
00368 {
00369         CSingleLock pLock( &m_pSection, TRUE );
00370         if ( m_bOpen == FALSE ) return FALSE;
00371 
00372         DWORD nLength = pSet->GetSerialSize();
00373 
00374         HASHDB_INDEX* pIndex = PrepareToStore( nIndex, HASH_ED2K, nLength );
00375         if ( pIndex == NULL ) return FALSE;
00376 
00377         try
00378         {
00379                 m_pFile.Seek( pIndex->nOffset, 0 );
00380                 CArchive ar( &m_pFile, CArchive::store );
00381                 pSet->Serialize( ar );
00382         }
00383         catch ( CException* pException )
00384         {
00385                 pException->Delete();
00386         }
00387 
00388         Commit();
00389 
00390         return TRUE;
00391 }
00392 
00393 BOOL CHashDatabase::DeleteED2K(DWORD nIndex)
00394 {
00395         CSingleLock pLock( &m_pSection, TRUE );
00396         if ( m_bOpen == FALSE ) return FALSE;
00397         return Erase( nIndex, HASH_ED2K );
00398 }

Generated on Thu Dec 15 10:39:43 2005 for Shareaza 2.2.1.0 by  doxygen 1.4.2