1515package scorch
1616
1717import (
18+ "bytes"
1819 "encoding/json"
1920 "fmt"
21+ "io"
2022 "os"
2123 "path/filepath"
2224 "strings"
@@ -513,7 +515,19 @@ func (s *Scorch) Batch(batch *index.Batch) (err error) {
513515 return err
514516}
515517
518+ func (s * Scorch ) getInternal (key []byte ) ([]byte , error ) {
519+ s .rootLock .RLock ()
520+ defer s .rootLock .RUnlock ()
521+ if string (key ) == "_centroid_index_complete" {
522+ return []byte (fmt .Sprintf ("%t" , s .centroidIndex != nil )), nil
523+ }
524+ return nil , nil
525+ }
526+
527+ // min 39 per centroid, recommeded 50
528+ // max 256
516529func (s * Scorch ) Train (batch * index.Batch ) error {
530+ // is the lock really needed?
517531 s .rootLock .Lock ()
518532 defer s .rootLock .Unlock ()
519533 if s .centroidIndex != nil {
@@ -523,6 +537,12 @@ func (s *Scorch) Train(batch *index.Batch) error {
523537 var trainData []index.Document
524538 if s .centroidIndex == nil {
525539 for key , doc := range batch .IndexOps {
540+ if doc != nil {
541+ // insert _id field
542+ // no need to track updates/deletes over here since
543+ // the API is singleton
544+ doc .AddIDField ()
545+ }
526546 if strings .HasPrefix (key , index .TrainDataPrefix ) {
527547 trainData = append (trainData , doc )
528548 }
@@ -537,11 +557,16 @@ func (s *Scorch) Train(batch *index.Batch) error {
537557 //
538558 // note: this might index text data too, how to handle this? s.segmentConfig?
539559 // todo: updates/deletes -> data drift detection
540- seg , _ , err := s .segPlugin .NewEx (trainData , s .segmentConfig )
560+ s .segmentConfig ["training" ] = true
561+ seg , n , err := s .segPlugin .NewEx (trainData , s .segmentConfig )
541562 if err != nil {
542563 return err
543564 }
544- filename := "centroid_index.zap"
565+ // reset the training flag once completed
566+ s .segmentConfig ["training" ] = false
567+ // not suffixing with .zap since the current garbage collection is tailored to .zap ext files
568+ // we don't want to gc this file ever.
569+ filename := "centroid_index"
545570 path := filepath .Join (s .path , filename )
546571
547572 switch seg := seg .(type ) {
@@ -562,7 +587,56 @@ func (s *Scorch) Train(batch *index.Batch) error {
562587 s .centroidIndex = & SegmentSnapshot {
563588 segment : persistedSegment ,
564589 }
565- s .segmentConfig ["getCentroidIndexCallback" ] = s .getCentroidIndex
590+
591+ fmt .Println ("number of bytes written to centroid index" , n )
592+ // s.segmentConfig["getCentroidIndexCallback"] = s.getCentroidIndex
593+ // updateBolt(tx, cetntroid)
594+ // filename := "centroid_index"
595+ // path := filepath.Join(s.path, filename)
596+ // f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0600)
597+ // if err != nil {
598+ // return err
599+ // }
600+
601+ // bufw := bufio.NewWriter(f)
602+ // _, err = bufw.Write([]byte(strings.Join([]string{"centroid_index1", path}, " ")))
603+ // if err != nil {
604+ // return err
605+ // }
606+ // err = bufw.Flush()
607+ // if err != nil {
608+ // return err
609+ // }
610+ // err = f.Sync()
611+ // if err != nil {
612+ // return err
613+ // }
614+ // err = f.Close()
615+ // if err != nil {
616+ // return err
617+ // }
618+
619+ tx , err := s .rootBolt .Begin (true )
620+ if err != nil {
621+ return err
622+ }
623+ defer tx .Rollback ()
624+
625+ snapshotsBucket , err := tx .CreateBucketIfNotExists (util .BoltSnapshotsBucket )
626+ if err != nil {
627+ return err
628+ }
629+
630+ err = snapshotsBucket .Put (util .BoltCentroidIndexKey , []byte (path ))
631+ if err != nil {
632+ return err
633+ }
634+
635+ err = tx .Commit ()
636+ if err != nil {
637+ return err
638+ }
639+
566640 return nil
567641}
568642
@@ -1018,6 +1092,91 @@ func (s *Scorch) CopyReader() index.CopyReader {
10181092 return rv
10191093}
10201094
1095+ func (s * Scorch ) updateCentroidIndexInBolt (tx * bolt.Tx ) error {
1096+ centroidIndexBucket , err := tx .CreateBucketIfNotExists (util .BoltCentroidIndexKey )
1097+ if err != nil {
1098+ return err
1099+ }
1100+
1101+ err = centroidIndexBucket .Put (util .BoltPathKey , []byte ("centroid_index.zap" ))
1102+ if err != nil {
1103+ return err
1104+ }
1105+
1106+ return nil
1107+ }
1108+
1109+ func (s * Scorch ) UpdateFileInBolt (key []byte , value []byte ) error {
1110+ tx , err := s .rootBolt .Begin (true )
1111+ if err != nil {
1112+ return err
1113+ }
1114+ defer tx .Rollback ()
1115+
1116+ snapshotsBucket , err := tx .CreateBucketIfNotExists (util .BoltSnapshotsBucket )
1117+ if err != nil {
1118+ return err
1119+ }
1120+
1121+ // currently this is specific to centroid index file update
1122+ if bytes .Equal (key , util .BoltCentroidIndexKey ) {
1123+ // guard against duplicate updates
1124+ existingValue := snapshotsBucket .Get (key )
1125+ if existingValue != nil {
1126+ return fmt .Errorf ("key already exists" )
1127+ }
1128+
1129+ err = snapshotsBucket .Put (key , value )
1130+ if err != nil {
1131+ return err
1132+ }
1133+ }
1134+
1135+ err = tx .Commit ()
1136+ if err != nil {
1137+ return err
1138+ }
1139+
1140+ err = s .rootBolt .Sync ()
1141+ if err != nil {
1142+ return err
1143+ }
1144+
1145+ return nil
1146+ }
1147+
1148+ // CopyFile copies a specific file to a destination directory which has an access to a bleve index
1149+ // doing a io.Copy() isn't enough because the file needs to be tracked in bolt file as well
1150+ func (s * Scorch ) CopyFile (file string , d index.IndexDirectory ) error {
1151+ s .rootLock .Lock ()
1152+ defer s .rootLock .Unlock ()
1153+
1154+ // this code is currently specific to centroid index file but is future proofed for other files
1155+ // to be updated in the dest's bolt
1156+ if strings .HasSuffix (file , "centroid_index" ) {
1157+ // centroid index file - this is outside the snapshots domain so the bolt update is different
1158+ err := d .UpdateFileInBolt (util .BoltCentroidIndexKey , []byte (file ))
1159+ if err != nil {
1160+ return err
1161+ }
1162+ }
1163+
1164+ dest , err := d .GetWriter (filepath .Join ("store" , file ))
1165+ if err != nil {
1166+ return err
1167+ }
1168+
1169+ source , err := os .Open (filepath .Join (s .path , file ))
1170+ if err != nil {
1171+ return err
1172+ }
1173+
1174+ defer source .Close ()
1175+ defer dest .Close ()
1176+ _ , err = io .Copy (dest , source )
1177+ return err
1178+ }
1179+
10211180// external API to fire a scorch event (EventKindIndexStart) externally from bleve
10221181func (s * Scorch ) FireIndexEvent () {
10231182 s .fireEvent (EventKindIndexStart , 0 )
0 commit comments