package org.openstack.atlas.service.domain.usage.repository;
import org.openstack.atlas.service.domain.exceptions.EntityNotFoundException;
import org.openstack.atlas.service.domain.usage.entities.HostUsage;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.TemporalType;
import java.util.Calendar;
import java.util.List;
import org.openstack.atlas.cfg.PublicApiServiceConfigurationKeys;
import org.openstack.atlas.cfg.RestApiConfiguration;
@Repository
@Transactional(value = "usage")
public class HostUsageRepository {
final Log LOG = LogFactory.getLog(HostUsageRepository.class);
@PersistenceContext(unitName = "loadbalancingUsage")
private EntityManager entityManager;
private final Integer NUM_DAYS_RETENTION = 60;
private final Integer DEFAULT_DELETE_LIMIT = 10000;
public HostUsage getById(Integer id) throws EntityNotFoundException {
HostUsage hostUsageRecord = entityManager.find(HostUsage.class, id);
if (hostUsageRecord == null) {
String errMsg = String.format("Host usage record not found");
LOG.warn(errMsg);
throw new EntityNotFoundException(errMsg);
}
return hostUsageRecord;
}
public List<HostUsage> getByDateRange(Calendar startTime, Calendar endTime) {
Query query = entityManager.createQuery("FROM HostUsage u WHERE u.snapshotTime between :startTime and :endTime order by u.hostId, u.snapshotTime asc")
.setParameter("startTime", startTime)
.setParameter("endTime", endTime);
return query.getResultList();
}
public void save(HostUsage usageToSave) {
entityManager.persist(usageToSave);
}
public void deleteOldRecords() {
Calendar deletePoint = Calendar.getInstance();
deletePoint.add(Calendar.DATE, -NUM_DAYS_RETENTION);
deleteAllRecordsBefore(deletePoint);
}
private void deleteAllRecordsBefore(Calendar time) {
RestApiConfiguration configuration = new RestApiConfiguration();
String limitStr = configuration.getString(PublicApiServiceConfigurationKeys.usage_deletion_limit);
int limitInt;
try {
limitInt = Integer.parseInt(limitStr);
} catch(NumberFormatException nfe) {
limitInt = DEFAULT_DELETE_LIMIT;
}
int numRowsDeleted;
int totalRowsDeleted = 0;
int batchCount = 0;
do {
Query nativeQ = entityManager.createNativeQuery("DELETE FROM host_usage WHERE snapshot_time <= :timestamp LIMIT :limit")
.setParameter("timestamp", time, TemporalType.TIMESTAMP).setParameter("limit", limitInt);
numRowsDeleted = nativeQ.executeUpdate();
totalRowsDeleted += numRowsDeleted;
batchCount++;
LOG.info(String.format("Deleted %d rows with endTime before %s from 'host_usage' table in batch %d.", numRowsDeleted, time.getTime(), batchCount));
} while(numRowsDeleted > 0);
LOG.info(String.format("Finished deleting rows. Deleted %d total rows in %d batch(es) with endTime before %s from 'host_usage' table.", totalRowsDeleted, batchCount, time.getTime()));
}
}