mirror of
https://github.com/golang/go
synced 2024-11-18 21:44:45 -07:00
54cf04ef09
This uses log messages to convey information to the debug system, which has the benefit of logging even if the debug pages are not active and also not requiring systems to reach into the debug system or require extra lifetime tracking Not all things are decoupled yet as there are a couple of places (notably the handshaker) that read information out of the debug system. Change-Id: Iec1f81c34ab3b11b3e3d6e6eb39b98ee5ed0d849 Reviewed-on: https://go-review.googlesource.com/c/tools/+/236337 Run-TryBot: Ian Cottrell <iancottrell@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
119 lines
2.6 KiB
Go
119 lines
2.6 KiB
Go
// Copyright 2019 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package cache
|
|
|
|
import (
|
|
"context"
|
|
"crypto/sha1"
|
|
"fmt"
|
|
"go/token"
|
|
"reflect"
|
|
"strconv"
|
|
"sync/atomic"
|
|
|
|
"golang.org/x/tools/internal/event"
|
|
"golang.org/x/tools/internal/lsp/source"
|
|
"golang.org/x/tools/internal/memoize"
|
|
"golang.org/x/tools/internal/span"
|
|
)
|
|
|
|
func New(ctx context.Context, options func(*source.Options)) *Cache {
|
|
index := atomic.AddInt64(&cacheIndex, 1)
|
|
c := &Cache{
|
|
fs: &nativeFileSystem{},
|
|
id: strconv.FormatInt(index, 10),
|
|
fset: token.NewFileSet(),
|
|
options: options,
|
|
}
|
|
return c
|
|
}
|
|
|
|
type Cache struct {
|
|
fs source.FileSystem
|
|
id string
|
|
fset *token.FileSet
|
|
options func(*source.Options)
|
|
|
|
store memoize.Store
|
|
}
|
|
|
|
type fileKey struct {
|
|
identity source.FileIdentity
|
|
}
|
|
|
|
type fileHandle struct {
|
|
cache *Cache
|
|
underlying source.FileHandle
|
|
handle *memoize.Handle
|
|
}
|
|
|
|
type fileData struct {
|
|
memoize.NoCopy
|
|
bytes []byte
|
|
hash string
|
|
err error
|
|
}
|
|
|
|
func (c *Cache) GetFile(uri span.URI) source.FileHandle {
|
|
underlying := c.fs.GetFile(uri)
|
|
key := fileKey{
|
|
identity: underlying.Identity(),
|
|
}
|
|
h := c.store.Bind(key, func(ctx context.Context) interface{} {
|
|
data := &fileData{}
|
|
data.bytes, data.hash, data.err = underlying.Read(ctx)
|
|
return data
|
|
})
|
|
return &fileHandle{
|
|
cache: c,
|
|
underlying: underlying,
|
|
handle: h,
|
|
}
|
|
}
|
|
|
|
func (c *Cache) NewSession(ctx context.Context) *Session {
|
|
index := atomic.AddInt64(&sessionIndex, 1)
|
|
s := &Session{
|
|
cache: c,
|
|
id: strconv.FormatInt(index, 10),
|
|
options: source.DefaultOptions(),
|
|
overlays: make(map[span.URI]*overlay),
|
|
}
|
|
event.Log(ctx, "New session", KeyCreateSession.Of(s))
|
|
return s
|
|
}
|
|
|
|
func (c *Cache) FileSet() *token.FileSet {
|
|
return c.fset
|
|
}
|
|
|
|
func (h *fileHandle) FileSystem() source.FileSystem {
|
|
return h.cache
|
|
}
|
|
|
|
func (h *fileHandle) Identity() source.FileIdentity {
|
|
return h.underlying.Identity()
|
|
}
|
|
|
|
func (h *fileHandle) Read(ctx context.Context) ([]byte, string, error) {
|
|
v := h.handle.Get(ctx)
|
|
if v == nil {
|
|
return nil, "", ctx.Err()
|
|
}
|
|
data := v.(*fileData)
|
|
return data.bytes, data.hash, data.err
|
|
}
|
|
|
|
func hashContents(contents []byte) string {
|
|
// TODO: consider whether sha1 is the best choice here
|
|
// This hash is used for internal identity detection only
|
|
return fmt.Sprintf("%x", sha1.Sum(contents))
|
|
}
|
|
|
|
var cacheIndex, sessionIndex, viewIndex int64
|
|
|
|
func (c *Cache) ID() string { return c.id }
|
|
func (c *Cache) MemStats() map[reflect.Type]int { return c.store.Stats() }
|