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
| | #!/usr/bin/env ruby
# -*- encoding: binary -*-
# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net>
# License: GPLv3 or later (see COPYING for details)
require 'test/test_helper'
require 'timeout'
TEST_PROG = 'test/pwrite-wrap'
class TestPwriteWrap < Test::Unit::TestCase
def setup
@tmpdir = Dir.mktmpdir('cmogstored-pwrite-wrap-test')
@to_close = []
@host = TEST_HOST
srv = TCPServer.new(@host, 0)
@port = srv.addr[1]
srv.close
srv = TCPServer.new(@host, 0)
@mgmt_port = srv.addr[1]
srv.close
Dir.mkdir("#@tmpdir/dev666")
Dir.mkdir("#@tmpdir/dev333")
File.open("#@tmpdir/dev666/get.fid", "w") { |fp|
fp.seek(1000)
fp.write("\0")
}
@err = Tempfile.new("stderr")
cmd = [ TEST_PROG, "--docroot=#@tmpdir", "--httplisten=#@host:#@port",
"--mgmtlisten=#@host:#@mgmt_port", "--maxconns=500" ]
@slow_time = 5000
if vg = ENV["VALGRIND"]
cmd = vg.split(/\s+/).concat(cmd)
# valgrind slows everything down, so increase the sleep time
@slow_time *= 2
end
ENV["PWRITE_WRAP_SLOW_MSEC"] ||= (@slow_time * 2).to_s
@pid = fork {
$stderr.reopen(@err.path, "a")
@err.close
exec(*cmd)
}
@client = get_client
@mgmt_client = get_client(300, @mgmt_port)
@mgmt_client.write "server aio_threads = 1\r\n"
@mgmt_client.gets
warning = "fewer aio_threads(1) than devices(2)"
wait_for(30, warning) do
buf = File.read(@err.path)
if buf =~ /aio_threads/
puts "BUF: #{buf}"
end
buf.include?(warning)
end
end
def wait_for(sec, reason, res = 0.1)
stop = Time.now + sec
begin
return if yield
sleep res
end while Time.now < stop
assert false, reason
end
def test_pwrite_slow_chunked
__test_pwrite_slow(true)
end
def test_pwrite_slow_identity
__test_pwrite_slow(false)
end
def __test_pwrite_slow(chunked)
Process.kill(:VTALRM, @pid)
t_yield
Process.kill(:TTIN, @pid)
wait_for(5, "enable slow knob") do
File.readlines(@err.path).grep(/knob set: slow/)[0] &&
File.readlines(@err.path).grep(/flag set: slow/)[0]
end
client_2 = get_client
thr = Thread.new do
begin
size = 1024 * 1024 * 1024 * 10
if chunked
@client.write("PUT /dev666/foo.fid HTTP/1.1\r\n" \
"Host: example.com\r\n" \
"Transfer-Encoding: chunked\r\n\r\n" \
"#{'%x' % size}\r\n")
else
@client.write("PUT /dev666/foo.fid HTTP/1.0\r\n" \
"Content-Length: #{size}\r\n\r\n")
end
IO.copy_stream("/dev/zero", @client, size)
rescue => err
end
err
end
wait_for(5, "temporary file to exist", 0.05) do
Dir["#@tmpdir/dev666/foo.*tmp"][0]
end
t_yield
# this should cause mog_ioq_contended to return true in http_put.c
a = Time.now
Timeout.timeout(@slow_time * 4) {
client_2.write("GET /dev666/get.fid HTTP/1.0\r\n\r\n")
assert_match(%r{HTTP/1\.1 200 OK}, client_2.gets)
}
diff = Time.now - a
assert_operator diff, :<, (@slow_time * 2), "diff=#{diff}"
@client.shutdown
thr.join
Process.kill(:TTOU, @pid)
wait_for(5, "clear slow flag") do
File.readlines(@err.path).grep(/flag set: slow/)[0]
end
end
def teardown
Process.kill(:QUIT, @pid) rescue nil
_, status = Process.waitpid2(@pid)
@to_close.each { |io| io.close unless io.closed? }
FileUtils.rm_rf(@tmpdir)
@err.rewind
$stderr.write(@err.read) if $DEBUG
assert status.success?, status.inspect
end
# this test is horribly slow under valgrind, and we probably don't need
# valgrind, here...
end if File.exist?(TEST_PROG) && ! ENV["VALGRIND"]
|