Rename singleton service components
[mdsal.git] / singleton-service / mdsal-singleton-impl / src / main / java / org / opendaylight / mdsal / singleton / impl / PlaceholderServiceGroup.java
1 /*
2  * Copyright (c) 2017 Pantheon Technologies, s.r.o. 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.mdsal.singleton.impl;
9
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;
13
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;
24
25 /**
26  * Intermediate place-holder to catch user requests while asynchronous shutdown of previous incarnation of
27  * a {@link ServiceGroup} finishes.
28  */
29 final class PlaceholderServiceGroup extends ServiceGroup {
30     private static final Logger LOG = LoggerFactory.getLogger(PlaceholderServiceGroup.class);
31
32     private final List<ServiceRegistration> services = new ArrayList<>(0);
33     private final ServiceGroup previous;
34     private final ListenableFuture<?> closeFuture;
35
36     private volatile ServiceGroup successor;
37
38     PlaceholderServiceGroup(final ServiceGroup previous, final ListenableFuture<?> closeFuture) {
39         this.previous = requireNonNull(previous);
40         this.closeFuture = requireNonNull(closeFuture);
41     }
42
43     @Override
44     public ServiceGroupIdentifier getIdentifier() {
45         return previous.getIdentifier();
46     }
47
48     @Override
49     void initialize() throws CandidateAlreadyRegisteredException {
50         throw new UnsupportedOperationException("This should never be invoked");
51     }
52
53     @Override
54     void registerService(final ServiceRegistration reg) {
55         verifyNoSuccessor();
56         services.add(reg);
57         LOG.debug("{}: added service {}", this, reg.getInstance());
58     }
59
60     @Override
61     ListenableFuture<?> unregisterService(final ServiceRegistration reg) {
62         verifyNoSuccessor();
63         services.remove(reg);
64         LOG.debug("{}: removed service {}", this, reg.getInstance());
65         return null;
66     }
67
68     @Override
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);
73     }
74
75     @Override
76     ListenableFuture<?> closeClusterSingletonGroup() {
77         final var local = successor;
78         return local == null ? closeFuture : local.closeClusterSingletonGroup();
79     }
80
81     // Note: this is a leaked structure, the caller can reuse it at will, but has to regard
82     List<ServiceRegistration> getServices() {
83         verifyNoSuccessor();
84         LOG.trace("{}: returning services {}", this, services);
85         return services;
86     }
87
88     void setSuccessor(final ServiceGroup successor) {
89         verifyNoSuccessor();
90         this.successor = verifyNotNull(successor);
91         LOG.debug("{}: successor set to {}", this, successor);
92     }
93
94     private void verifyNoSuccessor() {
95         verify(successor == null, "Placeholder already superseded by %s", successor);
96     }
97
98     @Override
99     public String toString() {
100         return MoreObjects.toStringHelper(this).add("id", getIdentifier()).toString();
101     }
102 }