00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
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
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
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
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
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
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
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
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
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
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 }