seaweedfs/weed/util/log_buffer/log_read.go

119 lines
3.3 KiB
Go
Raw Normal View History

package log_buffer
import (
"bytes"
2020-09-10 02:21:23 +08:00
"fmt"
"time"
2022-08-18 03:05:07 +08:00
"google.golang.org/protobuf/proto"
"github.com/seaweedfs/seaweedfs/weed/glog"
"github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
"github.com/seaweedfs/seaweedfs/weed/util"
)
2020-09-10 02:21:23 +08:00
var (
2021-01-12 18:30:12 +08:00
ResumeError = fmt.Errorf("resume")
ResumeFromDiskError = fmt.Errorf("resumeFromDisk")
2020-09-10 02:21:23 +08:00
)
2024-01-08 16:03:08 +08:00
type MessagePosition struct {
time.Time // this is the timestamp of the message
BatchIndex int64 // this is only used when the timestamp is not enough to identify the next message, when the timestamp is in the previous batch.
}
func NewMessagePosition(tsNs int64, batchIndex int64) MessagePosition {
return MessagePosition{
Time: time.Unix(0, tsNs).UTC(),
BatchIndex: batchIndex,
}
}
func (logBuffer *LogBuffer) LoopProcessLogData(readerName string, startPosition MessagePosition, inMemoryOnly bool, stopTsNs int64,
waitForDataFn func() bool, eachLogDataFn func(logEntry *filer_pb.LogEntry) error) (lastReadPosition MessagePosition, isDone bool, err error) {
// loop through all messages
var bytesBuf *bytes.Buffer
2024-01-08 16:03:08 +08:00
var batchIndex int64
lastReadPosition = startPosition
2024-01-11 23:55:26 +08:00
var entryCounter int64
defer func() {
if bytesBuf != nil {
2020-08-27 13:40:15 +08:00
logBuffer.ReleaseMemory(bytesBuf)
}
2024-01-11 23:55:26 +08:00
println("LoopProcessLogData", readerName, "sent messages total", entryCounter)
}()
for {
if bytesBuf != nil {
2020-08-27 13:40:15 +08:00
logBuffer.ReleaseMemory(bytesBuf)
}
2024-01-08 16:03:08 +08:00
bytesBuf, batchIndex, err = logBuffer.ReadFromBuffer(lastReadPosition, inMemoryOnly)
if err == ResumeFromDiskError {
time.Sleep(1127 * time.Millisecond)
2024-01-08 16:03:08 +08:00
return lastReadPosition, isDone, ResumeFromDiskError
}
readSize := 0
if bytesBuf != nil {
readSize = bytesBuf.Len()
}
2024-01-11 23:55:26 +08:00
glog.V(0).Infof("%s ReadFromBuffer at %v batch:%d, read bytes:%v batch:%d", readerName, lastReadPosition, lastReadPosition.BatchIndex, readSize, batchIndex)
if bytesBuf == nil {
2024-01-08 16:03:08 +08:00
if batchIndex >= 0 {
lastReadPosition = NewMessagePosition(lastReadPosition.UnixNano(), batchIndex)
}
if stopTsNs != 0 {
isDone = true
return
}
if waitForDataFn() {
continue
} else {
return
}
}
buf := bytesBuf.Bytes()
2024-01-08 16:03:08 +08:00
// fmt.Printf("ReadFromBuffer %s by %v size %d\n", readerName, lastReadPosition, len(buf))
batchSize := 0
for pos := 0; pos+4 < len(buf); {
size := util.BytesToUint32(buf[pos : pos+4])
2020-09-10 02:21:23 +08:00
if pos+4+int(size) > len(buf) {
err = ResumeError
2024-01-11 23:55:26 +08:00
glog.Errorf("LoopProcessLogData: %s read buffer %v read %d entries [%d,%d) from [0,%d)", readerName, lastReadPosition, batchSize, pos, pos+int(size)+4, len(buf))
2020-09-10 02:21:23 +08:00
return
}
entryData := buf[pos+4 : pos+4+int(size)]
logEntry := &filer_pb.LogEntry{}
if err = proto.Unmarshal(entryData, logEntry); err != nil {
2022-07-02 13:43:25 +08:00
glog.Errorf("unexpected unmarshal mq_pb.Message: %v", err)
pos += 4 + int(size)
continue
}
2022-05-31 06:25:21 +08:00
if stopTsNs != 0 && logEntry.TsNs > stopTsNs {
isDone = true
2024-01-11 23:55:26 +08:00
println("stopTsNs", stopTsNs, "logEntry.TsNs", logEntry.TsNs)
2022-05-31 06:25:21 +08:00
return
}
2024-01-08 16:03:08 +08:00
lastReadPosition = NewMessagePosition(logEntry.TsNs, batchIndex)
if err = eachLogDataFn(logEntry); err != nil {
2024-01-11 23:55:26 +08:00
glog.Errorf("LoopProcessLogData: %s process log entry %d %v: %v", readerName, batchSize+1, logEntry, err)
return
}
pos += 4 + int(size)
batchSize++
2024-01-11 23:55:26 +08:00
entryCounter++
2021-06-27 20:51:28 +08:00
}
2024-01-11 23:55:26 +08:00
glog.V(0).Infof("%s sent messages ts[%+v,%+v] size %d\n", readerName, startPosition, lastReadPosition, batchSize)
}
2020-04-21 08:48:06 +08:00
}