blob: e333c6e212a4220d985fa43d3dc1dc85adddb25f [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 util
import (
"database/sql"
"fmt"
log "github.com/Sirupsen/logrus"
_ "github.com/mattn/go-sqlite3"
)
type CfgDb struct {
DbPath string
DbPrefix string
Config map[string]map[string]string
db *sql.DB
}
func NewCfgDb(prefix string, dbPath string) (*CfgDb, error) {
c := &CfgDb{}
if err := c.Init(prefix, dbPath); err != nil {
return nil, err
}
return c, nil
}
func (c *CfgDb) createDb(db *sql.DB, prefix string) error {
query := `
CREATE TABLE IF NOT EXISTS %s_cfg (
cfg_name VARCHAR(255) NOT NULL,
key VARCHAR(255) NOT NULL,
value TEXT
)
`
query = fmt.Sprintf(query, prefix)
if _, err := db.Exec(query); err != nil {
return NewNewtError(err.Error())
}
return nil
}
func (c *CfgDb) Init(prefix string, dbPath string) error {
c.DbPrefix = prefix
c.DbPath = dbPath
c.Config = make(map[string]map[string]string)
db, err := sql.Open("sqlite3", dbPath)
if err != nil {
return err
}
if err = c.createDb(db, prefix); err != nil {
return err
}
c.db = db
log.Debugf("Reading config from %s for %s", dbPath, prefix)
rows, err := db.Query(fmt.Sprintf("SELECT * FROM %s_cfg", prefix))
if err != nil {
return NewNewtError(err.Error())
}
defer rows.Close()
for rows.Next() {
var cName sql.NullString
var cKey sql.NullString
var cVal sql.NullString
if err := rows.Scan(&cName, &cKey, &cVal); err != nil {
return NewNewtError(err.Error())
}
log.Debugf("Setting sect %s, key %s to val %s", cName.String,
cKey.String, cVal.String)
if _, ok := c.Config[cName.String]; !ok {
c.Config[cName.String] = make(map[string]string)
}
c.Config[cName.String][cKey.String] = cVal.String
}
return nil
}
func (c *CfgDb) HasSect(sect string) bool {
_, ok := c.Config[sect]
if !ok {
return false
}
return true
}
func (c *CfgDb) HasKey(sect string, key string) bool {
sMap, ok := c.Config[sect]
if !ok {
return false
}
_, ok = sMap[key]
if !ok {
return false
}
return true
}
func (c *CfgDb) GetKey(sect string, key string) (string, error) {
sMap, ok := c.Config[sect]
if !ok {
return "", NewNewtError("No configuration section " + sect + " exists")
}
val, ok := sMap[key]
if !ok {
return "", NewNewtError("No configuration variable " + key +
" in sect " + sect + "exists")
}
return val, nil
}
func (c *CfgDb) GetSect(sect string) (map[string]string, error) {
sMap, ok := c.Config[sect]
if !ok {
return nil, NewNewtError("No configuration section " + sect + "exists")
}
return sMap, nil
}
func (c *CfgDb) DeleteSect(sect string) error {
log.Debugf("Deleting sect %s", sect)
tx, err := c.db.Begin()
if err != nil {
return NewNewtError(err.Error())
}
stmt, err := tx.Prepare(fmt.Sprintf(
"DELETE FROM %s_cfg WHERE cfg_name=?", c.DbPrefix))
if err != nil {
return NewNewtError(err.Error())
}
defer stmt.Close()
r, err := stmt.Exec(sect)
if err != nil {
return err
}
tx.Commit()
if naffected, err := r.RowsAffected(); naffected > 0 && err == nil {
log.Debugf("Successfully deleted sect %s from db %s",
sect, c.DbPath)
} else {
log.Debugf("Sect %s not found in db %s. Delete "+
"successful", sect, c.DbPath)
}
return nil
}
func (c *CfgDb) DeleteKey(sect string, key string) error {
log.Debugf("Deleting sect %s, key %s", sect, key)
tx, err := c.db.Begin()
if err != nil {
return NewNewtError(err.Error())
}
stmt, err := tx.Prepare(fmt.Sprintf(
"DELETE FROM %s_cfg WHERE cfg_name=? AND key=?", c.DbPrefix))
if err != nil {
return NewNewtError(err.Error())
}
defer stmt.Close()
r, err := stmt.Exec(sect, key)
if err != nil {
return err
}
tx.Commit()
if naffected, err := r.RowsAffected(); naffected > 0 && err == nil {
log.Debugf("Successfully deleted sect %s, key %s from db %s",
sect, key, c.DbPath)
} else {
log.Debugf("Sect %s, key %s not found in db %s. Delete "+
"successful", sect, key, c.DbPath)
}
return nil
}
func (c *CfgDb) SetKey(sect string, key string, val string) error {
if _, ok := c.Config[sect]; !ok {
log.Debugf("Section %s doesn't exist, creating it!", sect)
c.Config[sect] = make(map[string]string)
}
c.Config[sect][key] = val
log.Debugf("Storing value %s in section %s, key %s",
val, sect, key)
tx, err := c.db.Begin()
if err != nil {
return NewNewtError(err.Error())
}
stmt, err := tx.Prepare(fmt.Sprintf(
"UPDATE %s_cfg SET value=? WHERE cfg_name=? AND key=?", c.DbPrefix))
if err != nil {
return NewNewtError(err.Error())
}
defer stmt.Close()
r, err := stmt.Exec(val, sect, key)
if err != nil {
return NewNewtError(err.Error())
}
// If update succeeded, then exit out.
if naffected, err := r.RowsAffected(); naffected > 0 && err == nil {
tx.Commit()
log.Debugf("Sect %s, key %s successfully updated to %s",
sect, key, val)
return nil
}
// Otherwise, insert a new row.
stmt, err = tx.Prepare(fmt.Sprintf("INSERT INTO %s_cfg VALUES (?, ?, ?)",
c.DbPrefix))
if err != nil {
return NewNewtError(err.Error())
}
defer stmt.Close()
if _, err = stmt.Exec(sect, key, val); err != nil {
return NewNewtError(err.Error())
}
tx.Commit()
log.Debugf("Section %s, key %s successfully created. Value set"+
"to %s", sect, key, val)
return nil
}