package org.mapfish.print.servlet.job.impl.hibernate;
import org.hibernate.Criteria;
import org.hibernate.FetchMode;
import org.hibernate.LockMode;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.type.LongType;
import org.hibernate.type.Type;
import org.mapfish.print.servlet.job.PrintJobStatus;
import org.springframework.beans.factory.annotation.Autowired;
import java.net.URI;
import java.util.List;
import javax.annotation.PostConstruct;
/**
* JobEntryDao.
*
*/
public class PrintJobDao {
@Autowired
private SessionFactory sf;
/**
* Initialize db manager.
*/
@PostConstruct
public final void init() {
this.sf.openSession();
}
public final Session getSession() {
return this.sf.getCurrentSession();
}
/**
*
* Save Job Record.
*
* @param entry the entry
*/
public final void save(final PrintJobStatusExtImpl entry) {
getSession().merge(entry);
getSession().flush();
getSession().evict(entry);
}
/**
*
* Get Job Record.
*
* @param id the id
* @return
*/
public final PrintJobStatusExtImpl get(final String id) {
final PrintJobStatusExtImpl result = get(id, false);
getSession().evict(result);
return result;
}
/**
*
* Get Job Record.
*
* @param id the id
* @param lock whether record should be locked for transaction
* @return the job status.
*/
public final PrintJobStatusExtImpl get(final String id, final boolean lock) {
Criteria c = getSession().createCriteria(PrintJobStatusExtImpl.class);
c.add(Restrictions.idEq(id));
if (lock) { //LOCK means SELECT FOR UPDATE which prevents these records to be pulled by different instances
c.setLockMode("pj", LockMode.PESSIMISTIC_READ);
c.setFetchMode("result", FetchMode.SELECT);
} else {
c.setReadOnly(true); // make sure the object is not updated if there is no lock
}
return (PrintJobStatusExtImpl) c.uniqueResult();
}
/**
* get specific property value of job.
*
* @param id the id
* @param property the property name/path
* @return the property value
*/
public final Object getValue(final String id, final String property) {
Criteria c = getSession().createCriteria(PrintJobStatusExtImpl.class);
c.add(Restrictions.idEq(id));
c.setProjection(Projections.property(property));
return c.uniqueResult();
}
/**
*
* @param statuses the statuses to include (or none if all)
* @return the total amount of jobs
*/
public final int count(final PrintJobStatus.Status... statuses) {
Criteria c = getSession().createCriteria(PrintJobStatusExtImpl.class);
if (statuses.length > 0) {
c.add(Restrictions.in("status" , statuses));
}
c.setProjection(Projections.rowCount());
return ((Number) c.uniqueResult()).intValue();
}
/**
*
* @param statuses the statuses to include (or none if all)
* @return the jobs
*/
@SuppressWarnings("unchecked")
public final List<PrintJobStatusExtImpl> get(final PrintJobStatus.Status... statuses) {
Criteria c = getSession().createCriteria(PrintJobStatusExtImpl.class);
if (statuses.length > 0) {
c.add(Restrictions.in("status" , statuses));
}
return (List<PrintJobStatusExtImpl>) c.list();
}
/**
*
* @return total time spent printing
*/
public final long getTotalTimeSpentPrinting() {
Criteria c = getSession().createCriteria(PrintJobStatusExtImpl.class);
c.add(Restrictions.isNotNull("completionTime"));
c.setProjection(Projections.sqlProjection("sum(completionTime - startTime) as totalTime",
new String[] {"totalTime"}, new Type[] { LongType.INSTANCE }));
Number result = (Number) c.uniqueResult();
return result == null ? 0 : result.longValue();
}
/**
* Cancel old waiting jobs.
*
* @param starttimeThreshold threshold for start time
* @param checkTimeThreshold threshold for last check time
* @param message the error message
*/
public final void cancelOld(final long starttimeThreshold, final long checkTimeThreshold, final String message) {
Query query = getSession().createQuery("update PrintJobStatusExtImpl pj " + "set status=:newstatus, error=:msg "
+ "where pj.status = :oldstatus " + "and (startTime < :starttimethreshold "
+ "or lastCheckTime < :checktimethreshold)");
query.setParameter("oldstatus", PrintJobStatus.Status.WAITING);
query.setParameter("newstatus", PrintJobStatus.Status.CANCELLED);
query.setParameter("msg", message);
query.setParameter("starttimethreshold", starttimeThreshold);
query.setParameter("checktimethreshold", checkTimeThreshold);
query.executeUpdate();
}
/**
* Update the lastCheckTime of the given record.
* @param id the id
* @param lastCheckTime the new value
*/
public final void updateLastCheckTime(final String id, final long lastCheckTime) {
Query query = getSession().createQuery("update PrintJobStatusExtImpl pj " + "set lastCheckTime=:lastCheckTime "
+ "where pj.referenceId = :id");
query.setParameter("id", id);
query.setParameter("lastCheckTime", lastCheckTime);
query.executeUpdate();
}
/**
* Delete old jobs.
*
* @param checkTimeThreshold
* threshold for last check time
*/
public final void deleteOld(final long checkTimeThreshold) {
Query query = getSession()
.createQuery("delete from PrintJobStatusExtImpl " + "where lastCheckTime < :checktimethreshold)");
query.setParameter("checktimethreshold", checkTimeThreshold);
query.executeUpdate();
}
/**
* Poll for the next N waiting jobs in line.
*
* @param size maximum amount of jobs to poll for
* @return
*/
@SuppressWarnings("unchecked")
public final List<PrintJobStatusExtImpl> poll(final int size) {
Query query = getSession()
.createQuery("from PrintJobStatusExtImpl pj " + "where status = :status " + "order by startTime");
query.setParameter("status", PrintJobStatus.Status.WAITING);
query.setMaxResults(size);
// LOCK but don't wait for release (since this is run continuously
// anyway, no wait prevents deadlock)
query.setLockMode("pj", LockMode.UPGRADE_NOWAIT);
return (List<PrintJobStatusExtImpl>) query.list();
}
/**
* Get result report.
*
* @param reportURI
* the URI of the report
* @return the result report.
*/
public final PrintJobResultExtImpl getResult(final URI reportURI) {
Criteria c = getSession().createCriteria(PrintJobResultExtImpl.class);
c.add(Restrictions.idEq(reportURI.toString()));
return (PrintJobResultExtImpl) c.uniqueResult();
}
}