Hi,
I’m currently reading your book. By doing so, I like to rewrite the code by myself. It helps me to deeply understand how it works.
However, I found something strange in the log package, concerning the Read() func. Let’s see that with a test example :
In the log_test.go
file, the original test is :
func testAppendRead(t *testing.T, log *log.Log) {
append := &api.Record{
Value: []byte("hello world"),
}
off, err := log.Append(append)
require.NoError(t, err)
require.Equal(t, uint64(0), off)
read, err := log.Read(off)
require.NoError(t, err)
require.Equal(t, append, read)
}
In this test, we write 1 record and read it.
Let’s write 4 records and read them:
func testAppendRead(t *testing.T, log *log.Log) {
for i := 0; i < 5; i++ {
append := &api.Record{
Value: []byte(fmt.Sprintf("Hello World %d !", i)),
}
off, err := log.Append(append)
require.NoError(t, err)
require.Equal(t, uint64(i), off)
read, err := log.Read(off)
require.NoError(t, err)
require.Equal(t, append, read)
}
}
Here is what I get by running go test -v log_test.go
:
=== RUN TestLog
=== RUN TestLog/append_and_read_a_record_succeeds
TestLog/append_and_read_a_record_succeeds: log_test.go:48:
Error Trace: log_test.go:48
log_test.go:32
Error: Received unexpected error:
offset out of range: 2
Test: TestLog/append_and_read_a_record_succeeds
I’m not sure why it fails, but I have understood that, in a log, segments are ordered from the oldest to the newest. It means the oldest will have a base offset of 0 (for example), the second will have a base offset of 2.
But then, there is this code in the Read method :
var s *segment
for _, segment := range l.segments {
//The first segment we read is the oldest one. That is to say, the one
//with a base offset equals to 0, right?
if segment.baseOffset <= off {
s = segment
break
}
}
if s == nil || s.nextOffset <= off {
return nil, fmt.Errorf("offset out of range: %d", off)
}
If we try to read offset 3, by reading the first (oldest) segment in the loop, we will have: segment.baseOffset = 0 <= 3
However, the Record with the offset 3 is in the segment which baseOffset is 2.
Did I miss something?