DatoPNCounter.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.hazelcast.counters;

  21. import java.util.concurrent.CompletionStage;

  22. import org.openspcoop2.pdd.config.OpenSPCoop2Properties;
  23. import org.openspcoop2.pdd.logger.OpenSPCoop2Logger;
  24. import org.openspcoop2.utils.Utilities;
  25. import org.slf4j.Logger;

  26. import com.hazelcast.core.HazelcastInstance;
  27. import com.hazelcast.crdt.pncounter.PNCounter;
  28. import com.hazelcast.spi.exception.DistributedObjectDestroyedException;

  29. /**
  30.  * DatoPNCounter
  31.  *
  32.  * @author Poli Andrea (apoli@link.it)
  33.  * @author $Author$
  34.  * @version $Rev$, $Date$
  35.  */

  36. public class DatoPNCounter {

  37.     private HazelcastInstance hazelcast;
  38.     private String name;
  39.    
  40.     private PNCounter counter;
  41.    
  42.     private int failover = -1;
  43.     private int failoverCheckEveryMs = -1;
  44.    
  45.     private Logger logControlloTraffico;
  46.    
  47.     public DatoPNCounter(HazelcastInstance hazelcast, String name) {
  48.         this.hazelcast = hazelcast;
  49.         this.name = name;
  50.         this.initCounter();
  51.         OpenSPCoop2Properties op2Props = OpenSPCoop2Properties.getInstance();
  52.         this.failover = op2Props.getHazelcastCPSubsystemDistributedObjectDestroyedExceptionFailover();
  53.         this.failoverCheckEveryMs = op2Props.getHazelcastCPSubsystemDistributedObjectDestroyedExceptionFailoverCheckEveryMs();
  54.         this.logControlloTraffico = OpenSPCoop2Logger.getLoggerOpenSPCoopControlloTraffico(op2Props.isControlloTrafficoDebug());
  55.     }
  56.     private void initCounter() {
  57.         this.counter = this.hazelcast.getPNCounter(this.name);
  58.     }
  59.    
  60.     public long get() {
  61.         PNCounterResponse r = process(PNCounterOperation.GET, -1, -1);
  62.         return r!=null ? r.valueL : -1; // else non dovrebbe succedere mai
  63.     }
  64.     public long addAndGet(long value) {
  65.         PNCounterResponse r = process(PNCounterOperation.ADD_AND_GET, value, -1);
  66.         return r!=null ? r.valueL : -1; // else non dovrebbe succedere mai
  67.     }
  68.     public long incrementAndGet() {
  69.         PNCounterResponse r = process(PNCounterOperation.INCREMENT_AND_GET, -1, -1);
  70.         return r!=null ? r.valueL : -1; // else non dovrebbe succedere mai
  71.     }
  72.     public long decrementAndGet() {
  73.         PNCounterResponse r = process(PNCounterOperation.DECREMENT_AND_GET, -1, -1);
  74.         return r!=null ? r.valueL : -1; // else non dovrebbe succedere mai
  75.     }
  76.     public long subtractAndGet(long value) {
  77.         PNCounterResponse r = process(PNCounterOperation.SUBTRACT_AND_GET, value, -1);
  78.         return r!=null ? r.valueL : -1; // else non dovrebbe succedere mai
  79.     }
  80.     public void destroy() {
  81.         process(PNCounterOperation.DESTROY, -1, -1);
  82.     }
  83.    
  84.     private PNCounterResponse process(PNCounterOperation op, long arg1, long arg2) {
  85.         String prefix = "[Hazelcast-PNCounter-"+this.name+" operation:"+op+"] ";
  86.         if(this.failover>0) {
  87.             return processFailOver(prefix, op, arg1, arg2);
  88.         }
  89.         else {
  90.             return operation(prefix, op, arg1, arg2);
  91.         }
  92.     }
  93.     private PNCounterResponse processFailOver(String prefix, PNCounterOperation op, long arg1, long arg2) {
  94.         boolean success = false;
  95.         DistributedObjectDestroyedException eFinal = null;
  96.         PNCounterResponse v = null;
  97.         for (int i = 0; i < this.failover; i++) {
  98.             try {
  99.                 if(i>0 && this.failoverCheckEveryMs>0) {
  100.                     Utilities.sleep(this.failoverCheckEveryMs);
  101.                     initCounter();
  102.                 }
  103.                 v = operation(prefix, op, arg1, arg2);
  104.                 success=true;
  105.                 break;
  106.             } catch (DistributedObjectDestroyedException e) {
  107.                 eFinal = e;
  108.                 if(i==0) {
  109.                     this.logControlloTraffico.error(prefix+"rilevato contatore distrutto (verrà riprovata la creazione): "+e.getMessage(),e);
  110.                 }
  111.                 else {
  112.                     this.logControlloTraffico.error(prefix+"il tenativo i="+i+" di ricreare il contatore è fallito: "+e.getMessage(),e);
  113.                 }
  114.             }
  115.         }
  116.         if(!success) {
  117.             throwDistributedObjectDestroyedException(prefix, eFinal);
  118.         }
  119.         return v;
  120.     }
  121.     private void throwDistributedObjectDestroyedException(String prefix, DistributedObjectDestroyedException eFinal) {
  122.         String msg = prefix+"tutti i tentativi di ricreare il contatore sono falliti";
  123.         this.logControlloTraffico.error(msg);
  124.         if(eFinal!=null) {
  125.             throw eFinal;
  126.         }
  127.         else {
  128.             throw new DistributedObjectDestroyedException("tutti i tentativi di ricreare il contatore sono falliti"); // l'eccezione eFinal esiste
  129.         }
  130.     }
  131.    
  132.     private PNCounterResponse operation(String prefix, PNCounterOperation op, long arg1, long arg2){
  133.         switch (op) {
  134.         case GET:
  135.             return new PNCounterResponse(this.counter.get());
  136.         case ADD_AND_GET:
  137.             return new PNCounterResponse(this.counter.addAndGet(arg1));
  138.         case INCREMENT_AND_GET:
  139.             return new PNCounterResponse(this.counter.incrementAndGet());
  140.         case DECREMENT_AND_GET:
  141.             return new PNCounterResponse(this.counter.decrementAndGet());
  142.         case SUBTRACT_AND_GET:
  143.             return new PNCounterResponse(this.counter.subtractAndGet(arg1));
  144.         case DESTROY:
  145.             try {
  146.                 this.counter.destroy();
  147.             }catch(Throwable e) {
  148.                 this.logControlloTraffico.error(prefix+"destroy non riuscito: "+e.getMessage(),e);
  149.                 throw e;
  150.             }
  151.             return null;        
  152.         }
  153.         return null;
  154.     }
  155. }

  156. enum PNCounterOperation {
  157.     GET,
  158.     ADD_AND_GET, INCREMENT_AND_GET, DECREMENT_AND_GET, SUBTRACT_AND_GET,
  159.     DESTROY
  160. }

  161. class PNCounterResponse{
  162.     PNCounterResponse(long l){
  163.         this.valueL = l;
  164.     }
  165.     PNCounterResponse(boolean b){
  166.         this.valueB = b;
  167.     }
  168.     PNCounterResponse(CompletionStage<Long> v){
  169.         this.valueAsync = v;
  170.     }
  171.     long valueL;    
  172.     boolean valueB;
  173.     CompletionStage<Long> valueAsync;
  174. }