Commit 46c542ee authored by Bradley C. Kuszmaul's avatar Bradley C. Kuszmaul Committed by Yoni Fogel

[t:3218] Incorporate changes from review. Refs #3218

git-svn-id: file:///svn/toku/tokudb@28256 c7de825b-a66e-492c-adef-691d508d4ae1
parent 793a548d
......@@ -90,19 +90,20 @@ grow_blocks_array (BLOCK_ALLOCATOR ba) {
grow_blocks_array_by(ba, 1);
}
static void
merge_blockpairs_into (u_int64_t d, struct block_allocator_blockpair dst[/*d*/],
u_int64_t s, struct block_allocator_blockpair src[/*s*/])
void
block_allocator_merge_blockpairs_into (u_int64_t d, struct block_allocator_blockpair dst[/*d*/],
u_int64_t s, const struct block_allocator_blockpair src[/*s*/])
// Effect: Merge dst[d] and src[s] into dst[d+s], merging in place.
// Initially dst and src hold sorted arrays (sorted by increasing offset).
// Finally dst contains all d+s elements sorted in order.
// dst must be large enough.
// Requires no overlaps.
// This is not static so that we can write a unit test for it. (Otherwise, this is static only to be used from inside the block allocator)
{
u_int64_t tail = d+s;
while (d>0 && s>0) {
struct block_allocator_blockpair *dp = &dst[d-1];
struct block_allocator_blockpair *sp = &src[s-1];
struct block_allocator_blockpair const *sp = &src[s-1];
struct block_allocator_blockpair *tp = &dst[tail-1];
assert(tail>0);
if (dp->offset > sp->offset) {
......@@ -123,7 +124,7 @@ merge_blockpairs_into (u_int64_t d, struct block_allocator_blockpair dst[/*d*/],
tail--;
}
while (s>0) {
struct block_allocator_blockpair *sp = &src[s-1];
struct block_allocator_blockpair const *sp = &src[s-1];
struct block_allocator_blockpair *tp = &dst[tail-1];
*tp = *sp;
s--;
......@@ -141,7 +142,8 @@ compare_blockpairs (const void *av, const void *bv) {
}
void
block_allocator_alloc_blocks_at (BLOCK_ALLOCATOR ba, u_int64_t n_blocks, struct block_allocator_blockpair *pairs)
block_allocator_alloc_blocks_at (BLOCK_ALLOCATOR ba, u_int64_t n_blocks, struct block_allocator_blockpair pairs[/*n_blocks*/])
// See the documentation in block_allocator.h
{
VALIDATE(ba);
qsort(pairs, n_blocks, sizeof(*pairs), compare_blockpairs);
......@@ -151,7 +153,7 @@ block_allocator_alloc_blocks_at (BLOCK_ALLOCATOR ba, u_int64_t n_blocks, struct
ba->n_bytes_in_use += pairs[i].size;
}
grow_blocks_array_by(ba, n_blocks);
merge_blockpairs_into(ba->n_blocks, ba->blocks_array,
block_allocator_merge_blockpairs_into(ba->n_blocks, ba->blocks_array,
n_blocks, pairs);
ba->n_blocks += n_blocks;
VALIDATE(ba);
......
......@@ -80,6 +80,7 @@ void
block_allocator_alloc_blocks_at (BLOCK_ALLOCATOR ba, u_int64_t n_blocks, struct block_allocator_blockpair *pairs);
// Effect: Take pairs in any order, and add them all, as if we did block_allocator_alloc_block() on each pair.
// This should run in time O(N + M log M) where N is the number of blocks in ba, and M is the number of new blocks.
// Modifies: pairs (sorts them).
void
block_allocator_alloc_block (BLOCK_ALLOCATOR ba, u_int64_t size, u_int64_t *offset);
......@@ -137,6 +138,11 @@ block_allocator_get_unused_statistics(BLOCK_ALLOCATOR ba, TOKU_DB_FRAGMENTATION
//Requires: report->data_bytes is filled in
//Requires: report->checkpoint_bytes_additional is filled in
void
block_allocator_merge_blockpairs_into (u_int64_t d, struct block_allocator_blockpair dst[/*d*/],
u_int64_t s, const struct block_allocator_blockpair src[/*s*/]);
// This is exposed so it can be tested.
#if defined(__cplusplus) || defined(__cilkplusplus)
};
#endif
......
/* -*- mode: C; c-basic-offset: 4 -*- */
#ident "Copyright (c) 2009-2010 Tokutek Inc. All rights reserved."
#include "../block_allocator.h"
#include <memory.h>
#include <assert.h>
// Test the merger.
#if 0
static void
print_array (u_int64_t n, const struct block_allocator_blockpair a[/*n*/]) {
printf("{");
for (u_int64_t i=0; i<n; i++) printf(" %016lx", (long)a[i].offset);
printf("}\n");
}
#endif
static int
compare_blockpairs (const void *av, const void *bv) {
const struct block_allocator_blockpair *a = av;
const struct block_allocator_blockpair *b = bv;
if (a->offset < b->offset) return -1;
if (a->offset > b->offset) return +1;
return 0;
}
static void
test_merge (u_int64_t an, const struct block_allocator_blockpair a[/*an*/],
u_int64_t bn, const struct block_allocator_blockpair b[/*bn*/]) {
//printf("a:"); print_array(an, a);
//printf("b:"); print_array(bn, b);
struct block_allocator_blockpair *MALLOC_N(an+bn, q);
struct block_allocator_blockpair *MALLOC_N(an+bn, m);
if (q==0 || m==0) {
fprintf(stderr, "malloc failed, continuing\n");
goto malloc_failed;
}
for (u_int64_t i=0; i<an; i++) {
q[i] = m[i] = a[i];
}
for (u_int64_t i=0; i<bn; i++) {
q[an+i] = b[i];
}
qsort(q, an+bn, sizeof(*q), compare_blockpairs);
//printf("q:"); print_array(an+bn, q);
block_allocator_merge_blockpairs_into(an, m, bn, b);
//printf("m:"); print_array(an+bn, m);
for (u_int64_t i=0; i<an+bn; i++) {
assert(q[i].offset == m[i].offset);
}
malloc_failed:
toku_free(q);
toku_free(m);
}
static void
test_merge_n_m (u_int64_t n, u_int64_t m)
{
struct block_allocator_blockpair *MALLOC_N(n, na);
struct block_allocator_blockpair *MALLOC_N(m, ma);
if (na==0 || ma==0) {
fprintf(stderr, "malloc failed, continuing\n");
goto malloc_failed;
}
for (u_int64_t i=0; i<n; i++) {
na[i].offset = (((u_int64_t)random())<<32) + random();
}
for (u_int64_t i=0; i<m; i++) {
ma[i].offset = (((u_int64_t)random())<<32) + random();
}
qsort(na, n, sizeof(*na), compare_blockpairs);
qsort(ma, m, sizeof(*ma), compare_blockpairs);
test_merge(n, na, m, ma);
malloc_failed:
toku_free(na);
toku_free(ma);
}
int main (int argc __attribute__((__unused__)), char *argv[] __attribute__((__unused__))) {
test_merge_n_m(4, 4);
test_merge_n_m(16, 16);
test_merge_n_m(0, 100);
test_merge_n_m(100, 0);
// Cannot run this on my laptop
u_int64_t too_big = 1024LL * 1024LL * 1024LL * 2;
test_merge_n_m(too_big, too_big);
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment