11package function
22
33import (
4- "crypto/sha1"
54 "encoding/json"
65 "fmt"
76 "hash"
@@ -16,7 +15,6 @@ import (
1615 "github.com/bblfsh/sdk/v3/uast"
1716 "github.com/bblfsh/sdk/v3/uast/nodes"
1817 "github.com/go-kit/kit/metrics/discard"
19- lru "github.com/hashicorp/golang-lru"
2018 "github.com/sirupsen/logrus"
2119
2220 "github.com/src-d/go-mysql-server/sql"
@@ -53,8 +51,24 @@ func observeQuery(lang, xpath string, t time.Time) func(bool) {
5351 }
5452}
5553
56- var uastCache * lru.Cache
57- var uastMaxBlobSize int
54+ var (
55+ uastmut sync.Mutex
56+ uastCache sql.KeyValueCache
57+ uastCacheSize int
58+ uastMaxBlobSize int
59+ )
60+
61+ func getUASTCache (ctx * sql.Context ) sql.KeyValueCache {
62+ uastmut .Lock ()
63+ defer uastmut .Unlock ()
64+ if uastCache == nil {
65+ // Dispose function is ignored because the cache will never be disposed
66+ // until the program dies.
67+ uastCache , _ = ctx .Memory .NewLRUCache (uint (uastCacheSize ))
68+ }
69+
70+ return uastCache
71+ }
5872
5973func init () {
6074 s := os .Getenv (uastCacheSizeKey )
@@ -63,10 +77,7 @@ func init() {
6377 size = defaultUASTCacheSize
6478 }
6579
66- uastCache , err = lru .New (size )
67- if err != nil {
68- panic (fmt .Errorf ("cannot initialize UAST cache: %s" , err ))
69- }
80+ uastCacheSize = size
7081
7182 uastMaxBlobSize , err = strconv .Atoi (os .Getenv (uastMaxBlobSizeKey ))
7283 if err != nil {
@@ -83,7 +94,7 @@ type uastFunc struct {
8394 Lang sql.Expression
8495 XPath sql.Expression
8596
86- h hash.Hash
97+ h hash.Hash64
8798 m sync.Mutex
8899}
89100
@@ -151,7 +162,7 @@ func (u *uastFunc) WithChildren(children ...sql.Expression) (sql.Expression, err
151162 Blob : blob ,
152163 XPath : xpath ,
153164 Lang : lang ,
154- h : sha1 . New (),
165+ h : newHash (),
155166 }, nil
156167}
157168
@@ -234,6 +245,13 @@ func (u *uastFunc) Eval(ctx *sql.Context, row sql.Row) (out interface{}, err err
234245 return u .getUAST (ctx , bytes , lang , xpath , mode )
235246}
236247
248+ func (u * uastFunc ) computeKey (mode , lang string , blob []byte ) (uint64 , error ) {
249+ u .m .Lock ()
250+ defer u .m .Unlock ()
251+
252+ return computeKey (u .h , mode , lang , blob )
253+ }
254+
237255func (u * uastFunc ) getUAST (
238256 ctx * sql.Context ,
239257 blob []byte ,
@@ -242,17 +260,17 @@ func (u *uastFunc) getUAST(
242260) (interface {}, error ) {
243261 finish := observeQuery (lang , xpath , time .Now ())
244262
245- u .m .Lock ()
246- key , err := computeKey (u .h , mode .String (), lang , blob )
247- u .m .Unlock ()
248-
263+ key , err := u .computeKey (mode .String (), lang , blob )
249264 if err != nil {
250265 return nil , err
251266 }
252267
268+ uastCache := getUASTCache (ctx )
269+
253270 var node nodes.Node
254- value , ok := uastCache .Get (key )
255- if ok {
271+ value , err := uastCache .Get (key )
272+ cacheMiss := err != nil
273+ if ! cacheMiss {
256274 node = value .(nodes.Node )
257275 } else {
258276 var err error
@@ -265,7 +283,9 @@ func (u *uastFunc) getUAST(
265283 return nil , err
266284 }
267285
268- uastCache .Add (key , node )
286+ if err := uastCache .Put (key , node ); err != nil {
287+ return nil , err
288+ }
269289 }
270290
271291 var nodeArray nodes.Array
@@ -288,7 +308,7 @@ func (u *uastFunc) getUAST(
288308 return nil , nil
289309 }
290310
291- finish (ok )
311+ finish (! cacheMiss )
292312
293313 return result , nil
294314}
@@ -321,7 +341,7 @@ func NewUAST(args ...sql.Expression) (sql.Expression, error) {
321341 Blob : blob ,
322342 Lang : lang ,
323343 XPath : xpath ,
324- h : sha1 . New (),
344+ h : newHash (),
325345 }}, nil
326346}
327347
@@ -380,7 +400,7 @@ func NewUASTMode(mode, blob, lang sql.Expression) sql.Expression {
380400 Blob : blob ,
381401 Lang : lang ,
382402 XPath : nil ,
383- h : sha1 . New (),
403+ h : newHash (),
384404 }}
385405}
386406
0 commit comments