summary refs log tree commit diff stats
path: root/svc/sqlite.go
diff options
context:
space:
mode:
authorBen Morrison <ben@gbmor.dev>2019-06-08 01:04:38 -0400
committerBen Morrison <ben@gbmor.dev>2019-06-08 02:29:33 -0400
commita5a32e7a317dd5cf156e52a71d7be432d0594bf7 (patch)
treec266a1652f78ec446b2eb85f2371e0cfabed65ff /svc/sqlite.go
parente6beae32cd45ea0057e1a5bc5e4b3f2a098a1a1e (diff)
downloadgetwtxt-a5a32e7a317dd5cf156e52a71d7be432d0594bf7.tar.gz
split db-specific funcs into separate files
Diffstat (limited to 'svc/sqlite.go')
-rw-r--r--svc/sqlite.go148
1 files changed, 148 insertions, 0 deletions
diff --git a/svc/sqlite.go b/svc/sqlite.go
new file mode 100644
index 0000000..3f50402
--- /dev/null
+++ b/svc/sqlite.go
@@ -0,0 +1,148 @@
+package svc // import "github.com/getwtxt/getwtxt/svc"
+
+import (
+	"database/sql"
+	"net"
+	"time"
+
+	"github.com/getwtxt/registry"
+	_ "github.com/mattn/go-sqlite3" // for the sqlite3 driver
+)
+
+type dbSqlite struct {
+	db       *sql.DB
+	pullStmt *sql.Stmt
+	pushStmt *sql.Stmt
+}
+
+func initSqlite() *dbSqlite {
+
+	confObj.Mu.RLock()
+	dbpath := confObj.DBPath
+	confObj.Mu.RUnlock()
+
+	lite, err := sql.Open("sqlite3", dbpath)
+	errFatal("Error opening sqlite3 DB: ", err)
+
+	errFatal("", lite.Ping())
+
+	_, err = lite.Exec("CREATE TABLE IF NOT EXISTS getwtxt (id INTEGER PRIMARY KEY, urlKey TEXT, isUser BOOL, dataKey TEXT, data BLOB)")
+	errFatal("Error preparing sqlite3 DB: ", err)
+
+	push, err := lite.Prepare("INSERT OR REPLACE INTO getwtxt (urlKey, isUser, dataKey, data) VALUES(?, ?, ?, ?)")
+	errFatal("", err)
+
+	pull, err := lite.Prepare("SELECT * FROM getwtxt")
+	errFatal("", err)
+
+	return &dbSqlite{
+		db:       lite,
+		pushStmt: push,
+		pullStmt: pull,
+	}
+}
+
+func (lite dbSqlite) push() error {
+	err := lite.db.Ping()
+	if err != nil {
+		return err
+	}
+
+	tx, err := lite.db.Begin()
+	errLog("", err)
+	txst := tx.Stmt(lite.pushStmt)
+
+	twtxtCache.Mu.RLock()
+	for i, e := range twtxtCache.Users {
+		e.Mu.RLock()
+
+		_, err = txst.Exec(i, true, "nickname", e.Nick)
+		errLog("", err)
+		_, err = txst.Exec(i, true, "rlen", e.RLen)
+		errLog("", err)
+		_, err = txst.Exec(i, true, "uip", e.IP)
+		errLog("", err)
+		_, err = txst.Exec(i, true, "date", e.Date)
+		errLog("", err)
+
+		for k, v := range e.Status {
+			_, err = txst.Exec(i, true, k.Format(time.RFC3339), v)
+			errLog("", err)
+		}
+
+		e.Mu.RUnlock()
+	}
+	twtxtCache.Mu.RUnlock()
+
+	remoteRegistries.Mu.RLock()
+	for _, e := range remoteRegistries.List {
+		_, err = txst.Exec(e, false, "REMOTE REGISTRY", "NULL")
+		errLog("", err)
+	}
+	remoteRegistries.Mu.RUnlock()
+
+	err = tx.Commit()
+	if err != nil {
+		tx.Rollback()
+		return err
+	}
+
+	return nil
+}
+
+func (lite dbSqlite) pull() {
+	errLog("Error pinging sqlite DB: ", lite.db.Ping())
+
+	rows, err := lite.pullStmt.Query()
+	errLog("", err)
+
+	defer func(rows *sql.Rows) {
+		errLog("Error while finalizing DB Pull: ", rows.Close())
+	}(rows)
+
+	twtxtCache.Mu.Lock()
+	for rows.Next() {
+		var urls string
+		var isUser bool
+		var dataKey string
+		var dBlob []byte
+
+		errLog("", rows.Scan(&urls, &isUser, &dataKey, &dBlob))
+
+		if !isUser {
+			remoteRegistries.Mu.Lock()
+			remoteRegistries.List = append(remoteRegistries.List, urls)
+			remoteRegistries.Mu.Unlock()
+			continue
+		}
+
+		user := registry.NewUser()
+		if _, ok := twtxtCache.Users[urls]; ok {
+			user = twtxtCache.Users[urls]
+		}
+		user.Mu.Lock()
+
+		switch dataKey {
+		case "nickname":
+			user.Nick = string(dBlob)
+		case "uip":
+			user.IP = net.ParseIP(string(dBlob))
+		case "date":
+			user.Date = string(dBlob)
+		case "rlen":
+			user.RLen = string(dBlob)
+		default:
+			thetime, err := time.Parse(time.RFC3339, dataKey)
+			errLog("While pulling statuses from SQLite: ", err)
+			user.Status[thetime] = string(dBlob)
+		}
+
+		twtxtCache.Users[urls] = user
+		user.Mu.Unlock()
+	}
+	twtxtCache.Mu.Unlock()
+
+	remoteRegistries.Mu.Lock()
+	remoteRegistries.List = dedupe(remoteRegistries.List)
+	remoteRegistries.Mu.Unlock()
+}