mirror of
https://github.com/golang/go
synced 2024-11-18 15:34:53 -07:00
006ac430a0
Currently, in http mode the server blocks until the corpus has been initialized. This can cause considerable delay if the user workspace is significantly large and the files are not present in the buffer cache. This CL spawns off the initialization in a separate goroutine if httpMode is set and turns on a flag when it's done. The http handler checks the flag and returns an error response if it has not been set. The check is only performed for the path prefixes handled by the handlerServer struct. Other paths do not call the GetPageInfo() function and hence can return immediately. This preserves maximum responsiveness of the server. Also adds an additional print statement in verbose mode Note: This is a re-do of a previous CL golang.org/cl/88695 which was incorrect committed without running tests. This CL fixes that test. Fixes golang/go#13278 Change-Id: I80c801f32af007312090d3783a2ea2c6f92cad66 Reviewed-on: https://go-review.googlesource.com/93215 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
165 lines
4.8 KiB
Go
165 lines
4.8 KiB
Go
// Copyright 2013 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 godoc
|
|
|
|
import (
|
|
"errors"
|
|
pathpkg "path"
|
|
"sync"
|
|
"time"
|
|
|
|
"golang.org/x/tools/godoc/analysis"
|
|
"golang.org/x/tools/godoc/util"
|
|
"golang.org/x/tools/godoc/vfs"
|
|
)
|
|
|
|
// A Corpus holds all the state related to serving and indexing a
|
|
// collection of Go code.
|
|
//
|
|
// Construct a new Corpus with NewCorpus, then modify options,
|
|
// then call its Init method.
|
|
type Corpus struct {
|
|
fs vfs.FileSystem
|
|
|
|
// Verbose logging.
|
|
Verbose bool
|
|
|
|
// IndexEnabled controls whether indexing is enabled.
|
|
IndexEnabled bool
|
|
|
|
// IndexFiles specifies a glob pattern specifying index files.
|
|
// If not empty, the index is read from these files in sorted
|
|
// order.
|
|
IndexFiles string
|
|
|
|
// IndexThrottle specifies the indexing throttle value
|
|
// between 0.0 and 1.0. At 0.0, the indexer always sleeps.
|
|
// At 1.0, the indexer never sleeps. Because 0.0 is useless
|
|
// and redundant with setting IndexEnabled to false, the
|
|
// zero value for IndexThrottle means 0.9.
|
|
IndexThrottle float64
|
|
|
|
// IndexInterval specifies the time to sleep between reindexing
|
|
// all the sources.
|
|
// If zero, a default is used. If negative, the index is only
|
|
// built once.
|
|
IndexInterval time.Duration
|
|
|
|
// IndexDocs enables indexing of Go documentation.
|
|
// This will produce search results for exported types, functions,
|
|
// methods, variables, and constants, and will link to the godoc
|
|
// documentation for those identifiers.
|
|
IndexDocs bool
|
|
|
|
// IndexGoCode enables indexing of Go source code.
|
|
// This will produce search results for internal and external identifiers
|
|
// and will link to both declarations and uses of those identifiers in
|
|
// source code.
|
|
IndexGoCode bool
|
|
|
|
// IndexFullText enables full-text indexing.
|
|
// This will provide search results for any matching text in any file that
|
|
// is indexed, including non-Go files (see whitelisted in index.go).
|
|
// Regexp searching is supported via full-text indexing.
|
|
IndexFullText bool
|
|
|
|
// MaxResults optionally specifies the maximum results for indexing.
|
|
MaxResults int
|
|
|
|
// SummarizePackage optionally specifies a function to
|
|
// summarize a package. It exists as an optimization to
|
|
// avoid reading files to parse package comments.
|
|
//
|
|
// If SummarizePackage returns false for ok, the caller
|
|
// ignores all return values and parses the files in the package
|
|
// as if SummarizePackage were nil.
|
|
//
|
|
// If showList is false, the package is hidden from the
|
|
// package listing.
|
|
SummarizePackage func(pkg string) (summary string, showList, ok bool)
|
|
|
|
// IndexDirectory optionally specifies a function to determine
|
|
// whether the provided directory should be indexed. The dir
|
|
// will be of the form "/src/cmd/6a", "/doc/play",
|
|
// "/src/io", etc.
|
|
// If nil, all directories are indexed if indexing is enabled.
|
|
IndexDirectory func(dir string) bool
|
|
|
|
testDir string // TODO(bradfitz,adg): migrate old godoc flag? looks unused.
|
|
|
|
// Send a value on this channel to trigger a metadata refresh.
|
|
// It is buffered so that if a signal is not lost if sent
|
|
// during a refresh.
|
|
refreshMetadataSignal chan bool
|
|
|
|
// file system information
|
|
fsTree util.RWValue // *Directory tree of packages, updated with each sync (but sync code is removed now)
|
|
fsModified util.RWValue // timestamp of last call to invalidateIndex
|
|
docMetadata util.RWValue // mapping from paths to *Metadata
|
|
|
|
// SearchIndex is the search index in use.
|
|
searchIndex util.RWValue
|
|
|
|
// Analysis is the result of type and pointer analysis.
|
|
Analysis analysis.Result
|
|
|
|
// flag to check whether a corpus is initialized or not
|
|
initMu sync.RWMutex
|
|
initDone bool
|
|
}
|
|
|
|
// NewCorpus returns a new Corpus from a filesystem.
|
|
// The returned corpus has all indexing enabled and MaxResults set to 1000.
|
|
// Change or set any options on Corpus before calling the Corpus.Init method.
|
|
func NewCorpus(fs vfs.FileSystem) *Corpus {
|
|
c := &Corpus{
|
|
fs: fs,
|
|
refreshMetadataSignal: make(chan bool, 1),
|
|
|
|
MaxResults: 1000,
|
|
IndexEnabled: true,
|
|
IndexDocs: true,
|
|
IndexGoCode: true,
|
|
IndexFullText: true,
|
|
}
|
|
return c
|
|
}
|
|
|
|
func (c *Corpus) CurrentIndex() (*Index, time.Time) {
|
|
v, t := c.searchIndex.Get()
|
|
idx, _ := v.(*Index)
|
|
return idx, t
|
|
}
|
|
|
|
func (c *Corpus) FSModifiedTime() time.Time {
|
|
_, ts := c.fsModified.Get()
|
|
return ts
|
|
}
|
|
|
|
// Init initializes Corpus, once options on Corpus are set.
|
|
// It must be called before any subsequent method calls.
|
|
func (c *Corpus) Init() error {
|
|
if err := c.initFSTree(); err != nil {
|
|
return err
|
|
}
|
|
c.updateMetadata()
|
|
go c.refreshMetadataLoop()
|
|
|
|
c.initMu.Lock()
|
|
c.initDone = true
|
|
c.initMu.Unlock()
|
|
return nil
|
|
}
|
|
|
|
func (c *Corpus) initFSTree() error {
|
|
dir := c.newDirectory(pathpkg.Join("/", c.testDir), -1)
|
|
if dir == nil {
|
|
return errors.New("godoc: corpus fstree is nil")
|
|
}
|
|
c.fsTree.Set(dir)
|
|
c.invalidateIndex()
|
|
return nil
|
|
}
|