View Javadoc

1   /**
2      This file is part of GoldenGate Project (named also GoldenGate or GG).
3   
4      Copyright 2009, Frederic Bregier, and individual contributors by the @author
5      tags. See the COPYRIGHT.txt in the distribution for a full listing of
6      individual contributors.
7   
8      All GoldenGate Project is free software: you can redistribute it and/or 
9      modify it under the terms of the GNU General Public License as published 
10     by the Free Software Foundation, either version 3 of the License, or
11     (at your option) any later version.
12  
13     GoldenGate is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
17  
18     You should have received a copy of the GNU General Public License
19     along with GoldenGate .  If not, see <http://www.gnu.org/licenses/>.
20   */
21  package openr66.commander;
22  
23  import goldengate.common.database.DbPreparedStatement;
24  import goldengate.common.database.data.AbstractDbData;
25  import goldengate.common.database.data.AbstractDbData.UpdatedInfo;
26  import goldengate.common.database.exception.GoldenGateDatabaseException;
27  import goldengate.common.database.exception.GoldenGateDatabaseNoConnectionException;
28  import goldengate.common.database.exception.GoldenGateDatabaseNoDataException;
29  import goldengate.common.database.exception.GoldenGateDatabaseSqlException;
30  import goldengate.common.database.model.DbModelFactory;
31  import goldengate.common.logging.GgInternalLogger;
32  import goldengate.common.logging.GgInternalLoggerFactory;
33  import openr66.database.DbConstant;
34  import openr66.database.data.DbConfiguration;
35  import openr66.database.data.DbHostAuth;
36  import openr66.database.data.DbMultipleMonitor;
37  import openr66.database.data.DbRule;
38  import openr66.database.data.DbTaskRunner;
39  import openr66.protocol.configuration.Configuration;
40  import openr66.protocol.utils.OpenR66SignalHandler;
41  
42  /**
43   * Commander is responsible to read from database updated data from time to time in order to
44   * achieve new runner or new configuration updates.
45   *
46   * @author Frederic Bregier
47   *
48   */
49  public class Commander implements CommanderInterface {
50      /**
51       * Internal Logger
52       */
53      private static final GgInternalLogger logger = GgInternalLoggerFactory
54              .getLogger(Commander.class);
55  
56      private static final int LIMITSUBMIT = 100;
57  
58      private InternalRunner internalRunner = null;
59      private DbPreparedStatement preparedStatementLock = null;
60      private DbPreparedStatement preparedStatementConfig = null;
61      private DbPreparedStatement preparedStatementHost = null;
62      private DbPreparedStatement preparedStatementRule = null;
63      private DbPreparedStatement preparedStatementRunner = null;
64  
65      /**
66       * Prepare requests that will be executed from time to time
67       * @param runner
68       * @throws GoldenGateDatabaseNoConnectionException
69       * @throws GoldenGateDatabaseSqlException
70       */
71      public Commander(InternalRunner runner)
72          throws GoldenGateDatabaseNoConnectionException, GoldenGateDatabaseSqlException {
73          this.internalConstructor(runner);
74      }
75      /**
76       * Prepare requests that will be executed from time to time
77       * @param runner
78       * @param fromStartup True if call from startup of the server
79       * @throws GoldenGateDatabaseNoConnectionException
80       * @throws GoldenGateDatabaseSqlException
81       */
82      public Commander(InternalRunner runner, boolean fromStartup)
83          throws GoldenGateDatabaseNoConnectionException, GoldenGateDatabaseSqlException {
84          this.internalConstructor(runner);
85          if (fromStartup) {
86              // Change RUNNING or INTERRUPTED to TOSUBMIT since they should be ready
87              DbTaskRunner.resetToSubmit(DbConstant.admin.session);
88          }
89      }
90      private void internalConstructor(InternalRunner runner)
91      throws GoldenGateDatabaseNoConnectionException, GoldenGateDatabaseSqlException {
92          try {
93              if (Configuration.configuration.multipleMonitors > 1) {
94                  preparedStatementLock =
95                      DbMultipleMonitor.getUpdatedPrepareStament(DbConstant.noCommitAdmin.session);
96              } else {
97                  preparedStatementLock = null;
98              }
99              preparedStatementConfig =
100                 DbConfiguration.getUpdatedPrepareStament(DbConstant.admin.session);
101             preparedStatementHost =
102                 DbHostAuth.getUpdatedPrepareStament(DbConstant.admin.session);
103             preparedStatementRule =
104                 DbRule.getUpdatedPrepareStament(DbConstant.admin.session);
105             preparedStatementRunner =
106                 DbTaskRunner.getSelectFromInfoPrepareStatement(DbConstant.admin.session,
107                         UpdatedInfo.TOSUBMIT, false, LIMITSUBMIT);
108             
109             // Clean tasks (CompleteOK and ALLDONE => DONE)
110             DbTaskRunner.changeFinishedToDone(DbConstant.admin.session);
111             internalRunner = runner;
112         } finally {
113             if (internalRunner == null) {
114                 // An error occurs
115                 if (preparedStatementLock != null) {
116                     preparedStatementLock.realClose();
117                 }
118                 if (preparedStatementConfig != null) {
119                     preparedStatementConfig.realClose();
120                 }
121                 if (preparedStatementHost != null) {
122                     preparedStatementHost.realClose();
123                 }
124                 if (preparedStatementRule != null) {
125                     preparedStatementRule.realClose();
126                 }
127                 if (preparedStatementRunner != null) {
128                     preparedStatementRunner.realClose();
129                 }
130             } else {
131                 if (preparedStatementLock != null) {
132                     DbConstant.noCommitAdmin.session.addLongTermPreparedStatement(preparedStatementLock);
133                 }
134                 if (preparedStatementConfig != null) {
135                     DbConstant.admin.session.addLongTermPreparedStatement(preparedStatementConfig);
136                 }
137                 if (preparedStatementHost != null) {
138                     DbConstant.admin.session.addLongTermPreparedStatement(preparedStatementHost);
139                 }
140                 if (preparedStatementRule != null) {
141                     DbConstant.admin.session.addLongTermPreparedStatement(preparedStatementRule);
142                 }
143                 if (preparedStatementRunner != null) {
144                     DbConstant.admin.session.addLongTermPreparedStatement(preparedStatementRunner);
145                 }
146             }
147         }
148     }
149     /**
150      * Finalize internal data
151      */
152     public void finalize() {
153         if (preparedStatementLock != null) {
154             try {
155                 DbConstant.noCommitAdmin.session.commit();
156             } catch (GoldenGateDatabaseSqlException e) {
157             } catch (GoldenGateDatabaseNoConnectionException e) {
158             }
159             preparedStatementLock.realClose();
160             DbConstant.noCommitAdmin.session.removeLongTermPreparedStatements(preparedStatementLock);
161             //DbConstant.noCommitAdmin.session.removeLongTermPreparedStatements();
162         }
163         if (preparedStatementConfig != null) {
164             preparedStatementConfig.realClose();
165             DbConstant.admin.session.removeLongTermPreparedStatements(preparedStatementConfig);
166         }
167         if (preparedStatementHost != null) {
168             preparedStatementHost.realClose();
169             DbConstant.admin.session.removeLongTermPreparedStatements(preparedStatementHost);
170         }
171         if (preparedStatementRule != null) {
172             preparedStatementRule.realClose();
173             DbConstant.admin.session.removeLongTermPreparedStatements(preparedStatementRule);
174         }
175         if (preparedStatementRunner != null) {
176             preparedStatementRunner.realClose();
177             DbConstant.admin.session.removeLongTermPreparedStatements(preparedStatementRunner);
178         }
179         //DbConstant.admin.session.removeLongTermPreparedStatements();
180     }
181 
182     /* (non-Javadoc)
183      * @see java.lang.Runnable#run()
184      */
185     @Override
186     public void run() {
187         Thread.currentThread().setName("OpenR66Commander");
188         // each time it is runned, it parses all database for updates
189         DbMultipleMonitor multipleMonitor = null;
190         // Open a lock to prevent other "HA" monitors to retrieve access as Commander
191         try {
192             try {
193                 if (preparedStatementLock != null) {
194                     preparedStatementLock.executeQuery();
195                     preparedStatementLock.getNext();
196                     multipleMonitor =
197                         DbMultipleMonitor.getFromStatement(preparedStatementLock);
198                 }
199             } catch (GoldenGateDatabaseNoConnectionException e) {
200                 logger.error("Database No Connection Error: Cannot execute Commander", e);
201                 try {
202                     DbModelFactory.dbModel.validConnection(DbConstant.noCommitAdmin.session);
203                 } catch (GoldenGateDatabaseNoConnectionException e1) {
204                 }
205                 return;
206             } catch (GoldenGateDatabaseSqlException e) {
207                 logger.error("Database SQL Error: Cannot execute Commander", e);
208                 try {
209                     DbModelFactory.dbModel.validConnection(DbConstant.noCommitAdmin.session);
210                 } catch (GoldenGateDatabaseNoConnectionException e1) {
211                 }
212                 return;
213             }
214             logger.debug("Before "+multipleMonitor);
215             // First check Configuration
216             try {
217                 preparedStatementConfig.executeQuery();
218                 while (preparedStatementConfig.getNext()) {
219                     // should be only one...
220                     DbConfiguration configuration = DbConfiguration.getFromStatement(preparedStatementConfig);
221                     if (configuration.isOwnConfiguration()) {
222                         configuration.updateConfiguration();
223                     }
224                     if (multipleMonitor != null) {
225                         // update the configuration in HA mode
226                         if (multipleMonitor.checkUpdateConfig()) {
227                             configuration.changeUpdatedInfo(AbstractDbData.UpdatedInfo.NOTUPDATED);
228                             configuration.update();
229                             logger.debug("Config "+multipleMonitor);
230                         } else {
231                             configuration.update();
232                             logger.debug("Config "+multipleMonitor);
233                         }
234                     } else {
235                         configuration.changeUpdatedInfo(AbstractDbData.UpdatedInfo.NOTUPDATED);
236                         configuration.update();
237                     }
238                     configuration = null;
239                 }
240                 preparedStatementConfig.close();
241             } catch (GoldenGateDatabaseNoConnectionException e) {
242                 try {
243                     DbModelFactory.dbModel.validConnection(DbConstant.admin.session);
244                 } catch (GoldenGateDatabaseNoConnectionException e1) {
245                 }
246                 logger.error("Database No Connection Error: Cannot execute Commander", e);
247                 return;
248             } catch (GoldenGateDatabaseSqlException e) {
249                 try {
250                     DbModelFactory.dbModel.validConnection(DbConstant.admin.session);
251                 } catch (GoldenGateDatabaseNoConnectionException e1) {
252                 }
253                 logger.error("Database SQL Error: Cannot execute Commander", e);
254                 return;
255             } catch (GoldenGateDatabaseException e) {
256                 try {
257                     DbModelFactory.dbModel.validConnection(DbConstant.admin.session);
258                 } catch (GoldenGateDatabaseNoConnectionException e1) {
259                 }
260                 logger.error("Database Error: Cannot execute Commander", e);
261                 return;
262             } finally {
263                 preparedStatementConfig.close();
264             }
265             // Check HostAuthent
266             try {
267                 preparedStatementHost.executeQuery();
268                 boolean mm = false;
269                 boolean lastUpdate = false;
270                 while (preparedStatementHost.getNext()) {
271                     // Maybe multiple
272                     DbHostAuth hostAuth = DbHostAuth.getFromStatement(preparedStatementHost);
273                     if (multipleMonitor != null) {
274                         if (!mm) {
275                             // not already set from a previous hostAuth
276                             mm = true;
277                             lastUpdate = multipleMonitor.checkUpdateHost();
278                         } // else already set so no action on multipleMonitor
279                         
280                         // Update the Host configuration in HA mode
281                         if (lastUpdate) {
282                             hostAuth.changeUpdatedInfo(AbstractDbData.UpdatedInfo.NOTUPDATED);
283                             hostAuth.update();
284                             logger.debug("Host "+multipleMonitor);
285                         } else {
286                             // Nothing to do except validate
287                             hostAuth.update();
288                             logger.debug("Host "+multipleMonitor);
289                         }
290                     } else {
291                         // Nothing to do except validate
292                         hostAuth.changeUpdatedInfo(AbstractDbData.UpdatedInfo.NOTUPDATED);
293                         hostAuth.update();
294                     }
295                     hostAuth = null;
296                 }
297             } catch (GoldenGateDatabaseNoConnectionException e) {
298                 try {
299                     DbModelFactory.dbModel.validConnection(DbConstant.admin.session);
300                 } catch (GoldenGateDatabaseNoConnectionException e1) {
301                 }
302                 logger.error("Database No Connection Error: Cannot execute Commander", e);
303                 return;
304             } catch (GoldenGateDatabaseSqlException e) {
305                 try {
306                     DbModelFactory.dbModel.validConnection(DbConstant.admin.session);
307                 } catch (GoldenGateDatabaseNoConnectionException e1) {
308                 }
309                 logger.error("Database SQL Error: Cannot execute Commander", e);
310                 return;
311             } catch (GoldenGateDatabaseException e) {
312                 try {
313                     DbModelFactory.dbModel.validConnection(DbConstant.admin.session);
314                 } catch (GoldenGateDatabaseNoConnectionException e1) {
315                 }
316                 logger.error("Database Error: Cannot execute Commander", e);
317                 return;
318             } finally {
319                 preparedStatementHost.close();
320             }
321             // Check Rules
322             try {
323                 preparedStatementRule.executeQuery();
324                 boolean mm = false;
325                 boolean lastUpdate = false;
326                 while (preparedStatementRule.getNext()) {
327                     DbRule rule = DbRule.getFromStatement(preparedStatementRule);
328                     if (multipleMonitor != null) {
329                         if (!mm) {
330                             // not already set from a previous hostAuth
331                             mm = true;
332                             lastUpdate = multipleMonitor.checkUpdateRule();
333                         } // else already set so no action on multipleMonitor
334                         // Update the Rules in HA mode
335                         if (lastUpdate) {
336                             rule.changeUpdatedInfo(AbstractDbData.UpdatedInfo.NOTUPDATED);
337                             rule.update();
338                             logger.debug("Rule "+multipleMonitor);
339                         } else {
340                             // Nothing to do except validate
341                             rule.update();
342                             logger.debug("Rule "+multipleMonitor);
343                         }
344                     } else {
345                         // Nothing to do except validate
346                         rule.changeUpdatedInfo(AbstractDbData.UpdatedInfo.NOTUPDATED);
347                         rule.update();
348                     }
349                     rule = null;
350                 }
351             } catch (GoldenGateDatabaseNoConnectionException e) {
352                 try {
353                     DbModelFactory.dbModel.validConnection(DbConstant.admin.session);
354                 } catch (GoldenGateDatabaseNoConnectionException e1) {
355                 }
356                 logger.error("Database No Connection Error: Cannot execute Commander", e);
357                 return;
358             } catch (GoldenGateDatabaseSqlException e) {
359                 try {
360                     DbModelFactory.dbModel.validConnection(DbConstant.admin.session);
361                 } catch (GoldenGateDatabaseNoConnectionException e1) {
362                 }
363                 logger.error("Database SQL Error: Cannot execute Commander", e);
364                 return;
365             } catch (GoldenGateDatabaseNoDataException e) {
366                 try {
367                     DbModelFactory.dbModel.validConnection(DbConstant.admin.session);
368                 } catch (GoldenGateDatabaseNoConnectionException e1) {
369                 }
370                 logger.error("Database Error: Cannot execute Commander", e);
371                 return;
372             } catch (GoldenGateDatabaseException e) {
373                 try {
374                     DbModelFactory.dbModel.validConnection(DbConstant.admin.session);
375                 } catch (GoldenGateDatabaseNoConnectionException e1) {
376                 }
377                 logger.error("Database Error: Cannot execute Commander", e);
378                 return;
379             } finally {
380                 preparedStatementRule.close();
381             }
382             if (OpenR66SignalHandler.isInShutdown()) {
383                 // no more task to submit
384                 return;
385             }
386             logger.debug("start runner");
387             // Check TaskRunner
388             try {
389                 DbTaskRunner.finishSelectOrCountPrepareStatement(preparedStatementRunner);
390                 // No specific HA mode since the other servers will wait for the commit on Lock
391                 preparedStatementRunner.executeQuery();
392                 while (preparedStatementRunner.getNext()) {
393                     DbTaskRunner taskRunner = DbTaskRunner.getFromStatement(preparedStatementRunner);
394                     logger.debug("get a task: {}",taskRunner);
395                     // Launch if possible this task
396                     String key = taskRunner.getRequested()+" "+taskRunner.getRequester()+
397                         " "+taskRunner.getSpecialId();
398                     if (Configuration.configuration.getLocalTransaction().
399                             getFromRequest(key) != null) {
400                         // already running
401                         continue;
402                     }
403                     if (taskRunner.isSelfRequested()) {
404                         // cannot schedule a request where the host is the requested host
405                         taskRunner.changeUpdatedInfo(UpdatedInfo.INTERRUPTED);
406                         taskRunner.update();
407                         continue;
408                     }
409                     taskRunner.changeUpdatedInfo(UpdatedInfo.RUNNING);
410                     taskRunner.update();
411                     internalRunner.submitTaskRunner(taskRunner);
412                     taskRunner = null;
413                 }
414             } catch (GoldenGateDatabaseNoConnectionException e) {
415                 try {
416                     DbModelFactory.dbModel.validConnection(DbConstant.admin.session);
417                 } catch (GoldenGateDatabaseNoConnectionException e1) {
418                 }
419                 logger.error("Database No Connection Error: Cannot execute Commander", e);
420                 return;
421             } catch (GoldenGateDatabaseSqlException e) {
422                 try {
423                     DbModelFactory.dbModel.validConnection(DbConstant.admin.session);
424                 } catch (GoldenGateDatabaseNoConnectionException e1) {
425                 }
426                 logger.error("Database SQL Error: Cannot execute Commander", e);
427                 return;
428             } catch (GoldenGateDatabaseException e) {
429                 try {
430                     DbModelFactory.dbModel.validConnection(DbConstant.admin.session);
431                 } catch (GoldenGateDatabaseNoConnectionException e1) {
432                 }
433                 logger.error("Database Error: Cannot execute Commander", e);
434                 return;
435             } finally {
436                 preparedStatementRunner.close();
437             }
438             logger.debug("end commander");
439         } finally {
440             if (multipleMonitor != null) {
441                 try {
442                     // Now update and Commit so releasing the lock
443                     logger.debug("Update "+multipleMonitor);
444                     multipleMonitor.update();
445                     DbConstant.noCommitAdmin.session.commit();
446                 } catch (GoldenGateDatabaseException e) {
447                     try {
448                         DbModelFactory.dbModel.validConnection(DbConstant.noCommitAdmin.session);
449                     } catch (GoldenGateDatabaseNoConnectionException e1) {
450                     }
451                 }
452                 multipleMonitor = null;
453             }
454         }
455     }
456 
457 }