Continuous debugging sessions...
authorChristos KK Loverdos <loverdos@gmail.com>
Fri, 9 Mar 2012 13:34:55 +0000 (15:34 +0200)
committerChristos KK Loverdos <loverdos@gmail.com>
Fri, 9 Mar 2012 13:34:55 +0000 (15:34 +0200)
src/main/scala/gr/grnet/aquarium/logic/accounting/Accounting.scala
src/main/scala/gr/grnet/aquarium/logic/accounting/dsl/DSLUtils.scala
src/main/scala/gr/grnet/aquarium/user/UserStateComputations.scala
src/main/scala/gr/grnet/aquarium/user/actor/UserActor.scala
src/test/scala/gr/grnet/aquarium/user/UserStateComputationsTest.scala

index b2934cd..7d1a077 100644 (file)
@@ -88,8 +88,8 @@ trait Accounting extends DSLUtils with Loggable {
     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()
@@ -100,12 +100,27 @@ trait Accounting extends DSLUtils with Loggable {
    * 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],
@@ -118,14 +133,8 @@ trait Accounting extends DSLUtils with Loggable {
     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
@@ -135,23 +144,27 @@ trait Accounting extends DSLUtils with Loggable {
     }
 
     // 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 ⇒
@@ -162,12 +175,10 @@ trait Accounting extends DSLUtils with Loggable {
         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
@@ -206,17 +217,16 @@ trait Accounting extends DSLUtils with Loggable {
             }
           }
 
+          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
   }
 
   /**
@@ -250,11 +260,15 @@ trait Accounting extends DSLUtils with Loggable {
           // 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)
 
@@ -276,9 +290,16 @@ trait Accounting extends DSLUtils with Loggable {
         // ... 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)
@@ -289,16 +310,7 @@ trait Accounting extends DSLUtils with Loggable {
 
         }
 
-        (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(
index 0653626..9ce9a91 100644 (file)
@@ -94,7 +94,7 @@ trait DSLUtils extends DateUtils {
       Timeslot(oneYearBack(timeslot.from, policy.effective.from),
       oneYearAhead (timeslot.to, policy.effective.to.getOrElse(maxdate))))
 
-    logger.debug("effective timeslots: %d".format(eff.size))
+//    logger.debug("effective timeslots: %d".format(eff.size))
 
     immutable.SortedMap[Timeslot, T]() ++
       timeslot.overlappingTimeslots(eff).flatMap {
index f4c3b6e..db32b8c 100644 (file)
@@ -373,8 +373,10 @@ class UserStateComputations extends Loggable {
                     clog.debug("theValue = %s, oldAmount = %s, newAmount = %s, oldCredits = %s", theValue, oldAmount, newAmount, oldCredits)
 
                     // B. Compute new wallet entries
+                    clog.debug("agreementsSnapshot = %s", _workingUserState.agreementsSnapshot)
                     val alltimeAgreements = _workingUserState.agreementsSnapshot.agreementsByTimeslot
 
+                    clog.debug("Computing full chargeslots")
                     val fullChargeslotsM = accounting.computeFullChargeslots(
                       previousResourceEventM,
                       currentResourceEvent,
index 2ba9a06..be102e3 100644 (file)
@@ -104,7 +104,7 @@ class UserActor extends AquariumActor
    * Create an empty state for a user
    */
   def createBlankState = {
-    this._userState = DefaultUserStateComputations.createFirstUserState(this._userId)
+    this._userState = DefaultUserStateComputations.createFirstUserState(this._userId, 0L, true, 0.0, null)
   }
 
   /**
@@ -178,6 +178,7 @@ class UserActor extends AquariumActor
           this._userState = DefaultUserStateComputations.createFirstUserState(
             userId,
             event.occurredMillis,
+            true, 0.0, null,
             DSLAgreement.DefaultAgreementName)
           saveUserState
           DEBUG("Created and stored %s", this._userState)
index 0c10d1c..514c15e 100644 (file)
@@ -44,9 +44,9 @@ aquariumpolicy:
   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
 
@@ -75,7 +75,7 @@ aquariumpolicy:
       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
@@ -92,9 +92,9 @@ aquariumpolicy:
   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)
@@ -124,16 +124,13 @@ aquariumpolicy:
 
     // 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
 
@@ -146,7 +143,6 @@ aquariumpolicy:
     BandwidthInstance.useBandwidth(bwDateCalc.toDate, 100.0)
 
     // ... and one "future" event
-    // 2012-02-07 07:07:07.007
     DiskInstance.consumeMB(
       StartOfBillingYearDateCalc.copy.
         goNextMonth.goPlusDays(6).
@@ -168,19 +164,25 @@ aquariumpolicy:
 
     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,