// Copyright 2020 The Gitea Authors. All rights reserved. // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. package nosql import ( "path" "strconv" "strings" "github.com/syndtr/goleveldb/leveldb" "github.com/syndtr/goleveldb/leveldb/errors" "github.com/syndtr/goleveldb/leveldb/opt" ) // CloseLevelDB closes a levelDB func (m *Manager) CloseLevelDB(connection string) error { m.mutex.Lock() defer m.mutex.Unlock() db, ok := m.LevelDBConnections[connection] if !ok { connection = ToLevelDBURI(connection).String() db, ok = m.LevelDBConnections[connection] } if !ok { return nil } db.count-- if db.count > 0 { return nil } for _, name := range db.name { delete(m.LevelDBConnections, name) } return db.db.Close() } // GetLevelDB gets a levelDB for a particular connection func (m *Manager) GetLevelDB(connection string) (*leveldb.DB, error) { m.mutex.Lock() defer m.mutex.Unlock() db, ok := m.LevelDBConnections[connection] if ok { db.count++ return db.db, nil } dataDir := connection uri := ToLevelDBURI(connection) db = &levelDBHolder{ name: []string{connection, uri.String()}, } dataDir = path.Join(uri.Host, uri.Path) opts := &opt.Options{} for k, v := range uri.Query() { switch replacer.Replace(strings.ToLower(k)) { case "blockcachecapacity": opts.BlockCacheCapacity, _ = strconv.Atoi(v[0]) case "blockcacheevictremoved": opts.BlockCacheEvictRemoved, _ = strconv.ParseBool(v[0]) case "blockrestartinterval": opts.BlockRestartInterval, _ = strconv.Atoi(v[0]) case "blocksize": opts.BlockSize, _ = strconv.Atoi(v[0]) case "compactionexpandlimitfactor": opts.CompactionExpandLimitFactor, _ = strconv.Atoi(v[0]) case "compactiongpoverlapsfactor": opts.CompactionGPOverlapsFactor, _ = strconv.Atoi(v[0]) case "compactionl0trigger": opts.CompactionL0Trigger, _ = strconv.Atoi(v[0]) case "compactionsourcelimitfactor": opts.CompactionSourceLimitFactor, _ = strconv.Atoi(v[0]) case "compactiontablesize": opts.CompactionTableSize, _ = strconv.Atoi(v[0]) case "compactiontablesizemultiplier": opts.CompactionTableSizeMultiplier, _ = strconv.ParseFloat(v[0], 64) case "compactiontablesizemultiplierperlevel": for _, val := range v { f, _ := strconv.ParseFloat(val, 64) opts.CompactionTableSizeMultiplierPerLevel = append(opts.CompactionTableSizeMultiplierPerLevel, f) } case "compactiontotalsize": opts.CompactionTotalSize, _ = strconv.Atoi(v[0]) case "compactiontotalsizemultiplier": opts.CompactionTotalSizeMultiplier, _ = strconv.ParseFloat(v[0], 64) case "compactiontotalsizemultiplierperlevel": for _, val := range v { f, _ := strconv.ParseFloat(val, 64) opts.CompactionTotalSizeMultiplierPerLevel = append(opts.CompactionTotalSizeMultiplierPerLevel, f) } case "compression": val, _ := strconv.Atoi(v[0]) opts.Compression = opt.Compression(val) case "disablebufferpool": opts.DisableBufferPool, _ = strconv.ParseBool(v[0]) case "disableblockcache": opts.DisableBlockCache, _ = strconv.ParseBool(v[0]) case "disablecompactionbackoff": opts.DisableCompactionBackoff, _ = strconv.ParseBool(v[0]) case "disablelargebatchtransaction": opts.DisableLargeBatchTransaction, _ = strconv.ParseBool(v[0]) case "errorifexist": opts.ErrorIfExist, _ = strconv.ParseBool(v[0]) case "errorifmissing": opts.ErrorIfMissing, _ = strconv.ParseBool(v[0]) case "iteratorsamplingrate": opts.IteratorSamplingRate, _ = strconv.Atoi(v[0]) case "nosync": opts.NoSync, _ = strconv.ParseBool(v[0]) case "nowritemerge": opts.NoWriteMerge, _ = strconv.ParseBool(v[0]) case "openfilescachecapacity": opts.OpenFilesCacheCapacity, _ = strconv.Atoi(v[0]) case "readonly": opts.ReadOnly, _ = strconv.ParseBool(v[0]) case "strict": val, _ := strconv.Atoi(v[0]) opts.Strict = opt.Strict(val) case "writebuffer": opts.WriteBuffer, _ = strconv.Atoi(v[0]) case "writel0pausetrigger": opts.WriteL0PauseTrigger, _ = strconv.Atoi(v[0]) case "writel0slowdowntrigger": opts.WriteL0SlowdownTrigger, _ = strconv.Atoi(v[0]) case "clientname": db.name = append(db.name, v[0]) } } var err error db.db, err = leveldb.OpenFile(dataDir, opts) if err != nil { if !errors.IsCorrupted(err) { return nil, err } db.db, err = leveldb.RecoverFile(dataDir, opts) if err != nil { return nil, err } } for _, name := range db.name { m.LevelDBConnections[name] = db } db.count++ return db.db, nil }