AbstractCacheImpl.java
/*
* GovWay - A customizable API Gateway
* https://govway.org
*
* Copyright (c) 2005-2024 Link.it srl (https://link.it).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3, as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openspcoop2.utils.cache;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import org.apache.commons.jcs3.admin.CountingOnlyOutputStream;
import org.apache.commons.jcs3.engine.CacheStatus;
import org.openspcoop2.utils.Utilities;
import org.openspcoop2.utils.UtilsException;
/**
* AbstractCacheImpl
*
* @author Poli Andrea (apoli@link.it)
* @author $Author$
* @version $Rev$, $Date$
*/
public abstract class AbstractCacheImpl implements ICacheImpl {
protected String cacheName = null;
protected CacheType cacheType = null;
public AbstractCacheImpl() {
}
public AbstractCacheImpl(CacheType cacheType, String cacheName) {
this.cacheType = cacheType;
this.cacheName = cacheName;
}
@Override
public CacheType getType() {
return this.cacheType;
}
@Override
public String getName() {
return this.cacheName;
}
@Override
public boolean isEternal() throws UtilsException{
return true;
}
@Override
public String toString(){
StringBuilder bf = new StringBuilder();
try {
bf.append("CACHE SIZE["+this.getCacheSize()
+"] ITEM_COUNT["+this.getItemCount()+"] ITEM_IDLE_TIME["+this.getItemIdleTime()+"] ITEM_IDLE_LIFE["+this.getItemLifeTime()
+"] IS_ETERNAL["+this.isEternal()
+"] CACHE_ALGO["+this.getCacheAlgoritm()+"] STATS{"+this.printStats("")+"}");
return bf.toString();
} catch (UtilsException e) {
return "NonDisponibile";
}
}
@Override
public String printKeys(String separator) throws UtilsException{
StringBuilder bf = new StringBuilder();
java.util.List<String> keys = this.keys();
for (int i = 0; i < keys.size(); i++) {
String key = (String) keys.get(i);
if(i>0){
bf.append(separator);
}
bf.append("Cache["+i+"]=["+key+"]");
}
return bf.toString();
}
@Override
public String printStats(String separator) throws UtilsException{
try{
ByteArrayOutputStream bout = new ByteArrayOutputStream();
this.printStats(bout,separator);
bout.flush();
bout.close();
return bout.toString();
}catch(Exception e){
throw new UtilsException(e.getMessage(),e);
}
}
protected String _printStats(String separator, boolean thisCache) throws UtilsException {
try{
int tentativi = 0;
long sizeAttuale = -1;
while (tentativi<10) {
sizeAttuale = this.getByteCount();
if(this.errorOccursCountingBytes==false){
break;
}
if(thisCache){
//System.err.println("PROVO ALTRO TENTATIVO");
tentativi++;
}
else{
break;
}
}
StringBuilder bf = new StringBuilder();
bf.append("Nome:");
bf.append(this.cacheName);
bf.append(" ");
bf.append(separator);
bf.append("Tipo:");
bf.append(this.cacheType);
bf.append(" ");
bf.append(separator);
bf.append("Stato:");
bf.append(CacheStatus.ALIVE); // uso terminologia JCS
bf.append(" ");
bf.append(separator);
// Dalla versione 3.0 non è più presente la gestione del synchronized
// bf.append("GetSyncDisabled:");
// bf.append(cache.isSyncDisabled());
// bf.append(" ");
//
// bf.append(separator);
bf.append("Algoritmo:");
CacheAlgorithm cacheEnum = this.getCacheAlgoritm();
if(cacheEnum!=null){
bf.append(cacheEnum.name());
}else{
bf.append("-");
}
bf.append(" ");
bf.append(separator);
bf.append("Dimensione:");
bf.append(this.getCacheSize());
bf.append(" ");
bf.append(separator);
bf.append("ElementiInCache:");
bf.append(this.getItemCount());
bf.append(" ");
bf.append(separator);
bf.append("MemoriaOccupata:");
bf.append(Utilities.convertBytesToFormatString(sizeAttuale));
bf.append(" ");
bf.append(separator);
bf.append("IdleTime:");
long idleTime = this.getItemIdleTime();
if(idleTime>0){
bf.append(Utilities.convertSystemTimeIntoStringMillisecondi(idleTime*1000,false));
}
else if(idleTime==0){
bf.append("0");
}
else if(idleTime<0){
bf.append("Infinito");
}
bf.append(" ");
bf.append(separator);
bf.append("LifeTime:");
long lifeTime = this.getItemLifeTime();
if(lifeTime>0){
bf.append(Utilities.convertSystemTimeIntoStringMillisecondi(lifeTime*1000,false));
}
else if(lifeTime==0){
bf.append("0");
}
else if(lifeTime<0){
if(this.isEternal()) {
bf.append("Infinito");
}
else {
bf.append("Infinito (NoEternal?)");
}
}
bf.append(" ");
bf.append(separator);
return bf.toString();
}catch(Throwable e){
throw new UtilsException(e.getMessage(),e);
}
}
protected void _printStats(OutputStream out, String separator, boolean thisCache) throws UtilsException {
try{
out.write(_printStats(separator, thisCache).getBytes());
}catch(Exception e){
throw new UtilsException(e.getMessage(),e);
}
}
private boolean errorOccursCountingBytes_debug = false;
private boolean errorOccursCountingBytes = false;
protected long getByteCount() {
this.errorOccursCountingBytes = false;
long size = 0;
try {
for (String key : this.keys())
{
Object element = null;
try
{
element = this.get(key);
}
catch (Throwable e)
{
if(this.errorOccursCountingBytes_debug) {
System.err.println("["+this.cacheName+"] Element cache get");
e.printStackTrace(System.err);
}
this.errorOccursCountingBytes = true;
continue;
//throw new RuntimeException("IOException while trying to get a cached element", e);
}
if (element == null)
{
continue;
}
//CountingOnlyOutputStream: Keeps track of the number of bytes written to it, but doesn't write them anywhere.
CountingOnlyOutputStream counter = new CountingOnlyOutputStream();
try (ObjectOutputStream out = new ObjectOutputStream(counter);)
{
out.writeObject(element);
}
catch (Throwable e)
{
if(this.errorOccursCountingBytes_debug) {
System.err.println("["+this.cacheName+"] Element cache writeObject ("+element.getClass().getName()+")");
e.printStackTrace(System.err);
}
this.errorOccursCountingBytes = true;
continue;
//throw new RuntimeException("IOException while trying to measure the size of the cached element", e);
}
finally
{
try
{
counter.close();
}
catch (IOException e)
{
// ignore
}
}
// 4 bytes lost for the serialization header
size += counter.getCount() - 4;
}
}
catch ( Exception e )
{
System.err.println( "Problem getting byte count (Modified by GovWay). Likley cause is a non serilizable object." + e.getMessage() );
e.printStackTrace(System.err);
}
return size;
}
}