Created
May 23, 2012 13:00
-
-
Save ghthor/2775131 to your computer and use it in GitHub Desktop.
Go Routine bug
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
throw: all goroutines are asleep - deadlock! | |
goroutine 1 [chan receive]: | |
main.main() | |
/home/ghthor/proj/go/ddnsd/main.go:121 +0x5e | |
goroutine 2 [syscall]: | |
created by runtime.main | |
/build/src/go/src/pkg/runtime/proc.c:221 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// This app will monitor a file that will be updated with an ip address | |
// 1. Monitor file for ip changes | |
// 2. Ip changes update rackspace dns record | |
package main | |
import ( | |
"code.google.com/p/go/src/pkg/exp/inotify" | |
"flag" | |
"io/ioutil" | |
"log" | |
"path" | |
"strings" | |
) | |
// Hostnames filesystem database that is updated by the clients | |
// databaseDir/[hostname] | |
// File contents will be the ip addr | |
var databaseDir string | |
func init() { | |
// CLI Flags | |
flag.StringVar(&databaseDir, "database", "hostnames", "Path to the directory of the Hostnames database that will be monitored by ddnsd") | |
flag.Parse() | |
} | |
func readFromDatabase(databaseHostname string) (ip string) { | |
ipRaw, err := ioutil.ReadFile(databaseHostname) | |
if err != nil { | |
log.Fatalf("Error reading from database: %s", err) | |
} | |
ip = strings.TrimRight(string(ipRaw), "\n") | |
return | |
} | |
type Record struct { | |
Hostname, IP string | |
} | |
func WatchForUpdates(filesystemDB string) <-chan Record { | |
// The in memory database of | |
// [hostname] ==> ip | |
hostnamesDB := make(map[string]string) | |
hostnames, err := ioutil.ReadDir(filesystemDB) | |
if err != nil { | |
log.Fatalf("Error opening database: %s", err) | |
} | |
// Generate the in memeory database of [hostname:ip] | |
for _, info := range hostnames { | |
hostnamesDB[info.Name()] = readFromDatabase(filesystemDB + "/" + info.Name()) | |
} | |
log.Printf("Loaded Database: %s", hostnamesDB) | |
watcher, err := inotify.NewWatcher() | |
if err != nil { | |
log.Fatal(err) | |
} | |
defer watcher.Close() | |
err = watcher.Watch(filesystemDB) | |
if err != nil { | |
log.Fatalf("Watch failed: %s", err) | |
} | |
log.Printf("Monitoring database: %s", filesystemDB) | |
// Receive errors on the error channel on a separate goroutine | |
go func() { | |
for err := range watcher.Error { | |
log.Fatalf("error received: %s", err) | |
} | |
}() | |
// We want to mark when a file is modified so we can check it on the next IN_CLOSE event | |
modified := make(map[string]bool) | |
for hostname, _ := range hostnamesDB { | |
modified[hostname] = false | |
} | |
updates := make(chan Record, 100) | |
// Receive inotify events | |
eventstream := watcher.Event | |
go func(updates chan<- Record) { | |
for event := range eventstream { | |
hostname := path.Base(event.Name) | |
if (event.Mask&inotify.IN_CLOSE != 0) && (modified[hostname] == true) { | |
log.Printf("Close Event: \t%s", event) | |
// Unset the modified flag | |
modified[hostname] = false | |
// Read in the IP | |
ip := readFromDatabase(event.Name) | |
// Check if it is changed from what it was | |
if ip != hostnamesDB[hostname] { | |
hostnamesDB[hostname] = ip | |
// TODO Update dns record with rackspace API | |
updates<- Record{hostname, ip} | |
} | |
} else if event.Mask&inotify.IN_MODIFY != 0 { | |
log.Printf("Modify Event: \t%s", event) | |
// Set the modified flag | |
modified[hostname] = true | |
} | |
} | |
}(updates) | |
return updates | |
} | |
func main() { | |
updates := WatchForUpdates(databaseDir) | |
for update := range updates { | |
log.Printf("Database Updated: \t%s:%s", update.Hostname, update.IP) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment