blob: b763166284448d7f55edfa441692a0693d46e039 [file] [log] [blame]
Sho SHIMIZU22fb2832016-05-06 11:44:03 -07001/*
2 * Copyright 2016-present Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.store.resource.impl;
17
18import com.google.common.collect.ImmutableList;
19import com.google.common.collect.ImmutableSet;
20import com.google.common.collect.Maps;
21import org.onlab.util.GuavaCollectors;
22import org.onlab.util.Tools;
23import org.onosproject.net.resource.ContinuousResource;
24import org.onosproject.net.resource.ContinuousResourceId;
25import org.onosproject.net.resource.DiscreteResourceId;
26import org.onosproject.net.resource.Resource;
27import org.onosproject.net.resource.ResourceAllocation;
28import org.onosproject.net.resource.ResourceConsumer;
29import org.onosproject.store.service.ConsistentMap;
30import org.onosproject.store.service.ConsistentMapException;
31import org.onosproject.store.service.StorageService;
32import org.onosproject.store.service.TransactionContext;
33import org.onosproject.store.service.Versioned;
34
35import java.util.LinkedHashSet;
36import java.util.List;
37import java.util.Set;
38import java.util.stream.Stream;
39
40import static org.onosproject.store.resource.impl.ConsistentResourceStore.ContinuousResourceAllocation;
41import static org.onosproject.store.resource.impl.ConsistentResourceStore.MAX_RETRIES;
42import static org.onosproject.store.resource.impl.ConsistentResourceStore.RETRY_DELAY;
43import static org.onosproject.store.resource.impl.ConsistentResourceStore.SERIALIZER;
44import static org.onosproject.store.resource.impl.ResourceStoreUtil.hasEnoughResource;
45
46class ConsistentContinuousResourceStore {
47 private ConsistentMap<ContinuousResourceId, ContinuousResourceAllocation> consumers;
48 private ConsistentMap<DiscreteResourceId, Set<ContinuousResource>> childMap;
49
50 ConsistentContinuousResourceStore(StorageService service) {
51 this.consumers = service.<ContinuousResourceId, ContinuousResourceAllocation>consistentMapBuilder()
52 .withName(MapNames.CONTINUOUS_CONSUMER_MAP)
53 .withSerializer(SERIALIZER)
54 .build();
55 this.childMap = service.<DiscreteResourceId, Set<ContinuousResource>>consistentMapBuilder()
56 .withName(MapNames.CONTINUOUS_CHILD_MAP)
57 .withSerializer(SERIALIZER)
58 .build();
59
60 Tools.retryable(() -> childMap.put(Resource.ROOT.id(), new LinkedHashSet<>()),
61 ConsistentMapException.class, MAX_RETRIES, RETRY_DELAY);
62 }
63
64 TransactionalContinuousResourceStore transactional(TransactionContext tx) {
65 return new TransactionalContinuousResourceStore(tx);
66 }
67
68 // computational complexity: O(n) where n is the number of the existing allocations for the resource
69 List<ResourceAllocation> getResourceAllocations(ContinuousResourceId resource) {
70 Versioned<ContinuousResourceAllocation> allocations = consumers.get(resource);
71 if (allocations == null) {
72 return ImmutableList.of();
73 }
74
75 return allocations.value().allocations().stream()
76 .filter(x -> x.resource().id().equals(resource))
77 .collect(GuavaCollectors.toImmutableList());
78 }
79
80 Set<ContinuousResource> getChildResources(DiscreteResourceId parent) {
81 Versioned<Set<ContinuousResource>> children = childMap.get(parent);
82
83 if (children == null) {
84 return ImmutableSet.of();
85 }
86
87 return children.value();
88 }
89
90 public boolean isAvailable(ContinuousResource resource) {
91 // check if it's registered or not.
92 Versioned<Set<ContinuousResource>> children = childMap.get(resource.parent().get().id());
93 if (children == null) {
94 return false;
95 }
96
97 ContinuousResource registered = children.value().stream()
98 .filter(c -> c.id().equals(resource.id()))
99 .findFirst()
100 .get();
101 if (registered.value() < resource.value()) {
102 // Capacity < requested, can never satisfy
103 return false;
104 }
105
106 // check if there's enough left
107 Versioned<ContinuousResourceAllocation> allocation = consumers.get(resource.id());
108 if (allocation == null) {
109 // no allocation (=no consumer) full registered resources available
110 return true;
111 }
112
113 return hasEnoughResource(allocation.value().original(), resource, allocation.value());
114 }
115
116 <T> Stream<ContinuousResource> getAllocatedResources(DiscreteResourceId parent, Class<T> cls) {
117 Set<ContinuousResource> children = getChildResources(parent);
118 if (children.isEmpty()) {
119 return Stream.of();
120 }
121
122 return children.stream()
123 .filter(x -> x.id().equals(parent.child(cls)))
124 // we don't use cascading simple predicates like follows to reduce accesses to consistent map
125 // .filter(x -> continuousConsumers.containsKey(x.id()))
126 // .filter(x -> continuousConsumers.get(x.id()) != null)
127 // .filter(x -> !continuousConsumers.get(x.id()).value().allocations().isEmpty());
128 .filter(resource -> {
129 Versioned<ContinuousResourceAllocation> allocation = consumers.get(resource.id());
130 if (allocation == null) {
131 return false;
132 }
133 return !allocation.value().allocations().isEmpty();
134 });
135 }
136
137 Stream<ContinuousResource> getResources(ResourceConsumer consumer) {
138 return consumers.values().stream()
139 .flatMap(x -> x.value().allocations().stream()
140 .map(y -> Maps.immutableEntry(x.value().original(), y)))
141 .filter(x -> x.getValue().consumer().equals(consumer))
142 .map(x -> x.getKey());
143 }
144}