GestoreLoadBalancerCaching.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.core.behaviour.built_in.load_balance;

  21. import java.util.ArrayList;
  22. import java.util.Date;
  23. import java.util.List;

  24. import org.openspcoop2.core.commons.CoreException;
  25. import org.openspcoop2.core.config.PortaApplicativa;
  26. import org.openspcoop2.core.config.PortaApplicativaServizioApplicativo;
  27. import org.openspcoop2.core.config.Proprieta;
  28. import org.openspcoop2.core.config.constants.CostantiConfigurazione;
  29. import org.openspcoop2.core.config.constants.StatoFunzionalita;
  30. import org.openspcoop2.core.config.constants.TipoBehaviour;
  31. import org.openspcoop2.core.id.IDPortaApplicativa;
  32. import org.openspcoop2.message.OpenSPCoop2Message;
  33. import org.openspcoop2.pdd.core.PdDContext;
  34. import org.openspcoop2.pdd.core.behaviour.BehaviourEmitDiagnosticException;
  35. import org.openspcoop2.pdd.core.behaviour.BehaviourException;
  36. import org.openspcoop2.pdd.core.behaviour.built_in.load_balance.health_check.HealthCheckUtils;
  37. import org.openspcoop2.pdd.core.behaviour.built_in.load_balance.sticky.StickyConnector;
  38. import org.openspcoop2.pdd.core.behaviour.built_in.load_balance.sticky.StickyResult;
  39. import org.openspcoop2.pdd.core.behaviour.built_in.load_balance.sticky.StickyUtils;
  40. import org.openspcoop2.pdd.core.behaviour.conditional.ConditionalFilterResult;
  41. import org.openspcoop2.pdd.core.behaviour.conditional.ConditionalUtils;
  42. import org.openspcoop2.pdd.logger.MsgDiagnostico;
  43. import org.openspcoop2.pdd.logger.OpenSPCoop2Logger;
  44. import org.openspcoop2.protocol.engine.ProtocolFactoryManager;
  45. import org.openspcoop2.protocol.sdk.Busta;
  46. import org.openspcoop2.protocol.sdk.IProtocolFactory;
  47. import org.openspcoop2.protocol.sdk.state.IState;
  48. import org.openspcoop2.protocol.sdk.state.RequestInfo;
  49. import org.openspcoop2.protocol.utils.PorteNamingUtils;
  50. import org.openspcoop2.utils.SemaphoreLock;
  51. import org.openspcoop2.utils.UtilsException;
  52. import org.openspcoop2.utils.cache.Cache;
  53. import org.openspcoop2.utils.cache.CacheAlgorithm;
  54. import org.openspcoop2.utils.cache.CacheType;
  55. import org.openspcoop2.utils.date.DateManager;
  56. import org.openspcoop2.utils.date.DateUtils;
  57. import org.slf4j.Logger;

  58. /**    
  59.  * GestoreCacheKeystore
  60.  *
  61.  * @author Poli Andrea (poli@link.it)
  62.  * @author $Author$
  63.  * @version $Rev$, $Date$
  64.  */
  65. public class GestoreLoadBalancerCaching {

  66.     /** Chiave della cache */
  67.     private static final String LOAD_BALANCER_CACHE_NAME = "consegnaApplicativi";
  68.     /** Cache */
  69.     private static Cache cache = null;
  70.     private static final org.openspcoop2.utils.Semaphore lock = new org.openspcoop2.utils.Semaphore("GestoreLoadBalancerCaching");
  71.    

  72.     /* --------------- Cache --------------------*/
  73.     public static boolean isCacheAbilitata() {
  74.         return cache!=null;
  75.     }
  76.     public static void resetCache() throws Exception{
  77.         try{
  78.             if(cache!=null){
  79.                 cache.clear();
  80.             }
  81.         }catch(Exception e){
  82.             throw new Exception("Reset della cache per i dati contenenti i dati di bilanciamento del carico non riuscita: "+e.getMessage(),e);
  83.         }
  84.     }
  85.     public static String printStatsCache(String separator) throws Exception{
  86.         try{
  87.             if(cache!=null){
  88.                 try{
  89.                     return cache.printStats(separator);
  90.                 }catch(Exception e){
  91.                     throw new Exception(e.getMessage(),e);
  92.                 }
  93.             }else{
  94.                 throw new Exception("Cache non abilitata");
  95.             }
  96.         }catch(Exception e){
  97.             throw new Exception("Visualizzazione Statistiche riguardante la cache per i dati contenenti i dati di bilanciamento del carico non riuscita: "+e.getMessage(),e);
  98.         }
  99.     }
  100.     public static void abilitaCache() throws Exception{
  101.         try{
  102.             if(cache!=null)
  103.                 throw new Exception("Cache gia' abilitata");
  104.             else{
  105.                 _abilitaCache();
  106.             }
  107.         }catch(Exception e){
  108.             throw new Exception("Abilitazione cache per i dati contenenti i dati di bilanciamento del carico non riuscita: "+e.getMessage(),e);
  109.         }
  110.     }
  111.     private static synchronized void _abilitaCache() throws Exception{
  112.         try{
  113.             if(cache==null) {
  114.                 cache = new Cache(CacheType.JCS, LOAD_BALANCER_CACHE_NAME);  // lascio JCS come default abilitato via jmx
  115.                 cache.build();
  116.             }
  117.         }catch(Exception e){
  118.             throw new Exception("Abilitazione cache per i dati contenenti i dati di bilanciamento del carico non riuscita: "+e.getMessage(),e);
  119.         }
  120.     }
  121.     public static void abilitaCache(Long dimensioneCache,Boolean algoritmoCacheLRU,Long itemIdleTime,Long itemLifeSecond, Logger log) throws Exception{
  122.         try{
  123.             if(cache!=null)
  124.                 throw new Exception("Cache gia' abilitata");
  125.             else{
  126.                 int dimensione = -1;
  127.                 if(dimensioneCache!=null){
  128.                     dimensione = dimensioneCache.intValue();
  129.                 }
  130.                 initCache(CacheType.JCS, dimensione, algoritmoCacheLRU, itemIdleTime, itemLifeSecond, log);  // lascio JCS come default abilitato via jmx
  131.             }
  132.         }catch(Exception e){
  133.             throw new Exception("Abilitazione cache per i dati contenenti i dati di bilanciamento del carico non riuscita: "+e.getMessage(),e);
  134.         }
  135.     }
  136.     public static void disabilitaCache() throws Exception{
  137.         try{
  138.             if(cache==null)
  139.                 throw new Exception("Cache gia' disabilitata");
  140.             else{
  141.                 _disabilitaCache();
  142.             }
  143.         }catch(Exception e){
  144.             throw new Exception("Disabilitazione cache per i dati contenenti i dati di bilanciamento del carico non riuscita: "+e.getMessage(),e);
  145.         }
  146.     }  
  147.     private static synchronized void _disabilitaCache() throws Exception{
  148.         try{
  149.             if(cache!=null) {
  150.                 cache.clear();
  151.                 cache = null;
  152.             }
  153.         }catch(Exception e){
  154.             throw new Exception("Disabilitazione cache per i dati contenenti i dati di bilanciamento del carico non riuscita: "+e.getMessage(),e);
  155.         }
  156.     }  
  157.     public static String listKeysCache(String separator) throws Exception{
  158.         try{
  159.             if(cache!=null){
  160.                 try{
  161.                     return cache.printKeys(separator);
  162.                 }catch(Exception e){
  163.                     throw new Exception(e.getMessage(),e);
  164.                 }
  165.             }else{
  166.                 throw new Exception("Cache non abilitata");
  167.             }
  168.         }catch(Exception e){
  169.             throw new Exception("Visualizzazione chiavi presenti nella cache per i dati contenenti i dati di bilanciamento del carico non riuscita: "+e.getMessage(),e);
  170.         }
  171.     }
  172.     public static List<String> keysCache() throws Exception{
  173.         if(cache!=null){
  174.             try{
  175.                 return cache.keys();
  176.             }catch(Exception e){
  177.                 throw new Exception(e.getMessage(),e);
  178.             }
  179.         }else{
  180.             throw new Exception("Cache non abilitata");
  181.         }
  182.     }
  183.     public static String getObjectCache(String key) throws Exception{
  184.         try{
  185.             if(cache!=null){
  186.                 try{
  187.                     Object o = cache.get(key);
  188.                     if(o!=null){
  189.                         return o.toString();
  190.                     }else{
  191.                         return "oggetto con chiave ["+key+"] non presente";
  192.                     }
  193.                 }catch(Exception e){
  194.                     throw new Exception(e.getMessage(),e);
  195.                 }
  196.             }else{
  197.                 throw new Exception("Cache non abilitata");
  198.             }
  199.         }catch(Exception e){
  200.             throw new Exception("Visualizzazione oggetto presente nella cache per i dati contenenti i dati di bilanciamento del carico non riuscita: "+e.getMessage(),e);
  201.         }
  202.     }
  203.    
  204.     public static void removeObjectCache(String key) throws Exception{
  205.         try{
  206.             if(cache!=null){
  207.                 try{
  208.                     cache.remove(key);
  209.                 }catch(Exception e){
  210.                     throw new Exception(e.getMessage(),e);
  211.                 }
  212.             }else{
  213.                 throw new Exception("Cache non abilitata");
  214.             }
  215.         }catch(Exception e){
  216.             throw new Exception("Rimozione oggetto presente nella cache per i dati contenenti i dati di bilanciamento del carico non riuscita: "+e.getMessage(),e);
  217.         }
  218.     }
  219.    
  220.    
  221.    
  222.    
  223.    
  224.     /*----------------- CLEANER --------------------*/
  225.    
  226.     public static void removePortaApplicativa(IDPortaApplicativa idPA) throws Exception {
  227.        
  228.         if(cache!=null){
  229.            
  230.             IProtocolFactory<?> protocolFactory = null;
  231.             PorteNamingUtils namingUtils = null;
  232.             try {
  233.                 ProtocolFactoryManager protocolFactoryManager = ProtocolFactoryManager.getInstance();
  234.                 String protocol = protocolFactoryManager.getProtocolByOrganizationType(idPA.getIdentificativiErogazione().getIdServizio().getSoggettoErogatore().getTipo());
  235.                 protocolFactory = protocolFactoryManager.getProtocolFactoryByName(protocol);
  236.                 namingUtils = new PorteNamingUtils(protocolFactory);
  237.             }catch(Throwable t) {
  238.                 OpenSPCoop2Logger.getLoggerOpenSPCoopCore().error("Errore durante la comprensione del protocol factory della PA ["+idPA+"]");
  239.             }
  240.            
  241.             String nomePorta = idPA.getNome();
  242.             String nomePorta_normalized = null;
  243.             if(namingUtils!=null) {
  244.                 nomePorta_normalized = namingUtils.normalizePA(nomePorta);
  245.             }
  246.            
  247.             String porta = _toKey_getKeyCacheNomePorta(nomePorta);
  248.             String porta_normalized = null;
  249.             if(nomePorta_normalized!=null){
  250.                 porta_normalized = _toKey_getKeyCacheNomePorta(nomePorta_normalized);
  251.             }
  252.            
  253.             List<String> keyForClean = new ArrayList<>();
  254.             List<String> keys = GestoreLoadBalancerCaching.keysCache();
  255.             if(keys!=null && !keys.isEmpty()) {
  256.                 for (String key : keys) {
  257.                     if(key!=null) {
  258.                         if(key.contains(porta)) {
  259.                             keyForClean.add(key);
  260.                         }
  261.                         else if(porta_normalized!=null && key.contains(porta_normalized)) {
  262.                             keyForClean.add(key);
  263.                         }
  264.                     }
  265.                 }
  266.             }
  267.             if(keyForClean!=null && !keyForClean.isEmpty()) {
  268.                 for (String key : keyForClean) {
  269.                     removeObjectCache(key);
  270.                 }
  271.             }
  272.            
  273.         }
  274.     }
  275.    
  276.    
  277.    

  278.     /*----------------- INIZIALIZZAZIONE --------------------*/

  279.     public static void initialize(Logger log) throws Exception{
  280.         GestoreLoadBalancerCaching.initialize(null, false, -1,null,-1l,-1l, log);
  281.     }
  282.     public static void initialize(CacheType cacheType, int dimensioneCache,String algoritmoCache,
  283.             long idleTime, long itemLifeSecond, Logger log) throws Exception{
  284.         GestoreLoadBalancerCaching.initialize(cacheType, true, dimensioneCache,algoritmoCache,idleTime,itemLifeSecond, log);
  285.     }

  286.     private static void initialize(CacheType cacheType, boolean cacheAbilitata,int dimensioneCache,String algoritmoCache,
  287.             long idleTime, long itemLifeSecond, Logger log) throws Exception{

  288.         // Inizializzazione Cache
  289.         if(cacheAbilitata){
  290.             GestoreLoadBalancerCaching.initCache(cacheType, dimensioneCache, algoritmoCache, idleTime, itemLifeSecond, log);
  291.         }

  292.     }
  293.     private static void initCache(CacheType cacheType, Integer dimensioneCache,String algoritmoCache,Long itemIdleTime,Long itemLifeSecond,Logger alog) throws Exception{
  294.         initCache(cacheType, dimensioneCache, CostantiConfigurazione.CACHE_LRU.toString().equalsIgnoreCase(algoritmoCache), itemIdleTime, itemLifeSecond, alog);
  295.     }
  296.    
  297.     private static void initCache(CacheType cacheType, Integer dimensioneCache,boolean algoritmoCacheLRU,Long itemIdleTime,Long itemLifeSecond,Logger alog) throws Exception{
  298.        
  299.         cache = new Cache(cacheType, LOAD_BALANCER_CACHE_NAME);
  300.    
  301.         // dimensione
  302.         if(dimensioneCache!=null && dimensioneCache>0){
  303.             try{
  304.                 String msg = "Dimensione della cache (ResponseCaching) impostata al valore: "+dimensioneCache;
  305.                 alog.info(msg);
  306.                 cache.setCacheSize(dimensioneCache);
  307.             }catch(Exception error){
  308.                 String msg = "Parametro errato per la dimensione della cache (ResponseCaching): "+error.getMessage();
  309.                 alog.error(msg);
  310.                 throw new Exception(msg,error);
  311.             }
  312.         }
  313.        
  314.         // algoritno
  315.         String msg = "Algoritmo di cache (ResponseCaching) impostato al valore: LRU";
  316.         if(!algoritmoCacheLRU){
  317.             msg = "Algoritmo di cache (ResponseCaching) impostato al valore: MRU";
  318.         }
  319.         alog.info(msg);
  320.         if(!algoritmoCacheLRU)
  321.             cache.setCacheAlgoritm(CacheAlgorithm.MRU);
  322.         else
  323.             cache.setCacheAlgoritm(CacheAlgorithm.LRU);
  324.        
  325.        
  326.         // idle time
  327.         if(itemIdleTime!=null && itemIdleTime>0){
  328.             try{
  329.                 msg = "Attributo 'IdleTime' (ResponseCaching) impostato al valore: "+itemIdleTime;
  330.                 alog.info(msg);
  331.                 cache.setItemIdleTime(itemIdleTime);
  332.             }catch(Exception error){
  333.                 msg = "Parametro errato per l'attributo 'IdleTime' (ResponseCaching): "+error.getMessage();
  334.                 alog.error(msg);
  335.                 throw new Exception(msg,error);
  336.             }
  337.         }
  338.        
  339.         // LifeSecond
  340.         long longItemLife = -1;
  341.         if(itemLifeSecond!=null && itemLifeSecond>0){
  342.             longItemLife = itemLifeSecond.longValue();
  343.         }
  344.         try{
  345.             msg = "Attributo 'MaxLifeSecond' (ResponseCaching) impostato al valore: "+longItemLife;
  346.             alog.info(msg);
  347.             cache.setItemLifeTime(longItemLife);
  348.         }catch(Exception error){
  349.             msg = "Parametro errato per l'attributo 'MaxLifeSecond' (ResponseCaching): "+error.getMessage();
  350.             alog.error(msg);
  351.             throw new Exception(msg,error);
  352.         }
  353.        
  354.         cache.build();
  355.     }
  356.    
  357.     @SuppressWarnings("deprecation")
  358.     @Deprecated
  359.     public static void disableSyncronizedGet() throws UtilsException {
  360.         if(GestoreLoadBalancerCaching.cache==null) {
  361.             throw new UtilsException("Cache disabled");
  362.         }
  363.         GestoreLoadBalancerCaching.cache.disableSyncronizedGet();
  364.     }
  365.     @SuppressWarnings("deprecation")
  366.     @Deprecated
  367.     public static boolean isDisableSyncronizedGet() throws UtilsException {
  368.         if(GestoreLoadBalancerCaching.cache==null) {
  369.             throw new UtilsException("Cache disabled");
  370.         }
  371.         return GestoreLoadBalancerCaching.cache.isDisableSyncronizedGet();
  372.     }
  373.    
  374.    

  375.    
  376.    
  377.     private static GestoreLoadBalancerCaching staticInstance = null;
  378.     public static synchronized void initialize() {
  379.         if(staticInstance==null){
  380.             staticInstance = new GestoreLoadBalancerCaching();
  381.         }
  382.     }
  383.     public static GestoreLoadBalancerCaching getInstance() throws CoreException{
  384.         if(staticInstance==null){
  385.             // spotbugs warning 'SING_SINGLETON_GETTER_NOT_SYNCHRONIZED': l'istanza viene creata allo startup
  386.             synchronized (GestoreLoadBalancerCaching.class) {
  387.                 throw new CoreException("GestoreKeystore non inizializzato");
  388.             }
  389.         }
  390.         return staticInstance;
  391.     }
  392.    
  393.     @SuppressWarnings("unused")
  394.     private Logger log;
  395.    
  396.     private GestoreLoadBalancerCaching() {
  397.         this.log = OpenSPCoop2Logger.getLoggerOpenSPCoopCore();
  398.     }
  399.    
  400.    
  401.    
  402.    
  403.    
  404.    
  405.    
  406.    
  407.    
  408.     /* ********************** ENGINE ************************** */
  409.    
  410.     public static LoadBalancerInstance getLoadBalancerInstance(PortaApplicativa pa, OpenSPCoop2Message message, Busta busta,
  411.             RequestInfo requestInfo, PdDContext pddContext,
  412.             MsgDiagnostico msgDiag, Logger log,
  413.             LoadBalancerType loadBalancerType, IState state) throws BehaviourException, BehaviourEmitDiagnosticException{
  414.        
  415.         LoadBalancerInstance instance = new LoadBalancerInstance();
  416.        
  417.         ConditionalFilterResult filterResult =
  418.                 ConditionalUtils.filter(pa, message, busta, requestInfo, pddContext, msgDiag, log,
  419.                         TipoBehaviour.CONSEGNA_LOAD_BALANCE, state);
  420.        
  421.         String keyCache = getKeyCache(pa, message, busta,
  422.                 requestInfo, pddContext,
  423.                 msgDiag, log,
  424.                 filterResult);
  425.        
  426.         String keyCacheLoadBalancerPool = "[POOL] "+keyCache;
  427.         instance.setLoadBalancerPool(getLoadBalancerPool(pa, message, busta,
  428.                 requestInfo, pddContext,
  429.                 msgDiag, log,
  430.                 keyCacheLoadBalancerPool, filterResult));
  431.        
  432.         StickyResult stickyResult = null;
  433.         if(LoadBalancerType.IP_HASH.equals(loadBalancerType)) {
  434.             String clientIp = LoadBalancer.getIpSourceFromContet(pddContext);
  435.             stickyResult = new StickyResult();
  436.             stickyResult.setCondition(clientIp);
  437.             stickyResult.setFound(true);
  438.         }
  439.         else {
  440.             stickyResult = getStickyInfo(pa, message, busta,
  441.                     requestInfo, pddContext,
  442.                     msgDiag, log,
  443.                     state);
  444.         }
  445.        
  446.         if(stickyResult!=null && stickyResult.isFound()) {
  447.             String keyCacheSticky = "[STICKY '"+stickyResult.getCondition()+"'] "+keyCache;
  448.             instance.setConnectorSelected(getNomeConnettore(pa, message, busta,
  449.                     requestInfo, pddContext,
  450.                     msgDiag, log,
  451.                     keyCacheSticky, instance.getLoadBalancerPool(), loadBalancerType, stickyResult));
  452.         }
  453.        
  454.         if(instance.getConnectorSelected()==null) {
  455.             instance.setConnectorSelected(selectConnector(loadBalancerType, instance.getLoadBalancerPool(), pddContext));
  456.         }
  457.        
  458.         return instance;
  459.     }
  460.    
  461.     private static StickyResult getStickyInfo(PortaApplicativa pa, OpenSPCoop2Message message, Busta busta,
  462.             RequestInfo requestInfo, PdDContext pddContext,
  463.             MsgDiagnostico msgDiag, Logger log,
  464.             IState state) throws BehaviourException, BehaviourEmitDiagnosticException{
  465.        
  466.         if(StickyUtils.isConfigurazioneSticky(pa, log)) {
  467.             return StickyUtils.getStickyResult(pa, message, busta, requestInfo, pddContext, msgDiag, log, state);
  468.         }
  469.        
  470.         return null;
  471.        
  472.     }
  473.    
  474.     protected static String _toKey_getKeyCacheNomePorta(String nomePorta) {
  475.         return " pa:"+nomePorta+" ";
  476.     }
  477.    
  478.     private static String getKeyCache(PortaApplicativa pa, OpenSPCoop2Message message, Busta busta,
  479.             RequestInfo requestInfo, PdDContext pddContext,
  480.             MsgDiagnostico msgDiag, Logger log,
  481.             ConditionalFilterResult filterResult) throws BehaviourException, BehaviourEmitDiagnosticException {
  482.        
  483.         String keyCache = "["+pa.getBehaviour().getNome()+"] "+pa.getTipoSoggettoProprietario()+"/"+pa.getNomeSoggettoProprietario()+
  484.                 _toKey_getKeyCacheNomePorta(pa.getNome());
  485.         if(filterResult!=null) {
  486.             if(filterResult.isByFilter()) {
  487.                 keyCache = keyCache +" [Conditional-By-Filter] ";
  488.             }
  489.             else {
  490.                 keyCache = keyCache +" [Conditional-By-Name] ";
  491.             }
  492.             if(filterResult.getRegola()!=null) {
  493.                 keyCache = keyCache +"[Regola "+filterResult.getRegola()+"] ";
  494.             }
  495.             if(filterResult.getCondition()!=null) {
  496.                 keyCache = keyCache +" "+filterResult.getCondition();
  497.             }
  498.         }
  499.        
  500.         return keyCache;
  501.        
  502.     }
  503.    
  504.     private static LoadBalancerPool getLoadBalancerPool(PortaApplicativa pa, OpenSPCoop2Message message, Busta busta,
  505.             RequestInfo requestInfo, PdDContext pddContext,
  506.             MsgDiagnostico msgDiag, Logger log,
  507.             String keyCache, ConditionalFilterResult filterResult) throws BehaviourException, BehaviourEmitDiagnosticException{
  508.        
  509.         if(GestoreLoadBalancerCaching.cache==null){
  510.             throw new BehaviourException("La funzionalità di Load Balancer richiede che sia abilitata la cache dedicata alla funzionalità");
  511.         }
  512.         else{
  513.            
  514.             // Fix: devo prima verificare se ho la chiave in cache prima di mettermi in sincronizzazione.
  515.             org.openspcoop2.utils.cache.CacheResponse response =
  516.                 (org.openspcoop2.utils.cache.CacheResponse) GestoreLoadBalancerCaching.cache.get(keyCache);
  517.             if(response != null){
  518.                 if(response.getObject()!=null){
  519.                     log.debug("Oggetto (tipo:"+response.getObject().getClass().getName()+") con chiave ["+keyCache+"] (method:getLoadBalancerPool) in cache.");
  520.                     return (LoadBalancerPool) response.getObject();
  521.                 }else if(response.getException()!=null){
  522.                     log.debug("Eccezione (tipo:"+response.getException().getClass().getName()+") con chiave ["+keyCache+"] (method:getLoadBalancerPool) in cache.");
  523.                     throw new BehaviourException( (Exception) response.getException() );
  524.                 }else{
  525.                     log.error("In cache non e' presente ne un oggetto ne un'eccezione.");
  526.                 }
  527.             }
  528.            
  529.             String idTransazione = (pddContext!=null && pddContext.containsKey(org.openspcoop2.core.constants.Costanti.ID_TRANSAZIONE)) ? PdDContext.getValue(org.openspcoop2.core.constants.Costanti.ID_TRANSAZIONE, pddContext) : null;
  530.             //synchronized (GestoreLoadBalancerCaching.cache) {
  531.             SemaphoreLock lock = GestoreLoadBalancerCaching.lock.acquireThrowRuntime("getLoadBalancerPool", idTransazione);
  532.             try {
  533.                
  534.                 response =
  535.                     (org.openspcoop2.utils.cache.CacheResponse) GestoreLoadBalancerCaching.cache.get(keyCache);
  536.                 if(response != null){
  537.                     if(response.getObject()!=null){
  538.                         log.debug("Oggetto (tipo:"+response.getObject().getClass().getName()+") con chiave ["+keyCache+"] (method:getLoadBalancerPool) in cache.");
  539.                         return (LoadBalancerPool) response.getObject();
  540.                     }else if(response.getException()!=null){
  541.                         log.debug("Eccezione (tipo:"+response.getException().getClass().getName()+") con chiave ["+keyCache+"] (method:getLoadBalancerPool) in cache.");
  542.                         throw new BehaviourException( (Exception) response.getException() );
  543.                     }else{
  544.                         log.error("In cache non e' presente ne un oggetto ne un'eccezione.");
  545.                     }
  546.                 }

  547.                 // Effettuo la query
  548.                 log.debug("oggetto con chiave ["+keyCache+"] (method:getLoadBalancerPool) ricerco nella configurazione...");
  549.                 LoadBalancerPool lbPool = readLoadBalancerPool(log, pa, filterResult);
  550.                
  551.                 // Aggiungo la risposta in cache (se esiste una cache)  
  552.                 // Sempre. Se la risposta non deve essere cachata l'implementazione può in alternativa:
  553.                 // - impostare una eccezione di processamento (che setta automaticamente noCache a true)
  554.                 // - impostare il noCache a true
  555.                 if(lbPool!=null){
  556.                     log.info("Aggiungo oggetto ["+keyCache+"] in cache");
  557.                     try{    
  558.                         org.openspcoop2.utils.cache.CacheResponse responseCache = new org.openspcoop2.utils.cache.CacheResponse();
  559.                         responseCache.setObject(lbPool);
  560.                         GestoreLoadBalancerCaching.cache.put(keyCache,responseCache);
  561.                     }catch(UtilsException e){
  562.                         log.error("Errore durante l'inserimento in cache ["+keyCache+"]: "+e.getMessage());
  563.                     }
  564.                     return lbPool;
  565.                 }else{
  566.                     throw new BehaviourException("Metodo (getLoadBalancerPool) non è riuscito a costruire un pool");
  567.                 }
  568.             }finally {
  569.                 GestoreLoadBalancerCaching.lock.release(lock, "getLoadBalancerPool", idTransazione);
  570.             }
  571.         }
  572.        
  573.     }
  574.    
  575.    
  576.     private static LoadBalancerPool readLoadBalancerPool(Logger log, PortaApplicativa pa, ConditionalFilterResult filterResult) throws BehaviourException {
  577.        
  578.         List<PortaApplicativaServizioApplicativo> listSA = null;
  579.         if(filterResult==null) {
  580.             listSA = pa.getServizioApplicativoList();
  581.         }
  582.         else {
  583.             listSA = filterResult.getListServiziApplicativi();
  584.         }
  585.        
  586.         LoadBalancerPool pool = new LoadBalancerPool(HealthCheckUtils.read(pa, log));
  587.         if(!listSA.isEmpty()) {
  588.             for (PortaApplicativaServizioApplicativo servizioApplicativo : listSA) {
  589.                 if(servizioApplicativo.getDatiConnettore()==null || servizioApplicativo.getDatiConnettore().getStato()==null ||
  590.                         StatoFunzionalita.ABILITATO.equals(servizioApplicativo.getDatiConnettore().getStato())) {
  591.                     int weight = -1;
  592.                     if(servizioApplicativo.getDatiConnettore()!=null && servizioApplicativo.getDatiConnettore().sizeProprietaList()>0) {
  593.                         String weightDefined = null;
  594.                         for (Proprieta p : servizioApplicativo.getDatiConnettore().getProprietaList()) {
  595.                             if(Costanti.LOAD_BALANCER_WEIGHT.equals(p.getNome())) {
  596.                                 weightDefined = p.getValore();
  597.                             }
  598.                         }
  599.                         if(weightDefined!=null) {
  600.                             try {
  601.                                 weight = Integer.valueOf(weightDefined);
  602.                             }catch(Exception e) {}
  603.                         }
  604.                     }
  605.                     String nomeConnettore = null;
  606.                     if(servizioApplicativo.getDatiConnettore()!=null) {
  607.                         nomeConnettore = servizioApplicativo.getDatiConnettore().getNome();
  608.                     }
  609.                     if(nomeConnettore==null) {
  610.                         nomeConnettore = org.openspcoop2.pdd.core.behaviour.built_in.Costanti.NOME_CONNETTORE_DEFAULT;
  611.                     }
  612.                     if(weight>0) {
  613.                         pool.addConnector(nomeConnettore, weight);
  614.                     }
  615.                     else {
  616.                         pool.addConnector(nomeConnettore);
  617.                     }
  618.                 }
  619.             }
  620.         }
  621.        
  622.         return pool;
  623.     }
  624.    
  625.     private static String getNomeConnettore(PortaApplicativa pa, OpenSPCoop2Message message, Busta busta,
  626.             RequestInfo requestInfo, PdDContext pddContext,
  627.             MsgDiagnostico msgDiag, Logger log,
  628.             String keyCache, LoadBalancerPool loadBalancerPool, LoadBalancerType loadBalancerType, StickyResult stickyResult) throws BehaviourException, BehaviourEmitDiagnosticException{
  629.        
  630.         if(GestoreLoadBalancerCaching.cache==null){
  631.             throw new BehaviourException("La funzionalità di Load Balancer richiede che sia abilitata la cache dedicata alla funzionalità");
  632.         }
  633.         else{
  634.            
  635.             // Fix: devo prima verificare se ho la chiave in cache prima di mettermi in sincronizzazione.
  636.            
  637.             org.openspcoop2.utils.cache.CacheResponse response =
  638.                 (org.openspcoop2.utils.cache.CacheResponse) GestoreLoadBalancerCaching.cache.get(keyCache);
  639.             if(response != null){
  640.                 if(response.getObject()!=null){
  641.                     log.debug("Oggetto (tipo:"+response.getObject().getClass().getName()+") con chiave ["+keyCache+"] (method:getLoadBalancerPool) in cache.");
  642.                    
  643.                     StickyConnector stickyConnector = (StickyConnector) response.getObject();
  644.                     if(stickyConnector.getExpirationDate()!=null) {
  645.                         Date now = DateManager.getDate();
  646.                         if(stickyConnector.getExpirationDate().after(now)){
  647.                             String c = stickyConnector.getConnector();
  648.                             if(loadBalancerPool.getConnectorNames(true).contains(c)) {
  649.                                 return c;
  650.                             }
  651.                             else {
  652.                                 // eseguo operazione in synchronized mode
  653.                             }
  654.                         }
  655.                         else {
  656.                             // eseguo operazione in synchronized mode
  657.                         }
  658.                     }
  659.                     else {
  660.                         String c = stickyConnector.getConnector();
  661.                         if(loadBalancerPool.getConnectorNames(true).contains(c)) {
  662.                             return c;
  663.                         }
  664.                         else {
  665.                             // eseguo operazione in synchronized mode
  666.                         }
  667.                     }
  668.                    
  669.                 }else if(response.getException()!=null){
  670.                     log.debug("Eccezione (tipo:"+response.getException().getClass().getName()+") con chiave ["+keyCache+"] (method:getLoadBalancerPool) in cache.");
  671.                     throw new BehaviourException( (Exception) response.getException() );
  672.                 }else{
  673.                     log.error("In cache non e' presente ne un oggetto ne un'eccezione.");
  674.                 }
  675.             }
  676.            
  677.             String idTransazione = (pddContext!=null && pddContext.containsKey(org.openspcoop2.core.constants.Costanti.ID_TRANSAZIONE)) ? PdDContext.getValue(org.openspcoop2.core.constants.Costanti.ID_TRANSAZIONE, pddContext) : null;
  678.             //synchronized (GestoreLoadBalancerCaching.cache) {
  679.             SemaphoreLock lock = GestoreLoadBalancerCaching.lock.acquireThrowRuntime("getNomeConnettore", idTransazione);
  680.             try {
  681.                
  682.                 response =
  683.                     (org.openspcoop2.utils.cache.CacheResponse) GestoreLoadBalancerCaching.cache.get(keyCache);
  684.                 if(response != null){
  685.                     if(response.getObject()!=null){
  686.                         log.debug("Oggetto (tipo:"+response.getObject().getClass().getName()+") con chiave ["+keyCache+"] (method:getLoadBalancerPool) in cache.");
  687.                        
  688.                         StickyConnector stickyConnector = (StickyConnector) response.getObject();
  689.                         if(stickyConnector.getExpirationDate()!=null) {
  690.                             Date now = DateManager.getDate();
  691.                             if(stickyConnector.getExpirationDate().after(now)){
  692.                                 String c = stickyConnector.getConnector();
  693.                                 if(loadBalancerPool.getConnectorNames(true).contains(c)) {
  694.                                     return c;
  695.                                 }
  696.                                 else {
  697.                                     String msg = "Connettore '"+stickyConnector.getConnector()+"' per sticky '"+stickyResult.getCondition()+"' non risulta più valido dopo il passive health check";
  698.                                     log.debug(msg);
  699.                                     try {
  700.                                         GestoreLoadBalancerCaching.cache.remove(keyCache);
  701.                                     }catch(Exception e) {
  702.                                         throw new BehaviourException(msg+". Rimozione dalla cache non riuscita: "+e.getMessage(),e);
  703.                                     }
  704.                                 }
  705.                             }
  706.                             else {
  707.                                 String msg = "Connettore '"+stickyConnector.getConnector()+"' scaduto per sticky '"+stickyResult.getCondition()+"' in data "+
  708.                                         DateUtils.getSimpleDateFormatMs().format(stickyConnector.getExpirationDate())+"";
  709.                                 log.debug(msg);
  710.                                 try {
  711.                                     GestoreLoadBalancerCaching.cache.remove(keyCache);
  712.                                 }catch(Exception e) {
  713.                                     throw new BehaviourException(msg+". Rimozione dalla cache non riuscita: "+e.getMessage(),e);
  714.                                 }
  715.                             }
  716.                         }
  717.                         else {
  718.                             String c = stickyConnector.getConnector();
  719.                             if(loadBalancerPool.getConnectorNames(true).contains(c)) {
  720.                                 return c;
  721.                             }
  722.                             else {
  723.                                 String msg = "Connettore '"+stickyConnector.getConnector()+"' per sticky '"+stickyResult.getCondition()+"' non risulta più valido dopo il passive health check";
  724.                                 log.debug(msg);
  725.                                 try {
  726.                                     GestoreLoadBalancerCaching.cache.remove(keyCache);
  727.                                 }catch(Exception e) {
  728.                                     throw new BehaviourException(msg+". Rimozione dalla cache non riuscita: "+e.getMessage(),e);
  729.                                 }
  730.                             }
  731.                         }
  732.                        
  733.                     }else if(response.getException()!=null){
  734.                         log.debug("Eccezione (tipo:"+response.getException().getClass().getName()+") con chiave ["+keyCache+"] (method:getLoadBalancerPool) in cache.");
  735.                         throw new BehaviourException( (Exception) response.getException() );
  736.                     }else{
  737.                         log.error("In cache non e' presente ne un oggetto ne un'eccezione.");
  738.                     }
  739.                 }

  740.                 // Effettuo la query
  741.                 log.debug("oggetto con chiave ["+keyCache+"] (method:getNomeConnettore) ricerco nella configurazione...");
  742.                 String selectedConnector = selectConnector(loadBalancerType, loadBalancerPool, pddContext);
  743.                 if(selectedConnector==null) {
  744.                     throw new BehaviourException("Metodo (getNomeConnettore) non è riuscito a selezionare un connettore");
  745.                 }
  746.                 StickyConnector stickyConnector = new StickyConnector();
  747.                 stickyConnector.setConnector(selectedConnector);
  748.                 if(stickyResult.getMaxAgeSeconds()!=null && stickyResult.getMaxAgeSeconds().intValue()>0) {
  749.                     Date expire = new Date((DateManager.getTimeMillis() + (1000*stickyResult.getMaxAgeSeconds().intValue())));
  750.                     stickyConnector.setExpirationDate(expire);
  751.                 }
  752.                
  753.                 // Aggiungo la risposta in cache (se esiste una cache)  
  754.                 // Sempre. Se la risposta non deve essere cachata l'implementazione può in alternativa:
  755.                 // - impostare una eccezione di processamento (che setta automaticamente noCache a true)
  756.                 // - impostare il noCache a true
  757.                 log.info("Aggiungo oggetto ["+keyCache+"] in cache");
  758.                 try{    
  759.                     org.openspcoop2.utils.cache.CacheResponse responseCache = new org.openspcoop2.utils.cache.CacheResponse();
  760.                     responseCache.setObject(stickyConnector);
  761.                     GestoreLoadBalancerCaching.cache.put(keyCache,responseCache);
  762.                 }catch(UtilsException e){
  763.                     log.error("Errore durante l'inserimento in cache ["+keyCache+"]: "+e.getMessage());
  764.                 }
  765.                 return stickyConnector.getConnector();

  766.             }finally {
  767.                 GestoreLoadBalancerCaching.lock.release(lock, "getNomeConnettore", idTransazione);
  768.             }
  769.         }
  770.        
  771.     }

  772.     private static String selectConnector(LoadBalancerType loadBalancerType, LoadBalancerPool pool, PdDContext pddContext) throws BehaviourException {
  773.         LoadBalancer lb = new LoadBalancer(loadBalancerType, pool, pddContext);
  774.         String nomeConnettore = lb.selectConnector();
  775.         if(nomeConnettore==null) {
  776.             throw new BehaviourException("Nessun connettore selezionato");
  777.         }
  778.         return nomeConnettore;
  779.     }
  780. }