diff --git a/ChangeLog b/ChangeLog index d625328a6..80973f51e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2009-02-11 Tatsuhiro Tsujikawa + + Fixed broken selected file BitTorrent download. + * src/MultiDiskWriter.cc + * test/MultiDiskWriterTest.cc + * test/MultiFileAllocationIteratorTest.cc + 2009-02-11 Tatsuhiro Tsujikawa Fixed #define guard for EpollEventPoll diff --git a/src/MultiDiskAdaptor.cc b/src/MultiDiskAdaptor.cc index 5cd8774ec..1b1ebb53f 100644 --- a/src/MultiDiskAdaptor.cc +++ b/src/MultiDiskAdaptor.cc @@ -34,8 +34,9 @@ /* copyright --> */ #include "MultiDiskAdaptor.h" -#include #include +#include +#include #include "DefaultDiskWriter.h" #include "message.h" @@ -196,18 +197,22 @@ void MultiDiskAdaptor::resetDiskWriterEntries() (createDiskWriterEntry(*i, (*i)->isRequested())); } + std::map dwreq; + // TODO Currently, pieceLength == 0 is used for unit testing only. if(pieceLength > 0) { std::deque >::iterator done = diskWriterEntries.begin(); for(std::deque >::iterator itr = diskWriterEntries.begin(); itr != diskWriterEntries.end();) { - if(!(*itr)->getFileEntry()->isRequested()) { + const SharedHandle& fileEntry = (*itr)->getFileEntry(); + + if(!fileEntry->isRequested()) { ++itr; continue; } off_t pieceStartOffset = - ((*itr)->getFileEntry()->getOffset()/pieceLength)*pieceLength; + (fileEntry->getOffset()/pieceLength)*pieceLength; if(itr != diskWriterEntries.begin()) { for(std::deque >::iterator i = itr-1; true; --i) { @@ -225,24 +230,45 @@ void MultiDiskAdaptor::resetDiskWriterEntries() } } - ++itr; + if(fileEntry->getLength() > 0) { + off_t lastPieceStartOffset = + (fileEntry->getOffset()+fileEntry->getLength()-1)/pieceLength*pieceLength; + logger->debug("Checking adjacent backward file to %s" + " whose lastPieceStartOffset+pieceLength=%lld", + fileEntry->getPath().c_str(), + lastPieceStartOffset+pieceLength); - for(; itr != diskWriterEntries.end(); ++itr) { - if((*itr)->getFileEntry()->getOffset() < - static_cast(pieceStartOffset+pieceLength)) { - (*itr)->needsFileAllocation(true); - } else { - break; + ++itr; + // adjacent backward files are not needed to be allocated. They + // just requre DiskWriter + for(; itr != diskWriterEntries.end() && + !(*itr)->getFileEntry()->isRequested(); ++itr) { + logger->debug("file=%s, offset=%lld", + (*itr)->getFileEntry()->getPath().c_str(), + (*itr)->getFileEntry()->getOffset()); + + if((*itr)->getFileEntry()->getOffset() < + static_cast(lastPieceStartOffset+pieceLength)) { + logger->debug("%s needs diskwriter", + (*itr)->getFileEntry()->getPath().c_str()); + dwreq[(*itr)->getFileEntry()->getPath()] = true; + } else { + break; + } } + done = itr-1; + } else { + done = itr; + ++itr; } - - done = itr-1; } } DefaultDiskWriterFactory dwFactory; for(std::deque >::iterator i = diskWriterEntries.begin(); i != diskWriterEntries.end(); ++i) { - if((*i)->needsFileAllocation() || (*i)->fileExists(getTopDirPath())) { + if((*i)->needsFileAllocation() || + dwreq.find((*i)->getFileEntry()->getPath()) != dwreq.end() || + (*i)->fileExists(getTopDirPath())) { logger->debug("Creating DiskWriter for filename=%s", (*i)->getFilePath(getTopDirPath()).c_str()); (*i)->setDiskWriter(dwFactory.newDiskWriter()); diff --git a/test/MultiDiskAdaptorTest.cc b/test/MultiDiskAdaptorTest.cc index e07c4c14a..71fb32284 100644 --- a/test/MultiDiskAdaptorTest.cc +++ b/test/MultiDiskAdaptorTest.cc @@ -48,13 +48,22 @@ CPPUNIT_TEST_SUITE_REGISTRATION( MultiDiskAdaptorTest ); std::deque > createEntries() { SharedHandle array[] = { - SharedHandle(new FileEntry("file1.txt", 0, 0)), - SharedHandle(new FileEntry("file2.txt", 15, 0)), - SharedHandle(new FileEntry("file3.txt", 7, 15)), - SharedHandle(new FileEntry("file4.txt", 0, 22)), - SharedHandle(new FileEntry("file5.txt", 2, 22)), - SharedHandle(new FileEntry("file6.txt", 0, 24)), + SharedHandle(new FileEntry("file0.txt", 0, 0)), + SharedHandle(new FileEntry("file1.txt", 15, 0)), + SharedHandle(new FileEntry("file2.txt", 7, 15)), + SharedHandle(new FileEntry("file3.txt", 0, 22)), + SharedHandle(new FileEntry("file4.txt", 2, 22)), + SharedHandle(new FileEntry("file5.txt", 0, 24)), }; + // 1 1 2 2 + // 0....5....0....5....0....5 + // ++--++--++--++--++--++--++ + // | file0 + // *************** file1 + // ******* file2 + // | file3 + // ** flie4 + // | file5 std::deque > entries(&array[0], &array[arrayLength(array)]); for(std::deque >::const_iterator i = entries.begin(); @@ -115,6 +124,7 @@ void MultiDiskAdaptorTest::testResetDiskWriterEntries() CPPUNIT_ASSERT(entries[0]->getDiskWriter().isNull()); // Because entries[2] spans entries[1] CPPUNIT_ASSERT(!entries[1]->getDiskWriter().isNull()); + CPPUNIT_ASSERT(entries[1]->needsFileAllocation()); CPPUNIT_ASSERT(!entries[2]->getDiskWriter().isNull()); CPPUNIT_ASSERT(!entries[3]->getDiskWriter().isNull()); CPPUNIT_ASSERT(!entries[4]->getDiskWriter().isNull()); @@ -136,6 +146,7 @@ void MultiDiskAdaptorTest::testResetDiskWriterEntries() CPPUNIT_ASSERT(!entries[2]->getDiskWriter().isNull()); // Because entries[4] spans entries[3] CPPUNIT_ASSERT(!entries[3]->getDiskWriter().isNull()); + CPPUNIT_ASSERT(entries[3]->needsFileAllocation()); CPPUNIT_ASSERT(!entries[4]->getDiskWriter().isNull()); CPPUNIT_ASSERT(!entries[5]->getDiskWriter().isNull()); @@ -154,8 +165,8 @@ void MultiDiskAdaptorTest::testResetDiskWriterEntries() CPPUNIT_ASSERT(!entries[1]->getDiskWriter().isNull()); CPPUNIT_ASSERT(!entries[2]->getDiskWriter().isNull()); CPPUNIT_ASSERT(!entries[3]->getDiskWriter().isNull()); - // Because entries[3] spans entries[4] - CPPUNIT_ASSERT(!entries[4]->getDiskWriter().isNull()); + // entries[3] is 0 length. No overrap with entries[4] + CPPUNIT_ASSERT(entries[4]->getDiskWriter().isNull()); CPPUNIT_ASSERT(!entries[5]->getDiskWriter().isNull()); adaptor->closeFile(); @@ -195,6 +206,44 @@ void MultiDiskAdaptorTest::testResetDiskWriterEntries() CPPUNIT_ASSERT(!entries[4]->getDiskWriter().isNull()); CPPUNIT_ASSERT(entries[5]->getDiskWriter().isNull()); + adaptor->closeFile(); + } + { + std::deque > fileEntries = createEntries(); + for(size_t i = 1; i < 6; ++i) { + fileEntries[i]->setRequested(false); + } + adaptor->setFileEntries(fileEntries); + adaptor->openFile(); + std::deque > entries = + adaptor->getDiskWriterEntries(); + CPPUNIT_ASSERT(!entries[0]->getDiskWriter().isNull()); + CPPUNIT_ASSERT(entries[1]->getDiskWriter().isNull()); + CPPUNIT_ASSERT(entries[2]->getDiskWriter().isNull()); + CPPUNIT_ASSERT(entries[3]->getDiskWriter().isNull()); + CPPUNIT_ASSERT(entries[4]->getDiskWriter().isNull()); + CPPUNIT_ASSERT(entries[5]->getDiskWriter().isNull()); + + adaptor->closeFile(); + } + { + std::deque > fileEntries = createEntries(); + for(size_t i = 2; i < 6; ++i) { + fileEntries[i]->setRequested(false); + } + adaptor->setFileEntries(fileEntries); + adaptor->openFile(); + std::deque > entries = + adaptor->getDiskWriterEntries(); + CPPUNIT_ASSERT(!entries[0]->getDiskWriter().isNull()); + CPPUNIT_ASSERT(!entries[1]->getDiskWriter().isNull()); + // entries[1] spans entries[2] + CPPUNIT_ASSERT(!entries[2]->getDiskWriter().isNull()); + CPPUNIT_ASSERT(!entries[2]->needsFileAllocation()); + CPPUNIT_ASSERT(entries[3]->getDiskWriter().isNull()); + CPPUNIT_ASSERT(entries[4]->getDiskWriter().isNull()); + CPPUNIT_ASSERT(entries[5]->getDiskWriter().isNull()); + adaptor->closeFile(); } } @@ -220,9 +269,9 @@ void MultiDiskAdaptorTest::testWriteData() { adaptor->writeData((const unsigned char*)msg.c_str(), msg.size(), 0); adaptor->closeFile(); - CPPUNIT_ASSERT(File("file1.txt").isFile()); + CPPUNIT_ASSERT(File("file0.txt").isFile()); char buf[128]; - readFile("file2.txt", buf, 5); + readFile("file1.txt", buf, 5); buf[5] = '\0'; CPPUNIT_ASSERT_EQUAL(msg, std::string(buf)); @@ -231,10 +280,10 @@ void MultiDiskAdaptorTest::testWriteData() { adaptor->writeData((const unsigned char*)msg2.c_str(), msg2.size(), 5); adaptor->closeFile(); - readFile("file2.txt", buf, 15); + readFile("file1.txt", buf, 15); buf[15] = '\0'; CPPUNIT_ASSERT_EQUAL(std::string("1234567890ABCDE"), std::string(buf)); - readFile("file3.txt", buf, 1); + readFile("file2.txt", buf, 1); buf[1] = '\0'; CPPUNIT_ASSERT_EQUAL(std::string("F"), std::string(buf)); @@ -243,20 +292,20 @@ void MultiDiskAdaptorTest::testWriteData() { adaptor->writeData((const unsigned char*)msg3.c_str(), msg3.size(), 10); adaptor->closeFile(); - readFile("file2.txt", buf, 15); + readFile("file1.txt", buf, 15); buf[15] = '\0'; CPPUNIT_ASSERT_EQUAL(std::string("123456789012345"), std::string(buf)); - readFile("file3.txt", buf, 7); + readFile("file2.txt", buf, 7); buf[7] = '\0'; CPPUNIT_ASSERT_EQUAL(std::string("1234567"), std::string(buf)); - CPPUNIT_ASSERT(File("file4.txt").isFile()); + CPPUNIT_ASSERT(File("file3.txt").isFile()); - readFile("file5.txt", buf, 2); + readFile("file4.txt", buf, 2); buf[2] = '\0'; CPPUNIT_ASSERT_EQUAL(std::string("12"), std::string(buf)); - CPPUNIT_ASSERT(File("file6.txt").isFile()); + CPPUNIT_ASSERT(File("file5.txt").isFile()); } catch(Exception& e) { CPPUNIT_FAIL(e.stackTrace()); diff --git a/test/MultiFileAllocationIteratorTest.cc b/test/MultiFileAllocationIteratorTest.cc index 288df5e2d..1ca3dfb09 100644 --- a/test/MultiFileAllocationIteratorTest.cc +++ b/test/MultiFileAllocationIteratorTest.cc @@ -120,7 +120,7 @@ void MultiFileAllocationIteratorTest::testMakeDiskWriterEntries() // file9 CPPUNIT_ASSERT_EQUAL(prefix+std::string("/file9"), entries[8]->getFilePath(prefix)); - CPPUNIT_ASSERT(entries[8]->needsFileAllocation()); + CPPUNIT_ASSERT(!entries[8]->needsFileAllocation()); CPPUNIT_ASSERT(!entries[8]->getDiskWriter().isNull()); // fileA CPPUNIT_ASSERT_EQUAL(prefix+std::string("/fileA"),