This repository has been archived by the owner on Feb 17, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6
/
chunk.go
127 lines (112 loc) · 3.92 KB
/
chunk.go
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
package chaos
import (
"context"
"github.com/stealthrocket/wasi-go"
)
// Chunk wraps the base system to return one that chunks reads and writes to
// only partially use the I/O vectors. The intent is to exercise paths that
// handle successful but partial completion of I/O operations.
//
// This fault injector has a side effect of increasing latency of I/O operations
// because it breaks down the buffering layers that are usually implemented in
// applications, which may cause measurable slow downs if triggered too often.
//
// The filter does not apply to datagram sockets because truncating messages
// may break network protocols such as DNS, and the intent of this wrapper is
// not to inject irrecoverable errors.
func Chunk(base wasi.System) wasi.System {
return &chunkSystem{System: base}
}
func canBeChunked(fileType wasi.FileType) bool {
return fileType != wasi.SocketDGramType
}
type chunkSystem struct {
wasi.System
iovs [1]wasi.IOVec
}
func (s *chunkSystem) chunk(fileType wasi.FileType, iovs []wasi.IOVec) []wasi.IOVec {
if canBeChunked(fileType) {
for _, iov := range iovs {
if len(iov) != 0 {
s.iovs[0] = iov[:1]
return s.iovs[:]
}
}
}
return iovs
}
func (s *chunkSystem) reset() {
s.iovs[0] = nil
}
func (s *chunkSystem) FDPread(ctx context.Context, fd wasi.FD, iovs []wasi.IOVec, offset wasi.FileSize) (wasi.Size, wasi.Errno) {
f, errno := s.System.FDStatGet(ctx, fd)
if errno != wasi.ESUCCESS {
return ^wasi.Size(0), errno
}
iovs = s.chunk(f.FileType, iovs)
defer s.reset()
return s.System.FDPread(ctx, fd, iovs, offset)
}
func (s *chunkSystem) FDPwrite(ctx context.Context, fd wasi.FD, iovs []wasi.IOVec, offset wasi.FileSize) (wasi.Size, wasi.Errno) {
f, errno := s.System.FDStatGet(ctx, fd)
if errno != wasi.ESUCCESS {
return ^wasi.Size(0), errno
}
iovs = s.chunk(f.FileType, iovs)
defer s.reset()
return s.System.FDPwrite(ctx, fd, iovs, offset)
}
func (s *chunkSystem) FDRead(ctx context.Context, fd wasi.FD, iovs []wasi.IOVec) (wasi.Size, wasi.Errno) {
f, errno := s.System.FDStatGet(ctx, fd)
if errno != wasi.ESUCCESS {
return ^wasi.Size(0), errno
}
iovs = s.chunk(f.FileType, iovs)
defer s.reset()
return s.System.FDRead(ctx, fd, iovs)
}
func (s *chunkSystem) FDWrite(ctx context.Context, fd wasi.FD, iovs []wasi.IOVec) (wasi.Size, wasi.Errno) {
f, errno := s.System.FDStatGet(ctx, fd)
if errno != wasi.ESUCCESS {
return ^wasi.Size(0), errno
}
iovs = s.chunk(f.FileType, iovs)
defer s.reset()
return s.System.FDWrite(ctx, fd, iovs)
}
func (s *chunkSystem) SockRecv(ctx context.Context, fd wasi.FD, iovs []wasi.IOVec, iflags wasi.RIFlags) (wasi.Size, wasi.ROFlags, wasi.Errno) {
f, errno := s.System.FDStatGet(ctx, fd)
if errno != wasi.ESUCCESS {
return ^wasi.Size(0), wasi.ROFlags(0), errno
}
iovs = s.chunk(f.FileType, iovs)
defer s.reset()
return s.System.SockRecv(ctx, fd, iovs, iflags)
}
func (s *chunkSystem) SockSend(ctx context.Context, fd wasi.FD, iovs []wasi.IOVec, iflags wasi.SIFlags) (wasi.Size, wasi.Errno) {
f, errno := s.System.FDStatGet(ctx, fd)
if errno != wasi.ESUCCESS {
return ^wasi.Size(0), errno
}
iovs = s.chunk(f.FileType, iovs)
defer s.reset()
return s.System.SockSend(ctx, fd, iovs, iflags)
}
func (s *chunkSystem) SockRecvFrom(ctx context.Context, fd wasi.FD, iovs []wasi.IOVec, iflags wasi.RIFlags) (wasi.Size, wasi.ROFlags, wasi.SocketAddress, wasi.Errno) {
f, errno := s.System.FDStatGet(ctx, fd)
if errno != wasi.ESUCCESS {
return ^wasi.Size(0), wasi.ROFlags(0), nil, errno
}
iovs = s.chunk(f.FileType, iovs)
defer s.reset()
return s.System.SockRecvFrom(ctx, fd, iovs, iflags)
}
func (s *chunkSystem) SockSendTo(ctx context.Context, fd wasi.FD, iovs []wasi.IOVec, iflags wasi.SIFlags, addr wasi.SocketAddress) (wasi.Size, wasi.Errno) {
f, errno := s.System.FDStatGet(ctx, fd)
if errno != wasi.ESUCCESS {
return ^wasi.Size(0), errno
}
iovs = s.chunk(f.FileType, iovs)
defer s.reset()
return s.System.SockSendTo(ctx, fd, iovs, iflags, addr)
}