import gr.grnet.aquarium.util.shortClassNameOf
import algorithm.CostPolicyAlgorithmCompiler
import dsl._
-import gr.grnet.aquarium.logic.events.{WalletEntry, ResourceEvent}
import collection.immutable.SortedMap
import java.util.Date
import com.ckkloverdos.maybe.{NoVal, Maybe, Failed, Just}
-import gr.grnet.aquarium.util.date.MutableDateCalc
import gr.grnet.aquarium.util.{ContextualLogger, CryptoUtils, Loggable}
import gr.grnet.aquarium.store.PolicyStore
+import gr.grnet.aquarium.event.{WalletEntry}
+import gr.grnet.aquarium.util.date.{TimeHelpers, MutableDateCalc}
+import gr.grnet.aquarium.event.resource.ResourceEventModel
+import gr.grnet.aquarium.{AquariumInternalError, AquariumException}
/**
* A timeslot together with the algorithm and unit price that apply for this particular timeslot.
protected
def resolveEffectiveAlgorithmsAndPriceLists(alignedTimeslot: Timeslot,
agreement: DSLAgreement,
- clogM: Maybe[ContextualLogger] = NoVal): (Map[Timeslot, DSLAlgorithm], Map[Timeslot, DSLPriceList]) = {
+ clogOpt: Option[ContextualLogger] = None):
+ (Map[Timeslot, DSLAlgorithm], Map[Timeslot, DSLPriceList]) = {
- val clog = ContextualLogger.fromOther(clogM, logger, "resolveEffectiveAlgorithmsAndPriceLists()")
+ val clog = ContextualLogger.fromOther(clogOpt, logger, "resolveEffectiveAlgorithmsAndPriceLists()")
// Note that most of the code is taken from calcChangeChunks()
val alg = resolveEffectiveAlgorithmsForTimeslot(alignedTimeslot, agreement)
dslResource: DSLResource,
policiesByTimeslot: Map[Timeslot, DSLPolicy],
agreementNamesByTimeslot: Map[Timeslot, String],
- contextualLogger: Maybe[ContextualLogger] = NoVal): Maybe[List[Chargeslot]] = Maybe {
+ clogOpt: Option[ContextualLogger] = None): List[Chargeslot] = {
- val clog = ContextualLogger.fromOther(contextualLogger, logger, "computeInitialChargeslots()")
+ val clog = ContextualLogger.fromOther(clogOpt, logger, "computeInitialChargeslots()")
// clog.begin()
val policyTimeslots = policiesByTimeslot.keySet
case None ⇒
val errMsg = "Unknown agreement %s during %s".format(agreementName, alignedTimeslot)
clog.error("%s", errMsg)
- throw new Exception(errMsg)
+ throw new AquariumException(errMsg)
case Some(agreement) ⇒
// TODO: Factor this out, just like we did with:
// TODO: val alignedTimeslots = splitTimeslotByPoliciesAndAgreements
// Note that most of the code is already taken from calcChangeChunks()
- val r = resolveEffectiveAlgorithmsAndPriceLists(alignedTimeslot, agreement, Just(clog))
+ val r = resolveEffectiveAlgorithmsAndPriceLists(alignedTimeslot, agreement, Some(clog))
val algorithmByTimeslot: Map[Timeslot, DSLAlgorithm] = r._1
val pricelistByTimeslot: Map[Timeslot, DSLPriceList] = r._2
val chargeslot = (algorithmDefOpt, priceUnitOpt) match {
case (None, None) ⇒
- throw new Exception(
+ throw new AquariumException(
"Unknown algorithm and price unit for resource %s during %s".
format(dslResource, finegrainedTimeslot))
case (None, _) ⇒
- throw new Exception(
+ throw new AquariumException(
"Unknown algorithm for resource %s during %s".
format(dslResource, finegrainedTimeslot))
case (_, None) ⇒
- throw new Exception(
+ throw new AquariumException(
"Unknown price unit for resource %s during %s".
format(dslResource, finegrainedTimeslot))
case (Some(algorithmDefinition), Some(priceUnit)) ⇒
* Compute the charge slots generated by a particular resource event.
*
*/
- def computeFullChargeslots(previousResourceEventM: Maybe[ResourceEvent],
- currentResourceEvent: ResourceEvent,
+ def computeFullChargeslots(previousResourceEventOpt: Option[ResourceEventModel],
+ currentResourceEvent: ResourceEventModel,
oldCredits: Double,
oldTotalAmount: Double,
newTotalAmount: Double,
agreementNamesByTimeslot: Map[Timeslot, String],
algorithmCompiler: CostPolicyAlgorithmCompiler,
policyStore: PolicyStore,
- contextualLogger: Maybe[ContextualLogger] = NoVal): Maybe[(Timeslot, List[Chargeslot])] = Maybe {
+ clogOpt: Option[ContextualLogger] = None): (Timeslot, List[Chargeslot]) = {
- val clog = ContextualLogger.fromOther(contextualLogger, logger, "computeFullChargeslots()")
+ val clog = ContextualLogger.fromOther(clogOpt, logger, "computeFullChargeslots()")
// clog.begin()
val occurredDate = currentResourceEvent.occurredDate
val (referenceTimeslot, relevantPolicies, previousValue) = costPolicy.needsPreviousEventForCreditAndAmountCalculation match {
// We need a previous event
case true ⇒
- previousResourceEventM match {
+ previousResourceEventOpt match {
// We have a previous event
- case Just(previousResourceEvent) ⇒
+ case Some(previousResourceEvent) ⇒
// clog.debug("Have previous event")
// clog.debug("previousValue = %s", previousResourceEvent.value)
(referenceTimeslot, relevantPolicies, previousResourceEvent.value)
// We do not have a previous event
- case NoVal ⇒
- throw new Exception(
+ case None ⇒
+ throw new AquariumException(
"Unable to charge. No previous event given for %s".
format(currentResourceEvent.toDebugString()))
-
- // We could not obtain a previous event
- case failed @ Failed(e, m) ⇒
- throw new Exception(
- "Unable to charge. Could not obtain previous event for %s".
- format(currentResourceEvent.toDebugString()), e)
}
// We do not need a previous event
// clog.debug("referenceTimeslot = %s".format(referenceTimeslot))
// clog.debug("Calling policyStore.loadValidPolicyEntryAt(%s)", new MutableDateCalc(occurredMillis))
- val relevantPolicyM = policyStore.loadValidPolicyAt(occurredMillis, dsl)
+ val relevantPolicyOpt = policyStore.loadValidPolicyAt(occurredMillis, dsl)
// clog.debug(" ==> relevantPolicyM = %s", relevantPolicyM)
- val relevantPolicies = relevantPolicyM match {
- case Just(relevantPolicy) ⇒
+ val relevantPolicies = relevantPolicyOpt match {
+ case Some(relevantPolicy) ⇒
Map(referenceTimeslot -> relevantPolicy)
- case NoVal ⇒
- throw new Exception("No relevant policy found for %s".format(referenceTimeslot))
- case failed @ Failed(e, _) ⇒
- throw new Exception("No relevant policy found for %s".format(referenceTimeslot), e)
+ case None ⇒
+ throw new AquariumInternalError("No relevant policy found for %s".format(referenceTimeslot))
}
(referenceTimeslot, relevantPolicies, previousValue)
}
- val initialChargeslotsM = computeInitialChargeslots(
+ val initialChargeslots = computeInitialChargeslots(
referenceTimeslot,
dslResource,
relevantPolicies,
agreementNamesByTimeslot,
- Just(clog)
+ Some(clog)
)
- val fullChargeslotsM = initialChargeslotsM.map { chargeslots ⇒
- chargeslots.map {
- case chargeslot @ Chargeslot(startMillis, stopMillis, algorithmDefinition, unitPrice, _) ⇒
- val execAlgorithmM = algorithmCompiler.compile(algorithmDefinition)
- execAlgorithmM match {
- case NoVal ⇒
- throw new Exception("Could not compile algorithm %s".format(algorithmDefinition))
-
- case failed @ Failed(e, m) ⇒
- throw new Exception(m, e)
-
- case Just(execAlgorithm) ⇒
- val valueMap = costPolicy.makeValueMap(
- oldCredits,
- oldTotalAmount,
- newTotalAmount,
- stopMillis - startMillis,
- previousValue,
- currentResourceEvent.value,
- unitPrice
- )
+ val fullChargeslots = initialChargeslots.map {
+ case chargeslot @ Chargeslot(startMillis, stopMillis, algorithmDefinition, unitPrice, _) ⇒
+ val execAlgorithm = algorithmCompiler.compile(algorithmDefinition)
+ val valueMap = costPolicy.makeValueMap(
+ oldCredits,
+ oldTotalAmount,
+ newTotalAmount,
+ stopMillis - startMillis,
+ previousValue,
+ currentResourceEvent.value,
+ unitPrice
+ )
// clog.debug("execAlgorithm = %s", execAlgorithm)
- clog.debugMap("valueMap", valueMap, 1)
-
- // This is it
- val creditsM = execAlgorithm.apply(valueMap)
+ clog.debugMap("valueMap", valueMap, 1)
- creditsM match {
- case NoVal ⇒
- throw new Exception(
- "Could not compute credits for resource %s during %s".
- format(dslResource.name, Timeslot(new Date(startMillis), new Date(stopMillis))))
-
- case failed @ Failed(e, m) ⇒
- throw new Exception(m, e)
-
- case Just(credits) ⇒
- chargeslot.copy(computedCredits = Some(credits))
- }
- }
- }
+ // This is it
+ val credits = execAlgorithm.apply(valueMap)
+ chargeslot.copy(computedCredits = Some(credits))
}
- val result = fullChargeslotsM match {
- case Just(fullChargeslots) ⇒
- referenceTimeslot -> fullChargeslots
- case NoVal ⇒
- null
- case failed @ Failed(e, m) ⇒
- throw new Exception(m, e)
- }
-
-// clog.end()
+ val result = referenceTimeslot -> fullChargeslots
result
}
* @param previousAmount The current state of the resource
* @param previousOccurred The last time the resource state was updated
*/
- def chargeEvent(currentResourceEvent: ResourceEvent,
+ def chargeEvent(currentResourceEvent: ResourceEventModel,
agreements: SortedMap[Timeslot, String],
previousAmount: Double,
previousOccurred: Date,
Some(x)
) match {
case Just(x) => x
- case Failed(f, e) => return Failed(f,e)
+ case Failed(f) => return Failed(f)
case NoVal => List()
}
entries
* resource event boundaries
* @return A list of wallet entries, one for each
*/
- def chargeEvent(event: ResourceEvent,
+ def chargeEvent(event: ResourceEventModel,
agr: DSLAgreement,
previousAmount: Double,
previousOccurred: Date,
chargeFor.map{x => assert(true,
Timeslot(previousOccurred, new Date(event.occurredMillis)))}
- if (!event.validate())
- return Failed(new AccountingException("Event not valid"))
+// if (!event.validate())
+// return Failed(new AccountingException("Event not valid"))
val policy = Policy.policy
val dslResource = policy.findResource(event.resource) match {
val creditCalculationValueM = dslResource.costPolicy.getValueForCreditCalculation(Just(previousAmount), event.value)
val amount = creditCalculationValueM match {
- case failed @ Failed(_, _) ⇒
+ case failed @ Failed(_) ⇒
return failed
case Just(amount) ⇒
amount
*/
val chargeChunks = calcChangeChunks(agr, amount, dslResource, timeslot)
- val timeReceived = System.currentTimeMillis
+ val timeReceived = TimeHelpers.nowMillis()
val rel = event.id :: related.map{x => x.sourceEventIDs}.flatten
sourceEventIDs = rel,
value = c.cost,
reason = c.reason,
- userId = event.userId,
+ userId = event.userID,
resource = event.resource,
- instanceId = event.instanceId,
+ instanceId = event.instanceID,
finalized = isFinal
)
}
def id(): String =
CryptoUtils.sha1("%f%s%f%s%s%d".format(value, algorithm, price, when.toString,
- resource.name, System.currentTimeMillis()))
+ resource.name, TimeHelpers.nowMillis()))
}
/** An exception raised when something goes wrong with accounting */
-class AccountingException(msg: String) extends Exception(msg)
+class AccountingException(msg: String) extends AquariumException(msg)