int main(int argc, char* argv[])
{
    size_t nins;
    {
        die_verbose_if(argc < 2, "Usage: " << argv[0] << " #log_ins");
        const auto log_nins = foxxll::atoi64(argv[1]);
        die_verbose_if(log_nins > 31, "This test can't do more than 2^31 operations, you requested 2^" << log_nins);
        nins = 1ULL << log_nins;
    }

    // prepare random unique keys
    stxxl::vector<key_type> values(nins);
    std::mt19937_64 randgen;
    {
        random_fill_vector(values, randgen);

        LOG1 << "Sorting the random values";
        stxxl::sort(values.begin(), values.end(), comp_type(), 128 * 1024 * 1024);

        LOG1 << "Deleting duplicate values";
        {
            auto new_end = std::unique(values.begin(), values.end());
            values.resize(std::distance(values.begin(), new_end));
        }

        LOG1 << "Randomly permute input values";
        stxxl::shuffle(values.begin(), values.end(), randgen, 128 * 1024 * 1024);
    }

    btree_type BTree(1024 * 128, 1024 * 128);
    {
        LOG1 << "Inserting " << values.size() << " random values into btree";
        for (auto it = values.cbegin(); it != values.cend(); ++it)
            BTree.insert({ *it, static_cast<payload_type>(*it + 1) });
        LOG1 << "Number of elements in btree: " << BTree.size();
    }

    {
        LOG1 << "Searching " << values.size() << " existing elements and erasing them";
        for (auto it = values.cbegin(); it != values.cend(); ++it) {
            auto bIt = BTree.find(*it);

            die_unless(bIt != BTree.end());
            // erasing non-existent element
            die_unless(BTree.erase((*it) + 1) == 0);
            // erasing existing element
            die_unless(BTree.erase(*it) == 1);
            // checking it is not there
            die_unless(BTree.find(*it) == BTree.end());
            // trying to erase it again
            die_unless(BTree.erase(*it) == 0);
        }
    }

    die_unless(BTree.empty());

    LOG1 << "Test passed.";

    return 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;
}