func (ds *BufferedUpdatesStream) prune(infos *SegmentInfos) {
	ds.assertDeleteStats()
	var minGen int64 = math.MaxInt64
	for _, info := range infos.Segments {
		if info.BufferedUpdatesGen < minGen {
			minGen = info.BufferedUpdatesGen
		}
	}
	if ds.infoStream.IsEnabled("BD") {
		var dir store.Directory
		if len(infos.Segments) > 0 {
			dir = infos.Segments[0].Info.Dir
		}
		ds.infoStream.Message("BD", "prune sis=%v minGen=%v packetCount=%v",
			infos.toString(dir), minGen, len(ds.updates))
	}
	for delIDX, update := range ds.updates {
		if update.gen >= minGen {
			ds.pruneUpdates(delIDX)
			ds.assertDeleteStats()
			return
		}
	}
	ds.pruneUpdates(len(ds.updates))
	assert(!ds.any())
	ds.assertDeleteStats()
}
Lock order IW -> BD
/*
Removes any BufferedUpdates that we no longer need to store because
all segments in the index have had the deletes applied.
package index
import (
	"errors"
	"fmt"
	. "github.com/balzaczyy/golucene/core/codec/spi"
	"github.com/balzaczyy/golucene/core/store"
	"github.com/balzaczyy/golucene/core/util"
	"log"
	"math"
	"sort"
	"sync"
	"sync/atomic"
	"time"
)
type ApplyDeletesResult struct {
	anyDeletes bool
	gen int64
	allDeleted []*SegmentCommitInfo
}
type SegInfoByDelGen []*SegmentCommitInfo
func (a SegInfoByDelGen) Len() int           { return len(a) }
func (a SegInfoByDelGen) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a SegInfoByDelGen) Less(i, j int) bool { return a[i].BufferedUpdatesGen < a[j].BufferedUpdatesGen }
type Query interface{}
type QueryAndLimit struct {
}
type CoalescedUpdates struct {
	_queries         map[Query]int
	numericDVUpdates []*DocValuesUpdate
	binaryDVUpdates  []*DocValuesUpdate
}
func newCoalescedUpdates() *CoalescedUpdates {
	return &CoalescedUpdates{
		_queries: make(map[Query]int),
	}
}
func (cd *CoalescedUpdates) String() string {
	panic("not implemented yet")
}
func (cd *CoalescedUpdates) update(in *FrozenBufferedUpdates) {
	panic("not implemented yet")
}
func (cd *CoalescedUpdates) terms() []*Term {
	panic("not implemented yet")
}
func (cd *CoalescedUpdates) queries() []*QueryAndLimit {
	panic("not implemented yet")
}
type BufferedUpdatesStream struct {
	sync.Locker
	updates []*FrozenBufferedUpdates
	nextGen int64
	lastDeleteTerm *Term
	infoStream util.InfoStream
	bytesUsed  int64  
	numTerms   int32  
}
func newBufferedUpdatesStream(infoStream util.InfoStream) *BufferedUpdatesStream {
	return &BufferedUpdatesStream{
		Locker:     &sync.Mutex{},
		updates:    make([]*FrozenBufferedUpdates, 0),
		nextGen:    1,
		infoStream: infoStream,
	}
}
func (s *BufferedUpdatesStream) push(packet *FrozenBufferedUpdates) int64 {
	panic("not implemented yet")
}
func (ds *BufferedUpdatesStream) clear() {
	ds.Lock()
	defer ds.Unlock()
	ds.updates = nil
	ds.nextGen = 1
	atomic.StoreInt32(&ds.numTerms, 0)
	atomic.StoreInt64(&ds.bytesUsed, 0)
}
func (ds *BufferedUpdatesStream) any() bool {
	return atomic.LoadInt64(&ds.bytesUsed) != 0
}
func (ds *BufferedUpdatesStream) RamBytesUsed() int64 {
	return atomic.LoadInt64(&ds.bytesUsed)
}
func (ds *BufferedUpdatesStream) applyDeletesAndUpdates(readerPool *ReaderPool, infos []*SegmentCommitInfo) (*ApplyDeletesResult, error) {
	ds.Lock()
	defer ds.Unlock()
	if len(infos) == 0 {
		ds.nextGen++
		return &ApplyDeletesResult{false, ds.nextGen - 1, nil}, nil
	}
	t0 := time.Now()
	ds.assertDeleteStats()
	if !ds.any() {
		if ds.infoStream.IsEnabled("BD") {
			ds.infoStream.Message("BD", "applyDeletes: no deletes; skipping")
		}
		ds.nextGen++
		return &ApplyDeletesResult{false, ds.nextGen - 1, nil}, nil
	}
	if ds.infoStream.IsEnabled("BD") {
		ds.infoStream.Message("BD", "applyDeletes: infos=%v packetCount=%v", infos, len(ds.updates))
	}
	gen := ds.nextGen
	ds.nextGen++
	infos2 := make([]*SegmentCommitInfo, len(infos))
	copy(infos2, infos)
	sort.Sort(SegInfoByDelGen(infos2))
	var coalescedUpdates *CoalescedUpdates
	var anyNewDeletes bool
	infosIDX := len(infos2) - 1
	delIDX := len(ds.updates) - 1
	var allDeleted []*SegmentCommitInfo
	for infosIDX >= 0 {
		log.Printf("BD: cycle delIDX=%v infoIDX=%v", delIDX, infosIDX)
		var packet *FrozenBufferedUpdates
		if delIDX >= 0 {
			packet = ds.updates[delIDX]
		}
		info := infos2[infosIDX]
		segGen := info.BufferedUpdatesGen
		if packet != nil && segGen < packet.gen {
			log.Println("  coalesce")
			if coalescedUpdates == nil {
				coalescedUpdates = newCoalescedUpdates()
			}
			if !packet.isSegmentPrivate {
				coalescedUpdates.update(packet)
			}
			delIDX--
		} else if packet != nil && segGen == packet.gen {
			assertn(packet.isSegmentPrivate,
				"Packet and Segments deletegen can only match on a segment private del packet gen=%v",
				segGen)
			log.Println("  eq")
			assert(readerPool.infoIsLive(info))
			rld := readerPool.get(info, true)
			reader, err := rld.reader(store.IO_CONTEXT_READ)
			if err != nil {
				return nil, err
			}
			delCount, segAllDeletes, err := func() (delCount int64, segAllDeletes bool, err error) {
				defer func() {
					err = mergeError(err, rld.release(reader))
					err = mergeError(err, readerPool.release(rld))
				}()
				dvUpdates := newDocValuesFieldUpdatesContainer()
				if coalescedUpdates != nil {
					fmt.Println("    del coalesced")
					var delta int64
					delta, err = ds._applyTermDeletes(coalescedUpdates.terms(), rld, reader)
					if err == nil {
						delCount += delta
						delta, err = applyQueryDeletes(coalescedUpdates.queries(), rld, reader)
						if err == nil {
							delCount += delta
							err = ds.applyDocValuesUpdates(coalescedUpdates.numericDVUpdates, rld, reader, dvUpdates)
							if err == nil {
								err = ds.applyDocValuesUpdates(coalescedUpdates.binaryDVUpdates, rld, reader, dvUpdates)
							}
						}
					}
					if err != nil {
						return
					}
				}
				fmt.Println("    del exact")
				var delta int64
				delta, err = applyQueryDeletes(packet.queries(), rld, reader)
				if err == nil {
					delCount += delta
					err = ds.applyDocValuesUpdates(packet.numericDVUpdates, rld, reader, dvUpdates)
					if err == nil {
						err = ds.applyDocValuesUpdates(packet.binaryDVUpdates, rld, reader, dvUpdates)
						if err == nil && dvUpdates.any() {
							err = rld.writeFieldUpdates(info.Info.Dir, dvUpdates)
						}
					}
				}
				if err != nil {
					return
				}
				fullDelCount := rld.info.DelCount() + rld.pendingDeleteCount()
				infoDocCount := rld.info.Info.DocCount()
				assert(fullDelCount <= infoDocCount)
				return delCount, fullDelCount == infoDocCount, nil
			}()
			if err != nil {
				return nil, err
			}
			anyNewDeletes = anyNewDeletes || (delCount > 0)
			if segAllDeletes {
				allDeleted = append(allDeleted, info)
			}
			if ds.infoStream.IsEnabled("BD") {
				var suffix string
				if segAllDeletes {
					suffix = " 100%% deleted"
				}
				ds.infoStream.Message("BD", "Seg=%v segGen=%v segDeletes=[%v]; coalesced deletes=[%v] newDelCount=%v%v",
					info, segGen, packet, coalescedUpdates, delCount, suffix)
			}
			if coalescedUpdates == nil {
				coalescedUpdates = newCoalescedUpdates()
			}
			delIDX--
			infosIDX--
			info.SetBufferedUpdatesGen(gen)
		} else {
			log.Println("  gt")
			if coalescedUpdates != nil {
				assert(readerPool.infoIsLive(info))
				rld := readerPool.get(info, true)
				reader, err := rld.reader(store.IO_CONTEXT_READ)
				if err != nil {
					return nil, err
				}
				delCount, segAllDeletes, err := func() (delCount int64, segAllDeletes bool, err error) {
					defer func() {
						err = mergeError(err, rld.release(reader))
						err = mergeError(err, readerPool.release(rld))
					}()
					var delta int64
					delta, err = ds._applyTermDeletes(coalescedUpdates.terms(), rld, reader)
					if err == nil {
						delCount += delta
						delta, err = applyQueryDeletes(coalescedUpdates.queries(), rld, reader)
						if err == nil {
							delCount += delta
							dvUpdates := newDocValuesFieldUpdatesContainer()
							err = ds.applyDocValuesUpdates(coalescedUpdates.numericDVUpdates, rld, reader, dvUpdates)
							if err == nil {
								err = ds.applyDocValuesUpdates(coalescedUpdates.binaryDVUpdates, rld, reader, dvUpdates)
								if err == nil && dvUpdates.any() {
									err = rld.writeFieldUpdates(info.Info.Dir, dvUpdates)
								}
							}
						}
					}
					if err != nil {
						return
					}
					fullDelCount := rld.info.DelCount() + rld.pendingDeleteCount()
					infoDocCount := rld.info.Info.DocCount()
					assert(fullDelCount <= infoDocCount)
					return delCount, fullDelCount == infoDocCount, nil
				}()
				if err != nil {
					return nil, err
				}
				anyNewDeletes = anyNewDeletes || (delCount > 0)
				if segAllDeletes {
					allDeleted = append(allDeleted, info)
				}
				if ds.infoStream.IsEnabled("BD") {
					var suffix string
					if segAllDeletes {
						suffix = " 100%% deleted"
					}
					ds.infoStream.Message("BD", "Seg=%v segGen=%v coalesced deletes=[%v] newDelCount=%v%v",
						info, segGen, coalescedUpdates, delCount, suffix)
				}
			}
			info.SetBufferedUpdatesGen(gen)
			infosIDX--
		}
	}
	ds.assertDeleteStats()
	if ds.infoStream.IsEnabled("BD") {
		ds.infoStream.Message("BD", "applyDeletes took %v", time.Now().Sub(t0))
	}
	return &ApplyDeletesResult{anyNewDeletes, gen, allDeleted}, nil
}
func mergeError(err, err2 error) error {
	if err == nil {
		return err2
	} else {
		return errors.New(fmt.Sprintf("%v\n  %v", err, err2))
	}
}