blob: 7ff65146ff3b152770b639c9b48b981dc0cf4c5c [file] [log] [blame]
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -07001/*
2 * Copyright 2015 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.net.newresource.impl;
17
18import com.google.common.annotations.Beta;
19import com.google.common.collect.ImmutableList;
20import org.apache.felix.scr.annotations.Component;
21import org.apache.felix.scr.annotations.Reference;
22import org.apache.felix.scr.annotations.ReferenceCardinality;
23import org.apache.felix.scr.annotations.Service;
Sho SHIMIZU70ee1ee2015-08-06 11:11:52 -070024import org.onosproject.net.newresource.ResourceAdminService;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070025import org.onosproject.net.newresource.ResourceAllocation;
26import org.onosproject.net.newresource.ResourceConsumer;
27import org.onosproject.net.newresource.ResourceService;
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -070028import org.onosproject.net.newresource.ResourcePath;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070029import org.onosproject.net.newresource.ResourceStore;
30
31import java.util.ArrayList;
32import java.util.Arrays;
33import java.util.Collection;
34import java.util.List;
35import java.util.Optional;
Sho SHIMIZU70ee1ee2015-08-06 11:11:52 -070036import java.util.concurrent.ConcurrentHashMap;
37import java.util.concurrent.ConcurrentMap;
38import java.util.function.Predicate;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070039import java.util.stream.Collectors;
40
41import static com.google.common.base.Preconditions.checkNotNull;
42
43/**
44 * An implementation of ResourceService.
45 */
46@Component(immediate = true, enabled = false)
47@Service
48@Beta
Sho SHIMIZU70ee1ee2015-08-06 11:11:52 -070049public final class ResourceManager implements ResourceService, ResourceAdminService {
50
51 private final ConcurrentMap<Class<?>, Predicate<?>> boundaries = new ConcurrentHashMap<>();
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070052
53 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
54 protected ResourceStore store;
55
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070056 @Override
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -070057 public Optional<ResourceAllocation> allocate(ResourceConsumer consumer, ResourcePath resource) {
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070058 checkNotNull(consumer);
59 checkNotNull(resource);
60
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -070061 List<ResourceAllocation> allocations = allocate(consumer, ImmutableList.of(resource));
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070062 if (allocations.isEmpty()) {
63 return Optional.empty();
64 }
65
66 assert allocations.size() == 1;
67
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -070068 ResourceAllocation allocation = allocations.get(0);
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070069
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -070070 assert allocation.resource().equals(resource);
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070071
72 // cast is ensured by the assertions above
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -070073 return Optional.of(allocation);
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070074 }
75
76 @Override
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -070077 public List<ResourceAllocation> allocate(ResourceConsumer consumer,
78 List<ResourcePath> resources) {
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070079 checkNotNull(consumer);
80 checkNotNull(resources);
81
82 if (resources.stream().anyMatch(x -> !isValid(x))) {
83 return ImmutableList.of();
84 }
85
86 // TODO: implement support of resource hierarchy
87 // allocation for a particular resource implies allocations for all of the sub-resources need to be done
88
89 boolean success = store.allocate(resources, consumer);
90 if (!success) {
91 return ImmutableList.of();
92 }
93
94 return resources.stream()
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -070095 .map(x -> new ResourceAllocation(x, consumer))
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070096 .collect(Collectors.toList());
97 }
98
99 @Override
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700100 public List<ResourceAllocation> allocate(ResourceConsumer consumer, ResourcePath... resources) {
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700101 checkNotNull(consumer);
102 checkNotNull(resources);
103
104 return allocate(consumer, Arrays.asList(resources));
105 }
106
107 @Override
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700108 public boolean release(ResourceAllocation allocation) {
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700109 checkNotNull(allocation);
110
111 return release(ImmutableList.of(allocation));
112 }
113
114 @Override
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700115 public boolean release(List<ResourceAllocation> allocations) {
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700116 checkNotNull(allocations);
117
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700118 List<ResourcePath> resources = allocations.stream()
119 .map(ResourceAllocation::resource)
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700120 .collect(Collectors.toList());
121 List<ResourceConsumer> consumers = allocations.stream()
122 .map(ResourceAllocation::consumer)
123 .collect(Collectors.toList());
124
125 return store.release(resources, consumers);
126 }
127
128 @Override
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700129 public boolean release(ResourceAllocation... allocations) {
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700130 checkNotNull(allocations);
131
132 return release(ImmutableList.copyOf(allocations));
133 }
134
135 @Override
136 public boolean release(ResourceConsumer consumer) {
137 checkNotNull(consumer);
138
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700139 Collection<ResourceAllocation> allocations = getResourceAllocations(consumer);
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700140 return release(ImmutableList.copyOf(allocations));
141 }
142
143 @Override
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700144 public <T> Collection<ResourceAllocation> getResourceAllocations(ResourcePath parent, Class<T> cls) {
145 checkNotNull(parent);
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700146 checkNotNull(cls);
147
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700148 Collection<ResourcePath> resources = store.getAllocatedResources(parent, cls);
149 List<ResourceAllocation> allocations = new ArrayList<>(resources.size());
150 for (ResourcePath resource: resources) {
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700151 // We access store twice in this method, then the store may be updated by others
152 Optional<ResourceConsumer> consumer = store.getConsumer(resource);
153 if (consumer.isPresent()) {
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700154 allocations.add(new ResourceAllocation(resource, consumer.get()));
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700155 }
156 }
157
158 return allocations;
159 }
160
161 @Override
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700162 public Collection<ResourceAllocation> getResourceAllocations(ResourceConsumer consumer) {
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700163 checkNotNull(consumer);
164
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700165 Collection<ResourcePath> resources = store.getResources(consumer);
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700166 return resources.stream()
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700167 .map(x -> new ResourceAllocation(x, consumer))
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700168 .collect(Collectors.toList());
169 }
170
171 @Override
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700172 public boolean isAvailable(ResourcePath resource) {
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700173 checkNotNull(resource);
174
175 Optional<ResourceConsumer> consumer = store.getConsumer(resource);
176 return !consumer.isPresent();
177 }
178
Sho SHIMIZU70ee1ee2015-08-06 11:11:52 -0700179 @Override
180 public <T> void defineResourceBoundary(Class<T> cls, Predicate<T> predicate) {
181 boundaries.put(cls, predicate);
182 }
183
184 /**
185 * Returns the predicate associated with the specified resource.
186 *
187 * @param resource resource whose associated predicate is to be returned
188 * @param <T> type of the resource
189 * @return predicate associated with the resource
190 * Null if the resource doesn't have an associated predicate.
191 */
192 @SuppressWarnings("unchecked")
193 private <T> Predicate<T> lookupPredicate(T resource) {
194 return (Predicate<T>) boundaries.get(resource.getClass());
195 }
196
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700197 /**
198 * Returns if the specified resource is in the resource range.
199 * E.g. VLAN ID against a link must be within 12 bit address space.
200 *
201 * @param resource resource to be checked if it is within the resource range
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700202 * @return true if the resource within the range, false otherwise
203 */
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700204 boolean isValid(ResourcePath resource) {
205 List<Object> flatten = resource.components();
206 Object bottom = flatten.get(flatten.size() - 1);
207 Predicate<Object> predicate = lookupPredicate(bottom);
Sho SHIMIZU70ee1ee2015-08-06 11:11:52 -0700208 if (predicate == null) {
209 return true;
210 }
211
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700212 return predicate.test(bottom);
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700213 }
214}