|
1 | 1 | package wrapio
|
2 | 2 |
|
3 |
| -import ( |
4 |
| - "fmt" |
5 |
| - "io" |
6 |
| -) |
| 3 | +import "io" |
7 | 4 |
|
8 | 5 | // DoerAt is a common interface for wrappers WriteAt or ReadAt functions
|
9 | 6 | type DoerAt interface {
|
@@ -98,26 +95,38 @@ func (r *WrapReader) ReadAt(p []byte, off int64) (n int, err error) {
|
98 | 95 | return Wrap(r, p, off, r.wrapAt)
|
99 | 96 | }
|
100 | 97 |
|
| 98 | +// maxConsecutiveEmptyActions determines how many consecutive empty reads/writes can occur before giving up |
| 99 | +const maxConsecutiveEmptyActions = 100 |
| 100 | + |
101 | 101 | // Wrap causes an action on an array of bytes (like read/write) to be done from an offset off,
|
102 | 102 | // wrapping at offset wrapAt.
|
103 | 103 | func Wrap(w DoerAt, p []byte, off int64, wrapAt int64) (n int, err error) {
|
104 |
| - var m int |
| 104 | + var m, fails int |
105 | 105 |
|
106 | 106 | off %= wrapAt
|
107 | 107 |
|
108 | 108 | for len(p) > 0 {
|
109 | 109 |
|
110 | 110 | if off+int64(len(p)) < wrapAt {
|
111 |
| - if m, err = w.DoAt(p, off); err != nil && err != io.EOF { |
112 |
| - fmt.Println(off, m, len(p), err) |
113 |
| - return n + m, err |
114 |
| - } |
| 111 | + m, err = w.DoAt(p, off) |
115 | 112 | } else {
|
116 | 113 | space := wrapAt - off
|
117 |
| - if m, err = w.DoAt(p[:space], off); err != nil && err != io.EOF { |
118 |
| - fmt.Println(off, m, len(p[:space]), err) |
119 |
| - return n + m, err |
120 |
| - } |
| 114 | + m, err = w.DoAt(p[:space], off) |
| 115 | + } |
| 116 | + |
| 117 | + if err != nil && err != io.EOF { |
| 118 | + return n + m, err |
| 119 | + } |
| 120 | + |
| 121 | + switch m { |
| 122 | + case 0: |
| 123 | + fails++ |
| 124 | + default: |
| 125 | + fails = 0 |
| 126 | + } |
| 127 | + |
| 128 | + if fails > maxConsecutiveEmptyActions { |
| 129 | + return n + m, io.ErrNoProgress |
121 | 130 | }
|
122 | 131 |
|
123 | 132 | n += m
|
|
0 commit comments