2023-10-18 19:34:08 +08:00
|
|
|
package iterator
|
|
|
|
|
|
|
|
import (
|
|
|
|
"sync"
|
|
|
|
|
|
|
|
"go.uber.org/atomic"
|
2024-02-04 10:49:05 +08:00
|
|
|
"go.uber.org/zap"
|
2023-10-18 19:34:08 +08:00
|
|
|
|
|
|
|
"github.com/milvus-io/milvus/internal/storage"
|
2024-02-04 10:49:05 +08:00
|
|
|
"github.com/milvus-io/milvus/pkg/log"
|
2023-10-18 19:34:08 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
var _ Iterator = (*DeltalogIterator)(nil)
|
|
|
|
|
|
|
|
type DeltalogIterator struct {
|
|
|
|
disposeCh chan struct{}
|
|
|
|
disposedOnce sync.Once
|
|
|
|
disposed atomic.Bool
|
|
|
|
|
|
|
|
data *storage.DeleteData
|
2024-02-04 10:49:05 +08:00
|
|
|
blobs []*storage.Blob
|
2023-10-18 19:34:08 +08:00
|
|
|
label *Label
|
|
|
|
pos int
|
|
|
|
}
|
|
|
|
|
2024-02-04 10:49:05 +08:00
|
|
|
func NewDeltalogIterator(v [][]byte, label *Label) *DeltalogIterator {
|
2023-10-18 19:34:08 +08:00
|
|
|
blobs := make([]*storage.Blob, len(v))
|
|
|
|
for i := range blobs {
|
|
|
|
blobs[i] = &storage.Blob{Value: v[i]}
|
|
|
|
}
|
|
|
|
|
|
|
|
return &DeltalogIterator{
|
|
|
|
disposeCh: make(chan struct{}),
|
2024-02-04 10:49:05 +08:00
|
|
|
blobs: blobs,
|
2023-10-18 19:34:08 +08:00
|
|
|
label: label,
|
2024-02-04 10:49:05 +08:00
|
|
|
}
|
2023-10-18 19:34:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (d *DeltalogIterator) HasNext() bool {
|
|
|
|
return !d.isDisposed() && d.hasNext()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *DeltalogIterator) Next() (*LabeledRowData, error) {
|
|
|
|
if d.isDisposed() {
|
|
|
|
return nil, ErrDisposed
|
|
|
|
}
|
|
|
|
|
|
|
|
if !d.hasNext() {
|
|
|
|
return nil, ErrNoMoreRecord
|
|
|
|
}
|
|
|
|
|
|
|
|
row := &DeltalogRow{
|
|
|
|
Pk: d.data.Pks[d.pos],
|
|
|
|
Timestamp: d.data.Tss[d.pos],
|
|
|
|
}
|
|
|
|
d.pos++
|
|
|
|
|
|
|
|
return NewLabeledRowData(row, d.label), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *DeltalogIterator) Dispose() {
|
|
|
|
d.disposed.CompareAndSwap(false, true)
|
|
|
|
d.disposedOnce.Do(func() {
|
|
|
|
close(d.disposeCh)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *DeltalogIterator) hasNext() bool {
|
2024-02-04 10:49:05 +08:00
|
|
|
if d.data == nil && d.blobs != nil {
|
|
|
|
reader := storage.NewDeleteCodec()
|
|
|
|
_, _, dData, err := reader.Deserialize(d.blobs)
|
|
|
|
if err != nil {
|
|
|
|
log.Warn("Deltalog iterator failed to deserialize blobs", zap.Error(err))
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
d.data = dData
|
|
|
|
d.blobs = nil
|
|
|
|
}
|
2023-10-18 19:34:08 +08:00
|
|
|
return int64(d.pos) < d.data.RowCount
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *DeltalogIterator) isDisposed() bool {
|
|
|
|
return d.disposed.Load()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *DeltalogIterator) WaitForDisposed() {
|
|
|
|
<-d.disposeCh
|
|
|
|
}
|