diff options
Diffstat (limited to 'storage')
-rw-r--r-- | storage/getdir_unix.go | 37 | ||||
-rw-r--r-- | storage/init.go | 63 | ||||
-rw-r--r-- | storage/storage.go | 44 |
3 files changed, 144 insertions, 0 deletions
diff --git a/storage/getdir_unix.go b/storage/getdir_unix.go new file mode 100644 index 0000000..29bedbe --- /dev/null +++ b/storage/getdir_unix.go @@ -0,0 +1,37 @@ +// +build linux netbsd openbsd freebsd dragonfly + +package storage + +import ( + "fmt" + "os" +) + +// GetDir returns grus data directory. Check if the user has set +// GRUS_DIR, if not then check if XDG_DATA_HOME is set & if that is +// not set then assume it to be the default value which is +// $HOME/.local/share according to XDG Base Directory Specification. +func GetDir() string { + cacheDir := SysDir() + + // Grus cache directory is cacheDir/grus. + grusCacheDir := fmt.Sprintf("%s/%s", cacheDir, + "grus") + + return grusCacheDir +} + +// SysDir returns the system data directory, this is useful for unveil in +// OpenBSD. +func SysDir() string { + cacheDir := os.Getenv("GRUS_DIR") + if len(cacheDir) == 0 { + cacheDir = os.Getenv("XDG_DATA_HOME") + } + if len(cacheDir) == 0 { + cacheDir = fmt.Sprintf("%s/%s/%s", os.Getenv("HOME"), + ".local", "share") + } + + return cacheDir +} diff --git a/storage/init.go b/storage/init.go new file mode 100644 index 0000000..9894c5b --- /dev/null +++ b/storage/init.go @@ -0,0 +1,63 @@ +package storage + +import ( + "database/sql" + "fmt" + "log" + + _ "github.com/mattn/go-sqlite3" +) + +// initErr will log the error and close the database connection if +// necessary. +func initErr(db *DB, err error) { + if db.Conn != nil { + db.Conn.Close() + } + log.Fatalf("Initialization Error :: %s", err.Error()) +} + +func initDB(db *DB) { + var err error + + db.Path = fmt.Sprintf("%s/grus.db", GetDir()) + + db.Conn, err = sql.Open("sqlite3", db.Path) + if err != nil { + log.Printf("storage/init.go: %s\n", + "Failed to open database connection") + initErr(db, err) + } + + sqlstmt := []string{ + `CREATE TABLE IF NOT EXISTS words ( + word TEXT PRIMARY KEY NOT NULL, + sorted TEXT NOT NULL);`, + `INSERT INTO words(word, lexical) + values("grus", "grsu");`, + } + + // We range over statements and execute them one by one, this + // is during initialization so it doesn't matter if it takes + // few more ms. This way we know which statement caused the + // program to fail. + for _, s := range sqlstmt { + stmt, err := db.Conn.Prepare(s) + + if err != nil { + log.Printf("storage/init.go: %s\n", + "failed to prepare statement") + log.Println(s) + initErr(db, err) + } + + _, err = stmt.Exec() + stmt.Close() + if err != nil { + log.Printf("storage/init.go: %s\n", + "failed to execute statement") + log.Println(s) + initErr(db, err) + } + } +} diff --git a/storage/storage.go b/storage/storage.go new file mode 100644 index 0000000..9aa1a57 --- /dev/null +++ b/storage/storage.go @@ -0,0 +1,44 @@ +package storage + +import ( + "database/sql" + "fmt" + "log" + "sync" +) + +// DB holds the database connection, mutex & path. +type DB struct { + Path string + Mu *sync.RWMutex + Conn *sql.DB +} + +// Init initializes the database. +func Init() *DB { + db := DB{ + Mu: new(sync.RWMutex), + } + + initDB(&db) + return &db +} + +// InitConn initializes database connection. +func InitConn() *DB { + var err error + db := DB{ + Mu: new(sync.RWMutex), + } + + db.Path = fmt.Sprintf("%s/grus.db", GetDir()) + + db.Conn, err = sql.Open("sqlite3", db.Path) + if err != nil { + log.Printf("storage/init.go: %s\n", + "Failed to open database connection") + initErr(&db, err) + } + + return &db +} |