// // tank // // Import and Playlist Daemon for autoradio project // // // Copyright (C) 2017 Christian Pointner <equinox@helsinki.at> // // This file is part of tank. // // tank is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // any later version. // // tank is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with tank. If not, see <http://www.gnu.org/licenses/>. // package store import ( "errors" "fmt" "os" "path/filepath" "time" "github.com/coreos/bbolt" ) const ( StoreVersion = 1 ) type Store struct { version int db *bolt.DB basePath string } // // Initialization and Destruction // func openDB(dbPath string, readOnly bool) (db *bolt.DB, version int, err error) { if _, err = os.Stat(dbPath); err != nil { if os.IsNotExist(err) { err = nil } return } opts := &bolt.Options{Timeout: 100 * time.Millisecond, ReadOnly: readOnly} db, err = bolt.Open(dbPath, 0600, opts) if err != nil { return } err = db.View(func(tx *bolt.Tx) error { b := tx.Bucket([]byte(infoBn)) if b == nil { return errors.New("store: failed to open, bucket '" + infoBn + "'does not exist.") } bVersion := b.Get([]byte(storeVersionKey)) if bVersion == nil { return errors.New("store: failed to open, no version found.") } version = btoi(bVersion) if version != StoreVersion { return fmt.Errorf("store: failed to open, wrong version: %d (expected: %d)", version, StoreVersion) } // TODO: check all group buckets?? return nil }) if err != nil { db.Close() } return } func createDB(dbPath string) (db *bolt.DB, version int, err error) { db, err = bolt.Open(dbPath, 0600, &bolt.Options{Timeout: 100 * time.Millisecond}) if err != nil { return } err = db.Update(func(tx *bolt.Tx) error { b, err := tx.CreateBucket([]byte(infoBn)) if err != nil { return err } version = StoreVersion if err := b.Put([]byte(storeVersionKey), itob(version)); err != nil { return err } b, err = tx.CreateBucket([]byte(groupsBn)) if err != nil { return err } _, err = newGroup(b, publicGroupBn) return err }) if err != nil { db.Close() } return } func NewStore(cfg *Config) (*Store, error) { dbpath := filepath.Join(cfg.BasePath, ".db.bolt") db, version, err := openDB(dbpath, false) if err != nil { return nil, err } if db != nil { return &Store{version, db, cfg.BasePath}, nil } db, version, err = createDB(dbpath) if err != nil { return nil, err } return &Store{version, db, cfg.BasePath}, nil } func (st *Store) Close() { st.db.Close() }