2 * Copyright (c) 2017 Pantheon Technologies, s.r.o. and others. All rights reserved.
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
8 package org.opendaylight.mdsal.singleton.dom.impl;
10 import static com.google.common.base.Verify.verify;
11 import static com.google.common.base.Verify.verifyNotNull;
12 import static java.util.Objects.requireNonNull;
14 import com.google.common.base.MoreObjects;
15 import com.google.common.util.concurrent.ListenableFuture;
16 import java.util.ArrayList;
17 import java.util.List;
18 import org.opendaylight.mdsal.eos.common.api.CandidateAlreadyRegisteredException;
19 import org.opendaylight.mdsal.eos.common.api.GenericEntity;
20 import org.opendaylight.mdsal.eos.common.api.GenericEntityOwnershipChange;
21 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration;
22 import org.opendaylight.yangtools.concepts.Path;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
27 * Intermediate place-holder to catch user requests while asynchronous shutdown of previous incarnation of
28 * a {@link ClusterSingletonServiceGroup} finishes.
30 final class PlaceholderGroup<P extends Path<P>, E extends GenericEntity<P>,
31 C extends GenericEntityOwnershipChange<P, E>> extends ClusterSingletonServiceGroup<P, E, C> {
32 private static final Logger LOG = LoggerFactory.getLogger(PlaceholderGroup.class);
34 private final List<ClusterSingletonServiceRegistration> services = new ArrayList<>(0);
35 private final ClusterSingletonServiceGroup<P, E, C> previous;
36 private final ListenableFuture<?> closeFuture;
38 private volatile ClusterSingletonServiceGroup<P, E, C> successor;
40 PlaceholderGroup(final ClusterSingletonServiceGroup<P, E, C> previous, final ListenableFuture<?> closeFuture) {
41 this.previous = requireNonNull(previous);
42 this.closeFuture = requireNonNull(closeFuture);
46 public String getIdentifier() {
47 return previous.getIdentifier();
51 void initialize() throws CandidateAlreadyRegisteredException {
52 throw new UnsupportedOperationException("This should never be invoked");
56 void registerService(final ClusterSingletonServiceRegistration reg) {
59 LOG.debug("{}: added service {}", this, reg.getInstance());
63 ListenableFuture<?> unregisterService(final ClusterSingletonServiceRegistration reg) {
66 LOG.debug("{}: removed service {}", this, reg.getInstance());
71 void ownershipChanged(final C ownershipChange) {
72 // This really should not happen, but let's be defensive
73 final ClusterSingletonServiceGroup<P, E, C> local = successor;
74 (local == null ? previous : local).ownershipChanged(ownershipChange);
78 ListenableFuture<?> closeClusterSingletonGroup() {
79 final ClusterSingletonServiceGroup<P, E, C> local = successor;
80 return local == null ? closeFuture : local.closeClusterSingletonGroup();
83 // Note: this is a leaked structure, the caller can reuse it at will, but has to regard
84 List<ClusterSingletonServiceRegistration> getServices() {
86 LOG.trace("{}: returning services {}", this, services);
90 void setSuccessor(final ClusterSingletonServiceGroup<P, E, C> successor) {
92 this.successor = verifyNotNull(successor);
93 LOG.debug("{}: successor set to {}", this, successor);
96 private void verifyNoSuccessor() {
97 verify(successor == null, "Placeholder already superseded by %s", successor);
101 public String toString() {
102 return MoreObjects.toStringHelper(this).add("id", getIdentifier()).toString();