github.com/balzaczyy/golucene@v0.0.0-20151210033525-d0be9ee89713/core/index/mergeControl.go (about)

     1  package index
     2  
     3  import (
     4  	"container/list"
     5  	. "github.com/balzaczyy/golucene/core/codec/spi"
     6  	"github.com/balzaczyy/golucene/core/util"
     7  	"sync"
     8  )
     9  
    10  type MergeControl struct {
    11  	sync.Locker
    12  	infoStream util.InfoStream
    13  
    14  	readerPool *ReaderPool
    15  
    16  	// Holds all SegmentInfo instances currently involved in merges
    17  	mergingSegments map[*SegmentCommitInfo]bool
    18  
    19  	pendingMerges *list.List
    20  	runningMerges map[*OneMerge]bool
    21  	mergeSignal   *sync.Cond
    22  
    23  	stopMerges bool
    24  }
    25  
    26  func newMergeControl(infoStream util.InfoStream, readerPool *ReaderPool) *MergeControl {
    27  	lock := &sync.Mutex{}
    28  	return &MergeControl{
    29  		Locker:          lock,
    30  		infoStream:      infoStream,
    31  		readerPool:      readerPool,
    32  		mergingSegments: make(map[*SegmentCommitInfo]bool),
    33  		pendingMerges:   list.New(),
    34  		runningMerges:   make(map[*OneMerge]bool),
    35  		mergeSignal:     sync.NewCond(lock),
    36  	}
    37  }
    38  
    39  // L2272
    40  /*
    41  Aborts runing merges. Be careful when using this method: when you
    42  abort a long-running merge, you lose a lot of work that must later be
    43  redone.
    44  */
    45  func (mc *MergeControl) abortAllMerges() {
    46  	mc.Lock() // synchronized
    47  	defer mc.Unlock()
    48  
    49  	mc.stopMerges = true
    50  
    51  	// Abort all pending & running merges:
    52  	for e := mc.pendingMerges.Front(); e != nil; e = e.Next() {
    53  		merge := e.Value.(*OneMerge)
    54  		if mc.infoStream.IsEnabled("IW") {
    55  			mc.infoStream.Message("IW", "now abort pending merge %v",
    56  				mc.readerPool.segmentsToString(merge.segments))
    57  		}
    58  		merge.abort()
    59  		mc.mergeFinish(merge)
    60  	}
    61  	mc.pendingMerges.Init()
    62  
    63  	for merge, _ := range mc.runningMerges {
    64  		if mc.infoStream.IsEnabled("IW") {
    65  			mc.infoStream.Message("IW", "now abort running merge %v",
    66  				mc.readerPool.segmentsToString(merge.segments))
    67  		}
    68  		merge.abort()
    69  	}
    70  
    71  	// These merges periodically check whether they have
    72  	// been aborted, and stop if so.  We wait here to make
    73  	// sure they all stop.  It should not take very long
    74  	// because the merge threads periodically check if
    75  	// they are aborted.
    76  	for len(mc.runningMerges) > 0 {
    77  		if mc.infoStream.IsEnabled("IW") {
    78  			mc.infoStream.Message("IW", "now wait for %v running merge(s) to abort",
    79  				len(mc.runningMerges))
    80  		}
    81  		mc.mergeSignal.Wait()
    82  	}
    83  
    84  	mc.stopMerges = false
    85  
    86  	assert(len(mc.mergingSegments) == 0)
    87  
    88  	if mc.infoStream.IsEnabled("IW") {
    89  		mc.infoStream.Message("IW", "all running merges have aborted")
    90  	}
    91  }
    92  
    93  /*
    94  Wait for any currently outstanding merges to finish.
    95  
    96  It is guaranteed that any merges started prior to calling this method
    97  will have completed once this method completes.
    98  */
    99  func (mc *MergeControl) waitForMerges() {
   100  	mc.Lock() // synchronized
   101  	defer mc.Unlock()
   102  	// ensureOpen(false)
   103  
   104  	if mc.infoStream.IsEnabled("IW") {
   105  		mc.infoStream.Message("IW", "waitForMerges")
   106  	}
   107  
   108  	for mc.pendingMerges.Len() > 0 || len(mc.runningMerges) > 0 {
   109  		mc.mergeSignal.Wait()
   110  	}
   111  
   112  	assert(len(mc.mergingSegments) == 0)
   113  
   114  	if mc.infoStream.IsEnabled("IW") {
   115  		mc.infoStream.Message("IW", "waitForMerges done")
   116  	}
   117  }
   118  
   119  // L3696
   120  /*
   121  Does finishing for a merge, which is fast but holds the synchronized
   122  lock on MergeControl instance.
   123  
   124  Note: it must be externally synchronized or used internally.
   125  */
   126  func (mc *MergeControl) mergeFinish(merge *OneMerge) {
   127  	// forceMerge, addIndexes or abortAllmerges may be waiting on
   128  	// merges to finish
   129  	// notifyAll()
   130  
   131  	// It's possible we are called twice, eg if there was an error
   132  	// inside mergeInit()
   133  	if merge.registerDone {
   134  		for _, info := range merge.segments {
   135  			delete(mc.mergingSegments, info)
   136  		}
   137  		merge.registerDone = false
   138  	}
   139  
   140  	delete(mc.runningMerges, merge)
   141  	if len(mc.runningMerges) == 0 {
   142  		mc.mergeSignal.Signal()
   143  	}
   144  }