// snapshotAtOrBeforeSeq returns true if the snapshot represents a seq // number at or before the given seq number. func snapshotAtOrBeforeSeq(path string, ss moss.Snapshot, seqMaxKey []byte, seqMaxWant uint64) (bool, error) { // Equivalent of bleve.Index.GetInternal(seqMaxKey). v, err := ss.Get(seqMaxKey, moss.ReadOptions{}) if err != nil { return false, err } if v == nil { return false, nil } if len(v) != 8 { return false, fmt.Errorf("wrong len seqMaxKey: %s, v: %s", seqMaxKey, v) } seqMaxCurr := binary.BigEndian.Uint64(v[0:8]) log.Printf("pindex_bleve_rollback: examining snapshot, path: %s,"+ " seqMaxKey: %s, seqMaxCurr: %d, seqMaxWant: %d", path, seqMaxKey, seqMaxCurr, seqMaxWant) return seqMaxCurr <= seqMaxWant, nil }
// update() mutates this lower level store with latest data from the // given higher level moss.Snapshot and returns a new moss.Snapshot // that the higher level can use which represents this lower level // store. func (s *llStore) update(ssHigher moss.Snapshot, maxBatchSize uint64) ( ssLower moss.Snapshot, err error) { if ssHigher != nil { iter, err := ssHigher.StartIterator(nil, nil, moss.IteratorOptions{ IncludeDeletions: true, SkipLowerLevel: true, }) if err != nil { return nil, err } defer func() { err = iter.Close() if err != nil { s.logf("llStore iter.Close err: %v", err) } }() kvWriter, err := s.kvStore.Writer() if err != nil { return nil, err } defer func() { err = kvWriter.Close() if err != nil { s.logf("llStore kvWriter.Close err: %v", err) } }() batch := kvWriter.NewBatch() defer func() { if batch != nil { err = batch.Close() if err != nil { s.logf("llStore batch.Close err: %v", err) } } }() var readOptions moss.ReadOptions i := uint64(0) for { if i%1000000 == 0 { s.logf("llStore.update, i: %d", i) } ex, key, val, err := iter.CurrentEx() if err == moss.ErrIteratorDone { break } if err != nil { return nil, err } switch ex.Operation { case moss.OperationSet: batch.Set(key, val) case moss.OperationDel: batch.Delete(key) case moss.OperationMerge: val, err = ssHigher.Get(key, readOptions) if err != nil { return nil, err } if val != nil { batch.Set(key, val) } else { batch.Delete(key) } default: return nil, fmt.Errorf("moss store, update,"+ " unexpected operation, ex: %v", ex) } i++ err = iter.Next() if err == moss.ErrIteratorDone { break } if err != nil { return nil, err } if maxBatchSize > 0 && i%maxBatchSize == 0 { err = kvWriter.ExecuteBatch(batch) if err != nil { return nil, err } err = batch.Close() if err != nil { return nil, err } batch = kvWriter.NewBatch() } } if i > 0 { s.logf("llStore.update, ExecuteBatch,"+ " path: %s, total: %d, start", s.llConfig["path"], i) err = kvWriter.ExecuteBatch(batch) if err != nil { return nil, err } s.logf("llStore.update, ExecuteBatch,"+ " path: %s: total: %d, done", s.llConfig["path"], i) } } kvReader, err := s.kvStore.Reader() if err != nil { return nil, err } s.logf("llStore.update, new reader") return &llSnapshot{ llStore: s.addRef(), kvReader: kvReader, refs: 1, }, nil }