blob: a11aabc4bdd622ee8c1a9b9bf57abb6fb5e2cbea [file] [log] [blame]
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -07003 *
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 */
Sho SHIMIZUe18cb122016-02-22 21:04:56 -080016package org.onosproject.store.resource.impl;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070017
18import com.google.common.annotations.Beta;
Sho SHIMIZU83258ae2016-01-29 17:39:07 -080019import com.google.common.collect.ImmutableSet;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070020import org.apache.felix.scr.annotations.Activate;
21import org.apache.felix.scr.annotations.Component;
22import org.apache.felix.scr.annotations.Reference;
23import org.apache.felix.scr.annotations.ReferenceCardinality;
24import org.apache.felix.scr.annotations.Service;
Sho SHIMIZUe18cb122016-02-22 21:04:56 -080025import org.onosproject.net.resource.ContinuousResource;
26import org.onosproject.net.resource.ContinuousResourceId;
27import org.onosproject.net.resource.DiscreteResource;
28import org.onosproject.net.resource.DiscreteResourceId;
Sho SHIMIZU22fb2832016-05-06 11:44:03 -070029import org.onosproject.net.resource.Resource;
Sho SHIMIZUe18cb122016-02-22 21:04:56 -080030import org.onosproject.net.resource.ResourceAllocation;
31import org.onosproject.net.resource.ResourceConsumer;
Naoki Shiotabd1974c2016-04-29 18:44:17 -070032import org.onosproject.net.resource.ResourceConsumerId;
Sho SHIMIZUe18cb122016-02-22 21:04:56 -080033import org.onosproject.net.resource.ResourceEvent;
34import org.onosproject.net.resource.ResourceId;
Sho SHIMIZUe18cb122016-02-22 21:04:56 -080035import org.onosproject.net.resource.ResourceStore;
36import org.onosproject.net.resource.ResourceStoreDelegate;
37import org.onosproject.net.resource.Resources;
Sho SHIMIZUfa62b472015-11-02 17:35:46 -080038import org.onosproject.store.AbstractStore;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070039import org.onosproject.store.serializers.KryoNamespaces;
Madan Jampani3780d4b2016-04-04 18:18:24 -070040import org.onosproject.store.service.CommitStatus;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070041import org.onosproject.store.service.Serializer;
42import org.onosproject.store.service.StorageService;
43import org.onosproject.store.service.TransactionContext;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070044import org.slf4j.Logger;
45import org.slf4j.LoggerFactory;
46
Sho SHIMIZUba41fc12015-08-12 15:43:22 -070047import java.util.Arrays;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070048import java.util.Collection;
Sho SHIMIZU69420fe2016-02-09 15:01:07 -080049import java.util.LinkedHashMap;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070050import java.util.List;
51import java.util.Map;
52import java.util.Optional;
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -080053import java.util.Set;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070054import java.util.stream.Collectors;
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -080055import java.util.stream.Stream;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070056
57import static com.google.common.base.Preconditions.checkArgument;
58import static com.google.common.base.Preconditions.checkNotNull;
Sho SHIMIZU22fb2832016-05-06 11:44:03 -070059import static org.onosproject.net.resource.ResourceEvent.Type.RESOURCE_ADDED;
60import static org.onosproject.net.resource.ResourceEvent.Type.RESOURCE_REMOVED;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070061
62/**
63 * Implementation of ResourceStore using TransactionalMap.
64 */
Sho SHIMIZU9a2b8292015-10-28 13:00:16 -070065@Component(immediate = true)
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070066@Service
67@Beta
Sho SHIMIZUfa62b472015-11-02 17:35:46 -080068public class ConsistentResourceStore extends AbstractStore<ResourceEvent, ResourceStoreDelegate>
69 implements ResourceStore {
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070070 private static final Logger log = LoggerFactory.getLogger(ConsistentResourceStore.class);
71
Sho SHIMIZU22fb2832016-05-06 11:44:03 -070072 static final Serializer SERIALIZER = Serializer.using(
HIGUCHI Yuta6f584222016-05-06 11:15:38 -070073 Arrays.asList(KryoNamespaces.API),
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -080074 ContinuousResourceAllocation.class);
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070075
Thomas Vachuska762a2d82016-01-04 10:25:20 -080076 // TODO: We should provide centralized values for this
Sho SHIMIZU22fb2832016-05-06 11:44:03 -070077 static final int MAX_RETRIES = 5;
78 static final int RETRY_DELAY = 1_000; // millis
Thomas Vachuska762a2d82016-01-04 10:25:20 -080079
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070080 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
81 protected StorageService service;
82
Sho SHIMIZU22fb2832016-05-06 11:44:03 -070083 private ConsistentDiscreteResourceStore discreteStore;
84 private ConsistentContinuousResourceStore continuousStore;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070085
86 @Activate
87 public void activate() {
Sho SHIMIZU22fb2832016-05-06 11:44:03 -070088 discreteStore = new ConsistentDiscreteResourceStore(service);
89 continuousStore = new ConsistentContinuousResourceStore(service);
Sho SHIMIZUe7db6142015-11-04 11:24:22 -080090
Madan Jampanic7f49f92015-12-10 11:35:06 -080091 log.info("Started");
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070092 }
93
Sho SHIMIZUdd3750c2016-02-01 11:37:04 -080094 // Computational complexity: O(1) if the resource is discrete type.
95 // O(n) if the resource is continuous type where n is the number of the existing allocations for the resource
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070096 @Override
Sho SHIMIZUdd3750c2016-02-01 11:37:04 -080097 public List<ResourceAllocation> getResourceAllocations(ResourceId id) {
98 checkNotNull(id);
99 checkArgument(id instanceof DiscreteResourceId || id instanceof ContinuousResourceId);
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700100
Sho SHIMIZUdd3750c2016-02-01 11:37:04 -0800101 if (id instanceof DiscreteResourceId) {
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700102 return discreteStore.getResourceAllocations((DiscreteResourceId) id);
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800103 } else {
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700104 return continuousStore.getResourceAllocations((ContinuousResourceId) id);
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800105 }
106 }
107
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700108 @Override
Jonathan Hart56151262016-02-11 09:48:50 -0800109 public boolean register(List<Resource> resources) {
Sho SHIMIZU83e17a02015-08-20 14:07:05 -0700110 checkNotNull(resources);
HIGUCHI Yuta6f828c32016-01-20 18:11:05 -0800111 if (log.isTraceEnabled()) {
112 resources.forEach(r -> log.trace("registering {}", r));
113 }
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700114
115 TransactionContext tx = service.transactionContextBuilder().build();
116 tx.begin();
117
Sho SHIMIZU69420fe2016-02-09 15:01:07 -0800118 // the order is preserved by LinkedHashMap
Sho SHIMIZUf33b8932016-01-25 18:43:32 -0800119 Map<DiscreteResource, List<Resource>> resourceMap = resources.stream()
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800120 .filter(x -> x.parent().isPresent())
Sho SHIMIZU69420fe2016-02-09 15:01:07 -0800121 .collect(Collectors.groupingBy(x -> x.parent().get(), LinkedHashMap::new, Collectors.toList()));
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700122
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700123 TransactionalDiscreteResourceStore discreteTxStore = discreteStore.transactional(tx);
124 TransactionalContinuousResourceStore continuousTxStore = continuousStore.transactional(tx);
125 for (Map.Entry<DiscreteResource, List<Resource>> entry : resourceMap.entrySet()) {
Sho SHIMIZU001e3f22016-05-06 14:46:15 -0700126 DiscreteResourceId parentId = entry.getKey().id();
Sho SHIMIZUd66148a2016-05-06 14:47:47 -0700127 if (!discreteTxStore.lookup(parentId).isPresent()) {
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800128 return abortTransaction(tx);
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700129 }
130
Sho SHIMIZUa2d99eb2016-05-06 14:52:55 -0700131 if (!register(discreteTxStore, continuousTxStore, parentId, entry.getValue())) {
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800132 return abortTransaction(tx);
133 }
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700134 }
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800135
Madan Jampani3780d4b2016-04-04 18:18:24 -0700136 return tx.commit().whenComplete((status, error) -> {
137 if (status == CommitStatus.SUCCESS) {
138 log.trace("Transaction commit succeeded on registration: resources={}", resources);
139 List<ResourceEvent> events = resources.stream()
140 .filter(x -> x.parent().isPresent())
141 .map(x -> new ResourceEvent(RESOURCE_ADDED, x))
142 .collect(Collectors.toList());
143 notifyDelegate(events);
144 } else {
145 log.warn("Transaction commit failed on registration", error);
146 }
147 }).join() == CommitStatus.SUCCESS;
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700148 }
149
150 @Override
Jonathan Hart56151262016-02-11 09:48:50 -0800151 public boolean unregister(List<ResourceId> ids) {
Sho SHIMIZU72f81b12016-02-09 09:26:17 -0800152 checkNotNull(ids);
Sho SHIMIZU2d8a13a2015-08-18 22:37:41 -0700153
154 TransactionContext tx = service.transactionContextBuilder().build();
155 tx.begin();
156
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700157 TransactionalDiscreteResourceStore discreteTxStore = discreteStore.transactional(tx);
158 TransactionalContinuousResourceStore continuousTxStore = continuousStore.transactional(tx);
Sho SHIMIZU7d54d9c2016-02-17 13:58:46 -0800159 // Look up resources by resource IDs
Sho SHIMIZU72f81b12016-02-09 09:26:17 -0800160 List<Resource> resources = ids.stream()
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800161 .filter(x -> x.parent().isPresent())
Sho SHIMIZU7d54d9c2016-02-17 13:58:46 -0800162 .map(x -> {
163 // avoid access to consistent map in the case of discrete resource
164 if (x instanceof DiscreteResourceId) {
165 return Optional.of(Resources.discrete((DiscreteResourceId) x).resource());
166 } else {
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700167 return continuousTxStore.lookup((ContinuousResourceId) x);
Sho SHIMIZU7d54d9c2016-02-17 13:58:46 -0800168 }
169 })
HIGUCHI Yuta315179a2016-02-18 14:01:22 -0800170 .filter(Optional::isPresent)
171 .map(Optional::get)
Sho SHIMIZU72f81b12016-02-09 09:26:17 -0800172 .collect(Collectors.toList());
Sho SHIMIZU69420fe2016-02-09 15:01:07 -0800173 // the order is preserved by LinkedHashMap
Sho SHIMIZU72f81b12016-02-09 09:26:17 -0800174 Map<DiscreteResourceId, List<Resource>> resourceMap = resources.stream()
Sho SHIMIZU69420fe2016-02-09 15:01:07 -0800175 .collect(Collectors.groupingBy(x -> x.parent().get().id(), LinkedHashMap::new, Collectors.toList()));
Sho SHIMIZU83e17a02015-08-20 14:07:05 -0700176
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700177 for (Map.Entry<DiscreteResourceId, List<Resource>> entry : resourceMap.entrySet()) {
Sho SHIMIZUa2d99eb2016-05-06 14:52:55 -0700178 if (!unregister(discreteTxStore, continuousTxStore, entry.getKey(), entry.getValue())) {
HIGUCHI Yuta6acdfd02016-02-18 10:39:43 -0800179 log.warn("Failed to unregister {}: Failed to remove {} values.",
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700180 entry.getKey(), entry.getValue().size());
HIGUCHI Yuta6acdfd02016-02-18 10:39:43 -0800181 log.debug("Failed to unregister {}: Failed to remove values: {}",
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700182 entry.getKey(), entry.getValue());
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800183 return abortTransaction(tx);
184 }
Sho SHIMIZU2d8a13a2015-08-18 22:37:41 -0700185 }
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800186
Madan Jampani3780d4b2016-04-04 18:18:24 -0700187 return tx.commit().whenComplete((status, error) -> {
188 if (status == CommitStatus.SUCCESS) {
189 List<ResourceEvent> events = resources.stream()
190 .filter(x -> x.parent().isPresent())
191 .map(x -> new ResourceEvent(RESOURCE_REMOVED, x))
192 .collect(Collectors.toList());
193 notifyDelegate(events);
194 } else {
195 log.warn("Failed to unregister {}: Commit failed.", ids, error);
196 }
197 }).join() == CommitStatus.SUCCESS;
Sho SHIMIZU2d8a13a2015-08-18 22:37:41 -0700198 }
199
200 @Override
Jonathan Hart56151262016-02-11 09:48:50 -0800201 public boolean allocate(List<Resource> resources, ResourceConsumer consumer) {
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700202 checkNotNull(resources);
203 checkNotNull(consumer);
204
205 TransactionContext tx = service.transactionContextBuilder().build();
206 tx.begin();
207
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700208 TransactionalDiscreteResourceStore discreteTxStore = discreteStore.transactional(tx);
209 TransactionalContinuousResourceStore continuousTxStore = continuousStore.transactional(tx);
210 for (Resource resource : resources) {
Sho SHIMIZU171a9382016-02-15 13:56:34 -0800211 if (resource instanceof DiscreteResource) {
Naoki Shiotabd1974c2016-04-29 18:44:17 -0700212 if (!discreteTxStore.allocate(consumer.consumerId(), (DiscreteResource) resource)) {
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800213 return abortTransaction(tx);
214 }
Sho SHIMIZUf33b8932016-01-25 18:43:32 -0800215 } else if (resource instanceof ContinuousResource) {
Naoki Shiotabd1974c2016-04-29 18:44:17 -0700216 if (!continuousTxStore.allocate(consumer.consumerId(), (ContinuousResource) resource)) {
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800217 return abortTransaction(tx);
218 }
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800219 }
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700220 }
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800221
Madan Jampani3780d4b2016-04-04 18:18:24 -0700222 return tx.commit().join() == CommitStatus.SUCCESS;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700223 }
224
225 @Override
Sho SHIMIZUfc64ffe2016-02-10 20:11:09 -0800226 public boolean release(List<ResourceAllocation> allocations) {
227 checkNotNull(allocations);
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700228
229 TransactionContext tx = service.transactionContextBuilder().build();
230 tx.begin();
231
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700232 TransactionalDiscreteResourceStore discreteTxStore = discreteStore.transactional(tx);
233 TransactionalContinuousResourceStore continuousTxStore = continuousStore.transactional(tx);
Sho SHIMIZUfc64ffe2016-02-10 20:11:09 -0800234 for (ResourceAllocation allocation : allocations) {
235 Resource resource = allocation.resource();
Naoki Shiotabd1974c2016-04-29 18:44:17 -0700236 ResourceConsumerId consumerId = allocation.consumerId();
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700237
Sho SHIMIZUf33b8932016-01-25 18:43:32 -0800238 if (resource instanceof DiscreteResource) {
Naoki Shiotabd1974c2016-04-29 18:44:17 -0700239 if (!discreteTxStore.release((DiscreteResource) resource, consumerId)) {
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800240 return abortTransaction(tx);
241 }
Sho SHIMIZUf33b8932016-01-25 18:43:32 -0800242 } else if (resource instanceof ContinuousResource) {
Naoki Shiotabd1974c2016-04-29 18:44:17 -0700243 if (!continuousTxStore.release((ContinuousResource) resource, consumerId)) {
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800244 return abortTransaction(tx);
245 }
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700246 }
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700247 }
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800248
Madan Jampani3780d4b2016-04-04 18:18:24 -0700249 return tx.commit().join() == CommitStatus.SUCCESS;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700250 }
251
Sho SHIMIZUdd3750c2016-02-01 11:37:04 -0800252 // computational complexity: O(1) if the resource is discrete type.
253 // O(n) if the resource is continuous type where n is the number of the children of
254 // the specified resource's parent
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700255 @Override
Sho SHIMIZU8fa670a2016-01-14 11:17:18 -0800256 public boolean isAvailable(Resource resource) {
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800257 checkNotNull(resource);
Sho SHIMIZUf33b8932016-01-25 18:43:32 -0800258 checkArgument(resource instanceof DiscreteResource || resource instanceof ContinuousResource);
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800259
Sho SHIMIZUf33b8932016-01-25 18:43:32 -0800260 if (resource instanceof DiscreteResource) {
HIGUCHI Yuta6f828c32016-01-20 18:11:05 -0800261 // check if already consumed
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700262 return discreteStore.isAvailable((DiscreteResource) resource);
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800263 } else {
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700264 return continuousStore.isAvailable((ContinuousResource) resource);
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800265 }
266 }
267
Sho SHIMIZUdd3750c2016-02-01 11:37:04 -0800268 // computational complexity: O(n + m) where n is the number of entries in discreteConsumers
269 // and m is the number of allocations for all continuous resources
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800270 @Override
Sho SHIMIZU8fa670a2016-01-14 11:17:18 -0800271 public Collection<Resource> getResources(ResourceConsumer consumer) {
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700272 checkNotNull(consumer);
Naoki Shiotabd1974c2016-04-29 18:44:17 -0700273 ResourceConsumerId consumerId = consumer.consumerId();
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700274
275 // NOTE: getting all entries may become performance bottleneck
276 // TODO: revisit for better backend data structure
Naoki Shiotabd1974c2016-04-29 18:44:17 -0700277 Stream<DiscreteResource> discrete = discreteStore.getResources(consumer.consumerId());
278 Stream<ContinuousResource> continuous = continuousStore.getResources(consumer.consumerId());
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800279
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700280 return Stream.concat(discrete, continuous).collect(Collectors.toList());
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700281 }
282
Sho SHIMIZU82bfe992016-02-10 09:55:32 -0800283 // computational complexity: O(1)
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700284 @Override
Sho SHIMIZUdd3750c2016-02-01 11:37:04 -0800285 public Set<Resource> getChildResources(DiscreteResourceId parent) {
Sho SHIMIZUe7f4f3f2015-10-13 16:27:25 -0700286 checkNotNull(parent);
287
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700288 return ImmutableSet.<Resource>builder()
289 .addAll(discreteStore.getChildResources(parent))
290 .addAll(continuousStore.getChildResources(parent))
291 .build();
Sho SHIMIZUe7f4f3f2015-10-13 16:27:25 -0700292 }
293
Sho SHIMIZUdd3750c2016-02-01 11:37:04 -0800294 // computational complexity: O(n) where n is the number of the children of the parent
Sho SHIMIZUe7f4f3f2015-10-13 16:27:25 -0700295 @Override
Sho SHIMIZUdd3750c2016-02-01 11:37:04 -0800296 public <T> Collection<Resource> getAllocatedResources(DiscreteResourceId parent, Class<T> cls) {
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700297 checkNotNull(parent);
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700298 checkNotNull(cls);
299
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700300 Stream<DiscreteResource> discrete = discreteStore.getAllocatedResources(parent, cls);
301 Stream<ContinuousResource> continuous = continuousStore.getAllocatedResources(parent, cls);
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800302
303 return Stream.concat(discrete, continuous).collect(Collectors.toList());
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700304 }
Sho SHIMIZUd29847f2015-08-13 09:10:59 -0700305
306 /**
307 * Abort the transaction.
308 *
309 * @param tx transaction context
310 * @return always false
311 */
312 private boolean abortTransaction(TransactionContext tx) {
313 tx.abort();
314 return false;
315 }
316
317 /**
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700318 * Appends the values to the existing values associated with the specified key.
Sho SHIMIZU4568c412015-08-21 16:39:07 -0700319 * If the map already has all the given values, appending will not happen.
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700320 *
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700321 * @param key key specifying values
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700322 * @param values values to be appended
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700323 * @return true if the operation succeeds, false otherwise.
324 */
Sho SHIMIZUdd3750c2016-02-01 11:37:04 -0800325 // computational complexity: O(n) where n is the number of the specified value
Sho SHIMIZUa2d99eb2016-05-06 14:52:55 -0700326 private boolean register(TransactionalDiscreteResourceStore discreteTxStore,
327 TransactionalContinuousResourceStore continuousTxStore,
328 DiscreteResourceId key, List<Resource> values) {
Sho SHIMIZU03be2662016-05-04 09:38:45 -0700329 // it's assumed that the passed "values" is non-empty
330
331 // This is 2-pass scan. Nicer to have 1-pass scan
332 List<DiscreteResource> discreteValues = values.stream()
333 .filter(x -> x instanceof DiscreteResource)
334 .map(x -> (DiscreteResource) x)
335 .collect(Collectors.toList());
336 List<ContinuousResource> continuousValues = values.stream()
337 .filter(x -> x instanceof ContinuousResource)
338 .map(x -> (ContinuousResource) x)
339 .collect(Collectors.toList());
340
Sho SHIMIZUa2d99eb2016-05-06 14:52:55 -0700341 return discreteTxStore.register(key, discreteValues)
342 && continuousTxStore.register(key, continuousValues);
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700343 }
344
345 /**
Sho SHIMIZUba1f83b2015-10-14 08:11:20 -0700346 * Removes the values from the existing values associated with the specified key.
Sho SHIMIZU5618ee52015-08-21 17:19:44 -0700347 * If the map doesn't contain the given values, removal will not happen.
Sho SHIMIZU2d8a13a2015-08-18 22:37:41 -0700348 *
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700349 * @param discreteTxStore map holding multiple discrete resources for a key
350 * @param continuousTxStore map holding multiple continuous resources for a key
351 * @param key key specifying values
352 * @param values values to be removed
Sho SHIMIZU2d8a13a2015-08-18 22:37:41 -0700353 * @return true if the operation succeeds, false otherwise
354 */
Sho SHIMIZUa2d99eb2016-05-06 14:52:55 -0700355 private boolean unregister(TransactionalDiscreteResourceStore discreteTxStore,
356 TransactionalContinuousResourceStore continuousTxStore,
357 DiscreteResourceId key, List<Resource> values) {
Sho SHIMIZU03be2662016-05-04 09:38:45 -0700358 // it's assumed that the passed "values" is non-empty
359
360 // This is 2-pass scan. Nicer to have 1-pass scan
361 List<DiscreteResource> discreteValues = values.stream()
362 .filter(x -> x instanceof DiscreteResource)
363 .map(x -> (DiscreteResource) x)
364 .collect(Collectors.toList());
365 List<ContinuousResource> continuousValues = values.stream()
366 .filter(x -> x instanceof ContinuousResource)
367 .map(x -> (ContinuousResource) x)
368 .collect(Collectors.toList());
369
Sho SHIMIZUa2d99eb2016-05-06 14:52:55 -0700370 return discreteTxStore.unregister(key, discreteValues)
371 && continuousTxStore.unregister(key, continuousValues);
Sho SHIMIZU03be2662016-05-04 09:38:45 -0700372 }
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700373}