summaryrefslogtreecommitdiff
path: root/t/restart.t
blob: 4a398f176d224f827982b21aba3c61cc5a9e118e (plain)
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#!/usr/bin/env perl

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

# NOTE: Do not use this feature on top of a filesystem, please use a ram disk!
# These tests use /tmp/ as some systems do not have or have a weirdly small
# /dev/shm.
my $mem_path = "/tmp/mc_restart.$$";

# read a invalid metadata file
{
    my $meta_path = "$mem_path.meta";
    open(my $f, "> $meta_path") || die("Can't open a metadata file.");
    eval {  new_memcached("-e $mem_path"); };
    unlink($meta_path);
    ok($@, "Died with an empty metadata file");
}

my $server = new_memcached("-m 128 -e $mem_path -I 2m");
my $sock = $server->sock;

diag "restart basic stats";
{
    my $stats = mem_stats($server->sock, ' settings');
    is($stats->{memory_file}, $mem_path);
}

diag "Set some values, various sizes.";
{
    my $cur = 2;
    my $cnt = 0;
    my $end = 2**20;
    while ($cur <= $end) {
        my $val = 'x' x $cur;
        print $sock "set foo${cnt} 0 0 $cur\r\n$val\r\n";
        like(scalar <$sock>, qr/STORED/, "stored $cur size item");
        $cur *= 2;
        $cnt++;
    }
}

diag "load enough items to change hash power level";
{
    my $stats = mem_stats($sock);
    is($stats->{hash_power_level}, 16, "starting hash level is 16");
    my $todo = 2**17;
    my $good = 1;
    while ($todo--) {
        print $sock "set z${todo} 0 0 0\r\n\r\n";
        my $res = <$sock>;
        $good = 0 if ($res !~ m/STORED/);
    }

    is($good, 1, "set responses were all STORED");
    sleep 3; # sigh.
    $stats = mem_stats($sock);
    is($stats->{hash_power_level}, 17, "new hash power level is 17");

    # Now delete all these items, so the auto-restore won't cause the hash
    # table to re-inflate, but the restart code should restore the hash table
    # to where it was regardless.
    $todo = 2**17;
    $good = 1;
    while ($todo--) {
        print $sock "delete z${todo}\r\n";
        my $res = <$sock>;
        $good = 0 if ($res !~ m/DELETED/);
    }
    is($good, 1, "delete responses were all DELETED");
}

diag "Load a couple chunked items";
my $deleted_chunked_item = 0;
{
    my $cur = 768000;
    my $cnt = 0;
    my $end = $cur + 1024;
    while ($cur <= $end) {
        my $val = 'x' x $cur;
        print $sock "set chunk${cnt} 0 0 $cur\r\n$val\r\n";
        like(scalar <$sock>, qr/STORED/, "stored $cur size item");
        $cur += 50;
        $cnt++;
    }
    # delete the last one.
    $cnt--;
    $deleted_chunked_item = $cnt;
    print $sock "delete chunk${cnt}\r\n";
    like(scalar <$sock>, qr/DELETED/, "deleted $cnt from large chunked items");
}

diag "Data that should expire while stopped.";
{
    print $sock "set low1 0 5 2\r\nbo\r\n";
    like(scalar <$sock>, qr/STORED/, "stored low ttl item");
    # This one should stay.
    print $sock "set low2 0 20 2\r\nmo\r\n";
    like(scalar <$sock>, qr/STORED/, "stored low ttl item");
}

# make sure it's okay to stop with a logger watcher enabled.
{
    my $wsock = $server->new_sock;
    print $wsock "watch fetchers mutations\n";
    my $res = <$wsock>;
    is($res, "OK\r\n", "watcher enabled");
}

$server->graceful_stop();
diag "killed, waiting";
# TODO: add way to wait for server to fully exit..
sleep 10;

{
    $server = new_memcached("-m 128 -e $mem_path -I 2m");
    $sock = $server->sock;
    diag "reconnected";

    my $stats = mem_stats($sock);
    is($stats->{hash_power_level}, 17, "restarted hash power level is 17");
}

diag "low TTL item should be gone";
{
    mem_get_is($sock, 'low1', undef);
    # but this one should exist.
    mem_get_is($sock, 'low2', 'mo');
}

# initially inserted items.
{
    my $cur = 2;
    my $cnt = 0;
    my $end = 1000000;
    while ($cur < $end) {
        my $val = 'x' x $cur;
        mem_get_is($sock, 'foo' . $cnt, $val);
        $cur *= 2;
        $cnt++;
    }
}

# chunked items.
{
    my $cur = 768000;
    my $cnt = 0;
    my $end = $cur + 1024;
    while ($cur <= $end) {
        my $val = 'x' x $cur;
        if ($cnt != $deleted_chunked_item) {
            mem_get_is($sock, 'chunk' . $cnt, $val);
        }
        $cur += 50;
        $cnt++;
    }
}

done_testing();

END {
    unlink $mem_path if $mem_path;
}