github.com/coocood/badger@v1.5.1-0.20200528065104-c02ac3616d04/util.go (about)

     1  /*
     2   * Copyright 2017 Dgraph Labs, Inc. and Contributors
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package badger
    18  
    19  import (
    20  	"io/ioutil"
    21  	"math/rand"
    22  	"sync/atomic"
    23  	"time"
    24  
    25  	"github.com/coocood/badger/table/sstable"
    26  	"github.com/coocood/badger/y"
    27  	"github.com/pingcap/errors"
    28  )
    29  
    30  // summary is produced when DB is closed. Currently it is used only for testing.
    31  type summary struct {
    32  	fileIDs map[uint64]bool
    33  }
    34  
    35  func (s *levelsController) getSummary() *summary {
    36  	out := &summary{
    37  		fileIDs: make(map[uint64]bool),
    38  	}
    39  	for _, l := range s.levels {
    40  		l.getSummary(out)
    41  	}
    42  	return out
    43  }
    44  
    45  func (s *levelHandler) getSummary(sum *summary) {
    46  	s.RLock()
    47  	defer s.RUnlock()
    48  	for _, t := range s.tables {
    49  		sum.fileIDs[t.ID()] = true
    50  	}
    51  }
    52  
    53  func (s *DB) validate() error { return s.lc.validate() }
    54  
    55  func (s *levelsController) validate() error {
    56  	for _, l := range s.levels {
    57  		if err := l.validate(); err != nil {
    58  			return errors.Wrap(err, "Levels Controller")
    59  		}
    60  	}
    61  	return nil
    62  }
    63  
    64  // Check does some sanity check on one level of data or in-memory index.
    65  func (s *levelHandler) validate() error {
    66  	if s.level == 0 {
    67  		return nil
    68  	}
    69  
    70  	s.RLock()
    71  	defer s.RUnlock()
    72  	numTables := len(s.tables)
    73  	for j := 1; j < numTables; j++ {
    74  		if j >= len(s.tables) {
    75  			return errors.Errorf("Level %d, j=%d numTables=%d", s.level, j, numTables)
    76  		}
    77  
    78  		if s.tables[j-1].Biggest().Compare(s.tables[j].Smallest()) >= 0 {
    79  			return errors.Errorf(
    80  				"Inter: %q vs %q: level=%d j=%d numTables=%d",
    81  				string(s.tables[j-1].Biggest().UserKey), string(s.tables[j].Smallest().UserKey), s.level, j, numTables)
    82  		}
    83  
    84  		if s.tables[j].Smallest().Compare(s.tables[j].Biggest()) > 0 {
    85  			return errors.Errorf(
    86  				"Intra: %q vs %q: level=%d j=%d numTables=%d",
    87  				s.tables[j].Smallest(), s.tables[j].Biggest(), s.level, j, numTables)
    88  		}
    89  	}
    90  	return nil
    91  }
    92  
    93  // func (s *KV) debugPrintMore() { s.lc.debugPrintMore() }
    94  
    95  // // debugPrintMore shows key ranges of each level.
    96  // func (s *levelsController) debugPrintMore() {
    97  // 	s.Lock()
    98  // 	defer s.Unlock()
    99  // 	for i := 0; i < s.kv.opt.MaxLevels; i++ {
   100  // 		s.levels[i].debugPrintMore()
   101  // 	}
   102  // }
   103  
   104  // func (s *levelHandler) debugPrintMore() {
   105  // 	s.RLock()
   106  // 	defer s.RUnlock()
   107  // 	s.elog.Printf("Level %d:", s.level)
   108  // 	for _, t := range s.tables {
   109  // 		y.Printf(" [%s, %s]", t.Smallest(), t.Biggest())
   110  // 	}
   111  // 	y.Printf("\n")
   112  // }
   113  
   114  // reserveFileID reserves a unique file id.
   115  func (s *levelsController) reserveFileID() uint64 {
   116  	id := atomic.AddUint64(&s.nextFileID, 1)
   117  	return id - 1
   118  }
   119  
   120  func getIDMap(dir string) map[uint64]struct{} {
   121  	fileInfos, err := ioutil.ReadDir(dir)
   122  	y.Check(err)
   123  	idMap := make(map[uint64]struct{})
   124  	for _, info := range fileInfos {
   125  		if info.IsDir() {
   126  			continue
   127  		}
   128  		fileID, ok := sstable.ParseFileID(info.Name())
   129  		if !ok {
   130  			continue
   131  		}
   132  		idMap[fileID] = struct{}{}
   133  	}
   134  	return idMap
   135  }
   136  
   137  func init() {
   138  	rand.Seed(time.Now().UnixNano())
   139  }