blob: d5f4567055a22932b5e4cb917eaf697f6da5945f [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
Sho SHIMIZU22fb2832016-05-06 11:44:03 -070040import static org.onosproject.store.resource.impl.ConsistentResourceStore.MAX_RETRIES;
41import static org.onosproject.store.resource.impl.ConsistentResourceStore.RETRY_DELAY;
42import static org.onosproject.store.resource.impl.ConsistentResourceStore.SERIALIZER;
43import static org.onosproject.store.resource.impl.ResourceStoreUtil.hasEnoughResource;
44
45class ConsistentContinuousResourceStore {
46 private ConsistentMap<ContinuousResourceId, ContinuousResourceAllocation> consumers;
47 private ConsistentMap<DiscreteResourceId, Set<ContinuousResource>> childMap;
48
49 ConsistentContinuousResourceStore(StorageService service) {
50 this.consumers = service.<ContinuousResourceId, ContinuousResourceAllocation>consistentMapBuilder()
51 .withName(MapNames.CONTINUOUS_CONSUMER_MAP)
52 .withSerializer(SERIALIZER)
53 .build();
54 this.childMap = service.<DiscreteResourceId, Set<ContinuousResource>>consistentMapBuilder()
55 .withName(MapNames.CONTINUOUS_CHILD_MAP)
56 .withSerializer(SERIALIZER)
57 .build();
58
59 Tools.retryable(() -> childMap.put(Resource.ROOT.id(), new LinkedHashSet<>()),
60 ConsistentMapException.class, MAX_RETRIES, RETRY_DELAY);
61 }
62
63 TransactionalContinuousResourceStore transactional(TransactionContext tx) {
64 return new TransactionalContinuousResourceStore(tx);
65 }
66
67 // computational complexity: O(n) where n is the number of the existing allocations for the resource
68 List<ResourceAllocation> getResourceAllocations(ContinuousResourceId resource) {
69 Versioned<ContinuousResourceAllocation> allocations = consumers.get(resource);
70 if (allocations == null) {
71 return ImmutableList.of();
72 }
73
74 return allocations.value().allocations().stream()
75 .filter(x -> x.resource().id().equals(resource))
76 .collect(GuavaCollectors.toImmutableList());
77 }
78
79 Set<ContinuousResource> getChildResources(DiscreteResourceId parent) {
80 Versioned<Set<ContinuousResource>> children = childMap.get(parent);
81
82 if (children == null) {
83 return ImmutableSet.of();
84 }
85
86 return children.value();
87 }
88
89 public boolean isAvailable(ContinuousResource resource) {
90 // check if it's registered or not.
91 Versioned<Set<ContinuousResource>> children = childMap.get(resource.parent().get().id());
92 if (children == null) {
93 return false;
94 }
95
96 ContinuousResource registered = children.value().stream()
97 .filter(c -> c.id().equals(resource.id()))
98 .findFirst()
99 .get();
100 if (registered.value() < resource.value()) {
101 // Capacity < requested, can never satisfy
102 return false;
103 }
104
105 // check if there's enough left
106 Versioned<ContinuousResourceAllocation> allocation = consumers.get(resource.id());
107 if (allocation == null) {
108 // no allocation (=no consumer) full registered resources available
109 return true;
110 }
111
112 return hasEnoughResource(allocation.value().original(), resource, allocation.value());
113 }
114
115 <T> Stream<ContinuousResource> getAllocatedResources(DiscreteResourceId parent, Class<T> cls) {
116 Set<ContinuousResource> children = getChildResources(parent);
117 if (children.isEmpty()) {
118 return Stream.of();
119 }
120
121 return children.stream()
122 .filter(x -> x.id().equals(parent.child(cls)))
123 // we don't use cascading simple predicates like follows to reduce accesses to consistent map
124 // .filter(x -> continuousConsumers.containsKey(x.id()))
125 // .filter(x -> continuousConsumers.get(x.id()) != null)
126 // .filter(x -> !continuousConsumers.get(x.id()).value().allocations().isEmpty());
127 .filter(resource -> {
128 Versioned<ContinuousResourceAllocation> allocation = consumers.get(resource.id());
129 if (allocation == null) {
130 return false;
131 }
132 return !allocation.value().allocations().isEmpty();
133 });
134 }
135
136 Stream<ContinuousResource> getResources(ResourceConsumer consumer) {
137 return consumers.values().stream()
138 .flatMap(x -> x.value().allocations().stream()
139 .map(y -> Maps.immutableEntry(x.value().original(), y)))
140 .filter(x -> x.getValue().consumer().equals(consumer))
141 .map(x -> x.getKey());
142 }
143}