Skip to content

Commit

Permalink
Allow to use decreasing ids in lsregion
Browse files Browse the repository at this point in the history
  • Loading branch information
Gerold103 committed Mar 1, 2017
1 parent d46cdd5 commit 2e8d1a0
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 16 deletions.
5 changes: 2 additions & 3 deletions small/lsregion.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,12 @@ lsregion_alloc_slow(struct lsregion *lsregion, size_t size, int64_t id)
}
}
assert(slab != NULL);
assert(slab->max_id <= id);
void *res = lslab_pos(slab);
slab->slab_used += size;

/* Update the memory block meta info. */
assert(slab->max_id <= id);
slab->max_id = id;
if (id > slab->max_id)
slab->max_id = id;
lsregion->slabs.stats.used += size;
return res;
}
25 changes: 14 additions & 11 deletions small/lsregion.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,20 +67,23 @@ struct lslab {
* written log. It allows to allocate memory chunks of any size,
* but does not support free() of an individual chunk. Instead,
* each chunk, when allocated, needs to be identified with an id.
* It is assumed that ids are nondecreasing.
* The chunks are stored in equally-sized slabs, obtained from
* slab arena.
* To free memory, the allocator requires an oldest id before
* which all memory could be discarded. Upon free, it returns
* all slabs containing chunks with smaller ids to the slab arena.
*
* id_i <= id_(i + 1)
* To free memory, the allocator requires the oldest id before
* first of which all memory could be discarded. Upon free, it
* returns all slabs containing chunks with smaller ids to the
* slab arena.
* *-------* *-------* *-------* *-------*
* | slab |-->| slab |-->| slab |--> -->| slab |
* *-------* *-------* *-------* *-------*
* <= id1 <= id2 | <= id3 <= idN
* |
* truncate with id in [id2, id3) deletes from this position.
*
* For example, if the ids sequense is following:
* id1 <= id2 | <= id3 > id4 <= id5 > id1 <= id2 <= id6
* |
* |
* then truncate with id in [id2, id3) deletes from this position.
* The second sequence id1 <= id2 <= id3 will not be truncated,
* before there is id3 between them.
*/
struct lsregion {
/**
Expand Down Expand Up @@ -175,11 +178,11 @@ lsregion_alloc(struct lsregion *lsregion, size_t size, int64_t id)
slab = rlist_last_entry(&lsregion->slabs.slabs, struct lslab,
next_in_list);
assert(slab != NULL);
assert(slab->max_id <= id);
if (size <= lslab_unused(lsregion, slab)) {
void *res = lslab_pos(slab);
slab->slab_used += size;
slab->max_id = id;
if (id > slab->max_id)
slab->max_id = id;
lsregion->slabs.stats.used += size;
return res;
}
Expand Down
61 changes: 60 additions & 1 deletion test/lsregion.c
Original file line number Diff line number Diff line change
Expand Up @@ -317,15 +317,74 @@ test_big_data_small_slabs()
check_plan();
}

static void
test_decreasing_ids()
{
note("decreasing_identifiers");
plan(15);
struct quota quota;
struct slab_arena arena;
struct lsregion allocator;
quota_init(&quota, 4 * SLAB_MIN_SIZE);
is(slab_arena_create(&arena, &quota, 0, 1024, MAP_PRIVATE), 0, "init");
lsregion_create(&allocator, &arena);
size_t size = 10;
char *data = lsregion_alloc(&allocator, size, 100);
isnt(data, NULL, "alloc(10) with id 100");
uint32_t used = lsregion_used(&allocator);
uint32_t total = lsregion_total(&allocator);
is(used, size, "used after alloc(10) with id 100");
is(total, arena.slab_size, "total after alloc(10) with id 100");
is(lsregion_slab_count(&allocator), 1,
"slab count after alloc(10) with id 100");

/* Use decreasing identifier to allocate data. */
data = lsregion_alloc(&allocator, size, 90);
isnt(data, NULL, "alloc(10) with id 90");
used = lsregion_used(&allocator);
total = lsregion_total(&allocator);
is(used, size * 2, "used after alloc(10) with id 90");
/*
* The single slab contains two allocations with
* decreasing identifiers.
*/
is(total, arena.slab_size, "total after alloc(10) with id 90");
is(lsregion_slab_count(&allocator), 1,
"slab count after alloc(10) with id 90");

/* We can't drop slab, because its max_ids == 100. */
lsregion_gc(&allocator, 95);
used = lsregion_used(&allocator);
total = lsregion_total(&allocator);
is(used, size * 2, "used after gc(95)");
is(total, arena.slab_size, "total after gc(95)");
is(lsregion_slab_count(&allocator), 1, "slab count after gc(95)");

/* Now we can drop slab, because 100 >= max_id == 100. */
lsregion_gc(&allocator, 100);
used = lsregion_used(&allocator);
total = lsregion_total(&allocator);
is(used, 0, "used after gc(100)");
/* Slab is cached. */
is(total, arena.slab_size, "total after gc(100)");
is(lsregion_slab_count(&allocator), 0, "slab count after gc(100)");

lsregion_destroy(&allocator);
slab_arena_destroy(&arena);

check_plan();
}

int
main()
{
plan(4);
plan(5);

test_basic();
test_many_allocs_one_slab();
test_many_allocs_many_slabs();
test_big_data_small_slabs();
test_decreasing_ids();

return check_plan();
}
20 changes: 19 additions & 1 deletion test/lsregion.result
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
1..4
1..5
# basic
1..36
ok 1 - init
Expand Down Expand Up @@ -70,3 +70,21 @@ ok 3 - subtests
ok 6 - slab count after gc (id / 2)
ok 7 - arena used after gc(id / 2)
ok 4 - subtests
# decreasing_identifiers
1..15
ok 1 - init
ok 2 - alloc(10) with id 100
ok 3 - used after alloc(10) with id 100
ok 4 - total after alloc(10) with id 100
ok 5 - slab count after alloc(10) with id 100
ok 6 - alloc(10) with id 90
ok 7 - used after alloc(10) with id 90
ok 8 - total after alloc(10) with id 90
ok 9 - slab count after alloc(10) with id 90
ok 10 - used after gc(95)
ok 11 - total after gc(95)
ok 12 - slab count after gc(95)
ok 13 - used after gc(100)
ok 14 - total after gc(100)
ok 15 - slab count after gc(100)
ok 5 - subtests

0 comments on commit 2e8d1a0

Please sign in to comment.