DynamicClusterManager.java

  1. /*
  2.  * GovWay - A customizable API Gateway
  3.  * https://govway.org
  4.  *
  5.  * Copyright (c) 2005-2025 Link.it srl (https://link.it).
  6.  *
  7.  * This program is free software: you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License version 3, as published by
  9.  * the Free Software Foundation.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18.  *
  19.  */

  20. package org.openspcoop2.pdd.config;

  21. import java.sql.Connection;
  22. import java.sql.PreparedStatement;
  23. import java.sql.ResultSet;
  24. import java.sql.SQLException;
  25. import java.sql.Timestamp;
  26. import java.util.ArrayList;
  27. import java.util.Date;
  28. import java.util.List;

  29. import org.apache.commons.codec.digest.DigestUtils;
  30. import org.openspcoop2.core.commons.CoreException;
  31. import org.openspcoop2.core.config.driver.db.DriverConfigurazioneDB;
  32. import org.openspcoop2.core.constants.CostantiDB;
  33. import org.openspcoop2.pdd.services.ServicesUtils;
  34. import org.openspcoop2.pdd.services.connector.proxy.ProxyOperation;
  35. import org.openspcoop2.utils.LoggerWrapperFactory;
  36. import org.openspcoop2.utils.Utilities;
  37. import org.openspcoop2.utils.date.DateManager;
  38. import org.openspcoop2.utils.date.DateUtils;
  39. import org.openspcoop2.utils.id.apache.serial.MaxReachedException;
  40. import org.openspcoop2.utils.jdbc.JDBCUtilities;
  41. import org.openspcoop2.utils.sql.ISQLQueryObject;
  42. import org.openspcoop2.utils.sql.SQLObjectFactory;
  43. import org.openspcoop2.utils.sql.SQLQueryObjectException;
  44. import org.slf4j.Logger;

  45. /**
  46.  * DynamicClusterManager
  47.  *
  48.  * @author Poli Andrea (apoli@link.it)
  49.  * @author $Author$
  50.  * @version $Rev$, $Date$
  51.  */
  52. public class DynamicClusterManager {

  53.     private static DynamicClusterManager staticInstance = null;
  54.     public static synchronized void initStaticInstance() throws CoreException {
  55.         if(staticInstance==null) {
  56.             staticInstance = new DynamicClusterManager();
  57.         }
  58.     }
  59.     public static DynamicClusterManager getInstance() throws CoreException {
  60.         if(staticInstance==null) {
  61.             // spotbugs warning 'SING_SINGLETON_GETTER_NOT_SYNCHRONIZED': l'istanza viene creata allo startup
  62.             synchronized (DynamicClusterManager.class) {
  63.                 initStaticInstance();
  64.             }
  65.         }
  66.         return staticInstance;
  67.     }
  68.     public static boolean isInitialized() {
  69.         return staticInstance!=null;
  70.     }
  71.    
  72.     private DriverConfigurazioneDB driverConfigurazioneDB = null;
  73.     private OpenSPCoop2Properties op2Properties = null;
  74.    
  75.     private DynamicClusterManager() throws CoreException {
  76.         Object oConfig = ConfigurazionePdDReader.getDriverConfigurazionePdD();
  77.         if(oConfig instanceof DriverConfigurazioneDB) {
  78.             this.driverConfigurazioneDB = (DriverConfigurazioneDB) oConfig;
  79.         }
  80.         else {
  81.             throw new CoreException("Modalità dinamica utilizzabile solamente con una configurazione su database");
  82.         }
  83.         this.op2Properties = OpenSPCoop2Properties.getInstance();
  84.     }
  85.    
  86.     private boolean rateLimitingGestioneCluster = false;
  87.     public boolean isRateLimitingGestioneCluster() {
  88.         return this.rateLimitingGestioneCluster;
  89.     }
  90.     public void setRateLimitingGestioneCluster(boolean rateLimitingGestioneCluster) {
  91.         this.rateLimitingGestioneCluster = rateLimitingGestioneCluster;
  92.     }
  93.    
  94.     private int identificativoNumerico = -1;
  95.     public int getIdentificativoNumerico() {
  96.         return this.identificativoNumerico;
  97.     }
  98.    
  99.     private String getSuffixMessageUpdate(int row) {
  100.         return " nella tabella '"+CostantiDB.CONFIG_NODI_RUNTIME+"' (update-row: "+row+")";
  101.     }
  102.    
  103.     public void register(Logger log) throws CoreException {
  104.         Connection con = null;
  105.         int oldTransactionIsolation = -1;
  106.         try {
  107.             con = this.driverConfigurazioneDB.getConnection("DynamicClusterManager.register");
  108.            
  109.             boolean autoCommit = false;
  110.             con.setAutoCommit(autoCommit);
  111.            
  112.             /*
  113.               Viene realizzato con livello di isolamento SERIALIZABLE, per essere sicuri
  114.               che esecuzioni parallele non leggano dati inconsistenti.
  115.               Con il livello SERIALIZABLE, se ritorna una eccezione, deve essere riprovato
  116.               La sincronizzazione e' necessaria per via del possibile accesso simultaneo del servizio Gop
  117.               e del servizio che si occupa di eliminare destinatari di messaggi
  118.              */
  119.             // setAutoCommit e livello Isolamento
  120.             try{
  121.                 oldTransactionIsolation = con.getTransactionIsolation();
  122.                 JDBCUtilities.setTransactionIsolationSerializable(this.driverConfigurazioneDB.getTipoDB(), con);
  123.             } catch(Exception er) {
  124.                 throw new CoreException("(setIsolation) "+er.getMessage(),er);
  125.             }

  126.             boolean updateEffettuato = false;
  127.            
  128.             long gestioneSerializableDBattesaAttiva = this.op2Properties.getGestioneSerializableDBAttesaAttiva();
  129.             int gestioneSerializableDBcheckInterval = this.op2Properties.getGestioneSerializableDBCheckInterval();
  130.             long scadenzaWhile = DateManager.getTimeMillis() + gestioneSerializableDBattesaAttiva;
  131.            
  132.             Exception eLast = null;
  133.            
  134.             while(!updateEffettuato && DateManager.getTimeMillis() < scadenzaWhile){

  135.                 try{
  136.                     this.registerEngine(con, log);

  137.                     updateEffettuato = true;

  138.                 }
  139.                 catch(MaxReachedException maxReached) {
  140.                     throw maxReached;
  141.                 }
  142.                 catch(Exception e) {
  143.                     eLast = e;
  144.                     /**System.out.println("Serializable error:"+e.getMessage());*/
  145.                 }

  146.                 if(!updateEffettuato){
  147.                     // Per aiutare ad evitare conflitti
  148.                     try{
  149.                         Utilities.sleep((ServicesUtils.getRandom()).nextInt(gestioneSerializableDBcheckInterval)); // random da 0ms a checkIntervalms
  150.                     }catch(Exception eRandom){
  151.                         // ignore
  152.                     }
  153.                 }
  154.             }
  155.                        
  156.             if(!updateEffettuato){
  157.                 throw new CoreException("Registrazione fallita: "+eLast.getMessage(), eLast);
  158.             }
  159.         }
  160.         catch(Exception e) {
  161.             throw new CoreException("[DynamicClusterManager.register] failed: "+e.getMessage(), e);
  162.         }
  163.         finally {
  164.             // Ripristino Transazione
  165.             try{
  166.                 con.setTransactionIsolation(oldTransactionIsolation);
  167.             } catch(Exception er) {
  168.                 if(log!=null) {
  169.                     log.error("(ripristinoIsolation) "+er.getMessage(),er);
  170.                 }
  171.                 else {
  172.                     LoggerWrapperFactory.getLogger(DynamicClusterManager.class).error("(ripristinoIsolation) "+er.getMessage(),er);
  173.                 }
  174.             }
  175.             try{
  176.                 con.setAutoCommit(true);
  177.             }catch(Exception eRollback){
  178.                 /**if(log!=null) {
  179.                     log.error("(setAutoCommit) "+eRollback.getMessage(),eRollback);
  180.                 }
  181.                 else {
  182.                     LoggerWrapperFactory.getLogger(DynamicClusterManager.class).error("(setAutoCommit) "+eRollback.getMessage(),eRollback);
  183.                 }*/
  184.             }
  185.             try {
  186.                 if(con!=null) {
  187.                     this.driverConfigurazioneDB.releaseConnection(con);
  188.                 }
  189.             }catch(Exception eClose) {
  190.                 // close
  191.             }
  192.         }
  193.     }
  194.    
  195.     private void registerEngine(Connection con, Logger log) throws MaxReachedException, SQLException, SQLQueryObjectException {
  196.         try {
  197.             boolean find = registerExistsId(con);
  198.            
  199.             if(find) {
  200.                
  201.                 // Update
  202.                 registerUpdate(con, log);
  203.                
  204.             }
  205.             else {
  206.                
  207.                 // Cerco idNumerico disponibile
  208.                 /**if(this.op2Properties.isClusterIdNumericoDinamico()) { FIX: va sempre calcolato per l'unique del db*/
  209.                 this.identificativoNumerico = this.getNextIdNumerico(con, log);
  210.                
  211.                 // Insert
  212.                 registerInsert(con, log);
  213.             }
  214.            
  215.             con.commit();
  216.         }
  217.         catch(Exception e) {
  218.             try{
  219.                 con.rollback();
  220.             } catch(Exception er) {
  221.                 // ignore
  222.             }
  223.             throw e;
  224.         }
  225.     }
  226.     private boolean registerExistsId(Connection con) throws SQLException, SQLQueryObjectException {
  227.         PreparedStatement pstmt = null;
  228.         ResultSet rs = null;
  229.         try {
  230.             ISQLQueryObject sqlQueryObject = SQLObjectFactory.createSQLQueryObject(this.driverConfigurazioneDB.getTipoDB());
  231.             sqlQueryObject.addFromTable(CostantiDB.CONFIG_NODI_RUNTIME);
  232.             sqlQueryObject.addSelectField(CostantiDB.CONFIG_NODI_RUNTIME_COLUMN_ID_NUMERICO);
  233.             sqlQueryObject.setANDLogicOperator(true);
  234.             sqlQueryObject.addWhereCondition(CostantiDB.CONFIG_NODI_RUNTIME_COLUMN_HOSTNAME+"=?");
  235.             String query = sqlQueryObject.createSQLQuery();
  236.             pstmt = con.prepareStatement(query);
  237.             int index = 1;
  238.             pstmt.setString(index++, this.op2Properties.getClusterHostname());
  239.             rs = pstmt.executeQuery();
  240.             boolean find = rs.next();
  241.             if(find) {
  242.                 this.identificativoNumerico = rs.getInt(CostantiDB.CONFIG_NODI_RUNTIME_COLUMN_ID_NUMERICO);
  243.             }
  244.             return find;
  245.         }
  246.         finally {
  247.             try {
  248.                 if(rs!=null) {
  249.                     rs.close();
  250.                 }
  251.             }catch(Exception eClose) {
  252.                 // close
  253.             }
  254.             try {
  255.                 if(pstmt!=null) {
  256.                     pstmt.close();
  257.                 }
  258.             }catch(Exception eClose) {
  259.                 // close
  260.             }
  261.         }
  262.     }
  263.     private void registerInsert(Connection con, Logger log) throws SQLException, SQLQueryObjectException {
  264.         PreparedStatement pstmt = null;
  265.         try {
  266.             // Insert
  267.             ISQLQueryObject sqlQueryObject = SQLObjectFactory.createSQLQueryObject(this.driverConfigurazioneDB.getTipoDB());
  268.             sqlQueryObject.addInsertTable(CostantiDB.CONFIG_NODI_RUNTIME);
  269.             sqlQueryObject.addInsertField(CostantiDB.CONFIG_NODI_RUNTIME_COLUMN_HOSTNAME, "?");
  270.             sqlQueryObject.addInsertField(CostantiDB.CONFIG_NODI_RUNTIME_COLUMN_GRUPPO, "?");
  271.             sqlQueryObject.addInsertField(CostantiDB.CONFIG_NODI_RUNTIME_COLUMN_DATA_REGISTRAZIONE, "?");
  272.             sqlQueryObject.addInsertField(CostantiDB.CONFIG_NODI_RUNTIME_COLUMN_DATA_REFRESH, "?");
  273.             sqlQueryObject.addInsertField(CostantiDB.CONFIG_NODI_RUNTIME_COLUMN_ID_NUMERICO, "?");
  274.             String insert = sqlQueryObject.createSQLInsert();
  275.             pstmt = con.prepareStatement(insert);
  276.             int index = 1;
  277.             pstmt.setString(index++, this.op2Properties.getClusterHostname());
  278.             pstmt.setString(index++, this.op2Properties.getGroupId(this.rateLimitingGestioneCluster));
  279.             Timestamp now = DateManager.getTimestamp();
  280.             pstmt.setTimestamp(index++, now);
  281.             pstmt.setTimestamp(index++, now);
  282.             pstmt.setInt(index++, this.identificativoNumerico);
  283.             int row = pstmt.executeUpdate();
  284.            
  285.             String msg = "Registrato hostname '"+this.op2Properties.getClusterHostname()+"'"+getSuffixMessageUpdate(row);
  286.             log.debug(msg);
  287.         }
  288.         finally {
  289.             try {
  290.                 if(pstmt!=null) {
  291.                     pstmt.close();
  292.                 }
  293.             }catch(Exception eClose) {
  294.                 // close
  295.             }
  296.         }
  297.     }
  298.     private void registerUpdate(Connection con, Logger log) throws SQLException, SQLQueryObjectException {
  299.         PreparedStatement pstmt = null;
  300.         try {
  301.             ISQLQueryObject sqlQueryObject = SQLObjectFactory.createSQLQueryObject(this.driverConfigurazioneDB.getTipoDB());
  302.             sqlQueryObject.addUpdateTable(CostantiDB.CONFIG_NODI_RUNTIME);
  303.             sqlQueryObject.addUpdateField(CostantiDB.CONFIG_NODI_RUNTIME_COLUMN_GRUPPO, "?");
  304.             sqlQueryObject.addUpdateField(CostantiDB.CONFIG_NODI_RUNTIME_COLUMN_DATA_REGISTRAZIONE, "?");
  305.             sqlQueryObject.addUpdateField(CostantiDB.CONFIG_NODI_RUNTIME_COLUMN_DATA_REFRESH, "?");
  306.             sqlQueryObject.setANDLogicOperator(true);
  307.             sqlQueryObject.addWhereCondition(CostantiDB.CONFIG_NODI_RUNTIME_COLUMN_HOSTNAME+"=?");
  308.             String update = sqlQueryObject.createSQLUpdate();
  309.             pstmt = con.prepareStatement(update);
  310.             int index = 1;
  311.             pstmt.setString(index++, this.op2Properties.getGroupId(this.rateLimitingGestioneCluster));
  312.             Timestamp now = DateManager.getTimestamp();
  313.             pstmt.setTimestamp(index++, now);
  314.             pstmt.setTimestamp(index++, now);
  315.             pstmt.setString(index++, this.op2Properties.getClusterHostname());
  316.             int row = pstmt.executeUpdate();
  317.            
  318.             String msg = "Registrato con aggiormanento hostname '"+this.op2Properties.getClusterHostname()+"'"+getSuffixMessageUpdate(row);
  319.             log.debug(msg);
  320.         }
  321.         finally {
  322.             try {
  323.                 if(pstmt!=null) {
  324.                     pstmt.close();
  325.                 }
  326.             }catch(Exception eClose) {
  327.                 // close
  328.             }
  329.         }
  330.     }
  331.     private int getNextIdNumerico(Connection con, Logger log) throws MaxReachedException, SQLException, SQLQueryObjectException {
  332.         PreparedStatement pstmt = null;
  333.         ResultSet rs = null;
  334.         try {
  335.             // Cerco idNumerico disponibile
  336.             int idNumerico = -1;
  337.             int max = getMax();
  338.            
  339.             ISQLQueryObject sqlQueryObject = SQLObjectFactory.createSQLQueryObject(this.driverConfigurazioneDB.getTipoDB());
  340.             sqlQueryObject.addFromTable(CostantiDB.CONFIG_NODI_RUNTIME);
  341.             sqlQueryObject.setANDLogicOperator(true);
  342.             sqlQueryObject.addSelectCountField(CostantiDB.CONFIG_NODI_RUNTIME_COLUMN_ID_NUMERICO, "countid");
  343.             sqlQueryObject.addSelectMaxField(CostantiDB.CONFIG_NODI_RUNTIME_COLUMN_ID_NUMERICO, "maxid");
  344.             sqlQueryObject.setANDLogicOperator(true);
  345.             sqlQueryObject.addWhereCondition(CostantiDB.CONFIG_NODI_RUNTIME_COLUMN_GRUPPO+"=?");
  346.             String query = sqlQueryObject.createSQLQuery();
  347.             pstmt = con.prepareStatement(query);
  348.             int index = 1;
  349.             pstmt.setString(index++, this.op2Properties.getGroupId(this.rateLimitingGestioneCluster));
  350.             rs = pstmt.executeQuery();
  351.             if(rs.next()) {
  352.                 int countid = rs.getInt("countid");
  353.                 int findId = rs.getInt("maxid");
  354.                 if(countid == 0) {
  355.                     idNumerico = 0; // primo id numerico
  356.                 }
  357.                 else if((findId+1)<=max) {
  358.                     idNumerico = findId+1;
  359.                 }
  360.             }
  361.             else {
  362.                 idNumerico = 0; // primo id numerico
  363.             }
  364.             rs.close(); rs = null;
  365.             pstmt.close(); pstmt = null;
  366.            
  367.             if(idNumerico<0) {
  368.                 try {
  369.                     idNumerico = getIdNumerico(con, max);
  370.                 }catch(MaxReachedException maxReached) {
  371.                     // provo a forzare svecchiamento
  372.                     try {
  373.                         deleteOldHostnames(con, log);
  374.                     }catch(Exception e) {
  375.                         // ignore e rilancio eccezione originale
  376.                         throw maxReached;
  377.                     }
  378.                     // riprovo a calcolarlo
  379.                     idNumerico = getIdNumerico(con, max);
  380.                 }
  381.             }

  382.             return idNumerico;
  383.         }
  384.         finally {
  385.             try {
  386.                 if(rs!=null) {
  387.                     rs.close();
  388.                 }
  389.             }catch(Exception eClose) {
  390.                 // close
  391.             }
  392.             try {
  393.                 if(pstmt!=null) {
  394.                     pstmt.close();
  395.                 }
  396.             }catch(Exception eClose) {
  397.                 // close
  398.             }
  399.         }
  400.     }
  401.     private int getMax() {
  402.         int cifre = this.op2Properties.getClusterDinamicoIdNumericoCifre(this.rateLimitingGestioneCluster);
  403.         StringBuilder sbCifre = new StringBuilder();
  404.         for (int i = 0; i < cifre; i++) {
  405.             sbCifre.append("9");
  406.         }
  407.         // int max
  408.         return Integer.parseInt(sbCifre.toString());
  409.     }
  410.     private int getIdNumerico(Connection con, int max) throws MaxReachedException, SQLException, SQLQueryObjectException {
  411.         PreparedStatement pstmt = null;
  412.         ResultSet rs = null;
  413.         int idNumerico = -1;
  414.         try {
  415.             ISQLQueryObject sqlQueryObject = SQLObjectFactory.createSQLQueryObject(this.driverConfigurazioneDB.getTipoDB());
  416.             sqlQueryObject.addFromTable(CostantiDB.CONFIG_NODI_RUNTIME);
  417.             sqlQueryObject.addSelectField(CostantiDB.CONFIG_NODI_RUNTIME_COLUMN_ID_NUMERICO);
  418.             sqlQueryObject.setANDLogicOperator(true);
  419.             sqlQueryObject.addWhereCondition(CostantiDB.CONFIG_NODI_RUNTIME_COLUMN_GRUPPO+"=?");
  420.             sqlQueryObject.addOrderBy(CostantiDB.CONFIG_NODI_RUNTIME_COLUMN_ID_NUMERICO, true);
  421.             String query = sqlQueryObject.createSQLQuery();
  422.             pstmt = con.prepareStatement(query);
  423.             int index = 1;
  424.             pstmt.setString(index++, this.op2Properties.getGroupId(this.rateLimitingGestioneCluster));
  425.             rs = pstmt.executeQuery();
  426.             int search = 0;
  427.             while(rs.next()) {
  428.                 int idNumericoExists = rs.getInt(CostantiDB.CONFIG_NODI_RUNTIME_COLUMN_ID_NUMERICO);
  429.                 if(search!=idNumericoExists) {
  430.                     idNumerico = search;
  431.                     break;
  432.                 }
  433.                 search++;
  434.                 if(search>max) {
  435.                     throw new MaxReachedException("Numero massimo di nodi registrabili ("+(max+1)+") raggiunto");
  436.                 }
  437.             }
  438.         }
  439.         finally {
  440.             try {
  441.                 if(rs!=null) {
  442.                     rs.close();
  443.                 }
  444.             }catch(Exception eClose) {
  445.                 // close
  446.             }
  447.             try {
  448.                 if(pstmt!=null) {
  449.                     pstmt.close();
  450.                 }
  451.             }catch(Exception eClose) {
  452.                 // close
  453.             }
  454.         }
  455.         return idNumerico;
  456.     }
  457.    
  458.     public void unregister(Logger log) throws CoreException {
  459.         unregister(log, this.op2Properties.getClusterHostname());
  460.     }
  461.     private void unregister(Logger log, String hostname) throws CoreException {
  462.         Connection con = null;
  463.         try {
  464.             con = this.driverConfigurazioneDB.getConnection("DynamicClusterManager.unregister");
  465.            
  466.             unregister(con, log, hostname);
  467.            
  468.             if(!con.getAutoCommit()) {
  469.                 con.commit();
  470.             }

  471.         }
  472.         catch(Exception e) {
  473.            
  474.             try {
  475.                 if(con!=null && !con.getAutoCommit()) {
  476.                     con.rollback();
  477.                 }
  478.             }catch(Exception eClose) {
  479.                 // close
  480.             }
  481.            
  482.             throw new CoreException("[DynamicClusterManager.unregister] failed: "+e.getMessage(), e);
  483.         }
  484.         finally {
  485.             try {
  486.                 if(con!=null) {
  487.                     this.driverConfigurazioneDB.releaseConnection(con);
  488.                 }
  489.             }catch(Exception eClose) {
  490.                 // close
  491.             }
  492.         }
  493.     }
  494.     private void unregister(Connection con, Logger log, String hostname) throws CoreException {
  495.         PreparedStatement pstmt = null;
  496.         try {
  497.             ISQLQueryObject sqlQueryObject = SQLObjectFactory.createSQLQueryObject(this.driverConfigurazioneDB.getTipoDB());
  498.             sqlQueryObject.addDeleteTable(CostantiDB.CONFIG_NODI_RUNTIME);
  499.             sqlQueryObject.setANDLogicOperator(true);
  500.             sqlQueryObject.addWhereCondition(CostantiDB.CONFIG_NODI_RUNTIME_COLUMN_HOSTNAME+"=?");
  501.             String query = sqlQueryObject.createSQLDelete();
  502.             pstmt = con.prepareStatement(query);
  503.             int index = 1;
  504.             pstmt.setString(index++, hostname);
  505.             int row = pstmt.executeUpdate();
  506.             pstmt.close(); pstmt = null;
  507.            
  508.             String msg = "Eliminato hostname '"+this.op2Properties.getClusterHostname()+"' dalla tabella '"+CostantiDB.CONFIG_NODI_RUNTIME+"' (update-row: "+row+")";
  509.             log.debug(msg);
  510.         }
  511.         catch(Exception e) {
  512.             throw new CoreException("[DynamicClusterManager.unregister] failed: "+e.getMessage(), e);
  513.         }
  514.         finally {
  515.             try {
  516.                 if(pstmt!=null) {
  517.                     pstmt.close();
  518.                 }
  519.             }catch(Exception eClose) {
  520.                 // close
  521.             }
  522.         }
  523.     }
  524.    
  525.     public void refresh(Logger log) throws CoreException {
  526.         Connection con = null;
  527.         PreparedStatement pstmt = null;
  528.         try {
  529.             con = this.driverConfigurazioneDB.getConnection("DynamicClusterManager.refresh");
  530.            
  531.             ISQLQueryObject sqlQueryObject = SQLObjectFactory.createSQLQueryObject(this.driverConfigurazioneDB.getTipoDB());
  532.             sqlQueryObject.addUpdateTable(CostantiDB.CONFIG_NODI_RUNTIME);
  533.             sqlQueryObject.addUpdateField(CostantiDB.CONFIG_NODI_RUNTIME_COLUMN_DATA_REFRESH, "?");
  534.             sqlQueryObject.setANDLogicOperator(true);
  535.             sqlQueryObject.addWhereCondition(CostantiDB.CONFIG_NODI_RUNTIME_COLUMN_HOSTNAME+"=?");
  536.             String update = sqlQueryObject.createSQLUpdate();
  537.             pstmt = con.prepareStatement(update);
  538.             int index = 1;
  539.             Timestamp now = DateManager.getTimestamp();
  540.             pstmt.setTimestamp(index++, now);
  541.             pstmt.setString(index++, this.op2Properties.getClusterHostname());
  542.             int row = pstmt.executeUpdate();
  543.             pstmt.close(); pstmt = null;
  544.            
  545.             if(!con.getAutoCommit()) {
  546.                 con.commit();
  547.             }
  548.            
  549.             String msg = "Aggiornato hostname '"+this.op2Properties.getClusterHostname()+"'"+getSuffixMessageUpdate(row);
  550.             log.debug(msg);
  551.         }
  552.         catch(Exception e) {
  553.            
  554.             try {
  555.                 if(con!=null && !con.getAutoCommit()) {
  556.                     con.rollback();
  557.                 }
  558.             }catch(Exception eClose) {
  559.                 // close
  560.             }
  561.            
  562.             throw new CoreException("[DynamicClusterManager.refresh] failed: "+e.getMessage(), e);
  563.         }
  564.         finally {
  565.             try {
  566.                 if(pstmt!=null) {
  567.                     pstmt.close();
  568.                 }
  569.             }catch(Exception eClose) {
  570.                 // close
  571.             }
  572.             try {
  573.                 if(con!=null) {
  574.                     this.driverConfigurazioneDB.releaseConnection(con);
  575.                 }
  576.             }catch(Exception eClose) {
  577.                 // close
  578.             }
  579.         }
  580.     }
  581.    
  582.    
  583.    
  584.     public void deleteOldHostnames(Logger log) throws CoreException {
  585.        
  586.         Connection con = null;
  587.         try {
  588.             con = this.driverConfigurazioneDB.getConnection("DynamicClusterManager.deleteOldHostnames");
  589.                        
  590.             deleteOldHostnames(con, log);
  591.            
  592.             if(!con.getAutoCommit()) {
  593.                 con.commit();
  594.             }
  595.         }
  596.         catch(Exception e) {
  597.            
  598.             try {
  599.                 if(con!=null && !con.getAutoCommit()) {
  600.                     con.rollback();
  601.                 }
  602.             }catch(Exception eClose) {
  603.                 // close
  604.             }
  605.            
  606.             if(e instanceof CoreException) {
  607.                 throw (CoreException) e;
  608.             }
  609.             else {
  610.                 throw new CoreException("[DynamicClusterManager.deleteOldHostnames] failed: "+e.getMessage(), e);
  611.             }
  612.         }
  613.         finally {
  614.             try {
  615.                 if(con!=null) {
  616.                     this.driverConfigurazioneDB.releaseConnection(con);
  617.                 }
  618.             }catch(Exception eClose) {
  619.                 // close
  620.             }
  621.         }
  622.        
  623.     }
  624.     private void deleteOldHostnames(Connection con, Logger log) throws CoreException {
  625.        
  626.         String gruppo = null;
  627.         String oldData = null;
  628.         try {
  629.             gruppo = this.op2Properties.getGroupId(this.rateLimitingGestioneCluster);
  630.             Timestamp oldest = getTimestampRefresh(this.op2Properties.getClusterDinamicoRefreshSecondsInterval());
  631.             oldData = DateUtils.getSimpleDateFormatMs().format(oldest);
  632.            
  633.             List<String> listOldHostnames = getHostnames(con, this.driverConfigurazioneDB.getTipoDB(),
  634.                     gruppo,
  635.                     oldest,
  636.                     true
  637.                     );
  638.             if(!listOldHostnames.isEmpty()) {
  639.                 for (String hostname : listOldHostnames) {
  640.                     unregister(con, log, hostname);
  641.                 }
  642.             }
  643.            
  644.         }
  645.         catch(Exception e) {
  646.             throw new CoreException("[DynamicClusterManager.deleteOldHostnames] (groupId:"+gruppo+" oldestDate:"+oldData+") failed: "+e.getMessage(), e);
  647.         }
  648.        
  649.     }
  650.    
  651.    
  652.     public List<String> getHostnames(Logger log) throws CoreException {
  653.         Connection con = null;
  654.         String gruppo = null;
  655.         String oldData = null;
  656.         try {
  657.             gruppo = this.op2Properties.getGroupId(this.rateLimitingGestioneCluster);
  658.             Timestamp oldest = getTimestampRefresh(this.op2Properties.getClusterDinamicoRefreshSecondsInterval());
  659.             oldData = DateUtils.getSimpleDateFormatMs().format(oldest);
  660.             con = this.driverConfigurazioneDB.getConnection("DynamicClusterManager.refresh");
  661.            
  662.             List<String> l = getHostnames(con, this.driverConfigurazioneDB.getTipoDB(),
  663.                     gruppo,
  664.                     oldest,
  665.                     false
  666.                     );
  667.             if(l.isEmpty()) {
  668.                 throw new CoreException("nodes not found");
  669.             }
  670.             return l;
  671.         }
  672.         catch(Exception e) {
  673.             if(log!=null) {
  674.                 // per adesso rilancio l'eccezione
  675.             }
  676.             throw new CoreException("[DynamicClusterManager.getHostnames] (groupId:"+gruppo+" oldestDate:"+oldData+") failed: "+e.getMessage(), e);
  677.         }
  678.         finally {
  679.             try {
  680.                 if(con!=null) {
  681.                     this.driverConfigurazioneDB.releaseConnection(con);
  682.                 }
  683.             }catch(Exception eClose) {
  684.                 // close
  685.             }
  686.         }
  687.     }
  688.    
  689.     private static Timestamp getTimestampRefresh(int refreshSecondsInterval) {
  690.         int oldSeconds = refreshSecondsInterval*2; // raddoppio il tempo di refresh
  691.         // aggiungo ancora la metà
  692.         oldSeconds = oldSeconds + (refreshSecondsInterval/2);
  693.         // Timestamp oldest
  694.         return new Timestamp(System.currentTimeMillis()-(oldSeconds*1000));
  695.     }
  696.    
  697.     public static List<String> getHostnames(Connection con, String tipoDB, String gruppo, int refreshSecondsInterval) throws CoreException {
  698.         Timestamp oldest = getTimestampRefresh(refreshSecondsInterval);
  699.         return getHostnames(con, tipoDB, gruppo, oldest, false);
  700.     }
  701.     public static List<String> getHostnames(Connection con, String tipoDB, String gruppo, Timestamp oldest, boolean returnOldHostname) throws CoreException {
  702.         PreparedStatement pstmt = null;
  703.         ResultSet rs = null;
  704.         try {
  705.             List<String> list = new ArrayList<>();
  706.             ISQLQueryObject sqlQueryObject = SQLObjectFactory.createSQLQueryObject(tipoDB);
  707.             sqlQueryObject.addFromTable(CostantiDB.CONFIG_NODI_RUNTIME);
  708.             sqlQueryObject.addSelectField(CostantiDB.CONFIG_NODI_RUNTIME_COLUMN_HOSTNAME);
  709.             sqlQueryObject.setANDLogicOperator(true);
  710.             sqlQueryObject.addWhereCondition(CostantiDB.CONFIG_NODI_RUNTIME_COLUMN_GRUPPO+"=?");
  711.             if(returnOldHostname) {
  712.                 sqlQueryObject.addWhereCondition(CostantiDB.CONFIG_NODI_RUNTIME_COLUMN_DATA_REFRESH+"<?");
  713.             }
  714.             else {
  715.                 sqlQueryObject.addWhereCondition(CostantiDB.CONFIG_NODI_RUNTIME_COLUMN_DATA_REFRESH+">?");
  716.             }
  717.             sqlQueryObject.addOrderBy(CostantiDB.CONFIG_NODI_RUNTIME_COLUMN_DATA_REFRESH, true); // parto dal piu' vecchio
  718.             String update = sqlQueryObject.createSQLQuery();
  719.             pstmt = con.prepareStatement(update);
  720.             int index = 1;
  721.             pstmt.setString(index++, gruppo);
  722.             pstmt.setTimestamp(index++, oldest);
  723.             rs = pstmt.executeQuery();
  724.             while(rs.next()) {
  725.                 String hostname = rs.getString(CostantiDB.CONFIG_NODI_RUNTIME_COLUMN_HOSTNAME);
  726.                 list.add(hostname);
  727.             }
  728.             rs.close(); rs = null;
  729.             pstmt.close(); pstmt = null;
  730.             return list;
  731.         }
  732.         catch(Exception e) {
  733.             throw new CoreException("[DynamicClusterManager.refresh] failed: "+e.getMessage(), e);
  734.         }
  735.         finally {
  736.             try {
  737.                 if(rs!=null) {
  738.                     rs.close();
  739.                 }
  740.             }catch(Exception eClose) {
  741.                 // close
  742.             }
  743.             try {
  744.                 if(pstmt!=null) {
  745.                     pstmt.close();
  746.                 }
  747.             }catch(Exception eClose) {
  748.                 // close
  749.             }
  750.         }
  751.     }
  752.    
  753.     public static String hashClusterId(String id) {
  754.         return DigestUtils.sha256Hex(id);
  755.     }
  756.    
  757.    
  758.    
  759.    
  760.    
  761.    
  762.    
  763.     public void registerOperation(Logger log, String descrizione, String operazione) throws CoreException {
  764.         Connection con = null;
  765.         PreparedStatement pstmt = null;
  766.         try {
  767.             if(descrizione==null) {
  768.                 throw new CoreException("Param 'descrizione' undefined");
  769.             }
  770.             if(operazione==null) {
  771.                 throw new CoreException("Param 'operazione' undefined");
  772.             }
  773.            
  774.             con = this.driverConfigurazioneDB.getConnection("DynamicClusterManager.registerOperation");
  775.            
  776.             ISQLQueryObject sqlQueryObject = SQLObjectFactory.createSQLQueryObject(this.driverConfigurazioneDB.getTipoDB());
  777.             sqlQueryObject.addInsertTable(CostantiDB.CONFIG_NODI_RUNTIME_OPERATIONS);
  778.             sqlQueryObject.addInsertField(CostantiDB.CONFIG_NODI_RUNTIME_OPERATIONS_COLUMN_DESCRIZIONE, "?");
  779.             sqlQueryObject.addInsertField(CostantiDB.CONFIG_NODI_RUNTIME_OPERATIONS_COLUMN_OPERAZIONE, "?");
  780.             sqlQueryObject.addInsertField(CostantiDB.CONFIG_NODI_RUNTIME_OPERATIONS_COLUMN_DATA_REGISTRAZIONE, "?");
  781.             String insert = sqlQueryObject.createSQLInsert();
  782.             pstmt = con.prepareStatement(insert);
  783.             int index = 1;
  784.             pstmt.setString(index++, descrizione);
  785.             pstmt.setString(index++, operazione);
  786.             Timestamp now = DateManager.getTimestamp();
  787.             pstmt.setTimestamp(index++, now);
  788.             int row = pstmt.executeUpdate();
  789.            
  790.             String msg = "Registrata operazione '"+descrizione+"'"+getSuffixMessageUpdate(row);
  791.             log.debug(msg);
  792.            
  793.             if(!con.getAutoCommit()) {
  794.                 con.commit();
  795.             }
  796.         }
  797.         catch(Exception e) {
  798.            
  799.             try {
  800.                 if(con!=null && !con.getAutoCommit()) {
  801.                     con.rollback();
  802.                 }
  803.             }catch(Exception eClose) {
  804.                 // close
  805.             }
  806.            
  807.             throw new CoreException("[DynamicClusterManager.registerOperation] failed: "+e.getMessage(), e);
  808.         }
  809.         finally {
  810.             try {
  811.                 if(pstmt!=null) {
  812.                     pstmt.close();
  813.                 }
  814.             }catch(Exception eClose) {
  815.                 // close
  816.             }
  817.             try {
  818.                 if(con!=null) {
  819.                     this.driverConfigurazioneDB.releaseConnection(con);
  820.                 }
  821.             }catch(Exception eClose) {
  822.                 // close
  823.             }
  824.         }
  825.     }
  826.    
  827.    
  828.     public List<ProxyOperation> findRemoteOperations(Date dataRegistrazione, Date now, int offset, int limit) throws CoreException {
  829.         Connection con = null;
  830.         PreparedStatement pstmt = null;
  831.         ResultSet rs = null;
  832.         try {
  833.             checkDate(dataRegistrazione, now);
  834.            
  835.             con = this.driverConfigurazioneDB.getConnection("DynamicClusterManager.findRemoteOperations");
  836.            
  837.             ISQLQueryObject sqlQueryObject = SQLObjectFactory.createSQLQueryObject(this.driverConfigurazioneDB.getTipoDB());
  838.             sqlQueryObject.addFromTable(CostantiDB.CONFIG_NODI_RUNTIME_OPERATIONS);
  839.             sqlQueryObject.addSelectField(CostantiDB.CONFIG_NODI_RUNTIME_OPERATIONS_COLUMN_DESCRIZIONE);
  840.             sqlQueryObject.addSelectField(CostantiDB.CONFIG_NODI_RUNTIME_OPERATIONS_COLUMN_OPERAZIONE);
  841.             sqlQueryObject.addSelectField(CostantiDB.CONFIG_NODI_RUNTIME_OPERATIONS_COLUMN_DATA_REGISTRAZIONE);
  842.             sqlQueryObject.addWhereCondition(CostantiDB.CONFIG_NODI_RUNTIME_OPERATIONS_COLUMN_DATA_REGISTRAZIONE+">=?");
  843.             sqlQueryObject.addWhereCondition(CostantiDB.CONFIG_NODI_RUNTIME_OPERATIONS_COLUMN_DATA_REGISTRAZIONE+"<?");
  844.             boolean asc = true;
  845.             sqlQueryObject.addOrderBy(CostantiDB.CONFIG_NODI_RUNTIME_OPERATIONS_COLUMN_DATA_REGISTRAZIONE, asc);
  846.             sqlQueryObject.setANDLogicOperator(true);
  847.             if(offset>=0) {
  848.                 sqlQueryObject.setOffset(offset);
  849.             }
  850.             if(limit>0) {
  851.                 sqlQueryObject.setLimit(limit);
  852.             }
  853.            
  854.             String query = sqlQueryObject.createSQLQuery();
  855.            
  856.             List<ProxyOperation> list = new ArrayList<>();
  857.            
  858.             pstmt = con.prepareStatement(query);
  859.             int index = 1;
  860.             pstmt.setTimestamp(index++, new Timestamp(dataRegistrazione.getTime()));
  861.             pstmt.setTimestamp(index++, new Timestamp(now.getTime()));
  862.             rs = pstmt.executeQuery();
  863.             while(rs.next()) {
  864.                 list.add(readProxyOperation(rs));
  865.             }
  866.            
  867.             return list;
  868.         }
  869.         catch(Exception e) {
  870.            
  871.             try {
  872.                 if(con!=null && !con.getAutoCommit()) {
  873.                     con.rollback();
  874.                 }
  875.             }catch(Exception eClose) {
  876.                 // close
  877.             }
  878.            
  879.             throw new CoreException("[DynamicClusterManager.findRemoteOperations] failed: "+e.getMessage(), e);
  880.         }
  881.         finally {
  882.             try {
  883.                 if(rs!=null) {
  884.                     rs.close();
  885.                 }
  886.             }catch(Exception eClose) {
  887.                 // close
  888.             }
  889.             try {
  890.                 if(pstmt!=null) {
  891.                     pstmt.close();
  892.                 }
  893.             }catch(Exception eClose) {
  894.                 // close
  895.             }
  896.             try {
  897.                 if(con!=null) {
  898.                     this.driverConfigurazioneDB.releaseConnection(con);
  899.                 }
  900.             }catch(Exception eClose) {
  901.                 // close
  902.             }
  903.         }
  904.     }
  905.     private void checkDate(Date dataRegistrazione, Date now) throws CoreException {
  906.         if(dataRegistrazione==null) {
  907.             throw new CoreException("Param 'dataRegistrazione' undefined");
  908.         }
  909.         if(now==null) {
  910.             throw new CoreException("Param 'now' undefined");
  911.         }
  912.     }
  913.     private ProxyOperation readProxyOperation(ResultSet rs) throws SQLException, CoreException {
  914.         if(rs==null) {
  915.             throw new CoreException("Param 'rs' undefined");
  916.         }
  917.        
  918.         String descrizione = rs.getString(CostantiDB.CONFIG_NODI_RUNTIME_OPERATIONS_COLUMN_DESCRIZIONE);
  919.         String operazione = rs.getString(CostantiDB.CONFIG_NODI_RUNTIME_OPERATIONS_COLUMN_OPERAZIONE);
  920.         Date dataRegistrazioneReaded = rs.getTimestamp(CostantiDB.CONFIG_NODI_RUNTIME_OPERATIONS_COLUMN_DATA_REGISTRAZIONE);
  921.         ProxyOperation po = new ProxyOperation();
  922.         po.setCommand(operazione);
  923.         po.setDescription(descrizione);
  924.         po.setRegistrationTime(dataRegistrazioneReaded);
  925.         return po;
  926.     }
  927.    
  928.     public int deleteRemoteOperations(Date dataRegistrazione) throws CoreException {
  929.         Connection con = null;
  930.         PreparedStatement pstmt = null;
  931.         try {
  932.             if(dataRegistrazione==null) {
  933.                 throw new CoreException("Param 'dataRegistrazione' undefined");
  934.             }
  935.            
  936.             con = this.driverConfigurazioneDB.getConnection("DynamicClusterManager.deleteRemoteOperations");
  937.            
  938.             ISQLQueryObject sqlQueryObject = SQLObjectFactory.createSQLQueryObject(this.driverConfigurazioneDB.getTipoDB());
  939.             sqlQueryObject.addDeleteTable(CostantiDB.CONFIG_NODI_RUNTIME_OPERATIONS);
  940.             sqlQueryObject.addWhereCondition(CostantiDB.CONFIG_NODI_RUNTIME_OPERATIONS_COLUMN_DATA_REGISTRAZIONE+"<?");
  941.             sqlQueryObject.setANDLogicOperator(true);
  942.            
  943.             String query = sqlQueryObject.createSQLDelete();
  944.            
  945.             pstmt = con.prepareStatement(query);
  946.             int index = 1;
  947.             pstmt.setTimestamp(index++, new Timestamp(dataRegistrazione.getTime()));
  948.             return pstmt.executeUpdate();
  949.         }
  950.         catch(Exception e) {
  951.            
  952.             try {
  953.                 if(con!=null && !con.getAutoCommit()) {
  954.                     con.rollback();
  955.                 }
  956.             }catch(Exception eClose) {
  957.                 // close
  958.             }
  959.            
  960.             throw new CoreException("[DynamicClusterManager.deleteRemoteOperations] failed: "+e.getMessage(), e);
  961.         }
  962.         finally {
  963.             try {
  964.                 if(pstmt!=null) {
  965.                     pstmt.close();
  966.                 }
  967.             }catch(Exception eClose) {
  968.                 // close
  969.             }
  970.             try {
  971.                 if(con!=null) {
  972.                     this.driverConfigurazioneDB.releaseConnection(con);
  973.                 }
  974.             }catch(Exception eClose) {
  975.                 // close
  976.             }
  977.         }
  978.     }
  979. }