/*
* Copyright (C) 2008 Universidade Federal de Campina Grande
*
* This file is part of OurGrid.
*
* OurGrid is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option)
* any later version.
*
* 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.ourgrid.peer.business.dao;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.ourgrid.common.interfaces.to.GridProcessAccounting;
import org.ourgrid.common.internal.IResponseTO;
import org.ourgrid.common.internal.response.LoggerResponseTO;
import org.ourgrid.common.statistics.beans.peer.Balance;
import org.ourgrid.common.statistics.beans.peer.BalanceValue;
import org.ourgrid.common.statistics.beans.peer.GridProcess;
import org.ourgrid.common.statistics.beans.peer.Peer;
import org.ourgrid.common.statistics.util.hibernate.HibernateUtil;
import org.ourgrid.common.util.CommonUtils;
import org.ourgrid.peer.business.controller.messages.AccountingMessages;
import org.ourgrid.peer.to.PeerBalance;
import org.ourgrid.reqtrace.Req;
/**
* Manages accounting data
*/
@Req("REQ027")
public class AccountingDAO {
public void addReplicaAccounting(GridProcessAccounting replicaAccounting, String dNdata) {
updateGridProcessAccounting(dNdata, replicaAccounting);
}
private void updateGridProcessAccounting(String dNdata,
GridProcessAccounting replicaAccounting) {
long jobId = replicaAccounting.getJobId();
int taskId = replicaAccounting.getTaskSequenceNumber();
int processId = replicaAccounting.getGridProcessSequenceNumber();
long requestId = replicaAccounting.getRequestId();
Criteria criteria = HibernateUtil.getSession().createCriteria(
GridProcess.class);
criteria.add(Restrictions.eq("sequenceNumber", processId));
Criteria taskCriteria = criteria.createCriteria("task");
taskCriteria.add(Restrictions.eq("sequenceNumber", taskId));
Criteria jobCriteria = taskCriteria.createCriteria("job");
jobCriteria.add(Restrictions.eq("jobId", jobId));
jobCriteria.add(Restrictions.eq("requestId", requestId));
GridProcess gridProcess = (GridProcess) criteria.uniqueResult();
gridProcess.setProviderDN(dNdata);
gridProcess.setCpuConsumed(replicaAccounting.getAccountings().getCPUTime());
gridProcess.setDataConsumed(replicaAccounting.getAccountings().getData());
Session session = HibernateUtil.getSession();
session.saveOrUpdate(gridProcess);
session.flush();
}
public Map<String, List<GridProcess>> getProcessesOfRequest(long requestId) {
Criteria criteria = HibernateUtil.getSession().createCriteria(
GridProcess.class);
criteria.createCriteria("task").createCriteria("job").add(
Restrictions.eq("requestId", requestId));
@SuppressWarnings("unchecked")
List<GridProcess> processes = criteria.list();
Map<String, List<GridProcess>> processPerPeerDn = CommonUtils.createSerializableMap();
for (GridProcess gridProcess : processes) {
String providerDN = gridProcess.getProviderDN();
List<GridProcess> gridProcesses = processPerPeerDn.get(providerDN);
if (gridProcesses == null) {
gridProcesses = new ArrayList<GridProcess>();
processPerPeerDn.put(providerDN, gridProcesses);
}
gridProcesses.add(gridProcess);
}
return processPerPeerDn;
}
/**
* Returns te current balance of a remote peer
* @param remotePeerPublicKey The remote peer's public key
* @return The remote peer balance
*/
public PeerBalance getRemotePeerBalance(Peer localPeer, Peer remotePeer) {
if (localPeer == null || remotePeer == null) {
return null;
}
Criteria criteria = HibernateUtil.getSession().createCriteria(Balance.class);
criteria.createCriteria("self").add(Restrictions.eq("DNdata", localPeer.getDNdata()));
criteria.createCriteria("other").add(Restrictions.eq("DNdata", remotePeer.getDNdata()));
// criteria.add(Restrictions.eq("self.DNdata", localPeer.getDNdata()));
// criteria.add(Restrictions.eq("other.DNdata", remotePeer.getDNdata()));
criteria.addOrder(Order.desc("balanceTime"));
List<Balance> balances = criteria.list();
PeerBalance balanceReturn = null;
if (balances != null && !balances.isEmpty()) {
Balance balance = balances.get(0);
List<BalanceValue> values = balance.getValues();
if (values != null) {
balanceReturn = fillBalanceValue(values);
}
}
return balanceReturn;
}
@Req("{REQ035, REQ115}")
public Map<String, PeerBalance> getBalances(Peer localPeer) {
Criteria criteria = HibernateUtil.getSession().createCriteria(Balance.class);
criteria.createCriteria("self").add(Restrictions.eq("DNdata", localPeer.getDNdata()));
//criteria.add(Restrictions.eq("self.dNdata", localPeer.getdndata()));
criteria.addOrder(Order.desc("balanceTime"));
List<Balance> balances = criteria.list();
//FIXME revise and improve filter
List<Balance> latestBalances = findLatestBalances(balances);
Map<String, PeerBalance> peerBalances = CommonUtils.createSerializableMap();
if (!latestBalances.isEmpty()) {
for (Iterator<Balance> iterator = latestBalances.iterator(); iterator.hasNext();) {
Balance balance = (Balance) iterator.next();
List<BalanceValue> values = balance.getValues();
if (values != null && !values.isEmpty()) {
PeerBalance pBalance = fillBalanceValue(values);
Peer remotePeer = balance.getOther();
// String[] splitAddress = remotePeer.getAddress().split("@");
// String userName = splitAddress[0];
// String serverName = splitAddress[1];
// ServiceID serviceID = new ServiceID(userName, serverName, PeerConstants.MODULE_NAME,
// PeerConstants.REMOTE_ACCESS_OBJECT_NAME);
peerBalances.put(remotePeer.getDNdata(), pBalance);
}
}
}
return peerBalances;
}
private PeerBalance fillBalanceValue(List<BalanceValue> values) {
Double cpuTime = null;
Double data = null;
for (Iterator<BalanceValue> iterator = values.iterator(); iterator.hasNext();) {
BalanceValue balanceValue = (BalanceValue) iterator.next();
if (balanceValue.getProperty().equals(PeerBalance.CPU_TIME)) {
cpuTime = Double.valueOf(balanceValue.getValue());
} else if (balanceValue.getProperty().equals(PeerBalance.DATA)) {
data = Double.valueOf(balanceValue.getValue());
}
}
return new PeerBalance(cpuTime, data);
}
private List<Balance> findLatestBalances(List<Balance> balances) {
List<String> remotePeers = new ArrayList<String>();
List<Balance> balanceReturn = new ArrayList<Balance>();
for (Iterator<Balance> iterator = balances.iterator(); iterator.hasNext();) {
Balance balance = (Balance) iterator.next();
if (!remotePeers.contains(balance.getOther().getAddress())) {
balanceReturn.add(balance);
remotePeers.add(balance.getOther().getAddress());
}
}
return balanceReturn;
}
public void setRemotePeerBalance(List<IResponseTO> responses, Peer localPeer, Peer remotePeer, PeerBalance newBalance,
String remotePeerDN) {
Session session = HibernateUtil.getSession();
if (remotePeer == null) {
LoggerResponseTO loggerResponse = new LoggerResponseTO(
AccountingMessages.getNotReceivedRemoteWorkerProviderMessage(
remotePeerDN), LoggerResponseTO.WARN);
responses.add(loggerResponse);
return;
}
if (newBalance.isClear()) {
Balance currentBalance = findBalanceByDate(new Date(), session, localPeer, remotePeer);
if (currentBalance != null) {
removeBalanceValues(session, currentBalance);
}
} else {
Balance currentBalance = findBalanceByDate(new Date(), session, localPeer, remotePeer);
if (currentBalance == null) {
Balance balance = new Balance();
balance.setBalanceTime(new Date());
balance.setLastModified(new Date().getTime());
balance.setOther(remotePeer);
balance.setSelf(localPeer);
fillBalanceValues(balance, newBalance.getCPUTime().toString(), newBalance.getData().toString());
session.save(balance);
} else {
if (currentBalance != null) {
removeBalanceValues(session, currentBalance);
}
fillBalanceValues(currentBalance, newBalance.getCPUTime().toString(), newBalance.getData().toString());
session.update(currentBalance);
}
}
}
private void removeBalanceValues(Session session, Balance currentBalance) {
List<BalanceValue> values = currentBalance.getValues();
if (values != null) {
for (BalanceValue balanceValue : values) {
session.delete(balanceValue);
}
}
currentBalance.setValues(null);
session.update(currentBalance);
}
protected void fillBalanceValues(Balance balance, String cpuTime, String dataValue) {
BalanceValue cpu = new BalanceValue();
cpu.setBalance(balance);
cpu.setProperty(PeerBalance.CPU_TIME);
cpu.setValue(cpuTime);
cpu.setLastModified(new Date().getTime());
BalanceValue data = new BalanceValue();
data.setBalance(balance);
data.setProperty(PeerBalance.DATA);
data.setValue(dataValue);
data.setLastModified(new Date().getTime());
balance.setValues(new ArrayList<BalanceValue>());
balance.getValues().add(cpu);
balance.getValues().add(data);
}
private Balance findBalanceByDate(Date date, Session session, Peer localPeer, Peer remotePeer) {
Calendar todayInitDalendar = Calendar.getInstance();
todayInitDalendar.set(Calendar.MILLISECOND, 0);
todayInitDalendar.set(Calendar.HOUR_OF_DAY, 0);
todayInitDalendar.set(Calendar.MINUTE, 0);
todayInitDalendar.set(Calendar.SECOND, 0);
Date todayInit = todayInitDalendar.getTime();
Calendar todayEndCalendar = Calendar.getInstance();
todayInitDalendar.set(Calendar.MILLISECOND, 0);
todayInitDalendar.set(Calendar.HOUR_OF_DAY, 23);
todayInitDalendar.set(Calendar.MINUTE, 59);
todayInitDalendar.set(Calendar.SECOND, 59);
Date todayEnd = todayEndCalendar.getTime();
Criteria criteria = session.createCriteria(Balance.class);
criteria.add(Restrictions.between("balanceTime", todayInit, todayEnd));
// criteria.add(Restrictions.eq("self.DNdata", localPeer.getDNdata()));
// criteria.add(Restrictions.eq("other.DNdata", remotePeer.getDNdata()));
criteria.createCriteria("self").add(Restrictions.eq("DNdata", localPeer.getDNdata()));
criteria.createCriteria("other").add(Restrictions.eq("DNdata", remotePeer.getDNdata()));
return (Balance) criteria.uniqueResult();
}
/**
* Save the current peer balances in a file
* @param rankingFilePath The path of file where the balances will be saved.
*/
public void saveBalancesRanking(String rankingFilePath) {
/*try {
serializeObject(rankingFilePath, getBalances(), "the accounting ranking");
} catch (IOException e) {
getLog().debug("The ranking file '" + rankingFilePath + "' could not be saved.", e);
}*/
}
/**
* Load the saved peer balances from a file
* @param filePath The path of file where the balances are saved.
*/
@SuppressWarnings("unchecked")
public void loadBalancesRanking(String filePath) {
/*try {
balances = (Map<String, PeerBalance>) loadObject(filePath, "the accounting ranking");
} catch (StreamCorruptedException e) {
getLog().fatal("The Network of Favors ranking file [" + filePath + "] is corrupted. " +
"The peer cannot be started.", e);
throw new RuntimeException(e);
} catch (IOException e) {
getLog().debug("The ranking file [" + filePath + "] could not be loaded. "
+ "Using empty NoF data.", e);
balances = new HashMap<String, PeerBalance>();
} catch (ClassNotFoundException e) {
getLog().fatal("The ranking file [" + filePath + "] could not be loaded. "
+ "Unknown error.", e);
throw new RuntimeException(e);
}*/
}
}