diskio/diskdb.go (89 lines of code) (raw):

// Copyright (c) Facebook, Inc. and its affiliates. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package diskio import ( "crypto/sha256" "encoding/hex" "errors" "os" "sync" "github.com/jgoguen/go-utils/xdg" "github.com/peterbourgon/diskv" ) var ( db Database once sync.Once ) // This file contains functions for working with the simple on-disk key/value // store. func (diskdb *diskKVStore) Load(key string) ([]byte, error) { diskdb.mux.RLock() defer diskdb.mux.RUnlock() return diskdb.db.Read(key) } func (diskdb *diskKVStore) Save(key string, value []byte) (string, error) { var savedKey string if key != "" { savedKey = key } else { sum := sha256.Sum256(value) savedKey = hex.EncodeToString(sum[:]) } diskdb.mux.Lock() defer diskdb.mux.Unlock() err := diskdb.db.Write(savedKey, value) return savedKey, err } func (diskdb *diskKVStore) HasKey(key string) bool { diskdb.mux.RLock() defer diskdb.mux.RUnlock() return diskdb.db.Has(key) } func (diskdb *diskKVStore) Delete(key string) error { diskdb.mux.Lock() defer diskdb.mux.Unlock() return diskdb.db.Erase(key) } func (diskdb *diskKVStore) List() ([]string, error) { var keys []string diskdb.mux.RLock() defer diskdb.mux.RUnlock() for v := range diskdb.db.Keys(nil) { keys = append(keys, v) } return keys, nil } func (diskdb *diskKVStore) Visit(visitor func(key string, val []byte) error) error { diskdb.mux.RLock() defer diskdb.mux.RUnlock() cancel := make(chan struct{}) defer close(cancel) for key := range diskdb.db.Keys(cancel) { val, err := diskdb.db.Read(key) if err != nil { return err } if err := visitor(key, val); err != nil { return err } } return nil } // OpenDB opens a Database connection. func OpenDB() (Database, error) { var err error once.Do(func() { dbDir := xdg.GetDataPath("sks") if dbDir == "" { err = errors.New("could not determine the location for the DB") } err = os.MkdirAll(dbDir, 0700) if err != nil { return } db = &diskKVStore{ db: diskv.New(diskv.Options{ BasePath: dbDir, CacheSizeMax: 1024 * 1024, // 1MB cache max FilePerm: 0600, PathPerm: 0700, }), } }) return db, err }