File: extstore-jbod.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 (105 lines) | stat: -rw-r--r-- 3,399 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
#!/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;
my $ext_path2;

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

$ext_path = "/tmp/extstore1.$$";
$ext_path2 = "/tmp/extstore2.$$";

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

my $value;
{
    my @chars = ("C".."Z");
    for (1 .. 20000) {
        $value .= $chars[rand @chars];
    }
}

# fill some larger objects
{
    my $free_before = summarize_buckets(mem_stats($sock, ' extstore'));
    # we gave 64m and 96m devices, so pages in DEFAULT should be > 8 or 12 to
    # be sure they're both in the same pool.
    cmp_ok($free_before->[0], '>', 18, "default has more pages");
    my $keycount = 4000;
    for (1 .. $keycount) {
        print $sock "set nfoo$_ 0 0 20000 noreply\r\n$value\r\n";
        print $sock "set lfoo$_ 0 0 20000 noreply\r\n$value\r\n";
    }
    # wait for a flush
    wait_ext_flush($sock);
    # TODO: this is failing only on github actions and I have no idea why.
    #mem_get_is($sock, "nfoo1", $value);
    # fill to excess
    for (1 .. $keycount) {
        print $sock "set kfoo$_ 0 0 20000 noreply\r\n$value\r\n";
        print $sock "set zfoo$_ 0 0 20000 noreply\r\n$value\r\n";
    }
    wait_ext_flush($sock);

    my $free_after = summarize_buckets(mem_stats($sock, ' extstore'));
    # delete half
    for (1 .. $keycount) {
        print $sock "delete lfoo$_ noreply\r\n";
    }
    print $sock "lru_crawler crawl all\r\n";
    <$sock>;

    cmp_ok($free_after->[0], '<', 4, "default is mostly full");
    # fetch
    # check extstore counters
    my $stats = mem_stats($sock);
    is($stats->{evictions}, 0, 'no RAM evictions');
    cmp_ok($stats->{extstore_page_allocs}, '>', 0, 'at least one page allocated');
    cmp_ok($stats->{extstore_objects_written}, '>', $keycount / 2, 'some objects written');
    cmp_ok($stats->{extstore_bytes_written}, '>', length($value) * 2, 'some bytes written');
    # commented out because we're not testing fetching data back in this test.
    #cmp_ok($stats->{get_extstore}, '>', 0, 'one object was fetched');
    #cmp_ok($stats->{extstore_objects_read}, '>', 0, 'one object read');
    #cmp_ok($stats->{extstore_bytes_read}, '>', length($value), 'some bytes read');
    cmp_ok($stats->{extstore_page_evictions}, '>', 0, 'at least one page evicted');
    cmp_ok($stats->{extstore_page_reclaims}, '>', 1, 'at least two pages reclaimed');
}

sub summarize_buckets {
    my $s = shift;
    my @buks = ();
    for (0 .. 6) {
        push(@buks, 0);
    }
    my $is_free = 0;
    my $x = 0;
    while (exists $s->{$x . ':version'}) {
        #my $fb = $s->{$x . ':free_bucket'};
        #print STDERR "BYTES: [$x:$fb] ", $s->{$x . ':bytes'}, "\n";
        my $is_used = $s->{$x . ':version'};
        if ($is_used == 0) {
            # version of 0 means the page is free.
            $buks[$s->{$x . ':free_bucket'}]++;
        }
        $x++;
    }
    return \@buks;
}

done_testing();

END {
    unlink $ext_path if $ext_path;
    unlink $ext_path2 if $ext_path2;
}