make an error handling function

Signed-off-by: Jeff Carr <jcarr@wit.com>
This commit is contained in:
Jeff Carr 2019-06-06 09:35:17 -07:00
parent e1b30b97cc
commit fc6db10c22
10 changed files with 321 additions and 30 deletions

33
bench1/fast-timer.go Normal file
View File

@ -0,0 +1,33 @@
package main
import (
"fmt"
"time"
)
var start time.Time
func init() {
start = time.Now()
}
func main() {
fmt.Println("main() started", time.Since(start))
chan1 := make(chan string, 2)
chan2 := make(chan string, 2)
chan1 <- "Value 1"
chan1 <- "Value 2"
chan2 <- "Value 1"
chan2 <- "Value 2"
select {
case res := <-chan1:
fmt.Println("Response from chan1", res, time.Since(start))
case res := <-chan2:
fmt.Println("Response from chan2", res, time.Since(start))
}
fmt.Println("main() stopped", time.Since(start))
for {}
}

115
bench1/readWriteOps.go Normal file
View File

@ -0,0 +1,115 @@
// In the previous example we used explicit locking with
// [mutexes](mutexes) to synchronize access to shared state
// across multiple goroutines. Another option is to use the
// built-in synchronization features of goroutines and
// channels to achieve the same result. This channel-based
// approach aligns with Go's ideas of sharing memory by
// communicating and having each piece of data owned
// by exactly 1 goroutine.
package main
import (
"fmt"
"math/rand"
"sync/atomic"
"time"
)
// In this example our state will be owned by a single
// goroutine. This will guarantee that the data is never
// corrupted with concurrent access. In order to read or
// write that state, other goroutines will send messages
// to the owning goroutine and receive corresponding
// replies. These `readOp` and `writeOp` `struct`s
// encapsulate those requests and a way for the owning
// goroutine to respond.
type readOp struct {
key int
resp chan int
}
type writeOp struct {
key int
val int
resp chan bool
}
func main() {
// As before we'll count how many operations we perform.
var readOps uint64
var writeOps uint64
// The `reads` and `writes` channels will be used by
// other goroutines to issue read and write requests,
// respectively.
reads := make(chan readOp)
writes := make(chan writeOp)
// Here is the goroutine that owns the `state`, which
// is a map as in the previous example but now private
// to the stateful goroutine. This goroutine repeatedly
// selects on the `reads` and `writes` channels,
// responding to requests as they arrive. A response
// is executed by first performing the requested
// operation and then sending a value on the response
// channel `resp` to indicate success (and the desired
// value in the case of `reads`).
go func() {
var state = make(map[int]int)
for {
select {
case read := <-reads:
read.resp <- state[read.key]
case write := <-writes:
state[write.key] = write.val
write.resp <- true
}
}
}()
// This starts 100 goroutines to issue reads to the
// state-owning goroutine via the `reads` channel.
// Each read requires constructing a `readOp`, sending
// it over the `reads` channel, and the receiving the
// result over the provided `resp` channel.
for r := 0; r < 100; r++ {
go func() {
for {
read := readOp{
key: rand.Intn(5),
resp: make(chan int)}
reads <- read
<-read.resp
atomic.AddUint64(&readOps, 1)
time.Sleep(time.Millisecond)
}
}()
}
// We start 10 writes as well, using a similar
// approach.
for w := 0; w < 10; w++ {
go func() {
for {
write := writeOp{
key: rand.Intn(5),
val: rand.Intn(100),
resp: make(chan bool)}
writes <- write
<-write.resp
atomic.AddUint64(&writeOps, 1)
time.Sleep(time.Millisecond)
}
}()
}
// Let the goroutines work for a second.
time.Sleep(time.Second)
// Finally, capture and report the op counts.
readOpsFinal := atomic.LoadUint64(&readOps)
fmt.Println("readOps:", readOpsFinal)
writeOpsFinal := atomic.LoadUint64(&writeOps)
fmt.Println("writeOps:", writeOpsFinal)
}

0
bench1/stuff.go Normal file
View File

View File

@ -1,5 +1,7 @@
package main
// This should build and upload the binary to mirrors
import "log"
// import "fmt"
import "os"
@ -20,7 +22,22 @@ var builddir string
var homedir string
func main() {
os.Chdir("~/go/src/wit/cloud-control-panel")
// os.Chdir("~/go/src/wit/cloud-control-panel")
// set epoch, version,
// set build cloud-control-panel
// get build time
// go build -ldflags
// "
// -X main.GITCOMMIT=${GITCOMMIT}
// -X main.GOVERSION='${GOVERSION}'
// -X main.BUILDTIME='${BUILDTIME}'
// -X main.VERSION=${VERSION}
// "
// upload binary to mirrors.wit.com/cloud/control-panel
setupUser()
@ -36,39 +53,13 @@ func main() {
shell.Run("pwd")
for {
time.Sleep(time.Second * 5)
build()
os.Exit(0)
time.Sleep(time.Second * 5)
}
}
/*
// slow down the polling to every 2 seconds
shell.SetDelayInMsec(2000)
shell.Run("ping -c 6 localhost")
// capture ping output into a file
fout, _ := os.Create("/tmp/example1.ping.stdout")
ferr, _ := os.Create("/tmp/example1.ping.stderr")
shell.SetStdout(fout)
shell.SetStderr(ferr)
shell.Run("ping -c 5 localhost")
// turn out process exit debugging
shell.SpewOn()
fout, _ = os.Create("/tmp/example1.fail.stdout")
ferr, _ = os.Create("/tmp/example1.fail.stderr")
shell.SetStdout(fout)
shell.SetStderr(ferr)
// TODO: this might not be working
// check error handling
shell.Run("ls /tmpthisisnothere")
*/
func build() {
// shell.SetDelayInMsec(50)
shell.Run("go get -v .")
@ -91,7 +82,6 @@ func ping() {
shell.Run("ping -c 6 localhost")
}
// func setupUser() string, string, string {
func setupUser() {
// look up the user information

View File

@ -16,10 +16,12 @@ import "os/user"
import "flag"
import "fmt"
import "runtime"
// import "runtime/debug"
import "io/ioutil"
import "strings"
import "reflect"
import "bytes"
// import "sys"
import "github.com/golang/protobuf/jsonpb"
import pb "git.wit.com/wit/witProtobuf"
@ -271,6 +273,33 @@ func parseConfig() {
log.Println("config.Gitref =", config.Gitref)
log.Println("config.Goversion =", config.Goversion)
log.Println("config.Dirty =", config.Dirty)
log.Println("runtime.Version =", runtime.Version())
log.Println("runtime Number of CPUs =", runtime.NumCPU())
log.Println("runtime Number of GoRoutines =", runtime.NumGoroutine())
log.Println("runtime.GOARCH =", runtime.GOARCH)
stackSlice := make([]byte, 12512)
s := runtime.Stack(stackSlice, false)
fmt.Printf("\n%s", stackSlice[0:s])
// blah := runtime.Stack()
spew.Dump(s)
// bi, biok := debug.ReadBuildInfo()
// log.Println("debug.BuildInfo() ok =", biok)
// spew.Dump(bi.Path)
// spew.Dump(bi.Main)
// log.Println("debug.BuildInfo.Path =", bi.Path)
errChan <- "hello"
errChan <- "hello"
errChan <- "hello"
errChan <- fmt.Errorf("mainMouseClick() got b = nil")
errChan <- "hello"
// for {}
// os.Exit(0)
}
func chompBytesBuffer(buf *bytes.Buffer) string {

78
example-pprof/main.go Normal file
View File

@ -0,0 +1,78 @@
package main
// run this and then hit:
// http://localhost:6060/debug/pprof/
//
// Also run from the command line:
// go tool pprof 'localhost:6060/debug/pprof/wit_pprof_experiment_thing?debug=1'
//
// https://medium.com/@cep21/creating-custom-go-profiles-with-pprof-b737dfc58e11
import "fmt"
import "log"
import "net/http"
import _ "net/http/pprof" // the _ means only the init() is needed
import "os"
import "runtime/pprof"
import "sync/atomic"
import "time"
var libProfile *pprof.Profile
func init() {
profName := "wit_pprof_experiment_thing" // this ends up in the URL
libProfile = pprof.Lookup(profName)
if libProfile == nil {
libProfile = pprof.NewProfile(profName)
}
}
type someResource struct {
*os.File
}
var fileIndex = int64(0)
func MustResource() *someResource {
f, err := os.Create(fmt.Sprintf("/tmp/%d.txt", atomic.AddInt64(&fileIndex, 1)))
if err != nil {
panic(err)
}
r := &someResource{f}
libProfile.Add(r, 1)
return r
}
func (r *someResource) Close() error {
libProfile.Remove(r)
return r.File.Close()
}
func trackAFunction() {
tracked := new(byte)
libProfile.Add(tracked, 1)
defer libProfile.Remove(tracked)
time.Sleep(time.Second)
}
func usesAResource() {
res := MustResource()
defer res.Close()
for i := 0; i < 10; i++ {
time.Sleep(time.Second)
}
}
func main() {
http.HandleFunc("/nonblock", func(rw http.ResponseWriter, req *http.Request) {
go usesAResource()
})
http.HandleFunc("/functiontrack", func(rw http.ResponseWriter, req *http.Request) {
trackAFunction()
})
http.HandleFunc("/block", func(rw http.ResponseWriter, req *http.Request) {
usesAResource()
})
log.Println("Running!")
log.Println(http.ListenAndServe("localhost:6060", nil))
}

Binary file not shown.

48
main.go
View File

@ -3,7 +3,9 @@ package main
import "log"
import "os"
import "time"
// import "reflect"
import "reflect"
import "os/signal"
import "syscall"
// this is the king of dns libraries
import "github.com/miekg/dns"
@ -11,6 +13,7 @@ import "github.com/miekg/dns"
import "git.wit.com/wit/gui"
import pb "git.wit.com/wit/witProtobuf"
import "git.wit.com/jcarr/dnssecsocket"
import "git.wit.com/wit/shell"
import "github.com/gobuffalo/packr"
import "github.com/davecgh/go-spew/spew"
@ -21,6 +24,8 @@ var BUILDTIME string // this is passed in as an ldflag
var VERSION string // this is passed in as an ldflag
var State string // used as a State machine
var sigChan chan os.Signal
var errChan chan interface{}
type myButtonInfo struct {
Account *pb.Account // associated with what account?
@ -57,6 +62,9 @@ type myButtonInfo struct {
// i18n with 'po' file support
// https://github.com/leonelquinteros/gotext
// a good example of using interface{}
// https://github.com/Jeffail/tunny
func onExit(err error) {
log.Println("Sleep for 1 second")
time.Sleep(1 * 1000 * 1000 * 1000)
@ -86,6 +94,8 @@ func lookupAAAA(hostname string) string {
}
func main() {
go handleErrors()
// This puts all the files in that directory in the binary
// This directory includes the default config file if there is not already one
packrBox = packr.NewBox("./resources")
@ -167,3 +177,39 @@ func r() {
}
}
}
func init() {
log.Println("init() WAS HERE")
log.Println("init() WAS HERE")
log.Println("init() WAS HERE")
errChan = make(chan interface{}, 3)
shell.InitCallback(handleShell) // asks for all the shell errors to be sent here
sigChan = make(chan os.Signal, 3)
signal.Notify(sigChan, syscall.SIGUSR1)
}
// get's sent the return values and errors from git.wit.com/wit/shell/
func handleShell(err interface{}, ret int) {
log.Println("shell.Run() END Returned ", ret)
errChan <- err
}
func handleErrors() {
for val := range errChan {
log.Println("handleErrors() val =", val)
log.Println("handleErrors() reflect.TypeOf(val) =", reflect.TypeOf(val))
log.Printf("handleErrors() val type T = %T\n", val)
}
}
// trap signals
/*
go func() {
s := make(chan os.Signal, 1)
signal.Notify(s, syscall.SIGQUIT)
<-s
panic("give me the stack")
}()
*/