package stmtcache
import (
)
type lruNode struct {
sd *pgconn.StatementDescription
prev *lruNode
next *lruNode
}
type LRUCache struct {
m map[string]*lruNode
head *lruNode
tail *lruNode
len int
cap int
freelist *lruNode
invalidStmts []*pgconn.StatementDescription
invalidSet map[string]struct{}
}
func ( int) *LRUCache {
:= &lruNode{}
:= &lruNode{}
.next =
.prev =
return &LRUCache{
cap: ,
m: make(map[string]*lruNode, ),
head: ,
tail: ,
invalidSet: make(map[string]struct{}),
}
}
func ( *LRUCache) ( string) *pgconn.StatementDescription {
, := .m[]
if ! {
return nil
}
.moveToFront()
return .sd
}
func ( *LRUCache) ( *pgconn.StatementDescription) {
if .SQL == "" {
panic("cannot store statement description with empty SQL")
}
if , := .m[.SQL]; {
return
}
if , := .invalidSet[.SQL]; {
return
}
if .len == .cap {
.invalidateOldest()
}
:= .allocNode()
.sd =
.insertAfter(.head, )
.m[.SQL] =
.len++
}
func ( *LRUCache) ( string) {
, := .m[]
if ! {
return
}
delete(.m, )
.invalidStmts = append(.invalidStmts, .sd)
.invalidSet[] = struct{}{}
.unlink()
.len--
.freeNode()
}
func ( *LRUCache) () {
for := .head.next; != .tail; {
:= .next
.invalidStmts = append(.invalidStmts, .sd)
.invalidSet[.sd.SQL] = struct{}{}
.freeNode()
=
}
clear(.m)
.head.next = .tail
.tail.prev = .head
.len = 0
}
func ( *LRUCache) () []*pgconn.StatementDescription {
return .invalidStmts
}
func ( *LRUCache) () {
.invalidStmts = .invalidStmts[:0]
clear(.invalidSet)
}
func ( *LRUCache) () int {
return .len
}
func ( *LRUCache) () int {
return .cap
}
func ( *LRUCache) () {
:= .tail.prev
if == .head {
return
}
.invalidStmts = append(.invalidStmts, .sd)
.invalidSet[.sd.SQL] = struct{}{}
delete(.m, .sd.SQL)
.unlink()
.len--
.freeNode()
}
func ( *LRUCache) (, *lruNode) {
.prev =
.next = .next
.next.prev =
.next =
}
func ( *LRUCache) ( *lruNode) {
.prev.next = .next
.next.prev = .prev
}
func ( *LRUCache) ( *lruNode) {
if .prev == .head {
return
}
.unlink()
.insertAfter(.head, )
}
func ( *LRUCache) () *lruNode {
if .freelist != nil {
:= .freelist
.freelist = .next
.next = nil
.prev = nil
return
}
return &lruNode{}
}
func ( *LRUCache) ( *lruNode) {
.sd = nil
.prev = nil
.next = .freelist
.freelist =
}