blob: 549675bd781c03285c28328a8c96af59ee00ec1a [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 SHIMIZUa4861d42016-05-26 12:25:07 -070025import org.onlab.util.Tools;
Sho SHIMIZUe18cb122016-02-22 21:04:56 -080026import org.onosproject.net.resource.ContinuousResource;
27import org.onosproject.net.resource.ContinuousResourceId;
28import org.onosproject.net.resource.DiscreteResource;
29import org.onosproject.net.resource.DiscreteResourceId;
Sho SHIMIZU22fb2832016-05-06 11:44:03 -070030import org.onosproject.net.resource.Resource;
Sho SHIMIZUe18cb122016-02-22 21:04:56 -080031import org.onosproject.net.resource.ResourceAllocation;
32import org.onosproject.net.resource.ResourceConsumer;
Naoki Shiotabd1974c2016-04-29 18:44:17 -070033import org.onosproject.net.resource.ResourceConsumerId;
Sho SHIMIZUe18cb122016-02-22 21:04:56 -080034import org.onosproject.net.resource.ResourceEvent;
35import org.onosproject.net.resource.ResourceId;
Sho SHIMIZUe18cb122016-02-22 21:04:56 -080036import org.onosproject.net.resource.ResourceStore;
37import org.onosproject.net.resource.ResourceStoreDelegate;
38import org.onosproject.net.resource.Resources;
Sho SHIMIZUfa62b472015-11-02 17:35:46 -080039import org.onosproject.store.AbstractStore;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070040import org.onosproject.store.serializers.KryoNamespaces;
Madan Jampani3780d4b2016-04-04 18:18:24 -070041import org.onosproject.store.service.CommitStatus;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070042import org.onosproject.store.service.Serializer;
43import org.onosproject.store.service.StorageService;
44import org.onosproject.store.service.TransactionContext;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070045import org.slf4j.Logger;
46import org.slf4j.LoggerFactory;
47
Sho SHIMIZUba41fc12015-08-12 15:43:22 -070048import java.util.Arrays;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070049import java.util.Collection;
Sho SHIMIZU69420fe2016-02-09 15:01:07 -080050import java.util.LinkedHashMap;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070051import java.util.List;
52import java.util.Map;
53import java.util.Optional;
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -080054import java.util.Set;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070055import java.util.stream.Collectors;
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -080056import java.util.stream.Stream;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070057
58import static com.google.common.base.Preconditions.checkArgument;
59import static com.google.common.base.Preconditions.checkNotNull;
Sho SHIMIZU22fb2832016-05-06 11:44:03 -070060import static org.onosproject.net.resource.ResourceEvent.Type.RESOURCE_ADDED;
61import static org.onosproject.net.resource.ResourceEvent.Type.RESOURCE_REMOVED;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070062
63/**
64 * Implementation of ResourceStore using TransactionalMap.
65 */
Sho SHIMIZU9a2b8292015-10-28 13:00:16 -070066@Component(immediate = true)
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070067@Service
68@Beta
Sho SHIMIZUfa62b472015-11-02 17:35:46 -080069public class ConsistentResourceStore extends AbstractStore<ResourceEvent, ResourceStoreDelegate>
70 implements ResourceStore {
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070071 private static final Logger log = LoggerFactory.getLogger(ConsistentResourceStore.class);
72
Sho SHIMIZU22fb2832016-05-06 11:44:03 -070073 static final Serializer SERIALIZER = Serializer.using(
HIGUCHI Yuta6f584222016-05-06 11:15:38 -070074 Arrays.asList(KryoNamespaces.API),
Sho SHIMIZU02e6e202016-05-18 10:47:47 -070075 UnifiedDiscreteResources.class,
Sho SHIMIZU32f57e92016-05-18 10:23:06 -070076 NonEncodableDiscreteResources.class,
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -080077 ContinuousResourceAllocation.class);
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070078
Thomas Vachuska762a2d82016-01-04 10:25:20 -080079 // TODO: We should provide centralized values for this
Sho SHIMIZU22fb2832016-05-06 11:44:03 -070080 static final int MAX_RETRIES = 5;
81 static final int RETRY_DELAY = 1_000; // millis
Thomas Vachuska762a2d82016-01-04 10:25:20 -080082
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070083 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
84 protected StorageService service;
85
Sho SHIMIZU7ecf5ea2016-05-13 15:28:59 -070086 private ConsistentDiscreteResourceSubStore discreteStore;
87 private ConsistentContinuousResourceSubStore continuousStore;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070088
89 @Activate
90 public void activate() {
Sho SHIMIZU7ecf5ea2016-05-13 15:28:59 -070091 discreteStore = new ConsistentDiscreteResourceSubStore(service);
92 continuousStore = new ConsistentContinuousResourceSubStore(service);
Sho SHIMIZUe7db6142015-11-04 11:24:22 -080093
Madan Jampanic7f49f92015-12-10 11:35:06 -080094 log.info("Started");
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070095 }
96
Sho SHIMIZUdd3750c2016-02-01 11:37:04 -080097 // Computational complexity: O(1) if the resource is discrete type.
98 // 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 -070099 @Override
Sho SHIMIZUdd3750c2016-02-01 11:37:04 -0800100 public List<ResourceAllocation> getResourceAllocations(ResourceId id) {
101 checkNotNull(id);
102 checkArgument(id instanceof DiscreteResourceId || id instanceof ContinuousResourceId);
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700103
Sho SHIMIZUdd3750c2016-02-01 11:37:04 -0800104 if (id instanceof DiscreteResourceId) {
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700105 return discreteStore.getResourceAllocations((DiscreteResourceId) id);
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800106 } else {
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700107 return continuousStore.getResourceAllocations((ContinuousResourceId) id);
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800108 }
109 }
110
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700111 @Override
Jonathan Hart56151262016-02-11 09:48:50 -0800112 public boolean register(List<Resource> resources) {
Sho SHIMIZU83e17a02015-08-20 14:07:05 -0700113 checkNotNull(resources);
HIGUCHI Yuta6f828c32016-01-20 18:11:05 -0800114 if (log.isTraceEnabled()) {
115 resources.forEach(r -> log.trace("registering {}", r));
116 }
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700117
118 TransactionContext tx = service.transactionContextBuilder().build();
119 tx.begin();
120
Sho SHIMIZU69420fe2016-02-09 15:01:07 -0800121 // the order is preserved by LinkedHashMap
Sho SHIMIZUf33b8932016-01-25 18:43:32 -0800122 Map<DiscreteResource, List<Resource>> resourceMap = resources.stream()
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800123 .filter(x -> x.parent().isPresent())
Sho SHIMIZU69420fe2016-02-09 15:01:07 -0800124 .collect(Collectors.groupingBy(x -> x.parent().get(), LinkedHashMap::new, Collectors.toList()));
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700125
Sho SHIMIZU7ecf5ea2016-05-13 15:28:59 -0700126 TransactionalDiscreteResourceSubStore discreteTxStore = discreteStore.transactional(tx);
127 TransactionalContinuousResourceSubStore continuousTxStore = continuousStore.transactional(tx);
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700128 for (Map.Entry<DiscreteResource, List<Resource>> entry : resourceMap.entrySet()) {
Sho SHIMIZU001e3f22016-05-06 14:46:15 -0700129 DiscreteResourceId parentId = entry.getKey().id();
Sho SHIMIZUd66148a2016-05-06 14:47:47 -0700130 if (!discreteTxStore.lookup(parentId).isPresent()) {
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800131 return abortTransaction(tx);
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700132 }
133
Sho SHIMIZUa2d99eb2016-05-06 14:52:55 -0700134 if (!register(discreteTxStore, continuousTxStore, parentId, entry.getValue())) {
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800135 return abortTransaction(tx);
136 }
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700137 }
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800138
Madan Jampani3780d4b2016-04-04 18:18:24 -0700139 return tx.commit().whenComplete((status, error) -> {
140 if (status == CommitStatus.SUCCESS) {
141 log.trace("Transaction commit succeeded on registration: resources={}", resources);
142 List<ResourceEvent> events = resources.stream()
143 .filter(x -> x.parent().isPresent())
144 .map(x -> new ResourceEvent(RESOURCE_ADDED, x))
145 .collect(Collectors.toList());
146 notifyDelegate(events);
147 } else {
148 log.warn("Transaction commit failed on registration", error);
149 }
150 }).join() == CommitStatus.SUCCESS;
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700151 }
152
153 @Override
Jonathan Hart56151262016-02-11 09:48:50 -0800154 public boolean unregister(List<ResourceId> ids) {
Sho SHIMIZU72f81b12016-02-09 09:26:17 -0800155 checkNotNull(ids);
Sho SHIMIZU2d8a13a2015-08-18 22:37:41 -0700156
157 TransactionContext tx = service.transactionContextBuilder().build();
158 tx.begin();
159
Sho SHIMIZU7ecf5ea2016-05-13 15:28:59 -0700160 TransactionalDiscreteResourceSubStore discreteTxStore = discreteStore.transactional(tx);
161 TransactionalContinuousResourceSubStore continuousTxStore = continuousStore.transactional(tx);
Sho SHIMIZU7d54d9c2016-02-17 13:58:46 -0800162 // Look up resources by resource IDs
Sho SHIMIZU72f81b12016-02-09 09:26:17 -0800163 List<Resource> resources = ids.stream()
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800164 .filter(x -> x.parent().isPresent())
Sho SHIMIZU7d54d9c2016-02-17 13:58:46 -0800165 .map(x -> {
166 // avoid access to consistent map in the case of discrete resource
167 if (x instanceof DiscreteResourceId) {
168 return Optional.of(Resources.discrete((DiscreteResourceId) x).resource());
169 } else {
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700170 return continuousTxStore.lookup((ContinuousResourceId) x);
Sho SHIMIZU7d54d9c2016-02-17 13:58:46 -0800171 }
172 })
Sho SHIMIZUa4861d42016-05-26 12:25:07 -0700173 .flatMap(Tools::stream)
Sho SHIMIZU72f81b12016-02-09 09:26:17 -0800174 .collect(Collectors.toList());
Sho SHIMIZU69420fe2016-02-09 15:01:07 -0800175 // the order is preserved by LinkedHashMap
Sho SHIMIZU72f81b12016-02-09 09:26:17 -0800176 Map<DiscreteResourceId, List<Resource>> resourceMap = resources.stream()
Sho SHIMIZU69420fe2016-02-09 15:01:07 -0800177 .collect(Collectors.groupingBy(x -> x.parent().get().id(), LinkedHashMap::new, Collectors.toList()));
Sho SHIMIZU83e17a02015-08-20 14:07:05 -0700178
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700179 for (Map.Entry<DiscreteResourceId, List<Resource>> entry : resourceMap.entrySet()) {
Sho SHIMIZUa2d99eb2016-05-06 14:52:55 -0700180 if (!unregister(discreteTxStore, continuousTxStore, entry.getKey(), entry.getValue())) {
HIGUCHI Yuta6acdfd02016-02-18 10:39:43 -0800181 log.warn("Failed to unregister {}: Failed to remove {} values.",
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700182 entry.getKey(), entry.getValue().size());
HIGUCHI Yuta6acdfd02016-02-18 10:39:43 -0800183 log.debug("Failed to unregister {}: Failed to remove values: {}",
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700184 entry.getKey(), entry.getValue());
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800185 return abortTransaction(tx);
186 }
Sho SHIMIZU2d8a13a2015-08-18 22:37:41 -0700187 }
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800188
Madan Jampani3780d4b2016-04-04 18:18:24 -0700189 return tx.commit().whenComplete((status, error) -> {
190 if (status == CommitStatus.SUCCESS) {
191 List<ResourceEvent> events = resources.stream()
192 .filter(x -> x.parent().isPresent())
193 .map(x -> new ResourceEvent(RESOURCE_REMOVED, x))
194 .collect(Collectors.toList());
195 notifyDelegate(events);
196 } else {
197 log.warn("Failed to unregister {}: Commit failed.", ids, error);
198 }
199 }).join() == CommitStatus.SUCCESS;
Sho SHIMIZU2d8a13a2015-08-18 22:37:41 -0700200 }
201
202 @Override
Jonathan Hart56151262016-02-11 09:48:50 -0800203 public boolean allocate(List<Resource> resources, ResourceConsumer consumer) {
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700204 checkNotNull(resources);
205 checkNotNull(consumer);
206
207 TransactionContext tx = service.transactionContextBuilder().build();
208 tx.begin();
209
Sho SHIMIZU7ecf5ea2016-05-13 15:28:59 -0700210 TransactionalDiscreteResourceSubStore discreteTxStore = discreteStore.transactional(tx);
211 TransactionalContinuousResourceSubStore continuousTxStore = continuousStore.transactional(tx);
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700212 for (Resource resource : resources) {
Sho SHIMIZU171a9382016-02-15 13:56:34 -0800213 if (resource instanceof DiscreteResource) {
Naoki Shiotabd1974c2016-04-29 18:44:17 -0700214 if (!discreteTxStore.allocate(consumer.consumerId(), (DiscreteResource) resource)) {
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800215 return abortTransaction(tx);
216 }
Sho SHIMIZUf33b8932016-01-25 18:43:32 -0800217 } else if (resource instanceof ContinuousResource) {
Naoki Shiotabd1974c2016-04-29 18:44:17 -0700218 if (!continuousTxStore.allocate(consumer.consumerId(), (ContinuousResource) resource)) {
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800219 return abortTransaction(tx);
220 }
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800221 }
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700222 }
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800223
Madan Jampani3780d4b2016-04-04 18:18:24 -0700224 return tx.commit().join() == CommitStatus.SUCCESS;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700225 }
226
227 @Override
Sho SHIMIZUfc64ffe2016-02-10 20:11:09 -0800228 public boolean release(List<ResourceAllocation> allocations) {
229 checkNotNull(allocations);
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700230
231 TransactionContext tx = service.transactionContextBuilder().build();
232 tx.begin();
233
Sho SHIMIZU7ecf5ea2016-05-13 15:28:59 -0700234 TransactionalDiscreteResourceSubStore discreteTxStore = discreteStore.transactional(tx);
235 TransactionalContinuousResourceSubStore continuousTxStore = continuousStore.transactional(tx);
Sho SHIMIZUfc64ffe2016-02-10 20:11:09 -0800236 for (ResourceAllocation allocation : allocations) {
237 Resource resource = allocation.resource();
Naoki Shiotabd1974c2016-04-29 18:44:17 -0700238 ResourceConsumerId consumerId = allocation.consumerId();
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700239
Sho SHIMIZUf33b8932016-01-25 18:43:32 -0800240 if (resource instanceof DiscreteResource) {
Naoki Shiotabd1974c2016-04-29 18:44:17 -0700241 if (!discreteTxStore.release((DiscreteResource) resource, consumerId)) {
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800242 return abortTransaction(tx);
243 }
Sho SHIMIZUf33b8932016-01-25 18:43:32 -0800244 } else if (resource instanceof ContinuousResource) {
Naoki Shiotabd1974c2016-04-29 18:44:17 -0700245 if (!continuousTxStore.release((ContinuousResource) resource, consumerId)) {
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800246 return abortTransaction(tx);
247 }
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700248 }
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700249 }
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800250
Madan Jampani3780d4b2016-04-04 18:18:24 -0700251 return tx.commit().join() == CommitStatus.SUCCESS;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700252 }
253
Sho SHIMIZUdd3750c2016-02-01 11:37:04 -0800254 // computational complexity: O(1) if the resource is discrete type.
255 // O(n) if the resource is continuous type where n is the number of the children of
256 // the specified resource's parent
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700257 @Override
Sho SHIMIZU8fa670a2016-01-14 11:17:18 -0800258 public boolean isAvailable(Resource resource) {
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800259 checkNotNull(resource);
Sho SHIMIZUf33b8932016-01-25 18:43:32 -0800260 checkArgument(resource instanceof DiscreteResource || resource instanceof ContinuousResource);
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800261
Sho SHIMIZUf33b8932016-01-25 18:43:32 -0800262 if (resource instanceof DiscreteResource) {
HIGUCHI Yuta6f828c32016-01-20 18:11:05 -0800263 // check if already consumed
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700264 return discreteStore.isAvailable((DiscreteResource) resource);
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800265 } else {
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700266 return continuousStore.isAvailable((ContinuousResource) resource);
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800267 }
268 }
269
Sho SHIMIZUdd3750c2016-02-01 11:37:04 -0800270 // computational complexity: O(n + m) where n is the number of entries in discreteConsumers
271 // and m is the number of allocations for all continuous resources
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800272 @Override
Sho SHIMIZU8fa670a2016-01-14 11:17:18 -0800273 public Collection<Resource> getResources(ResourceConsumer consumer) {
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700274 checkNotNull(consumer);
275
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}