// getStoreList returns a store list matching the required attributes. // Results are cached for performance. // // If it cannot retrieve a StoreDescriptor from the Store's gossip, it // garbage collects the failed key. // // TODO(embark, spencer): consider using a reverse index map from // Attr->stores, for efficiency. Ensure that entries in this map still // have an opportunity to be garbage collected. func (a *allocator) getStoreList(required proto.Attributes) *storeList { if a.storeLists == nil { a.storeLists = map[string]*storeList{} } key := required.SortedString() if sl, ok := a.storeLists[key]; ok { return sl } sl := &storeList{} a.storeLists[key] = sl updateStoreList := func(key string) { storeDesc, err := storeDescFromGossip(key, a.gossip) if err != nil { // We can no longer retrieve this key from the gossip store, // perhaps it expired. delete(a.capacityKeys, key) } else if required.IsSubset(*storeDesc.CombinedAttrs()) { sl.Add(storeDesc) } } if a.deterministic { var keys []string for key := range a.capacityKeys { keys = append(keys, key) } sort.Strings(keys) for _, key := range keys { updateStoreList(key) } return sl } for key := range a.capacityKeys { updateStoreList(key) } return sl }