diff options
author | Ondřej Surý <ondrej@sury.org> | 2011-09-13 13:13:40 +0200 |
---|---|---|
committer | Ondřej Surý <ondrej@sury.org> | 2011-09-13 13:13:40 +0200 |
commit | 5ff4c17907d5b19510a62e08fd8d3b11e62b431d (patch) | |
tree | c0650497e988f47be9c6f2324fa692a52dea82e1 /doc/codewalk/urlpoll.go | |
parent | 80f18fc933cf3f3e829c5455a1023d69f7b86e52 (diff) | |
download | golang-upstream/60.tar.gz |
Imported Upstream version 60upstream/60
Diffstat (limited to 'doc/codewalk/urlpoll.go')
-rw-r--r-- | doc/codewalk/urlpoll.go | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/doc/codewalk/urlpoll.go b/doc/codewalk/urlpoll.go new file mode 100644 index 000000000..b51be9502 --- /dev/null +++ b/doc/codewalk/urlpoll.go @@ -0,0 +1,117 @@ +// Copyright 2010 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 main + +import ( + "http" + "log" + "time" +) + +const ( + numPollers = 2 // number of Poller goroutines to launch + second = 1e9 // one second is 1e9 nanoseconds + pollInterval = 60 * second // how often to poll each URL + statusInterval = 10 * second // how often to log status to stdout + errTimeout = 10 * second // back-off timeout on error +) + +var urls = []string{ + "http://www.google.com/", + "http://golang.org/", + "http://blog.golang.org/", +} + +// State represents the last-known state of a URL. +type State struct { + url string + status string +} + +// StateMonitor maintains a map that stores the state of the URLs being +// polled, and prints the current state every updateInterval nanoseconds. +// It returns a chan State to which resource state should be sent. +func StateMonitor(updateInterval int64) chan<- State { + updates := make(chan State) + urlStatus := make(map[string]string) + ticker := time.NewTicker(updateInterval) + go func() { + for { + select { + case <-ticker.C: + logState(urlStatus) + case s := <-updates: + urlStatus[s.url] = s.status + } + } + }() + return updates +} + +// logState prints a state map. +func logState(s map[string]string) { + log.Println("Current state:") + for k, v := range s { + log.Printf(" %s %s", k, v) + } +} + +// Resource represents an HTTP URL to be polled by this program. +type Resource struct { + url string + errCount int64 +} + +// Poll executes an HTTP HEAD request for url +// and returns the HTTP status string or an error string. +func (r *Resource) Poll() string { + resp, err := http.Head(r.url) + if err != nil { + log.Println("Error", r.url, err) + r.errCount++ + return err.String() + } + r.errCount = 0 + return resp.Status +} + +// Sleep sleeps for an appropriate interval (dependant on error state) +// before sending the Resource to done. +func (r *Resource) Sleep(done chan *Resource) { + time.Sleep(pollInterval + errTimeout*r.errCount) + done <- r +} + +func Poller(in <-chan *Resource, out chan<- *Resource, status chan<- State) { + for r := range in { + s := r.Poll() + status <- State{r.url, s} + out <- r + } +} + +func main() { + // create our input and output channels + pending, complete := make(chan *Resource), make(chan *Resource) + + // launch the StateMonitor + status := StateMonitor(statusInterval) + + // launch some Poller goroutines + for i := 0; i < numPollers; i++ { + go Poller(pending, complete, status) + } + + // send some Resources to the pending queue + go func() { + for _, url := range urls { + pending <- &Resource{url: url} + } + }() + + for r := range complete { + go r.Sleep(pending) + } +} |