github.com/petermattis/pebble@v0.0.0-20190905164901-ab51a2166067/log_recycler.go (about)

     1  // Copyright 2019 The LevelDB-Go and Pebble Authors. All rights reserved. Use
     2  // of this source code is governed by a BSD-style license that can be found in
     3  // the LICENSE file.
     4  
     5  package pebble
     6  
     7  import (
     8  	"fmt"
     9  	"sync"
    10  )
    11  
    12  type logRecycler struct {
    13  	limit int
    14  	mu    struct {
    15  		sync.Mutex
    16  		logNums   []uint64
    17  		maxLogNum uint64
    18  	}
    19  }
    20  
    21  // add attempts to recycle the log file specified by logNum. Returns true if
    22  // the log file should not be deleted (i.e. the log is being recycled), and
    23  // false otherwise.
    24  func (r *logRecycler) add(logNum uint64) bool {
    25  	r.mu.Lock()
    26  	defer r.mu.Unlock()
    27  
    28  	if logNum <= r.mu.maxLogNum {
    29  		// The log file number was already considered for recycling. Don't consider
    30  		// it again. This avoids a race between adding the same log file for
    31  		// recycling multiple times, and removing the log file for actual
    32  		// reuse. Note that we return true because the log was already considered
    33  		// for recycling and either it was deleted on the previous attempt (which
    34  		// means we shouldn't get here) or it was recycled and thus the file
    35  		// shouldn't be deleted.
    36  		return true
    37  	}
    38  	r.mu.maxLogNum = logNum
    39  	if len(r.mu.logNums) >= r.limit {
    40  		return false
    41  	}
    42  	r.mu.logNums = append(r.mu.logNums, logNum)
    43  	return true
    44  }
    45  
    46  // peek returns the log number at the head of the recycling queue, or zero if
    47  // the queue is empty.
    48  func (r *logRecycler) peek() uint64 {
    49  	r.mu.Lock()
    50  	defer r.mu.Unlock()
    51  
    52  	if len(r.mu.logNums) == 0 {
    53  		return 0
    54  	}
    55  	return r.mu.logNums[0]
    56  }
    57  
    58  func (r *logRecycler) count() int {
    59  	r.mu.Lock()
    60  	defer r.mu.Unlock()
    61  	return len(r.mu.logNums)
    62  }
    63  
    64  // pop removes the log number at the head of the recycling queue, enforcing
    65  // that it matches the specifed logNum. An error is returned of the recycling
    66  // queue is empty or the head log number does not match the specified one.
    67  func (r *logRecycler) pop(logNum uint64) error {
    68  	r.mu.Lock()
    69  	defer r.mu.Unlock()
    70  
    71  	if len(r.mu.logNums) == 0 {
    72  		return fmt.Errorf("pebble: log recycler empty")
    73  	}
    74  	if r.mu.logNums[0] != logNum {
    75  		return fmt.Errorf("pebble: log recycler invalid %d vs %d", logNum, r.mu.logNums)
    76  	}
    77  	r.mu.logNums = r.mu.logNums[1:]
    78  	return nil
    79  }