Merge "Bug 5924 - Reuse Threads using ThreadPool in SystemNotificationListenerImpl"
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / role / RoleContextImpl.java
1 /**
2  * Copyright (c) 2015 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.openflowplugin.impl.role;
9
10 import com.google.common.base.Preconditions;
11 import java.util.concurrent.Semaphore;
12 import java.util.concurrent.TimeUnit;
13 import javax.annotation.Nonnull;
14 import javax.annotation.Nullable;
15 import org.opendaylight.controller.md.sal.common.api.clustering.CandidateAlreadyRegisteredException;
16 import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
17 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipCandidateRegistration;
18 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
19 import org.opendaylight.openflowplugin.api.openflow.OFPContext;
20 import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
21 import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
22 import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
23 import org.opendaylight.openflowplugin.api.openflow.role.RoleContext;
24 import org.opendaylight.openflowplugin.impl.rpc.AbstractRequestContext;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SalRoleService;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28
29 /**
30  * Role context hold information about entity ownership registration,
31  * register and unregister candidate (main and tx)
32  */
33 class RoleContextImpl implements RoleContext {
34
35     private static final Logger LOG = LoggerFactory.getLogger(RoleContextImpl.class);
36     private static final int TIMEOUT = 12;
37
38     private final DeviceInfo deviceInfo;
39     private final EntityOwnershipService entityOwnershipService;
40     private volatile EntityOwnershipCandidateRegistration entityOwnershipCandidateRegistration = null;
41     private volatile EntityOwnershipCandidateRegistration txEntityOwnershipCandidateRegistration = null;
42
43     private final Entity entity;
44     private final Entity txEntity;
45
46     private SalRoleService salRoleService = null;
47
48     private final Semaphore roleChangeGuard = new Semaphore(1, true);
49
50     private final LifecycleConductor conductor;
51     private volatile CONTEXT_STATE contextState;
52
53     RoleContextImpl(final DeviceInfo deviceInfo, final EntityOwnershipService entityOwnershipService, final Entity entity, final Entity txEntity, final LifecycleConductor lifecycleConductor) {
54         this.entityOwnershipService = entityOwnershipService;
55         this.entity = entity;
56         this.txEntity = txEntity;
57         this.deviceInfo = deviceInfo;
58         this.conductor = lifecycleConductor;
59         contextState = CONTEXT_STATE.INITIALIZATION;
60     }
61
62     @Override
63     public boolean initialization() {
64         LOG.info("Initialization main candidate for node {}", deviceInfo.getNodeId());
65         contextState = CONTEXT_STATE.WORKING;
66         return registerCandidate(this.entity);
67     }
68
69     @Override
70     public void unregisterAllCandidates() {
71         LOG.info("Role context closed, unregistering all candidates for ownership for node {}", deviceInfo.getNodeId());
72         if (isMainCandidateRegistered()) {
73             unregisterCandidate(this.entity);
74         }
75         if (isTxCandidateRegistered()) {
76             unregisterCandidate(this.txEntity);
77         }
78     }
79
80     @Nullable
81     @Override
82     public <T> RequestContext<T> createRequestContext() {
83         return new AbstractRequestContext<T>(conductor.reserveXidForDeviceMessage(deviceInfo)) {
84             @Override
85             public void close() {
86             }
87         };
88     }
89
90     @Override
91     public void setSalRoleService(@Nonnull final SalRoleService salRoleService) {
92         Preconditions.checkNotNull(salRoleService);
93         this.salRoleService = salRoleService;
94     }
95
96     @Override
97     public SalRoleService getSalRoleService() {
98         return this.salRoleService;
99     }
100
101     @Override
102     public Entity getEntity() {
103         return this.entity;
104     }
105
106     @Override
107     public Entity getTxEntity() {
108         return this.txEntity;
109     }
110
111     @Override
112     public DeviceInfo getDeviceInfo() {
113         return deviceInfo;
114     }
115
116     @Override
117     public boolean isMainCandidateRegistered() {
118         return entityOwnershipCandidateRegistration != null;
119     }
120
121     @Override
122     public boolean isTxCandidateRegistered() {
123         return txEntityOwnershipCandidateRegistration != null;
124     }
125
126     @Override
127     public boolean registerCandidate(final Entity entity_) {
128         boolean permit = false;
129         try {
130             permit = roleChangeGuard.tryAcquire(TIMEOUT, TimeUnit.SECONDS);
131             if(permit) {
132                 LOG.debug("Register candidate for entity {}", entity_);
133                 if (entity_.equals(this.entity)) {
134                     entityOwnershipCandidateRegistration = entityOwnershipService.registerCandidate(entity_);
135                 } else {
136                     txEntityOwnershipCandidateRegistration = entityOwnershipService.registerCandidate(entity_);
137                 }
138             } else {
139                 return false;
140             }
141         } catch (final CandidateAlreadyRegisteredException e) {
142             LOG.warn("Candidate for entity {} is already registered.", entity_.getType());
143             return false;
144         } catch (final InterruptedException e) {
145             LOG.warn("Cannot acquire semaphore for register entity {} candidate.", entity_.getType());
146             return false;
147         } finally {
148             if (permit) {
149                 roleChangeGuard.release();
150             }
151         }
152         return true;
153     }
154
155     @Override
156     public boolean unregisterCandidate(final Entity entity_) {
157         boolean permit = false;
158         try {
159             permit = roleChangeGuard.tryAcquire(TIMEOUT, TimeUnit.SECONDS);
160             if(permit) {
161                 if (entity_.equals(this.entity)) {
162                     if (entityOwnershipCandidateRegistration != null) {
163                         LOG.debug("Unregister candidate for entity {}", entity_);
164                         entityOwnershipCandidateRegistration.close();
165                         entityOwnershipCandidateRegistration = null;
166                     }
167                 } else {
168                     if (txEntityOwnershipCandidateRegistration != null) {
169                         LOG.debug("Unregister candidate for tx entity {}", entity_);
170                         txEntityOwnershipCandidateRegistration.close();
171                         txEntityOwnershipCandidateRegistration = null;
172                     }
173                 }
174             } else {
175                 return false;
176             }
177         } catch (final InterruptedException e) {
178             LOG.warn("Cannot acquire semaphore for unregister entity {} candidate.", entity_.getType());
179             return false;
180         } finally {
181             if (permit) {
182                 roleChangeGuard.release();
183             }
184         }
185         return true;
186     }
187
188     @Override
189     public void close() {
190         contextState = CONTEXT_STATE.TERMINATION;
191         unregisterAllCandidates();
192     }
193
194     public boolean isMaster(){
195         return (txEntityOwnershipCandidateRegistration != null && entityOwnershipCandidateRegistration != null);
196     }
197
198     @Override
199     public CONTEXT_STATE getState() {
200         return contextState;
201     }
202 }