//! Testing upper_bound compatibility
//! \param volume Volume
int run_upper_bound_test(size_t volume)
{
    const size_t size = volume / sizeof(value_type);
    STXXL_CHECK(volume > ea_type::block_size);
    STXXL_VARDUMP(size);
    STXXL_CHECK(size > 2000);

    ea_type::pool_type rw_pool;

    std::vector<value_type> v(size);

    {
        stxxl::scoped_print_timer timer("filling vector / internal array", volume);
        for (size_t i = 0; i < size; ++i) {
            v[i] = std::make_pair(i + 1, i + 1);
        }
    }

    ia_type a(v);
    ea_type b(size - 10, &rw_pool);

    {
        stxxl::scoped_print_timer timer("filling external array", volume);

        ea_type::writer_type ea_writer(b, 1);

        ea_type::writer_type::iterator it = ea_writer.begin();

        for (size_t i = 0; i < size - 10; ++i, ++it) {
            *it = std::make_pair(2 * i, 2 * i);
        }

        it = ea_writer.begin();
        for (size_t i = 0; i < size - 10; ++i, ++it) {
            STXXL_CHECK_EQUAL(it->first, 2 * i);
        }
    }

    {
        stxxl::scoped_print_timer timer("running upper_bound", 2 * volume);

        b.hint_next_block();
        b.wait_next_blocks();

        value_type minmax = std::make_pair(2000, 2000);

        ea_type::iterator uba = std::upper_bound(a.begin(), a.end(), minmax, value_comp());
        ea_type::iterator ubb = std::upper_bound(b.begin(), b.end(), minmax, value_comp());

        STXXL_CHECK_EQUAL((uba - 1)->first, 2000);
        STXXL_CHECK_EQUAL((ubb - 1)->first, 2000);
        STXXL_CHECK_EQUAL(uba->first, 2001);
        STXXL_CHECK_EQUAL(ubb->first, 2002);
        STXXL_CHECK_EQUAL(uba.get_index(), 2000);
        STXXL_CHECK_EQUAL(ubb.get_index(), 1001);
    }

    return EXIT_SUCCESS;
}
Ejemplo n.º 2
0
int main(int argc, char* argv[])
{
    if (argc < 2)
    {
        STXXL_MSG("Usage: " << argv[0] << " #log_ins");
        return -1;
    }

    const int log_nins = atoi(argv[1]);
    if (log_nins > 31) {
        STXXL_ERRMSG("This test can't do more than 2^31 operations, you requested 2^" << log_nins);
        return -1;
    }

    btree_type BTree(1024 * 128, 1024 * 128);

    const stxxl::uint64 nins = 1ULL << log_nins;

    stxxl::ran32State = (unsigned int)time(NULL);


    stxxl::vector<int> Values(nins);
    STXXL_MSG("Generating " << nins << " random values");
    stxxl::generate(Values.begin(), Values.end(), rnd_gen(), 4);

    stxxl::vector<int>::const_iterator it = Values.begin();
    STXXL_MSG("Inserting " << nins << " random values into btree");
    for ( ; it != Values.end(); ++it)
        BTree.insert(std::pair<int, double>(*it, double(*it) + 1.0));


    STXXL_MSG("Number of elements in btree: " << BTree.size());

    STXXL_MSG("Searching " << nins << " existing elements");
    stxxl::vector<int>::const_iterator vIt = Values.begin();

    for ( ; vIt != Values.end(); ++vIt)
    {
        btree_type::iterator bIt = BTree.find(*vIt);
        STXXL_CHECK(bIt != BTree.end());
        STXXL_CHECK(bIt->first == *vIt);
    }

    STXXL_MSG("Searching " << nins << " non-existing elements");
    stxxl::vector<int>::const_iterator vIt1 = Values.begin();

    for ( ; vIt1 != Values.end(); ++vIt1)
    {
        btree_type::iterator bIt = BTree.find((*vIt1) + 1);
        STXXL_CHECK(bIt == BTree.end());
    }

    STXXL_MSG("Test passed.");

    return 0;
}
Ejemplo n.º 3
0
void test(stxxl::uint64 data_mem, unsigned memory_to_use)
{
    stxxl::uint64 records_to_sort = data_mem / sizeof(T);
    typedef stxxl::vector<T, 2, stxxl::lru_pager<8>, block_size, alloc_strategy_type> vector_type;

    memory_to_use = stxxl::div_ceil(memory_to_use, vector_type::block_type::raw_size) * vector_type::block_type::raw_size;

    vector_type v(records_to_sort);
    size_t ndisks = stxxl::config::get_instance()->disks_number();
    STXXL_MSG("Sorting " << records_to_sort << " records of size " << sizeof(T));
    STXXL_MSG("Total volume " << (records_to_sort * sizeof(T)) / MB << " MiB");
    STXXL_MSG("Using " << memory_to_use / MB << " MiB");
    STXXL_MSG("Using " << ndisks << " disks");
    STXXL_MSG("Using " << alloc_strategy_type::name() << " allocation strategy ");
    STXXL_MSG("Block size " << vector_type::block_type::raw_size / 1024 << " KiB");

    STXXL_MSG("Filling vector...");
    stxxl::generate(v.begin(), v.end(), stxxl::random_number32_r(), 32);
    //std::generate(v.begin(),v.end(),zero());

    STXXL_MSG("Sorting vector...");

    stxxl::stats_data before(*stxxl::stats::get_instance());

    stxxl::ksort(v.begin(), v.end(), memory_to_use);

    stxxl::stats_data after(*stxxl::stats::get_instance());

    STXXL_MSG("Checking order...");
    STXXL_CHECK(stxxl::is_sorted(v.begin(), v.end()));

    STXXL_MSG("Sorting: " << (after - before));
    STXXL_MSG("Total:   " << *stxxl::stats::get_instance());
}
//! Fills an external array with increasing numbers
void fill(ea_type& ea, size_t index, size_t n)
{
    STXXL_CHECK(n > 0);

    ea_type::writer_type ea_writer(ea);

    size_t i = index;

    STXXL_CHECK_EQUAL(ea_writer.end() - ea_writer.begin(), (ssize_t)n);

    for (ea_type::writer_type::iterator it = ea_writer.begin();
         it != ea_writer.end(); ++it)
    {
        STXXL_CHECK(i < index + n);
        progress("Inserting element", i, n);
        *it = std::make_pair(i + 1, i + 1);
        ++i;
    }

    STXXL_CHECK(i == index + n);
}
void C(btree_type& BTree)
{
    stxxl::uint64 sum = 0;
    stxxl::timer Timer1;
    Timer1.start();
    btree_type::const_iterator it = BTree.begin(), end = BTree.end();
    for ( ; it != end; ++it)
        sum += it->second.data;

    Timer1.stop();
    STXXL_MSG("Scanning with const iterator: " << Timer1.mseconds() << " msec");
    STXXL_CHECK(sum == checksum);
}
void test_size(unsigned int size)
{
    std::cout << "testing parallel_sort_mwms with " << size << " items.\n";

    std::vector<Something> v(size);
    std::less<Something> cmp;

    stxxl::random_number32 rnd;

    for (unsigned int i = 0; i < size; ++i)
        v[i] = rnd();

    stxxl::parallel::parallel_sort_mwms<Stable>(v.begin(), v.end(), cmp, 8);

    STXXL_CHECK(stxxl::is_sorted(v.begin(), v.end(), cmp));
}
//! Fill internal array, remove 3 elements, read and check result.
//! \param volume Volume
int run_internal_array_test(size_t volume)
{
    const size_t size = volume / sizeof(value_type);
    STXXL_VARDUMP(size);
    STXXL_CHECK(size > 3);

    std::vector<value_type> v(size);

    {
        stxxl::scoped_print_timer timer("filling vector / internal array", volume);
        for (size_t i = 0; i < size; ++i) {
            v[i] = std::make_pair(i + 1, i + 1);
        }
    }

    ia_type ia(v);

    {
        stxxl::scoped_print_timer timer("reading and checking the order", volume);

        ia.inc_min();
        ia.inc_min(2);

        typedef ia_type::iterator iterator;
        size_t index = 4;

        // test iterator
        for (iterator it = ia.begin(); it != ia.end(); ++it) {
            STXXL_CHECK_EQUAL(it->first, index++);
        }

        for (size_t i = 3; i < size; ++i) {
            STXXL_CHECK_EQUAL(ia.begin()[i - 3].first, i + 1);
            STXXL_CHECK_EQUAL(ia[i].first, i + 1);
        }

        STXXL_CHECK_EQUAL(index, size + 1);
        STXXL_CHECK_EQUAL(ia.size(), size - 3);
    }

    return EXIT_SUCCESS;
}
void testIO()
{
    const unsigned nblocks = 2;
    stxxl::BIDArray<BLOCK_SIZE> bids(nblocks);
    std::vector<int> disks(nblocks, 2);
    stxxl::request_ptr* reqs = new stxxl::request_ptr[nblocks];
    stxxl::block_manager* bm = stxxl::block_manager::get_instance();
    bm->new_blocks(stxxl::striping(), bids.begin(), bids.end());

    block_type* block = new block_type;
    STXXL_MSG(std::hex);
    STXXL_MSG("Allocated block address    : " << (stxxl::unsigned_type)(block));
    STXXL_MSG("Allocated block address + 1: " << (stxxl::unsigned_type)(block + 1));
    STXXL_MSG(std::dec);
    unsigned i = 0;
    for (i = 0; i < block_type::size; ++i)
    {
        block->elem[i].integer = i;
        //memcpy (block->elem[i].chars, "STXXL", 4);
    }
    for (i = 0; i < nblocks; ++i)
        reqs[i] = block->write(bids[i], my_handler());

    std::cout << "Waiting " << std::endl;
    stxxl::wait_all(reqs, nblocks);

    for (i = 0; i < nblocks; ++i)
    {
        reqs[i] = block->read(bids[i], my_handler());
        reqs[i]->wait();
        for (int j = 0; j < block_type::size; ++j)
        {
            STXXL_CHECK(j == block->elem[j].integer);
        }
    }

    bm->delete_blocks(bids.begin(), bids.end());

    delete[] reqs;
    delete block;
}
Ejemplo n.º 9
0
int main()
{
    typedef stxxl::STACK_GENERATOR<int, stxxl::migrating, stxxl::normal, 4, 4096, std::stack<int>, critical_size>::result migrating_stack_type;

    STXXL_MSG("Starting test.");

    migrating_stack_type my_stack;
    int test_size = 1 * 1024 * 1024 / sizeof(int), i;

    STXXL_MSG("Filling stack.");

    for (i = 0; i < test_size; i++)
    {
        my_stack.push(i);
        STXXL_CHECK(my_stack.top() == i);
        STXXL_CHECK(my_stack.size() == i + 1);
        STXXL_CHECK((my_stack.size() >= critical_size) == my_stack.external());
    }

    STXXL_MSG("Testing swap.");
    // test swap
    migrating_stack_type my_stack2;
    std::swap(my_stack2, my_stack);
    std::swap(my_stack2, my_stack);

    STXXL_MSG("Removing elements from " <<
              (my_stack.external() ? "external" : "internal") << " stack");
    for (i = test_size - 1; i >= 0; i--)
    {
        STXXL_CHECK(my_stack.top() == i);
        STXXL_CHECK(my_stack.size() == i + 1);
        my_stack.pop();
        STXXL_CHECK(my_stack.size() == i);
        STXXL_CHECK(my_stack.external() == (test_size >= int(critical_size)));
    }

    STXXL_MSG("Test passed.");

    return 0;
}
void testStreams()
{
    const unsigned nblocks = 64;
    const unsigned nelements = nblocks * block_type1::size;
    stxxl::BIDArray<BLOCK_SIZE> bids(nblocks);

    stxxl::block_manager* bm = stxxl::block_manager::get_instance();
    bm->new_blocks(stxxl::striping(), bids.begin(), bids.end());
    {
        buf_ostream_type out(bids.begin(), 2);
        for (unsigned i = 0; i < nelements; i++)
            out << i;
    }
    {
        buf_istream_type in(bids.begin(), bids.end(), 2);
        for (unsigned i = 0; i < nelements; i++)
        {
            int value;
            in >> value;
            STXXL_CHECK(value == int(i));
        }
    }
    bm->delete_blocks(bids.begin(), bids.end());
}
Ejemplo n.º 11
0
int main(int argc, char* argv[])
{
    typedef std::vector<std::pair<key_type, data_type> > vector_type;

    STXXL_MSG("Node block size: " << NODE_BLOCK_SIZE << " bytes");
    STXXL_MSG("Leaf block size: " << LEAF_BLOCK_SIZE << " bytes");
    STXXL_MSG("Node max elements: " << NODE_MELEMENTS);
    STXXL_MSG("Leaf max elements: " << LEAF_MELEMENTS);

    stxxl::random_number32 rnd;
    //stxxl::ran32State = 1141225706;
    STXXL_MSG("Init random seed: " << stxxl::ran32State);

    int a = (PERCENT_CLEAR +
             PERCENT_SIZING +
             PERCENT_ERASE_BULK +
             PERCENT_ERASE_KEY +
             PERCENT_ERASE_ITERATOR +
             PERCENT_INSERT_PAIR +
             PERCENT_INSERT_BULK +
             PERCENT_LOWER +
             PERCENT_UPPER +
             PERCENT_FIND +
             PERCENT_ITERATOR);

    STXXL_CHECK(a == 1000);

    if (argc < 2)
    {
        STXXL_MSG("Usage: " << argv[0] << " STEP ");
        STXXL_MSG("Note, that STEP must be > 1000");
        return -1;
    }
    stxxl::uint64 MAX_STEP = atoi(argv[1]);
    STXXL_CHECK(MAX_STEP > 1000);
    std_map_type stdmap;
    xxl_map_type xxlmap(NODE_BLOCK_SIZE * 4, LEAF_BLOCK_SIZE * 3);

    for (stxxl::uint64 i = 0; i < MAX_STEP; i++)
    {
        // ***************************************************
        // A random number is created to determine which kind
        // of operation we will be called.
        // ***************************************************

        long step = rnd() % 1000;
        int percent = 0;

        if (i % (MAX_STEP / 100) == 0)
        {
            STXXL_MSG("Step=" << i << " (" << (unsigned)stdmap.size() << ")");
        }

        // *********************************************************
        // The clear function will be called
        // *********************************************************
        if (step < (percent += PERCENT_CLEAR))
        {
            if ((unsigned)rand() % 1000 < stdmap.size())
            {
                stdmap.clear();
                xxlmap.clear();

                STXXL_CHECK(stdmap.empty());
                STXXL_CHECK(xxlmap.empty());
            }
        }

        // *********************************************************
        // The size function will be called
        // *********************************************************
        else if (step < (percent += PERCENT_SIZING))
        {
            std_map_type::size_type size1 = stdmap.size();
            xxl_map_type::size_type size2 = xxlmap.size();

            STXXL_CHECK(size1 == size2);
        }

        // *********************************************************
        // The erase range function will be called
        // *********************************************************
        else if (step < (percent += PERCENT_ERASE_BULK))
        {
            key_type key1 = rand() % MAX_KEY;
            key_type key2 = rand() % MAX_KEY;

            if (key1 > key2)
            {
                std::swap(key1, key2);
            }

            stdmap.erase(stdmap.lower_bound(key1), stdmap.upper_bound(key2));
            xxlmap.erase(xxlmap.lower_bound(key1), xxlmap.upper_bound(key2));

            STXXL_CHECK(stdmap.size() == xxlmap.size());

            STXXL_CHECK(stdmap.lower_bound(key1) == stdmap.end() ||
                        stdmap.lower_bound(key1) == stdmap.upper_bound(key2));
            STXXL_CHECK(xxlmap.lower_bound(key1) == xxlmap.end() ||
                        xxlmap.lower_bound(key1) == xxlmap.upper_bound(key2));
        }

        // *********************************************************
        // The erase a key function will be called
        // *********************************************************
        else if (step < (percent += PERCENT_ERASE_KEY))
        {
            key_type key = rnd() % MAX_KEY;

            stdmap.erase(key);
            xxlmap.erase(key);

            STXXL_CHECK(stxxl::not_there(stdmap, key));
            STXXL_CHECK(stxxl::not_there(xxlmap, key));
        }

        // *********************************************************
        // The erase function will be called
        // *********************************************************
        else if (step < (percent += PERCENT_ERASE_ITERATOR))
        {
            key_type key = rnd() % MAX_KEY;

            std_map_type::iterator stditer = stdmap.find(key);
            xxl_map_type::iterator xxliter = xxlmap.find(key);

            STXXL_CHECK(stxxl::is_end(stdmap, stditer) == is_end(xxlmap, xxliter));

            if (stditer != stdmap.end())
                stdmap.erase(stditer);

            if (xxliter != xxlmap.end())
                xxlmap.erase(xxliter);


            STXXL_CHECK(stxxl::not_there(stdmap, key));
            STXXL_CHECK(stxxl::not_there(xxlmap, key));
        }

        // *********************************************************
        // The insert function will be called
        // *********************************************************
        else if (step < (percent += PERCENT_INSERT_PAIR))
        {
            key_type key = rnd() % MAX_KEY;
            stdmap.insert(std::pair<key_type, data_type>(key, 2 * key));
            xxlmap.insert(std::pair<key_type, data_type>(key, 2 * key));

            STXXL_CHECK(stxxl::there(stdmap, key, 2 * key));
            STXXL_CHECK(stxxl::there(xxlmap, key, 2 * key));
        }

        // *********************************************************
        // The bulk insert function will be called
        // *********************************************************
        else if (step < (percent += PERCENT_INSERT_BULK))
        {
            unsigned lower = rnd() % MAX_KEY;
            unsigned upper = rnd() % MAX_KEY;
            if (lower > upper)
                std::swap(lower, upper);


            vector_type v2(upper - lower);
            for (unsigned j = 0; j < (unsigned)(upper - lower); j++)
            {
                v2[j].first = lower + j;
                v2[j].second = 2 * v2[j].first;
            }

            stdmap.insert(v2.begin(), v2.end());
            xxlmap.insert(v2.begin(), v2.end());

            for (unsigned i = lower; i < upper; i++)
                STXXL_CHECK(stxxl::there(stdmap, i, 2 * i));

            for (unsigned i = lower; i < upper; i++)
                STXXL_CHECK(stxxl::there(xxlmap, i, 2 * i));
        }

        // *********************************************************
        // The lower_bound function will be called
        // *********************************************************
        else if (step < (percent += PERCENT_LOWER))
        {
            key_type key1 = rand() % MAX_KEY;
            key_type key2 = rand() % MAX_KEY;
            if (key1 > key2)
            {
                std::swap(key1, key2);
            }

            while (key1 < key2)
            {
                std_map_type::iterator stditer = stdmap.lower_bound(key1);
                xxl_map_type::iterator xxliter = xxlmap.lower_bound(key1);

                STXXL_CHECK(stxxl::is_end(stdmap, stditer) == is_end(xxlmap, xxliter));
                if (!stxxl::is_end(stdmap, stditer)) {
                    STXXL_CHECK(stxxl::is_same(*(stditer), *(xxliter)));
                }

                key1++;
            }
        }

        // *********************************************************
        // The upper_bound function will be called
        // *********************************************************
        else if (step < (percent += PERCENT_UPPER))
        {
            key_type key1 = rand() % MAX_KEY;
            key_type key2 = rand() % MAX_KEY;
            if (key1 > key2)
            {
                std::swap(key1, key2);
            }

            while (key1 < key2)
            {
                std_map_type::iterator stditer = stdmap.upper_bound(key1);
                xxl_map_type::iterator xxliter = xxlmap.upper_bound(key1);

                STXXL_CHECK(stxxl::is_end(stdmap, stditer) == is_end(xxlmap, xxliter));
                if (!stxxl::is_end(stdmap, stditer)) {
                    STXXL_CHECK(stxxl::is_same(*(stditer), *(xxliter)));
                }

                key1++;
            }
        }

        // *********************************************************
        // The find function will be called
        // *********************************************************
        else if (step < (percent += PERCENT_FIND))
        {
            key_type key1 = rand() % MAX_KEY;
            key_type key2 = rand() % MAX_KEY;
            if (key1 > key2)
            {
                std::swap(key1, key2);
            }

            while (key1 < key2)
            {
                std_map_type::iterator stditer = stdmap.find(key1);
                xxl_map_type::iterator xxliter = xxlmap.find(key1);

                STXXL_CHECK(stxxl::is_end(stdmap, stditer) == stxxl::is_end(xxlmap, xxliter));
                if (!stxxl::is_end(stdmap, stditer)) {
                    STXXL_CHECK(stxxl::is_same(*(stditer), *(xxliter)));
                }

                key1++;
            }
        }

        // *********************************************************
        // The iterate functions will be called
        // *********************************************************
        else if (step < (percent += PERCENT_ITERATOR))
        {
            std_map_type::const_iterator siter1 = stdmap.begin();
            xxl_map_type::const_iterator xiter1 = xxlmap.begin();

            std_map_type::const_iterator siter2 = siter1;
            xxl_map_type::const_iterator xiter2 = xiter1;

            while (siter1 != stdmap.end())
            {
                STXXL_CHECK(xiter1 != xxlmap.end());
                STXXL_CHECK(stxxl::is_same(*(siter1++), *(xiter1++)));
                if (siter1 != stdmap.end()) {
                    STXXL_CHECK(!stxxl::is_same(*siter1, *siter2));
                }
                if (xiter1 != xxlmap.end()) {
                    STXXL_CHECK(!stxxl::is_same(*xiter1, *xiter2));
                }
            }
            STXXL_CHECK(xiter1 == xxlmap.end());
            STXXL_CHECK(siter2 == stdmap.begin());
            STXXL_CHECK(xiter2 == xxlmap.begin());
        }
    }
    return 0;
}
int main()
{
    unsigned num_cols = 10000;
    unsigned num_rows = 5000;

    // buffers for streamify and materialize,
    // block size matches the block size of the input/output vector
    size_t numbuffers = 2 * stxxl::config::get_instance()->disks_number();

    // RAM to be used for sorting (in bytes)
    size_t memory_for_sorting = 1 << 28;

    ///////////////////////////////////////////////////////////////////////

    typedef stxxl::VECTOR_GENERATOR<unsigned>::result array_type;

    array_type input(num_rows * num_cols);
    array_type output(num_cols * num_rows);

    // fill the input array with some values
    for (unsigned i = 0; i < num_rows * num_cols; ++i)
        input[i] = i;

    std::cout << "Before transpose:" << std::endl;
    dump_upper_left(input, num_rows, num_cols, 10, 10);

    stxxl::stats_data stats_before(*stxxl::stats::get_instance());

    // HERE streaming part begins (streamifying)
    // create input stream
    typedef stxxl::stream::streamify_traits<array_type::iterator>::stream_type input_stream_type;
    input_stream_type input_stream = stxxl::stream::streamify(input.begin(), input.end(), numbuffers);

    // create stream of destination indices
    typedef streamop_matrix_transpose destination_index_stream_type;
    destination_index_stream_type destination_index_stream(num_cols, num_rows);

    // create tuple stream: (key, value)
    typedef stxxl::stream::make_tuple<destination_index_stream_type, input_stream_type> tuple_stream_type;
    tuple_stream_type tuple_stream(destination_index_stream, input_stream);

    // sort tuples by first entry (key)
    typedef cmp_tuple_first<tuple_stream_type::value_type> cmp_type;
    typedef stxxl::stream::sort<tuple_stream_type, cmp_type> sorted_tuple_stream_type;
    sorted_tuple_stream_type sorted_tuple_stream(tuple_stream, cmp_type(), memory_for_sorting);

    // discard the key we used for sorting, keep second entry of the tuple only (value)
    typedef stxxl::stream::choose<sorted_tuple_stream_type, 2> sorted_element_stream_type;
    sorted_element_stream_type sorted_element_stream(sorted_tuple_stream);

    // HERE streaming part ends (materializing)
    array_type::iterator o = stxxl::stream::materialize(sorted_element_stream, output.begin(), output.end(), numbuffers);
    STXXL_CHECK(o == output.end());
    STXXL_CHECK(sorted_element_stream.empty());

    stxxl::stats_data stats_after(*stxxl::stats::get_instance());

    std::cout << "After transpose:" << std::endl;
    dump_upper_left(output, num_cols, num_rows, 10, 10);

    std::cout << "I/O stats (streaming part only!)" << std::endl << (stats_after - stats_before);

    return 0;
}
Ejemplo n.º 13
0
int main(int argc, char* argv[])
{
    if (argc < 2)
    {
        STXXL_MSG("Usage: " << argv[0] << " #ins");
        return -1;
    }

    btree_type BTree1(node_cache_size, leaf_cache_size);

    unsigned nins = atoi(argv[1]);
    if (nins < 100)
        nins = 100;


    stxxl::random_number32 rnd;

    // .begin() .end() test
    BTree1[10] = 100.;
    btree_type::iterator begin = BTree1.begin();
    btree_type::iterator end = BTree1.end();
    STXXL_CHECK(begin == BTree1.begin());
    BTree1[5] = 50.;
    btree_type::iterator nbegin = BTree1.begin();
    btree_type::iterator nend = BTree1.end();
    STXXL_CHECK(nbegin == BTree1.begin());
    STXXL_CHECK(begin != nbegin);
    STXXL_CHECK(end == nend);
    STXXL_CHECK(begin != end);
    STXXL_CHECK(nbegin != end);
    STXXL_CHECK(begin->first == 10);
    STXXL_CHECK(begin->second == 100);
    STXXL_CHECK(nbegin->first == 5);
    STXXL_CHECK(nbegin->second == 50);

    BTree1[10] = 200.;
    STXXL_CHECK(begin->second == 200.);

    btree_type::iterator it = BTree1.find(5);
    STXXL_CHECK(it != BTree1.end());
    STXXL_CHECK(it->first == 5);
    STXXL_CHECK(it->second == 50.);
    it = BTree1.find(6);
    STXXL_CHECK(it == BTree1.end());
    it = BTree1.find(1000);
    STXXL_CHECK(it == BTree1.end());


    stxxl::unsigned_type f = BTree1.erase(5);
    STXXL_CHECK(f == 1);
    f = BTree1.erase(6);
    STXXL_CHECK(f == 0);
    f = BTree1.erase(5);
    STXXL_CHECK(f == 0);

    STXXL_CHECK(BTree1.count(10) == 1);
    STXXL_CHECK(BTree1.count(5) == 0);

    it = BTree1.insert(BTree1.begin(), std::pair<int, double>(7, 70.));
    STXXL_CHECK(it->second == 70.);
    STXXL_CHECK(BTree1.size() == 2);
    it = BTree1.insert(BTree1.begin(), std::pair<int, double>(10, 300.));
    STXXL_CHECK(it->second == 200.);
    STXXL_CHECK(BTree1.size() == 2);

    // test lower_bound

    it = BTree1.lower_bound(6);
    STXXL_CHECK(it != BTree1.end());
    STXXL_CHECK(it->first == 7);

    it = BTree1.lower_bound(7);
    STXXL_CHECK(it != BTree1.end());
    STXXL_CHECK(it->first == 7);

    it = BTree1.lower_bound(8);
    STXXL_CHECK(it != BTree1.end());
    STXXL_CHECK(it->first == 10);

    it = BTree1.lower_bound(11);
    STXXL_CHECK(it == BTree1.end());

    // test upper_bound

    it = BTree1.upper_bound(6);
    STXXL_CHECK(it != BTree1.end());
    STXXL_CHECK(it->first == 7);

    it = BTree1.upper_bound(7);
    STXXL_CHECK(it != BTree1.end());
    STXXL_CHECK(it->first == 10);

    it = BTree1.upper_bound(8);
    STXXL_CHECK(it != BTree1.end());
    STXXL_CHECK(it->first == 10);

    it = BTree1.upper_bound(10);
    STXXL_CHECK(it == BTree1.end());

    it = BTree1.upper_bound(11);
    STXXL_CHECK(it == BTree1.end());

    // test equal_range

    std::pair<btree_type::iterator, btree_type::iterator> it_pair = BTree1.equal_range(1);
    STXXL_CHECK(BTree1.find(7) == it_pair.first);
    STXXL_CHECK(BTree1.find(7) == it_pair.second);

    it_pair = BTree1.equal_range(7);
    STXXL_CHECK(BTree1.find(7) == it_pair.first);
    STXXL_CHECK(BTree1.find(10) == it_pair.second);

    it_pair = BTree1.equal_range(8);
    STXXL_CHECK(BTree1.find(10) == it_pair.first);
    STXXL_CHECK(BTree1.find(10) == it_pair.second);

    it_pair = BTree1.equal_range(10);
    STXXL_CHECK(BTree1.find(10) == it_pair.first);
    STXXL_CHECK(BTree1.end() == it_pair.second);

    it_pair = BTree1.equal_range(11);
    STXXL_CHECK(BTree1.end() == it_pair.first);
    STXXL_CHECK(BTree1.end() == it_pair.second);

    //

    it = BTree1.lower_bound(0);
    BTree1.erase(it);
    STXXL_CHECK(BTree1.size() == 1);

    BTree1.clear();
    STXXL_CHECK(BTree1.size() == 0);

    for (unsigned int i = 0; i < nins / 2; ++i)
    {
        BTree1[rnd() % nins] = 10.1;
    }
    STXXL_MSG("Size of map: " << BTree1.size());


    BTree1.clear();

    for (unsigned int i = 0; i < nins / 2; ++i)
    {
        BTree1[rnd() % nins] = 10.1;
    }

    STXXL_MSG("Size of map: " << BTree1.size());

    btree_type BTree2(comp_type(), node_cache_size, leaf_cache_size);

    STXXL_MSG("Construction of BTree3 from BTree1 that has " << BTree1.size() << " elements");
    btree_type BTree3(BTree1.begin(), BTree1.end(), comp_type(), node_cache_size, leaf_cache_size);

    STXXL_CHECK(BTree3 == BTree1);

    STXXL_MSG("Bulk construction of BTree4 from BTree1 that has " << BTree1.size() << " elements");
    btree_type BTree4(BTree1.begin(), BTree1.end(), comp_type(), node_cache_size, leaf_cache_size, true);

    STXXL_MSG("Size of BTree1: " << BTree1.size());
    STXXL_MSG("Size of BTree4: " << BTree4.size());

    STXXL_CHECK(BTree4 == BTree1);
    STXXL_CHECK(BTree3 == BTree4);

    BTree4.begin()->second = 0;
    STXXL_CHECK(BTree3 != BTree4);
    STXXL_CHECK(BTree4 < BTree3);

    BTree4.begin()->second = 1000;
    STXXL_CHECK(BTree4 > BTree3);

    STXXL_CHECK(BTree3 != BTree4);

    it = BTree4.begin();
    ++it;
    STXXL_MSG("Size of Btree4 before erase: " << BTree4.size());
    BTree4.erase(it, BTree4.end());
    STXXL_MSG("Size of Btree4 after erase: " << BTree4.size());
    STXXL_CHECK(BTree4.size() == 1);


    STXXL_MSG("Size of Btree1 before erase: " << BTree1.size());
    BTree1.erase(BTree1.begin(), BTree1.end());
    STXXL_MSG("Size of Btree1 after erase: " << BTree1.size());
    STXXL_CHECK(BTree1.empty());

    // a copy of BTree3
    btree_type BTree5(BTree3.begin(), BTree3.end(), comp_type(), node_cache_size, leaf_cache_size, true);
    STXXL_CHECK(BTree5 == BTree3);

    btree_type::iterator b3 = BTree3.begin();
    btree_type::iterator b4 = BTree4.begin();
    btree_type::iterator e3 = BTree3.end();
    btree_type::iterator e4 = BTree4.end();

    STXXL_MSG("Testing swapping operation (std::swap)");
    std::swap(BTree4, BTree3);
    STXXL_CHECK(b3 == BTree4.begin());
    STXXL_CHECK(b4 == BTree3.begin());
    STXXL_CHECK(e3 == BTree4.end());
    STXXL_CHECK(e4 == BTree3.end());

    STXXL_CHECK(BTree5 == BTree4);
    STXXL_CHECK(BTree5 != BTree3);

    btree_type::const_iterator cb = BTree3.begin();
    btree_type::const_iterator ce = BTree3.end();
    const btree_type& CBTree3 = BTree3;
    cb = CBTree3.begin();
    STXXL_CHECK(!(b3 == cb));
    STXXL_CHECK((b3 != cb));
    STXXL_CHECK(!(cb == b3));
    STXXL_CHECK((cb != b3));
    ce = CBTree3.end();
    btree_type::const_iterator cit = CBTree3.find(0);
    cit = CBTree3.lower_bound(0);
    cit = CBTree3.upper_bound(0);

    std::pair<btree_type::const_iterator, btree_type::const_iterator> cit_pair = CBTree3.equal_range(1);

    STXXL_CHECK(CBTree3.max_size() >= CBTree3.size());


    CBTree3.key_comp();
    CBTree3.value_comp();

    double sum = 0.0;

    STXXL_MSG(*stxxl::stats::get_instance());

    stxxl::timer Timer2;
    Timer2.start();
    cit = BTree5.begin();
    for ( ; cit != BTree5.end(); ++cit)
        sum += cit->second;

    Timer2.stop();
    STXXL_MSG("Scanning with const iterator: " << Timer2.mseconds() << " msec");

    STXXL_MSG(*stxxl::stats::get_instance());

    stxxl::timer Timer1;
    Timer1.start();
    it = BTree5.begin();
    for ( ; it != BTree5.end(); ++it)
        sum += it->second;

    Timer1.stop();
    STXXL_MSG("Scanning with non const iterator: " << Timer1.mseconds() << " msec");

    STXXL_MSG(*stxxl::stats::get_instance());

    BTree5.disable_prefetching();
    BTree5.enable_prefetching();
    BTree5.prefetching_enabled();
    STXXL_CHECK(BTree5.prefetching_enabled());

    STXXL_MSG("All tests passed successfully");

    return 0;
}
//! Run external array test.
//! Testing...
//!     - iterators
//!     - request_write_buffer()
//!     - random access
//!     - remove()
//!     - get_current_max()
//!     - request_further_block()
//!     - wait()
//!     - sizes
//!
//! \param volume Volume
//! \param numwbs Number of write buffer blocks for each external array.
int run_external_array_test(size_t volume)
{
    const size_t block_size = ea_type::block_size;
    const size_t N = volume / sizeof(value_type);
    const size_t num_blocks = stxxl::div_ceil(N, block_size);

    STXXL_VARDUMP(block_size);
    STXXL_VARDUMP(N);
    STXXL_VARDUMP(num_blocks);

    ea_type::pool_type rw_pool(6 * num_blocks, 4);
    ea_type ea(N, &rw_pool);

    {
        stxxl::scoped_print_timer timer("filling", volume);

        STXXL_CHECK(N >= 10 + 355 + 2 * block_size);

        fill(ea, 0, N);
    }

    {
        stxxl::scoped_print_timer timer("reading and checking", volume);

        STXXL_CHECK(N > 5 * block_size + 876);
        STXXL_CHECK(block_size > 34);

        STXXL_CHECK_EQUAL(ea.size(), N);

        // fetch first block
        ea.hint_next_block();
        ea.wait_next_blocks();

        STXXL_CHECK(ea.buffer_size() > 7);

        // Testing iterator...

        for (unsigned i = 0; i < 7; ++i) {
            STXXL_CHECK_EQUAL((ea.begin() + i)->first, i + 1);
        }

        STXXL_CHECK(ea.buffer_size() > 12);

        // Testing random access...

        for (unsigned i = 7; i < 12; ++i) {
            STXXL_CHECK_EQUAL(ea[i].first, i + 1);
        }

        // Testing remove...

        ea.remove_items(33);

        STXXL_CHECK_EQUAL(ea[33].first, 34);
        STXXL_CHECK_EQUAL(ea.begin().get_index(), 33);
        STXXL_CHECK_EQUAL(ea.begin()->first, 34);

        // Testing get_next_block_min()...

        unsigned maxround = 0;

        while (ea.get_next_block_min().first < 5 * block_size + 876) {
            switch (maxround) {
            case 0: STXXL_CHECK_EQUAL(ea.get_next_block_min().first, 131073);
                break;
            case 1: STXXL_CHECK_EQUAL(ea.get_next_block_min().first, 262145);
                break;
            case 2: STXXL_CHECK_EQUAL(ea.get_next_block_min().first, 393217);
                break;
            case 3: STXXL_CHECK_EQUAL(ea.get_next_block_min().first, 524289);
                break;
            case 4: STXXL_CHECK_EQUAL(ea.get_next_block_min().first, 655361);
                break;
            }

            ea.hint_next_block();
            ea.wait_next_blocks();
            ++maxround;
        }

        // Testing request_further_block() (called above)...

        STXXL_CHECK((ea.end() - 1)->first >= 5 * block_size + 876);

        size_t index = 33;

        for (ea_type::iterator it = ea.begin(); it != ea.end(); ++it) {
            progress("Extracting element", index, N);
            STXXL_CHECK_EQUAL(it.get_index(), index);
            STXXL_CHECK_EQUAL(it->first, index + 1);
            ++index;
        }

        ea.remove_items(ea.buffer_size());
        STXXL_CHECK(ea.buffer_size() == 0);

        // Extracting the rest...

        size_t round = 0;

        while (!ea.empty()) {
            if (ea.has_em_data() && round % 2 == 0) {
                ea.hint_next_block();
                ea.wait_next_blocks();
            }

            STXXL_CHECK((size_t)(ea.end() - ea.begin()) == ea.buffer_size());

            for (ea_type::iterator it = ea.begin(); it != ea.end(); ++it) {
                progress("Extracting element", index, N);
                STXXL_CHECK_EQUAL(it.get_index(), index);
                STXXL_CHECK_EQUAL(it->first, index + 1);
                ++index;
            }

            //std::cout << ea.buffer_size() << " - " << round << "\n";

            if (round % 3 == 0 && ea.buffer_size() > 0) {
                // remove all items but one
                ea.remove_items(ea.buffer_size() - 1);
                index--;
            }
            else {
                ea.remove_items(ea.buffer_size());
            }

            ++round;
        }
    }

    return EXIT_SUCCESS;
}