/*
* 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.statistics;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.ourgrid.common.interfaces.to.LocalWorkerState;
import org.ourgrid.common.internal.IResponseTO;
import org.ourgrid.common.specification.OurGridSpecificationConstants;
import org.ourgrid.common.specification.worker.WorkerSpecification;
import org.ourgrid.common.statistics.beans.peer.Attribute;
import org.ourgrid.common.statistics.beans.peer.Peer;
import org.ourgrid.common.statistics.beans.peer.Worker;
import org.ourgrid.common.statistics.beans.peer.monitor.WorkerStatusChange;
import org.ourgrid.common.statistics.beans.status.WorkerStatus;
import org.ourgrid.common.statistics.util.hibernate.HibernateUtil;
import org.ourgrid.peer.business.dao.LocalWorkersDAO;
import org.ourgrid.peer.business.dao.PeerDAOFactory;
import org.ourgrid.peer.business.util.LoggerUtil;
import org.ourgrid.peer.to.LocalWorker;
/**
*
*/
public class WorkerDAO extends EntityDAO {
public void insert(List<IResponseTO> responses, Worker worker) {
responses.add(LoggerUtil.enter());
worker.setAddress(worker.getAddress().toLowerCase());
Session session = HibernateUtil.getSession();
session.save(worker);
session.flush();
responses.add(LoggerUtil.leave());
}
public Worker findByID(List<IResponseTO> responses, long id) {
responses.add(LoggerUtil.enter());
Criteria criteria = HibernateUtil.getSession().createCriteria(Worker.class);
criteria.add(Restrictions.eq("id", id));
Worker worker = (Worker) criteria.uniqueResult();
responses.add(LoggerUtil.leave());
return worker;
}
public Worker findByID(List<IResponseTO> responses, String address) {
responses.add(LoggerUtil.enter());
Criteria criteria = HibernateUtil.getSession().createCriteria(Worker.class);
criteria.add(Restrictions.eq("address", address));
Worker worker = (Worker) criteria.uniqueResult();
responses.add(LoggerUtil.leave());
return worker;
}
public Collection<Worker> findAllActiveWorkers(List<IResponseTO> responses, String myUserAtServer) {
responses.add(LoggerUtil.enter());
Peer workerPeer = PeerDAOFactory.getInstance().getPeerDAO().findByID(responses, myUserAtServer);
Criteria criteria = HibernateUtil.getSession().createCriteria(Worker.class);
criteria.add(Restrictions.isNull("endTime"));
criteria.createCriteria("peer").add(Restrictions.eq("address", workerPeer.getAddress()));
Collection<Worker> workers = criteria.list();
for (Worker worker : workers) {
String queryStr = "SELECT distinct a FROM Attribute a " +
"WHERE a.worker.id = " + worker.getId() + " AND a.endTime = null";
Query query = HibernateUtil.getSession().createQuery(queryStr);
List<Attribute> attributes = query.list();
worker.setAttributes(attributes);
}
responses.add(LoggerUtil.leave());
return workers;
}
public void updateWorkAccounting(List<IResponseTO> responses, String workerUserAtServer, double cpuTime, double dataStored) {
Worker worker = findActiveWorker(responses, workerUserAtServer);
double newCpuTime = worker.getCpuTime() + cpuTime;
double newDataStored = worker.getDataStored() + dataStored;
worker.setCpuTime(newCpuTime);
worker.setDataStored(newDataStored);
update(responses, worker);
}
public void update(List<IResponseTO> responses, Worker worker) {
responses.add(LoggerUtil.enter());
Session session = HibernateUtil.getSession();
session.update(worker);
session.flush();
responses.add(LoggerUtil.leave());
}
public void insert(List<IResponseTO> responses, Attribute attribute) {
responses.add(LoggerUtil.enter());
Session session = HibernateUtil.getSession();
session.save(attribute);
session.flush();
responses.add(LoggerUtil.leave());
}
public void update(List<IResponseTO> responses, Attribute attribute) {
responses.add(LoggerUtil.enter());
Session session = HibernateUtil.getSession();
session.update(attribute);
session.flush();
responses.add(LoggerUtil.leave());
}
@SuppressWarnings("unchecked")
public WorkerStatusChange findCurrentStatus(List<IResponseTO> responses, Worker worker) {
responses.add(LoggerUtil.enter());
WorkerStatusChange wsc = null;
Criteria criteria = HibernateUtil.getSession().createCriteria(WorkerStatusChange.class);
criteria.createCriteria("worker").add(Restrictions.eq("id", worker.getId()));
criteria.addOrder(Order.desc("timeOfChange"));
List<WorkerStatusChange> result = criteria.list();
if(!result.isEmpty()){
wsc = result.get(0);
}
responses.add(LoggerUtil.leave());
return wsc;
}
public void insert(List<IResponseTO> responses, WorkerStatusChange statusChange) {
responses.add(LoggerUtil.enter());
Session session = HibernateUtil.getSession();
session.save(statusChange);
session.flush();
responses.add(LoggerUtil.leave());
}
@SuppressWarnings("unchecked")
public Attribute findByWorkerAndProperty(List<IResponseTO> responses, Worker worker, String key) {
responses.add(LoggerUtil.enter());
Attribute att = null;
Criteria criteria = HibernateUtil.getSession().createCriteria(Attribute.class);
criteria.createCriteria("worker").add(Restrictions.eq("id", worker.getId()));
criteria.add(Restrictions.eq("property", key));
List<Attribute> result = criteria.list();
if(!result.isEmpty()){
att = result.get(0);
}
responses.add(LoggerUtil.leave());
return att;
}
public Worker findActiveWorker(List<IResponseTO> responses, String workerUserAtServer) {
responses.add(LoggerUtil.enter());
Criteria criteria = HibernateUtil.getSession().createCriteria(Worker.class);
criteria.add(Restrictions.eq("address", workerUserAtServer.toLowerCase()));
criteria.add(Restrictions.isNull("endTime"));
Worker worker = (Worker) criteria.uniqueResult();
responses.add(LoggerUtil.leave());
return worker;
}
public void statusChanged(List<IResponseTO> responses, String workerUserAtServer, LocalWorkerState workerStatus, String allocatedFor) {
Worker worker = findActiveWorker(responses, workerUserAtServer);
if (worker == null) {
throw new RuntimeException("There is no worker " + workerUserAtServer);
}
WorkerStatusChange statusChange = new WorkerStatusChange();
statusChange.setLastModified(now());
WorkerStatus status = null;
if (LocalWorkerState.DONATED.equals(workerStatus)) {
status = WorkerStatus.DONATED;
} else if (LocalWorkerState.IDLE.equals(workerStatus)) {
status = WorkerStatus.IDLE;
} else if (LocalWorkerState.IN_USE.equals(workerStatus)) {
status = WorkerStatus.IN_USE;
} else if (LocalWorkerState.OWNER.equals(workerStatus)) {
status = WorkerStatus.OWNER;
} else if (LocalWorkerState.ERROR.equals(workerStatus)) {
status = WorkerStatus.ERROR;
}
worker.setStatus(status);
worker.setAllocatedFor(allocatedFor);
worker.setLastModified(now());
statusChange.setStatus(status);
statusChange.setTimeOfChange(now());
statusChange.setWorker(worker);
update(responses, worker);
insert(responses, statusChange);
}
public void statusChanged(List<IResponseTO> responses, String workerUserAtServer, LocalWorkerState workerStatus) {
statusChanged(responses, workerUserAtServer, workerStatus, null);
}
public void addRemoteWorker(List<IResponseTO> responses, WorkerSpecification workerSpec, String providerDN, String consumerUserAtServer) {
String address = workerSpec.getAttribute(OurGridSpecificationConstants.ATT_USERNAME) + "@" + workerSpec.getAttribute(OurGridSpecificationConstants.ATT_SERVERNAME);
Worker worker = findByID(responses, address);
PeerDAO peerDAO = PeerDAOFactory.getInstance().getPeerDAO();
Peer peer = peerDAO.getPeerBySubjectDN(responses, providerDN);
boolean isWorkerNew = worker == null;
if (isWorkerNew) {
worker = new Worker();
worker.setAddress(address);
}
worker.setLastModified(now());
worker.setBeginTime(now());
worker.setEndTime(null);
worker.setPeer(peer);
worker.setStatus(WorkerStatus.DONATED);
worker.setAllocatedFor(consumerUserAtServer);
if (isWorkerNew) {
insert(responses, worker);
} else {
update(responses, worker);
}
addWorkerAttributes(responses, worker, workerSpec.getAttributes(), false);
addWorkerAttributes(responses, worker, workerSpec.getAnnotations(), true);
}
public void addLocalWorker(List<IResponseTO> responses, LocalWorker localWorker, String myUserAtServer) {
//PeerDAO peerDAO = getDAO(PeerDAO.class);
String workerUserAtServer = localWorker.getWorkerUserAtServer();
Worker worker = findActiveWorker(responses, workerUserAtServer);
Peer peer = PeerDAOFactory.getInstance().getPeerDAO().findByID(responses, myUserAtServer);
if (worker == null) {
worker = new Worker();
worker.setAddress(workerUserAtServer);
worker.setLastModified(now());
worker.setBeginTime(now());
worker.setEndTime(null);
worker.setPeer(peer);
//peer.getWorkers().add(worker);
insert(responses, worker);
}
addWorkerAttributes(responses, worker, localWorker.getAttributes(), false);
addWorkerAttributes(responses, worker, localWorker.getAnnotations(), true);
statusChanged(responses, workerUserAtServer, LocalWorkerState.OWNER);
}
private void addWorkerAttributes(List<IResponseTO> responses, Worker worker, Map<String, String> attributes, boolean isAnnotation) {
for (String key : attributes.keySet()) {
String value = attributes.get(key);
Attribute attribute = findByWorkerAndProperty(responses, worker, key);
if (attribute == null) { //new attribute?
attribute = createAttribute(worker, key, value, isAnnotation);
insert(responses, attribute);
} else {
if( !attribute.getIsAnnotation() && isAnnotation)
continue; //An annotation cannot overwrite an attribute
String oldValue = attribute.getValue();
if (!oldValue.equals(value)) {
attribute.setEndTime(now());
attribute.setLastModified(now());
update(responses, attribute);
attribute = createAttribute(worker, key, value, isAnnotation);
insert(responses, attribute);
}
}
}
}
public void updateWorker(List<IResponseTO> responses, String workerUserAtServer, Map<String, String> currentAttributes, Map<String, String> currentAnnotations) {
Worker worker = findActiveWorker(responses, workerUserAtServer);
if (worker == null) {
throw new RuntimeException("There is no worker " + workerUserAtServer);
}
worker.setLastModified(now());
updateAttributes(responses, currentAttributes, worker, false);
updateAttributes(responses, currentAnnotations, worker, true);
}
private void updateAttributes(List<IResponseTO> responses, Map<String, String> currentAttributes, Worker worker, boolean annotation) {
List<String> newAttributes = new ArrayList<String>(currentAttributes.keySet());
for (Attribute oldAttribute : worker.getAttributes()) {
if(annotation && !oldAttribute.getIsAnnotation())
continue; //an annotation cannot overwrite an attribute
if (currentAttributes.containsKey(oldAttribute.getProperty())) {
oldAttribute.setValue(currentAttributes.get(oldAttribute.getProperty()));
oldAttribute.setIsAnnotation( annotation );
oldAttribute.setEndTime(null);
newAttributes.remove(oldAttribute.getProperty());
} else {
oldAttribute.setEndTime(now());
}
oldAttribute.setLastModified(now());
update(responses, oldAttribute);
} //for
for (String key : newAttributes) {
String value = currentAttributes.get(key);
Attribute attribute = createAttribute(worker, key, value, annotation);
insert(responses, attribute);
}
}
//TODO Must deal with annotations?
public LocalWorker removeLocalWorker(List<IResponseTO> responses,String workerUserAtServer) {
LocalWorkersDAO localWorkersDAO = PeerDAOFactory.getInstance().getLocalWorkersDAO();
LocalWorker localWorker = localWorkersDAO.getLocalWorker(responses, workerUserAtServer);
String address = workerUserAtServer;
Worker worker = findActiveWorker(responses, address);
if (worker == null) {
throw new RuntimeException("There is no worker " + address);
}
worker.setEndTime(now());
worker.setLastModified(now());
worker.setStatus(WorkerStatus.DISCONNECTED);
worker.setAllocatedFor(null);
WorkerStatusChange statusChange = new WorkerStatusChange();
statusChange.setLastModified(now());
statusChange.setStatus(WorkerStatus.DISCONNECTED);
statusChange.setTimeOfChange(now());
statusChange.setWorker(worker);
insert(responses, statusChange);
update(responses, worker);
for (Attribute attribute : worker.getAttributes()) {
attribute.setEndTime(now());
attribute.setLastModified(now());
update(responses, attribute);
}
return localWorker;
}
public void removeRemoteWorker(List<IResponseTO> responses, String remoteWorkerUserAtServer) {
Worker remoteWorker = findActiveWorker(responses, remoteWorkerUserAtServer);
if (remoteWorker != null) {
remoteWorker.setEndTime(now());
remoteWorker.setLastModified(now());
remoteWorker.setStatus(WorkerStatus.DISCONNECTED);
remoteWorker.setAllocatedFor(null);
update(responses, remoteWorker);
}
}
}