2013-02-22 00:06:10 -05:00
package main
import (
"asink"
"database/sql"
_ "github.com/mattn/go-sqlite3"
2013-07-19 22:15:53 -04:00
"sync"
2013-02-22 00:06:10 -05:00
)
2013-07-19 22:15:53 -04:00
type AsinkDB struct {
db * sql . DB
lock sync . Mutex
}
func GetAndInitDB ( ) ( * AsinkDB , error ) {
2013-02-22 00:06:10 -05:00
dbLocation := "asink-server.db" //TODO make me configurable
2013-08-13 23:12:08 -04:00
db , err := sql . Open ( "sqlite3" , "file:" + dbLocation + "?cache=shared&mode=rwc" )
2013-02-22 00:06:10 -05:00
if err != nil {
return nil , err
}
//make sure the events table is created
tx , err := db . Begin ( )
if err != nil {
return nil , err
}
rows , err := tx . Query ( "SELECT name FROM sqlite_master WHERE type='table' AND name='events';" )
if err != nil {
return nil , err
}
if ! rows . Next ( ) {
//if this is false, it means no rows were returned
2013-08-13 20:43:16 -04:00
tx . Exec ( "CREATE TABLE events (id INTEGER PRIMARY KEY ASC, localid INTEGER, type INTEGER, status INTEGER, path TEXT, hash TEXT, predecessor TEXT, timestamp INTEGER, permissions INTEGER);" )
2013-02-22 00:06:10 -05:00
tx . Exec ( "CREATE INDEX IF NOT EXISTS pathidx on events (path);" )
}
err = tx . Commit ( )
if err != nil {
return nil , err
}
2013-07-19 22:15:53 -04:00
ret := new ( AsinkDB )
ret . db = db
return ret , nil
2013-02-22 00:06:10 -05:00
}
2013-07-19 22:15:53 -04:00
func ( adb * AsinkDB ) DatabaseAddEvent ( e * asink . Event ) ( err error ) {
adb . lock . Lock ( )
tx , err := adb . db . Begin ( )
2013-02-22 00:06:10 -05:00
if err != nil {
return err
}
2013-03-17 23:04:04 -04:00
//make sure the transaction gets rolled back on error, and the database gets unlocked
defer func ( ) {
if err != nil {
tx . Rollback ( )
}
2013-07-19 22:15:53 -04:00
adb . lock . Unlock ( )
2013-03-17 23:04:04 -04:00
} ( )
2013-08-13 20:43:16 -04:00
result , err := tx . Exec ( "INSERT INTO events (localid, type, status, path, hash, predecessor, timestamp, permissions) VALUES (?,?,?,?,?,?,?,?);" , e . LocalId , e . Type , e . Status , e . Path , e . Hash , e . Predecessor , e . Timestamp , e . Permissions )
2013-02-22 00:06:10 -05:00
if err != nil {
return err
}
id , err := result . LastInsertId ( )
if err != nil {
return err
}
err = tx . Commit ( )
if err != nil {
return err
}
e . Id = id
e . InDB = true
return nil
}
2013-07-19 22:15:53 -04:00
func ( adb * AsinkDB ) DatabaseRetrieveEvents ( firstId uint64 , maxEvents uint ) ( events [ ] * asink . Event , err error ) {
adb . lock . Lock ( )
//make sure the database gets unlocked on return
defer func ( ) {
adb . lock . Unlock ( )
} ( )
2013-08-13 20:43:16 -04:00
rows , err := adb . db . Query ( "SELECT id, localid, type, status, path, hash, predecessor, timestamp, permissions FROM events WHERE id >= ? ORDER BY id ASC LIMIT ?;" , firstId , maxEvents )
2013-02-22 00:06:10 -05:00
if err != nil {
return nil , err
}
for rows . Next ( ) {
var event asink . Event
2013-08-13 20:43:16 -04:00
err = rows . Scan ( & event . Id , & event . LocalId , & event . Type , & event . Status , & event . Path , & event . Hash , & event . Predecessor , & event . Timestamp , & event . Permissions )
2013-02-22 00:06:10 -05:00
if err != nil {
return nil , err
}
events = append ( events , & event )
}
return events , nil
}