Skip to content

Commit ecbc5bd

Browse files
authored
MB-65860: Introducing support for fileIO Callbacks (#2209)
1 parent 8a44c37 commit ecbc5bd

16 files changed

Lines changed: 912 additions & 418 deletions

builder.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,10 @@ func newBuilder(path string, mapping mapping.IndexMapping, config map[string]int
7373

7474
// do not use real config, as these are options for the builder,
7575
// not the resulting index
76-
meta := newIndexMeta(scorch.Name, scorch.Name, map[string]interface{}{})
76+
meta, err := newIndexMeta(scorch.Name, scorch.Name, map[string]interface{}{}, path)
77+
if err != nil {
78+
return nil, err
79+
}
7780
err = meta.Save(path)
7881
if err != nil {
7982
return nil, err

go.mod

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module github.com/blevesearch/bleve/v2
22

3-
go 1.24.0
3+
go 1.25.0
44

55
require (
66
github.com/RoaringBitmap/roaring/v2 v2.14.5
@@ -29,7 +29,7 @@ require (
2929
github.com/couchbase/moss v0.2.0
3030
github.com/spf13/cobra v1.10.2
3131
go.etcd.io/bbolt v1.4.0
32-
golang.org/x/text v0.22.0
32+
golang.org/x/text v0.35.0
3333
google.golang.org/protobuf v1.36.6
3434
)
3535

@@ -41,5 +41,6 @@ require (
4141
github.com/json-iterator/go v0.0.0-20171115153421-f7279a603ede // indirect
4242
github.com/mschoch/smat v0.2.0 // indirect
4343
github.com/spf13/pflag v1.0.9 // indirect
44-
golang.org/x/sys v0.40.0 // indirect
44+
golang.org/x/net v0.51.0 // indirect
45+
golang.org/x/sys v0.42.0 // indirect
4546
)

go.sum

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -90,19 +90,20 @@ github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD
9090
go.etcd.io/bbolt v1.4.0 h1:TU77id3TnN/zKr7CO/uk+fBCwF2jGcMuw2B/FMAzYIk=
9191
go.etcd.io/bbolt v1.4.0/go.mod h1:AsD+OCi/qPN1giOX1aiLAha3o1U8rAz65bvN4j0sRuk=
9292
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
93-
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA=
9493
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
94+
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo=
95+
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=
9596
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
96-
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
97-
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
97+
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
98+
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
9899
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
99100
golang.org/x/sys v0.0.0-20181221143128-b4a75ba826a6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
100-
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
101-
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
101+
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
102+
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
102103
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
103104
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
104-
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
105-
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
105+
golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
106+
golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
106107
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
107108
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
108109
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=

index.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,11 @@ type SynonymIndex interface {
389389
IndexSynonym(id string, collection string, definition *SynonymDefinition) error
390390
}
391391

392+
type IndexWithCallbacks interface {
393+
FileWriterIDsInUse() (map[string]struct{}, error)
394+
DropFileWriterIDs(ids map[string]struct{}) error
395+
}
396+
392397
type InsightsIndex interface {
393398
Index
394399
// TermFrequencies returns the tokens ordered by frequencies for the field index.

index/scorch/merge.go

Lines changed: 67 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,19 @@ import (
3131

3232
const merger = "merger"
3333

34+
// used in the context of mergerCtrl to provide a way to verify
35+
// the completion of a merge operation
36+
const mergeDoneKey = "mergeDone"
37+
38+
type mergeDoneChan chan error
39+
40+
// used in the context of mergerCtrl to provide a way to use
41+
// a custom merge plan instead of the one generated by the
42+
// default merge planner
43+
const mergePlanFuncKey = "mergePlanFunc"
44+
45+
type mergePlanFunc func(*IndexSnapshot) (*mergeplan.MergePlan, error)
46+
3447
func (s *Scorch) mergerLoop() {
3548
defer func() {
3649
if r := recover(); r != nil {
@@ -95,11 +108,9 @@ OUTER:
95108
continue OUTER
96109
}
97110

98-
startTime := time.Now()
99-
100111
// lets get started
101-
err := s.planMergeAtSnapshot(ctrlMsg.ctx, ctrlMsg.options,
102-
ourSnapshot)
112+
startTime := time.Now()
113+
err := s.planMergeAtSnapshot(ctrlMsg, ourSnapshot)
103114
if err != nil {
104115
atomic.StoreUint64(&s.iStats.mergeEpoch, 0)
105116
if err == segment.ErrClosed {
@@ -286,42 +297,64 @@ func (w *closeChWrapper) listen() {
286297
}
287298
}
288299

289-
func (s *Scorch) planMergeAtSnapshot(ctx context.Context,
290-
options *mergeplan.MergePlanOptions, ourSnapshot *IndexSnapshot) error {
291-
// build list of persisted segments in this snapshot
292-
var onlyPersistedSnapshots []mergeplan.Segment
293-
for _, segmentSnapshot := range ourSnapshot.segment {
294-
if _, ok := segmentSnapshot.segment.(segment.PersistedSegment); ok {
295-
onlyPersistedSnapshots = append(onlyPersistedSnapshots, segmentSnapshot)
300+
// planMergeAtSnapshot plans and executes the merge operations for a given snapshot
301+
// if there is a custom merge plan function provided, it uses that to get the merge plan
302+
// otherwise, it builds the merge plan using the default planner and executes the merge tasks in the plan.
303+
func (s *Scorch) planMergeAtSnapshot(ctrlMsg *mergerCtrl, ourSnapshot *IndexSnapshot) error {
304+
var mergePlan *mergeplan.MergePlan
305+
// if a merge plan function is provided in the context, use it to get the merge plan
306+
if mergePlanFunc, ok := ctrlMsg.ctx.Value(mergePlanFuncKey).(mergePlanFunc); ok {
307+
var err error
308+
mergePlan, err = mergePlanFunc(ourSnapshot)
309+
if err != nil {
310+
atomic.AddUint64(&s.stats.TotFileMergePlanErr, 1)
311+
return fmt.Errorf("merge planning err: %v", err)
296312
}
297313
}
298314

299-
atomic.AddUint64(&s.stats.TotFileMergePlan, 1)
315+
// default to making a merge plan if a custom one is not provided
316+
if mergePlan == nil {
317+
// build list of persisted segments in this snapshot
318+
var onlyPersistedSnapshots []mergeplan.Segment
319+
for _, segmentSnapshot := range ourSnapshot.segment {
320+
if _, ok := segmentSnapshot.segment.(segment.PersistedSegment); ok {
321+
onlyPersistedSnapshots = append(onlyPersistedSnapshots, segmentSnapshot)
322+
}
323+
}
300324

301-
// give this list to the planner
302-
resultMergePlan, err := mergeplan.Plan(onlyPersistedSnapshots, options)
303-
if err != nil {
304-
atomic.AddUint64(&s.stats.TotFileMergePlanErr, 1)
305-
return fmt.Errorf("merge planning err: %v", err)
306-
}
307-
if resultMergePlan == nil {
308-
// nothing to do
309-
atomic.AddUint64(&s.stats.TotFileMergePlanNone, 1)
310-
return nil
311-
}
312-
atomic.AddUint64(&s.stats.TotFileMergePlanOk, 1)
325+
atomic.AddUint64(&s.stats.TotFileMergePlan, 1)
313326

314-
atomic.AddUint64(&s.stats.TotFileMergePlanTasks, uint64(len(resultMergePlan.Tasks)))
327+
// give this list to the planner
328+
var err error
329+
mergePlan, err = mergeplan.Plan(onlyPersistedSnapshots, ctrlMsg.options)
330+
if err != nil {
331+
atomic.AddUint64(&s.stats.TotFileMergePlanErr, 1)
332+
return fmt.Errorf("merge planning err: %v", err)
333+
}
334+
if mergePlan == nil {
335+
// nothing to do
336+
atomic.AddUint64(&s.stats.TotFileMergePlanNone, 1)
337+
return nil
338+
}
339+
}
315340

316-
// process tasks in serial for now
317-
var filenames []string
341+
atomic.AddUint64(&s.stats.TotFileMergePlanOk, 1)
342+
atomic.AddUint64(&s.stats.TotFileMergePlanTasks, uint64(len(mergePlan.Tasks)))
318343

319-
cw := newCloseChWrapper(s.closeCh, ctx)
344+
cw := newCloseChWrapper(s.closeCh, ctrlMsg.ctx)
320345
defer cw.close()
321-
322346
go cw.listen()
323347

324-
for _, task := range resultMergePlan.Tasks {
348+
var filenames []string
349+
var err error
350+
defer func() {
351+
// send error to done channel if present
352+
if done, ok := cw.ctx.Value(mergeDoneKey).(chan error); ok {
353+
done <- err
354+
}
355+
}()
356+
357+
for _, task := range mergePlan.Tasks {
325358
if len(task.Segments) == 0 {
326359
atomic.AddUint64(&s.stats.TotFileMergePlanTasksSegmentsEmpty, 1)
327360
continue
@@ -369,7 +402,8 @@ func (s *Scorch) planMergeAtSnapshot(ctx context.Context,
369402

370403
atomic.AddUint64(&s.stats.TotFileMergeZapBeg, 1)
371404
prevBytesReadTotal := cumulateBytesRead(segmentsToMerge)
372-
newDocNums, _, err := s.segPlugin.MergeUsing(segmentsToMerge, docsToDrop, path,
405+
var newDocNums [][]uint64
406+
newDocNums, _, err = s.segPlugin.MergeUsing(segmentsToMerge, docsToDrop, path,
373407
cw.cancelCh, s, s.segmentConfig)
374408
atomic.AddUint64(&s.stats.TotFileMergeZapEnd, 1)
375409

@@ -422,7 +456,8 @@ func (s *Scorch) planMergeAtSnapshot(ctx context.Context,
422456
select {
423457
case <-s.closeCh:
424458
_ = seg.Close()
425-
return segment.ErrClosed
459+
err = segment.ErrClosed
460+
return err
426461
case s.merges <- sm:
427462
atomic.AddUint64(&s.stats.TotFileMergeIntroductions, 1)
428463
}

0 commit comments

Comments
 (0)