| 
									
										
										
										
											2019-08-13 22:09:40 +00:00
										 |  |  | // Copyright 2019 Mikhail Klementev. All rights reserved. | 
					
						
							|  |  |  | // Use of this source code is governed by a AGPLv3 license | 
					
						
							|  |  |  | // (or later) that can be found in the LICENSE file. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package main | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"database/sql" | 
					
						
							| 
									
										
										
										
											2019-08-14 22:59:34 +00:00
										 |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"strconv" | 
					
						
							| 
									
										
										
										
											2019-08-13 23:33:52 +00:00
										 |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2019-08-13 22:09:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-13 22:17:24 +00:00
										 |  |  | 	_ "github.com/mattn/go-sqlite3" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-13 22:09:40 +00:00
										 |  |  | 	"code.dumpstack.io/tools/out-of-tree/config" | 
					
						
							| 
									
										
										
										
											2023-05-23 21:33:50 +00:00
										 |  |  | 	"code.dumpstack.io/tools/out-of-tree/distro" | 
					
						
							| 
									
										
										
										
											2019-08-13 22:09:40 +00:00
										 |  |  | 	"code.dumpstack.io/tools/out-of-tree/qemu" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-16 18:30:46 +00:00
										 |  |  | // Change on ANY database update | 
					
						
							| 
									
										
										
										
											2023-05-24 22:46:04 +00:00
										 |  |  | const currentDatabaseVersion = 3 | 
					
						
							| 
									
										
										
										
											2019-08-14 22:59:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-17 09:05:06 +00:00
										 |  |  | const versionField = "db_version" | 
					
						
							| 
									
										
										
										
											2019-08-14 22:59:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-13 23:33:52 +00:00
										 |  |  | type logEntry struct { | 
					
						
							|  |  |  | 	ID        int | 
					
						
							| 
									
										
										
										
											2019-08-16 18:30:46 +00:00
										 |  |  | 	Tag       string | 
					
						
							| 
									
										
										
										
											2019-08-13 23:33:52 +00:00
										 |  |  | 	Timestamp time.Time | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-17 09:05:06 +00:00
										 |  |  | 	qemu.System | 
					
						
							| 
									
										
										
										
											2019-08-13 23:33:52 +00:00
										 |  |  | 	config.Artifact | 
					
						
							| 
									
										
										
										
											2023-05-23 21:33:50 +00:00
										 |  |  | 	distro.KernelInfo | 
					
						
							| 
									
										
										
										
											2019-08-13 23:33:52 +00:00
										 |  |  | 	phasesResult | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-13 22:09:40 +00:00
										 |  |  | func createLogTable(db *sql.DB) (err error) { | 
					
						
							|  |  |  | 	_, err = db.Exec(` | 
					
						
							|  |  |  | 	CREATE TABLE IF NOT EXISTS log ( | 
					
						
							|  |  |  | 		id		INTEGER PRIMARY KEY, | 
					
						
							|  |  |  | 		time		DATETIME DEFAULT CURRENT_TIMESTAMP, | 
					
						
							| 
									
										
										
										
											2019-08-16 18:30:46 +00:00
										 |  |  | 		tag		TEXT, | 
					
						
							| 
									
										
										
										
											2019-08-13 22:09:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		name		TEXT, | 
					
						
							|  |  |  | 		type		TEXT, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		distro_type	TEXT, | 
					
						
							|  |  |  | 		distro_release	TEXT, | 
					
						
							|  |  |  | 		kernel_release	TEXT, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-24 22:46:04 +00:00
										 |  |  | 		internal_err	TEXT, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-13 22:09:40 +00:00
										 |  |  | 		build_output	TEXT, | 
					
						
							|  |  |  | 		build_ok	BOOLEAN, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		run_output	TEXT, | 
					
						
							|  |  |  | 		run_ok		BOOLEAN, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		test_output	TEXT, | 
					
						
							|  |  |  | 		test_ok		BOOLEAN, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 22:59:34 +00:00
										 |  |  | 		qemu_stdout	TEXT, | 
					
						
							|  |  |  | 		qemu_stderr	TEXT, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-13 22:09:40 +00:00
										 |  |  | 		kernel_panic	BOOLEAN, | 
					
						
							|  |  |  | 		timeout_kill	BOOLEAN | 
					
						
							|  |  |  | 	)`) | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 22:59:34 +00:00
										 |  |  | func createMetadataTable(db *sql.DB) (err error) { | 
					
						
							|  |  |  | 	_, err = db.Exec(` | 
					
						
							|  |  |  | 	CREATE TABLE IF NOT EXISTS metadata ( | 
					
						
							|  |  |  | 		id	INTEGER PRIMARY KEY, | 
					
						
							| 
									
										
										
										
											2019-08-16 18:30:46 +00:00
										 |  |  | 		key	TEXT UNIQUE, | 
					
						
							| 
									
										
										
										
											2019-08-14 22:59:34 +00:00
										 |  |  | 		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) { | 
					
						
							| 
									
										
										
										
											2019-08-16 18:30:46 +00:00
										 |  |  | 	stmt, err := db.Prepare("INSERT OR REPLACE INTO metadata " + | 
					
						
							| 
									
										
										
										
											2019-08-14 22:59:34 +00:00
										 |  |  | 		"(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) { | 
					
						
							| 
									
										
										
										
											2019-08-17 09:05:06 +00:00
										 |  |  | 	s, err := metaGetValue(db, versionField) | 
					
						
							| 
									
										
										
										
											2019-08-14 22:59:34 +00:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	version, err = strconv.Atoi(s) | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-17 09:05:06 +00:00
										 |  |  | func addToLog(db *sql.DB, q *qemu.System, ka config.Artifact, | 
					
						
							| 
									
										
										
										
											2023-05-23 21:33:50 +00:00
										 |  |  | 	ki distro.KernelInfo, res *phasesResult, tag string) (err error) { | 
					
						
							| 
									
										
										
										
											2019-08-13 22:09:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-16 18:30:46 +00:00
										 |  |  | 	stmt, err := db.Prepare("INSERT INTO log (name, type, tag, " + | 
					
						
							| 
									
										
										
										
											2019-08-13 22:09:40 +00:00
										 |  |  | 		"distro_type, distro_release, kernel_release, " + | 
					
						
							| 
									
										
										
										
											2023-05-24 22:46:04 +00:00
										 |  |  | 		"internal_err, " + | 
					
						
							| 
									
										
										
										
											2019-08-13 22:09:40 +00:00
										 |  |  | 		"build_output, build_ok, " + | 
					
						
							|  |  |  | 		"run_output, run_ok, " + | 
					
						
							|  |  |  | 		"test_output, test_ok, " + | 
					
						
							| 
									
										
										
										
											2019-08-14 22:59:34 +00:00
										 |  |  | 		"qemu_stdout, qemu_stderr, " + | 
					
						
							| 
									
										
										
										
											2019-08-13 22:09:40 +00:00
										 |  |  | 		"kernel_panic, timeout_kill) " + | 
					
						
							|  |  |  | 		"VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, " + | 
					
						
							| 
									
										
										
										
											2023-05-24 22:46:04 +00:00
										 |  |  | 		"$10, $11, $12, $13, $14, $15, $16, $17);") | 
					
						
							| 
									
										
										
										
											2019-08-13 22:09:40 +00:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	defer stmt.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_, err = stmt.Exec( | 
					
						
							| 
									
										
										
										
											2019-08-16 18:30:46 +00:00
										 |  |  | 		ka.Name, ka.Type, tag, | 
					
						
							| 
									
										
										
										
											2023-05-18 16:07:24 +00:00
										 |  |  | 		ki.Distro.ID, ki.Distro.Release, ki.KernelRelease, | 
					
						
							| 
									
										
										
										
											2023-05-24 22:46:04 +00:00
										 |  |  | 		res.InternalErrorString, | 
					
						
							| 
									
										
										
										
											2019-08-13 22:09:40 +00:00
										 |  |  | 		res.Build.Output, res.Build.Ok, | 
					
						
							|  |  |  | 		res.Run.Output, res.Run.Ok, | 
					
						
							|  |  |  | 		res.Test.Output, res.Test.Ok, | 
					
						
							| 
									
										
										
										
											2019-08-14 22:59:34 +00:00
										 |  |  | 		q.Stdout, q.Stderr, | 
					
						
							| 
									
										
										
										
											2019-08-13 22:09:40 +00:00
										 |  |  | 		q.KernelPanic, q.KilledByTimeout, | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-16 18:30:46 +00:00
										 |  |  | func getAllLogs(db *sql.DB, tag string, num int) (les []logEntry, err error) { | 
					
						
							|  |  |  | 	stmt, err := db.Prepare("SELECT id, time, name, type, tag, " + | 
					
						
							| 
									
										
										
										
											2019-08-13 23:33:52 +00:00
										 |  |  | 		"distro_type, distro_release, kernel_release, " + | 
					
						
							| 
									
										
										
										
											2023-05-24 22:46:04 +00:00
										 |  |  | 		"internal_err, " + | 
					
						
							| 
									
										
										
										
											2019-08-13 23:33:52 +00:00
										 |  |  | 		"build_ok, run_ok, test_ok, kernel_panic, " + | 
					
						
							|  |  |  | 		"timeout_kill FROM log ORDER BY datetime(time) DESC " + | 
					
						
							|  |  |  | 		"LIMIT $1") | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	defer stmt.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rows, err := stmt.Query(num) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	defer rows.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for rows.Next() { | 
					
						
							| 
									
										
										
										
											2023-05-24 22:46:04 +00:00
										 |  |  | 		var internalErr sql.NullString | 
					
						
							| 
									
										
										
										
											2019-08-13 23:33:52 +00:00
										 |  |  | 		le := logEntry{} | 
					
						
							|  |  |  | 		err = rows.Scan(&le.ID, &le.Timestamp, | 
					
						
							| 
									
										
										
										
											2019-08-16 18:30:46 +00:00
										 |  |  | 			&le.Name, &le.Type, &le.Tag, | 
					
						
							| 
									
										
										
										
											2023-05-18 16:07:24 +00:00
										 |  |  | 			&le.Distro.ID, &le.Distro.Release, &le.KernelRelease, | 
					
						
							| 
									
										
										
										
											2023-05-24 22:46:04 +00:00
										 |  |  | 			&internalErr, | 
					
						
							| 
									
										
										
										
											2019-08-13 23:33:52 +00:00
										 |  |  | 			&le.Build.Ok, &le.Run.Ok, &le.Test.Ok, | 
					
						
							|  |  |  | 			&le.KernelPanic, &le.KilledByTimeout, | 
					
						
							|  |  |  | 		) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-24 22:46:04 +00:00
										 |  |  | 		le.InternalErrorString = internalErr.String | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-16 18:30:46 +00:00
										 |  |  | 		if tag == "" || tag == le.Tag { | 
					
						
							|  |  |  | 			les = append(les, le) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-08-13 23:33:52 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-16 18:30:46 +00:00
										 |  |  | func getAllArtifactLogs(db *sql.DB, tag string, num int, ka config.Artifact) ( | 
					
						
							| 
									
										
										
										
											2019-08-13 23:33:52 +00:00
										 |  |  | 	les []logEntry, err error) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-16 18:30:46 +00:00
										 |  |  | 	stmt, err := db.Prepare("SELECT id, time, name, type, tag, " + | 
					
						
							| 
									
										
										
										
											2019-08-13 23:33:52 +00:00
										 |  |  | 		"distro_type, distro_release, kernel_release, " + | 
					
						
							| 
									
										
										
										
											2023-05-24 22:46:04 +00:00
										 |  |  | 		"internal_err, " + | 
					
						
							| 
									
										
										
										
											2019-08-13 23:33:52 +00:00
										 |  |  | 		"build_ok, run_ok, test_ok, kernel_panic, " + | 
					
						
							|  |  |  | 		"timeout_kill FROM log WHERE name=$1 AND type=$2 " + | 
					
						
							|  |  |  | 		"ORDER BY datetime(time) DESC LIMIT $3") | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	defer stmt.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rows, err := stmt.Query(ka.Name, ka.Type, num) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	defer rows.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for rows.Next() { | 
					
						
							| 
									
										
										
										
											2023-05-24 22:46:04 +00:00
										 |  |  | 		var internalErr sql.NullString | 
					
						
							| 
									
										
										
										
											2019-08-13 23:33:52 +00:00
										 |  |  | 		le := logEntry{} | 
					
						
							|  |  |  | 		err = rows.Scan(&le.ID, &le.Timestamp, | 
					
						
							| 
									
										
										
										
											2019-08-16 18:30:46 +00:00
										 |  |  | 			&le.Name, &le.Type, &le.Tag, | 
					
						
							| 
									
										
										
										
											2023-05-18 16:07:24 +00:00
										 |  |  | 			&le.Distro.ID, &le.Distro.Release, &le.KernelRelease, | 
					
						
							| 
									
										
										
										
											2023-05-24 22:46:04 +00:00
										 |  |  | 			&internalErr, | 
					
						
							| 
									
										
										
										
											2019-08-13 23:33:52 +00:00
										 |  |  | 			&le.Build.Ok, &le.Run.Ok, &le.Test.Ok, | 
					
						
							|  |  |  | 			&le.KernelPanic, &le.KilledByTimeout, | 
					
						
							|  |  |  | 		) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-24 22:46:04 +00:00
										 |  |  | 		le.InternalErrorString = internalErr.String | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-16 18:30:46 +00:00
										 |  |  | 		if tag == "" || tag == le.Tag { | 
					
						
							|  |  |  | 			les = append(les, le) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-08-13 23:33:52 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-13 23:54:45 +00:00
										 |  |  | func getLogByID(db *sql.DB, id int) (le logEntry, err error) { | 
					
						
							| 
									
										
										
										
											2019-08-16 18:30:46 +00:00
										 |  |  | 	stmt, err := db.Prepare("SELECT id, time, name, type, tag, " + | 
					
						
							| 
									
										
										
										
											2019-08-13 23:54:45 +00:00
										 |  |  | 		"distro_type, distro_release, kernel_release, " + | 
					
						
							| 
									
										
										
										
											2023-05-24 22:46:04 +00:00
										 |  |  | 		"internal_err, " + | 
					
						
							| 
									
										
										
										
											2019-08-13 23:54:45 +00:00
										 |  |  | 		"build_ok, run_ok, test_ok, " + | 
					
						
							|  |  |  | 		"build_output, run_output, test_output, " + | 
					
						
							| 
									
										
										
										
											2019-08-14 22:59:34 +00:00
										 |  |  | 		"qemu_stdout, qemu_stderr, " + | 
					
						
							| 
									
										
										
										
											2019-08-13 23:54:45 +00:00
										 |  |  | 		"kernel_panic, timeout_kill " + | 
					
						
							|  |  |  | 		"FROM log WHERE id=$1") | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	defer stmt.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-24 22:46:04 +00:00
										 |  |  | 	var internalErr sql.NullString | 
					
						
							| 
									
										
										
										
											2019-08-13 23:54:45 +00:00
										 |  |  | 	err = stmt.QueryRow(id).Scan(&le.ID, &le.Timestamp, | 
					
						
							| 
									
										
										
										
											2019-08-16 18:30:46 +00:00
										 |  |  | 		&le.Name, &le.Type, &le.Tag, | 
					
						
							| 
									
										
										
										
											2023-05-18 16:07:24 +00:00
										 |  |  | 		&le.Distro.ID, &le.Distro.Release, &le.KernelRelease, | 
					
						
							| 
									
										
										
										
											2023-05-24 22:46:04 +00:00
										 |  |  | 		&internalErr, | 
					
						
							| 
									
										
										
										
											2019-08-13 23:54:45 +00:00
										 |  |  | 		&le.Build.Ok, &le.Run.Ok, &le.Test.Ok, | 
					
						
							|  |  |  | 		&le.Build.Output, &le.Run.Output, &le.Test.Output, | 
					
						
							| 
									
										
										
										
											2019-08-14 22:59:34 +00:00
										 |  |  | 		&le.Stdout, &le.Stderr, | 
					
						
							| 
									
										
										
										
											2020-06-14 20:46:56 +00:00
										 |  |  | 		&le.KernelPanic, &le.KilledByTimeout, | 
					
						
							|  |  |  | 	) | 
					
						
							| 
									
										
										
										
											2023-05-24 22:46:04 +00:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	le.InternalErrorString = internalErr.String | 
					
						
							| 
									
										
										
										
											2020-06-14 20:46:56 +00:00
										 |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func getLastLog(db *sql.DB) (le logEntry, err error) { | 
					
						
							| 
									
										
										
										
											2023-05-24 22:48:58 +00:00
										 |  |  | 	var internalErr sql.NullString | 
					
						
							| 
									
										
										
										
											2020-06-14 20:46:56 +00:00
										 |  |  | 	err = db.QueryRow("SELECT MAX(id), time, name, type, tag, "+ | 
					
						
							|  |  |  | 		"distro_type, distro_release, kernel_release, "+ | 
					
						
							| 
									
										
										
										
											2023-05-24 22:46:04 +00:00
										 |  |  | 		"internal_err, "+ | 
					
						
							| 
									
										
										
										
											2020-06-14 20:46:56 +00:00
										 |  |  | 		"build_ok, run_ok, test_ok, "+ | 
					
						
							|  |  |  | 		"build_output, run_output, test_output, "+ | 
					
						
							|  |  |  | 		"qemu_stdout, qemu_stderr, "+ | 
					
						
							|  |  |  | 		"kernel_panic, timeout_kill "+ | 
					
						
							|  |  |  | 		"FROM log").Scan(&le.ID, &le.Timestamp, | 
					
						
							|  |  |  | 		&le.Name, &le.Type, &le.Tag, | 
					
						
							| 
									
										
										
										
											2023-05-18 16:07:24 +00:00
										 |  |  | 		&le.Distro.ID, &le.Distro.Release, &le.KernelRelease, | 
					
						
							| 
									
										
										
										
											2023-05-24 22:48:58 +00:00
										 |  |  | 		&internalErr, | 
					
						
							| 
									
										
										
										
											2020-06-14 20:46:56 +00:00
										 |  |  | 		&le.Build.Ok, &le.Run.Ok, &le.Test.Ok, | 
					
						
							|  |  |  | 		&le.Build.Output, &le.Run.Output, &le.Test.Output, | 
					
						
							|  |  |  | 		&le.Stdout, &le.Stderr, | 
					
						
							| 
									
										
										
										
											2019-08-13 23:54:45 +00:00
										 |  |  | 		&le.KernelPanic, &le.KilledByTimeout, | 
					
						
							|  |  |  | 	) | 
					
						
							| 
									
										
										
										
											2023-05-24 22:48:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	le.InternalErrorString = internalErr.String | 
					
						
							| 
									
										
										
										
											2019-08-13 23:54:45 +00:00
										 |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-13 22:09:40 +00:00
										 |  |  | func createSchema(db *sql.DB) (err error) { | 
					
						
							| 
									
										
										
										
											2019-08-14 22:59:34 +00:00
										 |  |  | 	err = createMetadataTable(db) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-13 22:09:40 +00:00
										 |  |  | 	err = createLogTable(db) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func openDatabase(path string) (db *sql.DB, err error) { | 
					
						
							|  |  |  | 	db, err = sql.Open("sqlite3", path) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 22:59:34 +00:00
										 |  |  | 	db.SetMaxOpenConns(1) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-17 09:05:06 +00:00
										 |  |  | 	exists, _ := metaChkValue(db, versionField) | 
					
						
							| 
									
										
										
										
											2019-08-14 22:59:34 +00:00
										 |  |  | 	if !exists { | 
					
						
							|  |  |  | 		err = createSchema(db) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-17 09:05:06 +00:00
										 |  |  | 		err = metaSetValue(db, versionField, | 
					
						
							|  |  |  | 			strconv.Itoa(currentDatabaseVersion)) | 
					
						
							| 
									
										
										
										
											2019-08-14 22:59:34 +00:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	version, err := getVersion(db) | 
					
						
							| 
									
										
										
										
											2019-08-13 22:09:40 +00:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-16 18:30:46 +00:00
										 |  |  | 	if version == 1 { | 
					
						
							|  |  |  | 		_, err = db.Exec(`ALTER TABLE log ADD tag TEXT`) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-17 09:05:06 +00:00
										 |  |  | 		err = metaSetValue(db, versionField, "2") | 
					
						
							| 
									
										
										
										
											2019-08-16 18:30:46 +00:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		version = 2 | 
					
						
							| 
									
										
										
										
											2023-05-24 22:46:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	} else if version == 2 { | 
					
						
							|  |  |  | 		_, err = db.Exec(`ALTER TABLE log ADD internal_err TEXT`) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		err = metaSetValue(db, versionField, "3") | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		version = 3 | 
					
						
							| 
									
										
										
										
											2019-08-16 18:30:46 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-17 09:05:06 +00:00
										 |  |  | 	if version != currentDatabaseVersion { | 
					
						
							| 
									
										
										
										
											2019-08-14 22:59:34 +00:00
										 |  |  | 		err = fmt.Errorf("Database is not supported (%d instead of %d)", | 
					
						
							| 
									
										
										
										
											2019-08-17 09:05:06 +00:00
										 |  |  | 			version, currentDatabaseVersion) | 
					
						
							| 
									
										
										
										
											2019-08-14 22:59:34 +00:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-13 22:09:40 +00:00
										 |  |  | 	return | 
					
						
							|  |  |  | } |