📄 storage.cpp
字号:
if(_bitSet.isSet(pieceIndex)) { return; } if(_banedBitSet.isSet(pieceIndex)) { return; } if(pieceIndex > _task->getTorrentFile()->getPieceCount()-1) { return; } if(_writeCache.find(pieceIndex) != _writeCache.end()) { return; } _writeCache[pieceIndex] = data; if(_writeCache.size() > getWriteCacheSizeMax()) { saveWriteCacheToDisk(); } _bitSet.set(pieceIndex, true); _finishedPiece++; if(_bitSet.getSize() - _banedBitSet.getSetedCount() == _finishedPiece) { _task->getPeerManager()->onDownloadComplete(); saveWriteCacheToDisk(); } }void CStorage::saveWriteCacheToDisk(){ //LOG_DEBUG("********* saveWriteCacheToDisk"); TPieceMap::iterator iter = _writeCache.begin(); for(; iter!=_writeCache.end(); ++iter) { writePieceD(iter->first, iter->second); } _writeCache.clear(); saveBitset();}void CStorage::writePieceD(unsigned int pieceIndex,std::string& data){ if(pieceIndex > _task->getTorrentFile()->getPieceCount()-1) { return; } int left = data.size(); off64_t globalOffet = (off64_t)pieceIndex*(off64_t)_task->getTorrentFile()->getPieceLength(); for(;left > 0;) { TStorageFileInfo sFileInfo = getFileInfoByOffset(globalOffet); if(sFileInfo.baned) { left -= (sFileInfo.fileInfo.offset + sFileInfo.fileInfo.size - globalOffet); globalOffet = sFileInfo.fileInfo.offset + sFileInfo.fileInfo.size; continue; } if(sFileInfo.handle == -1) { return; } off64_t fileOffset = globalOffet-sFileInfo.fileInfo.offset; int writelen = left; if(writelen > sFileInfo.fileInfo.size - fileOffset) { writelen = sFileInfo.fileInfo.size - fileOffset; } lseek64(sFileInfo.handle, fileOffset, SEEK_SET); writelen = write(sFileInfo.handle, data.data()+ data.size()-left, writelen); left -= writelen; globalOffet += writelen; }}std::string CStorage::readData(unsigned int pieceIndex, unsigned int offset, unsigned int len){ //LOG_DEBUG("readData pieceIndex="<<pieceIndex<<" offset="<<offset<<" len="<<len); if(pieceIndex > _task->getTorrentFile()->getPieceCount()-1) { return ""; } if(len > _task->getTorrentFile()->getPieceLength()-offset) { return ""; } std::string pieceData; bool inReadCache = false; //ReadCache TReadPieceMap::iterator iter = _readCache.find(pieceIndex); if(iter != _readCache.end()) { //LOG_DEBUG("命中_readCache"); pieceData = iter->second.data; iter->second.lastAccessTick = GetTickCount(); inReadCache = true; } if(pieceData.size() == 0) { //WriteCache TPieceMap::iterator iter2 = _writeCache.find(pieceIndex); if(iter2 != _writeCache.end()) { //LOG_DEBUG("命中_writeCache"); pieceData = iter2->second; } } //Disk if(pieceData.size() == 0) { //LOG_DEBUG("cache中无数据,直接读取磁盘"); pieceData = readDataD(pieceIndex, 0, getPieceLength(pieceIndex)); } if(pieceData.size() < offset+len) { return ""; } if(!inReadCache) { TPieceCahce cache; cache.data = pieceData; cache.lastAccessTick = GetTickCount(); _readCache[pieceIndex] = cache; for(; _readCache.size() > getReadCacheSizeMax();) { TReadPieceMap::iterator iter = _readCache.begin(); TReadPieceMap::iterator removeIter = iter; for(; iter!= _readCache.end(); ++iter) { if(removeIter->second.lastAccessTick > iter->second.lastAccessTick) { removeIter = iter; } } //LOG_DEBUG("从_readCache中删除 "<<removeIter->first); _readCache.erase(removeIter); } } return pieceData.substr(offset, len);}std::string CStorage::readDataD(unsigned int pieceIndex, off64_t offset, unsigned int len){ if(pieceIndex > _task->getTorrentFile()->getPieceCount()-1) { return ""; } if(len > _task->getTorrentFile()->getPieceLength()-offset) { return ""; } char* buf = new char[len]; int left = len; off64_t globalOffet = (off64_t)pieceIndex*(off64_t)_task->getTorrentFile()->getPieceLength() + offset; for(;left > 0;) { TStorageFileInfo sFileInfo = getFileInfoByOffset(globalOffet); if(sFileInfo.handle == -1) { delete[] buf; return ""; } off64_t fileOffset = globalOffet-sFileInfo.fileInfo.offset; int readlen = left; if(readlen > sFileInfo.fileInfo.size - fileOffset) { readlen = sFileInfo.fileInfo.size - fileOffset; } lseek64(sFileInfo.handle, fileOffset, SEEK_SET); readlen = read(sFileInfo.handle, buf+len-left, readlen); left -= readlen; globalOffet += readlen; } std::string result; result.append((const char*)buf, len); delete[] buf; return result;}std::string CStorage::readPiece(unsigned int pieceIndex){ return readData(pieceIndex, 0, getPieceLength(pieceIndex));}bool CStorage::openFile(unsigned int index, TFileInfo fileInfo){ bool baned = false; TStorageFileInfo sFileInfo; std::string filePath; if(_task->getTorrentFile()->IsUTF8Valid()) { filePath = _destDir + fileInfo.pathUTF8; filePath = filename_from_utf8(filePath.c_str()); } else { filePath = _destDir + fileInfo.path; } TBanedFileList::iterator iter = _bandFileList.begin(); for(; iter!= _bandFileList.end(); ++iter) { if(*iter == index) { baned = true; break; } } sFileInfo.fileInfo = fileInfo; if(!baned) { createDir(filePath.c_str()); int handle = open(filePath.c_str(), O_RDWR | O_CREAT | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRWXG | S_IRWXO); if(handle == -1) { LOG_INFO("can not open file : "<<filePath); return false; } struct stat64 st; fstat64(handle, & st); if(st.st_size != 0) { _newTask = false; } if(st.st_size != fileInfo.size) { ftruncate64(handle, fileInfo.size); } sFileInfo.handle = handle; sFileInfo.mtime = st.st_mtime; sFileInfo.baned = false; } else { sFileInfo.handle = -1; sFileInfo.mtime = 0; sFileInfo.baned = true; _banedSize += fileInfo.size; } _fileHandleList.push_back(sFileInfo); return true;}TStorageFileInfo CStorage::getFileInfoByOffset(off64_t offset){ TFileHandleList::iterator iter = _fileHandleList.begin(); TFileHandleList::iterator iter2; for(; iter!=_fileHandleList.end(); ++iter) { if(iter->fileInfo.size == 0) { continue; } if(iter->fileInfo.offset <= offset && (iter->fileInfo.offset + iter->fileInfo.size) > offset) { return *iter; } } //not found TStorageFileInfo result; result.handle = -1; return result;}float CStorage::getFinishedPercent(){ int64_t total = _bitSet.getSize()-_banedBitSet.getSetedCount(); if(total == 0) { return 1.0f; } return ((double)_finishedPiece)/((double)total);}int64_t CStorage::getLeftCount(){ return (_bitSet.getSize() - _banedBitSet.getSetedCount() - _finishedPiece)*(int64_t)_task->getTorrentFile()->getPieceLength();}int64_t CStorage::getSelectedCount(){ return _task->getTorrentFile()->getTotalSize() - _banedSize;}int64_t CStorage::getBanedCount(){ return _banedSize;}unsigned int CStorage::getReadCacheSizeMax(){ unsigned int cachedPieceCount = _task->getCacheSize() / _task->getTorrentFile()->getPieceLength(); if(finished()) { return cachedPieceCount; } return 2*cachedPieceCount/5;}unsigned int CStorage::getWriteCacheSizeMax(){ unsigned int cachedPieceCount = _task->getCacheSize() / _task->getTorrentFile()->getPieceLength(); if(finished()) { return 0; } return 3*cachedPieceCount/5; }void CStorage::genBanedBitSet(){ _banedBitSet.alloc(_task->getTorrentFile()->getPieceCount()); TFileHandleList::iterator iter = _fileHandleList.begin(); for(; iter!=_fileHandleList.end(); ++iter) { if(iter->fileInfo.size == 0) { continue; } if(!iter->baned) { continue; } unsigned int beginIndex = getPieceIndexByOffset(iter->fileInfo.offset); unsigned int endOffset = getPieceIndexByOffset(iter->fileInfo.offset + iter->fileInfo.size -1); for(unsigned int i = beginIndex; i<=endOffset; ++i) { _banedBitSet.set(i, true); } } iter = _fileHandleList.begin(); for(; iter!=_fileHandleList.end(); ++iter) { if(iter->fileInfo.size == 0) { continue; } if(iter->baned) { continue; } unsigned int beginIndex = getPieceIndexByOffset(iter->fileInfo.offset); _banedBitSet.set(beginIndex, false); unsigned int endOffset = getPieceIndexByOffset(iter->fileInfo.offset + iter->fileInfo.size -1); _banedBitSet.set(endOffset, false); } }unsigned int CStorage::getPieceIndexByOffset(off64_t offset){ return offset / _task->getTorrentFile()->getPieceLength();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -