blob: d858a88cbee06726dfcad02587831dfa858e3c0a [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 SHIMIZU32f57e92016-05-18 10:23:06 -070074 NonEncodableDiscreteResources.class,
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -080075 ContinuousResourceAllocation.class);
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070076
Thomas Vachuska762a2d82016-01-04 10:25:20 -080077 // TODO: We should provide centralized values for this
Sho SHIMIZU22fb2832016-05-06 11:44:03 -070078 static final int MAX_RETRIES = 5;
79 static final int RETRY_DELAY = 1_000; // millis
Thomas Vachuska762a2d82016-01-04 10:25:20 -080080
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070081 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
82 protected StorageService service;
83
Sho SHIMIZU7ecf5ea2016-05-13 15:28:59 -070084 private ConsistentDiscreteResourceSubStore discreteStore;
85 private ConsistentContinuousResourceSubStore continuousStore;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070086
87 @Activate
88 public void activate() {
Sho SHIMIZU7ecf5ea2016-05-13 15:28:59 -070089 discreteStore = new ConsistentDiscreteResourceSubStore(service);
90 continuousStore = new ConsistentContinuousResourceSubStore(service);
Sho SHIMIZUe7db6142015-11-04 11:24:22 -080091
Madan Jampanic7f49f92015-12-10 11:35:06 -080092 log.info("Started");
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070093 }
94
Sho SHIMIZUdd3750c2016-02-01 11:37:04 -080095 // Computational complexity: O(1) if the resource is discrete type.
96 // 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 -070097 @Override
Sho SHIMIZUdd3750c2016-02-01 11:37:04 -080098 public List<ResourceAllocation> getResourceAllocations(ResourceId id) {
99 checkNotNull(id);
100 checkArgument(id instanceof DiscreteResourceId || id instanceof ContinuousResourceId);
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700101
Sho SHIMIZUdd3750c2016-02-01 11:37:04 -0800102 if (id instanceof DiscreteResourceId) {
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700103 return discreteStore.getResourceAllocations((DiscreteResourceId) id);
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800104 } else {
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700105 return continuousStore.getResourceAllocations((ContinuousResourceId) id);
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800106 }
107 }
108
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700109 @Override
Jonathan Hart56151262016-02-11 09:48:50 -0800110 public boolean register(List<Resource> resources) {
Sho SHIMIZU83e17a02015-08-20 14:07:05 -0700111 checkNotNull(resources);
HIGUCHI Yuta6f828c32016-01-20 18:11:05 -0800112 if (log.isTraceEnabled()) {
113 resources.forEach(r -> log.trace("registering {}", r));
114 }
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700115
116 TransactionContext tx = service.transactionContextBuilder().build();
117 tx.begin();
118
Sho SHIMIZU69420fe2016-02-09 15:01:07 -0800119 // the order is preserved by LinkedHashMap
Sho SHIMIZUf33b8932016-01-25 18:43:32 -0800120 Map<DiscreteResource, List<Resource>> resourceMap = resources.stream()
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800121 .filter(x -> x.parent().isPresent())
Sho SHIMIZU69420fe2016-02-09 15:01:07 -0800122 .collect(Collectors.groupingBy(x -> x.parent().get(), LinkedHashMap::new, Collectors.toList()));
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700123
Sho SHIMIZU7ecf5ea2016-05-13 15:28:59 -0700124 TransactionalDiscreteResourceSubStore discreteTxStore = discreteStore.transactional(tx);
125 TransactionalContinuousResourceSubStore continuousTxStore = continuousStore.transactional(tx);
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700126 for (Map.Entry<DiscreteResource, List<Resource>> entry : resourceMap.entrySet()) {
Sho SHIMIZU001e3f22016-05-06 14:46:15 -0700127 DiscreteResourceId parentId = entry.getKey().id();
Sho SHIMIZUd66148a2016-05-06 14:47:47 -0700128 if (!discreteTxStore.lookup(parentId).isPresent()) {
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800129 return abortTransaction(tx);
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700130 }
131
Sho SHIMIZUa2d99eb2016-05-06 14:52:55 -0700132 if (!register(discreteTxStore, continuousTxStore, parentId, entry.getValue())) {
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800133 return abortTransaction(tx);
134 }
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700135 }
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800136
Madan Jampani3780d4b2016-04-04 18:18:24 -0700137 return tx.commit().whenComplete((status, error) -> {
138 if (status == CommitStatus.SUCCESS) {
139 log.trace("Transaction commit succeeded on registration: resources={}", resources);
140 List<ResourceEvent> events = resources.stream()
141 .filter(x -> x.parent().isPresent())
142 .map(x -> new ResourceEvent(RESOURCE_ADDED, x))
143 .collect(Collectors.toList());
144 notifyDelegate(events);
145 } else {
146 log.warn("Transaction commit failed on registration", error);
147 }
148 }).join() == CommitStatus.SUCCESS;
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700149 }
150
151 @Override
Jonathan Hart56151262016-02-11 09:48:50 -0800152 public boolean unregister(List<ResourceId> ids) {
Sho SHIMIZU72f81b12016-02-09 09:26:17 -0800153 checkNotNull(ids);
Sho SHIMIZU2d8a13a2015-08-18 22:37:41 -0700154
155 TransactionContext tx = service.transactionContextBuilder().build();
156 tx.begin();
157
Sho SHIMIZU7ecf5ea2016-05-13 15:28:59 -0700158 TransactionalDiscreteResourceSubStore discreteTxStore = discreteStore.transactional(tx);
159 TransactionalContinuousResourceSubStore continuousTxStore = continuousStore.transactional(tx);
Sho SHIMIZU7d54d9c2016-02-17 13:58:46 -0800160 // Look up resources by resource IDs
Sho SHIMIZU72f81b12016-02-09 09:26:17 -0800161 List<Resource> resources = ids.stream()
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800162 .filter(x -> x.parent().isPresent())
Sho SHIMIZU7d54d9c2016-02-17 13:58:46 -0800163 .map(x -> {
164 // avoid access to consistent map in the case of discrete resource
165 if (x instanceof DiscreteResourceId) {
166 return Optional.of(Resources.discrete((DiscreteResourceId) x).resource());
167 } else {
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700168 return continuousTxStore.lookup((ContinuousResourceId) x);
Sho SHIMIZU7d54d9c2016-02-17 13:58:46 -0800169 }
170 })
HIGUCHI Yuta315179a2016-02-18 14:01:22 -0800171 .filter(Optional::isPresent)
172 .map(Optional::get)
Sho SHIMIZU72f81b12016-02-09 09:26:17 -0800173 .collect(Collectors.toList());
Sho SHIMIZU69420fe2016-02-09 15:01:07 -0800174 // the order is preserved by LinkedHashMap
Sho SHIMIZU72f81b12016-02-09 09:26:17 -0800175 Map<DiscreteResourceId, List<Resource>> resourceMap = resources.stream()
Sho SHIMIZU69420fe2016-02-09 15:01:07 -0800176 .collect(Collectors.groupingBy(x -> x.parent().get().id(), LinkedHashMap::new, Collectors.toList()));
Sho SHIMIZU83e17a02015-08-20 14:07:05 -0700177
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700178 for (Map.Entry<DiscreteResourceId, List<Resource>> entry : resourceMap.entrySet()) {
Sho SHIMIZUa2d99eb2016-05-06 14:52:55 -0700179 if (!unregister(discreteTxStore, continuousTxStore, entry.getKey(), entry.getValue())) {
HIGUCHI Yuta6acdfd02016-02-18 10:39:43 -0800180 log.warn("Failed to unregister {}: Failed to remove {} values.",
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700181 entry.getKey(), entry.getValue().size());
HIGUCHI Yuta6acdfd02016-02-18 10:39:43 -0800182 log.debug("Failed to unregister {}: Failed to remove values: {}",
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700183 entry.getKey(), entry.getValue());
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800184 return abortTransaction(tx);
185 }
Sho SHIMIZU2d8a13a2015-08-18 22:37:41 -0700186 }
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800187
Madan Jampani3780d4b2016-04-04 18:18:24 -0700188 return tx.commit().whenComplete((status, error) -> {
189 if (status == CommitStatus.SUCCESS) {
190 List<ResourceEvent> events = resources.stream()
191 .filter(x -> x.parent().isPresent())
192 .map(x -> new ResourceEvent(RESOURCE_REMOVED, x))
193 .collect(Collectors.toList());
194 notifyDelegate(events);
195 } else {
196 log.warn("Failed to unregister {}: Commit failed.", ids, error);
197 }
198 }).join() == CommitStatus.SUCCESS;
Sho SHIMIZU2d8a13a2015-08-18 22:37:41 -0700199 }
200
201 @Override
Jonathan Hart56151262016-02-11 09:48:50 -0800202 public boolean allocate(List<Resource> resources, ResourceConsumer consumer) {
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700203 checkNotNull(resources);
204 checkNotNull(consumer);
205
206 TransactionContext tx = service.transactionContextBuilder().build();
207 tx.begin();
208
Sho SHIMIZU7ecf5ea2016-05-13 15:28:59 -0700209 TransactionalDiscreteResourceSubStore discreteTxStore = discreteStore.transactional(tx);
210 TransactionalContinuousResourceSubStore continuousTxStore = continuousStore.transactional(tx);
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700211 for (Resource resource : resources) {
Sho SHIMIZU171a9382016-02-15 13:56:34 -0800212 if (resource instanceof DiscreteResource) {
Naoki Shiotabd1974c2016-04-29 18:44:17 -0700213 if (!discreteTxStore.allocate(consumer.consumerId(), (DiscreteResource) resource)) {
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800214 return abortTransaction(tx);
215 }
Sho SHIMIZUf33b8932016-01-25 18:43:32 -0800216 } else if (resource instanceof ContinuousResource) {
Naoki Shiotabd1974c2016-04-29 18:44:17 -0700217 if (!continuousTxStore.allocate(consumer.consumerId(), (ContinuousResource) resource)) {
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800218 return abortTransaction(tx);
219 }
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800220 }
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700221 }
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800222
Madan Jampani3780d4b2016-04-04 18:18:24 -0700223 return tx.commit().join() == CommitStatus.SUCCESS;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700224 }
225
226 @Override
Sho SHIMIZUfc64ffe2016-02-10 20:11:09 -0800227 public boolean release(List<ResourceAllocation> allocations) {
228 checkNotNull(allocations);
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700229
230 TransactionContext tx = service.transactionContextBuilder().build();
231 tx.begin();
232
Sho SHIMIZU7ecf5ea2016-05-13 15:28:59 -0700233 TransactionalDiscreteResourceSubStore discreteTxStore = discreteStore.transactional(tx);
234 TransactionalContinuousResourceSubStore continuousTxStore = continuousStore.transactional(tx);
Sho SHIMIZUfc64ffe2016-02-10 20:11:09 -0800235 for (ResourceAllocation allocation : allocations) {
236 Resource resource = allocation.resource();
Naoki Shiotabd1974c2016-04-29 18:44:17 -0700237 ResourceConsumerId consumerId = allocation.consumerId();
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700238
Sho SHIMIZUf33b8932016-01-25 18:43:32 -0800239 if (resource instanceof DiscreteResource) {
Naoki Shiotabd1974c2016-04-29 18:44:17 -0700240 if (!discreteTxStore.release((DiscreteResource) resource, consumerId)) {
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800241 return abortTransaction(tx);
242 }
Sho SHIMIZUf33b8932016-01-25 18:43:32 -0800243 } else if (resource instanceof ContinuousResource) {
Naoki Shiotabd1974c2016-04-29 18:44:17 -0700244 if (!continuousTxStore.release((ContinuousResource) resource, consumerId)) {
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800245 return abortTransaction(tx);
246 }
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700247 }
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700248 }
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800249
Madan Jampani3780d4b2016-04-04 18:18:24 -0700250 return tx.commit().join() == CommitStatus.SUCCESS;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700251 }
252
Sho SHIMIZUdd3750c2016-02-01 11:37:04 -0800253 // computational complexity: O(1) if the resource is discrete type.
254 // O(n) if the resource is continuous type where n is the number of the children of
255 // the specified resource's parent
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700256 @Override
Sho SHIMIZU8fa670a2016-01-14 11:17:18 -0800257 public boolean isAvailable(Resource resource) {
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800258 checkNotNull(resource);
Sho SHIMIZUf33b8932016-01-25 18:43:32 -0800259 checkArgument(resource instanceof DiscreteResource || resource instanceof ContinuousResource);
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800260
Sho SHIMIZUf33b8932016-01-25 18:43:32 -0800261 if (resource instanceof DiscreteResource) {
HIGUCHI Yuta6f828c32016-01-20 18:11:05 -0800262 // check if already consumed
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700263 return discreteStore.isAvailable((DiscreteResource) resource);
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800264 } else {
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700265 return continuousStore.isAvailable((ContinuousResource) resource);
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800266 }
267 }
268
Sho SHIMIZUdd3750c2016-02-01 11:37:04 -0800269 // computational complexity: O(n + m) where n is the number of entries in discreteConsumers
270 // and m is the number of allocations for all continuous resources
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800271 @Override
Sho SHIMIZU8fa670a2016-01-14 11:17:18 -0800272 public Collection<Resource> getResources(ResourceConsumer consumer) {
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700273 checkNotNull(consumer);
Naoki Shiotabd1974c2016-04-29 18:44:17 -0700274 ResourceConsumerId consumerId = consumer.consumerId();
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700275
276 // NOTE: getting all entries may become performance bottleneck
277 // TODO: revisit for better backend data structure
Naoki Shiotabd1974c2016-04-29 18:44:17 -0700278 Stream<DiscreteResource> discrete = discreteStore.getResources(consumer.consumerId());
279 Stream<ContinuousResource> continuous = continuousStore.getResources(consumer.consumerId());
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800280
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700281 return Stream.concat(discrete, continuous).collect(Collectors.toList());
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700282 }
283
Sho SHIMIZU82bfe992016-02-10 09:55:32 -0800284 // computational complexity: O(1)
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700285 @Override
Sho SHIMIZUdd3750c2016-02-01 11:37:04 -0800286 public Set<Resource> getChildResources(DiscreteResourceId parent) {
Sho SHIMIZUe7f4f3f2015-10-13 16:27:25 -0700287 checkNotNull(parent);
288
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700289 return ImmutableSet.<Resource>builder()
290 .addAll(discreteStore.getChildResources(parent))
291 .addAll(continuousStore.getChildResources(parent))
292 .build();
Sho SHIMIZUe7f4f3f2015-10-13 16:27:25 -0700293 }
294
Sho SHIMIZUdd3750c2016-02-01 11:37:04 -0800295 // computational complexity: O(n) where n is the number of the children of the parent
Sho SHIMIZUe7f4f3f2015-10-13 16:27:25 -0700296 @Override
Sho SHIMIZUdd3750c2016-02-01 11:37:04 -0800297 public <T> Collection<Resource> getAllocatedResources(DiscreteResourceId parent, Class<T> cls) {
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700298 checkNotNull(parent);
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700299 checkNotNull(cls);
300
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700301 Stream<DiscreteResource> discrete = discreteStore.getAllocatedResources(parent, cls);
302 Stream<ContinuousResource> continuous = continuousStore.getAllocatedResources(parent, cls);
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800303
304 return Stream.concat(discrete, continuous).collect(Collectors.toList());
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700305 }
Sho SHIMIZUd29847f2015-08-13 09:10:59 -0700306
307 /**
308 * Abort the transaction.
309 *
310 * @param tx transaction context
311 * @return always false
312 */
313 private boolean abortTransaction(TransactionContext tx) {
314 tx.abort();
315 return false;
316 }
317
318 /**
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700319 * Appends the values to the existing values associated with the specified key.
Sho SHIMIZU4568c412015-08-21 16:39:07 -0700320 * If the map already has all the given values, appending will not happen.
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700321 *
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700322 * @param key key specifying values
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700323 * @param values values to be appended
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700324 * @return true if the operation succeeds, false otherwise.
325 */
Sho SHIMIZUdd3750c2016-02-01 11:37:04 -0800326 // computational complexity: O(n) where n is the number of the specified value
Sho SHIMIZU7ecf5ea2016-05-13 15:28:59 -0700327 private boolean register(TransactionalDiscreteResourceSubStore discreteTxStore,
328 TransactionalContinuousResourceSubStore continuousTxStore,
Sho SHIMIZUa2d99eb2016-05-06 14:52:55 -0700329 DiscreteResourceId key, List<Resource> values) {
Sho SHIMIZU03be2662016-05-04 09:38:45 -0700330 // it's assumed that the passed "values" is non-empty
331
332 // This is 2-pass scan. Nicer to have 1-pass scan
333 List<DiscreteResource> discreteValues = values.stream()
334 .filter(x -> x instanceof DiscreteResource)
335 .map(x -> (DiscreteResource) x)
336 .collect(Collectors.toList());
337 List<ContinuousResource> continuousValues = values.stream()
338 .filter(x -> x instanceof ContinuousResource)
339 .map(x -> (ContinuousResource) x)
340 .collect(Collectors.toList());
341
Sho SHIMIZUa2d99eb2016-05-06 14:52:55 -0700342 return discreteTxStore.register(key, discreteValues)
343 && continuousTxStore.register(key, continuousValues);
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700344 }
345
346 /**
Sho SHIMIZUba1f83b2015-10-14 08:11:20 -0700347 * Removes the values from the existing values associated with the specified key.
Sho SHIMIZU5618ee52015-08-21 17:19:44 -0700348 * If the map doesn't contain the given values, removal will not happen.
Sho SHIMIZU2d8a13a2015-08-18 22:37:41 -0700349 *
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700350 * @param discreteTxStore map holding multiple discrete resources for a key
351 * @param continuousTxStore map holding multiple continuous resources for a key
352 * @param key key specifying values
353 * @param values values to be removed
Sho SHIMIZU2d8a13a2015-08-18 22:37:41 -0700354 * @return true if the operation succeeds, false otherwise
355 */
Sho SHIMIZU7ecf5ea2016-05-13 15:28:59 -0700356 private boolean unregister(TransactionalDiscreteResourceSubStore discreteTxStore,
357 TransactionalContinuousResourceSubStore continuousTxStore,
Sho SHIMIZUa2d99eb2016-05-06 14:52:55 -0700358 DiscreteResourceId key, List<Resource> values) {
Sho SHIMIZU03be2662016-05-04 09:38:45 -0700359 // it's assumed that the passed "values" is non-empty
360
361 // This is 2-pass scan. Nicer to have 1-pass scan
362 List<DiscreteResource> discreteValues = values.stream()
363 .filter(x -> x instanceof DiscreteResource)
364 .map(x -> (DiscreteResource) x)
365 .collect(Collectors.toList());
366 List<ContinuousResource> continuousValues = values.stream()
367 .filter(x -> x instanceof ContinuousResource)
368 .map(x -> (ContinuousResource) x)
369 .collect(Collectors.toList());
370
Sho SHIMIZUa2d99eb2016-05-06 14:52:55 -0700371 return discreteTxStore.unregister(key, discreteValues)
372 && continuousTxStore.unregister(key, continuousValues);
Sho SHIMIZU03be2662016-05-04 09:38:45 -0700373 }
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700374}