package org.openstack.atlas.service.domain.usage.repository; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.openstack.atlas.service.domain.entities.LoadBalancer; import org.openstack.atlas.service.domain.entities.Usage; import org.openstack.atlas.service.domain.events.UsageEvent; import org.openstack.atlas.service.domain.exceptions.EntityNotFoundException; import org.openstack.atlas.service.domain.usage.entities.LoadBalancerMergedHostUsage; import org.openstack.atlas.service.domain.usage.entities.LoadBalancerMergedHostUsage_; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import javax.persistence.EntityManager; import javax.persistence.NoResultException; import javax.persistence.PersistenceContext; import javax.persistence.Query; import javax.persistence.TemporalType; import javax.persistence.criteria.*; import java.math.BigInteger; import java.sql.Timestamp; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.*; @Repository @Transactional(value = "usage") public class LoadBalancerMergedHostUsageRepository { final Log LOG = LogFactory.getLog(LoadBalancerMergedHostUsageRepository.class); @PersistenceContext(unitName = "loadbalancingUsage") private EntityManager entityManager; public List<LoadBalancerMergedHostUsage> getAllUsageRecordsInOrder() { CriteriaBuilder builder = entityManager.getCriteriaBuilder(); CriteriaQuery<LoadBalancerMergedHostUsage> criteria = builder.createQuery(LoadBalancerMergedHostUsage.class); Root<LoadBalancerMergedHostUsage> lbMergedHostUsageRoot = criteria.from(LoadBalancerMergedHostUsage.class); Order startTimeOrder = builder.asc(lbMergedHostUsageRoot.get(LoadBalancerMergedHostUsage_.pollTime)); criteria.select(lbMergedHostUsageRoot); criteria.orderBy(startTimeOrder); List<LoadBalancerMergedHostUsage> usageEvents = entityManager.createQuery(criteria).getResultList(); return (usageEvents == null) ? new ArrayList<LoadBalancerMergedHostUsage>() : usageEvents; } public List<LoadBalancerMergedHostUsage> getAllUsageRecordsInOrderBeforeOrEqualToTime(Calendar timestamp) { CriteriaBuilder builder = entityManager.getCriteriaBuilder(); CriteriaQuery<LoadBalancerMergedHostUsage> criteria = builder.createQuery(LoadBalancerMergedHostUsage.class); Root<LoadBalancerMergedHostUsage> lbMergedHostUsageRoot = criteria.from(LoadBalancerMergedHostUsage.class); Predicate pollTimeBeforeTime = builder.lessThanOrEqualTo(lbMergedHostUsageRoot.get(LoadBalancerMergedHostUsage_.pollTime), timestamp); Order startTimeOrder = builder.asc(lbMergedHostUsageRoot.get(LoadBalancerMergedHostUsage_.pollTime)); criteria.select(lbMergedHostUsageRoot); criteria.where(pollTimeBeforeTime); criteria.orderBy(startTimeOrder); List<LoadBalancerMergedHostUsage> usageEvents = entityManager.createQuery(criteria).getResultList(); return (usageEvents == null) ? new ArrayList<LoadBalancerMergedHostUsage>() : usageEvents; } public void deleteAllRecordsBefore(Calendar timestamp) { Query query = entityManager.createQuery("DELETE LoadBalancerMergedHostUsage u WHERE u.pollTime < :timestamp") .setParameter("timestamp", timestamp, TemporalType.TIMESTAMP); int numRowsDeleted = query.executeUpdate(); LOG.info(String.format("Deleted %d rows with pollTime before %s", numRowsDeleted, timestamp.getTime())); } public void create(LoadBalancerMergedHostUsage loadBalancerMergedHostUsage) { entityManager.persist(loadBalancerMergedHostUsage); } public LoadBalancerMergedHostUsage getMostRecentRecordForLoadBalancer(int lbId) throws EntityNotFoundException{ Query query = entityManager.createNativeQuery("SELECT u.id, u.loadbalancer_id, u.concurrent_connections, u.incoming_transfer, " + "u.outgoing_transfer, u.concurrent_connections_ssl, u.incoming_transfer_ssl, u.outgoing_transfer_ssl, u.poll_time, " + "u.num_vips, u.tags_bitmask, u.event_type, u.account_id" + " FROM lb_merged_host_usage u WHERE u.loadbalancer_id = :loadBalancerId" + " ORDER BY u.poll_time DESC LIMIT 1") .setParameter("loadBalancerId", lbId); final List<Object[]> resultList = query.getResultList(); if (resultList == null || resultList.isEmpty()) { String message = "No recent usage record found."; LOG.debug(message); throw new EntityNotFoundException(message); } return rowToUsage(resultList.get(0)); } private LoadBalancerMergedHostUsage rowToUsage(Object[] row) { Long pollTimeMillis = ((Timestamp) row[8]).getTime(); Calendar pollTimeCal = new GregorianCalendar(); pollTimeCal.setTimeInMillis(pollTimeMillis); LoadBalancerMergedHostUsage usageItem = new LoadBalancerMergedHostUsage(); usageItem.setId(((BigInteger) row[0]).longValue()); usageItem.setLoadbalancerId((Integer) row[1]); usageItem.setConcurrentConnections(((BigInteger) row[2]).longValue()); usageItem.setIncomingTransfer(((BigInteger) row[3]).longValue()); usageItem.setOutgoingTransfer(((BigInteger) row[4]).longValue()); usageItem.setConcurrentConnectionsSsl(((BigInteger) row[5]).longValue()); usageItem.setIncomingTransferSsl(((BigInteger) row[6]).longValue()); usageItem.setOutgoingTransferSsl(((BigInteger) row[7]).longValue()); usageItem.setPollTime(pollTimeCal); usageItem.setNumVips((Integer) row[9]); usageItem.setTagsBitmask((Integer) row[10]); usageItem.setEventType(null); if(row[11] != null) { usageItem.setEventType(UsageEvent.valueOf((String)row[11])); } usageItem.setAccountId((Integer) row[12]); return usageItem; } public void batchCreate(Collection<LoadBalancerMergedHostUsage> usages) { LOG.info(String.format("batchCreate() called with %d records", usages.size())); if(usages.isEmpty()) { return; } String query = generateBatchInsertQuery(usages); entityManager.createNativeQuery(query).executeUpdate(); } public void batchDelete(Collection<LoadBalancerMergedHostUsage> usages) { List<Long> usageIds = new ArrayList<Long>(); for (LoadBalancerMergedHostUsage usage : usages) { usageIds.add(usage.getId()); } entityManager.createQuery("DELETE LoadBalancerMergedHostUsage e WHERE e.id in (:ids)") .setParameter("ids", usageIds) .executeUpdate(); } private String generateBatchInsertQuery(Collection<LoadBalancerMergedHostUsage> usages) { final StringBuilder sb = new StringBuilder(); sb.append("INSERT INTO lb_merged_host_usage(account_id, loadbalancer_id, outgoing_transfer, incoming_transfer, outgoing_transfer_ssl, incoming_transfer_ssl, concurrent_connections, concurrent_connections_ssl, num_vips, tags_bitmask, poll_time, event_type) values"); sb.append(generateFormattedValues(usages)); return sb.toString(); } private String generateFormattedValues(Collection<LoadBalancerMergedHostUsage> usages) { StringBuilder sb = new StringBuilder(); for (LoadBalancerMergedHostUsage usage : usages) { sb.append("("); if (usage.getId() != null) { sb.append(usage.getId()).append(","); } sb.append(usage.getAccountId()).append(","); sb.append(usage.getLoadbalancerId()).append(","); sb.append(usage.getOutgoingTransfer()).append(","); sb.append(usage.getIncomingTransfer()).append(","); sb.append(usage.getOutgoingTransferSsl()).append(","); sb.append(usage.getIncomingTransferSsl()).append(","); sb.append(usage.getConcurrentConnections()).append(","); sb.append(usage.getConcurrentConnectionsSsl()).append(","); sb.append(usage.getNumVips()).append(","); sb.append(usage.getTagsBitmask()).append(","); DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String pollTime = formatter.format(usage.getPollTime().getTime()); sb.append("'").append(pollTime).append("',"); if (usage.getEventType() == null) { sb.append(usage.getEventType()); } else { sb.append("'").append(usage.getEventType()).append("'"); } sb.append("),"); } if (sb.toString().endsWith(",")) { sb.deleteCharAt(sb.lastIndexOf(",")); } return sb.toString(); } }