github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/open.go (about)

     1  // Copyright 2021 The Bitalosdb author(hustxrb@163.com) and other contributors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package bitalosdb
    16  
    17  import (
    18  	"time"
    19  
    20  	"github.com/zuoyebang/bitalosdb/internal/base"
    21  	"github.com/zuoyebang/bitalosdb/internal/bitask"
    22  	"github.com/zuoyebang/bitalosdb/internal/cache/lfucache"
    23  	"github.com/zuoyebang/bitalosdb/internal/cache/lrucache"
    24  	"github.com/zuoyebang/bitalosdb/internal/compress"
    25  	"github.com/zuoyebang/bitalosdb/internal/consts"
    26  	"github.com/zuoyebang/bitalosdb/internal/manual"
    27  	"github.com/zuoyebang/bitalosdb/internal/options"
    28  )
    29  
    30  func Open(dirname string, opts *Options) (db *DB, err error) {
    31  	opts = opts.Clone().EnsureDefaults()
    32  
    33  	var optsPool *options.OptionsPool
    34  	if opts.private.optspool == nil {
    35  		optsPool = opts.ensureOptionsPool(nil)
    36  	} else {
    37  		optsPool = opts.private.optspool
    38  	}
    39  
    40  	d := &DB{
    41  		dirname:    dirname,
    42  		walDirname: opts.WALDir,
    43  		opts:       opts,
    44  		optspool:   optsPool,
    45  		cmp:        opts.Comparer.Compare,
    46  		equal:      opts.Comparer.Equal,
    47  		split:      opts.Comparer.Split,
    48  		timeNow:    time.Now,
    49  		compressor: compress.SetCompressor(opts.CompressionType),
    50  		cache:      nil,
    51  		dbState:    optsPool.DbState,
    52  		taskClosed: make(chan struct{}),
    53  		meta:       &metaSet{},
    54  	}
    55  
    56  	defer func() {
    57  		if r := recover(); db == nil {
    58  			d.closeTask()
    59  
    60  			for i := range d.bitowers {
    61  				if d.bitowers[i] != nil {
    62  					for _, mem := range d.bitowers[i].mu.mem.queue {
    63  						switch t := mem.flushable.(type) {
    64  						case *memTable:
    65  							manual.Free(t.arenaBuf)
    66  							t.arenaBuf = nil
    67  						}
    68  					}
    69  				}
    70  			}
    71  
    72  			if d.cache != nil {
    73  				d.cache.Close()
    74  			}
    75  
    76  			if r != any(nil) {
    77  				panic(r)
    78  			}
    79  		}
    80  	}()
    81  
    82  	if err = opts.FS.MkdirAll(dirname, 0755); err != nil {
    83  		return nil, err
    84  	}
    85  	d.dataDir, err = opts.FS.OpenDir(dirname)
    86  	if err != nil {
    87  		return nil, err
    88  	}
    89  	if d.walDirname == "" {
    90  		d.walDirname = d.dirname
    91  	}
    92  	fileLock, err := opts.FS.Lock(base.MakeFilepath(opts.FS, dirname, fileTypeLock, 0))
    93  	if err != nil {
    94  		d.dataDir.Close()
    95  		return nil, err
    96  	}
    97  	defer func() {
    98  		if fileLock != nil {
    99  			fileLock.Close()
   100  		}
   101  	}()
   102  
   103  	if err = d.meta.init(dirname, opts); err != nil {
   104  		return nil, err
   105  	}
   106  	oldLogSeqNum := d.meta.atomic.logSeqNum
   107  	d.initFlushedBitable()
   108  
   109  	if opts.CacheSize > 0 {
   110  		cacheOpts := &options.CacheOptions{
   111  			Size:     opts.CacheSize,
   112  			Shards:   opts.CacheShards,
   113  			HashSize: opts.CacheHashSize,
   114  			Logger:   opts.Logger,
   115  		}
   116  		if opts.CacheType == consts.CacheTypeLfu {
   117  			d.cache = lfucache.New(cacheOpts)
   118  		} else {
   119  			d.cache = lrucache.New(cacheOpts)
   120  		}
   121  	}
   122  
   123  	d.memFlushTask = bitask.NewMemFlushTask(&bitask.MemFlushTaskOptions{
   124  		Size:   consts.DefaultBitowerNum * 6,
   125  		Logger: d.opts.Logger,
   126  		DoFunc: d.doMemFlushTask,
   127  		TaskWg: &d.taskWg,
   128  	})
   129  
   130  	d.bpageTask = bitask.NewBitpageTask(&bitask.BitpageTaskOptions{
   131  		Size:    consts.DefaultBitowerNum * 100,
   132  		DbState: d.optspool.DbState,
   133  		Logger:  opts.Logger,
   134  		DoFunc:  d.doBitpageTask,
   135  		TaskWg:  &d.taskWg,
   136  	})
   137  	d.optspool.BaseOptions.BitpageTaskPushFunc = d.bpageTask.PushTask
   138  
   139  	for i := range d.bitowers {
   140  		d.bitowers[i], err = openBitower(d, i)
   141  		if err != nil {
   142  			return nil, err
   143  		}
   144  	}
   145  
   146  	if d.opts.AutoCompact {
   147  		d.runCompactTask()
   148  	}
   149  
   150  	for i := range d.bitowers {
   151  		d.bitowers[i].btree.MaybeScheduleFlush(false)
   152  	}
   153  
   154  	d.meta.atomic.visibleSeqNum = d.meta.atomic.logSeqNum
   155  	d.fileLock, fileLock = fileLock, nil
   156  
   157  	d.opts.Logger.Infof("open bitalosdb success memSize:%d logSeqNum:%d oldLogSeqNum:%d",
   158  		d.opts.MemTableSize, d.meta.atomic.logSeqNum, oldLogSeqNum)
   159  
   160  	return d, nil
   161  }