|
18 | 18 |
|
19 | 19 | import java.math.BigDecimal; |
20 | 20 | import java.util.ArrayList; |
21 | | -import java.util.Collections; |
22 | 21 | import java.util.Date; |
23 | 22 | import java.util.List; |
24 | 23 |
|
25 | 24 | import org.apache.cloudstack.quota.vo.QuotaBalanceVO; |
| 25 | +import org.apache.commons.lang3.ObjectUtils; |
| 26 | +import org.apache.commons.lang3.time.DateUtils; |
| 27 | +import org.apache.logging.log4j.LogManager; |
| 28 | +import org.apache.logging.log4j.Logger; |
26 | 29 | import org.springframework.stereotype.Component; |
27 | 30 |
|
28 | 31 | import com.cloud.utils.db.Filter; |
|
32 | 35 | import com.cloud.utils.db.Transaction; |
33 | 36 | import com.cloud.utils.db.TransactionCallback; |
34 | 37 | import com.cloud.utils.db.TransactionLegacy; |
35 | | -import com.cloud.utils.db.TransactionStatus; |
36 | 38 |
|
37 | 39 | @Component |
38 | 40 | public class QuotaBalanceDaoImpl extends GenericDaoBase<QuotaBalanceVO, Long> implements QuotaBalanceDao { |
| 41 | + private static final Logger logger = LogManager.getLogger(QuotaBalanceDaoImpl.class); |
39 | 42 |
|
40 | 43 | @Override |
41 | | - public QuotaBalanceVO findLastBalanceEntry(final Long accountId, final Long domainId, final Date beforeThis) { |
42 | | - return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<QuotaBalanceVO>() { |
43 | | - @Override |
44 | | - public QuotaBalanceVO doInTransaction(final TransactionStatus status) { |
45 | | - List<QuotaBalanceVO> quotaBalanceEntries = new ArrayList<>(); |
46 | | - Filter filter = new Filter(QuotaBalanceVO.class, "updatedOn", false, 0L, 1L); |
47 | | - QueryBuilder<QuotaBalanceVO> qb = QueryBuilder.create(QuotaBalanceVO.class); |
48 | | - qb.and(qb.entity().getAccountId(), SearchCriteria.Op.EQ, accountId); |
49 | | - qb.and(qb.entity().getDomainId(), SearchCriteria.Op.EQ, domainId); |
50 | | - qb.and(qb.entity().getCreditsId(), SearchCriteria.Op.EQ, 0); |
| 44 | + public QuotaBalanceVO getLastQuotaBalanceEntry(final Long accountId, final Long domainId, final Date beforeThis) { |
| 45 | + return Transaction.execute(TransactionLegacy.USAGE_DB, (TransactionCallback<QuotaBalanceVO>) status -> { |
| 46 | + Filter filter = new Filter(QuotaBalanceVO.class, "updatedOn", false, 0L, 1L); |
| 47 | + QueryBuilder<QuotaBalanceVO> qb = getQuotaBalanceQueryBuilder(accountId, domainId); |
| 48 | + qb.and(qb.entity().getCreditsId(), SearchCriteria.Op.EQ, 0); |
| 49 | + |
| 50 | + if (beforeThis != null) { |
51 | 51 | qb.and(qb.entity().getUpdatedOn(), SearchCriteria.Op.LT, beforeThis); |
52 | | - quotaBalanceEntries = search(qb.create(), filter); |
53 | | - return !quotaBalanceEntries.isEmpty() ? quotaBalanceEntries.get(0) : null; |
54 | 52 | } |
| 53 | + |
| 54 | + List<QuotaBalanceVO> quotaBalanceEntries = search(qb.create(), filter); |
| 55 | + return !quotaBalanceEntries.isEmpty() ? quotaBalanceEntries.get(0) : null; |
55 | 56 | }); |
56 | 57 | } |
57 | 58 |
|
58 | 59 | @Override |
59 | 60 | public QuotaBalanceVO findLaterBalanceEntry(final Long accountId, final Long domainId, final Date afterThis) { |
60 | | - return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<QuotaBalanceVO>() { |
61 | | - @Override |
62 | | - public QuotaBalanceVO doInTransaction(final TransactionStatus status) { |
63 | | - List<QuotaBalanceVO> quotaBalanceEntries = new ArrayList<>(); |
64 | | - Filter filter = new Filter(QuotaBalanceVO.class, "updatedOn", true, 0L, 1L); |
65 | | - QueryBuilder<QuotaBalanceVO> qb = QueryBuilder.create(QuotaBalanceVO.class); |
66 | | - qb.and(qb.entity().getAccountId(), SearchCriteria.Op.EQ, accountId); |
67 | | - qb.and(qb.entity().getDomainId(), SearchCriteria.Op.EQ, domainId); |
68 | | - qb.and(qb.entity().getCreditsId(), SearchCriteria.Op.EQ, 0); |
69 | | - qb.and(qb.entity().getUpdatedOn(), SearchCriteria.Op.GT, afterThis); |
70 | | - quotaBalanceEntries = search(qb.create(), filter); |
71 | | - return quotaBalanceEntries.size() > 0 ? quotaBalanceEntries.get(0) : null; |
72 | | - } |
| 61 | + return Transaction.execute(TransactionLegacy.USAGE_DB, (TransactionCallback<QuotaBalanceVO>) status -> { |
| 62 | + Filter filter = new Filter(QuotaBalanceVO.class, "updatedOn", true, 0L, 1L); |
| 63 | + QueryBuilder<QuotaBalanceVO> qb = getQuotaBalanceQueryBuilder(accountId, domainId); |
| 64 | + qb.and(qb.entity().getCreditsId(), SearchCriteria.Op.EQ, 0); |
| 65 | + qb.and(qb.entity().getUpdatedOn(), SearchCriteria.Op.GT, afterThis); |
| 66 | + |
| 67 | + List<QuotaBalanceVO> quotaBalanceEntries = search(qb.create(), filter); |
| 68 | + return !quotaBalanceEntries.isEmpty() ? quotaBalanceEntries.get(0) : null; |
73 | 69 | }); |
74 | 70 | } |
75 | 71 |
|
76 | 72 | @Override |
77 | 73 | public QuotaBalanceVO saveQuotaBalance(final QuotaBalanceVO qb) { |
78 | | - return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<QuotaBalanceVO>() { |
79 | | - @Override |
80 | | - public QuotaBalanceVO doInTransaction(final TransactionStatus status) { |
81 | | - return persist(qb); |
82 | | - } |
83 | | - }); |
| 74 | + return Transaction.execute(TransactionLegacy.USAGE_DB, (TransactionCallback<QuotaBalanceVO>) status -> persist(qb)); |
84 | 75 | } |
85 | 76 |
|
86 | 77 | @Override |
87 | | - public List<QuotaBalanceVO> findCreditBalance(final Long accountId, final Long domainId, final Date lastbalancedate, final Date beforeThis) { |
88 | | - return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<List<QuotaBalanceVO>>() { |
89 | | - @Override |
90 | | - public List<QuotaBalanceVO> doInTransaction(final TransactionStatus status) { |
91 | | - if ((lastbalancedate != null) && (beforeThis != null) && lastbalancedate.before(beforeThis)) { |
92 | | - Filter filter = new Filter(QuotaBalanceVO.class, "updatedOn", true, 0L, Long.MAX_VALUE); |
93 | | - QueryBuilder<QuotaBalanceVO> qb = QueryBuilder.create(QuotaBalanceVO.class); |
94 | | - qb.and(qb.entity().getAccountId(), SearchCriteria.Op.EQ, accountId); |
95 | | - qb.and(qb.entity().getDomainId(), SearchCriteria.Op.EQ, domainId); |
96 | | - qb.and(qb.entity().getCreditsId(), SearchCriteria.Op.GT, 0); |
97 | | - qb.and(qb.entity().getUpdatedOn(), SearchCriteria.Op.BETWEEN, lastbalancedate, beforeThis); |
98 | | - return search(qb.create(), filter); |
99 | | - } else { |
100 | | - return new ArrayList<QuotaBalanceVO>(); |
101 | | - } |
| 78 | + public List<QuotaBalanceVO> findCreditBalances(final Long accountId, final Long domainId, final Date startDate, final Date endDate) { |
| 79 | + return Transaction.execute(TransactionLegacy.USAGE_DB, (TransactionCallback<List<QuotaBalanceVO>>) status -> { |
| 80 | + if (ObjectUtils.anyNull(startDate, endDate) || startDate.after(endDate)) { |
| 81 | + return new ArrayList<>(); |
102 | 82 | } |
103 | | - }); |
104 | | - } |
105 | 83 |
|
106 | | - @Override |
107 | | - public List<QuotaBalanceVO> findQuotaBalance(final Long accountId, final Long domainId, final Date startDate, final Date endDate) { |
108 | | - return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<List<QuotaBalanceVO>>() { |
109 | | - @Override |
110 | | - public List<QuotaBalanceVO> doInTransaction(final TransactionStatus status) { |
111 | | - List<QuotaBalanceVO> quotaUsageRecords = null; |
112 | | - QueryBuilder<QuotaBalanceVO> qb = QueryBuilder.create(QuotaBalanceVO.class); |
113 | | - if (accountId != null) { |
114 | | - qb.and(qb.entity().getAccountId(), SearchCriteria.Op.EQ, accountId); |
115 | | - } |
116 | | - if (domainId != null) { |
117 | | - qb.and(qb.entity().getDomainId(), SearchCriteria.Op.EQ, domainId); |
118 | | - } |
119 | | - if ((startDate != null) && (endDate != null) && startDate.before(endDate)) { |
120 | | - qb.and(qb.entity().getUpdatedOn(), SearchCriteria.Op.BETWEEN, startDate, endDate); |
121 | | - } else { |
122 | | - return Collections.<QuotaBalanceVO> emptyList(); |
123 | | - } |
124 | | - quotaUsageRecords = listBy(qb.create()); |
125 | | - if (quotaUsageRecords.size() == 0) { |
126 | | - quotaUsageRecords.addAll(lastQuotaBalanceVO(accountId, domainId, startDate)); |
127 | | - } |
128 | | - return quotaUsageRecords; |
| 84 | + Filter filter = new Filter(QuotaBalanceVO.class, "updatedOn", true, 0L, Long.MAX_VALUE); |
| 85 | + QueryBuilder<QuotaBalanceVO> qb = getQuotaBalanceQueryBuilder(accountId, domainId); |
| 86 | + qb.and(qb.entity().getCreditsId(), SearchCriteria.Op.GT, 0); |
| 87 | + qb.and(qb.entity().getUpdatedOn(), SearchCriteria.Op.BETWEEN, startDate, endDate); |
129 | 88 |
|
130 | | - } |
| 89 | + return search(qb.create(), filter); |
131 | 90 | }); |
132 | | - |
133 | 91 | } |
134 | 92 |
|
135 | 93 | @Override |
136 | | - public List<QuotaBalanceVO> lastQuotaBalanceVO(final Long accountId, final Long domainId, final Date pivotDate) { |
137 | | - return Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallback<List<QuotaBalanceVO>>() { |
138 | | - @Override |
139 | | - public List<QuotaBalanceVO> doInTransaction(final TransactionStatus status) { |
140 | | - List<QuotaBalanceVO> quotaUsageRecords = null; |
141 | | - List<QuotaBalanceVO> trimmedRecords = new ArrayList<QuotaBalanceVO>(); |
142 | | - Filter filter = new Filter(QuotaBalanceVO.class, "updatedOn", false, 0L, 100L); |
143 | | - // ASSUMPTION there will be less than 100 continuous credit |
144 | | - // transactions |
145 | | - QueryBuilder<QuotaBalanceVO> qb = QueryBuilder.create(QuotaBalanceVO.class); |
146 | | - if (accountId != null) { |
147 | | - qb.and(qb.entity().getAccountId(), SearchCriteria.Op.EQ, accountId); |
148 | | - } |
149 | | - if (domainId != null) { |
150 | | - qb.and(qb.entity().getDomainId(), SearchCriteria.Op.EQ, domainId); |
151 | | - } |
152 | | - if ((pivotDate != null)) { |
153 | | - qb.and(qb.entity().getUpdatedOn(), SearchCriteria.Op.LTEQ, pivotDate); |
154 | | - } |
155 | | - quotaUsageRecords = search(qb.create(), filter); |
156 | | - |
157 | | - // get records before startDate to find start balance |
158 | | - for (QuotaBalanceVO entry : quotaUsageRecords) { |
159 | | - if (logger.isDebugEnabled()) { |
160 | | - logger.debug("FindQuotaBalance Entry=" + entry); |
161 | | - } |
162 | | - if (entry.getCreditsId() > 0) { |
163 | | - trimmedRecords.add(entry); |
164 | | - } else { |
165 | | - trimmedRecords.add(entry); |
166 | | - break; // add only consecutive credit entries and last balance entry |
167 | | - } |
168 | | - } |
169 | | - return trimmedRecords; |
| 94 | + public List<QuotaBalanceVO> listQuotaBalances(final Long accountId, final Long domainId, final Date startDate, final Date endDate) { |
| 95 | + return Transaction.execute(TransactionLegacy.USAGE_DB, (TransactionCallback<List<QuotaBalanceVO>>) status -> { |
| 96 | + QueryBuilder<QuotaBalanceVO> qb = getQuotaBalanceQueryBuilder(accountId, domainId); |
| 97 | + qb.and(qb.entity().getCreditsId(), SearchCriteria.Op.EQ, 0); |
| 98 | + if (startDate != null) { |
| 99 | + qb.and(qb.entity().getUpdatedOn(), SearchCriteria.Op.GTEQ, startDate); |
| 100 | + } |
| 101 | + if (endDate != null) { |
| 102 | + qb.and(qb.entity().getUpdatedOn(), SearchCriteria.Op.LTEQ, endDate); |
170 | 103 | } |
| 104 | + |
| 105 | + Filter filter = new Filter(QuotaBalanceVO.class, "updatedOn", true); |
| 106 | + return listBy(qb.create(), filter); |
171 | 107 | }); |
172 | 108 | } |
173 | 109 |
|
174 | 110 | @Override |
175 | | - public BigDecimal lastQuotaBalance(final Long accountId, final Long domainId, Date startDate) { |
176 | | - List<QuotaBalanceVO> quotaBalance = lastQuotaBalanceVO(accountId, domainId, startDate); |
177 | | - BigDecimal finalBalance = new BigDecimal(0); |
178 | | - if (quotaBalance.isEmpty()) { |
179 | | - logger.info("There are no balance entries on or before the requested date."); |
180 | | - return finalBalance; |
| 111 | + public BigDecimal getLastQuotaBalance(final Long accountId, final Long domainId) { |
| 112 | + QuotaBalanceVO quotaBalance = getLastQuotaBalanceEntry(accountId, domainId, null); |
| 113 | + BigDecimal finalBalance = BigDecimal.ZERO; |
| 114 | + Date startDate = DateUtils.addDays(new Date(), -1); |
| 115 | + if (quotaBalance == null) { |
| 116 | + logger.info("There are no balance entries for account [{}] and domain [{}]. Considering only new added credits.", accountId, domainId); |
| 117 | + } else { |
| 118 | + finalBalance = quotaBalance.getCreditBalance(); |
| 119 | + startDate = quotaBalance.getUpdatedOn(); |
181 | 120 | } |
182 | | - for (QuotaBalanceVO entry : quotaBalance) { |
183 | | - if (logger.isDebugEnabled()) { |
184 | | - logger.debug("lastQuotaBalance Entry=" + entry); |
185 | | - } |
186 | | - finalBalance = finalBalance.add(entry.getCreditBalance()); |
| 121 | + |
| 122 | + List<QuotaBalanceVO> credits = findCreditBalances(accountId, domainId, startDate, new Date()); |
| 123 | + |
| 124 | + for (QuotaBalanceVO credit : credits) { |
| 125 | + finalBalance = finalBalance.add(credit.getCreditBalance()); |
187 | 126 | } |
| 127 | + |
188 | 128 | return finalBalance; |
189 | 129 | } |
190 | 130 |
|
| 131 | + private QueryBuilder<QuotaBalanceVO> getQuotaBalanceQueryBuilder(Long accountId, Long domainId) { |
| 132 | + QueryBuilder<QuotaBalanceVO> qb = QueryBuilder.create(QuotaBalanceVO.class); |
| 133 | + qb.and(qb.entity().getAccountId(), SearchCriteria.Op.EQ, accountId); |
| 134 | + qb.and(qb.entity().getDomainId(), SearchCriteria.Op.EQ, domainId); |
| 135 | + return qb; |
| 136 | + } |
| 137 | + |
191 | 138 | } |
0 commit comments