Mark potentially-static methods as static
[genius.git] / mdsalutil / mdsalutil-api / src / main / java / org / opendaylight / genius / utils / clustering / EntityOwnershipUtils.java
1 /*
2  * Copyright (c) 2017 Inocybe Technologies 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.genius.utils.clustering;
9
10 import com.google.common.util.concurrent.Futures;
11 import com.google.common.util.concurrent.ListenableFuture;
12 import java.util.Collections;
13 import java.util.List;
14 import java.util.Objects;
15 import java.util.concurrent.Callable;
16 import javax.inject.Inject;
17 import org.opendaylight.genius.utils.SystemPropertyReader;
18 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
19 import org.opendaylight.mdsal.eos.binding.api.Entity;
20 import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipService;
21 import org.opendaylight.mdsal.eos.common.api.EntityOwnershipState;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
24
25 /**
26  * EntityOwnershipService utilities.
27  *
28  * @author Thomas Pantelis
29  */
30 public class EntityOwnershipUtils {
31     private static final Logger LOG = LoggerFactory.getLogger(EntityOwnershipUtils.class);
32
33     private final EntityOwnershipService entityOwnershipService;
34
35     @Inject
36     public EntityOwnershipUtils(EntityOwnershipService entityOwnershipService) {
37         this.entityOwnershipService = Objects.requireNonNull(entityOwnershipService);
38     }
39
40     public EntityOwnershipService getEntityOwnershipService() {
41         return entityOwnershipService;
42     }
43
44     /**
45      * Checks if the local node is the owner of an entity.
46      *
47      * @param entityType the entity type
48      * @param entityName the entity name
49      * @return true is the owner, false otherwise
50      */
51     public boolean isEntityOwner(String entityType, String entityName) {
52         return isEntityOwner(new Entity(entityType, entityName));
53     }
54
55     /**
56      * Checks if the local node is the owner of an entity.
57      *
58      * @param entity the entity
59      * @return true is the owner, false otherwise
60      */
61     public boolean isEntityOwner(Entity entity) {
62         return isEntityOwner(entity, SystemPropertyReader.Cluster.getSleepTimeBetweenRetries(),
63                 SystemPropertyReader.Cluster.getMaxRetries());
64     }
65
66     /**
67      * Checks if the local node is the owner of an entity.
68      *
69      * @param entity the entity
70      * @param sleepBetweenRetries the busy wait interval in millis if the entity is not yet present
71      * @param tries the total number of busy wait tries
72      * @return true is the owner, false otherwise
73      */
74     public boolean isEntityOwner(Entity entity, long sleepBetweenRetries, int tries) {
75         while (true) {
76             java.util.Optional<EntityOwnershipState> entityState = entityOwnershipService.getOwnershipState(entity);
77             if (entityState.isPresent()) {
78                 EntityOwnershipState entityOwnershipState = entityState.get();
79                 return entityOwnershipState == EntityOwnershipState.IS_OWNER;
80             }
81
82             tries--;
83
84             LOG.debug("EntityOwnershipState for {} is not yet available. {} tries left", entity, tries);
85
86             if (tries > 0) {
87                 try {
88                     Thread.sleep(sleepBetweenRetries);
89                 } catch (InterruptedException e) {
90                     continue;
91                 }
92             } else {
93                 break;
94             }
95         }
96
97         return false;
98     }
99
100     /**
101      * Runs a job task if the local node is the owner of an entity.
102      *
103      * @param entityType the entity type
104      * @param entityName the entity name
105      * @param coordinator the JobCoordinator on which to run the job task
106      * @param jobDesc description of the job for logging
107      * @param job the job task
108      */
109     public void runOnlyInOwnerNode(String entityType, String entityName, JobCoordinator coordinator, String jobDesc,
110             Runnable job) {
111         final Entity entity = new Entity(entityType, entityName);
112         coordinator.enqueueJob(getEntityIdentifierString(entityType, entityName), () -> {
113             if (isEntityOwner(entity)) {
114                 LOG.debug("Running job {} for {}", jobDesc, entity);
115                 job.run();
116             } else {
117                 LOG.debug("runOnlyInOwnerNode: job {} was not run as I'm not the owner of {} ", jobDesc, entity);
118             }
119
120             return Collections.singletonList(Futures.immediateFuture(null));
121         });
122     }
123
124     /**
125      * Runs a job task if the local node is the owner of an entity.
126      *
127      * @param entityType the entity type
128      * @param entityName the entity name
129      * @param coordinator the JobCoordinator on which to run the job
130      * @param jobKey the job key
131      * @param jobDesc description of the job for logging
132      * @param job the job task
133      */
134     public void runOnlyInOwnerNode(String entityType, String entityName, JobCoordinator coordinator,
135             String jobKey, String jobDesc, Callable<List<? extends ListenableFuture<?>>> job) {
136         final Entity entity = new Entity(entityType, entityName);
137         coordinator.enqueueJob(getEntityIdentifierString(entityType, entityName), () -> {
138             if (isEntityOwner(entity)) {
139                 LOG.debug("Scheduling job {} for {}", jobDesc, entity);
140                 coordinator.enqueueJob(jobKey, job, SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
141             } else {
142                 LOG.debug("runOnlyInOwnerNode: job {} was not run as I'm not the owner of {} ", jobDesc, entity);
143             }
144
145             return Collections.singletonList(Futures.immediateFuture(null));
146         });
147     }
148
149     // see GENIUS-237 why we do this optimization instead of using Entity.toString()
150     private static String getEntityIdentifierString(String entityType, String entityName) {
151         return new StringBuilder(entityType.length() + entityName.length()).append(entityType).append(entityName)
152                 .toString();
153     }
154 }