Commit 2cd4dc5f authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent acad7a9d
...@@ -35,23 +35,30 @@ func NewSeqBufReaderSize(r io.ReaderAt, size int) *SeqBufReader { ...@@ -35,23 +35,30 @@ func NewSeqBufReaderSize(r io.ReaderAt, size int) *SeqBufReader {
// readFromBuf reads as much as possible for ReadAt(p, pos) request from buffered data // readFromBuf reads as much as possible for ReadAt(p, pos) request from buffered data
// it returns nread and (p', pos') that was left for real reading to complete // it returns nread and (p', pos') that was left for real reading to complete
// XXX dir?
func (sb *SeqBufReader) readFromBuf(p []byte, pos int64) (int, []byte, int64) { func (sb *SeqBufReader) readFromBuf(p []byte, pos int64) (int, []byte, int64) {
n := 0 n := 0
switch { switch {
// use buffered data: start + forward // use buffered data: start + forward
case pos >= sb.pos && pos < sb.pos + int64(len(sb.buf)): case pos >= sb.pos && pos < sb.pos + int64(len(sb.buf)):
copyPos := pos - sb.pos n = copy(p, sb.buf[pos - sb.pos:]) // NOTE len(p) can be < len(sb[copyPos:])
n = copy(p, sb.buf[copyPos:]) // NOTE len(p) can be < len(sb[copyPos:])
p = p[n:] p = p[n:]
pos += int64(n) pos += int64(n)
//sb.dir = +1 // XXX recheck
// use buffered data: tail + backward // use buffered data: tail + backward
case pos + int64(len(p)) <= sb.pos + int64(len(sb.buf)) && pos + int64(len(p)) > sb.pos: case pos + int64(len(p)) > sb.pos && pos + int64(len(p)) <= sb.pos + int64(len(sb.buf)):
// TODO // here we know pos is < sb.pos
//sb.dir = -1 // XXX recheck //
// proof: consider if pos >= sb.pos.
// Then from `pos + len(p) > sb.pos` above it follows that:
// len(p) = 0 only if pos > sb.pos
// Then from `pos <= sb.pos + len(sb.buf) - len(p)` above it follow that:
// pos < sb.pos + len(sb.buf) (NOTE strictly < because if len(p) = 0
// FIXME ^^^
n = copy(p[sb.pos - pos:], sb.buf) // NOTE n == len(p[sb.pos - pos:])
p = p[:sb.pos - pos]
// pos to read stays the same
} }
return n, p, pos return n, p, pos
......
...@@ -42,19 +42,34 @@ func TestSeqBufReader(t *testing.T) { ...@@ -42,19 +42,34 @@ func TestSeqBufReader(t *testing.T) {
r := &XReader{} r := &XReader{}
rb := NewSeqBufReaderSize(r, 10) // with 10 it is easier to do/check math for a human rb := NewSeqBufReaderSize(r, 10) // with 10 it is easier to do/check math for a human
// read @pos/len -> rb.pos, len(rb.buf) //, rb.dir // read @pos/len -> rb.pos, len(rb.buf)
testv := []struct {pos int64; Len int; bufPos int64; bufLen int} { //, bufDir int} { testv := []struct {pos int64; Len int; bufPos int64; bufLen int} {
{40, 5, 40, 10}, // 1st access, forward by default {40, 5, 40, 10}, // 1st access, forward by default
{45, 7, 50, 10}, // part taken from buf, part read next, forward detected {45, 7, 50, 10}, // part taken from buf, part read next, forward
{52, 5, 50, 10}, // everything taken from buf {52, 5, 50, 10}, // everything taken from buf
{57, 5, 60, 10}, // part taken from buf, part read next {57, 5, 60, 10}, // part taken from buf, part read next
{60, 11, 60, 10}, // access > cap(buf) {60, 11, 60, 10}, // access > cap(buf), buf skipped
{71, 11, 60, 10}, // access > cap(buf), once again {71, 11, 60, 10}, // access > cap(buf), once again
{82, 10, 82, 10}, // access = cap(buf), should refill buf
{92, 5, 92, 8}, // next access - should refill buffer, but only up to EIO range
{97, 4, 92, 8}, // this triggers user-visible EIO, buffer not refilled
{101, 5, 92, 8}, // EIO again
{105, 5, 105, 10}, // past EIO range - buffer refilled
{110,70, 105, 10}, // very big access forward, buf untouched
{180,11, 105, 10}, // big access ~ forward
// TODO access near EOF - buffer fill hits EOF, but not returns it to client
// TODO access overlapping EOF - EOF returned
{170,11, 105, 10}, // big access backward
{160,11, 105, 10}, // big access backward, once more
{155, 5, 155, 10}, // access backward - buffer refilled
// XXX refilled forward first time after big backward readings
{150, 5, 150, 10}, // next access backward - buffer refilled backward
// big backward
// small backward - refilled backward
// XXX big access going backward - detect dir change // XXX big access going backward - detect dir change
// TODO accees around and in error range
// TODO overlap // TODO overlap
} }
...@@ -66,14 +81,17 @@ func TestSeqBufReader(t *testing.T) { ...@@ -66,14 +81,17 @@ func TestSeqBufReader(t *testing.T) {
nOk, errOk := r.ReadAt(pOk, tt.pos) nOk, errOk := r.ReadAt(pOk, tt.pos)
nB, errB := rb.ReadAt(pB, tt.pos) nB, errB := rb.ReadAt(pB, tt.pos)
pOk = pOk[:nOk]
pB = pB[:nB]
// check that reading result is the same // check that reading result is the same
if !(nB == nOk && errB == errOk && bytes.Equal(pB, pOk)) { if !(bytes.Equal(pB, pOk) && errB == errOk) {
t.Fatalf("%v: -> %v, %#v, %v ; want %v, %#v, %v", tt, nB, errB, pB, nOk, errOk, pOk) t.Fatalf("%v: -> %v, %#v ; want %v, %#v", tt, pB, errB, pOk, errOk)
} }
// verify buffer state // verify buffer state
if !(rb.pos == tt.bufPos && len(rb.buf) == tt.bufLen){ // && rb.dir == tt.bufDir) { if !(rb.pos == tt.bufPos && len(rb.buf) == tt.bufLen){
t.Fatalf("%v: -> unexpected buffer state @%v #%v", tt, rb.pos, len(rb.buf)) //, rb.dir) t.Fatalf("%v: -> unexpected buffer state @%v #%v", tt, rb.pos, len(rb.buf))
} }
} }
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment