BUG-5280: handle TransactionPurgeRequest replay
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / main / java / org / opendaylight / controller / cluster / databroker / actors / dds / SimpleShardBackendResolver.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.controller.cluster.databroker.actors.dds;
9
10 import com.google.common.base.Preconditions;
11 import java.util.concurrent.CompletionStage;
12 import javax.annotation.concurrent.ThreadSafe;
13 import org.opendaylight.controller.cluster.access.client.BackendInfoResolver;
14 import org.opendaylight.controller.cluster.access.concepts.ClientIdentifier;
15 import org.opendaylight.controller.cluster.datastore.utils.ActorContext;
16 import org.slf4j.Logger;
17 import org.slf4j.LoggerFactory;
18
19 /**
20  * {@link BackendInfoResolver} implementation for static shard configuration based on ShardManager. Unlike the full
21  * {@link ModuleShardBackendResolver}, this resolver is used in situations where the client corresponds exactly to one
22  * backend shard, e.g. there is only one fixed cookie assigned and the operation path is not consulted at all.
23  *
24  * @author Robert Varga
25  */
26 @ThreadSafe
27 final class SimpleShardBackendResolver extends AbstractShardBackendResolver {
28     private static final Logger LOG = LoggerFactory.getLogger(SimpleShardBackendResolver.class);
29
30     private final String shardName;
31
32     private volatile ShardState state;
33
34     // FIXME: we really need just ActorContext.findPrimaryShardAsync()
35     SimpleShardBackendResolver(final ClientIdentifier clientId, final ActorContext actorContext,
36             final String shardName) {
37         super(clientId, actorContext);
38         this.shardName = Preconditions.checkNotNull(shardName);
39     }
40
41     private CompletionStage<ShardBackendInfo> getBackendInfo(final long cookie) {
42         Preconditions.checkArgument(cookie == 0);
43
44         ShardState local = state;
45         if (local == null) {
46             synchronized (this) {
47                 local = state;
48                 if (local == null) {
49                     local = resolveBackendInfo(shardName, 0);
50                     state = local;
51                 }
52             }
53         }
54
55         return local.getStage();
56     }
57
58     @Override
59     public CompletionStage<ShardBackendInfo> getBackendInfo(final Long cookie) {
60         return getBackendInfo(cookie.longValue());
61     }
62
63     @Override
64     public CompletionStage<? extends ShardBackendInfo> refreshBackendInfo(final Long cookie,
65             final ShardBackendInfo staleInfo) {
66
67         final ShardState existing = state;
68         if (existing != null) {
69             if (!staleInfo.equals(existing.getResult())) {
70                 return existing.getStage();
71             }
72
73             synchronized (this) {
74                 LOG.debug("Invalidating backend information {}", staleInfo);
75                 flushCache(shardName);
76                 LOG.trace("Invalidated cache %s", staleInfo);
77                 state = null;
78             }
79         }
80
81         return getBackendInfo(cookie);
82     }
83 }