2016-01-29 15:54:16 +01:00
|
|
|
package org.gcube.accounting.aggregator.plugin;
|
|
|
|
|
2017-05-10 15:01:46 +02:00
|
|
|
import java.io.BufferedReader;
|
2016-07-29 10:48:26 +02:00
|
|
|
import java.io.File;
|
2017-05-10 15:01:46 +02:00
|
|
|
import java.io.FileOutputStream;
|
|
|
|
import java.io.FileReader;
|
|
|
|
import java.io.PrintStream;
|
2016-07-29 10:48:26 +02:00
|
|
|
import java.io.Serializable;
|
2017-05-10 15:01:46 +02:00
|
|
|
import java.text.DateFormat;
|
2016-07-29 10:48:26 +02:00
|
|
|
import java.text.SimpleDateFormat;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.Calendar;
|
2017-05-10 15:01:46 +02:00
|
|
|
import java.util.Date;
|
2016-07-29 10:48:26 +02:00
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.List;
|
2016-01-29 15:54:16 +01:00
|
|
|
import java.util.Map;
|
2016-07-29 10:48:26 +02:00
|
|
|
import java.util.UUID;
|
|
|
|
import java.util.concurrent.TimeUnit;
|
2016-01-29 15:54:16 +01:00
|
|
|
|
2016-07-29 10:48:26 +02:00
|
|
|
import org.gcube.accounting.aggregator.configuration.ConfigurationServiceEndpoint;
|
|
|
|
import org.gcube.accounting.aggregator.configuration.Constant;
|
|
|
|
import org.gcube.accounting.aggregator.configuration.ManagementFileBackup;
|
|
|
|
import org.gcube.accounting.aggregator.madeaggregation.Aggregation;
|
|
|
|
import org.gcube.accounting.aggregator.madeaggregation.AggregationType;
|
|
|
|
import org.gcube.accounting.aggregator.persistence.AggregatorPersistenceBackendQueryConfiguration;
|
|
|
|
import org.gcube.accounting.aggregator.recovery.RecoveryRecord;
|
2017-05-10 15:01:46 +02:00
|
|
|
import org.gcube.accounting.datamodel.aggregation.AggregatedJobUsageRecord;
|
|
|
|
import org.gcube.accounting.datamodel.aggregation.AggregatedPortletUsageRecord;
|
2016-07-29 10:48:26 +02:00
|
|
|
import org.gcube.accounting.datamodel.aggregation.AggregatedServiceUsageRecord;
|
2017-05-10 15:01:46 +02:00
|
|
|
import org.gcube.accounting.datamodel.aggregation.AggregatedStorageUsageRecord;
|
|
|
|
import org.gcube.accounting.datamodel.aggregation.AggregatedTaskUsageRecord;
|
|
|
|
import org.gcube.accounting.datamodel.usagerecords.JobUsageRecord;
|
|
|
|
import org.gcube.accounting.datamodel.usagerecords.PortletUsageRecord;
|
2016-07-29 10:48:26 +02:00
|
|
|
import org.gcube.accounting.datamodel.usagerecords.ServiceUsageRecord;
|
2017-05-10 15:01:46 +02:00
|
|
|
import org.gcube.accounting.datamodel.usagerecords.StorageUsageRecord;
|
|
|
|
import org.gcube.accounting.datamodel.usagerecords.TaskUsageRecord;
|
2016-07-29 10:48:26 +02:00
|
|
|
import org.gcube.common.scope.api.ScopeProvider;
|
|
|
|
import org.gcube.documentstore.exception.InvalidValueException;
|
|
|
|
import org.gcube.documentstore.persistence.PersistenceCouchBase;
|
|
|
|
import org.gcube.documentstore.records.AggregatedRecord;
|
|
|
|
import org.gcube.documentstore.records.RecordUtility;
|
2016-01-29 15:54:16 +01:00
|
|
|
import org.gcube.vremanagement.executor.plugin.Plugin;
|
|
|
|
import org.slf4j.Logger;
|
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
2016-07-29 10:48:26 +02:00
|
|
|
import com.couchbase.client.java.Bucket;
|
|
|
|
import com.couchbase.client.java.Cluster;
|
|
|
|
import com.couchbase.client.java.CouchbaseCluster;
|
|
|
|
import com.couchbase.client.java.PersistTo;
|
|
|
|
import com.couchbase.client.java.document.JsonDocument;
|
|
|
|
import com.couchbase.client.java.document.json.JsonArray;
|
|
|
|
import com.couchbase.client.java.env.CouchbaseEnvironment;
|
|
|
|
import com.couchbase.client.java.env.DefaultCouchbaseEnvironment;
|
|
|
|
import com.couchbase.client.java.view.ViewQuery;
|
|
|
|
import com.couchbase.client.java.view.ViewResult;
|
|
|
|
import com.couchbase.client.java.view.ViewRow;
|
|
|
|
|
|
|
|
|
2016-01-29 15:54:16 +01:00
|
|
|
/**
|
2016-07-29 10:48:26 +02:00
|
|
|
* @author Alessandro Pieve (ISTI - CNR)
|
|
|
|
*
|
2016-01-29 15:54:16 +01:00
|
|
|
*/
|
|
|
|
public class AccountingAggregatorPlugin extends Plugin<AccountingAggregatorPluginDeclaration> {
|
|
|
|
|
2016-07-29 10:48:26 +02:00
|
|
|
|
2016-01-29 15:54:16 +01:00
|
|
|
private static Logger logger = LoggerFactory.getLogger(AccountingAggregatorPlugin.class);
|
2016-07-29 10:48:26 +02:00
|
|
|
|
|
|
|
public Bucket accountingBucket;
|
|
|
|
protected Cluster cluster;
|
|
|
|
|
|
|
|
public Aggregation aggregate;
|
|
|
|
|
|
|
|
public static final String AGGREGATED = "aggregated";
|
|
|
|
private final static String LINE_FREFIX = "{";
|
|
|
|
private final static String LINE_SUFFIX = "}";
|
|
|
|
private final static String KEY_VALUE_PAIR_SEPARATOR = ",";
|
|
|
|
private final static String KEY_VALUE_LINKER = "=";
|
2017-01-25 15:06:16 +01:00
|
|
|
|
2016-09-30 14:44:58 +02:00
|
|
|
public static Integer countInsert=0;
|
|
|
|
public static Integer countDelete=0;
|
2017-01-25 15:06:16 +01:00
|
|
|
public static Integer recoveryMode=0;
|
|
|
|
public Boolean backup=true;
|
|
|
|
//value if 0 PersistTo.MASTER if 1 PersistTo.ONE
|
|
|
|
public static Integer typePersisted=0;
|
|
|
|
|
|
|
|
|
|
|
|
protected PersistTo persisted ;
|
2016-09-30 14:44:58 +02:00
|
|
|
/**
|
|
|
|
* @param runningPluginEvolution
|
|
|
|
*/
|
|
|
|
public AccountingAggregatorPlugin(AccountingAggregatorPluginDeclaration pluginDeclaration) {
|
|
|
|
super(pluginDeclaration);
|
|
|
|
}
|
2016-07-29 10:48:26 +02:00
|
|
|
|
|
|
|
/* The environment configuration */
|
|
|
|
protected static final CouchbaseEnvironment ENV =
|
|
|
|
DefaultCouchbaseEnvironment.builder()
|
|
|
|
.connectTimeout(Constant.CONNECTION_TIMEOUT * 1000)
|
2017-01-25 15:06:16 +01:00
|
|
|
.maxRequestLifetime(Constant.MAX_REQUEST_LIFE_TIME * 1000)
|
|
|
|
.queryTimeout(Constant.CONNECTION_TIMEOUT * 1000) //15 Seconds in milliseconds
|
|
|
|
.viewTimeout(Constant.VIEW_TIMEOUT_BUCKET * 1000)//120 Seconds in milliseconds
|
|
|
|
.keepAliveInterval(3600 * 1000) // 3600 Seconds in milliseconds
|
|
|
|
.kvTimeout(5000) //in ms
|
2016-07-29 10:48:26 +02:00
|
|
|
.build();
|
|
|
|
|
2016-01-29 15:54:16 +01:00
|
|
|
/**{@inheritDoc}*/
|
|
|
|
@Override
|
|
|
|
public void launch(Map<String, Object> inputs) throws Exception {
|
2016-07-29 15:25:30 +02:00
|
|
|
countInsert=0;
|
|
|
|
countDelete=0;
|
2016-01-29 15:54:16 +01:00
|
|
|
if(inputs == null || inputs.isEmpty()){
|
|
|
|
logger.debug("{} inputs {}", this.getClass().getSimpleName(), inputs);
|
2016-07-29 10:48:26 +02:00
|
|
|
throw new Exception("Inputs null");
|
2016-01-29 15:54:16 +01:00
|
|
|
}
|
2016-07-29 10:48:26 +02:00
|
|
|
//Type :HOURLY,DAILY,MONTHLY,YEARLY
|
|
|
|
//Interval: Number of hour,day,month,year
|
|
|
|
if (!inputs.containsKey("type") || !inputs.containsKey("interval"))
|
|
|
|
throw new IllegalArgumentException("Interval and type must be defined");
|
|
|
|
|
|
|
|
AggregationType aggType =AggregationType.valueOf((String)inputs.get("type"));
|
2017-05-10 15:01:46 +02:00
|
|
|
Integer intervaTot=(Integer)inputs.get("interval");
|
|
|
|
Integer interval=intervaTot* aggType.getMultiplierFactor();
|
2016-07-29 10:48:26 +02:00
|
|
|
|
2017-01-25 15:06:16 +01:00
|
|
|
//new feature for not elaborate the full range but a set of small intervals
|
|
|
|
if (inputs.containsKey("intervalStep"))
|
|
|
|
interval=(Integer)inputs.get("intervalStep");
|
|
|
|
|
2016-07-29 10:48:26 +02:00
|
|
|
Integer inputStartTime=null;
|
2017-05-10 15:01:46 +02:00
|
|
|
String pathFile = null;
|
2016-07-29 10:48:26 +02:00
|
|
|
if (inputs.containsKey("startTime"))
|
|
|
|
inputStartTime=(Integer)inputs.get("startTime");
|
2017-05-10 15:01:46 +02:00
|
|
|
else{
|
|
|
|
//get start time with file
|
|
|
|
logger.debug("Attention get start Time from file");
|
|
|
|
if (inputs.containsKey("pathFile")){
|
|
|
|
//get start time from file
|
|
|
|
pathFile=(String) inputs.get("pathFile");
|
2017-05-12 12:39:58 +02:00
|
|
|
logger.trace("open file:{}",pathFile);
|
2017-05-10 15:01:46 +02:00
|
|
|
|
|
|
|
BufferedReader reader = new BufferedReader(new FileReader(pathFile));
|
|
|
|
String line;
|
|
|
|
while ((line = reader.readLine()) != null)
|
|
|
|
{
|
|
|
|
line=line.trim();
|
2017-05-12 11:48:38 +02:00
|
|
|
|
|
|
|
String strDate = line;
|
|
|
|
SimpleDateFormat fmt = new SimpleDateFormat("yyyy/MM/dd");
|
|
|
|
Date d1 = fmt.parse(strDate);
|
|
|
|
Date now = new Date();
|
|
|
|
|
|
|
|
long millisDiff = now.getTime() - d1.getTime();
|
|
|
|
inputStartTime= (int) (millisDiff / 86400000);
|
|
|
|
logger.debug("Read Start Time:{}",d1.toString());
|
2017-05-10 15:01:46 +02:00
|
|
|
logger.debug("Start Time:{}",inputStartTime);
|
|
|
|
}
|
|
|
|
reader.close();
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
2016-07-29 10:48:26 +02:00
|
|
|
|
|
|
|
Boolean currentScope =false;
|
2016-07-29 11:49:12 +02:00
|
|
|
String scope=null;
|
2016-07-29 10:48:26 +02:00
|
|
|
if (inputs.containsKey("currentScope"))
|
|
|
|
currentScope=(Boolean)inputs.get("currentScope");
|
2017-01-25 15:06:16 +01:00
|
|
|
|
2016-07-29 10:48:26 +02:00
|
|
|
if (currentScope)
|
|
|
|
scope=ScopeProvider.instance.get();
|
2017-01-25 15:06:16 +01:00
|
|
|
|
2016-07-29 10:48:26 +02:00
|
|
|
if (inputs.containsKey("user"))
|
|
|
|
Constant.user=(String)inputs.get("user");
|
|
|
|
else
|
|
|
|
Constant.user="service.aggregatorAccounting";
|
|
|
|
|
|
|
|
if (inputs.containsKey("recovery"))
|
2017-01-25 15:06:16 +01:00
|
|
|
recoveryMode=(Integer)inputs.get("recovery");
|
2016-07-29 10:48:26 +02:00
|
|
|
|
2017-01-25 15:06:16 +01:00
|
|
|
if (inputs.containsKey("backup"))
|
|
|
|
backup=(Boolean)inputs.get("backup");
|
|
|
|
|
|
|
|
if (inputs.containsKey("typePersisted"))
|
|
|
|
typePersisted=(Integer)inputs.get("typePersisted");
|
|
|
|
switch(typePersisted) {
|
2017-02-21 14:17:41 +01:00
|
|
|
case 0:
|
|
|
|
persisted=PersistTo.MASTER;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
persisted=PersistTo.ONE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
persisted=PersistTo.MASTER;
|
2017-01-25 15:06:16 +01:00
|
|
|
}
|
|
|
|
|
2017-02-23 16:25:13 +01:00
|
|
|
logger.debug("-Launch with Type:{}, Interval:{}, startTime:{}, Scope:{}, Recovery:{}",aggType.toString(),interval,inputStartTime,scope,recoveryMode);
|
2017-01-25 15:06:16 +01:00
|
|
|
logger.debug("persist:{} backup:{}",persisted.toString(),backup);
|
|
|
|
if(!backup){
|
|
|
|
logger.warn("Attention backup disabled");
|
|
|
|
Thread.sleep(20000);
|
|
|
|
}
|
|
|
|
if (inputs.containsKey("intervalStep")){
|
|
|
|
logger.debug("Interval is not considered, aggregate only :{} step",interval);
|
|
|
|
}
|
2017-02-21 14:17:41 +01:00
|
|
|
|
2016-07-29 10:48:26 +02:00
|
|
|
//Get Configuration from service end point
|
|
|
|
String url=null;
|
|
|
|
String password =null;
|
|
|
|
List<String> listBucket=new ArrayList<String>();
|
|
|
|
AggregatorPersistenceBackendQueryConfiguration configuration;
|
|
|
|
try{
|
|
|
|
configuration = new AggregatorPersistenceBackendQueryConfiguration(PersistenceCouchBase.class);
|
|
|
|
url = configuration.getProperty(ConfigurationServiceEndpoint.URL_PROPERTY_KEY);
|
|
|
|
password = configuration.getProperty(ConfigurationServiceEndpoint.PASSWORD_PROPERTY_KEY);
|
|
|
|
if (inputs.containsKey("bucket"))
|
|
|
|
listBucket.add(inputs.get("bucket").toString());
|
|
|
|
else{
|
|
|
|
listBucket.add(configuration.getProperty(ConfigurationServiceEndpoint.BUCKET_STORAGE_NAME_PROPERTY_KEY));
|
|
|
|
listBucket.add(configuration.getProperty(ConfigurationServiceEndpoint.BUCKET_SERVICE_NAME_PROPERTY_KEY));
|
|
|
|
listBucket.add(configuration.getProperty(ConfigurationServiceEndpoint.BUCKET_JOB_NAME_PROPERTY_KEY));
|
|
|
|
listBucket.add(configuration.getProperty(ConfigurationServiceEndpoint.BUCKET_PORTLET_NAME_PROPERTY_KEY));
|
|
|
|
listBucket.add(configuration.getProperty(ConfigurationServiceEndpoint.BUCKET_TASK_NAME_PROPERTY_KEY));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (Exception e) {
|
2016-09-30 18:39:37 +02:00
|
|
|
logger.error("launch",e.getLocalizedMessage());
|
2016-07-29 10:48:26 +02:00
|
|
|
throw e;
|
|
|
|
}
|
|
|
|
Cluster cluster = CouchbaseCluster.create(ENV, url);
|
2017-01-25 15:06:16 +01:00
|
|
|
|
2016-07-29 10:48:26 +02:00
|
|
|
//Define a type for aggregate
|
2017-05-10 15:01:46 +02:00
|
|
|
RecordUtility.addRecordPackage(PortletUsageRecord.class.getPackage());
|
|
|
|
RecordUtility.addRecordPackage(AggregatedPortletUsageRecord.class.getPackage());
|
2016-07-29 10:48:26 +02:00
|
|
|
|
2017-05-10 15:01:46 +02:00
|
|
|
RecordUtility.addRecordPackage(JobUsageRecord.class.getPackage());
|
|
|
|
RecordUtility.addRecordPackage(AggregatedJobUsageRecord.class.getPackage());
|
2017-01-25 15:06:16 +01:00
|
|
|
|
2017-05-10 15:01:46 +02:00
|
|
|
RecordUtility.addRecordPackage(TaskUsageRecord.class.getPackage());
|
|
|
|
RecordUtility.addRecordPackage(AggregatedTaskUsageRecord.class.getPackage());
|
2017-01-25 15:06:16 +01:00
|
|
|
|
2017-05-10 15:01:46 +02:00
|
|
|
RecordUtility.addRecordPackage(StorageUsageRecord.class.getPackage());
|
|
|
|
RecordUtility.addRecordPackage(AggregatedStorageUsageRecord.class.getPackage());
|
|
|
|
|
|
|
|
RecordUtility.addRecordPackage(ServiceUsageRecord.class.getPackage());
|
|
|
|
RecordUtility.addRecordPackage(AggregatedServiceUsageRecord.class.getPackage());
|
|
|
|
//end define
|
|
|
|
|
|
|
|
Date today = new Date();
|
|
|
|
Date endScriptTime = new Date();
|
|
|
|
if (inputs.containsKey("endScriptTime")){
|
|
|
|
DateFormat df = new SimpleDateFormat ("MM/dd/yyyy HH:mm");
|
|
|
|
|
|
|
|
endScriptTime = df.parse ((today.getMonth()+1)+"/"+today.getDate()+"/"+(today.getYear()+1900) +" "+(String)inputs.get("endScriptTime"));
|
2017-05-12 12:37:19 +02:00
|
|
|
logger.debug("Script Run until :{}",endScriptTime);
|
2016-07-29 10:48:26 +02:00
|
|
|
}
|
2017-01-25 15:06:16 +01:00
|
|
|
|
2017-05-10 15:01:46 +02:00
|
|
|
do {
|
|
|
|
logger.debug("--Start Time Loop:{}"+inputStartTime);
|
|
|
|
initFolder();
|
|
|
|
if ((recoveryMode==2)||(recoveryMode==0)){
|
|
|
|
logger.debug("Recovery mode enabled");
|
|
|
|
RecoveryRecord.searchFile(cluster,configuration);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (recoveryMode!=2){
|
2017-05-12 11:56:53 +02:00
|
|
|
|
2017-05-10 15:01:46 +02:00
|
|
|
for (String bucket:listBucket){
|
|
|
|
logger.trace("OpenBucket:{}",bucket);
|
|
|
|
accountingBucket = cluster.openBucket(bucket,password);
|
|
|
|
//elaborate bucket, with scope, type aggregation and interval
|
|
|
|
elaborateBucket(bucket,scope, inputStartTime, interval, aggType);
|
|
|
|
}
|
2017-05-12 11:56:53 +02:00
|
|
|
|
2017-05-10 15:01:46 +02:00
|
|
|
if (inputs.containsKey("pathFile")){
|
|
|
|
//update a file for new start time
|
|
|
|
FileOutputStream file = new FileOutputStream(pathFile);
|
|
|
|
PrintStream output = new PrintStream(file);
|
|
|
|
logger.debug("Update pathfile:{} with new start time:{}",pathFile,inputStartTime-intervaTot);
|
2017-05-12 11:48:38 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Date dateNow = new Date();
|
|
|
|
Calendar data = Calendar.getInstance();
|
|
|
|
data.setTime(dateNow);
|
|
|
|
|
2017-05-12 11:56:53 +02:00
|
|
|
data.add(Calendar.DATE,-(inputStartTime-intervaTot));
|
2017-05-12 11:48:38 +02:00
|
|
|
SimpleDateFormat format1 = new SimpleDateFormat("yyyy/MM/dd");
|
|
|
|
|
|
|
|
String formatted = format1.format(data.getTime());
|
|
|
|
|
|
|
|
output.println(formatted);
|
2017-05-10 15:01:46 +02:00
|
|
|
inputStartTime=inputStartTime-intervaTot;
|
|
|
|
today = new Date();
|
|
|
|
}
|
|
|
|
logger.debug("Complete countInsert{}, countDelete{}",countInsert,countDelete);
|
2016-07-29 10:48:26 +02:00
|
|
|
}
|
|
|
|
|
2017-05-10 15:01:46 +02:00
|
|
|
} while(today.compareTo(endScriptTime)<0);
|
|
|
|
logger.debug("Plugin Terminated");
|
2016-01-29 15:54:16 +01:00
|
|
|
}
|
|
|
|
|
2016-07-29 10:48:26 +02:00
|
|
|
|
2016-01-29 15:54:16 +01:00
|
|
|
/**{@inheritDoc}*/
|
|
|
|
@Override
|
|
|
|
protected void onStop() throws Exception {
|
2016-07-29 10:48:26 +02:00
|
|
|
logger.trace("{} onStop() function", this.getClass().getSimpleName());
|
|
|
|
Thread.currentThread().interrupt();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Init folder for backup file
|
|
|
|
*/
|
|
|
|
public void initFolder(){
|
|
|
|
Constant.PATH_DIR_BACKUP=System.getProperty(Constant.HOME_SYSTEM_PROPERTY)+"/"+Constant.NAME_DIR_BACKUP;
|
|
|
|
Constant.PATH_DIR_BACKUP_INSERT=Constant.PATH_DIR_BACKUP+"/insert";
|
|
|
|
Constant.PATH_DIR_BACKUP_DELETE=Constant.PATH_DIR_BACKUP+"/delete";
|
|
|
|
File DirRoot = new File(Constant.PATH_DIR_BACKUP);
|
|
|
|
if (!DirRoot.exists()) {
|
|
|
|
DirRoot.mkdir();
|
|
|
|
}
|
|
|
|
logger.debug("init folder:{}",Constant.PATH_DIR_BACKUP);
|
2017-01-25 15:06:16 +01:00
|
|
|
|
|
|
|
|
2016-07-29 10:48:26 +02:00
|
|
|
}
|
2017-01-25 15:06:16 +01:00
|
|
|
|
2016-07-29 10:48:26 +02:00
|
|
|
/**
|
|
|
|
* Elaborate a Bucket from startTime to interval
|
|
|
|
* @param bucket
|
|
|
|
* @param inputStartTime
|
|
|
|
* @param interval
|
|
|
|
* @param aggType
|
|
|
|
* @return
|
|
|
|
* @throws Exception
|
|
|
|
*/
|
|
|
|
protected boolean elaborateBucket(String bucket,String scope ,Integer inputStartTime,Integer interval,AggregationType aggType) throws Exception{
|
|
|
|
|
|
|
|
SimpleDateFormat format = new SimpleDateFormat(aggType.getDateformat());
|
|
|
|
//calculate a start time and end time for map reduce key
|
|
|
|
Calendar now, nowTemp;
|
|
|
|
if (inputStartTime==null){
|
|
|
|
now= Calendar.getInstance();
|
|
|
|
nowTemp= Calendar.getInstance();
|
|
|
|
}else{
|
|
|
|
now=Calendar.getInstance();
|
|
|
|
nowTemp= Calendar.getInstance();
|
|
|
|
switch (aggType.name()) {
|
|
|
|
case "YEARLY":
|
|
|
|
now.add( Calendar.YEAR, -inputStartTime );
|
|
|
|
nowTemp.add( Calendar.YEAR, -inputStartTime );
|
|
|
|
break;
|
|
|
|
case "MONTHLY":
|
|
|
|
now.add( Calendar.MONTH, -inputStartTime );
|
|
|
|
nowTemp.add( Calendar.MONTH, -inputStartTime );
|
|
|
|
break;
|
|
|
|
case "DAILY":
|
|
|
|
now.add( Calendar.DATE, -inputStartTime );
|
|
|
|
nowTemp.add( Calendar.DATE, -inputStartTime );
|
|
|
|
break;
|
|
|
|
case "HOURLY":
|
|
|
|
now.add( Calendar.HOUR, -inputStartTime );
|
|
|
|
nowTemp.add( Calendar.HOUR, -inputStartTime );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
String endAllKeyString = format.format(now.getTime());
|
|
|
|
String endKeyString = format.format(now.getTime());
|
|
|
|
|
|
|
|
//save a record modified into a file and save into a workspace
|
|
|
|
nowTemp.add(aggType.getCalendarField(), -1*interval);
|
|
|
|
String startAllKeyString = format.format(nowTemp.getTime());
|
2017-01-25 15:06:16 +01:00
|
|
|
if (backup){
|
|
|
|
logger.debug("Start Backup");
|
2017-05-10 15:01:46 +02:00
|
|
|
WorkSpaceManagement.onSaveBackupFile(accountingBucket,bucket,scope,startAllKeyString, endAllKeyString,aggType);
|
2017-01-25 15:06:16 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
logger.debug("No Backup required");
|
2016-07-29 10:48:26 +02:00
|
|
|
|
|
|
|
List<JsonDocument> documentElaborate=new ArrayList<JsonDocument>();
|
|
|
|
|
|
|
|
for (int i=0; i<interval; i++){
|
|
|
|
now.add(aggType.getCalendarField(), -1);
|
|
|
|
String startKeyString = format.format(now.getTime());
|
|
|
|
|
|
|
|
//init a json start,end key
|
|
|
|
JsonArray startKey = Utility.generateKey(scope,startKeyString);
|
|
|
|
JsonArray endKey = Utility.generateKey(scope,endKeyString);
|
|
|
|
|
|
|
|
DesignID designid=DesignID.valueOf(bucket);
|
|
|
|
String designDocId=designid.getNameDesign();
|
|
|
|
|
|
|
|
String viewName="";
|
|
|
|
if (scope!=null)
|
|
|
|
viewName=designid.getNameViewScope();
|
|
|
|
else
|
|
|
|
viewName=designid.getNameView();
|
|
|
|
|
|
|
|
ViewQuery query = ViewQuery.from(designDocId, viewName);
|
|
|
|
query.startKey(startKey);
|
|
|
|
query.endKey(endKey);
|
|
|
|
query.reduce(false);
|
|
|
|
query.inclusiveEnd(false);
|
2017-01-25 15:06:16 +01:00
|
|
|
logger.debug("--{}/{} View Query: startKey:{} - endKey:{} designDocId:{} - viewName:{}",i,interval,startKey, endKey,designDocId,viewName);
|
2016-07-29 10:48:26 +02:00
|
|
|
ViewResult viewResult = null;
|
|
|
|
try {
|
|
|
|
viewResult = accountingBucket.query(query);
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
2017-01-25 15:06:16 +01:00
|
|
|
logger.error("Exception error VIEW",e.getLocalizedMessage(),e);
|
2016-07-29 10:48:26 +02:00
|
|
|
}
|
2017-05-10 15:01:46 +02:00
|
|
|
|
2016-07-29 10:48:26 +02:00
|
|
|
// Iterate through the returned ViewRows
|
|
|
|
aggregate = new Aggregation();
|
|
|
|
documentElaborate.clear();
|
2017-01-25 15:06:16 +01:00
|
|
|
logger.debug("Start elaborate row");
|
2017-02-21 14:17:41 +01:00
|
|
|
Boolean resultElaborate=false;
|
2016-07-29 10:48:26 +02:00
|
|
|
for (ViewRow row : viewResult)
|
2017-02-21 14:17:41 +01:00
|
|
|
resultElaborate=elaborateRow(row,documentElaborate);
|
2017-01-25 15:06:16 +01:00
|
|
|
logger.debug("End elaborate row");
|
2017-05-10 15:01:46 +02:00
|
|
|
|
|
|
|
//Backup File saved
|
2016-07-29 10:48:26 +02:00
|
|
|
String nameFileBackup="";
|
|
|
|
if (scope!=null)
|
|
|
|
nameFileBackup=scope.replace("/", "")+"-"+startKeyString+"-"+endKeyString;
|
|
|
|
else
|
|
|
|
nameFileBackup=startKeyString+"-"+endKeyString;
|
2017-05-10 15:01:46 +02:00
|
|
|
|
|
|
|
|
2016-07-29 10:48:26 +02:00
|
|
|
reallyFlush(aggregate,documentElaborate,nameFileBackup);
|
2017-02-21 14:17:41 +01:00
|
|
|
|
2016-07-29 10:48:26 +02:00
|
|
|
endKeyString = startKeyString;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Elaborate row for aggregate
|
2016-09-30 14:44:58 +02:00
|
|
|
* elaborateRow
|
2016-07-29 10:48:26 +02:00
|
|
|
* @param row
|
|
|
|
* @return
|
|
|
|
* @throws Exception
|
|
|
|
*/
|
2017-02-21 14:17:41 +01:00
|
|
|
protected Boolean elaborateRow(ViewRow row ,List<JsonDocument> documentElaborate) throws Exception{
|
2017-02-23 11:41:08 +01:00
|
|
|
int i=0;
|
|
|
|
JsonDocument documentJson = null;
|
2016-07-29 10:48:26 +02:00
|
|
|
try {
|
|
|
|
//patch for field of long type
|
|
|
|
String document=row.value().toString().replace("\":", "=").replace("\"", "");
|
2017-01-25 15:06:16 +01:00
|
|
|
i=1;//1
|
2016-07-29 10:48:26 +02:00
|
|
|
Map<String,? extends Serializable> map = getMapFromString(document);
|
2017-01-25 15:06:16 +01:00
|
|
|
i=2;//2
|
|
|
|
//prepare a document for elaborate
|
|
|
|
String identifier=(String) row.document().content().get("id");
|
2017-02-21 14:17:41 +01:00
|
|
|
i=3;//3
|
2017-02-23 11:41:08 +01:00
|
|
|
documentJson = JsonDocument.create(identifier, row.document().content());
|
2017-02-21 14:17:41 +01:00
|
|
|
i=4;//4
|
2017-01-25 15:06:16 +01:00
|
|
|
|
2016-09-30 18:39:37 +02:00
|
|
|
@SuppressWarnings("rawtypes")
|
2016-07-29 10:48:26 +02:00
|
|
|
AggregatedRecord record = (AggregatedRecord)RecordUtility.getRecord(map);
|
2017-02-21 14:17:41 +01:00
|
|
|
i=5;//5
|
2016-07-29 10:48:26 +02:00
|
|
|
aggregate.aggregate(record);
|
2017-02-21 14:17:41 +01:00
|
|
|
i=6;//6
|
2016-09-30 18:39:37 +02:00
|
|
|
//insert an elaborate row into list JsonDocument for memory document elaborate
|
2016-07-29 10:48:26 +02:00
|
|
|
documentElaborate.add(documentJson);
|
2017-01-25 15:06:16 +01:00
|
|
|
i=7;//7
|
2016-07-29 10:48:26 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
catch(InvalidValueException ex){
|
2017-01-25 15:06:16 +01:00
|
|
|
logger.warn("InvalidValueException - Record is not valid. Anyway, it will be persisted i:{}",i);
|
2017-02-27 10:38:00 +01:00
|
|
|
logger.warn("Runtime Exception ex",ex);
|
2017-02-23 11:41:08 +01:00
|
|
|
if ((i==5)&&(documentJson!=null)){
|
|
|
|
documentElaborate.add(documentJson);
|
|
|
|
}
|
2017-02-21 14:17:41 +01:00
|
|
|
return false;
|
2017-01-25 15:06:16 +01:00
|
|
|
}
|
|
|
|
catch(RuntimeException exr){
|
2017-02-23 11:41:08 +01:00
|
|
|
logger.warn("Runtime Exception -Record is not valid. Anyway, it will be persisted i:{}",i);
|
2017-02-23 16:25:13 +01:00
|
|
|
logger.warn("Runtime Exception exr",exr);
|
2017-02-23 11:41:08 +01:00
|
|
|
if ((i==5)&&(documentJson!=null)){
|
|
|
|
documentElaborate.add(documentJson);
|
2017-02-23 16:25:13 +01:00
|
|
|
logger.debug("Record is elaborate");
|
2017-02-23 11:41:08 +01:00
|
|
|
}
|
2017-02-21 14:17:41 +01:00
|
|
|
return false;
|
2016-07-29 10:48:26 +02:00
|
|
|
}
|
|
|
|
catch (Exception e) {
|
2017-01-25 15:06:16 +01:00
|
|
|
logger.error("record is not elaborated:"+row.toString()+" but it will be persisted");
|
|
|
|
logger.error("error elaborateRow", e);
|
2017-02-23 11:41:08 +01:00
|
|
|
logger.error("i:{}",i);
|
|
|
|
if ((i==5)&&(documentJson!=null)){
|
|
|
|
documentElaborate.add(documentJson);
|
2017-02-23 16:25:13 +01:00
|
|
|
logger.debug("Record is elaborate");
|
2017-02-23 11:41:08 +01:00
|
|
|
}
|
2016-07-29 10:48:26 +02:00
|
|
|
return false;
|
|
|
|
}
|
2016-01-29 15:54:16 +01:00
|
|
|
}
|
2016-07-29 10:48:26 +02:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* getMapFromString
|
|
|
|
* @param serializedMap
|
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
protected static Map<String, ? extends Serializable> getMapFromString(String serializedMap){
|
|
|
|
/* Checking line sanity */
|
2017-01-25 15:06:16 +01:00
|
|
|
if(!serializedMap.startsWith(LINE_FREFIX) && !serializedMap.endsWith(LINE_SUFFIX)){
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
/* Cleaning prefix and suffix to parse line */
|
|
|
|
serializedMap = serializedMap.replace(LINE_FREFIX, "");
|
|
|
|
serializedMap = serializedMap.replace(LINE_SUFFIX, "");
|
|
|
|
|
|
|
|
Map<String, Serializable> map = new HashMap<String,Serializable>();
|
|
|
|
|
|
|
|
String[] pairs = serializedMap.split(KEY_VALUE_PAIR_SEPARATOR);
|
|
|
|
for (int i=0;i<pairs.length;i++) {
|
|
|
|
String pair = pairs[i];
|
|
|
|
pair.trim();
|
|
|
|
String[] keyValue = pair.split(KEY_VALUE_LINKER);
|
|
|
|
String key = keyValue[0].trim();
|
|
|
|
Serializable value = keyValue[1].trim();
|
|
|
|
map.put(key, value);
|
|
|
|
}
|
|
|
|
return map;
|
2016-07-29 10:48:26 +02:00
|
|
|
}
|
2017-01-25 15:06:16 +01:00
|
|
|
|
|
|
|
|
2016-07-29 10:48:26 +02:00
|
|
|
/**
|
|
|
|
* Delete a record not aggregate and insert a new record aggregate
|
|
|
|
* If a problem with delete record, not insert a new record and save a backupfile
|
2016-09-30 14:44:58 +02:00
|
|
|
* reallyFlush
|
2016-07-29 10:48:26 +02:00
|
|
|
* @param aggregate
|
|
|
|
* @param docs
|
|
|
|
* @param nameFile
|
|
|
|
* @return
|
|
|
|
* @throws Exception
|
|
|
|
*/
|
|
|
|
protected boolean reallyFlush(Aggregation aggregate, List<JsonDocument> docs,String nameFile) throws Exception{
|
|
|
|
if (docs.size()!=0){
|
|
|
|
Integer index=0;
|
|
|
|
boolean succesfulDelete=false;
|
2017-01-25 15:06:16 +01:00
|
|
|
logger.trace("Start a delete document:{}",docs.size());
|
2017-05-10 15:01:46 +02:00
|
|
|
|
2016-07-29 10:48:26 +02:00
|
|
|
//before elaborate a record, create a backup file
|
|
|
|
List<JsonDocument> notDeleted = docs;
|
|
|
|
List<JsonDocument> notInserted = aggregate.reallyFlush();
|
|
|
|
|
|
|
|
nameFile =nameFile+"-"+UUID.randomUUID();
|
|
|
|
ManagementFileBackup.getInstance().onCreateStringToFile(notDeleted,Constant.FILE_RECORD_NO_AGGREGATE+"_"+nameFile,false);
|
|
|
|
ManagementFileBackup.getInstance().onCreateStringToFile(notInserted,Constant.FILE_RECORD_AGGREGATE+"_"+nameFile,true);
|
2017-02-23 16:25:13 +01:00
|
|
|
List<JsonDocument> notDeletedTemp = null;
|
2016-07-29 10:48:26 +02:00
|
|
|
while ((index < Constant.NUM_RETRY) && !succesfulDelete){
|
2017-02-23 16:25:13 +01:00
|
|
|
notDeletedTemp = new ArrayList<JsonDocument>();
|
2016-07-29 10:48:26 +02:00
|
|
|
for (JsonDocument doc: notDeleted){
|
2017-02-23 16:25:13 +01:00
|
|
|
if (index>0){
|
|
|
|
logger.trace("delete Start {} pass",index);
|
|
|
|
}
|
2016-07-29 10:48:26 +02:00
|
|
|
countDelete ++;
|
|
|
|
try{
|
2017-01-25 15:06:16 +01:00
|
|
|
accountingBucket.remove(doc.id(),persisted,Constant.CONNECTION_TIMEOUT_BUCKET, TimeUnit.SECONDS);
|
2017-02-27 10:38:00 +01:00
|
|
|
}
|
|
|
|
catch(Exception e){
|
2017-02-21 14:17:41 +01:00
|
|
|
logger.warn("doc:{} not deleted retry:{} for error:{}",doc.id(),index,e);
|
2017-01-25 15:06:16 +01:00
|
|
|
Thread.sleep(1500);
|
2016-07-29 10:48:26 +02:00
|
|
|
try{
|
|
|
|
if (accountingBucket.exists(doc.id()))
|
|
|
|
notDeletedTemp.add(doc);
|
|
|
|
}
|
2017-01-25 15:06:16 +01:00
|
|
|
catch(Exception ext){
|
2017-02-27 10:38:00 +01:00
|
|
|
logger.warn("doc:{} not verify for delete because timeout, retry:{}",doc.id(),index,ext);
|
2017-02-21 14:17:41 +01:00
|
|
|
Thread.sleep(3000);
|
2017-01-25 15:06:16 +01:00
|
|
|
try{
|
2017-02-27 10:38:00 +01:00
|
|
|
if (accountingBucket.exists(doc.id()))
|
2017-01-25 15:06:16 +01:00
|
|
|
notDeletedTemp.add(doc);
|
|
|
|
}
|
|
|
|
catch(Exception ex) {
|
|
|
|
logger.error("doc:{} not delete ({}), problem with exist bucket",doc.id(),doc.toString(),ex);
|
|
|
|
logger.error("force insert into list for delete");
|
|
|
|
notDeletedTemp.add(doc);
|
|
|
|
}
|
|
|
|
}
|
2016-07-29 10:48:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (notDeletedTemp.isEmpty()){
|
|
|
|
succesfulDelete=true;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
index++;
|
|
|
|
notDeleted = new ArrayList<JsonDocument>(notDeletedTemp);
|
|
|
|
Thread.sleep(1000);
|
2017-02-23 16:25:13 +01:00
|
|
|
logger.trace("First pass no delete all succesfulDelete:{} index:{}",succesfulDelete,index);
|
2016-07-29 10:48:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!succesfulDelete){
|
|
|
|
logger.error("Error Delete record");
|
2017-01-25 15:06:16 +01:00
|
|
|
}
|
|
|
|
logger.debug("Delete complete:{}, Start a insert aggregated document:{}",countDelete,notInserted.size());
|
2017-05-10 15:01:46 +02:00
|
|
|
|
2017-01-25 15:06:16 +01:00
|
|
|
// delete all record and ready for insert a new aggregated record
|
2016-07-29 10:48:26 +02:00
|
|
|
if (succesfulDelete){
|
|
|
|
//if successful record delete, delete backup file
|
|
|
|
ManagementFileBackup.getInstance().onDeleteFile(Constant.FILE_RECORD_NO_AGGREGATE+"_"+nameFile,false);
|
|
|
|
index=0;
|
|
|
|
boolean succesfulInsert=false;
|
|
|
|
while ((index < Constant.NUM_RETRY) && !succesfulInsert){
|
|
|
|
List<JsonDocument> notInsertedTemp = new ArrayList<JsonDocument>();
|
|
|
|
for (JsonDocument document: notInserted){
|
2017-02-23 16:25:13 +01:00
|
|
|
if (index>0){
|
|
|
|
logger.trace("insert Start {} pass for document:{}",index,document.toString());
|
|
|
|
}
|
2016-07-29 10:48:26 +02:00
|
|
|
countInsert ++;
|
|
|
|
try{
|
2017-01-25 15:06:16 +01:00
|
|
|
//JsonDocument response = accountingBucket.upsert(document,PersistTo.MASTER,Constant.CONNECTION_TIMEOUT_BUCKET, TimeUnit.SECONDS);
|
|
|
|
JsonDocument response = accountingBucket.upsert(document,persisted,Constant.CONNECTION_TIMEOUT_BUCKET, TimeUnit.SECONDS);
|
2016-07-29 10:48:26 +02:00
|
|
|
}
|
|
|
|
catch(Exception e){
|
2017-02-21 14:17:41 +01:00
|
|
|
logger.warn("record:{} not insert retry:{} for error:{}",document.id(),index,e);
|
2017-01-25 15:06:16 +01:00
|
|
|
Thread.sleep(1500);
|
2016-07-29 10:48:26 +02:00
|
|
|
try{
|
2017-01-25 15:06:16 +01:00
|
|
|
|
2016-07-29 10:48:26 +02:00
|
|
|
if (!accountingBucket.exists(document.id()))
|
|
|
|
notInsertedTemp.add(document);
|
|
|
|
}
|
2017-01-25 15:06:16 +01:00
|
|
|
catch(Exception ext){
|
|
|
|
logger.warn("doc:{} not verify for insert because timeout, retry",document.id(),ext);
|
|
|
|
Thread.sleep(3000);
|
|
|
|
try{
|
|
|
|
if (!accountingBucket.exists(document.id()))
|
|
|
|
notInsertedTemp.add(document);
|
|
|
|
}
|
|
|
|
catch(Exception ex) {
|
|
|
|
logger.error("doc:{} not insert ({}), problem with exist bucket",document.id(),document.toString(),ex);
|
|
|
|
logger.error("force insert into list for insert");
|
|
|
|
notInsertedTemp.add(document);
|
|
|
|
}
|
|
|
|
}
|
2016-07-29 10:48:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (notInsertedTemp.isEmpty()){
|
2017-01-25 15:06:16 +01:00
|
|
|
succesfulInsert=true;
|
2016-07-29 10:48:26 +02:00
|
|
|
}
|
|
|
|
else {
|
2017-02-23 16:25:13 +01:00
|
|
|
|
2016-07-29 10:48:26 +02:00
|
|
|
index++;
|
|
|
|
notInserted = new ArrayList<JsonDocument>(notInsertedTemp);
|
2017-02-23 16:25:13 +01:00
|
|
|
Thread.sleep(1000);
|
|
|
|
logger.trace("First pass no insert all succesfulInsert:{} index:{}",succesfulInsert,index);
|
2016-07-29 10:48:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!succesfulInsert){
|
|
|
|
//do something clever with the exception
|
|
|
|
logger.error("Error Insert record{}");
|
|
|
|
} else{
|
|
|
|
logger.debug("elaborate record aggregate:{} and record not aggregate:{}",countInsert, countDelete);
|
|
|
|
ManagementFileBackup.getInstance().onDeleteFile(Constant.FILE_RECORD_AGGREGATE+"_"+nameFile,true);
|
|
|
|
}
|
|
|
|
|
2017-01-25 15:06:16 +01:00
|
|
|
}
|
|
|
|
logger.trace("Insert complete");
|
2016-07-29 10:48:26 +02:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2016-01-29 15:54:16 +01:00
|
|
|
}
|
2016-07-29 10:48:26 +02:00
|
|
|
|