TEST(TestLocatedBlocks, TestFindBlock) { // repro GPSQL-3051 LocatedBlocksImpl *lbs = new LocatedBlocksImpl(); // one element in blocks lbs->setFileLength(10*1024+500); LocatedBlock *blk = new LocatedBlock(10240); blk->setNumBytes(500); lbs->getBlocks().push_back(*blk); const LocatedBlock *lb = lbs->findBlock(10239); EXPECT_TRUE(lb == NULL); lb = lbs->findBlock(10240); EXPECT_TRUE(lb->getOffset() == blk->getOffset()); EXPECT_TRUE(lb->getNumBytes() == blk->getNumBytes()); lbs->getBlocks().clear(); // 3 elements in blocks lbs->setFileLength(1024*2+100); LocatedBlock *blk1 = new LocatedBlock(0); blk1->setNumBytes(1024); LocatedBlock *blk2 = new LocatedBlock(1024); blk2->setNumBytes(1024); LocatedBlock *blk3 = new LocatedBlock(2048); blk3->setNumBytes(100); lbs->getBlocks().push_back(*blk1); lbs->getBlocks().push_back(*blk2); lbs->getBlocks().push_back(*blk3); lb = lbs->findBlock(-100); EXPECT_TRUE(lb == NULL); lb = lbs->findBlock(0); EXPECT_TRUE(lb->getOffset() == 0); lb = lbs->findBlock(100); EXPECT_TRUE(lb->getOffset() == 0); lb = lbs->findBlock(1023); EXPECT_TRUE(lb->getOffset() == 0); lb = lbs->findBlock(1024); EXPECT_TRUE(lb->getOffset() == 1024); lb = lbs->findBlock(1024+100); EXPECT_TRUE(lb->getOffset() == 1024); lb = lbs->findBlock(2047); EXPECT_TRUE(lb->getOffset() == 1024); lb = lbs->findBlock(2047); EXPECT_TRUE(lb->getOffset() == 1024); lb = lbs->findBlock(2048); EXPECT_TRUE(lb->getOffset() == 2048); lb = lbs->findBlock(2048+100-1); EXPECT_TRUE(lb->getOffset() == 2048); lb = lbs->findBlock(2048+100); EXPECT_TRUE(lb == NULL); lb = lbs->findBlock(2048+1000); EXPECT_TRUE(lb == NULL); delete blk; delete blk1; delete blk2; delete blk3; delete lbs; }
const LocatedBlock * LocatedBlocksImpl::findBlock(int64_t position) { if (position < fileLength) { LocatedBlock target(position); std::vector<LocatedBlock>::iterator bound; if (blocks.empty() || position < blocks.begin()->getOffset()) { return NULL; } /* * bound is first block which start offset is larger than * or equal to position */ bound = std::lower_bound(blocks.begin(), blocks.end(), target, std::less<LocatedBlock>()); assert(bound == blocks.end() || bound->getOffset() >= position); LocatedBlock * retval = NULL; if (bound == blocks.end()) { retval = &blocks.back(); } else if (bound->getOffset() > position) { assert(bound != blocks.begin()); --bound; retval = &(*bound); } else { retval = &(*bound); } if (position < retval->getOffset() || position >= retval->getOffset() + retval->getNumBytes()) { return NULL; } return retval; } else { return lastBlock.get(); } }