blob: 0be8a37a7f48c6719b3837c4effe157e5b25d866 [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;
32import org.onosproject.net.resource.ResourceEvent;
33import org.onosproject.net.resource.ResourceId;
Sho SHIMIZUe18cb122016-02-22 21:04:56 -080034import org.onosproject.net.resource.ResourceStore;
35import org.onosproject.net.resource.ResourceStoreDelegate;
36import org.onosproject.net.resource.Resources;
Sho SHIMIZUfa62b472015-11-02 17:35:46 -080037import org.onosproject.store.AbstractStore;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070038import org.onosproject.store.serializers.KryoNamespaces;
Madan Jampani3780d4b2016-04-04 18:18:24 -070039import org.onosproject.store.service.CommitStatus;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070040import org.onosproject.store.service.Serializer;
41import org.onosproject.store.service.StorageService;
42import org.onosproject.store.service.TransactionContext;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070043import org.slf4j.Logger;
44import org.slf4j.LoggerFactory;
45
Sho SHIMIZUba41fc12015-08-12 15:43:22 -070046import java.util.Arrays;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070047import java.util.Collection;
Sho SHIMIZU69420fe2016-02-09 15:01:07 -080048import java.util.LinkedHashMap;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070049import java.util.List;
50import java.util.Map;
51import java.util.Optional;
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -080052import java.util.Set;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070053import java.util.stream.Collectors;
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -080054import java.util.stream.Stream;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070055
56import static com.google.common.base.Preconditions.checkArgument;
57import static com.google.common.base.Preconditions.checkNotNull;
Sho SHIMIZU22fb2832016-05-06 11:44:03 -070058import static org.onosproject.net.resource.ResourceEvent.Type.RESOURCE_ADDED;
59import static org.onosproject.net.resource.ResourceEvent.Type.RESOURCE_REMOVED;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070060
61/**
62 * Implementation of ResourceStore using TransactionalMap.
63 */
Sho SHIMIZU9a2b8292015-10-28 13:00:16 -070064@Component(immediate = true)
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070065@Service
66@Beta
Sho SHIMIZUfa62b472015-11-02 17:35:46 -080067public class ConsistentResourceStore extends AbstractStore<ResourceEvent, ResourceStoreDelegate>
68 implements ResourceStore {
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070069 private static final Logger log = LoggerFactory.getLogger(ConsistentResourceStore.class);
70
Sho SHIMIZU22fb2832016-05-06 11:44:03 -070071 static final Serializer SERIALIZER = Serializer.using(
HIGUCHI Yuta6f584222016-05-06 11:15:38 -070072 Arrays.asList(KryoNamespaces.API),
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -080073 ContinuousResourceAllocation.class);
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070074
Thomas Vachuska762a2d82016-01-04 10:25:20 -080075 // TODO: We should provide centralized values for this
Sho SHIMIZU22fb2832016-05-06 11:44:03 -070076 static final int MAX_RETRIES = 5;
77 static final int RETRY_DELAY = 1_000; // millis
Thomas Vachuska762a2d82016-01-04 10:25:20 -080078
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070079 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
80 protected StorageService service;
81
Sho SHIMIZU22fb2832016-05-06 11:44:03 -070082 private ConsistentDiscreteResourceStore discreteStore;
83 private ConsistentContinuousResourceStore continuousStore;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070084
85 @Activate
86 public void activate() {
Sho SHIMIZU22fb2832016-05-06 11:44:03 -070087 discreteStore = new ConsistentDiscreteResourceStore(service);
88 continuousStore = new ConsistentContinuousResourceStore(service);
Sho SHIMIZUe7db6142015-11-04 11:24:22 -080089
Madan Jampanic7f49f92015-12-10 11:35:06 -080090 log.info("Started");
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070091 }
92
Sho SHIMIZUdd3750c2016-02-01 11:37:04 -080093 // Computational complexity: O(1) if the resource is discrete type.
94 // 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 -070095 @Override
Sho SHIMIZUdd3750c2016-02-01 11:37:04 -080096 public List<ResourceAllocation> getResourceAllocations(ResourceId id) {
97 checkNotNull(id);
98 checkArgument(id instanceof DiscreteResourceId || id instanceof ContinuousResourceId);
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -070099
Sho SHIMIZUdd3750c2016-02-01 11:37:04 -0800100 if (id instanceof DiscreteResourceId) {
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700101 return discreteStore.getResourceAllocations((DiscreteResourceId) id);
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800102 } else {
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700103 return continuousStore.getResourceAllocations((ContinuousResourceId) id);
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800104 }
105 }
106
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700107 @Override
Jonathan Hart56151262016-02-11 09:48:50 -0800108 public boolean register(List<Resource> resources) {
Sho SHIMIZU83e17a02015-08-20 14:07:05 -0700109 checkNotNull(resources);
HIGUCHI Yuta6f828c32016-01-20 18:11:05 -0800110 if (log.isTraceEnabled()) {
111 resources.forEach(r -> log.trace("registering {}", r));
112 }
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700113
114 TransactionContext tx = service.transactionContextBuilder().build();
115 tx.begin();
116
Sho SHIMIZU69420fe2016-02-09 15:01:07 -0800117 // the order is preserved by LinkedHashMap
Sho SHIMIZUf33b8932016-01-25 18:43:32 -0800118 Map<DiscreteResource, List<Resource>> resourceMap = resources.stream()
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800119 .filter(x -> x.parent().isPresent())
Sho SHIMIZU69420fe2016-02-09 15:01:07 -0800120 .collect(Collectors.groupingBy(x -> x.parent().get(), LinkedHashMap::new, Collectors.toList()));
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700121
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700122 TransactionalDiscreteResourceStore discreteTxStore = discreteStore.transactional(tx);
123 TransactionalContinuousResourceStore continuousTxStore = continuousStore.transactional(tx);
124 for (Map.Entry<DiscreteResource, List<Resource>> entry : resourceMap.entrySet()) {
Sho SHIMIZU001e3f22016-05-06 14:46:15 -0700125 DiscreteResourceId parentId = entry.getKey().id();
Sho SHIMIZUd66148a2016-05-06 14:47:47 -0700126 if (!discreteTxStore.lookup(parentId).isPresent()) {
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800127 return abortTransaction(tx);
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700128 }
129
Sho SHIMIZUa2d99eb2016-05-06 14:52:55 -0700130 if (!register(discreteTxStore, continuousTxStore, parentId, entry.getValue())) {
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800131 return abortTransaction(tx);
132 }
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700133 }
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800134
Madan Jampani3780d4b2016-04-04 18:18:24 -0700135 return tx.commit().whenComplete((status, error) -> {
136 if (status == CommitStatus.SUCCESS) {
137 log.trace("Transaction commit succeeded on registration: resources={}", resources);
138 List<ResourceEvent> events = resources.stream()
139 .filter(x -> x.parent().isPresent())
140 .map(x -> new ResourceEvent(RESOURCE_ADDED, x))
141 .collect(Collectors.toList());
142 notifyDelegate(events);
143 } else {
144 log.warn("Transaction commit failed on registration", error);
145 }
146 }).join() == CommitStatus.SUCCESS;
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700147 }
148
149 @Override
Jonathan Hart56151262016-02-11 09:48:50 -0800150 public boolean unregister(List<ResourceId> ids) {
Sho SHIMIZU72f81b12016-02-09 09:26:17 -0800151 checkNotNull(ids);
Sho SHIMIZU2d8a13a2015-08-18 22:37:41 -0700152
153 TransactionContext tx = service.transactionContextBuilder().build();
154 tx.begin();
155
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700156 TransactionalDiscreteResourceStore discreteTxStore = discreteStore.transactional(tx);
157 TransactionalContinuousResourceStore continuousTxStore = continuousStore.transactional(tx);
Sho SHIMIZU7d54d9c2016-02-17 13:58:46 -0800158 // Look up resources by resource IDs
Sho SHIMIZU72f81b12016-02-09 09:26:17 -0800159 List<Resource> resources = ids.stream()
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800160 .filter(x -> x.parent().isPresent())
Sho SHIMIZU7d54d9c2016-02-17 13:58:46 -0800161 .map(x -> {
162 // avoid access to consistent map in the case of discrete resource
163 if (x instanceof DiscreteResourceId) {
164 return Optional.of(Resources.discrete((DiscreteResourceId) x).resource());
165 } else {
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700166 return continuousTxStore.lookup((ContinuousResourceId) x);
Sho SHIMIZU7d54d9c2016-02-17 13:58:46 -0800167 }
168 })
HIGUCHI Yuta315179a2016-02-18 14:01:22 -0800169 .filter(Optional::isPresent)
170 .map(Optional::get)
Sho SHIMIZU72f81b12016-02-09 09:26:17 -0800171 .collect(Collectors.toList());
Sho SHIMIZU69420fe2016-02-09 15:01:07 -0800172 // the order is preserved by LinkedHashMap
Sho SHIMIZU72f81b12016-02-09 09:26:17 -0800173 Map<DiscreteResourceId, List<Resource>> resourceMap = resources.stream()
Sho SHIMIZU69420fe2016-02-09 15:01:07 -0800174 .collect(Collectors.groupingBy(x -> x.parent().get().id(), LinkedHashMap::new, Collectors.toList()));
Sho SHIMIZU83e17a02015-08-20 14:07:05 -0700175
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700176 for (Map.Entry<DiscreteResourceId, List<Resource>> entry : resourceMap.entrySet()) {
Sho SHIMIZUa2d99eb2016-05-06 14:52:55 -0700177 if (!unregister(discreteTxStore, continuousTxStore, entry.getKey(), entry.getValue())) {
HIGUCHI Yuta6acdfd02016-02-18 10:39:43 -0800178 log.warn("Failed to unregister {}: Failed to remove {} values.",
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700179 entry.getKey(), entry.getValue().size());
HIGUCHI Yuta6acdfd02016-02-18 10:39:43 -0800180 log.debug("Failed to unregister {}: Failed to remove values: {}",
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700181 entry.getKey(), entry.getValue());
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800182 return abortTransaction(tx);
183 }
Sho SHIMIZU2d8a13a2015-08-18 22:37:41 -0700184 }
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800185
Madan Jampani3780d4b2016-04-04 18:18:24 -0700186 return tx.commit().whenComplete((status, error) -> {
187 if (status == CommitStatus.SUCCESS) {
188 List<ResourceEvent> events = resources.stream()
189 .filter(x -> x.parent().isPresent())
190 .map(x -> new ResourceEvent(RESOURCE_REMOVED, x))
191 .collect(Collectors.toList());
192 notifyDelegate(events);
193 } else {
194 log.warn("Failed to unregister {}: Commit failed.", ids, error);
195 }
196 }).join() == CommitStatus.SUCCESS;
Sho SHIMIZU2d8a13a2015-08-18 22:37:41 -0700197 }
198
199 @Override
Jonathan Hart56151262016-02-11 09:48:50 -0800200 public boolean allocate(List<Resource> resources, ResourceConsumer consumer) {
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700201 checkNotNull(resources);
202 checkNotNull(consumer);
203
204 TransactionContext tx = service.transactionContextBuilder().build();
205 tx.begin();
206
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700207 TransactionalDiscreteResourceStore discreteTxStore = discreteStore.transactional(tx);
208 TransactionalContinuousResourceStore continuousTxStore = continuousStore.transactional(tx);
209 for (Resource resource : resources) {
Sho SHIMIZU171a9382016-02-15 13:56:34 -0800210 if (resource instanceof DiscreteResource) {
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700211 if (!discreteTxStore.allocate(consumer, (DiscreteResource) resource)) {
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800212 return abortTransaction(tx);
213 }
Sho SHIMIZUf33b8932016-01-25 18:43:32 -0800214 } else if (resource instanceof ContinuousResource) {
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700215 if (!continuousTxStore.allocate(consumer, (ContinuousResource) resource)) {
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800216 return abortTransaction(tx);
217 }
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800218 }
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700219 }
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800220
Madan Jampani3780d4b2016-04-04 18:18:24 -0700221 return tx.commit().join() == CommitStatus.SUCCESS;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700222 }
223
224 @Override
Sho SHIMIZUfc64ffe2016-02-10 20:11:09 -0800225 public boolean release(List<ResourceAllocation> allocations) {
226 checkNotNull(allocations);
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700227
228 TransactionContext tx = service.transactionContextBuilder().build();
229 tx.begin();
230
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700231 TransactionalDiscreteResourceStore discreteTxStore = discreteStore.transactional(tx);
232 TransactionalContinuousResourceStore continuousTxStore = continuousStore.transactional(tx);
Sho SHIMIZUfc64ffe2016-02-10 20:11:09 -0800233 for (ResourceAllocation allocation : allocations) {
234 Resource resource = allocation.resource();
235 ResourceConsumer consumer = allocation.consumer();
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700236
Sho SHIMIZUf33b8932016-01-25 18:43:32 -0800237 if (resource instanceof DiscreteResource) {
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700238 if (!discreteTxStore.release((DiscreteResource) resource, consumer)) {
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800239 return abortTransaction(tx);
240 }
Sho SHIMIZUf33b8932016-01-25 18:43:32 -0800241 } else if (resource instanceof ContinuousResource) {
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700242 if (!continuousTxStore.release((ContinuousResource) resource, consumer)) {
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800243 return abortTransaction(tx);
244 }
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700245 }
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700246 }
Sho SHIMIZU1e0a34c2015-11-02 16:52:29 -0800247
Madan Jampani3780d4b2016-04-04 18:18:24 -0700248 return tx.commit().join() == CommitStatus.SUCCESS;
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700249 }
250
Sho SHIMIZUdd3750c2016-02-01 11:37:04 -0800251 // computational complexity: O(1) if the resource is discrete type.
252 // O(n) if the resource is continuous type where n is the number of the children of
253 // the specified resource's parent
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700254 @Override
Sho SHIMIZU8fa670a2016-01-14 11:17:18 -0800255 public boolean isAvailable(Resource resource) {
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800256 checkNotNull(resource);
Sho SHIMIZUf33b8932016-01-25 18:43:32 -0800257 checkArgument(resource instanceof DiscreteResource || resource instanceof ContinuousResource);
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800258
Sho SHIMIZUf33b8932016-01-25 18:43:32 -0800259 if (resource instanceof DiscreteResource) {
HIGUCHI Yuta6f828c32016-01-20 18:11:05 -0800260 // check if already consumed
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700261 return discreteStore.isAvailable((DiscreteResource) resource);
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800262 } else {
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700263 return continuousStore.isAvailable((ContinuousResource) resource);
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800264 }
265 }
266
Sho SHIMIZUdd3750c2016-02-01 11:37:04 -0800267 // computational complexity: O(n + m) where n is the number of entries in discreteConsumers
268 // and m is the number of allocations for all continuous resources
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800269 @Override
Sho SHIMIZU8fa670a2016-01-14 11:17:18 -0800270 public Collection<Resource> getResources(ResourceConsumer consumer) {
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700271 checkNotNull(consumer);
272
273 // NOTE: getting all entries may become performance bottleneck
274 // TODO: revisit for better backend data structure
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700275 Stream<DiscreteResource> discrete = discreteStore.getResources(consumer);
276 Stream<ContinuousResource> continuous = continuousStore.getResources(consumer);
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800277
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700278 return Stream.concat(discrete, continuous).collect(Collectors.toList());
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700279 }
280
Sho SHIMIZU82bfe992016-02-10 09:55:32 -0800281 // computational complexity: O(1)
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700282 @Override
Sho SHIMIZUdd3750c2016-02-01 11:37:04 -0800283 public Set<Resource> getChildResources(DiscreteResourceId parent) {
Sho SHIMIZUe7f4f3f2015-10-13 16:27:25 -0700284 checkNotNull(parent);
285
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700286 return ImmutableSet.<Resource>builder()
287 .addAll(discreteStore.getChildResources(parent))
288 .addAll(continuousStore.getChildResources(parent))
289 .build();
Sho SHIMIZUe7f4f3f2015-10-13 16:27:25 -0700290 }
291
Sho SHIMIZUdd3750c2016-02-01 11:37:04 -0800292 // computational complexity: O(n) where n is the number of the children of the parent
Sho SHIMIZUe7f4f3f2015-10-13 16:27:25 -0700293 @Override
Sho SHIMIZUdd3750c2016-02-01 11:37:04 -0800294 public <T> Collection<Resource> getAllocatedResources(DiscreteResourceId parent, Class<T> cls) {
Sho SHIMIZU1f5e5912015-08-10 17:00:00 -0700295 checkNotNull(parent);
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700296 checkNotNull(cls);
297
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700298 Stream<DiscreteResource> discrete = discreteStore.getAllocatedResources(parent, cls);
299 Stream<ContinuousResource> continuous = continuousStore.getAllocatedResources(parent, cls);
Sho SHIMIZU6c9e33a2016-01-07 18:45:27 -0800300
301 return Stream.concat(discrete, continuous).collect(Collectors.toList());
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700302 }
Sho SHIMIZUd29847f2015-08-13 09:10:59 -0700303
304 /**
305 * Abort the transaction.
306 *
307 * @param tx transaction context
308 * @return always false
309 */
310 private boolean abortTransaction(TransactionContext tx) {
311 tx.abort();
312 return false;
313 }
314
315 /**
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700316 * Appends the values to the existing values associated with the specified key.
Sho SHIMIZU4568c412015-08-21 16:39:07 -0700317 * If the map already has all the given values, appending will not happen.
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700318 *
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700319 * @param key key specifying values
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700320 * @param values values to be appended
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700321 * @return true if the operation succeeds, false otherwise.
322 */
Sho SHIMIZUdd3750c2016-02-01 11:37:04 -0800323 // computational complexity: O(n) where n is the number of the specified value
Sho SHIMIZUa2d99eb2016-05-06 14:52:55 -0700324 private boolean register(TransactionalDiscreteResourceStore discreteTxStore,
325 TransactionalContinuousResourceStore continuousTxStore,
326 DiscreteResourceId key, List<Resource> values) {
Sho SHIMIZU03be2662016-05-04 09:38:45 -0700327 // it's assumed that the passed "values" is non-empty
328
329 // This is 2-pass scan. Nicer to have 1-pass scan
330 List<DiscreteResource> discreteValues = values.stream()
331 .filter(x -> x instanceof DiscreteResource)
332 .map(x -> (DiscreteResource) x)
333 .collect(Collectors.toList());
334 List<ContinuousResource> continuousValues = values.stream()
335 .filter(x -> x instanceof ContinuousResource)
336 .map(x -> (ContinuousResource) x)
337 .collect(Collectors.toList());
338
Sho SHIMIZUa2d99eb2016-05-06 14:52:55 -0700339 return discreteTxStore.register(key, discreteValues)
340 && continuousTxStore.register(key, continuousValues);
Sho SHIMIZUba41fc12015-08-12 15:43:22 -0700341 }
342
343 /**
Sho SHIMIZUba1f83b2015-10-14 08:11:20 -0700344 * Removes the values from the existing values associated with the specified key.
Sho SHIMIZU5618ee52015-08-21 17:19:44 -0700345 * If the map doesn't contain the given values, removal will not happen.
Sho SHIMIZU2d8a13a2015-08-18 22:37:41 -0700346 *
Sho SHIMIZU22fb2832016-05-06 11:44:03 -0700347 * @param discreteTxStore map holding multiple discrete resources for a key
348 * @param continuousTxStore map holding multiple continuous resources for a key
349 * @param key key specifying values
350 * @param values values to be removed
Sho SHIMIZU2d8a13a2015-08-18 22:37:41 -0700351 * @return true if the operation succeeds, false otherwise
352 */
Sho SHIMIZUa2d99eb2016-05-06 14:52:55 -0700353 private boolean unregister(TransactionalDiscreteResourceStore discreteTxStore,
354 TransactionalContinuousResourceStore continuousTxStore,
355 DiscreteResourceId key, List<Resource> values) {
Sho SHIMIZU03be2662016-05-04 09:38:45 -0700356 // it's assumed that the passed "values" is non-empty
357
358 // This is 2-pass scan. Nicer to have 1-pass scan
359 List<DiscreteResource> discreteValues = values.stream()
360 .filter(x -> x instanceof DiscreteResource)
361 .map(x -> (DiscreteResource) x)
362 .collect(Collectors.toList());
363 List<ContinuousResource> continuousValues = values.stream()
364 .filter(x -> x instanceof ContinuousResource)
365 .map(x -> (ContinuousResource) x)
366 .collect(Collectors.toList());
367
Sho SHIMIZUa2d99eb2016-05-06 14:52:55 -0700368 return discreteTxStore.unregister(key, discreteValues)
369 && continuousTxStore.unregister(key, continuousValues);
Sho SHIMIZU03be2662016-05-04 09:38:45 -0700370 }
Sho SHIMIZU78ee25c2015-07-16 15:54:14 -0700371}