func (c *ConsulClient) GASNewSecLabelID(basePath string, baseID uint32, secCtxLabels *labels.SecCtxLabel) error { setID2Label := func(lockPair *consulAPI.KVPair) error { defer c.KV().Release(lockPair, nil) secCtxLabels.ID = baseID keyPath := path.Join(basePath, strconv.FormatUint(uint64(secCtxLabels.ID), 10)) if err := c.SetValue(keyPath, secCtxLabels); err != nil { return err } return c.setMaxLabelID(baseID + 1) } session, _, err := c.Session().CreateNoChecks(nil, nil) if err != nil { return err } beginning := baseID for { log.Debugf("Trying to acquire a new free ID %d", baseID) keyPath := path.Join(basePath, strconv.FormatUint(uint64(baseID), 10)) lockPair := &consulAPI.KVPair{Key: GetLockPath(keyPath), Session: session} acq, _, err := c.KV().Acquire(lockPair, nil) if err != nil { return err } if acq { lblKey, _, err := c.KV().Get(keyPath, nil) if err != nil { c.KV().Release(lockPair, nil) return err } if lblKey == nil { return setID2Label(lockPair) } var consulLabels labels.SecCtxLabel if err := json.Unmarshal(lblKey.Value, &consulLabels); err != nil { c.KV().Release(lockPair, nil) return err } if consulLabels.RefCount() == 0 { log.Infof("Recycling ID %d", baseID) return setID2Label(lockPair) } c.KV().Release(lockPair, nil) } baseID++ if baseID > common.MaxSetOfLabels { baseID = common.FirstFreeLabelID } if beginning == baseID { return fmt.Errorf("reached maximum set of labels available.") } } }
// GASNewSecLabelID gets the next available LabelID and sets it in secCtxLabels. After // assigning the LabelID to secCtxLabels it sets the LabelID + 1 in // common.LastFreeLabelIDKeyPath path. func (e *EtcdClient) GASNewSecLabelID(basePath string, baseID uint32, secCtxLabels *labels.SecCtxLabel) error { setID2Label := func(id uint32) error { secCtxLabels.ID = id keyPath := path.Join(basePath, strconv.FormatUint(uint64(secCtxLabels.ID), 10)) if err := e.SetValue(keyPath, secCtxLabels); err != nil { return err } return e.setMaxLabelID(id + 1) } acquireFreeID := func(firstID uint32, incID *uint32) (bool, error) { log.Debugf("Trying to acquire a new free ID %d", *incID) keyPath := path.Join(basePath, strconv.FormatUint(uint64(*incID), 10)) locker, err := e.LockPath(GetLockPath(keyPath)) if err != nil { return false, err } defer locker.Unlock() value, err := e.GetValue(keyPath) if err != nil { return false, err } if value == nil { return false, setID2Label(*incID) } var consulLabels labels.SecCtxLabel if err := json.Unmarshal(value, &consulLabels); err != nil { return false, err } if consulLabels.RefCount() == 0 { log.Infof("Recycling ID %d", *incID) return false, setID2Label(*incID) } *incID++ if *incID > common.MaxSetOfLabels { *incID = common.FirstFreeLabelID } if firstID == *incID { return false, fmt.Errorf("reached maximum set of labels available.") } return true, nil } beginning := baseID for { retry, err := acquireFreeID(beginning, &baseID) if err != nil { return err } else if !retry { return nil } } }