val alignedPolicyTimeslots = referenceTimeslot.align(policyTimeslots)
val alignedAgreementTimeslots = referenceTimeslot.align(agreementTimeslots)
- ContextualLogger.debugList(clog, "alignedPolicyTimeslots", alignedPolicyTimeslots)
- ContextualLogger.debugList(clog, "alignedAgreementTimeslots", alignedAgreementTimeslots)
+ clog.debugSeq("alignedPolicyTimeslots", alignedPolicyTimeslots, 0)
+ clog.debugSeq("alignedAgreementTimeslots", alignedAgreementTimeslots, 0)
val result = alignTimeslots(alignedPolicyTimeslots, alignedAgreementTimeslots)
clog.end()
* Given a reference timeslot, we have to break it up to a series of timeslots where a particular
* algorithm and price unit is in effect.
*
- * @param referenceTimeslot
- * @param policiesByTimeslot
- * @param agreementNamesByTimeslot
- * @return
*/
protected
+ def resolveEffectiveAlgorithmsAndPriceLists(alignedTimeslot: Timeslot,
+ agreement: DSLAgreement,
+ clogM: Maybe[ContextualLogger] = NoVal): (Map[Timeslot, DSLAlgorithm], Map[Timeslot, DSLPriceList]) = {
+
+ val clog = ContextualLogger.fromOther(clogM, logger, "resolveEffectiveAlgorithmsAndPriceLists()")
+
+ // Note that most of the code is taken from calcChangeChunks()
+ val alg = resolveEffectiveAlgorithmsForTimeslot(alignedTimeslot, agreement)
+ val pri = resolveEffectivePricelistsForTimeslot(alignedTimeslot, agreement)
+ val chargeChunks = splitChargeChunks(alg, pri)
+ val algorithmByTimeslot = chargeChunks._1
+ val pricelistByTimeslot = chargeChunks._2
+
+ assert(algorithmByTimeslot.size == pricelistByTimeslot.size)
+
+ (algorithmByTimeslot, pricelistByTimeslot)
+ }
+
+ protected
def computeInitialChargeslots(referenceTimeslot: Timeslot,
dslResource: DSLResource,
policiesByTimeslot: Map[Timeslot, DSLPolicy],
val policyTimeslots = policiesByTimeslot.keySet
val agreementTimeslots = agreementNamesByTimeslot.keySet
- clog.debug("policiesByTimeslot:")
- clog.withIndent {
- policyTimeslots.foreach(pt ⇒ clog.debug("%s: %s", pt, policiesByTimeslot(pt)))
- }
- clog.debug("agreementNamesByTimeslot:")
- clog.withIndent {
- agreementTimeslots.foreach(at ⇒ clog.debug("%s: %s", at, agreementNamesByTimeslot(at)))
- }
+ clog.debugMap("policiesByTimeslot", policiesByTimeslot, 1)
+ clog.debugMap("agreementNamesByTimeslot", agreementNamesByTimeslot, 1)
def getPolicy(ts: Timeslot): DSLPolicy = {
policiesByTimeslot.find(_._1.contains(ts)).get._2
}
// 1. Round ONE: split time according to overlapping policies and agreements.
+ clog.begin("ROUND 1")
val alignedTimeslots = splitTimeslotByPoliciesAndAgreements(referenceTimeslot, policyTimeslots.toList, agreementTimeslots.toList, Just(clog))
- clog.debug("ROUND 1: alignedTimeslots:")
- clog.withIndent {
- alignedTimeslots.foreach(ts ⇒ clog.debug("%s", ts))
- }
+ clog.debugSeq("alignedTimeslots", alignedTimeslots, 1)
+ clog.end("ROUND 1")
// 2. Round TWO: Use the aligned timeslots of Round ONE to produce even more
// fine-grained timeslots according to applicable algorithms.
// Then pack the info into charge slots.
- clog.debug("ROUND 2")
- clog.indent()
+ clog.begin("ROUND 2")
val allChargeslots = for {
alignedTimeslot <- alignedTimeslots
} yield {
+ val alignedTimeslotMsg = "alignedTimeslot = %s".format(alignedTimeslot)
+ clog.begin(alignedTimeslotMsg)
+
val dslPolicy = getPolicy(alignedTimeslot)
+ clog.debug("dslPolicy = %s", dslPolicy)
val agreementName = getAgreementName(alignedTimeslot)
+ clog.debug("agreementName = %s", agreementName)
val agreementOpt = dslPolicy.findAgreement(agreementName)
+ clog.debug("agreementOpt = %s", agreementOpt)
agreementOpt match {
case None ⇒
case Some(agreement) ⇒
// TODO: Factor this out, just like we did with:
// TODO: val alignedTimeslots = splitTimeslotByPoliciesAndAgreements
- // TODO: Note that most of the code is already taken from calcChangeChunks()
- val alg = resolveEffectiveAlgorithmsForTimeslot(alignedTimeslot, agreement)
- val pri = resolveEffectivePricelistsForTimeslot(alignedTimeslot, agreement)
- val chargeChunks = splitChargeChunks(alg, pri)
- val algorithmByTimeslot = chargeChunks._1
- val pricelistByTimeslot = chargeChunks._2
+ // Note that most of the code is already taken from calcChangeChunks()
+ val r = resolveEffectiveAlgorithmsAndPriceLists(alignedTimeslot, agreement, Just(clog))
+ val algorithmByTimeslot: Map[Timeslot, DSLAlgorithm] = r._1
+ val pricelistByTimeslot: Map[Timeslot, DSLPriceList] = r._2
// Now, the timeslots must be the same
val finegrainedTimeslots = algorithmByTimeslot.keySet
}
}
+ clog.end(alignedTimeslotMsg)
chargeslots.toList
}
}
- clog.unindent() // ROUND 2
+ clog.end("ROUND 2")
- clog.end()
+ val result = allChargeslots.flatten
clog.end()
- clog.end()
-
- allChargeslots.flatten
+ result
}
/**
// We have a previous event
case Just(previousResourceEvent) ⇒
clog.debug("Have previous event")
+ clog.debug("previousValue = %s", previousResourceEvent.value)
+
val referenceTimeslot = Timeslot(previousResourceEvent.occurredDate, occurredDate)
+ clog.debug("referenceTimeslot = %s".format(referenceTimeslot))
// all policies within the interval from previous to current resource event
clog.debug("Calling policyStore.loadAndSortPoliciesWithin(%s)", referenceTimeslot)
val relevantPolicies = policyStore.loadAndSortPoliciesWithin(referenceTimeslot.from.getTime, referenceTimeslot.to.getTime, dsl)
+ clog.debugMap("relevantPolicies", relevantPolicies)
(referenceTimeslot, relevantPolicies, previousResourceEvent.value)
// ... so we cannot compute timedelta from a previous event, there is just one chargeslot
// referring to (almost) an instant in time
clog.debug("DO NOT have previous event")
+ val previousValue = costPolicy.getResourceInstanceUndefinedAmount
+ clog.debug("previousValue = costPolicy.getResourceInstanceUndefinedAmount = %s", previousValue)
+
val referenceTimeslot = Timeslot(new MutableDateCalc(occurredDate).goPreviousMilli.toDate, occurredDate)
+ clog.debug("referenceTimeslot = %s".format(referenceTimeslot))
+
clog.debug("Calling policyStore.loadValidPolicyEntryAt(%s)", new MutableDateCalc(occurredMillis))
val relevantPolicyM = policyStore.loadValidPolicyAt(occurredMillis, dsl)
+ clog.debug("relevantPolicyM = %s", relevantPolicyM)
+
val relevantPolicies = relevantPolicyM match {
case Just(relevantPolicy) ⇒
Map(referenceTimeslot -> relevantPolicy)
}
- (referenceTimeslot, relevantPolicies, costPolicy.getResourceInstanceUndefinedAmount)
- }
- clog.debug("previousValue = %s".format(previousValue))
- clog.debug("referenceTimeslot = %s".format(referenceTimeslot))
- clog.debug("relevantPolicies:")
- clog.withIndent {
- val timeslots = relevantPolicies.keysIterator
- for(ts <- timeslots) {
- clog.debug("%s: %s", ts, relevantPolicies(ts))
- }
+ (referenceTimeslot, relevantPolicies, previousValue)
}
val initialChargeslotsM = computeInitialChargeslots(
algorithms:
- algorithm:
name: default
- bandwidth: $NotNow
- vmtime: $NotNow
- diskspace: $NotNow
+ bandwidth: function bandwidth() {return 1;}
+ vmtime: function vmtime() {return 1;}
+ diskspace: function diskspace() {return 1;}
effective:
from: 0
creditplan: default
"""
- val DefaultPolicy = new DSL{}.parse(PolicyYAML)
+ val DefaultPolicy = new DSL{} parse PolicyYAML
// TODO: integrate this with the rest of the simulation stuff
// TODO: since, right now, the resource strings have to be given twice
def testOne: Unit = {
val clog = ContextualLogger.fromOther(NoVal, logger, "testOne()")
val StartOfBillingYearDateCalc = new MutableDateCalc(2012, 1, 1)
- val UserCreationDateCalc = StartOfBillingYearDateCalc.copy.goMinusMonths(2)
+ val UserCreationDateCalc = new MutableDateCalc(2012, 1, 1).goMinusMonths(2)
- val computer = new UserStateComputations
+ val computations = new UserStateComputations
val mc = Configurator.MasterConfigurator.withStoreProviderClass(classOf[MemStore])
Policy.withConfigurator(mc)
// Let's create our dates of interest
val vmStartDateCalc = StartOfBillingYearDateCalc.copy.goPlusDays(1).goPlusHours(1)
- // 2012-01-16 01:00:00.000
val vmStartDate = vmStartDateCalc.toDate
// Within January, create one VM ON-OFF ...
VMTimeInstance.newONOFF(vmStartDate, 9)
val diskConsumptionDateCalc = StartOfBillingYearDateCalc.copy.goPlusHours(3)
- // 2012-01-16 04:00:00.000
val diskConsumptionDate1 = diskConsumptionDateCalc.toDate
- // 2012-01-17 05:00:00.000
val diskConsumptionDateCalc2 = diskConsumptionDateCalc.copy.goPlusDays(1).goPlusHours(1)
val diskConsumptionDate2 = diskConsumptionDateCalc2.toDate
BandwidthInstance.useBandwidth(bwDateCalc.toDate, 100.0)
// ... and one "future" event
- // 2012-02-07 07:07:07.007
DiskInstance.consumeMB(
StartOfBillingYearDateCalc.copy.
goNextMonth.goPlusDays(6).
val billingMonthInfo = BillingMonthInfo.fromDateCalc(StartOfBillingYearDateCalc)
- val initialUserState = computer.createFirstUserState(
+ val initialUserState = computations.createFirstUserState(
userId = UserCKKL.userId,
- millis = StartOfBillingYearDateCalc.copy.goPreviousYear.toMillis
+ userCreationMillis = UserCreationDateCalc.toMillis,
+ isActive = true,
+ credits = 0.0,
+ defaultPolicy = DefaultPolicy,
+ agreementName = DSLAgreement.DefaultAgreementName
)
- val userStateM = computer.doFullMonthlyBilling(
+ val currentUserState = initialUserState
+
+ val userStateM = computations.doFullMonthlyBilling(
UserCKKL.userId,
billingMonthInfo,
userStateStore,
resourceEventStore,
policyStore,
UserCKKL.userCreationDate.getTime,
- initialUserState,
+ currentUserState,
initialUserState,
DefaultPolicy,
DefaultResourcesMap,