DatiCollezionatiDistributedLongAdder.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.controllo_traffico.policy.driver.redisson.counters;

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

  24. import org.openspcoop2.core.controllo_traffico.beans.ActivePolicy;
  25. import org.openspcoop2.core.controllo_traffico.beans.DatiCollezionati;
  26. import org.openspcoop2.core.controllo_traffico.beans.IDUnivocoGroupByPolicyMapId;
  27. import org.openspcoop2.core.controllo_traffico.beans.IDatiCollezionatiDistributed;
  28. import org.openspcoop2.core.controllo_traffico.constants.TipoControlloPeriodo;
  29. import org.openspcoop2.pdd.core.controllo_traffico.policy.driver.BuilderDatiCollezionatiDistributed;
  30. import org.openspcoop2.utils.SemaphoreLock;
  31. import org.redisson.api.RedissonClient;
  32. import org.slf4j.Logger;

  33. /**
  34.  * Versione simile a quella del PNCounter per hazelcast. Abbiamo un contatore distribuito molto veloce, il LongAdder.
  35.  *
  36.  * Per il PNCounter abbiamo le versioni incrementAndGet e addAndGet e in questo caso invece no.
  37.  * Significa che durante gli incrementi, nella PNCCounter si setta subito anche il valore aggiornato che verrà poi consultato dal PolicyVerifier, poichè le get ritornano il valore in RAM.
  38.  * Mentre in questa implementazione si aggiornano i contatori distributi senza poter aggiornare il valore in ram.
  39.  * Dopodichè una volta che lo si recupera tramite la 'sum()' potrebbero essere tornati anche risultati derivanti da altre richieste in corso.
  40.  * Il PolicyVerifier valuterà quindi informazioni non consistenti.
  41.  *
  42.  * Si sceglie inoltre di fare prima la sum() e poi l'incremento sia remoto che in ram, per evitare che una sum() effettuata dopo l'increment, ritorni il risultato di tutti gli increment degli altri thread e quindi il 429 immediato.
  43.  * Per avere una atomicita almeno sul solito nodo si mette il lock su queste operazioni.
  44.  *
  45.  * @author Francesco Scarlato (scarlato@link.it)
  46.  * @author $Author$
  47.  * @version $Rev$, $Date$
  48.  */
  49. public class DatiCollezionatiDistributedLongAdder  extends DatiCollezionati implements IDatiCollezionatiDistributed {
  50.    
  51.     private static final long serialVersionUID = 1L;
  52.    
  53.     private final transient org.openspcoop2.utils.Semaphore lock = new org.openspcoop2.utils.Semaphore("DatiCollezionatiDistributedLongAdder");
  54.    
  55.     private final transient org.openspcoop2.utils.Semaphore lockActiveRequestCounterGetAndSum = new org.openspcoop2.utils.Semaphore("DatiCollezionatiDistributedLongAdder_ActiveRequestCounterGetAndSum");
  56.     private final transient org.openspcoop2.utils.Semaphore lockRequestCounterGetAndSum = new org.openspcoop2.utils.Semaphore("DatiCollezionatiDistributedLongAdder_RequestCounterGetAndSum");
  57.     private final transient org.openspcoop2.utils.Semaphore lockCounterGetAndSum = new org.openspcoop2.utils.Semaphore("DatiCollezionatiDistributedLongAdder_CounterGetAndSum");
  58.     private final transient org.openspcoop2.utils.Semaphore lockDegradoPrestazionaleRequestCounterGetAndSum = new org.openspcoop2.utils.Semaphore("DatiCollezionatiDistributedLongAdder_DegradoPrestazionaleRequestCounterGetAndSum");
  59.     private final transient org.openspcoop2.utils.Semaphore lockDegradoPrestazionaleCounterGetAndSum = new org.openspcoop2.utils.Semaphore("DatiCollezionatiDistributedLongAdder_DegradoPrestazionaleCounterGetAndSum");
  60.    
  61.     private final transient RedissonClient redisson;
  62.     private final IDUnivocoGroupByPolicyMapId groupByPolicyMapId;
  63.     private final int groupByPolicyMapIdHashCode;

  64.     // data di registrazione/aggiornamento policy
  65.    
  66.     // final: sono i contatori che non dipendono da una finestra temporale

  67.     // sono rimasti AtomicLong le date

  68.     private final transient DatoRAtomicLong distributedUpdatePolicyDate; // data di ultima modifica della policy
  69.     private final transient DatoRAtomicLong distributedPolicyDate; // intervallo corrente su cui vengono costruiti gli altri contatori  
  70.    
  71.     private transient DatoRLongAdder distributedPolicyRequestCounter; // numero di richieste effettuato nell'intervallo
  72.     private transient DatoRLongAdder distributedPolicyCounter;  // utilizzato per tempi o banda
  73.    
  74.     private final transient DatoRAtomicLong distributedPolicyDegradoPrestazionaleDate; // intervallo corrente su cui vengono costruiti gli altri contatori
  75.     private transient DatoRLongAdder distributedPolicyDegradoPrestazionaleRequestCounter; // numero di richieste effettuato nell'intervallo
  76.     private transient DatoRLongAdder distributedPolicyDegradoPrestazionaleCounter; // contatore del degrado
  77.    
  78.     private final boolean distribuitedActiveRequestCounterPolicyRichiesteSimultanee;
  79.     private final transient DatoRLongAdder distributedActiveRequestCounterForStats; // numero di richieste simultanee
  80.     private transient DatoRLongAdder distributedActiveRequestCounterForCheck; // numero di richieste simultanee
  81.    
  82.     private transient DatoRLongAdder distributedPolicyDenyRequestCounter; // policy bloccate
  83.    
  84.     // I contatori da eliminare
  85.     // Se si effettua il drop di un contatore quando si rileva il cambio di intervallo, potrebbe succedere che in un altro nodo del cluster che sta effettuando la fase di 'end'
  86.     // non rilevi più il contatore e di fatto quindi lo riprende partenzo da 0. Poi a sua volta capisce il cambio di intervallo e lo rielimina.
  87.     // per questo motivo, il drop viene effettuato al secondo cambio di intervallo, e ad ogni cambio i contatori vengono collezionati nel cestino
  88.     private transient List<DatoRLongAdder> cestinoPolicyCounters = new ArrayList<>();
  89.     private transient List<DatoRLongAdder> cestinoPolicyCountersDegradoPrestazionale = new ArrayList<>();
  90.    
  91.     private boolean initialized = false;

  92.     private String getRLongAdderName(String name, Long date) {
  93.         String t = "";
  94.         if(date!=null) {
  95.             t = date + "";
  96.         }
  97.        
  98.         String configDate = BuilderDatiCollezionatiDistributed.DISTRUBUITED_SUFFIX_CONFIG_DATE+
  99.                 (this.gestorePolicyConfigDate!=null ? this.gestorePolicyConfigDate.getTime() : -1);
  100.        
  101.         return "longadder-"+this.groupByPolicyMapIdHashCode+"-"+name+t+configDate+"-rl"; // non modificare inizio e fine
  102.     }
  103.        
  104.     public DatiCollezionatiDistributedLongAdder(Logger log, Date updatePolicyDate, Date gestorePolicyConfigDate, RedissonClient  redisson, IDUnivocoGroupByPolicyMapId groupByPolicyMapId, ActivePolicy activePolicy) {
  105.         super(updatePolicyDate, gestorePolicyConfigDate);
  106.    
  107.         this.redisson = redisson;
  108.         this.groupByPolicyMapId = groupByPolicyMapId;
  109.         this.groupByPolicyMapIdHashCode = this.groupByPolicyMapId.hashCode();
  110.        
  111.         this.initDatiIniziali(activePolicy);
  112.         this.checkDate(log, activePolicy); // inizializza le date se ci sono
  113.        
  114.         this.distributedPolicyDate = this.initPolicyDate();
  115.         this.distributedUpdatePolicyDate = this.initUpdatePolicyDate();
  116.        
  117.         this.distributedPolicyDegradoPrestazionaleDate = this.initPolicyDegradoPrestazionaleDate();

  118.         this.distribuitedActiveRequestCounterPolicyRichiesteSimultanee = activePolicy.getConfigurazionePolicy().isSimultanee() &&
  119.                 TipoControlloPeriodo.REALTIME.equals(activePolicy.getConfigurazionePolicy().getModalitaControllo());
  120.         if(this.distribuitedActiveRequestCounterPolicyRichiesteSimultanee){
  121.             this.distributedActiveRequestCounterForCheck = this.initActiveRequestCounters();
  122.             this.distributedActiveRequestCounterForStats = null;
  123.         }
  124.         else {
  125.             this.distributedActiveRequestCounterForStats = this.initActiveRequestCounters();
  126.         }
  127.        
  128.         if(this.policyRealtime!=null && this.policyRealtime){
  129.             initPolicyCounters(super.getPolicyDate().getTime());
  130.         }
  131.         if(this.policyDegradoPrestazionaleRealtime!=null && this.policyDegradoPrestazionaleRealtime){
  132.             initPolicyCountersDegradoPrestazionale(super.getPolicyDegradoPrestazionaleDate().getTime());
  133.         }
  134.        
  135.         // Gestisco la updatePolicyDate qui.
  136.         // se updatePolicyDate è > this.distributedUpdatePolicyDate.get() allora resetto i contatori del cluster e setto la nuova data distribuita.
  137.         // Questo per via di come funziona l'aggiornamento delle policy: i datiCollezionati correnti per una map<IDUnivoco..., DatiCollezionati> vengono cancellati e reinizializzati.
  138.         // Per gli altri nodi in esecuzione, la updatePolicyDate locale resta sempre la stessa, ma non viene usata.
  139.         if(this.policyRealtime!=null && this.policyRealtime &&
  140.             updatePolicyDate != null && this.distributedUpdatePolicyDate!=null && this.distributedUpdatePolicyDate.get() < updatePolicyDate.getTime()) {
  141.             this.resetCounters(updatePolicyDate);
  142.         }
  143.        
  144.         this.initialized = true;
  145.     }
  146.    
  147.    
  148.     public DatiCollezionatiDistributedLongAdder(Logger log, DatiCollezionati dati, RedissonClient redisson, IDUnivocoGroupByPolicyMapId groupByPolicyMapId, ActivePolicy activePolicy) {
  149.         super(dati.getUpdatePolicyDate(), dati.getGestorePolicyConfigDate());
  150.        
  151.         if(log!=null) {
  152.             // nop
  153.         }
  154.        
  155.         // Inizializzo il padre
  156.         dati.setValuesIn(this, false);
  157.        
  158.         this.redisson = redisson;
  159.         this.groupByPolicyMapId = groupByPolicyMapId;
  160.         this.groupByPolicyMapIdHashCode = this.groupByPolicyMapId.hashCode();
  161.        
  162.         this.distributedPolicyDate = this.initPolicyDate();
  163.         this.distributedUpdatePolicyDate = this.initUpdatePolicyDate();
  164.        
  165.         this.distributedPolicyDegradoPrestazionaleDate = this.initPolicyDegradoPrestazionaleDate();

  166.         this.distribuitedActiveRequestCounterPolicyRichiesteSimultanee = activePolicy.getConfigurazionePolicy().isSimultanee() &&
  167.                 TipoControlloPeriodo.REALTIME.equals(activePolicy.getConfigurazionePolicy().getModalitaControllo());
  168.         if(this.distribuitedActiveRequestCounterPolicyRichiesteSimultanee){
  169.             this.distributedActiveRequestCounterForCheck = this.initActiveRequestCounters();
  170.             this.distributedActiveRequestCounterForStats = null;
  171.         }
  172.         else {
  173.             this.distributedActiveRequestCounterForStats = this.initActiveRequestCounters();
  174.         }
  175.        
  176.         // Se non ho la policyDate, non considero il resto delle informazioni, che senza di essa non hanno senso.
  177.         if (super.getPolicyDate() != null) {

  178.             // Non serve: essendo già persistente, si va a sommare un dato gia' esistente
  179.             /**
  180.            
  181.             // Se ci sono altri nodi che stanno andando, la distributedPolicyDate DEVE essere != 0
  182.             // Se la policyDate è a zero vuol dire che questo è il primo nodo del cluster che sta inizializzando la policy per mezzo di un backup e che su tutto il cluster
  183.             // non sono ancora transitate richieste.
  184.             if (this.distributedPolicyDate.compareAndSet(0, super.getPolicyDate().getTime())) {
  185.                 // Se la data distribuita non era inizializzata e questo nodo l'ha settata, imposto i contatori come da immagine bin.
  186.                 //  Faccio la addAndGet, in quanto tutti valori positivi, non entriamo in conflitto con gli altri nodi che stanno effettuando lo startup nello stesso momento
  187.                
  188.                 Long polDate = super.getPolicyDate().getTime();
  189.                 initPolicyCounters(polDate);
  190.                
  191.                 Long getPolicyRequestCounter = super.getPolicyRequestCounter(true);
  192.                 if (getPolicyRequestCounter != null) {
  193.                     this.distributedPolicyRequestCounter.add(getPolicyRequestCounter);
  194.                 }
  195.                
  196.                 Long getPolicyDenyRequestCounter = super.getPolicyDenyRequestCounter(true); // sarà comunque l'immagine del file
  197.                 if (getPolicyDenyRequestCounter != null) {
  198.                     this.distributedPolicyDenyRequestCounter.add(getPolicyDenyRequestCounter);
  199.                 }
  200.                
  201.                 if(this.tipoRisorsa==null || !isRisorsaContaNumeroRichieste(this.tipoRisorsa)){
  202.                     Long getPolicyCounter = super.getPolicyCounter(true);
  203.                     if (getPolicyCounter != null) {
  204.                         this.distributedPolicyCounter.add(getPolicyCounter);
  205.                     }
  206.                 }
  207.                
  208.                 Long getActiveRequestCounter = super.getActiveRequestCounter(true); // sarà comunque l'immagine del file
  209.                 if (getActiveRequestCounter!=null && getActiveRequestCounter != 0) {
  210.                     if(this.distribuitedActiveRequestCounter_policyRichiesteSimultanee){
  211.                         this.distributedActiveRequestCounterForCheck.add(getActiveRequestCounter);
  212.                     }
  213.                     else {
  214.                         this.distributedActiveRequestCounterForStats.add(getActiveRequestCounter);
  215.                     }
  216.                 }
  217.                                        
  218.             } else {
  219.             */
  220.                 Long polDate = this.distributedPolicyDegradoPrestazionaleDate!=null ? this.distributedPolicyDegradoPrestazionaleDate.get() : null;
  221.                 initPolicyCounters(polDate);
  222.                
  223.             /**}*/
  224.         }
  225.        
  226.         // Se non ho la policyDegradoPrestazionaleDate, non considero il resto delle informazioni, che senza di essa non hanno senso.
  227.         if(this.policyDegradoPrestazionaleRealtime!=null && this.policyDegradoPrestazionaleRealtime &&
  228.             super.getPolicyDegradoPrestazionaleDate() != null) {
  229.                
  230.             // Non serve: essendo già persistente, si va a sommare un dato gia' esistente
  231.             /**
  232.             // Imposto i contatori distribuiti solo se nel frattempo non l'ha fatto un altro thread del cluster.
  233.             if (this.distributedPolicyDegradoPrestazionaleDate.compareAndSet(0, super.getPolicyDegradoPrestazionaleDate().getTime())) {
  234.                
  235.                 Long degradoPrestazionaleTime = super.getPolicyDegradoPrestazionaleDate().getTime();
  236.                 initPolicyCountersDegradoPrestazionale(degradoPrestazionaleTime);
  237.                                
  238.                 Long getPolicyDegradoPrestazionaleRequestCounter = super.getPolicyDegradoPrestazionaleRequestCounter(true);
  239.                 if (getPolicyDegradoPrestazionaleRequestCounter != null) {
  240.                     this.distributedPolicyDegradoPrestazionaleRequestCounter.add(getPolicyDegradoPrestazionaleRequestCounter);
  241.                 }
  242.                
  243.                 Long getPolicyDegradoPrestazionaleCounter = super.getPolicyDegradoPrestazionaleCounter(true);
  244.                 if (getPolicyDegradoPrestazionaleCounter != null) {
  245.                     this.distributedPolicyDegradoPrestazionaleCounter.add(getPolicyDegradoPrestazionaleCounter);
  246.                 }
  247.             }  else {
  248.             */  
  249.                 Long degradoPrestazionaleTime = this.distributedPolicyDate!=null ? this.distributedPolicyDate.get() : null;
  250.                 initPolicyCountersDegradoPrestazionale(degradoPrestazionaleTime);
  251.                
  252.             /**}*/
  253.         }
  254.        
  255.         this.initialized = true;
  256.     }
  257.    
  258.     private DatoRAtomicLong initPolicyDate() {
  259.         if(this.policyRealtime!=null && this.policyRealtime){
  260.             return new DatoRAtomicLong(this.redisson,
  261.                     this.groupByPolicyMapIdHashCode+
  262.                     BuilderDatiCollezionatiDistributed.DISTRUBUITED_POLICY_DATE+
  263.                     (this.gestorePolicyConfigDate!=null ? this.gestorePolicyConfigDate.getTime() : -1));
  264.         }
  265.         return null;
  266.     }
  267.     private DatoRAtomicLong initUpdatePolicyDate() {
  268.         if(this.policyRealtime!=null && this.policyRealtime){
  269.             return new DatoRAtomicLong(this.redisson,
  270.                     this.groupByPolicyMapIdHashCode+
  271.                     BuilderDatiCollezionatiDistributed.DISTRUBUITED_UPDATE_POLICY_DATE+
  272.                     (this.gestorePolicyConfigDate!=null ? this.gestorePolicyConfigDate.getTime() : -1));
  273.         }
  274.         return null;
  275.     }
  276.     private DatoRAtomicLong initPolicyDegradoPrestazionaleDate() {
  277.         if(this.policyDegradoPrestazionaleRealtime!=null && this.policyDegradoPrestazionaleRealtime){
  278.             return new DatoRAtomicLong(this.redisson,
  279.                     this.groupByPolicyMapIdHashCode+
  280.                     BuilderDatiCollezionatiDistributed.DISTRUBUITED_POLICY_DEGRADO_PRESTAZIONALE_DATE+
  281.                     (this.gestorePolicyConfigDate!=null ? this.gestorePolicyConfigDate.getTime() : -1));
  282.         }
  283.         return null;
  284.     }
  285.    
  286.     private DatoRLongAdder initActiveRequestCounters() {
  287.         return new DatoRLongAdder(this.redisson,
  288.                 getRLongAdderName(BuilderDatiCollezionatiDistributed.DISTRUBUITED_ACTIVE_REQUEST_COUNTER,
  289.                         (this.gestorePolicyConfigDate!=null ? this.gestorePolicyConfigDate.getTime() : -1)));
  290.     }
  291.    
  292.     private void initPolicyCounters(Long policyDate) {

  293.         if(this.policyRealtime!=null && this.policyRealtime){
  294.                        
  295.             this.distributedPolicyRequestCounter = new DatoRLongAdder(this.redisson,
  296.                     this.getRLongAdderName(BuilderDatiCollezionatiDistributed.DISTRUBUITED_INTERVAL_POLICY_REQUEST_COUNTER,policyDate));
  297.            
  298.             this.distributedPolicyDenyRequestCounter = new DatoRLongAdder(this.redisson,
  299.                     this.getRLongAdderName(BuilderDatiCollezionatiDistributed.DISTRUBUITED_INTERVAL_POLICY_DENY_REQUEST_COUNTER,policyDate));
  300.            
  301.             if(this.tipoRisorsa==null || !isRisorsaContaNumeroRichieste(this.tipoRisorsa)){
  302.                 this.distributedPolicyCounter = new DatoRLongAdder(this.redisson,
  303.                         this.getRLongAdderName(BuilderDatiCollezionatiDistributed.DISTRUBUITED_INTERVAL_POLICY_COUNTER,policyDate));
  304.             }
  305.         }
  306.        
  307.     }
  308.    
  309.     private void initPolicyCountersDegradoPrestazionale(Long policyDate) {
  310.        
  311.         if(this.policyDegradoPrestazionaleRealtime!=null && this.policyDegradoPrestazionaleRealtime){
  312.             this.distributedPolicyDegradoPrestazionaleCounter = new DatoRLongAdder(this.redisson,
  313.                     this.getRLongAdderName(BuilderDatiCollezionatiDistributed.DISTRUBUITED_INTERVAL_POLICY_DEGRADO_PRESTAZIONALE_COUNTER,policyDate));

  314.             this.distributedPolicyDegradoPrestazionaleRequestCounter = new DatoRLongAdder(this.redisson,
  315.                     this.getRLongAdderName(BuilderDatiCollezionatiDistributed.DISTRUBUITED_INTERVAL_POLICY_DEGRADO_PRESTAZIONALE_REQUEST_COUNTER,policyDate));

  316.         }  
  317.        
  318.     }
  319.    
  320.    

  321.     @Override
  322.     protected void resetPolicyCounterForDate(Date date) {
  323.        
  324.         if(this.initialized) {
  325.             SemaphoreLock slock = this.lock.acquireThrowRuntime("resetPolicyCounterForDate");
  326.             try {
  327.                 long policyDate = date.getTime();
  328.                 long actual = this.distributedPolicyDate.get();
  329.                 long actualSuper = super.policyDate!=null ? super.policyDate.getTime() : -1;
  330.                 if(actualSuper!=policyDate && actual<policyDate && this.distributedPolicyDate.compareAndSet(actual, policyDate)) {                  
  331.                
  332.                     // Solo 1 nodo del cluster deve entrare in questo codice, altrimenti vengono fatti destroy più volte sullo stesso contatore
  333.                     // Potrà capitare che il cestino di un nodo non venga svuotato se si entra sempre sull'altro, cmq sia rimarrà 1 cestino con dei contatori di 1 intervallo.
  334.                     // Non appena ci entra poi li distruggerà.
  335.                    
  336.                     // effettuo il drop creati due intervalli indietro
  337.                     if(!this.cestinoPolicyCounters.isEmpty()) {
  338.                         for (DatoRLongAdder rLongAdder : this.cestinoPolicyCounters) {
  339.                             rLongAdder.destroy();
  340.                         }
  341.                         this.cestinoPolicyCounters.clear();
  342.                     }
  343.                    
  344.                     if(this.distributedPolicyRequestCounter!=null || this.distributedPolicyDenyRequestCounter!=null || this.distributedPolicyCounter!=null) {
  345.                         // conservo precedenti contatori
  346.                         if(this.distributedPolicyRequestCounter!=null) {
  347.                             this.cestinoPolicyCounters.add(this.distributedPolicyRequestCounter);
  348.                         }
  349.                         if(this.distributedPolicyDenyRequestCounter!=null) {
  350.                             this.cestinoPolicyCounters.add(this.distributedPolicyDenyRequestCounter);
  351.                         }
  352.                         if(this.distributedPolicyCounter!=null) {
  353.                             this.cestinoPolicyCounters.add(this.distributedPolicyCounter);
  354.                         }
  355.                     }
  356.                                        
  357.                 }

  358.                 if(actualSuper!=policyDate) {
  359.                    
  360.                     // Serve per inizializzare i nuovi riferimenti ai contatori
  361.                     initPolicyCounters(policyDate);
  362.                    
  363.                     // Serve per aggiornare la copia in ram del nodo in cui non si e' entrati nell'if precedente
  364.                     super.resetPolicyCounterForDate(date);
  365.                 }
  366.                
  367.             }finally {
  368.                 this.lock.release(slock, "resetPolicyCounterForDate");
  369.             }
  370.         }
  371.         else {
  372.             super.resetPolicyCounterForDate(date);
  373.         }
  374.     }
  375.    
  376.    
  377.     @Override
  378.     protected void resetPolicyCounterForDateDegradoPrestazionale(Date date) {
  379.        
  380.         if(this.initialized) {
  381.            
  382.             SemaphoreLock slock = this.lock.acquireThrowRuntime("resetPolicyCounterForDateDegradoPrestazionale");
  383.             try {
  384.                 long policyDate = date.getTime();
  385.                 long actual = this.distributedPolicyDate.get();
  386.                 long actualSuper = super.policyDegradoPrestazionaleDate!=null ? super.policyDegradoPrestazionaleDate.getTime() : -1;
  387.                 if(actualSuper!=policyDate && actual<policyDate && this.distributedPolicyDegradoPrestazionaleDate.compareAndSet(actual, policyDate)) {  
  388.                
  389.                     // Solo 1 nodo del cluster deve entrare in questo codice, altrimenti vengono fatti destroy più volte sullo stesso contatore
  390.                     // Potrà capitare che il cestino di un nodo non venga svuotato se si entra sempre sull'altro, cmq sia rimarrà 1 cestino con dei contatori di 1 intervallo.
  391.                     // Non appena ci entra poi li distruggerà.
  392.                    
  393.                     // effettuo il drop creati due intervalli indietro
  394.                     if(!this.cestinoPolicyCountersDegradoPrestazionale.isEmpty()) {
  395.                         for (DatoRLongAdder pnCounter : this.cestinoPolicyCountersDegradoPrestazionale) {
  396.                             pnCounter.destroy();
  397.                         }
  398.                         this.cestinoPolicyCountersDegradoPrestazionale.clear();
  399.                     }
  400.                    
  401.                     if(this.distributedPolicyRequestCounter!=null || this.distributedPolicyDenyRequestCounter!=null || this.distributedPolicyCounter!=null) {
  402.                         // conservo precedenti contatori
  403.                         if(this.distributedPolicyDegradoPrestazionaleCounter!=null) {
  404.                             this.cestinoPolicyCountersDegradoPrestazionale.add(this.distributedPolicyDegradoPrestazionaleCounter);
  405.                         }
  406.                         if(this.distributedPolicyDegradoPrestazionaleRequestCounter!=null) {
  407.                             this.cestinoPolicyCountersDegradoPrestazionale.add(this.distributedPolicyDegradoPrestazionaleRequestCounter);
  408.                         }
  409.                     }
  410.                                        
  411.                 }
  412.                
  413.                 if(actualSuper!=policyDate) {
  414.                    
  415.                     // Serve per inizializzare i nuovi riferimenti ai contatori
  416.                     initPolicyCountersDegradoPrestazionale(policyDate);
  417.                    
  418.                     // Serve per aggiornare la copia in ram del nodo in cui non si e' entrati nell'if precedente
  419.                     super.resetPolicyCounterForDateDegradoPrestazionale(date);
  420.                 }
  421.                
  422.             }finally {
  423.                 this.lock.release(slock, "resetPolicyCounterForDateDegradoPrestazionale");
  424.             }
  425.         }
  426.         else {
  427.             super.resetPolicyCounterForDateDegradoPrestazionale(date);
  428.         }
  429.     }
  430.    
  431.    
  432.     @Override
  433.     public void resetCounters(Date updatePolicyDate) {
  434.         super.resetCounters(updatePolicyDate);
  435.        
  436.         if(updatePolicyDate!=null) {
  437.             this.distributedUpdatePolicyDate.set(updatePolicyDate.getTime());
  438.         }
  439.        
  440.         if (this.distributedPolicyDenyRequestCounter != null) {
  441.             this.distributedPolicyDenyRequestCounter.reset();
  442.         }
  443.        
  444.         if (this.distributedPolicyRequestCounter != null)  {
  445.             this.distributedPolicyRequestCounter.reset();
  446.         }
  447.        
  448.         if (this.distributedPolicyCounter != null) {
  449.             this.distributedPolicyCounter.reset();
  450.         }
  451.        
  452.         if (this.distributedPolicyDegradoPrestazionaleRequestCounter != null) {
  453.             this.distributedPolicyDegradoPrestazionaleRequestCounter.reset();
  454.         }
  455.        
  456.         if (this.distributedPolicyDegradoPrestazionaleCounter != null) {
  457.             this.distributedPolicyDegradoPrestazionaleCounter.reset();
  458.         }
  459.        
  460.     }
  461.    
  462.    
  463.     // NOTA:  Si sceglie inoltre di fare prima la sum() e poi l'incremento sia remoto che in ram, per evitare che una sum() effettuata dopo l'increment, ritorni il risultato di tutti gli increment degli altri thread e quindi il 429 immediato.
  464.     //        Per avere una atomicita almeno sul solito nodo si mette il lock su queste operazioni.
  465.     //        Vedi commento in java doc della classe.
  466.    
  467.     @Override
  468.     protected void internalRegisterStartRequestIncrementActiveRequestCounter(DatiCollezionati datiCollezionatiPerPolicyVerifier) {
  469.         if(this.distribuitedActiveRequestCounterPolicyRichiesteSimultanee){
  470.             SemaphoreLock slock = this.lockActiveRequestCounterGetAndSum.acquireThrowRuntime("internalRegisterStartRequestIncrementActiveRequestCounter");
  471.             try {
  472.                 // prendo il valore. Non esiste un unico incrementAndGet
  473.                 if(datiCollezionatiPerPolicyVerifier!=null) {
  474.                     super.activeRequestCounter = datiCollezionatiPerPolicyVerifier.setAndGetActiveRequestCounter(this.distributedActiveRequestCounterForCheck.sum());
  475.                 }
  476.                 else {
  477.                     super.activeRequestCounter = this.distributedActiveRequestCounterForCheck.sum();
  478.                 }
  479.                 this.distributedActiveRequestCounterForCheck.increment();
  480.                 super.activeRequestCounter++;
  481.             }finally {
  482.                 this.lockActiveRequestCounterGetAndSum.release(slock, "internalRegisterStartRequestIncrementActiveRequestCounter");
  483.             }
  484.         }
  485.         else {
  486.             this.distributedActiveRequestCounterForStats.increment();
  487.         }
  488.     }
  489.    
  490.    
  491.     @Override
  492.     protected void internalUpdateDatiStartRequestApplicabileIncrementRequestCounter(DatiCollezionati datiCollezionatiPerPolicyVerifier) {
  493.         SemaphoreLock slock = this.lockRequestCounterGetAndSum.acquireThrowRuntime("internalUpdateDatiStartRequestApplicabileIncrementRequestCounter");
  494.         try {
  495.             // prendo il valore. Non esiste un unico incrementAndGet
  496.             if(datiCollezionatiPerPolicyVerifier!=null) {
  497.                 super.policyRequestCounter = datiCollezionatiPerPolicyVerifier.setAndGetPolicyRequestCounter(this.distributedPolicyRequestCounter.sum());
  498.             }
  499.             else {
  500.                 super.policyRequestCounter = this.distributedPolicyRequestCounter.sum();
  501.             }
  502.             this.distributedPolicyRequestCounter.increment();
  503.             super.policyRequestCounter++;
  504.         }finally {
  505.             this.lockRequestCounterGetAndSum.release(slock, "internalUpdateDatiStartRequestApplicabileIncrementRequestCounter");
  506.         }
  507.     }
  508.    
  509.    
  510.     @Override
  511.     protected void internalRegisterEndRequestDecrementActiveRequestCounter() {
  512.         if(this.distribuitedActiveRequestCounterPolicyRichiesteSimultanee){
  513.             SemaphoreLock slock = this.lockActiveRequestCounterGetAndSum.acquireThrowRuntime("internalRegisterEndRequestDecrementActiveRequestCounter");
  514.             try {
  515.                 super.activeRequestCounter = this.distributedActiveRequestCounterForCheck.sum(); // prendo il valore. Non esiste un unico incrementAndGet
  516.                 this.distributedActiveRequestCounterForCheck.decrement();
  517.                 super.activeRequestCounter--;
  518.             }finally {
  519.                 this.lockActiveRequestCounterGetAndSum.release(slock, "internalRegisterEndRequestDecrementActiveRequestCounter");
  520.             }
  521.         }
  522.         else {
  523.             this.distributedActiveRequestCounterForStats.decrement();
  524.         }
  525.     }
  526.     @Override
  527.     protected void internalRegisterEndRequestIncrementDegradoPrestazionaleRequestCounter() {
  528.         SemaphoreLock slock = this.lockDegradoPrestazionaleRequestCounterGetAndSum.acquireThrowRuntime("internalRegisterEndRequestIncrementDegradoPrestazionaleRequestCounter");
  529.         try {
  530.             super.policyDegradoPrestazionaleRequestCounter = this.distributedPolicyDegradoPrestazionaleRequestCounter.sum(); // prendo il valore. Non esiste un unico incrementAndGet
  531.             this.distributedPolicyDegradoPrestazionaleRequestCounter.increment();
  532.             super.policyDegradoPrestazionaleRequestCounter++;
  533.         }finally {
  534.             this.lockDegradoPrestazionaleRequestCounterGetAndSum.release(slock, "internalRegisterEndRequestIncrementDegradoPrestazionaleRequestCounter");
  535.         }
  536.     }
  537.     @Override
  538.     protected void internalRegisterEndRequestIncrementDegradoPrestazionaleCounter(long latenza) {
  539.         SemaphoreLock slock = this.lockDegradoPrestazionaleCounterGetAndSum.acquireThrowRuntime("internalRegisterEndRequestIncrementDegradoPrestazionaleCounter");
  540.         try {
  541.             super.policyDegradoPrestazionaleCounter = this.distributedPolicyDegradoPrestazionaleCounter.sum(); // prendo il valore. Non esiste un unico incrementAndGet
  542.             this.distributedPolicyDegradoPrestazionaleCounter.add(latenza);
  543.             super.policyDegradoPrestazionaleCounter++;
  544.         }finally {
  545.             this.lockDegradoPrestazionaleCounterGetAndSum.release(slock, "internalRegisterEndRequestIncrementDegradoPrestazionaleCounter");
  546.         }
  547.     }
  548.    
  549.    
  550.     @Override
  551.     protected void internalUpdateDatiEndRequestApplicabileIncrementRequestCounter() {
  552.         SemaphoreLock slock = this.lockRequestCounterGetAndSum.acquireThrowRuntime("internalUpdateDatiEndRequestApplicabileIncrementRequestCounter");
  553.         try {
  554.             super.policyRequestCounter = this.distributedPolicyRequestCounter.sum(); // prendo il valore. Non esiste un unico incrementAndGet
  555.             this.distributedPolicyRequestCounter.increment();
  556.             super.policyRequestCounter++;
  557.         }finally {
  558.             this.lockRequestCounterGetAndSum.release(slock, "internalUpdateDatiEndRequestApplicabileIncrementRequestCounter");
  559.         }
  560.     }
  561.     @Override
  562.     protected void internalUpdateDatiEndRequestApplicabileDecrementRequestCounter() {
  563.         SemaphoreLock slock = this.lockRequestCounterGetAndSum.acquireThrowRuntime("internalUpdateDatiEndRequestApplicabileDecrementRequestCounter");
  564.         try {
  565.             super.policyRequestCounter = this.distributedPolicyRequestCounter.sum(); // prendo il valore. Non esiste un unico incrementAndGet
  566.             this.distributedPolicyRequestCounter.decrement();
  567.             super.policyRequestCounter--;
  568.         }finally {
  569.             this.lockRequestCounterGetAndSum.release(slock, "internalUpdateDatiEndRequestApplicabileDecrementRequestCounter");
  570.         }
  571.     }
  572.     @Override
  573.     protected void internalUpdateDatiEndRequestApplicabileIncrementDenyRequestCounter() {
  574.         this.distributedPolicyDenyRequestCounter.increment();
  575.     }
  576.     @Override
  577.     protected void internalUpdateDatiEndRequestApplicabileIncrementCounter(long v) {
  578.         SemaphoreLock slock = this.lockCounterGetAndSum.acquireThrowRuntime("internalUpdateDatiEndRequestApplicabileIncrementCounter");
  579.         try {
  580.             super.policyCounter = this.distributedPolicyCounter.sum(); // prendo il valore. Non esiste un unico incrementAndGet
  581.             this.distributedPolicyCounter.add(v);
  582.             super.policyCounter+=v;
  583.         }finally {
  584.             this.lockCounterGetAndSum.release(slock, "internalUpdateDatiEndRequestApplicabileIncrementCounter");
  585.         }
  586.     }
  587.    
  588.    
  589.    
  590.    
  591.     @Override
  592.     public void destroyDatiDistribuiti() {
  593.         if(this.distributedPolicyDate!=null) {
  594.             this.distributedPolicyDate.delete();
  595.         }
  596.         if(this.distributedUpdatePolicyDate!=null) {
  597.             this.distributedUpdatePolicyDate.delete();
  598.         }
  599.        
  600.         if(this.distributedPolicyRequestCounter!=null) {
  601.             this.distributedPolicyRequestCounter.destroy();
  602.         }
  603.         if(this.distributedPolicyCounter!=null) {
  604.             this.distributedPolicyCounter.destroy();
  605.         }
  606.        
  607.         if(this.distributedPolicyDegradoPrestazionaleDate!=null) {
  608.             this.distributedPolicyDegradoPrestazionaleDate.delete();
  609.         }
  610.         if(this.distributedPolicyDegradoPrestazionaleRequestCounter!=null) {
  611.             this.distributedPolicyDegradoPrestazionaleRequestCounter.destroy();
  612.         }
  613.         if(this.distributedPolicyDegradoPrestazionaleCounter!=null) {
  614.             this.distributedPolicyDegradoPrestazionaleCounter.destroy();
  615.         }
  616.        
  617.         if(this.distributedActiveRequestCounterForStats!=null) {
  618.             this.distributedActiveRequestCounterForStats.destroy();
  619.         }
  620.         if(this.distributedActiveRequestCounterForCheck!=null) {
  621.             this.distributedActiveRequestCounterForCheck.destroy();
  622.         }
  623.        
  624.         if(this.distributedPolicyDenyRequestCounter!=null) {
  625.             this.distributedPolicyDenyRequestCounter.destroy();
  626.         }
  627.     }
  628.    
  629.    
  630.    
  631.     // Getters necessari poichè non viene aggiornato il field nella classe nonno DatiCollezionati, poichè i metodi increment, decrement e add non ritornano anche il valore
  632.    
  633.     @Override
  634.     public Long getActiveRequestCounter(boolean readRemoteInfo) {
  635.         if(this.distribuitedActiveRequestCounterPolicyRichiesteSimultanee){
  636.             if(readRemoteInfo) {
  637.                 return this.distributedActiveRequestCounterForCheck.sum();
  638.             }
  639.             else {
  640.                 return super.activeRequestCounter; // nelle operazioni di incremento/decremento l'ho aggiarnato via via e quindi il check utilizzerà questa informazione nel PolicyVerifier
  641.             }
  642.         }
  643.         else {
  644.             return this.distributedActiveRequestCounterForStats.sum();
  645.         }
  646.     }
  647.    
  648.     // Getters non necessari, sono utili solo se viene richiesta una lettura del dato remoto
  649.    
  650.     @Override
  651.     public Long getPolicyDenyRequestCounter(boolean readRemoteInfo) {
  652.         if(readRemoteInfo) {
  653.             if(this.distributedPolicyDenyRequestCounter!=null) {
  654.                 return this.distributedPolicyDenyRequestCounter.sum();
  655.             }
  656.             else {
  657.                 return null;
  658.             }
  659.         }
  660.         else {
  661.             return super.getPolicyDenyRequestCounter(readRemoteInfo);
  662.         }  
  663.     }
  664.    
  665.     @Override
  666.     public Long getPolicyRequestCounter(boolean readRemoteInfo) {
  667.         if(readRemoteInfo) {
  668.             if(this.distributedPolicyRequestCounter!=null) {
  669.                 return this.distributedPolicyRequestCounter.sum();
  670.             }
  671.             else {
  672.                 return null;
  673.             }
  674.         }
  675.         else {
  676.             return super.getPolicyRequestCounter(readRemoteInfo);
  677.         }
  678.     }
  679.     @Override
  680.     public Long getPolicyCounter(boolean readRemoteInfo) {
  681.         if(readRemoteInfo) {
  682.             if(this.distributedPolicyCounter!=null) {
  683.                 return this.distributedPolicyCounter.sum();
  684.             }
  685.             else {
  686.                 return null;
  687.             }
  688.         }
  689.         else {
  690.             return super.getPolicyRequestCounter(readRemoteInfo);
  691.         }
  692.     }  
  693.     @Override
  694.     public Long getPolicyDegradoPrestazionaleRequestCounter(boolean readRemoteInfo) {
  695.         if(readRemoteInfo) {
  696.             if(this.distributedPolicyDegradoPrestazionaleRequestCounter!=null) {
  697.                 return this.distributedPolicyDegradoPrestazionaleRequestCounter.sum();
  698.             }
  699.             else {
  700.                 return null;
  701.             }
  702.         }
  703.         else {
  704.             return super.getPolicyDegradoPrestazionaleRequestCounter(readRemoteInfo);
  705.         }
  706.     }
  707.     @Override
  708.     public Long getPolicyDegradoPrestazionaleCounter(boolean readRemoteInfo) {
  709.         if(readRemoteInfo) {
  710.             if(this.distributedPolicyDegradoPrestazionaleCounter!=null) {
  711.                 return this.distributedPolicyDegradoPrestazionaleCounter.sum();
  712.             }
  713.             else {
  714.                 return null;
  715.             }
  716.         }
  717.         else {
  718.             return super.getPolicyDegradoPrestazionaleCounter(readRemoteInfo);
  719.         }
  720.     }
  721.    
  722. }