Adding interfaces in documentation
[aai/sparky-be.git] / sparkybe-onap-service / src / main / java / org / onap / aai / sparky / sync / SyncControllerService.java
1 /**
2  * ============LICENSE_START===================================================
3  * SPARKY (AAI UI service)
4  * ============================================================================
5  * Copyright © 2017 AT&T Intellectual Property.
6  * Copyright © 2017 Amdocs
7  * All rights reserved.
8  * ============================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * ============LICENSE_END=====================================================
21  *
22  * ECOMP and OpenECOMP are trademarks
23  * and service marks of AT&T Intellectual Property.
24  */
25 package org.onap.aai.sparky.sync;
26
27 import java.lang.Thread.UncaughtExceptionHandler;
28 import java.util.concurrent.ExecutorService;
29 import java.util.concurrent.Executors;
30 import java.util.concurrent.ScheduledExecutorService;
31 import java.util.concurrent.TimeUnit;
32
33 import org.onap.aai.cl.api.Logger;
34 import org.onap.aai.cl.eelf.LoggerFactory;
35 import org.onap.aai.sparky.logging.AaiUiMsgs;
36 import org.onap.aai.sparky.sync.SyncControllerImpl.SyncActions;
37 import org.onap.aai.sparky.sync.enumeration.OperationState;
38 import org.onap.aai.sparky.sync.enumeration.SynchronizerState;
39 import org.springframework.context.ApplicationListener;
40 import org.springframework.context.event.ApplicationContextEvent;
41
42 import com.google.common.util.concurrent.ThreadFactoryBuilder;
43
44 public class SyncControllerService implements ApplicationListener<ApplicationContextEvent> {
45
46   private SyncControllerRegistry syncControllerRegistry;
47   private ExecutorService runonceSyncExecutor;
48   private ScheduledExecutorService periodicSyncExecutor;
49   private boolean syncStarted;
50
51   private static final Logger LOG =
52       LoggerFactory.getInstance().getLogger(SyncControllerService.class);
53
54   private class SyncControllerTask implements Runnable {
55
56     private SyncController controller;
57
58     public SyncControllerTask(SyncController controller) {
59       this.controller = controller;
60     }
61
62     @Override
63     public void run() {
64
65       try {
66
67         if (controller.getState() == SynchronizerState.IDLE) {
68
69           /*
70            * This is a blocking-call, but would be nicer if it was async internally within the
71            * controller but at the moment, that's not the way it works.
72            */
73
74           if (controller.performAction(SyncActions.SYNCHRONIZE) != OperationState.OK) {
75
76             LOG.info(AaiUiMsgs.INFO_GENERIC,
77                 controller.getControllerName() + " is not idle, sync attempt has been skipped.");
78           }
79         } else {
80
81           LOG.info(AaiUiMsgs.INFO_GENERIC,
82               controller.getControllerName() + " is not idle, sync attempt has been skipped.");
83         }
84
85       } catch (Exception exception) {
86         LOG.error(AaiUiMsgs.ERROR_GENERIC,
87             "Error while attempting synchronization.  Error = " + exception.getMessage());
88       }
89
90     }
91
92   }
93
94   public SyncControllerService(SyncControllerRegistry syncControllerRegistry, int numRunOnceWorkers,
95       int numPeriodicWorkers) {
96     this.syncControllerRegistry = syncControllerRegistry;
97     this.syncStarted = false;
98
99     UncaughtExceptionHandler uncaughtExceptionHandler = new Thread.UncaughtExceptionHandler() {
100
101       @Override
102       public void uncaughtException(Thread thread, Throwable exc) {
103         LOG.error(AaiUiMsgs.ERROR_GENERIC, thread.getName() + ": " + exc);
104       }
105     };
106
107     runonceSyncExecutor = Executors.newFixedThreadPool(numRunOnceWorkers,
108         new ThreadFactoryBuilder().setNameFormat("RunonceSyncWorker-%d")
109             .setUncaughtExceptionHandler(uncaughtExceptionHandler).build());
110
111
112     periodicSyncExecutor = Executors.newScheduledThreadPool(numPeriodicWorkers,
113         new ThreadFactoryBuilder().setNameFormat("PeriodicSyncWorker-%d")
114             .setUncaughtExceptionHandler(uncaughtExceptionHandler).build());
115
116   }
117
118   public SyncControllerRegistry getSyncControllerRegistry() {
119     return syncControllerRegistry;
120   }
121
122   public void startSync() {
123
124     long syncInitialDelayInMs = 0;
125
126     for (SyncController controller : syncControllerRegistry.getControllers()) {
127
128       syncInitialDelayInMs = controller.getDelayInMs();
129
130       if (!controller.isPeriodicSyncEnabled()) {
131
132         if (controller.isRunOnceSyncEnabled()) {
133           LOG.info(AaiUiMsgs.INFO_GENERIC, controller.getControllerName() + " is enabled.");
134           runonceSyncExecutor.submit(new SyncControllerTask(controller));
135         } else {
136           LOG.info(AaiUiMsgs.INFO_GENERIC, controller.getControllerName() + " is disabled.");
137         }
138
139       } else {
140
141         /**
142          * Do both. We'll take one instance of the SyncController and wrap the object instance into
143          * two SyncControllerTasks. The responsibility for preventing a conflicting sync should live
144          * in the SyncController instance. If a sync is underway when the periodic sync kicks in,
145          * then it will be ignored by the SyncController which is already underway.
146          * 
147          * The SyncController instance itself would then also be stateful such that it would know
148          * the last time it ran, and the next time it is supposed to run, the number times a sync
149          * has executed, etc.
150          */
151
152         if (controller.isRunOnceSyncEnabled()) {
153           LOG.info(AaiUiMsgs.INFO_GENERIC,
154               controller.getControllerName() + " run-once sync is enabled.");
155           runonceSyncExecutor.submit(new SyncControllerTask(controller));
156         } else {
157           LOG.info(AaiUiMsgs.INFO_GENERIC,
158               controller.getControllerName() + " run-once sync is disabled.");
159         }
160
161         /*
162          * The controller knows it's configuredfrequency and we can just ask it to tell us what the
163          * delay and frequency needs to be, rather than trying to calculate the configured frequency
164          * per controller which "could" be different for each controller.
165          */
166
167         if (controller.isPeriodicSyncEnabled()) {
168
169           LOG.info(AaiUiMsgs.INFO_GENERIC,
170               controller.getControllerName() + " periodic sync is enabled and scheduled to start @ "
171                   + controller.getNextSyncTime());
172
173           periodicSyncExecutor.scheduleAtFixedRate(new SyncControllerTask(controller),
174               controller.getDelayInMs(), controller.getSyncFrequencyInMs(), TimeUnit.MILLISECONDS);
175
176         } else {
177
178           LOG.info(AaiUiMsgs.INFO_GENERIC,
179               controller.getControllerName() + " periodic sync is disabled.");
180
181         }
182
183       }
184
185     }
186
187   }
188
189   public void shutdown() {
190
191     if (runonceSyncExecutor != null) {
192       runonceSyncExecutor.shutdown();
193     }
194
195     if (periodicSyncExecutor != null) {
196       periodicSyncExecutor.shutdown();
197     }
198
199     if (syncControllerRegistry != null) {
200       for (SyncController controller : syncControllerRegistry.getControllers()) {
201         controller.shutdown();
202       }
203     }
204
205   }
206
207   @Override
208   public synchronized void onApplicationEvent(ApplicationContextEvent arg0) {
209
210     /*
211      * Start sync service processing when spring-context-initialization has finished
212      */
213     
214     if (!syncStarted) {
215       syncStarted = true;
216       startSync();
217     }
218
219   }
220
221
222 }