Skip to content

Commit bf18138

Browse files
committed
bug fix
1 parent 0f61c0e commit bf18138

2 files changed

Lines changed: 77 additions & 14 deletions

File tree

index/scorch/scorch.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@ type trainer interface {
123123
// trainer specific file transfer operations
124124
copyFileLOCKED(file string, d index.IndexDirectory) error
125125
updateBolt(snapshotsBucket *util.BoltBucketImpl, key []byte, value []byte) error
126+
127+
dropFileWriterIDs(ids map[string]struct{}) error
128+
FileWriterIDsInUse() (map[string]struct{}, error)
126129
}
127130

128131
type ScorchErrorType string
@@ -1365,7 +1368,7 @@ func (s *Scorch) DropFileWriterIDs(ids map[string]struct{}) error {
13651368
}
13661369

13671370
if s.trainer != nil {
1368-
err := s.trainer.removeFileWriterIDs(ids)
1371+
err := s.trainer.dropFileWriterIDs(ids)
13691372
if err != nil {
13701373
return err
13711374
}

index/scorch/train_vector.go

Lines changed: 73 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,12 @@ import (
3737
)
3838

3939
type trainRequest struct {
40-
finalSample bool
41-
sampleSize int
42-
ackCh chan error
43-
sample segment.Segment
44-
trainingParams *index.TrainingParams
40+
finalSample bool
41+
sampleSize int
42+
ackCh chan error
43+
sample segment.Segment
44+
trainingParams *index.TrainingParams
45+
removedFileWriterIDs map[string]struct{}
4546
}
4647

4748
type vectorTrainer struct {
@@ -85,6 +86,7 @@ func moveFile(sourcePath, destPath string) error {
8586
return nil
8687
}
8788

89+
// update with the new writer API
8890
func (t *vectorTrainer) persistToBolt(trainReq *trainRequest) error {
8991
tx, err := t.parent.rootBolt.Begin(true)
9092
if err != nil {
@@ -159,6 +161,16 @@ func (t *vectorTrainer) trainLoop() {
159161
t.config[index.TrainingKey] = trainReq.trainingParams
160162
}
161163

164+
// remove any file writer ids that are no longer in use
165+
if trainReq.removedFileWriterIDs != nil {
166+
err := t.removeFileWriterIDs(trainReq.removedFileWriterIDs)
167+
if err != nil {
168+
trainReq.ackCh <- fmt.Errorf("error removing file writer ids: %v", err)
169+
close(trainReq.ackCh)
170+
return
171+
}
172+
}
173+
162174
// no sample segment: just persist state if this is the final sample and move on.
163175
if sampleSeg == nil {
164176
if trainReq.finalSample {
@@ -430,31 +442,76 @@ func (t *vectorTrainer) updateBolt(snapshotsBucket *util.BoltBucketImpl, key []b
430442
return nil
431443
}
432444

433-
func (t *vectorTrainer) removeFileWriterIDs(ids map[string]struct{}) error {
445+
func (t *vectorTrainer) dropFileWriterIDs(ids map[string]struct{}) error {
434446
t.m.Lock()
435447
defer t.m.Unlock()
436-
path := filepath.Join(t.parent.path, index.TrainedIndexFileName)
437-
writer, err := util.NewFileWriter([]byte(path))
448+
449+
trainReq := &trainRequest{
450+
ackCh: make(chan error),
451+
removedFileWriterIDs: ids,
452+
}
453+
t.trainCh <- trainReq
454+
err := <-trainReq.ackCh
455+
if err != nil {
456+
return fmt.Errorf("train_vector: dropFileWriterIDs() err'd out with: %w", err)
457+
}
458+
459+
return err
460+
}
461+
462+
func (t *vectorTrainer) removeFileWriterIDs(ids map[string]struct{}) error {
463+
// create a new writer to update the trainerBucket in bolt
464+
boltPath := filepath.Join(t.parent.path, "root.bolt")
465+
writer, err := util.NewFileWriter([]byte(boltPath))
438466
if err != nil {
439467
return err
440468
}
441469

470+
// only the writer id needs to be updated in the bucket
471+
err = t.parent.rootBolt.Update(func(tx *util.BoltTxImpl) error {
472+
snapshots := tx.Bucket(util.BoltSnapshotsBucket)
473+
if snapshots == nil {
474+
return nil
475+
}
476+
c := snapshots.Cursor()
477+
for k, _ := c.First(); k != nil; k, _ = c.Next() {
478+
if bytes.Equal(k, util.BoltTrainerKey) {
479+
trainerBucket := snapshots.GetBucket(k)
480+
if trainerBucket == nil {
481+
continue
482+
}
483+
oldWriterID, err := trainerBucket.Get(util.BoltMetaDataFileWriterIDKey, nil)
484+
if err != nil {
485+
return err
486+
}
487+
if _, ok := ids[string(oldWriterID)]; ok {
488+
err = trainerBucket.Put(util.BoltMetaDataFileWriterIDKey, []byte(writer.Id()), writer)
489+
if err != nil {
490+
return err
491+
}
492+
}
493+
}
494+
}
495+
return nil
496+
})
497+
498+
// invoke the merge API and let the zap side of things handle the update of writer IDs and also
499+
// the data in the trained index.
500+
trainedIndexPath := filepath.Join(t.parent.path, index.TrainedIndexFileName)
442501
if encryptedIndex, ok := t.trainedIndex.segment.(segment.SegmentWithCallbacks); ok {
443502
if _, ok := ids[encryptedIndex.CallbackId()]; ok {
444-
445503
_, _, err := t.parent.segPlugin.MergeUsing([]segment.Segment{t.trainedIndex.segment},
446-
[]*roaring.Bitmap{nil, nil}, path+".tmp", t.parent.closeCh, nil, t.config)
504+
[]*roaring.Bitmap{nil, nil}, trainedIndexPath+".tmp", t.parent.closeCh, nil, t.config)
447505
if err != nil {
448506
return err
449507
}
450508

451-
// todo: handle removeFileWriterIDs call happens during training
452509
t.trainedIndex.segment.Close()
453-
if err = moveFile(path+".tmp", path); err != nil {
510+
if err = moveFile(trainedIndexPath+".tmp", trainedIndexPath); err != nil {
454511
return err
455512
}
456513

457-
trainedIndex, err := t.parent.segPlugin.OpenUsing(path, t.config)
514+
trainedIndex, err := t.parent.segPlugin.OpenUsing(trainedIndexPath, t.config)
458515
if err != nil {
459516
return err
460517
}
@@ -465,6 +522,9 @@ func (t *vectorTrainer) removeFileWriterIDs(ids map[string]struct{}) error {
465522

466523
}
467524
}
525+
return err
526+
}
527+
468528
func (t *vectorTrainer) FileWriterIDsInUse() (map[string]struct{}, error) {
469529
t.m.RLock()
470530
defer t.m.RUnlock()

0 commit comments

Comments
 (0)