void ChunkManager::recreateMissingFiles() { createFiles(); if (tor.isMultiFile()) { // loop over all files and mark all chunks of all missing files as // not downloaded for (Uint32 i = 0;i < tor.getNumFiles();i++) { TorrentFile & tf = tor.getFile(i); if (!tf.isMissing()) continue; for (Uint32 j = tf.getFirstChunk(); j <= tf.getLastChunk();j++) resetChunk(j); tf.setMissing(false); } } else { // reset all chunks in case of single file torrent for (Uint32 j = 0; j < tor.getNumChunks();j++) resetChunk(j); } d->saveIndexFile(); d->recalc_chunks_left = true; chunksLeft(); }
void ChunkManager::dataChecked(const BitSet & ok_chunks) { // go over all chunks at check each of them for (Uint32 i = 0;i < chunks.count();i++) { Chunk* c = chunks[i]; if (ok_chunks.get(i) && !bitset.get(i)) { // We think we do not hae a chunk, but we do have it bitset.set(i,true); todo.set(i,false); // the chunk must be on disk c->setStatus(Chunk::ON_DISK); tor.updateFilePercentage(i,bitset); } else if (!ok_chunks.get(i) && bitset.get(i)) { Out(SYS_DIO|LOG_IMPORTANT) << "Previously OK chunk " << i << " is corrupt !!!!!" << endl; // We think we have a chunk, but we don't bitset.set(i,false); todo.set(i,!only_seed_chunks.get(i) && !excluded_chunks.get(i)); if (c->getStatus() == Chunk::ON_DISK) { c->setStatus(Chunk::NOT_DOWNLOADED); tor.updateFilePercentage(i,bitset); } else if (c->getStatus() == Chunk::MMAPPED || c->getStatus() == Chunk::BUFFERED) { resetChunk(i); } else { tor.updateFilePercentage(i,bitset); } } } recalc_chunks_left = true; try { saveIndexFile(); } catch (bt::Error & err) { Out(SYS_DIO|LOG_DEBUG) << "Failed to save index file : " << err.toString() << endl; } catch (...) { Out(SYS_DIO|LOG_DEBUG) << "Failed to save index file : unkown exception" << endl; } chunksLeft(); corrupted_count = 0; }
Chunk* ChunkManager::grabChunk(unsigned int i) { if (i >= chunks.size()) return 0; Chunk* c = chunks[i]; if (c->getStatus() == Chunk::NOT_DOWNLOADED || c->isExcluded()) { return 0; } else if (c->getStatus() == Chunk::ON_DISK) { // load the chunk if it is on disk cache->load(c); loaded.insert(i,bt::GetCurrentTime()); bool check_allowed = (max_chunk_size_for_data_check == 0 || tor.getChunkSize() <= max_chunk_size_for_data_check); // when no corruptions have been found, only check once every 5 chunks if (check_allowed && recheck_counter < 5 && corrupted_count == 0) check_allowed = false; if (c->getData() && check_allowed) { recheck_counter = 0; if (!c->checkHash(tor.getHash(i))) { Out(SYS_DIO|LOG_IMPORTANT) << "Chunk " << i << " has been found invalid, redownloading" << endl; resetChunk(i); tor.updateFilePercentage(i,bitset); saveIndexFile(); recalc_chunks_left = true; corrupted_count++; corrupted(i); return 0; } } else { recheck_counter++; } } loaded.insert(i,bt::GetCurrentTime()); return c; }
void ChunkManager::dndMissingFiles() { // createFiles(); // create them again // loop over all files and mark all chunks of all missing files as // not downloaded for (Uint32 i = 0;i < tor.getNumFiles();i++) { TorrentFile & tf = tor.getFile(i); if (!tf.isMissing()) continue; for (Uint32 j = tf.getFirstChunk(); j <= tf.getLastChunk();j++) resetChunk(j); tf.setMissing(false); tf.setDoNotDownload(true); // set do not download } d->savePriorityInfo(); d->saveIndexFile(); d->recalc_chunks_left = true; chunksLeft(); }
void ChunkManager::downloadStatusChanged(TorrentFile* tf,bool download) { Uint32 first = tf->getFirstChunk(); Uint32 last = tf->getLastChunk(); if (download) { // include the chunks include(first,last); // if it is a multimedia file, prioritise first and last chunks of file if (tf->isMultimedia()) { Uint32 chunkOffset; chunkOffset = ((last - first) / 100) + 1; prioritise(first,first+chunkOffset,PREVIEW_PRIORITY); if (last - first > 2) { prioritise(last - chunkOffset, last, PREVIEW_PRIORITY); //prioritise(last -1,last, PREVIEW_PRIORITY); } } } else { // Out(SYS_DIO|LOG_DEBUG) << "Excluding chunks " << first << " to " << last << endl; // first and last chunk may be part of multiple files // so we can't just exclude them QValueList<Uint32> files,last_files; // get list of files where first chunk lies in tor.calcChunkPos(first,files); tor.calcChunkPos(last,last_files); // check for exceptional case which causes very long loops if (first == last && files.count() > 1) { cache->downloadStatusChanged(tf,download); savePriorityInfo(); return; } // go over all chunks from first to last and mark them as not downloaded // (first and last not included) for (Uint32 i = first + 1;i < last;i++) resetChunk(i); // if the first chunk only lies in one file, reset it if (files.count() == 1 && first != 0) { // Out(SYS_DIO|LOG_DEBUG) << "Resetting first " << first << endl; resetChunk(first); } // if the last chunk only lies in one file reset it if (last != first && last_files.count() == 1) { // Out(SYS_DIO|LOG_DEBUG) << "Resetting last " << last << endl; resetChunk(last); } Priority maxp = ONLY_SEED_PRIORITY; bool reprioritise_border_chunk = false; bool modified = false; // if one file in the list needs to be downloaded,increment first for (QValueList<Uint32>::iterator i = files.begin();i != files.end();i++) { if (*i == tf->getIndex()) continue; const TorrentFile & other = tor.getFile(*i); if (!other.doNotDownload()) { if (first != last && !modified) { first++; reprioritise_border_chunk = true; modified = true; } if (other.getPriority() > maxp) maxp = other.getPriority(); } } // in case we have incremented first, we better reprioritise the border chunk if (reprioritise_border_chunk) prioritise(first-1,first-1,maxp); maxp = ONLY_SEED_PRIORITY; reprioritise_border_chunk = false; modified = false; // if one file in the list needs to be downloaded,decrement last for (QValueList<Uint32>::iterator i = last_files.begin();i != last_files.end();i++) { if (*i == tf->getIndex()) continue; const TorrentFile & other = tor.getFile(*i); if (!other.doNotDownload()) { if (first != last && last > 0 && !modified) { last--; reprioritise_border_chunk = true; modified = true; } if (other.getPriority() > maxp) maxp = other.getPriority(); } } if (reprioritise_border_chunk) prioritise(last+1,last+1,maxp); // last smaller then first is not normal, so just return if (last < first) { cache->downloadStatusChanged(tf,download); savePriorityInfo(); return; } // Out(SYS_DIO|LOG_DEBUG) << "exclude " << first << " to " << last << endl; exclude(first,last); } // alert the cache but first put things in critical operation mode cache->downloadStatusChanged(tf,download); savePriorityInfo(); }