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.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.EntityOwnershipStateChange;
20 import org.opendaylight.mdsal.eos.dom.api.DOMEntity;
21 import org.opendaylight.mdsal.singleton.api.ServiceGroupIdentifier;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
26 * Intermediate place-holder to catch user requests while asynchronous shutdown of previous incarnation of
27 * a {@link ServiceGroup} finishes.
29 final class PlaceholderServiceGroup extends ServiceGroup {
30 private static final Logger LOG = LoggerFactory.getLogger(PlaceholderServiceGroup.class);
32 private final List<ServiceRegistration> services = new ArrayList<>(0);
33 private final ServiceGroup previous;
34 private final ListenableFuture<?> closeFuture;
36 private volatile ServiceGroup successor;
38 PlaceholderServiceGroup(final ServiceGroup previous, final ListenableFuture<?> closeFuture) {
39 this.previous = requireNonNull(previous);
40 this.closeFuture = requireNonNull(closeFuture);
44 public ServiceGroupIdentifier getIdentifier() {
45 return previous.getIdentifier();
49 void initialize() throws CandidateAlreadyRegisteredException {
50 throw new UnsupportedOperationException("This should never be invoked");
54 void registerService(final ServiceRegistration reg) {
57 LOG.debug("{}: added service {}", this, reg.getInstance());
61 ListenableFuture<?> unregisterService(final ServiceRegistration reg) {
64 LOG.debug("{}: removed service {}", this, reg.getInstance());
69 void ownershipChanged(final DOMEntity entity, final EntityOwnershipStateChange change, final boolean inJeopardy) {
70 // This really should not happen, but let's be defensive
71 final var local = successor;
72 (local == null ? previous : local).ownershipChanged(entity, change, inJeopardy);
76 ListenableFuture<?> closeClusterSingletonGroup() {
77 final var local = successor;
78 return local == null ? closeFuture : local.closeClusterSingletonGroup();
81 // Note: this is a leaked structure, the caller can reuse it at will, but has to regard
82 List<ServiceRegistration> getServices() {
84 LOG.trace("{}: returning services {}", this, services);
88 void setSuccessor(final ServiceGroup successor) {
90 this.successor = verifyNotNull(successor);
91 LOG.debug("{}: successor set to {}", this, successor);
94 private void verifyNoSuccessor() {
95 verify(successor == null, "Placeholder already superseded by %s", successor);
99 public String toString() {
100 return MoreObjects.toStringHelper(this).add("id", getIdentifier()).toString();