use of org.mobicents.charging.server.account.CreditControlUnit in project charging-server by RestComm.
the class DiameterChargingServerSbb method collectUsedUnits.
private ArrayList<CreditControlUnit> collectUsedUnits(UsedServiceUnitAvp[] usuAvps, ArrayList<CreditControlUnit> reservedCCUnits) {
if (tracer.isInfoEnabled()) {
tracer.info("[><] " + sidString + " Collecting " + usuAvps.length + " Used Units AVPs.");
}
ArrayList<CreditControlUnit> usedCCUnits = new ArrayList<CreditControlUnit>();
for (UsedServiceUnitAvp usuAvp : usuAvps) {
for (int n = 0; n < CcUnitType.values().length; n++) {
CcUnitType type = CcUnitType.fromInt(n);
// MONEY is not supported by 3GPP
if (type == CcUnitType.MONEY) {
continue;
}
String methodName = "getCreditControl" + toCamelCase(type.toString());
try {
Method m = usuAvp.getClass().getMethod(methodName);
long value = (Long) m.invoke(usuAvp);
if (value == Long.MIN_VALUE) {
// It means the AVP was not present.. no null or NoSuchAvpException :(
continue;
}
if (tracer.isInfoEnabled()) {
tracer.info("[><] " + sidString + " Got " + value + " Used Units of type '" + type.toString() + "' ");
}
CreditControlUnit ccUnit = new CreditControlUnit();
ccUnit.setUnitType(type);
ccUnit.setUsedUnits(ccUnit.getUsedUnits() + value);
// If we can find Reserved Units and Rate Information, let's fill with it
for (CreditControlUnit reservedCCUnit : reservedCCUnits) {
if (reservedCCUnit.getUnitType() == type) {
// Copy the reserved amount from the last session into this session so that ABMF can update used units.
ccUnit.setReservedUnits(reservedCCUnit.getReservedUnits());
ccUnit.setReservedAmount(reservedCCUnit.getReservedAmount());
ccUnit.setUsedAmount((long) Math.ceil(reservedCCUnit.getRateForService() * ccUnit.getUsedUnits()));
ccUnit.setRateForService(reservedCCUnit.getRateForService());
}
}
usedCCUnits.add(ccUnit);
} catch (Exception e) {
tracer.severe("[xx] " + sidString + " Unable to retrieve/invoke '" + methodName + "' for extracting Used Units of type " + type, e);
}
}
}
return usedCCUnits;
}
use of org.mobicents.charging.server.account.CreditControlUnit in project charging-server by RestComm.
the class ReserveUnitsJdbcTask method executeSimple.
@Override
public Object executeSimple(JdbcTaskContext taskContext) {
try {
long balance = 0;
// get Balance Before (can this be made more efficient?)
PreparedStatement preparedStatement = taskContext.getConnection().prepareStatement(DataSourceSchemaInfo._QUERY_SELECT);
preparedStatement.setString(1, msisdn);
preparedStatement.execute();
ResultSet resultSet = preparedStatement.getResultSet();
while (resultSet.next()) {
balance = resultSet.getLong(DataSourceSchemaInfo._COL_BALANCE);
ccInfo.setBalanceBefore(balance);
}
for (int i = 0; i < ccUnits.size(); i++) {
CreditControlUnit ccUnit = ccUnits.get(i);
if (balance <= 0 && ccUnit.getRateForService() > 0) {
accountData = new UserAccountData();
accountData.setMsisdn(msisdn);
accountData.setBalance(0);
accountData.setFailure(true);
ccUnit.setReservedUnits(0);
ccUnit.setReservedAmount(0);
if (tracer.isInfoEnabled()) {
tracer.info("[//] User does not have sufficient balance for reservation. Balance available: " + balance + ".");
}
break;
} else {
long reservedAmount = ccUnit.getReservedAmount();
long usedAmount = ccUnit.getUsedAmount();
long requestedAmount = ccUnit.getRequestedAmount();
long requestedUnits = ccUnit.getRequestedUnits();
if (ccUnit.getRateForService() > 0) {
// If RSU < balance, reserve and set GSU=balance
if ((reservedAmount - usedAmount + requestedAmount) > balance) {
long newRequestedAmount = balance;
long newRequestedUnits = (long) Math.floor(newRequestedAmount / ccUnit.getRateForService());
if (tracer.isInfoEnabled()) {
tracer.info("[//] User does not have sufficient balance for the entire reservation request (" + requestedUnits + " " + ccUnit.getUnitType() + " units @rate=" + ccUnit.getRateForService() + "). Balance available: " + balance + ". Reserving " + newRequestedUnits + " units instead ...");
}
requestedAmount = newRequestedAmount;
requestedUnits = newRequestedUnits;
// TODO: Need to set Final Unit Indication for this case.
// See http://www.ietf.org/rfc/rfc4006.txt, 8.34. Final-Unit-Indication AVP
}
}
int n = 1;
tracer.info(("[//] Executing DB Statement '" + DataSourceSchemaInfo._QUERY_RESERVE).replaceFirst("\\?", String.valueOf(reservedAmount - usedAmount)).replaceFirst("\\?", String.valueOf(requestedAmount)).replaceFirst("\\?", String.valueOf(requestedAmount)).replaceFirst("\\?", msisdn));
preparedStatement = taskContext.getConnection().prepareStatement(DataSourceSchemaInfo._QUERY_RESERVE);
preparedStatement.setLong(n++, (reservedAmount - usedAmount));
preparedStatement.setLong(n++, requestedAmount);
preparedStatement.setLong(n++, requestedAmount);
preparedStatement.setString(n++, msisdn);
accountData = new UserAccountData();
accountData.setMsisdn(msisdn);
if (preparedStatement.executeUpdate() == 1) {
// ok great, we have successfully reserved the units
preparedStatement = taskContext.getConnection().prepareStatement(DataSourceSchemaInfo._QUERY_SELECT);
preparedStatement.setString(1, msisdn);
// tracer.info(("[//] Executing DB Statement '" + DataSourceSchemaInfo._QUERY_SELECT).replaceFirst("\\?", msisdn));
preparedStatement.execute();
resultSet = preparedStatement.getResultSet();
while (resultSet.next()) {
balance = resultSet.getLong(DataSourceSchemaInfo._COL_BALANCE);
accountData.setBalance(balance);
accountData.setFailure(false);
ccUnit.setReservedUnits(requestedUnits);
ccUnit.setReservedAmount(requestedAmount);
ccInfo.setBalanceAfter(balance);
}
} else {
// check what kind of error happened
accountData.setBalance(0);
accountData.setFailure(true);
ccUnit.setReservedUnits(0);
ccUnit.setReservedAmount(0);
}
}
}
} catch (Exception e) {
tracer.severe("[xx] Failed to execute task to Reserve Units for MSISDN '" + msisdn + "'", e);
}
return this;
}
Aggregations