diff --git a/db.go b/db.go index 6b2ae5a..138ffaf 100644 --- a/db.go +++ b/db.go @@ -6,6 +6,8 @@ package main import ( "database/sql" + "fmt" + "strconv" "time" _ "github.com/mattn/go-sqlite3" @@ -14,6 +16,10 @@ import ( "code.dumpstack.io/tools/out-of-tree/qemu" ) +const CURRENT_DATABASE_VERSION = 1 + +const VERSION_FIELD = "db_version" + type logEntry struct { ID int Timestamp time.Time @@ -46,12 +52,71 @@ func createLogTable(db *sql.DB) (err error) { test_output TEXT, test_ok BOOLEAN, + qemu_stdout TEXT, + qemu_stderr TEXT, + kernel_panic BOOLEAN, timeout_kill BOOLEAN )`) return } +func createMetadataTable(db *sql.DB) (err error) { + _, err = db.Exec(` + CREATE TABLE IF NOT EXISTS metadata ( + id INTEGER PRIMARY KEY, + key TEXT, + value TEXT + )`) + return +} + +func metaChkValue(db *sql.DB, key string) (exist bool, err error) { + sql := "SELECT EXISTS(SELECT id FROM metadata WHERE key = $1)" + stmt, err := db.Prepare(sql) + if err != nil { + return + } + defer stmt.Close() + + err = stmt.QueryRow(key).Scan(&exist) + return +} + +func metaGetValue(db *sql.DB, key string) (value string, err error) { + stmt, err := db.Prepare("SELECT value FROM metadata " + + "WHERE key = $1") + if err != nil { + return + } + defer stmt.Close() + + err = stmt.QueryRow(key).Scan(&value) + return +} + +func metaSetValue(db *sql.DB, key, value string) (err error) { + stmt, err := db.Prepare("INSERT INTO metadata " + + "(key, value) VALUES ($1, $2)") + if err != nil { + return + } + defer stmt.Close() + + _, err = stmt.Exec(key, value) + return +} + +func getVersion(db *sql.DB) (version int, err error) { + s, err := metaGetValue(db, VERSION_FIELD) + if err != nil { + return + } + + version, err = strconv.Atoi(s) + return +} + func addToLog(db *sql.DB, q *qemu.QemuSystem, ka config.Artifact, ki config.KernelInfo, res *phasesResult) (err error) { @@ -60,9 +125,10 @@ func addToLog(db *sql.DB, q *qemu.QemuSystem, ka config.Artifact, "build_output, build_ok, " + "run_output, run_ok, " + "test_output, test_ok, " + + "qemu_stdout, qemu_stderr, " + "kernel_panic, timeout_kill) " + "VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, " + - "$10, $11, $12, $13);") + "$10, $11, $12, $13, $14, $15);") if err != nil { return } @@ -75,6 +141,7 @@ func addToLog(db *sql.DB, q *qemu.QemuSystem, ka config.Artifact, res.Build.Output, res.Build.Ok, res.Run.Output, res.Run.Ok, res.Test.Output, res.Test.Ok, + q.Stdout, q.Stderr, q.KernelPanic, q.KilledByTimeout, ) if err != nil { @@ -161,6 +228,7 @@ func getLogByID(db *sql.DB, id int) (le logEntry, err error) { "distro_type, distro_release, kernel_release, " + "build_ok, run_ok, test_ok, " + "build_output, run_output, test_output, " + + "qemu_stdout, qemu_stderr, " + "kernel_panic, timeout_kill " + "FROM log WHERE id=$1") if err != nil { @@ -173,12 +241,18 @@ func getLogByID(db *sql.DB, id int) (le logEntry, err error) { &le.DistroType, &le.DistroRelease, &le.KernelRelease, &le.Build.Ok, &le.Run.Ok, &le.Test.Ok, &le.Build.Output, &le.Run.Output, &le.Test.Output, + &le.Stdout, &le.Stderr, &le.KernelPanic, &le.KilledByTimeout, ) return } func createSchema(db *sql.DB) (err error) { + err = createMetadataTable(db) + if err != nil { + return + } + err = createLogTable(db) if err != nil { return @@ -193,10 +267,30 @@ func openDatabase(path string) (db *sql.DB, err error) { return } - err = createSchema(db) + db.SetMaxOpenConns(1) + + exists, _ := metaChkValue(db, VERSION_FIELD) + if !exists { + err = createSchema(db) + if err != nil { + return + } + + err = metaSetValue(db, VERSION_FIELD, + strconv.Itoa(CURRENT_DATABASE_VERSION)) + return + } + + version, err := getVersion(db) if err != nil { return } + if version != CURRENT_DATABASE_VERSION { + err = fmt.Errorf("Database is not supported (%d instead of %d)", + version, CURRENT_DATABASE_VERSION) + return + } + return } diff --git a/log.go b/log.go index 889e23f..3e5de44 100644 --- a/log.go +++ b/log.go @@ -129,5 +129,11 @@ func logDumpHandler(db *sql.DB, id int) (err error) { fmt.Printf("Test output:\n%s\n", l.Test.Output) fmt.Println() + fmt.Printf("Qemu stdout:\n%s\n", l.Stdout) + fmt.Println() + + fmt.Printf("Qemu stderr:\n%s\n", l.Stderr) + fmt.Println() + return }