changeset 201:80dc7bbe97db

Persistent session store: Implemented Do.
author Sascha L. Teichmann <teichmann@intevation.de>
date Sun, 22 Jul 2018 09:34:45 +0200
parents 8426a92fda00
children dba50c51cda7
files auth/persistent.go
diffstat 1 files changed, 75 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/auth/persistent.go	Sun Jul 22 09:25:25 2018 +0200
+++ b/auth/persistent.go	Sun Jul 22 09:34:45 2018 +0200
@@ -167,9 +167,82 @@
 	return r.newToken, r.err
 }
 
+func (pcp *PersistentConnectionPool) trim(conn *Connection) {
+
+	conn.refCount--
+
+	for {
+		least := time.Now()
+		var count int
+		var oldest *Connection
+
+		for _, con := range pcp.conns {
+			if con.db != nil && con.refCount <= 0 {
+				if last := con.last(); last.Before(least) {
+					least = last
+					oldest = con
+				}
+				count++
+			}
+		}
+		if count <= maxOpen {
+			break
+		}
+		oldest.close()
+	}
+}
+
 func (pcp *PersistentConnectionPool) Do(token string, fn func(*sql.DB) error) error {
-	log.Println("Do: Not implemented, yet.")
-	return nil
+
+	type result struct {
+		con *Connection
+		err error
+	}
+
+	res := make(chan result)
+
+	pcp.cmds <- func(pcp *PersistentConnectionPool) {
+		con := pcp.conns[token]
+		if con == nil {
+			res <- result{err: ErrNoSuchToken}
+			return
+		}
+		con.touch()
+		// store the session here. The ref counting for
+		// open db connections is irrelevant for persistence
+		// as they all come up closed when the system reboots.
+		pcp.store(token, con)
+
+		if con.db != nil {
+			con.refCount++
+			res <- result{con: con}
+			return
+		}
+
+		session := con.session
+		db, err := opendb(session.User, session.Password)
+		if err != nil {
+			res <- result{err: err}
+			return
+		}
+		con.db = db
+		con.refCount++
+		res <- result{con: con}
+	}
+
+	r := <-res
+
+	if r.err != nil {
+		return r.err
+	}
+
+	defer func() {
+		pcp.cmds <- func(pcp *PersistentConnectionPool) {
+			pcp.trim(r.con)
+		}
+	}()
+
+	return fn(r.con.db)
 }
 
 func (pcp *PersistentConnectionPool) Session(token string) *Session {