blob: 30a6f26eb6a93a3bb6bbea5616c6f274d5a72ffa [file] [log] [blame]
Madan Jampani64689552015-02-17 10:00:27 -08001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Madan Jampanif4c88502016-01-21 12:35:36 -080017package org.onosproject.store.primitives.impl;
Madan Jampani64689552015-02-17 10:00:27 -080018
19import java.util.List;
20import java.util.Map;
Madan Jampanicadd70b2016-02-08 13:45:43 -080021import java.util.concurrent.CompletableFuture;
22import java.util.function.Function;
Madan Jampani50589ac2015-06-08 11:38:46 -070023import java.util.function.Supplier;
Madan Jampani64689552015-02-17 10:00:27 -080024
25import static com.google.common.base.Preconditions.*;
26
Madan Jampani74da78b2016-02-09 21:18:36 -080027import org.onosproject.store.primitives.MapUpdate;
Madan Jampanicadd70b2016-02-08 13:45:43 -080028import org.onosproject.store.primitives.TransactionId;
29import org.onosproject.store.primitives.resources.impl.CommitResult;
Madan Jampani3780d4b2016-04-04 18:18:24 -070030import org.onosproject.store.service.CommitStatus;
Madan Jampani50589ac2015-06-08 11:38:46 -070031import org.onosproject.store.service.ConsistentMapBuilder;
Madan Jampani64689552015-02-17 10:00:27 -080032import org.onosproject.store.service.Serializer;
33import org.onosproject.store.service.TransactionContext;
Madan Jampani64689552015-02-17 10:00:27 -080034import org.onosproject.store.service.TransactionalMap;
Madan Jampani64689552015-02-17 10:00:27 -080035
HIGUCHI Yutadc4394c2016-01-29 15:35:10 -080036import com.google.common.base.MoreObjects;
37import com.google.common.base.MoreObjects.ToStringHelper;
Madan Jampani64689552015-02-17 10:00:27 -080038import com.google.common.collect.Lists;
39import com.google.common.collect.Maps;
Madan Jampanibab51a42015-08-10 13:53:35 -070040import com.google.common.util.concurrent.Futures;
Madan Jampani64689552015-02-17 10:00:27 -080041
42/**
43 * Default TransactionContext implementation.
44 */
45public class DefaultTransactionContext implements TransactionContext {
Madan Jampanibff6d8f2015-03-31 16:53:47 -070046 private static final String TX_NOT_OPEN_ERROR = "Transaction Context is not open";
47
48 @SuppressWarnings("rawtypes")
49 private final Map<String, DefaultTransactionalMap> txMaps = Maps.newConcurrentMap();
Madan Jampani64689552015-02-17 10:00:27 -080050 private boolean isOpen = false;
Madan Jampanicadd70b2016-02-08 13:45:43 -080051 private final Function<Transaction, CompletableFuture<CommitResult>> transactionCommitter;
52 private final TransactionId transactionId;
Madan Jampani50589ac2015-06-08 11:38:46 -070053 private final Supplier<ConsistentMapBuilder> mapBuilderSupplier;
Madan Jampani64689552015-02-17 10:00:27 -080054
Madan Jampanicadd70b2016-02-08 13:45:43 -080055 public DefaultTransactionContext(TransactionId transactionId,
56 Function<Transaction, CompletableFuture<CommitResult>> transactionCommitter,
Madan Jampani50589ac2015-06-08 11:38:46 -070057 Supplier<ConsistentMapBuilder> mapBuilderSupplier) {
Madan Jampanibff6d8f2015-03-31 16:53:47 -070058 this.transactionId = transactionId;
Madan Jampanicadd70b2016-02-08 13:45:43 -080059 this.transactionCommitter = checkNotNull(transactionCommitter);
Madan Jampani50589ac2015-06-08 11:38:46 -070060 this.mapBuilderSupplier = checkNotNull(mapBuilderSupplier);
Madan Jampanibff6d8f2015-03-31 16:53:47 -070061 }
62
63 @Override
Madan Jampanicadd70b2016-02-08 13:45:43 -080064 public TransactionId transactionId() {
Madan Jampanibff6d8f2015-03-31 16:53:47 -070065 return transactionId;
Madan Jampani64689552015-02-17 10:00:27 -080066 }
67
68 @Override
69 public void begin() {
Madan Jampanibff6d8f2015-03-31 16:53:47 -070070 checkState(!isOpen, "Transaction Context is already open");
Madan Jampani64689552015-02-17 10:00:27 -080071 isOpen = true;
72 }
73
74 @Override
Madan Jampanibff6d8f2015-03-31 16:53:47 -070075 public boolean isOpen() {
76 return isOpen;
77 }
78
79 @Override
Ray Milkey8dc82082015-02-20 16:22:38 -080080 @SuppressWarnings("unchecked")
Madan Jampanibff6d8f2015-03-31 16:53:47 -070081 public <K, V> TransactionalMap<K, V> getTransactionalMap(String mapName,
Madan Jampani64689552015-02-17 10:00:27 -080082 Serializer serializer) {
Madan Jampani64689552015-02-17 10:00:27 -080083 checkState(isOpen, TX_NOT_OPEN_ERROR);
Madan Jampanibff6d8f2015-03-31 16:53:47 -070084 checkNotNull(mapName);
85 checkNotNull(serializer);
Madan Jampani538be742016-02-10 14:55:38 -080086 return txMaps.computeIfAbsent(mapName, name -> {
87 ConsistentMapBuilder mapBuilder = (ConsistentMapBuilder) mapBuilderSupplier.get()
88 .withName(name)
89 .withSerializer(serializer);
90 return new DefaultTransactionalMap<>(
Madan Jampanibff6d8f2015-03-31 16:53:47 -070091 name,
Madan Jampani538be742016-02-10 14:55:38 -080092 mapBuilder.buildAsyncMap(),
Madan Jampanibff6d8f2015-03-31 16:53:47 -070093 this,
Madan Jampani538be742016-02-10 14:55:38 -080094 serializer);
95 });
Madan Jampani64689552015-02-17 10:00:27 -080096 }
97
Ray Milkey8dc82082015-02-20 16:22:38 -080098 @SuppressWarnings("unchecked")
Madan Jampani64689552015-02-17 10:00:27 -080099 @Override
Madan Jampani3780d4b2016-04-04 18:18:24 -0700100 public CompletableFuture<CommitStatus> commit() {
Madan Jampanibab51a42015-08-10 13:53:35 -0700101 // TODO: rework commit implementation to be more intuitive
Madan Jampani64689552015-02-17 10:00:27 -0800102 checkState(isOpen, TX_NOT_OPEN_ERROR);
Madan Jampani3780d4b2016-04-04 18:18:24 -0700103 CommitStatus status;
Madan Jampani64689552015-02-17 10:00:27 -0800104 try {
Madan Jampanicadd70b2016-02-08 13:45:43 -0800105 List<MapUpdate<String, byte[]>> updates = Lists.newLinkedList();
106 txMaps.values().forEach(m -> updates.addAll(m.toMapUpdates()));
107 Transaction transaction = new Transaction(transactionId, updates);
Madan Jampani3780d4b2016-04-04 18:18:24 -0700108 status = Futures.getUnchecked(transactionCommitter.apply(transaction)) == CommitResult.OK
109 ? CommitStatus.SUCCESS : CommitStatus.FAILURE;
Sho SHIMIZUd936b422015-11-02 16:38:18 -0800110 } catch (Exception e) {
111 abort();
Madan Jampani3780d4b2016-04-04 18:18:24 -0700112 status = CommitStatus.FAILURE;
Madan Jampani64689552015-02-17 10:00:27 -0800113 } finally {
114 isOpen = false;
115 }
Madan Jampani3780d4b2016-04-04 18:18:24 -0700116 return CompletableFuture.completedFuture(status);
Madan Jampani64689552015-02-17 10:00:27 -0800117 }
118
119 @Override
Madan Jampanibff6d8f2015-03-31 16:53:47 -0700120 public void abort() {
Madan Jampanibab51a42015-08-10 13:53:35 -0700121 if (isOpen) {
122 try {
Madan Jampani74da78b2016-02-09 21:18:36 -0800123 txMaps.values().forEach(m -> m.abort());
Madan Jampanibab51a42015-08-10 13:53:35 -0700124 } finally {
125 isOpen = false;
126 }
127 }
Madan Jampani64689552015-02-17 10:00:27 -0800128 }
HIGUCHI Yutadc4394c2016-01-29 15:35:10 -0800129
130 @Override
131 public String toString() {
132 ToStringHelper s = MoreObjects.toStringHelper(this)
133 .add("transactionId", transactionId)
134 .add("isOpen", isOpen);
135
136 txMaps.entrySet().forEach(e -> {
137 s.add(e.getKey(), e.getValue());
138 });
139 return s.toString();
140 }
Madan Jampanicadd70b2016-02-08 13:45:43 -0800141
142 @Override
143 public String name() {
144 return transactionId.toString();
145 }
Madan Jampani02b7fb82015-05-01 13:01:20 -0700146}