Open Kilda Java Documentation
ResourceCache.java
Go to the documentation of this file.
1 /* Copyright 2017 Telstra Open Source
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 package org.openkilda.pce.cache;
17 
22 
23 import com.google.common.base.MoreObjects;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
26 
27 import java.util.Collections;
28 import java.util.Map;
29 import java.util.Map.Entry;
30 import java.util.Set;
31 import java.util.concurrent.ConcurrentHashMap;
32 import java.util.stream.Collectors;
33 
37 public class ResourceCache extends Cache {
41  public static final long FLOW_COOKIE_VALUE_MASK = 0x00000000FFFFFFFFL;
42 
46  public static final long FORWARD_FLOW_COOKIE_MASK = 0x4000000000000000L;
47 
51  public static final long REVERSE_FLOW_COOKIE_MASK = 0x2000000000000000L;
52 
56  static final int MIN_VLAN_ID = 2;
57 
61  static final int MAX_VLAN_ID = 4094;
62 
66  static final int MIN_METER_ID = 11;
67 
73  static final int MAX_METER_ID = 2500;
74 
78  static final int MAX_COOKIE = 128 * 1024;
79 
83  static final int MIN_COOKIE = 1;
84 
88  private static final Logger logger = LoggerFactory.getLogger(ResourceCache.class);
89 
93  private final Map<SwitchId, ResourcePool> meterPool = new ConcurrentHashMap<>();
94 
98  private final ResourcePool cookiePool = new ResourcePool(MIN_COOKIE, MAX_COOKIE);
99 
103  private final ResourcePool vlanPool = new ResourcePool(MIN_VLAN_ID, MAX_VLAN_ID);
104 
108  public ResourceCache() {
109  }
110 
114  public void clear() {
115  cookiePool.dumpPool().forEach(cookiePool::deallocate);
116  vlanPool.dumpPool().forEach(vlanPool::deallocate);
117  meterPool.clear();
118  }
119 
125  public Integer allocateCookie() {
126  return cookiePool.allocate();
127  }
128 
135  public Integer allocateCookie(Integer cookie) {
136  if (cookie == 0) {
137  return cookiePool.allocate();
138  } else {
139  cookiePool.allocate(cookie);
140  return cookie;
141  }
142  }
143 
150  public Integer deallocateCookie(Integer cookie) {
151  return cookiePool.deallocate(cookie);
152  }
153 
159  public Integer allocateVlanId() {
160  return vlanPool.allocate();
161  }
162 
169  public Integer allocateVlanId(Integer vlanId) {
170  if (vlanId == 0) {
171  return vlanPool.allocate();
172  } else {
173  vlanPool.allocate(vlanId);
174  return vlanId;
175  }
176  }
177 
184  public Integer deallocateVlanId(Integer vlanId) {
185  return vlanPool.deallocate(vlanId);
186  }
187 
194  public synchronized Integer allocateMeterId(SwitchId switchId) {
195  return meterPool.computeIfAbsent(switchId, k -> new ResourcePool(MIN_METER_ID, MAX_METER_ID)).allocate();
196  }
197 
205  public synchronized Integer allocateMeterId(SwitchId switchId, Integer meterId) {
206  if (meterId == 0) {
207  return meterPool.computeIfAbsent(switchId, k -> new ResourcePool(MIN_METER_ID, MAX_METER_ID))
208  .allocate();
209  } else {
210  meterPool.computeIfAbsent(switchId, k -> new ResourcePool(MIN_METER_ID, MAX_METER_ID))
211  .allocate(meterId);
212  return meterId;
213  }
214  }
215 
223  public synchronized Integer deallocateMeterId(SwitchId switchId, Integer meterId) {
224  ResourcePool switchMeterPool = meterPool.get(switchId);
225  return switchMeterPool != null ? switchMeterPool.deallocate(meterId) : null;
226  }
227 
234  public synchronized Set<Integer> deallocateMeterId(SwitchId switchId) {
235  ResourcePool switchMeterPool = meterPool.remove(switchId);
236  return switchMeterPool != null ? switchMeterPool.dumpPool() : null;
237  }
238 
244  public Set<Integer> getAllCookies() {
245  return cookiePool.dumpPool();
246  }
247 
253  public Set<Integer> getAllVlanIds() {
254  return vlanPool.dumpPool();
255  }
256 
263  public Set<Integer> getAllMeterIds(SwitchId switchId) {
264  return meterPool.containsKey(switchId) ? meterPool.get(switchId).dumpPool() : Collections.emptySet();
265  }
266 
272  public Map<SwitchId, Set<Integer>> getAllMeterIds() {
273  return meterPool.entrySet().stream()
274  .collect(Collectors.toMap(
275  Entry::getKey,
276  e -> e.getValue().dumpPool())
277  );
278  }
279 
280 
287 
288  if (flow.left != null) {
289  allocateCookie((int) (FLOW_COOKIE_VALUE_MASK & flow.left.getCookie()));
290  if (!flow.left.isOneSwitchFlow()) {
291  // Don't allocate if one switch .. it is zero
292  // .. and allocateVlanId *will* allocate if it is zero, which consumes a very
293  // .. limited resource unnecessarily
294  allocateVlanId(flow.left.getTransitVlan());
295  }
296  allocateMeterId(flow.left.getSourceSwitch(), flow.left.getMeterId());
297  }
298 
299  if (flow.right != null) {
300  if (!flow.right.isOneSwitchFlow()) {
301  // Don't allocate if one switch .. it is zero
302  // .. and allocateVlanId *will* allocate if it is zero, which consumes a very
303  // .. limited resource unnecessarily
304  allocateVlanId(flow.right.getTransitVlan());
305  }
306  allocateMeterId(flow.right.getSourceSwitch(), flow.right.getMeterId());
307  }
308  }
309 
316  deallocateCookie((int) (FLOW_COOKIE_VALUE_MASK & flow.left.getCookie()));
317 
318  deallocateVlanId(flow.left.getTransitVlan());
319  deallocateMeterId(flow.left.getSourceSwitch(), flow.left.getMeterId());
320 
321  if (flow.right != null) {
322  deallocateVlanId(flow.right.getTransitVlan());
323  deallocateMeterId(flow.right.getSourceSwitch(), flow.right.getMeterId());
324  }
325  }
326 
330  @Override
331  public String toString() {
332  return MoreObjects.toStringHelper(this)
333  .add("meters", meterPool)
334  .add("cookies", cookiePool)
335  .add("vlans", vlanPool)
336  .toString();
337  }
338 }
synchronized Set< Integer > deallocateMeterId(SwitchId switchId)
synchronized Integer allocateMeterId(SwitchId switchId, Integer meterId)
void deallocateFlow(ImmutablePair< Flow, Flow > flow)
Map< SwitchId, Set< Integer > > getAllMeterIds()
Integer allocateCookie(Integer cookie)
Integer deallocateCookie(Integer cookie)
void allocateFlow(ImmutablePair< Flow, Flow > flow)
Integer deallocate(final Integer resourceId)
synchronized Integer allocateMeterId(SwitchId switchId)
Set< Integer > getAllMeterIds(SwitchId switchId)
synchronized Integer deallocateMeterId(SwitchId switchId, Integer meterId)
Integer allocateVlanId(Integer vlanId)
Integer deallocateVlanId(Integer vlanId)