Update Red Hat Copyright Notices
[nbdkit.git] / tests / test-multi-conn.sh
blobacd12989a3338a8d39cc37360830a20a08d314eb
1 #!/usr/bin/env bash
2 # nbdkit
3 # Copyright Red Hat
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are
7 # met:
9 # * Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
12 # * Redistributions in binary form must reproduce the above copyright
13 # notice, this list of conditions and the following disclaimer in the
14 # documentation and/or other materials provided with the distribution.
16 # * Neither the name of Red Hat nor the names of its contributors may be
17 # used to endorse or promote products derived from this software without
18 # specific prior written permission.
20 # THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
21 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 # PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
24 # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
27 # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 # SUCH DAMAGE.
33 # Demonstrate various multi-conn filter behaviors.
35 source ./functions.sh
36 set -e
37 set -x
39 requires_plugin sh
40 requires_nbdsh_uri
41 requires dd iflag=count_bytes </dev/null
43 files="test-multi-conn.out test-multi-conn.stat"
44 rm -f $files
45 cleanup_fn rm -f $files
47 fail=0
48 export handles preamble uri
49 uri= # will be set by --run later
50 handles=3
51 preamble='
52 import os
54 uri = os.environ["uri"]
55 handles = int(os.environ["handles"])
56 h = []
57 for i in range(handles):
58 h.append(nbd.NBD())
59 h[i].connect_uri(uri)
60 print(h[0].can_multi_conn())
63 # Demonstrate the caching present without use of filter
64 for filter in '' '--filter=multi-conn multi-conn-mode=plugin'; do
65 nbdkit -vf -U - sh test-multi-conn-plugin.sh $filter \
66 --run 'handles=4 nbdsh -c "$preamble" -c "
67 # Without flush, reads cache, and writes do not affect persistent data
68 print(bytes(h[0].pread(4, 0)))
69 h[1].pwrite(b'\''next '\'', 0)
70 print(bytes(h[0].pread(4, 0)))
71 print(bytes(h[1].pread(4, 0)))
72 print(bytes(h[2].pread(4, 0)))
73 # Flushing an unrelated connection does not make writes persistent
74 h[2].flush()
75 print(bytes(h[0].pread(4, 0)))
76 print(bytes(h[1].pread(4, 0)))
77 print(bytes(h[2].pread(4, 0)))
78 # After write is flushed, only connections without cache see new data
79 h[1].flush()
80 print(bytes(h[0].pread(4, 0)))
81 print(bytes(h[1].pread(4, 0)))
82 print(bytes(h[2].pread(4, 0)))
83 print(bytes(h[3].pread(4, 0)))
84 # Flushing before reads clears the cache
85 h[0].flush()
86 h[2].flush()
87 print(bytes(h[0].pread(4, 0)))
88 print(bytes(h[2].pread(4, 0)))
89 "' > test-multi-conn.out || fail=1
90 diff -u <(cat <<\EOF
91 False
92 b'Init'
93 b'Init'
94 b'next'
95 b'Init'
96 b'Init'
97 b'next'
98 b'Init'
99 b'Init'
100 b'next'
101 b'Init'
102 b'next'
103 b'next'
104 b'next'
106 ) test-multi-conn.out || fail=1
107 done
109 # Demonstrate specifics of FUA flag
110 for filter in '' '--filter=multi-conn multi-conn-mode=plugin'; do
111 nbdkit -vf -U - sh test-multi-conn-plugin.sh $filter \
112 --run 'nbdsh -c "$preamble" -c "
113 # Some servers let FUA flush all outstanding requests
114 h[0].pwrite(b'\''hello '\'', 0)
115 h[0].pwrite(b'\''world.'\'', 6, nbd.CMD_FLAG_FUA)
116 print(bytes(h[1].pread(12, 0)))
117 "' > test-multi-conn.out || fail=1
118 diff -u <(cat <<\EOF
119 False
120 b'hello world.'
122 ) test-multi-conn.out || fail=1
123 done
124 for filter in '' '--filter=multi-conn multi-conn-mode=plugin'; do
125 nbdkit -vf -U - sh test-multi-conn-plugin.sh strictfua=1 $filter \
126 --run 'nbdsh -c "$preamble" -c "
127 # But it is also compliant for a server that only flushes the exact request
128 h[0].pwrite(b'\''hello '\'', 0)
129 h[0].pwrite(b'\''world.'\'', 6, nbd.CMD_FLAG_FUA)
130 print(bytes(h[1].pread(12, 0)))
131 # Without multi-conn, data flushed in one connection can later be reverted
132 # by a flush of earlier data in another connection
133 h[1].pwrite(b'\''H'\'', 0, nbd.CMD_FLAG_FUA)
134 h[2].flush()
135 print(bytes(h[2].pread(12, 0)))
136 h[0].flush()
137 h[2].flush()
138 print(bytes(h[2].pread(12, 0)))
139 h[1].flush()
140 h[2].flush()
141 print(bytes(h[2].pread(12, 0)))
142 "' > test-multi-conn.out || fail=1
143 diff -u <(cat <<\EOF
144 False
145 b'Initiaworld.'
146 b'Hnitiaworld.'
147 b'hello world.'
148 b'Hello world.'
150 ) test-multi-conn.out || fail=1
151 done
153 # Demonstrate multi-conn effects. The cache filter in writeback
154 # mode is also able to supply multi-conn by a different technique.
155 for filter in '--filter=multi-conn' 'strictfua=1 --filter=multi-conn' \
156 '--filter=multi-conn multi-conn-mode=plugin --filter=cache' ; do
157 nbdkit -vf -U - sh test-multi-conn-plugin.sh $filter \
158 --run 'nbdsh -c "$preamble" -c "
159 # FUA writes are immediately visible on all connections
160 h[0].cache(12, 0)
161 h[1].pwrite(b'\''Hello '\'', 0, nbd.CMD_FLAG_FUA)
162 print(bytes(h[0].pread(12, 0)))
163 # A flush on an unrelated connection makes all other connections consistent
164 h[1].pwrite(b'\''world.'\'', 6)
165 h[2].flush()
166 print(bytes(h[0].pread(12, 0)))
167 "' > test-multi-conn.out || fail=1
168 diff -u <(cat <<\EOF
169 True
170 b'Hello l cont'
171 b'Hello world.'
173 ) test-multi-conn.out || fail=1
174 done
176 # unsafe mode intentionally lacks consistency, use at your own risk
177 nbdkit -vf -U - sh test-multi-conn-plugin.sh \
178 --filter=multi-conn multi-conn-mode=unsafe \
179 --run 'nbdsh -c "$preamble" -c "
180 h[0].cache(12, 0)
181 h[1].pwrite(b'\''Hello '\'', 0, nbd.CMD_FLAG_FUA)
182 print(bytes(h[0].pread(12, 0)))
183 h[1].pwrite(b'\''world.'\'', 6)
184 h[2].flush()
185 print(bytes(h[0].pread(12, 0)))
186 "' > test-multi-conn.out || fail=1
187 diff -u <(cat <<\EOF
188 True
189 b'Initial cont'
190 b'Initial cont'
192 ) test-multi-conn.out || fail=1
194 # auto mode devolves to multi-conn disable when connections are serialized
195 nbdkit -vf -U - sh test-multi-conn-plugin.sh --filter=noparallel \
196 serialize=connections --filter=multi-conn --filter=cache \
197 --run 'handles=1 nbdsh -c "$preamble"
198 ' > test-multi-conn.out || fail=1
199 diff -u <(cat <<\EOF
200 False
202 ) test-multi-conn.out || fail=1
204 # Use --filter=stats to show track-dirty effects
205 for level in off connection fast; do
206 for mode in emulate 'emulate --filter=cache' \
207 plugin 'plugin --filter=cache'; do
208 echo "setup: $level $mode" >> test-multi-conn.stat
209 # Flush with no activity
210 nbdkit -vf -U - sh test-multi-conn-plugin.sh --filter=multi-conn \
211 --filter=stats statsfile=test-multi-conn.stat statsappend=true \
212 multi-conn-track-dirty=$level multi-conn-mode=$mode \
213 --run 'nbdsh -c "$preamble" -c "
214 h[0].flush()
215 h[0].pread(1, 0)
216 h[0].flush()
217 "' > test-multi-conn.out || fail=1
218 # Client that flushes assuming multi-conn semantics
219 nbdkit -vf -U - sh test-multi-conn-plugin.sh --filter=multi-conn \
220 --filter=stats statsfile=test-multi-conn.stat statsappend=true \
221 multi-conn-track-dirty=$level multi-conn-mode=$mode \
222 --run 'handles=4 nbdsh -c "$preamble" -c "
223 h[0].pread(1, 0)
224 h[1].zero(1, 0)
225 h[3].flush()
226 h[2].zero(1, 1)
227 h[0].pread(1, 0)
228 h[3].flush()
229 h[3].flush()
230 "' > test-multi-conn.out || fail=1
231 # Client that flushes assuming inconsistent semantics
232 nbdkit -vf -U - sh test-multi-conn-plugin.sh --filter=multi-conn \
233 --filter=stats statsfile=test-multi-conn.stat statsappend=true \
234 multi-conn-track-dirty=$level multi-conn-mode=$mode \
235 --run 'nbdsh -c "$preamble" -c "
236 h[0].pread(1, 0)
237 h[1].trim(1, 0)
238 h[0].flush()
239 h[1].flush()
240 h[0].pread(1, 0)
241 h[2].trim(1, 1)
242 h[0].flush()
243 h[2].flush()
244 "' > test-multi-conn.out || fail=1
245 done
246 done
247 cat test-multi-conn.stat
248 diff -u <(cat <<\EOF
249 setup: off emulate
250 flush: 6 ops
251 flush: 12 ops
252 flush: 12 ops
253 setup: off emulate --filter=cache
254 flush: 6 ops
255 flush: 12 ops
256 flush: 12 ops
257 setup: off plugin
258 flush: 2 ops
259 flush: 3 ops
260 flush: 4 ops
261 setup: off plugin --filter=cache
262 flush: 2 ops
263 flush: 3 ops
264 flush: 4 ops
265 setup: connection emulate
266 flush: 4 ops
267 flush: 4 ops
268 setup: connection emulate --filter=cache
269 flush: 4 ops
270 flush: 4 ops
271 setup: connection plugin
272 flush: 3 ops
273 flush: 4 ops
274 setup: connection plugin --filter=cache
275 flush: 2 ops
276 flush: 2 ops
277 setup: fast emulate
278 flush: 8 ops
279 flush: 6 ops
280 setup: fast emulate --filter=cache
281 flush: 8 ops
282 flush: 6 ops
283 setup: fast plugin
284 flush: 2 ops
285 flush: 2 ops
286 setup: fast plugin --filter=cache
287 flush: 2 ops
288 flush: 2 ops
290 ) <($SED -n 's/\(flush:.*ops\).*/\1/p; /^setup:/p' \
291 test-multi-conn.stat) || fail=1
293 exit $fail