/* */ #include "MultiFileAllocationIterator.h" #include "MultiDiskAdaptor.h" #include "FileEntry.h" #include "SingleFileAllocationIterator.h" #include "DiskWriter.h" namespace aria2 { MultiFileAllocationIterator::MultiFileAllocationIterator(MultiDiskAdaptor* diskAdaptor): _diskAdaptor(diskAdaptor), _offset(0) { makeDiskWriterEntries(_entries, diskAdaptor->diskWriterEntries, diskAdaptor->getPieceLength()); } MultiFileAllocationIterator::~MultiFileAllocationIterator() {} void MultiFileAllocationIterator::allocateChunk() { while(_fileAllocationIterator.isNull() || _fileAllocationIterator->finished()) { if(_entries.empty()) { break; } DiskWriterEntryHandle entry = _entries.front(); _entries.pop_front(); FileEntryHandle fileEntry = entry->getFileEntry(); // Open file before calling DiskWriterEntry::size() _diskAdaptor->openIfNot(entry, &DiskWriterEntry::openFile, _diskAdaptor->getTopDirPath()); entry->enableDirectIO(); if(entry->size() < fileEntry->getLength()) { // Calling private function of MultiDiskAdaptor. _fileAllocationIterator.reset (new SingleFileAllocationIterator(entry->getDiskWriter().get(), entry->size(), fileEntry->getLength())); _fileAllocationIterator->init(); } } if(finished()) { return; } _fileAllocationIterator->allocateChunk(); } bool MultiFileAllocationIterator::finished() { return _entries.empty() && (_fileAllocationIterator.isNull() || _fileAllocationIterator->finished()); } off_t MultiFileAllocationIterator::getCurrentLength() { if(_fileAllocationIterator.isNull()) { return 0; } else { return _fileAllocationIterator->getCurrentLength(); } } uint64_t MultiFileAllocationIterator::getTotalLength() { if(_fileAllocationIterator.isNull()) { return 0; } else { return _fileAllocationIterator->getTotalLength(); } } const DiskWriterEntries& MultiFileAllocationIterator::getDiskWriterEntries() const { return _entries; } void MultiFileAllocationIterator::makeDiskWriterEntries (std::deque >& dwEntries, const DiskWriterEntries& srcEntries, size_t pieceLength) const { if(pieceLength == 0) { for(DiskWriterEntries::const_iterator itr = srcEntries.begin(); itr != srcEntries.end(); ++itr) { if((*itr)->getFileEntry()->isRequested()) { dwEntries.push_back(*itr); } } } else { DiskWriterEntries temp(srcEntries); { SharedHandle f(new FileEntry()); SharedHandle e(new DiskWriterEntry(f)); temp.push_front(e); } DiskWriterEntries::const_iterator done = temp.begin(); for(DiskWriterEntries::const_iterator itr = temp.begin()+1; itr != temp.end(); ++itr) { const FileEntryHandle& fileEntry = (*itr)->getFileEntry(); if(!fileEntry->isRequested()) { continue; } off_t pieceStartOffset = (fileEntry->getOffset()/pieceLength)*pieceLength; for(DiskWriterEntries::const_iterator i = itr-1; i != done; --i) { if((uint64_t)pieceStartOffset < (*i)->getFileEntry()->getOffset()+(*i)->getFileEntry()->getLength()) { dwEntries.push_back(*i); } else { break; } } dwEntries.push_back(*itr); done = itr; } } } } // namespace aria2