<groupId>org.scala-lang</groupId>
<artifactId>scala-compiler</artifactId>
<version>${scala.version}</version>
- <scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<resources>
<resource>
<directory>${basedir}/src/main/resources</directory>
+ <excludes>
+ <exclude>aquarium.properties</exclude>
+ </excludes>
</resource>
<resource>
<directory>${project.build.directory}/generated-resources</directory>
mongodb.connection.pool.size=20
# Relative to AQUARIUM_HOME or an absolute path
-events.store.folder=../events-store
+# DO NOT set this in production
+#events.store.folder=../events-store
# Store resource events to events.store.folder as well
-events.store.save.rc.events=true
+events.store.save.rc.events=false
# Store IM events to events.store.folder as well
-events.store.save.im.events=true
+events.store.save.im.events=false
# How often do we attempt a reconnection to the store(s)?
anystore.reconnect.period.millis=1000
import gr.grnet.aquarium.logic.accounting.algorithm.{SimpleCostPolicyAlgorithmCompiler, CostPolicyAlgorithmCompiler}
import gr.grnet.aquarium.logic.accounting.dsl.DSLResourcesMap
import gr.grnet.aquarium.logic.accounting.Policy
+import org.slf4j.{Logger, LoggerFactory}
/**
* This is the Aquarium entry point.
def isStopping() = _isStopping.get()
+ @inline
+ def getClientLogger(client: AnyRef): Logger = {
+ client match {
+ case null ⇒
+ this.logger
+
+ case _ ⇒
+ LoggerFactory.getLogger(client.getClass)
+ }
+ }
+
def debug(client: AnyRef, fmt: String, args: Any*) = {
- logger.debug("[%s] %s".format(shortClassNameOf(client), fmt.format(args: _*)))
+ getClientLogger(client).debug(fmt.format(args: _*))
}
def info(client: AnyRef, fmt: String, args: Any*) = {
- logger.info("[%s] %s".format(shortClassNameOf(client), fmt.format(args: _*)))
+ getClientLogger(client).info(fmt.format(args: _*))
}
def warn(client: AnyRef, fmt: String, args: Any*) = {
- logger.warn("[%s] %s".format(shortClassNameOf(client), fmt.format(args: _*)))
+ getClientLogger(client).warn(fmt.format(args: _*))
}
/**
final val aquarium_role_agreement_map = "aquarium.role-agreement.map"
/**
- * A time period in milliseconds for which we can tolerate stale data regarding user state.
+ * A time period in milliseconds for which we can tolerate stale parts regarding user state.
*
- * The smaller the value, the more accurate the user credits and other state data are.
+ * The smaller the value, the more accurate the user credits and other state parts are.
*
* If a request for user state (e.g. balance) is received and the request timestamp exceeds
* the timestamp of the last known balance amount by this value, then a re-computation for
package gr.grnet.aquarium
/**
- * Timely snapshots of data.
+ * Timely snapshots of parts.
*
- * We are interested only on the time aspect here, the data part is left open to the implementors.
+ * We are interested only on the time aspect here, the parts part is left open to the implementors.
*
* @author Christos KK Loverdos <loverdos@gmail.com>
*/
trait DataSnapshot {
/**
- * The unix time (millis) when the data was actually calculated/obtained.
+ * The unix time (millis) when the parts was actually calculated/obtained.
*/
def snapshotTime: Long
}
\ No newline at end of file
package gr.grnet.aquarium.actor.message
-import gr.grnet.aquarium.computation.UserState
+import gr.grnet.aquarium.computation.state.UserState
/**
*
import akka.config.Supervision.Temporary
import gr.grnet.aquarium.actor.message.event.{ProcessResourceEvent, ProcessIMEvent}
-import gr.grnet.aquarium.computation.data.IMStateSnapshot
import gr.grnet.aquarium.actor.message.config.{InitializeUserState, ActorProviderConfigured, AquariumPropertiesLoaded}
-import gr.grnet.aquarium.computation.{BillingMonthInfo, UserStateBootstrappingData, UserState}
import gr.grnet.aquarium.util.date.TimeHelpers
import gr.grnet.aquarium.event.model.im.IMEventModel
import gr.grnet.aquarium.actor.message.{GetUserStateResponse, GetUserBalanceResponseData, GetUserBalanceResponse, GetUserStateRequest, GetUserBalanceRequest}
import gr.grnet.aquarium.util.{LogHelpers, shortClassNameOf, shortNameOfClass, shortNameOfType}
-import gr.grnet.aquarium.computation.reason.{RealtimeBillingCalculation, NoSpecificChangeReason, InitialUserActorSetup, UserStateChangeReason, IMEventArrival, InitialUserStateSetup}
-import gr.grnet.aquarium.{AquariumInternalError, AquariumException, Aquarium}
+import gr.grnet.aquarium.computation.reason.{RealtimeBillingCalculation, InitialUserActorSetup, UserStateChangeReason, IMEventArrival, InitialUserStateSetup}
+import gr.grnet.aquarium.{AquariumInternalError, Aquarium}
+import gr.grnet.aquarium.computation.state.parts.IMStateSnapshot
+import gr.grnet.aquarium.computation.BillingMonthInfo
+import gr.grnet.aquarium.computation.state.{UserStateBootstrap, UserState}
+import gr.grnet.aquarium.event.model.resource.ResourceEventModel
/**
*
def role = UserActorRole
private[this] def aquarium: Aquarium = Aquarium.Instance
+
private[this] def userStateComputations = aquarium.userStateComputations
+ private[this] def stdUserStateStoreFunc = (userState: UserState) ⇒ {
+ aquarium.userStateStore.insertUserState(userState)
+ }
+
private[this] def _timestampTheshold = {
aquarium.props.getLong(Aquarium.Keys.user_state_timestamp_threshold).getOr(1000L * 60 * 5 /* 5 minutes */)
}
val userCreationMillis = this._imState.userCreationMillis.get
val initialRole = this._imState.roleHistory.firstRole.get.name
- val userStateBootstrap = UserStateBootstrappingData(
+ val userStateBootstrap = UserStateBootstrap(
this._userID,
userCreationMillis,
initialRole,
aquarium.initialBalanceForRole(initialRole, userCreationMillis)
)
- val userState = userStateComputations.doBillingForMonth(
+ val now = TimeHelpers.nowMillis()
+ val userState = userStateComputations.doMonthBillingUpTo(
+ BillingMonthInfo.fromMillis(now),
+ now,
userStateBootstrap,
- BillingMonthInfo.fromMillis(TimeHelpers.nowMillis()),
- false,
- TimeHelpers.nowMillis(),
aquarium.currentResourcesMap,
- InitialUserStateSetup(None),
+ InitialUserActorSetup(),
+ stdUserStateStoreFunc,
None
)
* call this.
*/
private[this] def newUserStateWithUpdatedRoleHistory(stateChangeReason: UserStateChangeReason): UserState = {
- this._userState.copy(
- roleHistory = this._imState.roleHistory,
- // FIXME: Also update agreement
- stateChangeCounter = this._userState.stateChangeCounter + 1,
- lastChangeReason = stateChangeReason
- )
+ // FIXME: Also update agreement
+ this._userState.newWithRoleHistory(this._imState.roleHistory, stateChangeReason)
}
/**
val initialRole = this._imState.roleHistory.firstRoleName.getOrElse(aquarium.defaultInitialUserRole)
val initialAgreement = aquarium.initialAgreementForRole(initialRole, userCreationMillis)
val initialCredits = aquarium.initialBalanceForRole(initialRole, userCreationMillis)
- val userStateBootstrap = UserStateBootstrappingData(
+ val userStateBootstrap = UserStateBootstrap(
userID,
userCreationMillis,
initialRole,
initialAgreement,
initialCredits
)
- val billingMonthInfoNow =BillingMonthInfo.fromMillis(now)
+ val billingMonthInfo = BillingMonthInfo.fromMillis(now)
val currentResourcesMap = aquarium.currentResourcesMap
val calculationReason = RealtimeBillingCalculation(None, now)
+ val eventOccurredMillis = rcEvent.occurredMillis
DEBUG("Using %s", currentResourcesMap)
- this._userState = aquarium.userStateComputations.doBillingForMonth(
+ this._userState = aquarium.userStateComputations.doMonthBillingUpTo(
+ billingMonthInfo,
+ now max eventOccurredMillis, // take into account that the event may be out-of-sync
userStateBootstrap,
- billingMonthInfoNow,
- false,
- now,
currentResourcesMap,
- calculationReason
+ calculationReason,
+ stdUserStateStoreFunc
)
this._latestResourceEventOccurredMillis = event.rcEvent.occurredMillis
package gr.grnet.aquarium.computation
import gr.grnet.aquarium.util.shortClassNameOf
-import gr.grnet.aquarium.util.date.{TimeHelpers, MutableDateCalc}
+import gr.grnet.aquarium.util.date.MutableDateCalc
/**
* Provides information about the billing month and related calculation utilities.
override def toString = "%s(%s-%02d-01)".format(shortClassNameOf(this), year, month)
+ def toDebugString = toString
+
def toShortDebugString = "%s-%02d-01".format(year, month)
}
import gr.grnet.aquarium.util.{ContextualLogger, Loggable}
import gr.grnet.aquarium.util.date.{TimeHelpers, MutableDateCalc}
import gr.grnet.aquarium.logic.accounting.dsl.DSLResourcesMap
-import gr.grnet.aquarium.computation.data._
+import gr.grnet.aquarium.computation.state.parts._
import gr.grnet.aquarium.event.model.NewWalletEntry
import gr.grnet.aquarium.event.model.resource.ResourceEventModel
import gr.grnet.aquarium.{Aquarium, AquariumInternalError}
import gr.grnet.aquarium.computation.reason.{MonthlyBillingCalculation, InitialUserStateSetup, UserStateChangeReason}
+import gr.grnet.aquarium.computation.state.{UserStateWorker, UserStateBootstrap, UserState}
/**
*
final class UserStateComputations(_aquarium: => Aquarium) extends Loggable {
lazy val aquarium = _aquarium
- lazy val storeProvider = aquarium.storeProvider
- lazy val timeslotComputations = new TimeslotComputations {}
- lazy val algorithmCompiler = aquarium.algorithmCompiler
- lazy val policyStore = storeProvider.policyStore
- lazy val userStateStore = storeProvider.userStateStore
- lazy val resourceEventStore = storeProvider.resourceEventStore
-
- def findUserStateAtEndOfBillingMonth(userStateBootstrap: UserStateBootstrappingData,
- billingMonthInfo: BillingMonthInfo,
- billingTimeMillis: Long,
- defaultResourcesMap: DSLResourcesMap,
- calculationReason: UserStateChangeReason,
- clogOpt: Option[ContextualLogger] = None): UserState = {
+
+ lazy val storeProvider = aquarium.storeProvider
+ lazy val timeslotComputations = new TimeslotComputations {}
+ lazy val algorithmCompiler = aquarium.algorithmCompiler
+ lazy val policyStore = storeProvider.policyStore
+ lazy val userStateStoreForRead = storeProvider.userStateStore
+ lazy val resourceEventStore = storeProvider.resourceEventStore
+
+ def findUserStateAtEndOfBillingMonth(
+ userStateBootstrap: UserStateBootstrap,
+ billingMonthInfo: BillingMonthInfo,
+ defaultResourcesMap: DSLResourcesMap,
+ calculationReason: UserStateChangeReason,
+ storeFunc: UserState ⇒ UserState,
+ clogOpt: Option[ContextualLogger] = None
+ ): UserState = {
val clog = ContextualLogger.fromOther(
clogOpt,
"findUserStateAtEndOfBillingMonth(%s)", billingMonthInfo.toShortDebugString)
clog.begin()
- def computeFullMonthlyBilling(): UserState = {
- doFullMonthlyBilling(
+ def computeFullMonthBillingAndSaveState(): UserState = {
+ val userState0 = doFullMonthBilling(
userStateBootstrap,
billingMonthInfo,
- billingTimeMillis,
defaultResourcesMap,
- MonthlyBillingCalculation(calculationReason, billingMonthInfo),
- Some(clog))
+ calculationReason,
+ storeFunc,
+ Some(clog)
+ )
+
+ // We always save the state when it is a full month billing
+ val userState1 = storeFunc.apply(
+ userState0.newWithChangeReason(
+ MonthlyBillingCalculation(calculationReason, billingMonthInfo))
+ )
+
+ clog.debug("Stored full %s %s", billingMonthInfo.toDebugString, userState1.toJsonString)
+ userState1
}
val userID = userStateBootstrap.userID
// If the user did not exist for this billing month, piece of cake
clog.debug("User did not exist before %s", userCreationDateCalc)
+ // TODO: The initial user state might have already been created.
+ // First ask if it exists and compute only if not
val initialUserState0 = UserState.createInitialUserStateFromBootstrap(
userStateBootstrap,
TimeHelpers.nowMillis(),
InitialUserStateSetup(Some(calculationReason)) // we record the originating calculation reason
)
- val initialUserState1 = userStateStore.insertUserState(initialUserState0)
- clog.debug("Initial state %s".format(initialUserState1))
+ // We always save the initial state
+ val initialUserState1 = storeFunc.apply(initialUserState0)
+
+ clog.debug("Stored initial state = %s", initialUserState1.toJsonString)
clog.end()
return initialUserState1
}
// Ask DB cache for the latest known user state for this billing period
- val latestUserStateOpt = userStateStore.findLatestUserStateForEndOfBillingMonth(
+ val latestUserStateOpt = userStateStoreForRead.findLatestUserStateForFullMonthBilling(
userID,
- billingMonthInfo.year,
- billingMonthInfo.month)
+ billingMonthInfo)
latestUserStateOpt match {
case None ⇒
// Not found, must compute
clog.debug("No user state found from cache, will have to (re)compute")
- val result = computeFullMonthlyBilling
+ val result = computeFullMonthBillingAndSaveState
clog.end()
result
case n if n > 0 ⇒
clog.debug(
"Found %s out of sync events (%s more), will have to (re)compute user state", actualOOSEventsCounter, n)
- val result = computeFullMonthlyBilling
+ val result = computeFullMonthBillingAndSaveState
clog.end()
result
}
//- Utility methods
- def processResourceEvent(startingUserState: UserState,
- userStateWorker: UserStateWorker,
- currentResourceEvent: ResourceEventModel,
- stateChangeReason: UserStateChangeReason,
- billingMonthInfo: BillingMonthInfo,
- walletEntriesBuffer: mutable.Buffer[NewWalletEntry],
- clogOpt: Option[ContextualLogger] = None): UserState = {
+ def processResourceEvent(
+ startingUserState: UserState,
+ userStateWorker: UserStateWorker,
+ currentResourceEvent: ResourceEventModel,
+ stateChangeReason: UserStateChangeReason,
+ billingMonthInfo: BillingMonthInfo,
+ walletEntriesBuffer: mutable.Buffer[NewWalletEntry],
+ clogOpt: Option[ContextualLogger] = None
+ ): UserState = {
val clog = ContextualLogger.fromOther(clogOpt, logger, "processResourceEvent(%s)", currentResourceEvent.id)
_workingUserState
}
- def processResourceEvents(resourceEvents: Traversable[ResourceEventModel],
- startingUserState: UserState,
- userStateWorker: UserStateWorker,
- stateChangeReason: UserStateChangeReason,
- billingMonthInfo: BillingMonthInfo,
- walletEntriesBuffer: mutable.Buffer[NewWalletEntry],
- clogOpt: Option[ContextualLogger] = None): UserState = {
+ def processResourceEvents(
+ resourceEvents: Traversable[ResourceEventModel],
+ startingUserState: UserState,
+ userStateWorker: UserStateWorker,
+ stateChangeReason: UserStateChangeReason,
+ billingMonthInfo: BillingMonthInfo,
+ walletEntriesBuffer: mutable.Buffer[NewWalletEntry],
+ clogOpt: Option[ContextualLogger] = None
+ ): UserState = {
var _workingUserState = startingUserState
_workingUserState
}
- def doFullMonthlyBilling(userStateBootstrap: UserStateBootstrappingData,
- billingMonthInfo: BillingMonthInfo,
- billingTimeMillis: Long,
- defaultResourcesMap: DSLResourcesMap,
- calculationReason: UserStateChangeReason,
- clogOpt: Option[ContextualLogger] = None): UserState = {
- doBillingForMonth(
- userStateBootstrap,
+ def doFullMonthBilling(
+ userStateBootstrap: UserStateBootstrap,
+ billingMonthInfo: BillingMonthInfo,
+ defaultResourcesMap: DSLResourcesMap,
+ calculationReason: UserStateChangeReason,
+ storeFunc: UserState ⇒ UserState,
+ clogOpt: Option[ContextualLogger] = None
+ ): UserState = {
+
+ doMonthBillingUpTo(
billingMonthInfo,
- true,
- billingTimeMillis,
+ billingMonthInfo.monthStopMillis,
+ userStateBootstrap,
defaultResourcesMap,
calculationReason,
+ storeFunc,
clogOpt
)
}
- def doBillingForMonth(userStateBootstrap: UserStateBootstrappingData,
- billingMonthInfo: BillingMonthInfo,
- fullBillingMonthState: Boolean, // See UserState#isFullBillingMonthState
- billingTimeMillis: Long, // See UserState$occurredMillis
- defaultResourcesMap: DSLResourcesMap,
- calculationReason: UserStateChangeReason,
- clogOpt: Option[ContextualLogger] = None): UserState = {
-
+ def doMonthBillingUpTo(
+ /**
+ * Which month to bill.
+ */
+ billingMonthInfo: BillingMonthInfo,
+ /**
+ * Bill from start of month up to (and including) this time.
+ */
+ billingEndTimeMillis: Long,
+ userStateBootstrap: UserStateBootstrap,
+ defaultResourcesMap: DSLResourcesMap,
+ calculationReason: UserStateChangeReason,
+ storeFunc: UserState ⇒ UserState,
+ clogOpt: Option[ContextualLogger] = None
+ ): UserState = {
+
+ val isFullMonthBilling = billingEndTimeMillis == billingMonthInfo.monthStopMillis
val userID = userStateBootstrap.userID
val clog = ContextualLogger.fromOther(
clogOpt,
logger,
- "doFullMonthlyBilling(%s)", billingMonthInfo.toShortDebugString)
+ "doMonthBillingUpTo(%s)", new MutableDateCalc(billingEndTimeMillis).toYYYYMMDDHHMMSSSSS)
clog.begin()
+ clog.debug("calculationReason = %s", calculationReason)
+
val clogSome = Some(clog)
val previousBillingMonthUserState = findUserStateAtEndOfBillingMonth(
userStateBootstrap,
billingMonthInfo.previousMonth,
- billingTimeMillis,
defaultResourcesMap,
- calculationReason.forBillingMonthInfo(billingMonthInfo.previousMonth),
+ calculationReason,
+ storeFunc,
clogSome
)
val startingUserState = previousBillingMonthUserState
- val billingMonthStartMillis = billingMonthInfo.monthStartMillis
- val billingMonthEndMillis = billingMonthInfo.monthStopMillis
-
// Keep the working (current) user state. This will get updated as we proceed with billing for the month
// specified in the parameters.
// NOTE: The calculation reason is not the one we get from the previous user state but the one our caller specifies
// First, find and process the actual resource events from DB
val allResourceEventsForMonth = resourceEventStore.findAllRelevantResourceEventsForBillingPeriod(
userID,
- billingMonthStartMillis,
- billingMonthEndMillis)
+ billingMonthInfo.monthStartMillis, // from start of month
+ billingEndTimeMillis // to requested time
+ )
val newWalletEntries = scala.collection.mutable.ListBuffer[NewWalletEntry]()
clogSome
)
- // Second, for the remaining events which must contribute an implicit OFF, we collect those OFFs
- // ... in order to generate an implicit ON later
- val (specialEvents, theirImplicitEnds) = userStateWorker.
- findAndRemoveGeneratorsOfImplicitEndEvents(billingMonthEndMillis)
- if(specialEvents.lengthCompare(1) >= 0 || theirImplicitEnds.lengthCompare(1) >= 0) {
- clog.debug("")
- clog.debug("Process implicitly issued events")
- clog.debugSeq("specialEvents", specialEvents, 0)
- clog.debugSeq("theirImplicitEnds", theirImplicitEnds, 0)
- }
-
- // Now, the previous and implicitly started must be our base for the following computation, so we create an
- // appropriate worker
- val specialUserStateWorker = UserStateWorker(
- userStateWorker.userID,
- LatestResourceEventsWorker.fromList(specialEvents),
- ImplicitlyIssuedResourceEventsWorker.Empty,
- IgnoredFirstResourceEventsWorker.Empty,
- userStateWorker.resourcesMap
- )
+ if(isFullMonthBilling) {
+ // Second, for the remaining events which must contribute an implicit OFF, we collect those OFFs
+ // ... in order to generate an implicit ON later (during the next billing cycle).
+ val (specialEvents, theirImplicitEnds) = userStateWorker.
+ findAndRemoveGeneratorsOfImplicitEndEvents(billingMonthInfo.monthStopMillis)
+
+ if(specialEvents.lengthCompare(1) >= 0 || theirImplicitEnds.lengthCompare(1) >= 0) {
+ clog.debug("")
+ clog.debug("Process implicitly issued events")
+ clog.debugSeq("specialEvents", specialEvents, 0)
+ clog.debugSeq("theirImplicitEnds", theirImplicitEnds, 0)
+ }
+
+ // Now, the previous and implicitly started must be our base for the following computation, so we create an
+ // appropriate worker
+ val specialUserStateWorker = UserStateWorker(
+ userStateWorker.userID,
+ LatestResourceEventsWorker.fromList(specialEvents),
+ ImplicitlyIssuedResourceEventsWorker.Empty,
+ IgnoredFirstResourceEventsWorker.Empty,
+ userStateWorker.resourcesMap
+ )
- _workingUserState = processResourceEvents(
- theirImplicitEnds,
- _workingUserState,
- specialUserStateWorker,
- calculationReason,
- billingMonthInfo,
- newWalletEntries,
- clogSome
- )
+ _workingUserState = processResourceEvents(
+ theirImplicitEnds,
+ _workingUserState,
+ specialUserStateWorker,
+ calculationReason,
+ billingMonthInfo,
+ newWalletEntries,
+ clogSome
+ )
+ }
val lastUpdateTime = TimeHelpers.nowMillis()
_workingUserState = _workingUserState.copy(
- isFullBillingMonthState = fullBillingMonthState,
+ isFullBillingMonthState = isFullMonthBilling,
- theFullBillingMonth = if(fullBillingMonthState)
+ theFullBillingMonth = if(isFullMonthBilling)
Some(billingMonthInfo)
else
_workingUserState.theFullBillingMonth,
newWalletEntries = newWalletEntries.toList
)
- clog.debug("calculationReason = %s", calculationReason)
-
- if(calculationReason.shouldStoreUserState) {
- val storedUserState = userStateStore.insertUserState(_workingUserState)
- clog.debug("Saved [_id=%s] %s", storedUserState._id, storedUserState)
- _workingUserState = storedUserState
- }
-
- clog.debug("RETURN %s", _workingUserState)
clog.end()
_workingUserState
}
+++ /dev/null
-/*
- * Copyright 2011-2012 GRNET S.A. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and
- * documentation are those of the authors and should not be
- * interpreted as representing official policies, either expressed
- * or implied, of GRNET S.A.
- */
-
-package gr.grnet.aquarium.computation.data
-
-
-/**
- *
- * @author Christos KK Loverdos <loverdos@gmail.com>
- */
-
-case class CreditSnapshot(creditAmount: Double)
import gr.grnet.aquarium.util.shortClassNameOf
/**
- * Provides information explaining the reason Aquarium calculated a new [[gr.grnet.aquarium.computation.UserState]].
+ * Provides information explaining the reason Aquarium calculated a new
+ * [[gr.grnet.aquarium.computation.state.UserState]].
*/
case class UserStateChangeReason(
- parentReason: Option[UserStateChangeReason],
+ details: Map[String, String],
billingMonthInfo: Option[BillingMonthInfo],
- details: Map[String, Any]
+ parentReason: Option[UserStateChangeReason]
) {
require(
- details.contains(UserStateChangeReason.Names.`type`),
- "No type present in the details of %s".format(shortClassNameOf(this))
+ details.contains(UserStateChangeReason.Names.name),
+ "No name present in the details of %s".format(shortClassNameOf(this))
)
private[this] def booleanFromDetails(name: String, default: Boolean) = {
details.get(name) match {
- case Some(value: Boolean) ⇒
- value
+ case Some(value) ⇒
+ value.toBoolean
case _ ⇒
false
* [[gr.grnet.aquarium.store.UserStateStore]].
*
*/
- def shouldStoreUserState: Boolean =
- booleanFromDetails(UserStateChangeReason.Names.shouldStoreUserState, false)
+// def shouldStoreUserState: Boolean =
+// booleanFromDetails(UserStateChangeReason.Names.shouldStoreUserState, false)
def shouldStoreCalculatedWalletEntries: Boolean =
booleanFromDetails(UserStateChangeReason.Names.shouldStoreCalculatedWalletEntries, false)
)
}
- def `type`: String = {
+ def name: String = {
// This must be always present
- details(UserStateChangeReason.Names.`type`).asInstanceOf[String]
+ details.get(UserStateChangeReason.Names.name).getOrElse("<unknown>")
}
}
object UserStateChangeReason {
object Names {
- final val `type` = "type"
+ final val name = "name"
final val imEvent = "imEvent"
final val forWhenMillis = "forWhenMillis"
def code: UserStateChangeReasonCodes.ChangeReasonCode
}
+/**
+ * Used when the very first user state is saved.
+ */
object InitialUserStateSetup {
- def `type` = "InitialUserStateSetup"
+ def name = "InitialUserStateSetup"
/**
* When the user state is initially set up.
*/
def apply(parentReason: Option[UserStateChangeReason]) = {
UserStateChangeReason(
- parentReason,
- None,
Map(
- UserStateChangeReason.Names.`type` -> `type`,
- UserStateChangeReason.Names.shouldStoreUserState -> true
- )
+ UserStateChangeReason.Names.name -> name//,
+// UserStateChangeReason.Names.shouldStoreUserState -> true
+ ),
+ None,
+ parentReason
)
}
}
object InitialUserActorSetup {
- def `type` = "InitialUserActorSetup"
+ def name = "InitialUserActorSetup"
/**
* When the user processing unit (actor) is initially set up.
*/
def apply() = {
UserStateChangeReason(
- None,
- None,
Map(
- UserStateChangeReason.Names.`type` -> `type`,
- UserStateChangeReason.Names.shouldStoreUserState -> true
- )
+ UserStateChangeReason.Names.name -> name//,
+// UserStateChangeReason.Names.shouldStoreUserState -> true
+ ),
+ None,
+ None
)
}
}
object NoSpecificChangeReason {
- def `type` = "NoSpecificChangeReason"
+ def name = "NoSpecificChangeReason"
/**
* A calculation made for no specific reason. Can be for testing, for example.
*/
def apply() = {
UserStateChangeReason(
- None,
- None,
Map(
- UserStateChangeReason.Names.`type` -> `type`
- )
+ UserStateChangeReason.Names.name -> name
+ ),
+ None,
+ None
)
}
}
object MonthlyBillingCalculation {
- def `type` = "MonthlyBillingCalculation"
+ def name = "MonthlyBillingCalculation"
/**
* An authoritative calculation for the billing period.
*/
def apply(parentReason: UserStateChangeReason, billingMongthInfo: BillingMonthInfo) = {
UserStateChangeReason(
- Some(parentReason),
- Some(billingMongthInfo),
Map(
- UserStateChangeReason.Names.`type` -> `type`,
- UserStateChangeReason.Names.shouldStoreUserState -> true,
- UserStateChangeReason.Names.shouldStoreCalculatedWalletEntries -> true,
- UserStateChangeReason.Names.calculateCreditsForImplicitlyTerminated -> true
- )
+ UserStateChangeReason.Names.name -> name,
+// UserStateChangeReason.Names.shouldStoreUserState -> true,
+ UserStateChangeReason.Names.shouldStoreCalculatedWalletEntries -> true.toString,
+ UserStateChangeReason.Names.calculateCreditsForImplicitlyTerminated -> true.toString
+ ),
+ Some(billingMongthInfo),
+ Some(parentReason)
)
}
}
object RealtimeBillingCalculation {
- def `type` = "RealtimeBillingCalculation"
+ def name = "RealtimeBillingCalculation"
/**
* Used for the real-time billing calculation.
*/
def apply(parentReason: Option[UserStateChangeReason], forWhenMillis: Long) = {
UserStateChangeReason(
- parentReason,
- None,
Map(
- UserStateChangeReason.Names.`type` -> `type`,
- UserStateChangeReason.Names.forWhenMillis -> forWhenMillis
- )
+ UserStateChangeReason.Names.name -> name,
+ UserStateChangeReason.Names.forWhenMillis -> forWhenMillis.toString
+ ),
+ None,
+ parentReason
)
}
}
object IMEventArrival {
- def `type` = "IMEventArrival"
+ def name = "IMEventArrival"
def apply(imEvent: IMEventModel) = {
UserStateChangeReason(
- None,
- None,
Map(
- UserStateChangeReason.Names.`type` -> `type`,
- UserStateChangeReason.Names.imEvent -> imEvent,
- UserStateChangeReason.Names.shouldStoreUserState -> true
- )
+ UserStateChangeReason.Names.name -> name,
+ UserStateChangeReason.Names.imEvent -> imEvent.toJsonString//,
+// UserStateChangeReason.Names.shouldStoreUserState -> true
+ ),
+ None,
+ None
)
}
}
* or implied, of GRNET S.A.
*/
-package gr.grnet.aquarium.computation
+package gr.grnet.aquarium.computation.state
import gr.grnet.aquarium.converter.{JsonTextFormat, StdConverters}
import gr.grnet.aquarium.event.model.NewWalletEntry
import gr.grnet.aquarium.util.json.JsonSupport
import gr.grnet.aquarium.logic.accounting.dsl.DSLAgreement
import gr.grnet.aquarium.computation.reason.{NoSpecificChangeReason, UserStateChangeReason, InitialUserStateSetup}
-import gr.grnet.aquarium.computation.data.{OwnedResourcesMap, RoleHistory, ResourceInstanceSnapshot, OwnedResourcesSnapshot, AgreementHistory, LatestResourceEventsSnapshot, ImplicitlyIssuedResourceEventsSnapshot}
import gr.grnet.aquarium.event.model.resource.ResourceEventModel
+import gr.grnet.aquarium.computation.BillingMonthInfo
+import gr.grnet.aquarium.computation.parts.RoleHistory
+import gr.grnet.aquarium.computation.state.parts.{OwnedResourcesMap, ResourceInstanceSnapshot, OwnedResourcesSnapshot, AgreementHistory, ImplicitlyIssuedResourceEventsSnapshot, LatestResourceEventsSnapshot}
/**
* A comprehensive representation of the User's state.
*
- * Note that it is made of autonomous parts that are actually data snapshots.
+ * Note that it is made of autonomous parts that are actually parts snapshots.
*
* The different snapshots need not agree on the snapshot time, ie. some state
* part may be stale, while other may be fresh.
* The user state is meant to be partially updated according to relevant events landing on Aquarium.
*
* @define communicatedByIM
- * This is communicated to Aquarium from the `IM` system.
+ * This is communicated to Aquarium from the `IM` system.
*
*
* @param userID
- * The user ID. $communicatedByIM
+ * The user ID. $communicatedByIM
* @param userCreationMillis
- * When the user was created.
- * $communicatedByIM
- * Set to zero if unknown.
+ * When the user was created.
+ * $communicatedByIM
+ * Set to zero if unknown.
* @param stateChangeCounter
* @param isFullBillingMonthState
* @param theFullBillingMonth
* @param agreementHistory
* @param ownedResourcesSnapshot
* @param newWalletEntries
- * The wallet entries computed. Not all user states need to holds wallet entries,
- * only those that refer to billing periods (end of billing period).
- * @param lastChangeReason
- * The [[gr.grnet.aquarium.computation.reason.UserStateChangeReason]] for which the usr state has changed.
+ * The wallet entries computed. Not all user states need to holds wallet entries,
+ * only those that refer to billing periods (end of billing period).
+ * @param lastChangeReason
+ * The [[gr.grnet.aquarium.computation.reason.UserStateChangeReason]] for which the usr state has changed.
* @param parentUserStateIDInStore
- * The `ID` of the parent state. The parent state is the one used as a reference point in order to calculate
- * this user state.
+ * The `ID` of the parent state. The parent state is the one used as a reference point in order to calculate
+ * this user state.
* @param _id
- * The unique `ID` given by the store.
+ * The unique `ID` given by the store.
*
* @author Christos KK Loverdos <loverdos@gmail.com>
*/
def idInStore: Option[String] = _id match {
case null ⇒ None
- case _id ⇒ Some(_id.toString)
+ case _id ⇒ Some(_id.toString)
}
-// def userCreationDate = new Date(userCreationMillis)
-//
-// def userCreationFormatedDate = new MutableDateCalc(userCreationMillis).toString
+ // def userCreationDate = new Date(userCreationMillis)
+ //
+ // def userCreationFormatedDate = new MutableDateCalc(userCreationMillis).toString
def findDSLAgreementForTime(at: Long): Option[DSLAgreement] = {
agreementHistory.findForTime(at)
ownedResourcesSnapshot.getResourceInstanceAmount(resource, instanceId, defaultValue)
}
- def newWithResourcesSnapshotUpdate(resource: String, // resource name
+ def newWithResourcesSnapshotUpdate(resource: String, // resource name
instanceId: String, // resource instance id
newAmount: Double,
snapshotTime: Long): UserState = {
this.copy(
isInitial = false,
ownedResourcesSnapshot = newResources,
- stateChangeCounter = this.stateChangeCounter + 1)
+ stateChangeCounter = this.stateChangeCounter + 1
+ )
}
def newWithChangeReason(changeReason: UserStateChangeReason) = {
)
}
+ def newWithRoleHistory(newRoleHistory: RoleHistory, changeReason: UserStateChangeReason) = {
+ // FIXME: Also update agreement
+ this.copy(
+ isInitial = false,
+ stateChangeCounter = this.stateChangeCounter + 1,
+ roleHistory = newRoleHistory,
+ lastChangeReason = changeReason
+ )
+ }
+
def resourcesMap: OwnedResourcesMap = {
ownedResourcesSnapshot.toResourcesMap
}
latestResourceEventsSnapshot.findTheLatestID
}
-// def toShortString = "UserState(%s, %s, %s, %s, %s)".format(
-// userId,
-// _id,
-// parentUserStateId,
-// totalEventsProcessedCounter,
-// calculationReason)
+ // def toShortString = "UserState(%s, %s, %s, %s, %s)".format(
+ // userId,
+ // _id,
+ // parentUserStateId,
+ // totalEventsProcessedCounter,
+ // calculationReason)
}
object UserState {
}
object JsonNames {
- final val _id = "_id"
+ final val _id = "_id"
final val userID = "userID"
final val isFullBillingMonthState = "isFullBillingMonthState"
final val occurredMillis = "occurredMillis"
+ final val theFullBillingMonth_year = "theFullBillingMonth.year" // FQN
+ final val theFullBillingMonth_month = "theFullBillingMonth.month" // FQN
object theFullBillingMonth {
- final val year = "year"
+ final val year = "year"
final val month = "month"
- final val monthStartMillis = "monthStartMillis"
- final val monthStopMillis = "monthStopMillis"
}
+
}
def createInitialUserState(
}
def createInitialUserStateFromBootstrap(
- usb: UserStateBootstrappingData,
+ usb: UserStateBootstrap,
occurredMillis: Long,
calculationReason: UserStateChangeReason
): UserState = {
* or implied, of GRNET S.A.
*/
-package gr.grnet.aquarium.computation
+package gr.grnet.aquarium.computation.state
/**
- * This is used to bootstrap the user state.
+ * This is used to bootstrap the [[gr.grnet.aquarium.computation.state.UserState]].
*
* @author Christos KK Loverdos <loverdos@gmail.com>
*/
-case class UserStateBootstrappingData(
- userID: String,
+case class UserStateBootstrap(
+ userID: String,
userCreationMillis: Long,
- initialRole: String,
- initialAgreement: String,
- initialCredits: Double
+ initialRole: String,
+ initialAgreement: String,
+ initialCredits: Double
)
*/
package gr.grnet.aquarium.computation
+package state
import scala.collection.mutable
import gr.grnet.aquarium.logic.accounting.dsl.DSLResourcesMap
-import gr.grnet.aquarium.computation.data.{LatestResourceEventsWorker, ImplicitlyIssuedResourceEventsWorker, IgnoredFirstResourceEventsWorker}
import gr.grnet.aquarium.util.ContextualLogger
import gr.grnet.aquarium.event.model.resource.ResourceEventModel
+import gr.grnet.aquarium.computation.state.parts.{IgnoredFirstResourceEventsWorker, ImplicitlyIssuedResourceEventsWorker, LatestResourceEventsWorker}
/**
* A helper object holding intermediate state/results during resource event processing.
*
* @author Christos KK Loverdos <loverdos@gmail.com>
*/
-case class UserStateWorker(userID: String,
- previousResourceEvents: LatestResourceEventsWorker,
- implicitlyIssuedStartEvents: ImplicitlyIssuedResourceEventsWorker,
- ignoredFirstResourceEvents: IgnoredFirstResourceEventsWorker,
- resourcesMap: DSLResourcesMap) {
+case class UserStateWorker(
+ userID: String,
+ previousResourceEvents: LatestResourceEventsWorker,
+ implicitlyIssuedStartEvents: ImplicitlyIssuedResourceEventsWorker,
+ ignoredFirstResourceEvents: IgnoredFirstResourceEventsWorker,
+ resourcesMap: DSLResourcesMap
+ ) {
/**
* Finds the previous resource event by checking two possible sources: a) The implicitly terminated resource
* @see [[gr.grnet.aquarium.logic.accounting.dsl.DSLCostPolicy]]
*/
def findAndRemoveGeneratorsOfImplicitEndEvents(
+ /**
+ * The `occurredMillis` that will be recorded in the synthetic implicit OFFs.
+ * Normally, this will be the end of a billing month.
+ */
newOccuredMillis: Long
): (List[ResourceEventModel], List[ResourceEventModel]) = {
* or implied, of GRNET S.A.
*/
-package gr.grnet.aquarium.computation.data
+package gr.grnet.aquarium.computation
+package state
+package parts
import java.util.Date
import scala.collection.immutable.{SortedMap, TreeMap}
/**
- * User agreement data that will be part of UserState.
+ * User agreement parts that will be part of UserState.
* The provided list of agreements cannot have time gaps. This is checked at object creation type.
*
* @author Christos KK Loverdos <loverdos@gmail.com>
* or implied, of GRNET S.A.
*/
-package gr.grnet.aquarium.computation.data
+package gr.grnet.aquarium.computation
+package state
+package parts
import gr.grnet.aquarium.util.date.MutableDateCalc
-import java.util.Date
import gr.grnet.aquarium.logic.accounting.dsl.Timeslot
/**
* or implied, of GRNET S.A.
*/
-package gr.grnet.aquarium.computation.data
+package gr.grnet.aquarium.computation
+package state
+package parts
import gr.grnet.aquarium.event.model.im.IMEventModel
import gr.grnet.aquarium.util.shortClassNameOf
import gr.grnet.aquarium.util.date.MutableDateCalc
+import gr.grnet.aquarium.computation.parts.RoleHistory
/**
*
*/
case class IMStateSnapshot(
- /**
- * This is the latest processed IMEvent
- */
- latestIMEvent: IMEventModel,
-
- /**
- * The earliest activation time, if it exists.
- */
- userEarliestActivationMillis: Option[Long],
-
- /**
- * The user creation time, if it exists
- */
- userCreationMillis: Option[Long],
-
- /**
- * This is the recorded role history
- */
- roleHistory: RoleHistory) {
+ /**
+ * This is the latest processed IMEvent
+ */
+ latestIMEvent: IMEventModel,
+
+ /**
+ * The earliest activation time, if it exists.
+ */
+ userEarliestActivationMillis: Option[Long],
+
+ /**
+ * The user creation time, if it exists
+ */
+ userCreationMillis: Option[Long],
+
+ /**
+ * This is the recorded role history
+ */
+ roleHistory: RoleHistory
+) {
/**
* True iff the user has ever been activated even once.
* or implied, of GRNET S.A.
*/
-package gr.grnet.aquarium.computation.data
+package gr.grnet.aquarium.computation
+package state
+package parts
import gr.grnet.aquarium.event.model.resource.ResourceEventModel
* or implied, of GRNET S.A.
*/
-package gr.grnet.aquarium.computation.data
+package gr.grnet.aquarium.computation
+package state
+package parts
import gr.grnet.aquarium.util.findAndRemoveFromMap
import gr.grnet.aquarium.event.model.resource.ResourceEventModel
def size = ignoredFirstEventsMap.size
- def foreach[U](f: ResourceEventModel => U): Unit = {
+ def foreach[U](f: ResourceEventModel ⇒ U): Unit = {
ignoredFirstEventsMap.valuesIterator.foreach(f)
}
}
* or implied, of GRNET S.A.
*/
-package gr.grnet.aquarium.computation.data
+package gr.grnet.aquarium.computation
+package state
+package parts
import gr.grnet.aquarium.event.model.resource.ResourceEventModel
/**
* Keeps the implicit OFF events when a billing period ends.
- * This is normally recorded in the [[gr.grnet.aquarium.computation.UserState]].
+ * This is normally recorded in the [[gr.grnet.aquarium.computation.state.UserState]].
*
* @author Christos KK Loverdos <loverdos@gmail.com>
*/
/**
* The gateway to playing with mutable state.
*
- * @return A fresh instance of [[gr.grnet.aquarium.computation.data.ImplicitlyIssuedResourceEventsWorker]].
+ * @return A fresh instance of [[gr.grnet.aquarium.computation.state.parts.ImplicitlyIssuedResourceEventsWorker]].
*/
def toMutableWorker = {
val map = scala.collection.mutable.Map[ResourceEventModel.FullResourceType, ResourceEventModel]()
* or implied, of GRNET S.A.
*/
-package gr.grnet.aquarium.computation.data
+package gr.grnet.aquarium.computation
+package state
+package parts
import gr.grnet.aquarium.util.findAndRemoveFromMap
import gr.grnet.aquarium.event.model.resource.ResourceEventModel
/**
- * This is the mutable cousin of [[gr.grnet.aquarium.computation.data.ImplicitlyIssuedResourceEventsSnapshot]].
- *
- * @param implicitlyIssuedEventsMap
+ * This is the mutable cousin of [[gr.grnet.aquarium.computation.state.parts.ImplicitlyIssuedResourceEventsSnapshot]].
*
* @author Christos KK Loverdos <loverdos@gmail.com>
*/
* or implied, of GRNET S.A.
*/
-package gr.grnet.aquarium.computation.data
+package gr.grnet.aquarium.computation
+package state
+package parts
import gr.grnet.aquarium.event.model.resource.ResourceEventModel
/**
* The gateway to playing with mutable state.
*
- * @return A fresh instance of [[gr.grnet.aquarium.computation.data.LatestResourceEventsWorker]].
+ * @return A fresh instance of [[gr.grnet.aquarium.computation.state.parts.LatestResourceEventsWorker]].
*/
def toMutableWorker = {
val map = scala.collection.mutable.Map[ResourceEventModel.FullResourceType, ResourceEventModel]()
* or implied, of GRNET S.A.
*/
-package gr.grnet.aquarium.computation.data
+package gr.grnet.aquarium.computation
+package state
+package parts
import gr.grnet.aquarium.util.findAndRemoveFromMap
import gr.grnet.aquarium.event.model.resource.ResourceEventModel
import gr.grnet.aquarium.event.model.resource.ResourceEventModel.FullMutableResourceTypeMap
/**
- * This is the mutable cousin of [[gr.grnet.aquarium.computation.data.LatestResourceEventsSnapshot]].
+ * This is the mutable cousin of [[gr.grnet.aquarium.computation.state.parts.LatestResourceEventsSnapshot]].
*
* @param latestEventsMap
*
* The gateway to immutable state.
*
* @param snapshotTime The relevant snapshot time.
- * @return A fresh instance of [[gr.grnet.aquarium.computation.data.LatestResourceEventsSnapshot]].
+ * @return A fresh instance of [[gr.grnet.aquarium.computation.state.parts.LatestResourceEventsSnapshot]].
*/
def toImmutableSnapshot(snapshotTime: Long) =
LatestResourceEventsSnapshot(latestEventsMap.valuesIterator.toList)
* or implied, of GRNET S.A.
*/
-package gr.grnet.aquarium.computation.data
+package gr.grnet.aquarium.computation
+package state
+package parts
/**
* A map from (resourceName, resourceInstanceId) to value.
*
* This representation is convenient for computations and updating, while the
- * [[gr.grnet.aquarium.computation.data.OwnedResourcesSnapshot]] representation is convenient for JSON serialization.
+ * [[gr.grnet.aquarium.computation.state.parts.OwnedResourcesSnapshot]] representation is convenient for JSON
+ * serialization.
*
* @author Christos KK Loverdos <loverdos@gmail.com>
*/
* or implied, of GRNET S.A.
*/
-package gr.grnet.aquarium.computation.data
-
+package gr.grnet.aquarium.computation
+package state
+package parts
/**
*
}
def resourceInstanceSnapshotsExcept(resource: String, instanceId: String) = {
- // Unfortunately, we have to use a List for data, since JSON serialization is not as flexible
- // (at least out of the box). Thus, the update is O(L), where L is the length of the data List.
+ // Unfortunately, we have to use a List for parts, since JSON serialization is not as flexible
+ // (at least out of the box). Thus, the update is O(L), where L is the length of the parts List.
resourceInstanceSnapshots.filterNot(_.isSameResourceInstance(resource, instanceId))
}
* or implied, of GRNET S.A.
*/
-package gr.grnet.aquarium.computation.data
+package gr.grnet.aquarium.computation
+package state
+package parts
/**
* Maintains the current state of a resource instance owned by the user.
*
* name: DSLResource.name
* instanceId: instance-id (in the resource's descriminatorField)
- * data: current-resource-value
+ * parts: current-resource-value
* snapshotTime: last-update-timestamp
*
* In order to have a uniform representation of the resource state for all
* - If the resource is complex, the (name, instanceId) is (DSLResource.name, instance-id)
* - If the resource is simple, the (name, instanceId) is (DSLResource.name, "1")
*
- * @param resource Same as `resource` of [[gr.grnet.aquarium.event.resource.ResourceEventModel]]
- * @param instanceId Same as `instanceId` of [[gr.grnet.aquarium.event.resource.ResourceEventModel]]
+ * @param resource Same as `resource` of [[gr.grnet.aquarium.event.model.resource.ResourceEventModel]]
+ * @param instanceId Same as `instanceId` of [[gr.grnet.aquarium.event.model.resource.ResourceEventModel]]
* @param instanceAmount This is the amount kept for the resource instance.
-* The general rule is that an amount saved in a [[gr.grnet.aquarium.computation.data. ResourceInstanceSnapshot]]
- * represents a total value, while a value appearing in a [[gr.grnet.aquarium.event.resource.ResourceEventModel]]
+* The general rule is that an amount saved in a
+ * [[gr.grnet.aquarium.computation.parts. ResourceInstanceSnapshot]]
+ * represents a total value, while a value appearing in a
+ * [[gr.grnet.aquarium.event .model.resource.ResourceEventModel]]
* represents a difference. How these two values are combined to form the new amount is dictated
* by the underlying [[gr.grnet.aquarium.logic.accounting.dsl.DSLCostPolicy]]
*
* or implied, of GRNET S.A.
*/
-package gr.grnet.aquarium.computation.data
+package gr.grnet.aquarium.computation.parts
import gr.grnet.aquarium.logic.accounting.dsl.Timeslot
import scala.collection.immutable.{TreeMap, SortedMap}
*/
case class RoleHistory(
- /**
- * The head role is the most recent. The same rule applies for the tail.
- */
- roles: List[RoleHistoryItem]) {
+ /**
+ * The head role is the most recent. The same rule applies for the tail.
+ */
+ roles: List[RoleHistoryItem]
+) {
def roleNamesByTimeslot: SortedMap[Timeslot, String] = {
TreeMap(roles.map(role ⇒ (role.timeslot, role.name)): _*)
* or implied, of GRNET S.A.
*/
-package gr.grnet.aquarium.computation.data
+package gr.grnet.aquarium.computation.parts
import gr.grnet.aquarium.util.date.MutableDateCalc
import gr.grnet.aquarium.logic.accounting.dsl.Timeslot
/**
* Validity stop time for this role. The time is exclusive.
*/
- validTo: Long = Long.MaxValue) {
+ validTo: Long = Long.MaxValue
+) {
try {
require(
}
catch {
case e: IllegalArgumentException ⇒
+ // TODO Remove this
Aquarium.Instance.debug(this, "!! validFrom = %s, validTo = %s, dx=%s", validFrom, validTo, validTo-validFrom)
throw e
}
* The application-wide JSON formats used from the underlying lift-json library.
*/
implicit final val Formats = (DefaultFormats ++ JodaTimeSerializers.all)
+// implicit final val Formats = (DefaultFormats.withHints(FullTypeHints(List(classOf[AnyRef]))) ++ JodaTimeSerializers.all)
+// Serialization.formats(FullTypeHints(List(classOf[AnyRef])))
/**
* Converts a value to JSON AST (Abstract Syntax Tree) by acting a bit intelligently, depending on the actual type
/**
- * Every data type conversion happening inside Aquarium is defined here.
+ * Every parts type conversion happening inside Aquarium is defined here.
*
* @author Christos KK Loverdos <loverdos@gmail.com>
*/
import gr.grnet.aquarium.converter.{JsonTextFormat, StdConverters}
/**
- * Store entry for serialized policy data.
+ * Store entry for serialized policy parts.
*
* @author Georgios Gousios <gousiosg@gmail.com>
*/
package gr.grnet.aquarium.store
/**
- * Represents an ID given by a store to a data object (document).
+ * Represents an ID given by a store to a parts object (document).
*
* @author Christos KK Loverdos <loverdos@gmail.com>.
*/
package gr.grnet.aquarium.store
-import gr.grnet.aquarium.computation.UserState
+import gr.grnet.aquarium.computation.state.UserState
+import gr.grnet.aquarium.computation.BillingMonthInfo
/**
* A store for user state snapshots.
*
- * This is used to hold snapshots of [[gr.grnet.aquarium.computation.UserState]]
+ * This is used to hold snapshots of [[gr.grnet.aquarium.computation.state.UserState]].
*
* @author Christos KK Loverdos <loverdos@gmail.com>
*/
trait UserStateStore {
/**
- * Store a user state.
+ * Stores a user state.
*/
def insertUserState(userState: UserState): UserState
/**
- * Find a state by user ID
+ * Finds a state by user ID
*/
def findUserStateByUserID(userID: String): Option[UserState]
/**
- * Find the most up-to-date user state for the particular billing period.
+ * Finds the most up-to-date user state for the particular billing period.
*/
- def findLatestUserStateForEndOfBillingMonth(userID: String, yearOfBillingMonth: Int, billingMonth: Int): Option[UserState]
-
- /**
- * Delete a state for a user
- */
- def deleteUserState(userId: String): Unit
+ def findLatestUserStateForFullMonthBilling(userID: String, bmi: BillingMonthInfo): Option[UserState]
}
\ No newline at end of file
package gr.grnet.aquarium.store.memory
import com.ckkloverdos.props.Props
-import com.ckkloverdos.maybe.{NoVal, Just}
+import com.ckkloverdos.maybe.Just
import gr.grnet.aquarium.store._
import scala.collection.JavaConversions._
import collection.mutable.ConcurrentMap
import java.util.concurrent.ConcurrentHashMap
-import gr.grnet.aquarium.uid.ConcurrentVMLocalUIDGenerator
import gr.grnet.aquarium.Configurable
import gr.grnet.aquarium.event.model.PolicyEntry
import gr.grnet.aquarium.event.model.im.{StdIMEvent, IMEventModel}
import org.bson.types.ObjectId
import gr.grnet.aquarium.event.model.resource.{StdResourceEvent, ResourceEventModel}
-import gr.grnet.aquarium.computation.UserState
+import gr.grnet.aquarium.computation.state.UserState
import gr.grnet.aquarium.util.Tags
+import gr.grnet.aquarium.computation.BillingMonthInfo
/**
- * An implementation of various stores that persists data in memory.
+ * An implementation of various stores that persists parts in memory.
*
* This is just for testing purposes.
*
_userStates.find(_.userID == userID)
}
- def findLatestUserStateForEndOfBillingMonth(userID: String,
- yearOfBillingMonth: Int,
- billingMonth: Int): Option[UserState] = {
+ def findLatestUserStateForFullMonthBilling(userID: String, bmi: BillingMonthInfo): Option[UserState] = {
val goodOnes = _userStates.filter(_.theFullBillingMonth.isDefined).filter { userState ⇒
val f1 = userState.userID == userID
val f2 = userState.isFullBillingMonthState
val bm = userState.theFullBillingMonth.get
- val f3 = (bm ne null) && {
- bm.year == yearOfBillingMonth && bm.month == billingMonth
- }
+ val f3 = bm == bmi
f1 && f2 && f3
}
None
}
}
-
- def deleteUserState(userId: String) {
- _userStates.filterNot(_.userID == userId)
- }
//- UserStateStore
//+ ResourceEventStore
package gr.grnet.aquarium.store.mongodb
import com.mongodb.util.JSON
-import gr.grnet.aquarium.computation.UserState.{JsonNames ⇒ UserStateJsonNames}
+import gr.grnet.aquarium.computation.state.UserState.{JsonNames ⇒ UserStateJsonNames}
import gr.grnet.aquarium.util.json.JsonSupport
import collection.mutable.ListBuffer
import gr.grnet.aquarium.event.model.im.IMEventModel
import com.ckkloverdos.maybe.Maybe
import gr.grnet.aquarium.util._
import gr.grnet.aquarium.converter.Conversions
-import gr.grnet.aquarium.computation.UserState
+import gr.grnet.aquarium.computation.state.UserState
import gr.grnet.aquarium.event.model.{ExternalEventModel, PolicyEntry}
+import gr.grnet.aquarium.computation.BillingMonthInfo
+import gr.grnet.aquarium.Aquarium
/**
* Mongodb implementation of the various aquarium stores.
MongoDBStore.firstResultIfExists(cursor, MongoDBStore.dbObjectToUserState)
}
- def findLatestUserStateForEndOfBillingMonth(userID: String,
- yearOfBillingMonth: Int,
- billingMonth: Int): Option[UserState] = {
+ def findLatestUserStateForFullMonthBilling(userID: String, bmi: BillingMonthInfo): Option[UserState] = {
val query = new BasicDBObjectBuilder().
add(UserState.JsonNames.userID, userID).
add(UserState.JsonNames.isFullBillingMonthState, true).
- add(UserState.JsonNames.theFullBillingMonth.year, yearOfBillingMonth).
- add(UserState.JsonNames.theFullBillingMonth.month, billingMonth).
+ add(UserState.JsonNames.theFullBillingMonth_year, bmi.year).
+ add(UserState.JsonNames.theFullBillingMonth_month, bmi.month).
get()
+ logger.debug("findLatestUserStateForFullMonthBilling(%s, %s) query: %s".format(userID, bmi, query))
+
// Descending order, so that the latest comes first
val sorter = new BasicDBObject(UserState.JsonNames.occurredMillis, -1)
MongoDBStore.firstResultIfExists(cursor, MongoDBStore.dbObjectToUserState)
}
-
- def deleteUserState(userId: String) = {
- val query = new BasicDBObject(UserStateJsonNames.userID, userId)
- userStates.findAndRemove(query)
- }
//- UserStateStore
//+IMEventStore
final val RESOURCE_EVENTS_COLLECTION = "resevents"
/**
- * Collection holding the snapshots of [[gr.grnet.aquarium.computation.UserState]].
+ * Collection holding the snapshots of [[gr.grnet.aquarium.computation.state.UserState]].
*
- * [[gr.grnet.aquarium.computation.UserState]] is held internally within [[gr.grnet.aquarium.actor.service.user.UserActor]]s.
+ * [[gr.grnet.aquarium.computation.state.UserState]] is held internally within
+ * [[gr.grnet.aquarium.actor.service.user .UserActor]]s.
*/
final val USER_STATES_COLLECTION = "userstates"
DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - testOrphanOFF() EVENT(0, [2012-01-01 00:00:00], 0.0, vmtime::VM.1, Map(), CKKL, synnefo)
DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - testOrphanOFF() --- [Events by OccurredMillis] ---
DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - testOrphanOFF()
-DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - doFullMonthlyBilling(2012-01) BEGIN
+DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - doFullMonthBilling(2012-01) BEGIN
DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - …ndUserStateAtEndOfBillingMonth(2011-12) BEGIN
DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - …ndUserStateAtEndOfBillingMonth(2011-12) No user state found from cache, will have to (re)compute
-DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - doFullMonthlyBilling(2011-12) BEGIN
+DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - doFullMonthBilling(2011-12) BEGIN
DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - …ndUserStateAtEndOfBillingMonth(2011-11) BEGIN
DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - …ndUserStateAtEndOfBillingMonth(2011-11) No user state found from cache, will have to (re)compute
-DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - doFullMonthlyBilling(2011-11) BEGIN
+DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - doFullMonthBilling(2011-11) BEGIN
DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - …ndUserStateAtEndOfBillingMonth(2011-10) BEGIN
DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - …ndUserStateAtEndOfBillingMonth(2011-10) User did not exist before 2011-11-01 00:00:00.000
DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - …ndUserStateAtEndOfBillingMonth(2011-10) Returning INITIAL state [_id=4fa7e12ba0eee3db73fbe8d0] UserState(true,CKKL,1320098400000,0,false,null,ImplicitlyIssuedResourceEventsSnapshot(List()),List(),List(),LatestResourceEventsSnapshot(List()),0,0,IMStateSnapshot(StdIMEvent(,1320098400000,1320098400000,CKKL,,true,user,1.0,create,Map())),CreditSnapshot(0.0),AgreementHistory(List(AgreementHistoryItem(default, 2011-11-01 00:00:00.000, 292278994-08-17 07:12:55.807))),OwnedResourcesSnapshot(List()),List(),1320098400000,InitialUserStateSetup,0,None,4fa7e12ba0eee3db73fbe8d0)
DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - …ndUserStateAtEndOfBillingMonth(2011-10) END
-DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - doFullMonthlyBilling(2011-11) calculationReason = MonthlyBillingCalculation(2011-11)
-DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - doFullMonthlyBilling(2011-11) Saved [_id=4fa7e12ba0eee3db73fbe8d0] UserState(true,CKKL,1320098400000,1,false,null,ImplicitlyIssuedResourceEventsSnapshot(List()),List(),List(),LatestResourceEventsSnapshot(List()),0,0,IMStateSnapshot(StdIMEvent(,1320098400000,1320098400000,CKKL,,true,user,1.0,create,Map())),CreditSnapshot(0.0),AgreementHistory(List(AgreementHistoryItem(default, 2011-11-01 00:00:00.000, 292278994-08-17 07:12:55.807))),OwnedResourcesSnapshot(List()),List(),1320098400000,MonthlyBillingCalculation(2011-11),0,Some(4fa7e12ba0eee3db73fbe8d0),4fa7e12ba0eee3db73fbe8d0)
-DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - doFullMonthlyBilling(2011-11) RETURN UserState(true,CKKL,1320098400000,1,false,null,ImplicitlyIssuedResourceEventsSnapshot(List()),List(),List(),LatestResourceEventsSnapshot(List()),0,0,IMStateSnapshot(StdIMEvent(,1320098400000,1320098400000,CKKL,,true,user,1.0,create,Map())),CreditSnapshot(0.0),AgreementHistory(List(AgreementHistoryItem(default, 2011-11-01 00:00:00.000, 292278994-08-17 07:12:55.807))),OwnedResourcesSnapshot(List()),List(),1320098400000,MonthlyBillingCalculation(2011-11),0,Some(4fa7e12ba0eee3db73fbe8d0),4fa7e12ba0eee3db73fbe8d0)
-DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - doFullMonthlyBilling(2011-11) END
+DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - doFullMonthBilling(2011-11) calculationReason = MonthlyBillingCalculation(2011-11)
+DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - doFullMonthBilling(2011-11) Saved [_id=4fa7e12ba0eee3db73fbe8d0] UserState(true,CKKL,1320098400000,1,false,null,ImplicitlyIssuedResourceEventsSnapshot(List()),List(),List(),LatestResourceEventsSnapshot(List()),0,0,IMStateSnapshot(StdIMEvent(,1320098400000,1320098400000,CKKL,,true,user,1.0,create,Map())),CreditSnapshot(0.0),AgreementHistory(List(AgreementHistoryItem(default, 2011-11-01 00:00:00.000, 292278994-08-17 07:12:55.807))),OwnedResourcesSnapshot(List()),List(),1320098400000,MonthlyBillingCalculation(2011-11),0,Some(4fa7e12ba0eee3db73fbe8d0),4fa7e12ba0eee3db73fbe8d0)
+DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - doFullMonthBilling(2011-11) RETURN UserState(true,CKKL,1320098400000,1,false,null,ImplicitlyIssuedResourceEventsSnapshot(List()),List(),List(),LatestResourceEventsSnapshot(List()),0,0,IMStateSnapshot(StdIMEvent(,1320098400000,1320098400000,CKKL,,true,user,1.0,create,Map())),CreditSnapshot(0.0),AgreementHistory(List(AgreementHistoryItem(default, 2011-11-01 00:00:00.000, 292278994-08-17 07:12:55.807))),OwnedResourcesSnapshot(List()),List(),1320098400000,MonthlyBillingCalculation(2011-11),0,Some(4fa7e12ba0eee3db73fbe8d0),4fa7e12ba0eee3db73fbe8d0)
+DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - doFullMonthBilling(2011-11) END
DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - …ndUserStateAtEndOfBillingMonth(2011-11) END
-DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - doFullMonthlyBilling(2011-12) calculationReason = MonthlyBillingCalculation(2011-12)
-DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - doFullMonthlyBilling(2011-12) Saved [_id=4fa7e12ba0eee3db73fbe8d0] UserState(true,CKKL,1320098400000,2,false,null,ImplicitlyIssuedResourceEventsSnapshot(List()),List(),List(),LatestResourceEventsSnapshot(List()),0,0,IMStateSnapshot(StdIMEvent(,1320098400000,1320098400000,CKKL,,true,user,1.0,create,Map())),CreditSnapshot(0.0),AgreementHistory(List(AgreementHistoryItem(default, 2011-11-01 00:00:00.000, 292278994-08-17 07:12:55.807))),OwnedResourcesSnapshot(List()),List(),1320098400000,MonthlyBillingCalculation(2011-12),0,Some(4fa7e12ba0eee3db73fbe8d0),4fa7e12ba0eee3db73fbe8d0)
-DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - doFullMonthlyBilling(2011-12) RETURN UserState(true,CKKL,1320098400000,2,false,null,ImplicitlyIssuedResourceEventsSnapshot(List()),List(),List(),LatestResourceEventsSnapshot(List()),0,0,IMStateSnapshot(StdIMEvent(,1320098400000,1320098400000,CKKL,,true,user,1.0,create,Map())),CreditSnapshot(0.0),AgreementHistory(List(AgreementHistoryItem(default, 2011-11-01 00:00:00.000, 292278994-08-17 07:12:55.807))),OwnedResourcesSnapshot(List()),List(),1320098400000,MonthlyBillingCalculation(2011-12),0,Some(4fa7e12ba0eee3db73fbe8d0),4fa7e12ba0eee3db73fbe8d0)
-DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - doFullMonthlyBilling(2011-12) END
+DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - doFullMonthBilling(2011-12) calculationReason = MonthlyBillingCalculation(2011-12)
+DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - doFullMonthBilling(2011-12) Saved [_id=4fa7e12ba0eee3db73fbe8d0] UserState(true,CKKL,1320098400000,2,false,null,ImplicitlyIssuedResourceEventsSnapshot(List()),List(),List(),LatestResourceEventsSnapshot(List()),0,0,IMStateSnapshot(StdIMEvent(,1320098400000,1320098400000,CKKL,,true,user,1.0,create,Map())),CreditSnapshot(0.0),AgreementHistory(List(AgreementHistoryItem(default, 2011-11-01 00:00:00.000, 292278994-08-17 07:12:55.807))),OwnedResourcesSnapshot(List()),List(),1320098400000,MonthlyBillingCalculation(2011-12),0,Some(4fa7e12ba0eee3db73fbe8d0),4fa7e12ba0eee3db73fbe8d0)
+DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - doFullMonthBilling(2011-12) RETURN UserState(true,CKKL,1320098400000,2,false,null,ImplicitlyIssuedResourceEventsSnapshot(List()),List(),List(),LatestResourceEventsSnapshot(List()),0,0,IMStateSnapshot(StdIMEvent(,1320098400000,1320098400000,CKKL,,true,user,1.0,create,Map())),CreditSnapshot(0.0),AgreementHistory(List(AgreementHistoryItem(default, 2011-11-01 00:00:00.000, 292278994-08-17 07:12:55.807))),OwnedResourcesSnapshot(List()),List(),1320098400000,MonthlyBillingCalculation(2011-12),0,Some(4fa7e12ba0eee3db73fbe8d0),4fa7e12ba0eee3db73fbe8d0)
+DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - doFullMonthBilling(2011-12) END
DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - …ndUserStateAtEndOfBillingMonth(2011-12) END
DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - walletEntriesForResourceEvent(0) +++ [EVENT(0, [2012-01-01 00:00:00], 0.0, vmtime::VM.1, Map(), CKKL, synnefo)] +++
DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - walletEntriesForResourceEvent(0) Cost policy OnOffCostPolicy for DSLResource(vmtime,Hr,OnOffCostPolicy,true,instanceId)
DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - walletEntriesForResourceEvent(0) PreviousM None
DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - walletEntriesForResourceEvent(0) Ignoring first event of its kind EVENT(0, [2012-01-01 00:00:00], 0.0, vmtime::VM.1, Map(), CKKL, synnefo)
DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - walletEntriesForResourceEvent(0) --- [EVENT(0, [2012-01-01 00:00:00], 0.0, vmtime::VM.1, Map(), CKKL, synnefo)] ---
-DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - doFullMonthlyBilling(2012-01) calculationReason = MonthlyBillingCalculation(2012-01)
-DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - doFullMonthlyBilling(2012-01) Saved [_id=4fa7e12ba0eee3db73fbe8d0] UserState(true,CKKL,1320098400000,3,false,null,ImplicitlyIssuedResourceEventsSnapshot(List()),List(),List(),LatestResourceEventsSnapshot(List(StdResourceEvent(0,1325368800000,1325368800000,CKKL,synnefo,vmtime,VM.1,0.0,1.0,Map()))),0,0,IMStateSnapshot(StdIMEvent(,1320098400000,1320098400000,CKKL,,true,user,1.0,create,Map())),CreditSnapshot(0.0),AgreementHistory(List(AgreementHistoryItem(default, 2011-11-01 00:00:00.000, 292278994-08-17 07:12:55.807))),OwnedResourcesSnapshot(List()),List(),1320098400000,MonthlyBillingCalculation(2012-01),0,Some(4fa7e12ba0eee3db73fbe8d0),4fa7e12ba0eee3db73fbe8d0)
-DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - doFullMonthlyBilling(2012-01) RETURN UserState(true,CKKL,1320098400000,3,false,null,ImplicitlyIssuedResourceEventsSnapshot(List()),List(),List(),LatestResourceEventsSnapshot(List(StdResourceEvent(0,1325368800000,1325368800000,CKKL,synnefo,vmtime,VM.1,0.0,1.0,Map()))),0,0,IMStateSnapshot(StdIMEvent(,1320098400000,1320098400000,CKKL,,true,user,1.0,create,Map())),CreditSnapshot(0.0),AgreementHistory(List(AgreementHistoryItem(default, 2011-11-01 00:00:00.000, 292278994-08-17 07:12:55.807))),OwnedResourcesSnapshot(List()),List(),1320098400000,MonthlyBillingCalculation(2012-01),0,Some(4fa7e12ba0eee3db73fbe8d0),4fa7e12ba0eee3db73fbe8d0)
-DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - doFullMonthlyBilling(2012-01) END
+DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - doFullMonthBilling(2012-01) calculationReason = MonthlyBillingCalculation(2012-01)
+DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - doFullMonthBilling(2012-01) Saved [_id=4fa7e12ba0eee3db73fbe8d0] UserState(true,CKKL,1320098400000,3,false,null,ImplicitlyIssuedResourceEventsSnapshot(List()),List(),List(),LatestResourceEventsSnapshot(List(StdResourceEvent(0,1325368800000,1325368800000,CKKL,synnefo,vmtime,VM.1,0.0,1.0,Map()))),0,0,IMStateSnapshot(StdIMEvent(,1320098400000,1320098400000,CKKL,,true,user,1.0,create,Map())),CreditSnapshot(0.0),AgreementHistory(List(AgreementHistoryItem(default, 2011-11-01 00:00:00.000, 292278994-08-17 07:12:55.807))),OwnedResourcesSnapshot(List()),List(),1320098400000,MonthlyBillingCalculation(2012-01),0,Some(4fa7e12ba0eee3db73fbe8d0),4fa7e12ba0eee3db73fbe8d0)
+DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - doFullMonthBilling(2012-01) RETURN UserState(true,CKKL,1320098400000,3,false,null,ImplicitlyIssuedResourceEventsSnapshot(List()),List(),List(),LatestResourceEventsSnapshot(List(StdResourceEvent(0,1325368800000,1325368800000,CKKL,synnefo,vmtime,VM.1,0.0,1.0,Map()))),0,0,IMStateSnapshot(StdIMEvent(,1320098400000,1320098400000,CKKL,,true,user,1.0,create,Map())),CreditSnapshot(0.0),AgreementHistory(List(AgreementHistoryItem(default, 2011-11-01 00:00:00.000, 292278994-08-17 07:12:55.807))),OwnedResourcesSnapshot(List()),List(),1320098400000,MonthlyBillingCalculation(2012-01),0,Some(4fa7e12ba0eee3db73fbe8d0),4fa7e12ba0eee3db73fbe8d0)
+DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - doFullMonthBilling(2012-01) END
DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - testOrphanOFF() _id = 4fa7e12ba0eee3db73fbe8d0
DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - testOrphanOFF() parentId = Some(4fa7e12ba0eee3db73fbe8d0)
DEBUG 17:50:19 g.g.a.user.UserStateComputationsTest - testOrphanOFF() credits = 0.0
import gr.grnet.aquarium.AquariumException
import gr.grnet.aquarium.Aquarium.{Instance ⇒ AquariumInstance}
import gr.grnet.aquarium.computation.reason.{NoSpecificChangeReason, MonthlyBillingCalculation}
-import gr.grnet.aquarium.computation.{TimeslotComputations, UserStateBootstrappingData, UserState, BillingMonthInfo}
-import gr.grnet.aquarium.util.date.{TimeHelpers, MutableDateCalc}
+import gr.grnet.aquarium.util.date.MutableDateCalc
+import gr.grnet.aquarium.computation.BillingMonthInfo
+import gr.grnet.aquarium.computation.state.{UserStateBootstrap, UserState}
/**
// initialAgreement = DSLAgreement.DefaultAgreementName
// )
- val UserStateBootstrap = UserStateBootstrappingData(
+ val UserStateBootstrapper = UserStateBootstrap(
userID = UserCKKL.userID,
userCreationMillis = UserCreationDate.getTime(),
initialRole = "default",
def doFullMonthlyBilling(
clog: ContextualLogger,
billingMonthInfo: BillingMonthInfo,
- isFullBillingMonthState: Boolean,
billingTimeMillis: Long) = {
- Computations.doBillingForMonth(
- UserStateBootstrap,
+ Computations.doMonthBillingUpTo(
billingMonthInfo,
- isFullBillingMonthState,
billingTimeMillis,
+ UserStateBootstrapper,
DefaultResourcesMap,
MonthlyBillingCalculation(NoSpecificChangeReason(), billingMonthInfo),
+ aquarium.userStateStore.insertUserState,
Some(clog)
)
}
private[this]
- def expectCredits(clog: ContextualLogger,
- creditsConsumed: Double,
- userState: UserState,
- accuracy: Double = 0.001): Unit = {
+ def expectCredits(
+ clog: ContextualLogger,
+ creditsConsumed: Double,
+ userState: UserState,
+ accuracy: Double = 0.001
+ ): Unit = {
+
val computed = userState.totalCredits
Assert.assertEquals(-creditsConsumed, computed, accuracy)
+
clog.info("Consumed %.3f credits [accuracy = %f]", creditsConsumed, accuracy)
}
showResourceEvents(clog)
- val userState = doFullMonthlyBilling(clog, BillingMonthInfoJan, false, TimeHelpers.nowMillis())
+ val userState = doFullMonthlyBilling(clog, BillingMonthInfoJan, BillingMonthInfoJan.monthStopMillis)
showUserState(clog, userState)
showResourceEvents(clog)
- val userState = doFullMonthlyBilling(clog, BillingMonthInfoJan, false, TimeHelpers.nowMillis())
+ val userState = doFullMonthlyBilling(clog, BillingMonthInfoJan, BillingMonthInfoJan.monthStopMillis)
showUserState(clog, userState)
showResourceEvents(clog)
- val userState = doFullMonthlyBilling(clog, BillingMonthInfoJan, false, TimeHelpers.nowMillis())
+ val userState = doFullMonthlyBilling(clog, BillingMonthInfoJan, BillingMonthInfoJan.monthStopMillis)
showUserState(clog, userState)
clog.debugMap("DefaultResourcesMap", DefaultResourcesMap.map, 1)
- val userState = doFullMonthlyBilling(clog, BillingMonthInfoJan, false, TimeHelpers.nowMillis())
+ val userState = doFullMonthlyBilling(clog, BillingMonthInfoJan, BillingMonthInfoJan.monthStopMillis)
showUserState(clog, userState)