// acquireOrRenewLease either races to acquire a new master lease, or update the existing master's lease // returns true if we have the lease, and an error if one occurs. // TODO: use the master election utility once it is merged in. func (c *Config) acquireOrRenewLease(etcdClient *etcd.Client) (bool, error) { result, err := etcdClient.Get(c.key, false, false) if err != nil { if tools.IsEtcdNotFound(err) { // there is no current master, try to become master, create will fail if the key already exists _, err := etcdClient.Create(c.key, c.whoami, c.ttl) if err != nil { return false, err } c.lastLease = time.Now() return true, nil } return false, err } if result.Node.Value == c.whoami { glog.Infof("key already exists, we are the master (%s)", result.Node.Value) // we extend our lease @ 1/2 of the existing TTL, this ensures the master doesn't flap around if result.Node.Expiration.Sub(time.Now()) < time.Duration(c.ttl/2)*time.Second { _, err := etcdClient.CompareAndSwap(c.key, c.whoami, c.ttl, c.whoami, result.Node.ModifiedIndex) if err != nil { return false, err } } c.lastLease = time.Now() return true, nil } glog.Infof("key already exists, the master is %s, sleeping.", result.Node.Value) return false, nil }
// setCommandFunc executes the "set" command. func setCommandFunc(cmd *cobra.Command, args []string, client *etcd.Client) (*etcd.Response, error) { if len(args) == 0 { return nil, errors.New("Key required") } key := args[0] value, err := argOrStdin(args, os.Stdin, 1) if err != nil { return nil, errors.New("Value required") } ttl := ttlFlag prevValue := swapWithValueFlag prevIndex := swapWithIndexFlag if prevValue == "" && prevIndex == 0 { return client.Set(key, value, uint64(ttl)) } else { return client.CompareAndSwap(key, value, uint64(ttl), prevValue, uint64(prevIndex)) } }
func CASEpoch(client *etcd.Client, appname string, prevEpoch, epoch uint64) error { prevEpochStr := strconv.FormatUint(prevEpoch, 10) epochStr := strconv.FormatUint(epoch, 10) _, err := client.CompareAndSwap(EpochPath(appname), epochStr, 0, prevEpochStr, 0) return err }