// this function is only allowed to be called right after successfully calculating the hashset (!) // will delete the hashset, after saving to free the memory bool CAICHRecoveryHashSet::SaveHashSet(){ if (m_eStatus != AICH_HASHSETCOMPLETE){ ASSERT( false ); return false; } if ( !m_pHashTree.m_bHashValid || m_pHashTree.m_nDataSize != m_pOwner->GetFileSize()){ ASSERT( false ); return false; } CSingleLock lockKnown2Met(&m_mutKnown2File, false); if (!lockKnown2Met.Lock(5000)){ return false; } CString fullpath = thePrefs.GetMuleDirectory(EMULE_CONFIGDIR); fullpath.Append(KNOWN2_MET_FILENAME); CSafeFile file; CFileException fexp; if (!file.Open(fullpath,CFile::modeCreate|CFile::modeReadWrite|CFile::modeNoTruncate|CFile::osSequentialScan|CFile::typeBinary|CFile::shareDenyNone, &fexp)){ if (fexp.m_cause != CFileException::fileNotFound){ CString strError(_T("Failed to load ") KNOWN2_MET_FILENAME _T(" file")); TCHAR szError[MAX_CFEXP_ERRORMSG]; if (fexp.GetErrorMessage(szError, ARRSIZE(szError))){ strError += _T(" - "); strError += szError; } theApp.QueueLogLine(true, _T("%s"), strError); } return false; } try { //setvbuf(file.m_pStream, NULL, _IOFBF, 16384); uint8 header = file.ReadUInt8(); if (header != KNOWN2_MET_VERSION){ AfxThrowFileException(CFileException::endOfFile, 0, file.GetFileName()); } // first we check if the hashset we want to write is already stored if (m_liAICHHashsStored.Find(m_pHashTree.m_Hash) != NULL) { theApp.QueueDebugLogLine(false, _T("AICH Hashset to write should be already present in known2.met - %s"), m_pHashTree.m_Hash.GetString()); // this hashset if already available, no need to save it again return true; } /*CAICHHash CurrentHash; while (file.GetPosition() < nExistingSize){ CurrentHash.Read(&file); if (m_pHashTree.m_Hash == CurrentHash){ // this hashset if already available, no need to save it again return true; } nHashCount = file.ReadUInt32(); if (file.GetPosition() + nHashCount*HASHSIZE > nExistingSize){ AfxThrowFileException(CFileException::endOfFile, 0, file.GetFileName()); } // skip the rest of this hashset file.Seek(nHashCount*HASHSIZE, CFile::current); }*/ // write hashset uint32 nExistingSize = (UINT)file.GetLength(); file.SeekToEnd(); m_pHashTree.m_Hash.Write(&file); uint32 nHashCount = (uint32)((PARTSIZE/EMBLOCKSIZE + ((PARTSIZE % EMBLOCKSIZE != 0)? 1 : 0)) * (m_pHashTree.m_nDataSize/PARTSIZE)); if (m_pHashTree.m_nDataSize % PARTSIZE != 0) nHashCount += (uint32)((m_pHashTree.m_nDataSize % PARTSIZE)/EMBLOCKSIZE + (((m_pHashTree.m_nDataSize % PARTSIZE) % EMBLOCKSIZE != 0)? 1 : 0)); file.WriteUInt32(nHashCount); if (!m_pHashTree.WriteLowestLevelHashs(&file, 0, true, true)){ // thats bad... really file.SetLength(nExistingSize); theApp.QueueDebugLogLine(true, _T("Failed to save HashSet: WriteLowestLevelHashs() failed!")); return false; } if (file.GetLength() != nExistingSize + (nHashCount+1)*HASHSIZE + 4){ // thats even worse file.SetLength(nExistingSize); theApp.QueueDebugLogLine(true, _T("Failed to save HashSet: Calculated and real size of hashset differ!")); return false; } CAICHRecoveryHashSet::AddStoredAICHHash(m_pHashTree.m_Hash); theApp.QueueDebugLogLine(false, _T("Successfully saved eMuleAC Hashset, %u Hashs + 1 Masterhash written"), nHashCount); file.Flush(); file.Close(); } catch(CFileException* error){ if (error->m_cause == CFileException::endOfFile) theApp.QueueLogLine(true, GetResString(IDS_ERR_MET_BAD), KNOWN2_MET_FILENAME); else{ TCHAR buffer[MAX_CFEXP_ERRORMSG]; error->GetErrorMessage(buffer, ARRSIZE(buffer)); theApp.QueueLogLine(true,GetResString(IDS_ERR_SERVERMET_UNKNOWN),buffer); } error->Delete(); return false; } FreeHashSet(); return true; }