quota: fixed transaction, boundary conditions

This commit is contained in:
Abhinandan Prateek 2015-07-21 14:11:04 +05:30
parent c13b329df7
commit 6688220cb2
7 changed files with 98 additions and 48 deletions

View File

@ -128,13 +128,10 @@ public class QuotaBalanceCmd extends BaseCmd {
QuotaBalanceResponse response;
if (getEndDate() == null) {
response = _quotaDBUtils.createQuotaLastBalanceResponse(quotaUsage);
response = _quotaDBUtils.createQuotaLastBalanceResponse(quotaUsage, startDate);
} else {
response = _quotaDBUtils.createQuotaBalanceResponse(quotaUsage);
response.setEndDate(endDate);
response = _quotaDBUtils.createQuotaBalanceResponse(quotaUsage, startDate, endDate);
}
response.setStartDate(startDate);
response.setResponseName(getCommandName());
setResponseObject(response);
}

View File

@ -40,13 +40,13 @@ public interface QuotaDBUtils {
QuotaStatementResponse createQuotaStatementResponse(List<QuotaUsageVO> quotaUsage);
QuotaBalanceResponse createQuotaBalanceResponse(List<QuotaBalanceVO> quotaUsage);
QuotaBalanceResponse createQuotaBalanceResponse(List<QuotaBalanceVO> quotaUsage, Date startDate, Date endDate);
Pair<List<? extends UsageVO>, Integer> getUsageRecords(long accountId, long domainId);
ServiceOfferingVO findServiceOffering(Long vmId, long serviceOfferingId);
QuotaBalanceResponse createQuotaLastBalanceResponse(List<QuotaBalanceVO> quotaBalance);
QuotaBalanceResponse createQuotaLastBalanceResponse(List<QuotaBalanceVO> quotaBalance, Date startDate);
QuotaCreditsResponse addQuotaCredits(Long accountId, Long domainId, Double amount, Long updatedBy, Date despositedOn);

View File

@ -83,7 +83,7 @@ public class QuotaDBUtilsImpl implements QuotaDBUtils {
}
@Override
public QuotaBalanceResponse createQuotaLastBalanceResponse(List<QuotaBalanceVO> quotaBalance) {
public QuotaBalanceResponse createQuotaLastBalanceResponse(List<QuotaBalanceVO> quotaBalance, Date startDate) {
if (quotaBalance.size() == 0) {
new InvalidParameterValueException("There are no balance entries on or before the requested date.");
}
@ -101,17 +101,17 @@ public class QuotaDBUtilsImpl implements QuotaDBUtils {
lastCredits=lastCredits.add(entry.getCreditBalance());
}
else {
resp.setStartDate(entry.getUpdatedOn());
resp.setStartQuota(entry.getCreditBalance().add(lastCredits));
break; // add only consecutive credit entries
}
}
resp.setStartDate(startDate);
resp.setObjectName("balance");
return resp;
}
@Override
public QuotaBalanceResponse createQuotaBalanceResponse(List<QuotaBalanceVO> quotaBalance) {
public QuotaBalanceResponse createQuotaBalanceResponse(List<QuotaBalanceVO> quotaBalance, Date startDate, Date endDate) {
if (quotaBalance.size() == 0) {
new InvalidParameterValueException("The request period does not contain balance entries.");
}
@ -133,9 +133,9 @@ public class QuotaDBUtilsImpl implements QuotaDBUtils {
if (quotaBalance.size() > 0) {
QuotaBalanceVO startItem = quotaBalance.get(0);
QuotaBalanceVO endItem = quotaBalance.get(quotaBalance.size() - 1);
resp.setStartDate(startItem.getUpdatedOn());
resp.setStartDate(startDate);
resp.setStartQuota(startItem.getCreditBalance());
resp.setEndDate(endItem.getUpdatedOn());
resp.setEndDate(endDate);
resp.setEndQuota(endItem.getCreditBalance());
} else {
resp.setStartQuota(new BigDecimal(0));

View File

@ -154,34 +154,36 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
} while ((usageRecords != null) && !usageRecords.first().isEmpty());
// list of quotas for this account
s_logger.info("Quota entries size = " + quotalistforaccount.size());
quotalistforaccount.add(new QuotaUsageVO());
Date startDate = new Date(0);
Date endDate = new Date(0);
BigDecimal aggrUsage = new BigDecimal(0);
for (QuotaUsageVO entry : quotalistforaccount) {
if (startDate.compareTo(entry.getStartDate()) != 0) {
QuotaBalanceVO lastrealbalanceentry = _quotaBalanceDao.findLastBalanceEntry(account.getAccountId(), account.getDomainId(), startDate);
Date lastbalancedate;
if (lastrealbalanceentry != null) {
lastbalancedate = lastrealbalanceentry.getUpdatedOn();
aggrUsage = aggrUsage.add(lastrealbalanceentry.getCreditBalance());
} else {
lastbalancedate = new Date(0);
}
if (quotalistforaccount.size() > 0) { // balance to be processed
quotalistforaccount.add(new QuotaUsageVO());
Date startDate = new Date(0);
Date endDate = new Date(0);
BigDecimal aggrUsage = new BigDecimal(0);
for (QuotaUsageVO entry : quotalistforaccount) {
if (startDate.compareTo(entry.getStartDate()) != 0) {
QuotaBalanceVO lastrealbalanceentry = _quotaBalanceDao.findLastBalanceEntry(account.getAccountId(), account.getDomainId(), startDate);
Date lastbalancedate;
if (lastrealbalanceentry != null) {
lastbalancedate = lastrealbalanceentry.getUpdatedOn();
aggrUsage = aggrUsage.add(lastrealbalanceentry.getCreditBalance());
} else {
lastbalancedate = new Date(0);
}
List<QuotaBalanceVO> creditsrcvd = _quotaBalanceDao.findCreditBalance(account.getAccountId(), account.getDomainId(), lastbalancedate, endDate);
for (QuotaBalanceVO credit : creditsrcvd) {
aggrUsage = aggrUsage.add(credit.getCreditBalance());
}
List<QuotaBalanceVO> creditsrcvd = _quotaBalanceDao.findCreditBalance(account.getAccountId(), account.getDomainId(), lastbalancedate, endDate);
for (QuotaBalanceVO credit : creditsrcvd) {
aggrUsage = aggrUsage.add(credit.getCreditBalance());
}
QuotaBalanceVO newbalance = new QuotaBalanceVO(account.getAccountId(), account.getDomainId(), aggrUsage, endDate);
_quotaBalanceDao.persist(newbalance);
aggrUsage = new BigDecimal(0);
QuotaBalanceVO newbalance = new QuotaBalanceVO(account.getAccountId(), account.getDomainId(), aggrUsage, endDate);
_quotaBalanceDao.persist(newbalance);
aggrUsage = new BigDecimal(0);
}
startDate = entry.getStartDate();
endDate = entry.getEndDate();
aggrUsage = aggrUsage.subtract(entry.getQuotaUsed());
}
startDate = entry.getStartDate();
endDate = entry.getEndDate();
aggrUsage = aggrUsage.subtract(entry.getQuotaUsed());
}
}// balance processed
} // END ACCOUNT
jobResult = true;
} catch (Exception e) {

View File

@ -168,12 +168,26 @@ public class QuotaServiceImpl extends ManagerBase implements QuotaService, Confi
Date adjustedStartDate = computeAdjustedTime(startDate, usageTZ);
if (endDate == null) {
s_logger.debug("getting quota balance records for account: " + accountId + ", domainId: " + domainId + ", on or before " + adjustedStartDate);
return _quotaBalanceDao.findQuotaBalance(accountId, domainId, adjustedStartDate);
s_logger.debug("Getting quota balance records for account: " + accountId + ", domainId: " + domainId + ", on or before " + adjustedStartDate);
List<QuotaBalanceVO> qbrecords = _quotaBalanceDao.findQuotaBalance(accountId, domainId, adjustedStartDate);
s_logger.info("Found records size=" + qbrecords.size());
if (qbrecords.size() == 0){
throw new InvalidParameterValueException("Incorrect Date there are no quota records before this date " + adjustedStartDate);
}
else {
return qbrecords;
}
} else if (startDate.before(endDate)) {
Date adjustedEndDate = computeAdjustedTime(endDate, usageTZ);
s_logger.debug("getting quota balance records for account: " + accountId + ", domainId: " + domainId + ", between " + adjustedStartDate + " and " + adjustedEndDate);
return _quotaBalanceDao.findQuotaBalance(accountId, domainId, adjustedStartDate, adjustedEndDate);
s_logger.debug("Getting quota balance records for account: " + accountId + ", domainId: " + domainId + ", between " + adjustedStartDate + " and " + adjustedEndDate);
List<QuotaBalanceVO> qbrecords = _quotaBalanceDao.findQuotaBalance(accountId, domainId, adjustedStartDate, adjustedEndDate);
s_logger.info("Found records size=" + qbrecords.size());
if (qbrecords.size() == 0){
throw new InvalidParameterValueException("Incorrect Date range there are no quota records between these dates start date " + adjustedStartDate + " and end date:" + endDate);
}
else {
return qbrecords;
}
} else {
throw new InvalidParameterValueException("Incorrect Date Range. Start date: " + startDate + " is after end date:" + endDate);
}

View File

@ -18,12 +18,14 @@ package org.apache.cloudstack.quota.dao;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import javax.ejb.Local;
import org.springframework.stereotype.Component;
import org.apache.cloudstack.quota.QuotaBalanceVO;
import org.apache.log4j.Logger;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDaoBase;
@ -33,6 +35,7 @@ import com.cloud.utils.db.TransactionLegacy;
@Component
@Local(value = { QuotaBalanceDao.class })
public class QuotaBalanceDaoImpl extends GenericDaoBase<QuotaBalanceVO, Long> implements QuotaBalanceDao {
private static final Logger s_logger = Logger.getLogger(QuotaBalanceDaoImpl.class.getName());
@SuppressWarnings("deprecation")
@Override
@ -121,6 +124,21 @@ public class QuotaBalanceDaoImpl extends GenericDaoBase<QuotaBalanceVO, Long> im
return new ArrayList<QuotaBalanceVO>();
}
quotaUsageRecords = listBy(sc);
// get records before startDate to find start balance
List<QuotaBalanceVO> quotaUsageOnOrBeforeStartDate = findQuotaBalance(accountId, domainId, startDate);
for (Iterator<QuotaBalanceVO> it = quotaUsageOnOrBeforeStartDate.iterator(); it.hasNext();) {
QuotaBalanceVO entry = it.next();
s_logger.info("Date=" + entry.getUpdatedOn().toGMTString() + " balance=" + entry.getCreditBalance() + " credit=" + entry.getCreditsId());
if (entry.getCreditsId() > 0) {
quotaUsageRecords.add(entry);
} else {
quotaUsageRecords.add(entry);
break; // add only consecutive credit entries and last
// balance entry
}
}
} finally {
txn.close();
}
@ -136,6 +154,7 @@ public class QuotaBalanceDaoImpl extends GenericDaoBase<QuotaBalanceVO, Long> im
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
List<QuotaBalanceVO> quotaUsageRecords = null;
List<QuotaBalanceVO> trimmedRecords = new ArrayList<QuotaBalanceVO>();
try {
Filter filter = new Filter(QuotaBalanceVO.class, "updatedOn", false, 0L, 100L);
// ASSUMPTION there will be less than 100 continuous credit
@ -151,12 +170,26 @@ public class QuotaBalanceDaoImpl extends GenericDaoBase<QuotaBalanceVO, Long> im
sc.addAnd("updatedOn", SearchCriteria.Op.LTEQ, startDate);
}
quotaUsageRecords = search(sc, filter);
// get records before startDate to find start balance
for (Iterator<QuotaBalanceVO> it = quotaUsageRecords.iterator(); it.hasNext();) {
QuotaBalanceVO entry = it.next();
s_logger.info("Date=" + entry.getUpdatedOn().toGMTString() + " balance=" + entry.getCreditBalance() + " credit=" + entry.getCreditsId());
if (entry.getCreditsId() > 0) {
trimmedRecords.add(entry);
} else {
trimmedRecords.add(entry);
break; // add only consecutive credit entries and last
// balance entry
}
}
} finally {
txn.close();
}
TransactionLegacy.open(opendb).close();
return quotaUsageRecords;
return trimmedRecords;
}
}

View File

@ -45,6 +45,7 @@ public class QuotaTariffDaoImpl extends GenericDaoBase<QuotaTariffVO, Long> impl
@Override
public QuotaTariffVO findTariffPlanByUsageType(final int usageType) {
short opendb = TransactionLegacy.currentTxn().getDatabaseId();
QuotaTariffVO result = null;
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
try {
@ -53,14 +54,15 @@ public class QuotaTariffDaoImpl extends GenericDaoBase<QuotaTariffVO, Long> impl
result = findOneBy(sc);
} finally {
txn.close();
// Switch back to Cloud DB
TransactionLegacy.open(TransactionLegacy.CLOUD_DB).close();
// Switch back
TransactionLegacy.open(opendb).close();
}
return result;
}
@Override
public List<QuotaTariffVO> listAllTariffPlans() {
short opendb = TransactionLegacy.currentTxn().getDatabaseId();
List<QuotaTariffVO> result = null;
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
try {
@ -69,17 +71,19 @@ public class QuotaTariffDaoImpl extends GenericDaoBase<QuotaTariffVO, Long> impl
result = listBy(sc);
} finally {
txn.close();
// Switch back to Cloud DB
TransactionLegacy.open(TransactionLegacy.CLOUD_DB).close();
// Switch back
TransactionLegacy.open(opendb).close();
}
return result;
}
@Override
public boolean updateQuotaTariff(QuotaTariffVO plan) {
TransactionLegacy.open(TransactionLegacy.USAGE_DB).close(); // Switch to Usage DB
short opendb = TransactionLegacy.currentTxn().getDatabaseId();
TransactionLegacy.open(TransactionLegacy.USAGE_DB).close(); // Switch to
// Usage DB
boolean result = this.update(plan.getId(), plan);
TransactionLegacy.open(TransactionLegacy.CLOUD_DB).close(); // Switch back to Cloud DB
TransactionLegacy.open(opendb).close(); // Switch back
return result;
}
}