# HG changeset patch # User Sascha L. Teichmann # Date 1532244885 -7200 # Node ID 80dc7bbe97db6ff10043707675c553ba8ecd9024 # Parent 8426a92fda00ce70503c06deb3038a389aa5b195 Persistent session store: Implemented Do. diff -r 8426a92fda00 -r 80dc7bbe97db auth/persistent.go --- 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 {