inline typename ListType::Iterator randomFragment(const ListType& src) { if( src.empty() ) return src.end(); typename ListType::ConstIterator result = src.begin(); ::std::advance( result, ::std::rand() % src.size() ); return result; }
typename ListType::FragmentType selectBlock(const ListType& src, typename ListType::FSizeType blockSize, const AvailableType* available ) { typedef typename ListType::FragmentType FragmentType; typedef typename ListType::FSizeType FSizeType; typedef typename ListType::ConstIterator ConstIterator; if( src.empty() ) return FragmentType( 0, ::std::numeric_limits< FSizeType >::max() ); ::std::deque< FSizeType > blocks; for( ConstIterator selectIterator = src.begin(); selectIterator != src.end(); ++selectIterator ) { FSizeType blockBegin = selectIterator->begin() / blockSize; FSizeType blockEnd = ( selectIterator->end() - 1 ) / blockSize; if ( selectIterator->begin() % blockSize ) { // the start of a block is complete, but part is missing if ( !available || available[ blockBegin ] ) { return FragmentType( selectIterator->begin(), ::std::min( selectIterator->end(), blockSize * ( blockBegin + 1 ) ) ); } ++blockBegin; } if ( blockBegin <= blockEnd && selectIterator->end() % blockSize && selectIterator->end() < src.limit() ) { // the end of a block is complete, but part is missing if ( !available || available[ blockEnd ] ) { return FragmentType( blockEnd * blockSize, selectIterator->end() ); } --blockEnd; } // this fragment contains one or more aligned empty blocks if( blockEnd != ~0ULL ) for( ; blockBegin <= blockEnd; ++blockBegin ) { if( !available || available[ blockBegin ] ) { blocks.push_back( blockBegin ); } } } if( blocks.empty() ) return FragmentType( 0, ::std::numeric_limits< FSizeType >::max() ); FSizeType blockBegin = blocks[ ::std::rand() % blocks.size() ] * blockSize; return FragmentType( blockBegin, ::std::min( blockBegin + blockSize, src.limit() ) ); }