File: extstore-overdel.t

package info (click to toggle)
memcached 1.6.39-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,320 kB
  • sloc: ansic: 62,281; perl: 12,500; sh: 4,569; makefile: 468; python: 402; xml: 59
file content (112 lines) | stat: -rw-r--r-- 3,191 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#!/usr/bin/env perl

use strict;
use warnings;
use Test::More;
use FindBin qw($Bin);
use lib "$Bin/lib";
use MemcachedTest;
use Data::Dumper qw/Dumper/;

my $ext_path;

if (!supports_extstore()) {
    plan skip_all => 'extstore not enabled';
    exit 0;
}

$ext_path = "/tmp/extstore.$$";

my $server = new_memcached("-m 64 -U 0 -o ext_page_size=8,ext_wbuf_size=2,ext_threads=1,ext_item_size=512,ext_item_age=0,ext_recache_rate=0,ext_max_frag=0.9,ext_path=$ext_path:64m,slab_automove=0,ext_compact_under=1,ext_max_sleep=10000");
my $sock = $server->sock;

# Wait until all items have flushed
sub wait_for_ext {
    my $target = shift || 0;
    my $sum = $target + 1;
    while ($sum > $target) {
        my $s = mem_stats($sock, "items");
        $sum = 0;
        for my $key (keys %$s) {
            if ($key =~ m/items:(\d+):number/) {
                # Ignore classes which can contain extstore items
                next if $1 < 3;
                $sum += $s->{$key};
            }
        }
        select undef, undef, undef, 0.05 if $sum > $target;
    }
}

sub rand_value {
    my $v = '';
    my $s = shift;
    my @chars = ("C".."Z");
    for (1 .. $s) {
        $v .= $chars[rand @chars];
    }
    return $v;
}
my $value = rand_value(20000);

note "fill page with same key over and over";
{
    my $rval;

    for (1 .. 100) {
        $rval = rand_value(20000);
        print $sock "set overwrite 0 0 20000 noreply\r\n$rval\r\n";
        wait_for_ext(0);
    }

    # poke the final overwrite key a few times so it will get rescued later
    print $sock "mg overwrite\r\n";
    is(scalar <$sock>, "HD\r\n");
    print $sock "mg overwrite\r\n";
    is(scalar <$sock>, "HD\r\n");

    print $sock "extstore compact_under 6\r\n";
    my $res = <$sock>;
    print $sock "extstore drop_under 3\r\n";
    $res = <$sock>;

    # fill with junk to allow compaction to run.
    my $keycount = 1800;
    for (1 .. $keycount) {
        print $sock "set mfoo$_ 0 0 20000 noreply\r\n$value\r\n";
        # wait to avoid evictions
        wait_for_ext(100);
        # Keep poking the overwrite key.
        print $sock "mg overwrite\r\n";
        my $res = <$sock>;
    }
    wait_for_ext();

    my $stats = mem_stats($sock);
    is($stats->{evictions}, 0, 'no evictions');
    is($stats->{miss_from_extstore}, 0, 'no misses');

    for (1 .. $keycount) {
        next unless $_ % 2 == 0;
        #    print $sock "delete mfoo$_ noreply\r\n";
    }

    # With the bug we rescue the first seen item from the page, and since we
    # were randomizing values we could end up returning an old value (or more
    # likely none at all).
    # This should find the final randomized value has been rescued.
    mem_get_is($sock, "overwrite", $rval);
    $stats = mem_stats($sock);
    is($stats->{badcrc_from_extstore}, 0, 'CRC checks successful');
    is($stats->{miss_from_extstore}, 0, 'no misses');
    cmp_ok($stats->{extstore_pages_free}, '>', 0, 'some pages now free');
    cmp_ok($stats->{extstore_compact_rescues}, '>', 0, 'some compaction rescues happened');
    print $sock "extstore drop_unread 0\r\n";
    $res = <$sock>;
}

done_testing();

END {
    unlink $ext_path if $ext_path;
}