9741a6bda49b1880caf44f112ee3dc6b72cd0851
[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         final ShardState existing = state;
45         if (existing != null) {
46             return existing.getStage();
47         }
48
49         synchronized (this) {
50             final ShardState recheck = state;
51             if (recheck != null) {
52                 return recheck.getStage();
53             }
54
55             final ShardState newState = resolveBackendInfo(shardName, 0);
56             state = newState;
57
58             final CompletionStage<ShardBackendInfo> stage = newState.getStage();
59             stage.whenComplete((info, failure) -> {
60                 if (failure != null) {
61                     synchronized (SimpleShardBackendResolver.this) {
62                         if (state == newState) {
63                             state = null;
64                         }
65                     }
66                 }
67             });
68
69             return stage;
70         }
71     }
72
73     @Override
74     public CompletionStage<ShardBackendInfo> getBackendInfo(final Long cookie) {
75         return getBackendInfo(cookie.longValue());
76     }
77
78     @Override
79     public CompletionStage<? extends ShardBackendInfo> refreshBackendInfo(final Long cookie,
80             final ShardBackendInfo staleInfo) {
81
82         final ShardState existing = state;
83         if (existing != null) {
84             if (!staleInfo.equals(existing.getResult())) {
85                 return existing.getStage();
86             }
87
88             synchronized (this) {
89                 LOG.debug("Invalidating backend information {}", staleInfo);
90                 flushCache(shardName);
91                 LOG.trace("Invalidated cache {}", staleInfo);
92                 state = null;
93             }
94         }
95
96         return getBackendInfo(cookie);
97     }
98 }