mirror of
https://github.com/lightningnetwork/lnd.git
synced 2024-11-19 18:10:34 +01:00
90 lines
1.8 KiB
Go
90 lines
1.8 KiB
Go
package postgres
|
|
|
|
import (
|
|
"database/sql"
|
|
"fmt"
|
|
"sync"
|
|
|
|
_ "github.com/jackc/pgx/v4/stdlib"
|
|
)
|
|
|
|
// dbConn stores the actual connection and a user count.
|
|
type dbConn struct {
|
|
db *sql.DB
|
|
count int
|
|
}
|
|
|
|
// dbConnSet stores a set of connections.
|
|
type dbConnSet struct {
|
|
dbConn map[string]*dbConn
|
|
maxConnections int
|
|
|
|
sync.Mutex
|
|
}
|
|
|
|
// newDbConnSet initializes a new set of connections.
|
|
func newDbConnSet(maxConnections int) *dbConnSet {
|
|
return &dbConnSet{
|
|
dbConn: make(map[string]*dbConn),
|
|
maxConnections: maxConnections,
|
|
}
|
|
}
|
|
|
|
// Open opens a new database connection. If a connection already exists for the
|
|
// given dsn, the existing connection is returned.
|
|
func (d *dbConnSet) Open(dsn string) (*sql.DB, error) {
|
|
d.Lock()
|
|
defer d.Unlock()
|
|
|
|
if dbConn, ok := d.dbConn[dsn]; ok {
|
|
dbConn.count++
|
|
|
|
return dbConn.db, nil
|
|
}
|
|
|
|
db, err := sql.Open("pgx", dsn)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Limit maximum number of open connections. This is useful to prevent
|
|
// the server from running out of connections and returning an error.
|
|
// With this client-side limit in place, lnd will wait for a connection
|
|
// to become available.
|
|
if d.maxConnections != 0 {
|
|
db.SetMaxOpenConns(d.maxConnections)
|
|
}
|
|
|
|
d.dbConn[dsn] = &dbConn{
|
|
db: db,
|
|
count: 1,
|
|
}
|
|
|
|
return db, nil
|
|
}
|
|
|
|
// Close closes the connection with the given dsn. If there are still other
|
|
// users of the same connection, this function does nothing.
|
|
func (d *dbConnSet) Close(dsn string) error {
|
|
d.Lock()
|
|
defer d.Unlock()
|
|
|
|
dbConn, ok := d.dbConn[dsn]
|
|
if !ok {
|
|
return fmt.Errorf("connection not found: %v", dsn)
|
|
}
|
|
|
|
// Reduce user count.
|
|
dbConn.count--
|
|
|
|
// Do not close if there are other users.
|
|
if dbConn.count > 0 {
|
|
return nil
|
|
}
|
|
|
|
// Close connection.
|
|
delete(d.dbConn, dsn)
|
|
|
|
return dbConn.db.Close()
|
|
}
|