// This will attempt to Acquire a lock for a given amount of time. // If the lock is acquired, goChan will be unblocked // If the lock is lost, stopChan will be unblocked // TODO: Handle non-expected errors func Acquire(cli *etcd.Client, lock string, timeout uint64) (goChan chan int, stopChan chan int) { me := uuid.NewV1().String() goChan = make(chan int) stopChan = make(chan int) go func() { log.Println("Hello, I am:", me) for { resp, acq, err := cli.TestAndSet(lock, "", me, timeout) if debug { log.Println("Lock Resp:", acq, resp, err) } if !acq { // We want to watch for a change in the lock, and we'll repeat var watcherCh = make(chan *store.Response) var endCh = make(chan bool) go cli.Watch(lock, 0, watcherCh, endCh) <-watcherCh // Now, we'll try to acquire the lock, again } else { // We got a lock, we want to keep it go func() { for { resp, acq, err := cli.TestAndSet(lock, me, me, timeout) // Keep the lock alive if debug { log.Println("Reset Resp:", acq, resp, err) } if !acq { if debug { log.Println("Demoted:", me) } stopChan <- 1 // Let's boot ourselves, we're no longer the leader } time.Sleep(time.Duration(timeout*500) * time.Millisecond) // We'll re-up after 50% fo the lock period } }() if debug { log.Println("King:", me) } goChan <- 1 } } }() return }
// A stupid spin lock func lock(c *etcd.Client) bool { for { _, success, _ := c.TestAndSet("lock", "unlock", "lock", 0) if success != true { fmt.Println("tried lock failed!") } else { return true } } }
func inspectAndSet(c chan string, etcdClient *etcd.Client, dockerClient *docker.Client, keyname *string, ttl *uint64) { for { id := <-c container, err := dockerClient.InspectContainer(id) if err != nil { log.Fatal(err) } else { var addr string //if the container config contains ports then set the IP as the host IP if len(container.Config.PortSpecs) > 0 { addr = localIp() } else { addr = container.NetworkSettings.IPAddress } etcdClient.TestAndSet(*keyname+"/"+container.Config.Hostname, addr, addr, *ttl) log.Print(container.Config.Hostname) } } }