Exemple #1
0
int main()
{
    // Create a vector with 3 default Test objects (-1) and reserved space for 6 objects.
    // Content afterwards: {-1,-1,-1}
    stxxl::swap_vector<Test> vec(3, 6);

    // Push back 10 values from 0 to 9. Internally a swap resize will happen
    // Content afterwards: {-1,-1,-1,0,1,2,3,4,5,6,7,8,9}
    for (unsigned i = 0; i < 10; ++i) {
        Test a(i);
        vec.swap_back(a);
    }

    // Delete the third and the fourth object.
    // Content afterwards: {-1,-1,1,2,3,4,5,6,7,8,9}
    vec.erase(vec.begin() + 2, vec.begin() + 4);

    // Delete the sixth object.
    // Content afterwards: {-1,-1,1,2,3,5,6,7,8,9}
    vec.erase(vec.begin() + 5);

    // Check the values.
    int expected_vals[10] = { -1, -1, 1, 2, 3, 5, 6, 7, 8, 9 };
    die_unequal(vec.size(), 10u);
    for (unsigned i = 0; i < vec.size(); ++i) {
        die_unequal(vec[i].get_i(), expected_vals[i]);
    }

    // std::remove_if would fail because it makes use of copy assignment.
    // We test stxxl's swap_remove_if implementation instead.
    // STL: vec.erase(std::remove_if(vec.begin(), vec.end(), test_eraser()), vec.end());
    vec.erase(stxxl::swap_remove_if(vec.begin(), vec.end(), test_eraser()), vec.end());

    // Check the values.
    int expected_vals2[10] = { 1, 2, 3, 5, 6, 7, 9 };
    die_unequal(vec.size(), 7u);
    for (unsigned i = 0; i < vec.size(); ++i) {
        die_unequal(vec[i].get_i(), expected_vals2[i]);
    }

    // Clear the vector.
    vec.clear();
    die_unless(vec.empty());

    // Resize to 100 and overwrite the last value.
    // Content after resize and overwrite: {...,-1,100}
    // Note: clear() does not overwrite any values in the underlaying array.
    vec.resize(20);
    Test t(11);
    std::swap(vec[19], t);

    // Check the values.
    die_unequal(vec.size(), 20u);
    die_unequal(vec[19].get_i(), 11);

    return EXIT_SUCCESS;
}
bool test_block_cache()
{
    using value_type = std::pair<int, int>;

    constexpr size_t magic1 = 0xc01ddead;

    constexpr unsigned subblock_raw_size = 1024 * 8; // 8KB subblocks
    constexpr unsigned block_size = 128;             // 1MB blocks (=128 subblocks)

    constexpr unsigned num_blocks = 64;              // number of blocks to use for this test
    constexpr unsigned cache_size = 8;               // size of cache in blocks

    using subblock_type = foxxll::typed_block<subblock_raw_size, value_type>;
    using block_type = foxxll::typed_block<block_size* sizeof(subblock_type), subblock_type>;

    constexpr unsigned subblock_size = subblock_type::size;          // size in values

    using bid_type = block_type::bid_type;
    using bid_container_type = std::vector<bid_type>;

    // prepare test: allocate blocks, fill them with values and write to disk
    bid_container_type bids(num_blocks);
    foxxll::block_manager* bm = foxxll::block_manager::get_instance();
    bm->new_blocks(foxxll::striping(), bids.begin(), bids.end());

    block_type* block = new block_type;
    for (unsigned i_block = 0; i_block < num_blocks; i_block++) {
        for (unsigned i_subblock = 0; i_subblock < block_size; i_subblock++) {
            for (unsigned i_value = 0; i_value < subblock_size; i_value++) {
                int value = i_value + i_subblock * subblock_size + i_block * block_size;
                (*block)[i_subblock][i_value] = value_type(value, value);
            }
        }
        foxxll::request_ptr req = block->write(bids[i_block]);
        req->wait();
    }

    std::mt19937 randgen;
    std::uniform_int_distribution<int> distr_num(0, num_blocks - 1);
    std::uniform_int_distribution<int> distr_size(0, block_size - 1);

    // create block_cache
    using cache_type = stxxl::hash_map::block_cache<block_type>;
    cache_type cache(cache_size);

    // load random subblocks and check for values
    int n_runs = cache_size * 10;
    for (int i_run = 0; i_run < n_runs; i_run++) {
        int i_block = distr_num(randgen);
        int i_subblock = distr_size(randgen);

        subblock_type* subblock = cache.get_subblock(bids[i_block], i_subblock);

        int expected = i_block * block_size + i_subblock * subblock_size + 1;
        die_unless((*subblock)[1].first == expected);
    }

    // do the same again but this time with prefetching
    for (int i_run = 0; i_run < n_runs; i_run++) {
        int i_block = distr_num(randgen);
        int i_subblock = distr_size(randgen);

        cache.prefetch_block(bids[i_block]);
        subblock_type* subblock = cache.get_subblock(bids[i_block], i_subblock);
        int expected = i_block * block_size + i_subblock * subblock_size + 1;
        die_unless((*subblock)[1].first == expected);
    }

    // load and modify some subblocks; flush cache and check values
    randgen.seed(magic1);
    for (int i_run = 0; i_run < n_runs; i_run++) {
        int i_block = distr_num(randgen);
        int i_subblock = distr_size(randgen);

        subblock_type* subblock = cache.get_subblock(bids[i_block], i_subblock);

        die_unless(cache.make_dirty(bids[i_block]));
        (*subblock)[1].first = (*subblock)[1].second + 42;
    }

    randgen.seed(magic1);
    for (int i_run = 0; i_run < n_runs; i_run++) {
        int i_block = distr_num(randgen);
        int i_subblock = distr_size(randgen);
        subblock_type* subblock = cache.get_subblock(bids[i_block], i_subblock);

        int expected = i_block * block_size + i_subblock * subblock_size + 1;
        die_unequal((*subblock)[1].first, expected + 42);
    }

    // test retaining
    cache.clear();

    // not yet cached
    die_unless(cache.retain_block(bids[0]) == false);
    cache.prefetch_block(bids[0]);

    // cached, should be retained
    die_unless(cache.retain_block(bids[0]) == true);
    // release again
    die_unless(cache.release_block(bids[0]) == true);
    // retrain-count should be 0, release fails
    die_unless(cache.release_block(bids[0]) == false);

    // cache new block
    subblock_type* kicked_subblock = cache.get_subblock(bids[1], 0);
    // load other blocks, so that kicked_subblock, well, gets kicked
    for (unsigned i = 0; i < cache_size + 5; i++) {
        cache.prefetch_block(bids[i + 3]);
    }
    // load kicked subblock again, should be at a different location
    die_unless(cache.get_subblock(bids[1], 0) != kicked_subblock);

    subblock_type* retained_subblock = cache.get_subblock(bids[1], 0);
    // now retain subblock
    die_unless(cache.retain_block(bids[1]) == true);
    for (unsigned i = 0; i < cache_size + 5; i++) {
        cache.prefetch_block(bids[i + 3]);
    }
    // retained_subblock should not have been kicked
    die_unless(cache.get_subblock(bids[1], 0) == retained_subblock);
    cache.clear();

    // test swapping
    subblock_type* a_subblock = cache.get_subblock(bids[6], 1);
    cache_type cache2(cache_size / 2);
    std::swap(cache, cache2);
    die_unless(cache.size() == cache_size / 2);
    die_unless(cache2.size() == cache_size);
    die_unless(cache2.get_subblock(bids[6], 1) == a_subblock);
    delete block;

    LOG1 << "Passed Block-Cache Test";

    return true;
}
Exemple #3
0
void Connection::SyncRecv(void* out_data, size_t size) {
    net::Buffer msg = RecvNext();
    die_unequal(msg.size(), size);
    char* out_cdata = reinterpret_cast<char*>(out_data);
    std::copy(msg.begin(), msg.end(), out_cdata);
}