mirror of
https://github.com/MariaDB/server.git
synced 2025-01-22 06:44:16 +01:00
[t:3218] Incorporate changes from review. Refs #3218
git-svn-id: file:///svn/toku/tokudb@28256 c7de825b-a66e-492c-adef-691d508d4ae1
This commit is contained in:
parent
7635187648
commit
6b945fa29e
3 changed files with 106 additions and 11 deletions
|
@ -90,20 +90,21 @@ 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 *tp = &dst[tail-1];
|
||||
struct block_allocator_blockpair *dp = &dst[d-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) {
|
||||
*tp = *dp;
|
||||
|
@ -123,8 +124,8 @@ 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 *tp = &dst[tail-1];
|
||||
struct block_allocator_blockpair const *sp = &src[s-1];
|
||||
struct block_allocator_blockpair *tp = &dst[tail-1];
|
||||
*tp = *sp;
|
||||
s--;
|
||||
tail--;
|
||||
|
@ -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,8 +153,8 @@ 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,
|
||||
n_blocks, pairs);
|
||||
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
|
||||
|
|
87
newbrt/tests/test_block_allocator_merge.c
Normal file
87
newbrt/tests/test_block_allocator_merge.c
Normal file
|
@ -0,0 +1,87 @@
|
|||
/* -*- 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;
|
||||
}
|
Loading…
Add table
Reference in a new issue