mirror of
https://github.com/tendermint/tendermint.git
synced 2026-09-20 23:14:37 +00:00
go vendor; track uptime, health
This commit is contained in:
+13
@@ -0,0 +1,13 @@
|
||||
Copyright 2014 Alan Shreve
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
+225
@@ -0,0 +1,225 @@
|
||||
// Package stack implements utilities to capture, manipulate, and format call
|
||||
// stacks.
|
||||
package stack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Call records a single function invocation from a goroutine stack. It is a
|
||||
// wrapper for the program counter values returned by runtime.Caller and
|
||||
// runtime.Callers and consumed by runtime.FuncForPC.
|
||||
type Call uintptr
|
||||
|
||||
// Format implements fmt.Formatter with support for the following verbs.
|
||||
//
|
||||
// %s source file
|
||||
// %d line number
|
||||
// %n function name
|
||||
// %v equivalent to %s:%d
|
||||
//
|
||||
// It accepts the '+' and '#' flags for most of the verbs as follows.
|
||||
//
|
||||
// %+s path of source file relative to the compile time GOPATH
|
||||
// %#s full path of source file
|
||||
// %+n import path qualified function name
|
||||
// %+v equivalent to %+s:%d
|
||||
// %#v equivalent to %#s:%d
|
||||
func (pc Call) Format(s fmt.State, c rune) {
|
||||
// BUG(ChrisHines): Subtracting one from pc is a work around for
|
||||
// https://code.google.com/p/go/issues/detail?id=7690. The idea for this
|
||||
// work around comes from rsc's initial patch at
|
||||
// https://codereview.appspot.com/84100043/#ps20001, but as noted in the
|
||||
// issue discussion, it is not a complete fix since it doesn't handle some
|
||||
// cases involving signals. Just the same, it handles all of the other
|
||||
// cases I have tested.
|
||||
pcFix := uintptr(pc) - 1
|
||||
fn := runtime.FuncForPC(pcFix)
|
||||
if fn == nil {
|
||||
fmt.Fprintf(s, "%%!%c(NOFUNC)", c)
|
||||
return
|
||||
}
|
||||
|
||||
switch c {
|
||||
case 's', 'v':
|
||||
file, line := fn.FileLine(pcFix)
|
||||
switch {
|
||||
case s.Flag('#'):
|
||||
// done
|
||||
case s.Flag('+'):
|
||||
// Here we want to get the source file path relative to the
|
||||
// compile time GOPATH. As of Go 1.3.x there is no direct way to
|
||||
// know the compiled GOPATH at runtime, but we can infer the
|
||||
// number of path segments in the GOPATH. We note that fn.Name()
|
||||
// returns the function name qualified by the import path, which
|
||||
// does not include the GOPATH. Thus we can trim segments from the
|
||||
// beginning of the file path until the number of path separators
|
||||
// remaining is one more than the number of path separators in the
|
||||
// function name. For example, given:
|
||||
//
|
||||
// GOPATH /home/user
|
||||
// file /home/user/src/pkg/sub/file.go
|
||||
// fn.Name() pkg/sub.Type.Method
|
||||
//
|
||||
// We want to produce:
|
||||
//
|
||||
// pkg/sub/file.go
|
||||
//
|
||||
// From this we can easily see that fn.Name() has one less path
|
||||
// separator than our desired output.
|
||||
const sep = "/"
|
||||
impCnt := strings.Count(fn.Name(), sep) + 1
|
||||
pathCnt := strings.Count(file, sep)
|
||||
for pathCnt > impCnt {
|
||||
i := strings.Index(file, sep)
|
||||
if i == -1 {
|
||||
break
|
||||
}
|
||||
file = file[i+len(sep):]
|
||||
pathCnt--
|
||||
}
|
||||
default:
|
||||
const sep = "/"
|
||||
if i := strings.LastIndex(file, sep); i != -1 {
|
||||
file = file[i+len(sep):]
|
||||
}
|
||||
}
|
||||
fmt.Fprint(s, file)
|
||||
if c == 'v' {
|
||||
fmt.Fprint(s, ":", line)
|
||||
}
|
||||
|
||||
case 'd':
|
||||
_, line := fn.FileLine(pcFix)
|
||||
fmt.Fprint(s, line)
|
||||
|
||||
case 'n':
|
||||
name := fn.Name()
|
||||
if !s.Flag('+') {
|
||||
const pathSep = "/"
|
||||
if i := strings.LastIndex(name, pathSep); i != -1 {
|
||||
name = name[i+len(pathSep):]
|
||||
}
|
||||
const pkgSep = "."
|
||||
if i := strings.Index(name, pkgSep); i != -1 {
|
||||
name = name[i+len(pkgSep):]
|
||||
}
|
||||
}
|
||||
fmt.Fprint(s, name)
|
||||
}
|
||||
}
|
||||
|
||||
// Callers returns a Trace for the current goroutine with element 0
|
||||
// identifying the calling function.
|
||||
func Callers() Trace {
|
||||
pcs := poolBuf()
|
||||
pcs = pcs[:cap(pcs)]
|
||||
n := runtime.Callers(2, pcs)
|
||||
cs := make([]Call, n)
|
||||
for i, pc := range pcs[:n] {
|
||||
cs[i] = Call(pc)
|
||||
}
|
||||
putPoolBuf(pcs)
|
||||
return cs
|
||||
}
|
||||
|
||||
// name returns the import path qualified name of the function containing the
|
||||
// call.
|
||||
func (pc Call) name() string {
|
||||
pcFix := uintptr(pc) - 1 // work around for go issue #7690
|
||||
fn := runtime.FuncForPC(pcFix)
|
||||
if fn == nil {
|
||||
return "???"
|
||||
}
|
||||
return fn.Name()
|
||||
}
|
||||
|
||||
func (pc Call) file() string {
|
||||
pcFix := uintptr(pc) - 1 // work around for go issue #7690
|
||||
fn := runtime.FuncForPC(pcFix)
|
||||
if fn == nil {
|
||||
return "???"
|
||||
}
|
||||
file, _ := fn.FileLine(pcFix)
|
||||
return file
|
||||
}
|
||||
|
||||
// Trace records a sequence of function invocations from a goroutine stack.
|
||||
type Trace []Call
|
||||
|
||||
// Format implements fmt.Formatter by printing the Trace as square brackes ([,
|
||||
// ]) surrounding a space separated list of Calls each formatted with the
|
||||
// supplied verb and options.
|
||||
func (pcs Trace) Format(s fmt.State, c rune) {
|
||||
s.Write([]byte("["))
|
||||
for i, pc := range pcs {
|
||||
if i > 0 {
|
||||
s.Write([]byte(" "))
|
||||
}
|
||||
pc.Format(s, c)
|
||||
}
|
||||
s.Write([]byte("]"))
|
||||
}
|
||||
|
||||
// TrimBelow returns a slice of the Trace with all entries below pc removed.
|
||||
func (pcs Trace) TrimBelow(pc Call) Trace {
|
||||
for len(pcs) > 0 && pcs[0] != pc {
|
||||
pcs = pcs[1:]
|
||||
}
|
||||
return pcs
|
||||
}
|
||||
|
||||
// TrimAbove returns a slice of the Trace with all entries above pc removed.
|
||||
func (pcs Trace) TrimAbove(pc Call) Trace {
|
||||
for len(pcs) > 0 && pcs[len(pcs)-1] != pc {
|
||||
pcs = pcs[:len(pcs)-1]
|
||||
}
|
||||
return pcs
|
||||
}
|
||||
|
||||
// TrimBelowName returns a slice of the Trace with all entries below the
|
||||
// lowest with function name name removed.
|
||||
func (pcs Trace) TrimBelowName(name string) Trace {
|
||||
for len(pcs) > 0 && pcs[0].name() != name {
|
||||
pcs = pcs[1:]
|
||||
}
|
||||
return pcs
|
||||
}
|
||||
|
||||
// TrimAboveName returns a slice of the Trace with all entries above the
|
||||
// highest with function name name removed.
|
||||
func (pcs Trace) TrimAboveName(name string) Trace {
|
||||
for len(pcs) > 0 && pcs[len(pcs)-1].name() != name {
|
||||
pcs = pcs[:len(pcs)-1]
|
||||
}
|
||||
return pcs
|
||||
}
|
||||
|
||||
var goroot string
|
||||
|
||||
func init() {
|
||||
goroot = filepath.ToSlash(runtime.GOROOT())
|
||||
if runtime.GOOS == "windows" {
|
||||
goroot = strings.ToLower(goroot)
|
||||
}
|
||||
}
|
||||
|
||||
func inGoroot(path string) bool {
|
||||
if runtime.GOOS == "windows" {
|
||||
path = strings.ToLower(path)
|
||||
}
|
||||
return strings.HasPrefix(path, goroot)
|
||||
}
|
||||
|
||||
// TrimRuntime returns a slice of the Trace with the topmost entries from the
|
||||
// go runtime removed. It considers any calls originating from files under
|
||||
// GOROOT as part of the runtime.
|
||||
func (pcs Trace) TrimRuntime() Trace {
|
||||
for len(pcs) > 0 && inGoroot(pcs[len(pcs)-1].file()) {
|
||||
pcs = pcs[:len(pcs)-1]
|
||||
}
|
||||
return pcs
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// +build go1.3
|
||||
|
||||
package stack
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
var pcStackPool = sync.Pool{
|
||||
New: func() interface{} { return make([]uintptr, 1000) },
|
||||
}
|
||||
|
||||
func poolBuf() []uintptr {
|
||||
return pcStackPool.Get().([]uintptr)
|
||||
}
|
||||
|
||||
func putPoolBuf(p []uintptr) {
|
||||
pcStackPool.Put(p)
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
// +build !go1.3 appengine
|
||||
|
||||
package stack
|
||||
|
||||
const (
|
||||
stackPoolSize = 64
|
||||
)
|
||||
|
||||
var (
|
||||
pcStackPool = make(chan []uintptr, stackPoolSize)
|
||||
)
|
||||
|
||||
func poolBuf() []uintptr {
|
||||
select {
|
||||
case p := <-pcStackPool:
|
||||
return p
|
||||
default:
|
||||
return make([]uintptr, 1000)
|
||||
}
|
||||
}
|
||||
|
||||
func putPoolBuf(p []uintptr) {
|
||||
select {
|
||||
case pcStackPool <- p:
|
||||
default:
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Simon Eskildsen
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// Based on ssh/terminal:
|
||||
// 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.
|
||||
|
||||
// +build appengine
|
||||
|
||||
package term
|
||||
|
||||
// IsTty always returns false on AppEngine.
|
||||
func IsTty(fd uintptr) bool {
|
||||
return false
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
// Based on ssh/terminal:
|
||||
// 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 term
|
||||
|
||||
import "syscall"
|
||||
|
||||
const ioctlReadTermios = syscall.TIOCGETA
|
||||
|
||||
type Termios syscall.Termios
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package term
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
const ioctlReadTermios = syscall.TIOCGETA
|
||||
|
||||
// Go 1.2 doesn't include Termios for FreeBSD. This should be added in 1.3 and this could be merged with terminal_darwin.
|
||||
type Termios struct {
|
||||
Iflag uint32
|
||||
Oflag uint32
|
||||
Cflag uint32
|
||||
Lflag uint32
|
||||
Cc [20]uint8
|
||||
Ispeed uint32
|
||||
Ospeed uint32
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
// Based on ssh/terminal:
|
||||
// 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.
|
||||
|
||||
// +build !appengine
|
||||
|
||||
package term
|
||||
|
||||
import "syscall"
|
||||
|
||||
const ioctlReadTermios = syscall.TCGETS
|
||||
|
||||
type Termios syscall.Termios
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// Based on ssh/terminal:
|
||||
// Copyright 2011 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.
|
||||
|
||||
// +build linux,!appengine darwin freebsd openbsd
|
||||
|
||||
package term
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// IsTty returns true if the given file descriptor is a terminal.
|
||||
func IsTty(fd uintptr) bool {
|
||||
var termios Termios
|
||||
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
|
||||
return err == 0
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package term
|
||||
|
||||
import "syscall"
|
||||
|
||||
const ioctlReadTermios = syscall.TIOCGETA
|
||||
|
||||
type Termios syscall.Termios
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// Based on ssh/terminal:
|
||||
// Copyright 2011 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.
|
||||
|
||||
// +build windows
|
||||
|
||||
package term
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||
|
||||
var (
|
||||
procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
|
||||
)
|
||||
|
||||
// IsTty returns true if the given file descriptor is a terminal.
|
||||
func IsTty(fd uintptr) bool {
|
||||
var st uint32
|
||||
r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, fd, uintptr(unsafe.Pointer(&st)), 0)
|
||||
return r != 0 && e == 0
|
||||
}
|
||||
Reference in New Issue
Block a user