ovsdb enable checkstyle on error
[ovsdb.git] / southbound / southbound-impl / src / main / java / org / opendaylight / ovsdb / southbound / reconciliation / ReconciliationManager.java
1 /*
2  * Copyright (c) 2016 Brocade Communications 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.ovsdb.southbound.reconciliation;
9
10 import com.google.common.util.concurrent.ThreadFactoryBuilder;
11 import java.util.concurrent.ExecutorService;
12 import java.util.concurrent.Executors;
13 import java.util.concurrent.ScheduledExecutorService;
14 import java.util.concurrent.ThreadFactory;
15 import java.util.concurrent.TimeUnit;
16 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
17 import org.opendaylight.yangtools.util.concurrent.SpecialExecutors;
18 import org.slf4j.Logger;
19 import org.slf4j.LoggerFactory;
20
21 /**
22  * This class provides the implementation of ovsdb southbound plugins
23  * configuration reconciliation engine. This engine provide interfaces
24  * to enqueue (one time retry)/ enqueueForRetry(periodic retry)/ dequeue
25  * (remove from retry queue) reconciliation task. Reconciliation task can
26  * be a connection reconciliation or configuration reconciliation of any
27  * ovsdb managed resource like bridge, termination point etc. This engine
28  * execute all the reconciliation task through a fixed size thread pool.
29  * If submitted task need to be retry after a periodic interval they are
30  * submitted to a single thread executor to periodically wake up and check
31  * if task is ready for execution.
32  * Ideally, addition of any type of reconciliation task should not require
33  * any change in this reconciliation manager execution engine.
34  * <p>
35  * 3-Node Cluster:
36  * Reconciliation manager is agnostic of whether it's running in single
37  * node cluster or 3-node cluster. It's a responsibility of the task
38  * submitter to make sure that it submit the task for reconciliation only
39  * if it's an owner of that device EXCEPT controller initiated Connection.
40  * Reconciliation of controller initiated connection should be done by all
41  * the 3-nodes in the cluster, because connection to individual controller
42  * can be interrupted for various reason.
43  * </p>
44  */
45 public class ReconciliationManager implements AutoCloseable {
46     private static final Logger LOG = LoggerFactory.getLogger(ReconciliationManager.class);
47
48     private static final int NO_OF_RECONCILER = 10;
49     private static final int RECON_TASK_QUEUE_SIZE = 5000;
50
51     private final DataBroker db;
52     private final ExecutorService reconcilers;
53     private final ScheduledExecutorService taskTriager;
54
55     private final ReconciliationTaskManager reconTaskManager = new ReconciliationTaskManager();
56
57     public ReconciliationManager(final DataBroker db) {
58         this.db = db;
59         reconcilers = SpecialExecutors.newBoundedCachedThreadPool(NO_OF_RECONCILER, RECON_TASK_QUEUE_SIZE,
60                 "ovsdb-reconciler");
61
62         ThreadFactory threadFact = new ThreadFactoryBuilder()
63                 .setNameFormat("ovsdb-recon-task-triager-%d").build();
64         taskTriager = Executors.newSingleThreadScheduledExecutor(threadFact);
65     }
66
67     public boolean isEnqueued(final ReconciliationTask task) {
68         return reconTaskManager.isTaskQueued(task);
69     }
70
71     public void enqueue(final ReconciliationTask task) {
72         LOG.trace("Reconciliation task submitted for execution {}",task);
73         reconTaskManager.cacheTask(task, reconcilers.submit(task));
74     }
75
76     public void enqueueForRetry(final ReconciliationTask task) {
77         LOG.trace("Reconciliation task re-queued for re-execution {}",task);
78         reconTaskManager.cacheTask(task, taskTriager.schedule(
79                 new Runnable() {
80                     @Override
81                     public void run() {
82                         task.checkReadinessAndProcess();
83                     }
84                 }, task.retryDelayInMills(), TimeUnit.MILLISECONDS
85             )
86         );
87     }
88
89     public void dequeue(final ReconciliationTask task) {
90         reconTaskManager.cancelTask(task);
91     }
92
93     public DataBroker getDb() {
94         return db;
95     }
96
97     @Override
98     public void close() throws Exception {
99         if (this.reconcilers != null) {
100             this.reconcilers.shutdownNow();
101         }
102
103         if (this.taskTriager != null) {
104             this.taskTriager.shutdownNow();
105         }
106     }
107 }