From 77ea8fd035b427f8a799ed8bdb1502418cea1e33 Mon Sep 17 00:00:00 2001 From: Christos KK Loverdos Date: Thu, 19 Jul 2012 21:19:58 +0300 Subject: [PATCH] Slash'em high --- .../aquarium/actor/service/user/UserActor.scala | 8 +- .../grnet/aquarium/charging/ChargingBehavior.scala | 7 +- .../grnet/aquarium/charging/ChargingService.scala | 2 +- .../state}/AgreementHistory.scala | 15 +- .../aquarium/charging/state/StdUserState.scala | 2 - .../state/UserStateBootstrap.scala | 10 +- .../aquarium/charging/state/UserStateModel.scala | 4 +- .../charging/state/WorkingAgreementHistory.scala | 1 - .../aquarium/charging/state/WorkingUserState.scala | 7 +- .../aquarium/computation/state/UserState.scala | 298 -------------------- .../computation/state/UserStateWorker.scala | 199 ------------- .../computation/state/parts/IMStateSnapshot.scala | 185 ------------ .../parts/IgnoredFirstResourceEventsSnapshot.scala | 56 ---- .../parts/IgnoredFirstResourceEventsWorker.scala | 69 ----- .../ImplicitlyIssuedResourceEventsSnapshot.scala | 67 ----- .../ImplicitlyIssuedResourceEventsWorker.scala | 72 ----- .../state/parts/LatestResourceEventsSnapshot.scala | 77 ----- .../state/parts/LatestResourceEventsWorker.scala | 91 ------ .../state/parts/OwnedResourcesMap.scala | 57 ---- .../state/parts/OwnedResourcesSnapshot.scala | 95 ------- .../state/parts/ResourceInstanceAmount.scala | 73 ----- .../computation/state/parts/RoleHistory.scala | 152 ---------- .../computation/state/parts/RoleHistoryItem.scala | 90 ------ .../aquarium/store/mongodb/MongoDBStore.scala | 37 +-- .../aquarium/store/mongodb/MongoDBUserState.scala | 3 +- .../aquarium/user/UserStateComputationsTest.scala | 3 +- 26 files changed, 30 insertions(+), 1650 deletions(-) rename src/main/scala/gr/grnet/aquarium/{computation/state/parts => charging/state}/AgreementHistory.scala (88%) rename src/main/scala/gr/grnet/aquarium/{computation => charging}/state/UserStateBootstrap.scala (88%) delete mode 100644 src/main/scala/gr/grnet/aquarium/computation/state/UserState.scala delete mode 100644 src/main/scala/gr/grnet/aquarium/computation/state/UserStateWorker.scala delete mode 100644 src/main/scala/gr/grnet/aquarium/computation/state/parts/IMStateSnapshot.scala delete mode 100644 src/main/scala/gr/grnet/aquarium/computation/state/parts/IgnoredFirstResourceEventsSnapshot.scala delete mode 100644 src/main/scala/gr/grnet/aquarium/computation/state/parts/IgnoredFirstResourceEventsWorker.scala delete mode 100644 src/main/scala/gr/grnet/aquarium/computation/state/parts/ImplicitlyIssuedResourceEventsSnapshot.scala delete mode 100644 src/main/scala/gr/grnet/aquarium/computation/state/parts/ImplicitlyIssuedResourceEventsWorker.scala delete mode 100644 src/main/scala/gr/grnet/aquarium/computation/state/parts/LatestResourceEventsSnapshot.scala delete mode 100644 src/main/scala/gr/grnet/aquarium/computation/state/parts/LatestResourceEventsWorker.scala delete mode 100644 src/main/scala/gr/grnet/aquarium/computation/state/parts/OwnedResourcesMap.scala delete mode 100644 src/main/scala/gr/grnet/aquarium/computation/state/parts/OwnedResourcesSnapshot.scala delete mode 100644 src/main/scala/gr/grnet/aquarium/computation/state/parts/ResourceInstanceAmount.scala delete mode 100644 src/main/scala/gr/grnet/aquarium/computation/state/parts/RoleHistory.scala delete mode 100644 src/main/scala/gr/grnet/aquarium/computation/state/parts/RoleHistoryItem.scala diff --git a/src/main/scala/gr/grnet/aquarium/actor/service/user/UserActor.scala b/src/main/scala/gr/grnet/aquarium/actor/service/user/UserActor.scala index 7769783..46f5824 100644 --- a/src/main/scala/gr/grnet/aquarium/actor/service/user/UserActor.scala +++ b/src/main/scala/gr/grnet/aquarium/actor/service/user/UserActor.scala @@ -47,7 +47,7 @@ import gr.grnet.aquarium.actor.message.{GetUserStateResponse, GetUserBalanceResp import gr.grnet.aquarium.util.{LogHelpers, shortClassNameOf} import gr.grnet.aquarium.AquariumInternalError import gr.grnet.aquarium.computation.BillingMonthInfo -import gr.grnet.aquarium.computation.state.UserStateBootstrap +import gr.grnet.aquarium.charging.state.UserStateBootstrap import gr.grnet.aquarium.charging.state.{WorkingAgreementHistory, WorkingUserState, UserStateModel} import gr.grnet.aquarium.charging.reason.{InitialUserActorSetup, RealtimeChargingReason} import gr.grnet.aquarium.policy.{PolicyDefinedFullPriceTableRef, StdUserAgreement} @@ -170,7 +170,7 @@ class UserActor extends ReflectiveRoleableActor { } if(haveAgreements) { - DEBUG("Initial %s", this._workingAgreementHistory.toJsonString) + DEBUG("Initial agreement history %s", this._workingAgreementHistory.toJsonString) logSeparator() } } @@ -216,7 +216,7 @@ class UserActor extends ReflectiveRoleableActor { // state this._workingAgreementHistory is always the authoritative source. if(haveWorkingUserState) { this._workingUserState.workingAgreementHistory.setFrom(this._workingAgreementHistory) - DEBUG("Computed %s", this._workingUserState.toJsonString) + DEBUG("Computed working user state %s", this._workingUserState.toJsonString) } } @@ -235,7 +235,7 @@ class UserActor extends ReflectiveRoleableActor { loadWorkingUserStateAndUpdateAgreementHistory() if(haveWorkingUserState) { - DEBUG("Initial %s", this._workingUserState.toJsonString) + DEBUG("Initial working user state %s", this._workingUserState.toJsonString) logSeparator() } } diff --git a/src/main/scala/gr/grnet/aquarium/charging/ChargingBehavior.scala b/src/main/scala/gr/grnet/aquarium/charging/ChargingBehavior.scala index 605aa72..462a750 100644 --- a/src/main/scala/gr/grnet/aquarium/charging/ChargingBehavior.scala +++ b/src/main/scala/gr/grnet/aquarium/charging/ChargingBehavior.scala @@ -46,7 +46,7 @@ import gr.grnet.aquarium.util._ import gr.grnet.aquarium.util.date.TimeHelpers import gr.grnet.aquarium.charging.wallet.WalletEntry import gr.grnet.aquarium.computation.{TimeslotComputations, BillingMonthInfo} -import gr.grnet.aquarium.computation.state.parts.AgreementHistory +import gr.grnet.aquarium.charging.state.AgreementHistory import gr.grnet.aquarium.logic.accounting.dsl.Timeslot import gr.grnet.aquarium.store.PolicyStore import gr.grnet.aquarium.charging.ChargingBehavior.EnvKeys @@ -425,9 +425,8 @@ abstract class ChargingBehavior(val alias: String, val inputs: Set[ChargingInput } /** - * Given the old amount of a resource instance - * (see [[gr.grnet.aquarium.computation.state.parts.ResourceInstanceAmount]]), the - * value arriving in a new resource event and the new details, compute the new instance amount. + * Given the old amount of a resource instance, the value arriving in a new resource event and the new details, + * compute the new instance amount. * * Note that the `oldAmount` does not make sense for all types of [[gr.grnet.aquarium.charging.ChargingBehavior]], * in which case it is ignored. diff --git a/src/main/scala/gr/grnet/aquarium/charging/ChargingService.scala b/src/main/scala/gr/grnet/aquarium/charging/ChargingService.scala index 33e1457..7491669 100644 --- a/src/main/scala/gr/grnet/aquarium/charging/ChargingService.scala +++ b/src/main/scala/gr/grnet/aquarium/charging/ChargingService.scala @@ -37,7 +37,7 @@ package gr.grnet.aquarium.charging import gr.grnet.aquarium.event.model.resource.ResourceEventModel import gr.grnet.aquarium.computation.BillingMonthInfo -import gr.grnet.aquarium.computation.state.UserStateBootstrap +import gr.grnet.aquarium.charging.state.UserStateBootstrap import gr.grnet.aquarium.policy.ResourceType import gr.grnet.aquarium.util.{Lifecycle, Loggable, ContextualLogger} import gr.grnet.aquarium.util.date.{MutableDateCalc, TimeHelpers} diff --git a/src/main/scala/gr/grnet/aquarium/computation/state/parts/AgreementHistory.scala b/src/main/scala/gr/grnet/aquarium/charging/state/AgreementHistory.scala similarity index 88% rename from src/main/scala/gr/grnet/aquarium/computation/state/parts/AgreementHistory.scala rename to src/main/scala/gr/grnet/aquarium/charging/state/AgreementHistory.scala index 369e8d5..96b2a48 100644 --- a/src/main/scala/gr/grnet/aquarium/computation/state/parts/AgreementHistory.scala +++ b/src/main/scala/gr/grnet/aquarium/charging/state/AgreementHistory.scala @@ -33,14 +33,11 @@ * or implied, of GRNET S.A. */ -package gr.grnet.aquarium.computation -package state -package parts +package gr.grnet.aquarium.charging.state import scala.collection.immutable import gr.grnet.aquarium.logic.accounting.dsl.Timeslot import gr.grnet.aquarium.policy.UserAgreementModel -import gr.grnet.aquarium.charging.state.WorkingAgreementHistory /** * The whole history of of a user's agreements. @@ -58,14 +55,6 @@ case class AgreementHistory(agreements: List[UserAgreementModel]) { } /** - * Get the user agreement at the specified timestamp - */ - def findForTime(at: Long): Option[UserAgreementModel] = { - // FIXME: Refactor and do not make this static call to Policy - None - } - - /** * Returns the first, chronologically, agreement. */ def firstAgreement: Option[UserAgreementModel] = { @@ -83,7 +72,7 @@ case class AgreementHistory(agreements: List[UserAgreementModel]) { object AgreementHistory { final val Empty = AgreementHistory(Nil) - def initial(userAgreement: UserAgreementModel): AgreementHistory ={ + def initial(userAgreement: UserAgreementModel): AgreementHistory = { AgreementHistory(userAgreement :: Nil) } } diff --git a/src/main/scala/gr/grnet/aquarium/charging/state/StdUserState.scala b/src/main/scala/gr/grnet/aquarium/charging/state/StdUserState.scala index 0b065c8..990c446 100644 --- a/src/main/scala/gr/grnet/aquarium/charging/state/StdUserState.scala +++ b/src/main/scala/gr/grnet/aquarium/charging/state/StdUserState.scala @@ -36,11 +36,9 @@ package gr.grnet.aquarium.charging.state import scala.collection.mutable -import gr.grnet.aquarium.computation.state.UserStateBootstrap import gr.grnet.aquarium.policy.{ResourceType, UserAgreementModel} import gr.grnet.aquarium.computation.BillingMonthInfo import gr.grnet.aquarium.event.model.resource.ResourceEventModel -import gr.grnet.aquarium.computation.state.parts.{ResourceInstanceAmount, AgreementHistory} import gr.grnet.aquarium.charging.wallet.WalletEntry import gr.grnet.aquarium.charging.reason.{InitialUserStateSetup, ChargingReason} import gr.grnet.aquarium.AquariumInternalError diff --git a/src/main/scala/gr/grnet/aquarium/computation/state/UserStateBootstrap.scala b/src/main/scala/gr/grnet/aquarium/charging/state/UserStateBootstrap.scala similarity index 88% rename from src/main/scala/gr/grnet/aquarium/computation/state/UserStateBootstrap.scala rename to src/main/scala/gr/grnet/aquarium/charging/state/UserStateBootstrap.scala index 7401e91..f0888b8 100644 --- a/src/main/scala/gr/grnet/aquarium/computation/state/UserStateBootstrap.scala +++ b/src/main/scala/gr/grnet/aquarium/charging/state/UserStateBootstrap.scala @@ -33,19 +33,19 @@ * or implied, of GRNET S.A. */ -package gr.grnet.aquarium.computation.state +package gr.grnet.aquarium.charging.state import gr.grnet.aquarium.policy.UserAgreementModel /** - * This is used to bootstrap the [[gr.grnet.aquarium.computation.state.UserState]]. + * This is used to bootstrap the [[gr.grnet.aquarium.charging.state.UserStateModel]]. * * @author Christos KK Loverdos */ case class UserStateBootstrap( - userID: String, + userID: String, userCreationMillis: Long, - initialAgreement: UserAgreementModel, - initialCredits: Double + initialAgreement: UserAgreementModel, + initialCredits: Double ) diff --git a/src/main/scala/gr/grnet/aquarium/charging/state/UserStateModel.scala b/src/main/scala/gr/grnet/aquarium/charging/state/UserStateModel.scala index 90187e3..a5c40fc 100644 --- a/src/main/scala/gr/grnet/aquarium/charging/state/UserStateModel.scala +++ b/src/main/scala/gr/grnet/aquarium/charging/state/UserStateModel.scala @@ -38,7 +38,6 @@ package gr.grnet.aquarium.charging.state import gr.grnet.aquarium.util.json.JsonSupport import gr.grnet.aquarium.computation.BillingMonthInfo import gr.grnet.aquarium.event.model.resource.ResourceEventModel -import gr.grnet.aquarium.computation.state.parts.{ResourceInstanceAmount, AgreementHistory} import gr.grnet.aquarium.charging.wallet.WalletEntry import gr.grnet.aquarium.charging.reason.ChargingReason import gr.grnet.aquarium.policy.ResourceType @@ -87,6 +86,9 @@ trait UserStateModel extends JsonSupport { object UserStateModel { trait NamesT { final val userID = "userID" + final val occurredMillis = "occurredMillis" + final val theFullBillingMonth_year = "theFullBillingMonth.year" + final val theFullBillingMonth_month = "theFullBillingMonth.month" } object Names extends NamesT diff --git a/src/main/scala/gr/grnet/aquarium/charging/state/WorkingAgreementHistory.scala b/src/main/scala/gr/grnet/aquarium/charging/state/WorkingAgreementHistory.scala index a397796..2039a25 100644 --- a/src/main/scala/gr/grnet/aquarium/charging/state/WorkingAgreementHistory.scala +++ b/src/main/scala/gr/grnet/aquarium/charging/state/WorkingAgreementHistory.scala @@ -37,7 +37,6 @@ package gr.grnet.aquarium.charging.state import scala.collection.immutable import gr.grnet.aquarium.policy.{PolicyDefinedFullPriceTableRef, StdUserAgreement, UserAgreementModel} -import gr.grnet.aquarium.computation.state.parts.AgreementHistory import gr.grnet.aquarium.util.json.JsonSupport /** diff --git a/src/main/scala/gr/grnet/aquarium/charging/state/WorkingUserState.scala b/src/main/scala/gr/grnet/aquarium/charging/state/WorkingUserState.scala index 8230faf..90d8083 100644 --- a/src/main/scala/gr/grnet/aquarium/charging/state/WorkingUserState.scala +++ b/src/main/scala/gr/grnet/aquarium/charging/state/WorkingUserState.scala @@ -36,19 +36,16 @@ package gr.grnet.aquarium.charging.state import scala.collection.mutable -import scala.collection.immutable -import gr.grnet.aquarium.policy.{UserAgreementModel, ResourceType} +import gr.grnet.aquarium.policy.ResourceType import gr.grnet.aquarium.event.model.resource.ResourceEventModel import gr.grnet.aquarium.computation.BillingMonthInfo import gr.grnet.aquarium.charging.reason.ChargingReason import gr.grnet.aquarium.util.json.JsonSupport import gr.grnet.aquarium.charging.ChargingBehavior import gr.grnet.aquarium.charging.wallet.WalletEntry -import gr.grnet.aquarium.computation.state.parts.AgreementHistory /** - * A mutable view of the [[gr.grnet.aquarium.computation.state.UserState]], so that intermediate computations are a - * bit more memory friendly (and probably faster). + * A mutable view of the [[gr.grnet.aquarium.charging.state.UserStateModel]]. * * @author Christos KK Loverdos */ diff --git a/src/main/scala/gr/grnet/aquarium/computation/state/UserState.scala b/src/main/scala/gr/grnet/aquarium/computation/state/UserState.scala deleted file mode 100644 index 00b6d25..0000000 --- a/src/main/scala/gr/grnet/aquarium/computation/state/UserState.scala +++ /dev/null @@ -1,298 +0,0 @@ -/* - * 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.state - -import gr.grnet.aquarium.converter.{JsonTextFormat, StdConverters} -import gr.grnet.aquarium.charging.wallet.WalletEntry -import gr.grnet.aquarium.util.json.JsonSupport -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, ResourceInstanceAmount, OwnedResourcesSnapshot, AgreementHistory, ImplicitlyIssuedResourceEventsSnapshot, LatestResourceEventsSnapshot} -import gr.grnet.aquarium.policy.UserAgreementModel -import gr.grnet.aquarium.charging.reason.{InitialUserStateSetup, NoSpecificChargingReason, ChargingReason} - -/** - * A comprehensive representation of the User's state. - * - * 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. - * - * - * @param userID - * The user ID. $communicatedByIM - * @param userCreationMillis - * When the user was created. - * $communicatedByIM - * Set to zero if unknown. - * @param stateChangeCounter - * @param isFullBillingMonthState - * @param theFullBillingMonth - * @param implicitlyIssuedSnapshot - * @param latestResourceEventsSnapshot - * @param billingPeriodOutOfSyncResourceEventsCounter - * @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.charging.reason.ChargingReason]] 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. - * @param _id - * The unique `ID` given by the store. - * - * @author Christos KK Loverdos - */ -case class UserState( - isInitial: Boolean, - userID: String, - - userCreationMillis: Long, - - /** - * Each time the user state is updated, this must be increased. - * The counter is used when accessing user state from the cache (user state store) - * in order to get the latest value for a particular billing period. - */ - stateChangeCounter: Long, - - /** - * True iff this user state refers to a full billing period, that is a full billing month. - */ - isFullBillingMonthState: Boolean, - - /** - * The full billing period for which this user state refers to. - * This is set when the user state refers to a full billing period (= month) - * and is used to cache the user state for subsequent queries. - */ - theFullBillingMonth: Option[BillingMonthInfo], - - /** - * If this is a state for a full billing month, then keep here the implicit OFF - * resource events or any other whose cost policy demands an implicit event at the end of the billing period. - * - * The use case is this: A VM may have been started (ON state) before the end of the billing period - * and ended (OFF state) after the beginning of the next billing period. In order to bill this, we must assume - * an implicit OFF even right at the end of the billing period and an implicit ON event with the beginning of the - * next billing period. - */ - implicitlyIssuedSnapshot: ImplicitlyIssuedResourceEventsSnapshot, - - /** - * The latest (previous) resource events per resource instance. - */ - latestResourceEventsSnapshot: LatestResourceEventsSnapshot, - - /** - * The out of sync events used to produce this user state for - * the billing period recorded by `billingPeriodSnapshot` - */ - billingPeriodOutOfSyncResourceEventsCounter: Long, - - totalCredits: Double, - - roleHistory: RoleHistory, - - agreementHistory: AgreementHistory, - - ownedResourcesSnapshot: OwnedResourcesSnapshot, - - newWalletEntries: List[WalletEntry], - - occurredMillis: Long, // When this user state was computed - - // The last known change reason for this userState - lastChangeReason: ChargingReason = NoSpecificChargingReason(), - // The user state we used to compute this one. Normally the (cached) - // state at the beginning of the billing period. - parentUserStateIDInStore: Option[String] = None, - _id: String = null -) extends JsonSupport { - - def idInStore: Option[String] = _id match { - case null ⇒ None - case _id ⇒ Some(_id.toString) - } - - // def userCreationDate = new Date(userCreationMillis) - // - // def userCreationFormatedDate = new MutableDateCalc(userCreationMillis).toString - - def findDSLAgreementForTime(at: Long): Option[UserAgreementModel] = { - agreementHistory.findForTime(at) - } - - def findResourceInstanceSnapshot(resource: String, instanceId: String): Option[ResourceInstanceAmount] = { - ownedResourcesSnapshot.findResourceInstanceSnapshot(resource, instanceId) - } - - def getResourceInstanceAmount(resource: String, instanceId: String, defaultValue: Double): Double = { - ownedResourcesSnapshot.getResourceInstanceAmount(resource, instanceId, defaultValue) - } - - def newWithResourcesSnapshotUpdate(resource: String, // resource name - instanceId: String, // resource instance id - newAmount: Double, - snapshotTime: Long): UserState = { - - val (newResources, _, _) = - ownedResourcesSnapshot.computeResourcesSnapshotUpdate(resource, instanceId, newAmount, snapshotTime) - - this.copy( - isInitial = false, - ownedResourcesSnapshot = newResources, - stateChangeCounter = this.stateChangeCounter + 1 - ) - } - - def newWithChangeReason(changeReason: ChargingReason) = { - this.copy( - isInitial = false, - lastChangeReason = changeReason, - stateChangeCounter = this.stateChangeCounter + 1 - ) - } - - def newWithRoleHistory(newRoleHistory: RoleHistory, changeReason: ChargingReason) = { - // FIXME: Also update agreement - this.copy( - isInitial = false, - stateChangeCounter = this.stateChangeCounter + 1, - roleHistory = newRoleHistory, - lastChangeReason = changeReason - ) - } - - def resourcesMap: OwnedResourcesMap = { - ownedResourcesSnapshot.toResourcesMap - } - - def findLatestResourceEvent: Option[ResourceEventModel] = { - latestResourceEventsSnapshot.findTheLatest - } - - def findLatestResourceEventID: Option[String] = { - latestResourceEventsSnapshot.findTheLatestID - } - - def isLatestResourceEventIDEqualTo(toCheckID: String) = { - findLatestResourceEventID.map(_ == toCheckID).getOrElse(false) - } - - // def toShortString = "UserState(%s, %s, %s, %s, %s)".format( - // userId, - // _id, - // parentUserStateId, - // totalEventsProcessedCounter, - // calculationReason) -} - -object UserState { - def fromJson(json: String): UserState = { - StdConverters.AllConverters.convertEx[UserState](JsonTextFormat(json)) - } - - object JsonNames { - 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 month = "month" - } - - } - - def createInitialUserState( - userID: String, - userCreationMillis: Long, - occurredMillis: Long, - totalCredits: Double, - initialAgreement: UserAgreementModel, - calculationReason: ChargingReason = InitialUserStateSetup(None) - ) = { - - UserState( - true, - userID, - userCreationMillis, - 0L, - false, - None, - ImplicitlyIssuedResourceEventsSnapshot.Empty, - LatestResourceEventsSnapshot.Empty, - 0L, - totalCredits, - RoleHistory.initial(initialAgreement.role, userCreationMillis), - AgreementHistory.initial(initialAgreement), - OwnedResourcesSnapshot.Empty, - Nil, - occurredMillis, - calculationReason - ) - } - - def createInitialUserStateFromBootstrap( - usb: UserStateBootstrap, - occurredMillis: Long, - calculationReason: ChargingReason - ): UserState = { - - createInitialUserState( - usb.userID, - usb.userCreationMillis, - occurredMillis, - usb.initialCredits, - usb.initialAgreement, - calculationReason - ) - } -} diff --git a/src/main/scala/gr/grnet/aquarium/computation/state/UserStateWorker.scala b/src/main/scala/gr/grnet/aquarium/computation/state/UserStateWorker.scala deleted file mode 100644 index 1b072c5..0000000 --- a/src/main/scala/gr/grnet/aquarium/computation/state/UserStateWorker.scala +++ /dev/null @@ -1,199 +0,0 @@ -/* - * 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 -package state - -import scala.collection.mutable -import gr.grnet.aquarium.util.ContextualLogger -import gr.grnet.aquarium.event.model.resource.ResourceEventModel -import gr.grnet.aquarium.computation.state.parts.{IgnoredFirstResourceEventsWorker, ImplicitlyIssuedResourceEventsWorker, LatestResourceEventsWorker} -import gr.grnet.aquarium.policy.ResourceType -import gr.grnet.aquarium.Aquarium - -/** - * A helper object holding intermediate state/results during resource event processing. - * - * @author Christos KK Loverdos - */ -case class UserStateWorker( - userID: String, - - /** - * This is a collection of all the latest resource events. - * We want these in order to correlate incoming resource events with their previous (in `occurredMillis` time) - * ones. Will be updated on processing the next resource event. - */ - previousResourceEvents: LatestResourceEventsWorker, - - /** - * The implicitly issued resource events at the beginning of the billing period. - */ - implicitlyIssuedStartEvents: ImplicitlyIssuedResourceEventsWorker, - - /** - * The resource events that were first (and unused) of their kind. - */ - ignoredFirstResourceEvents: IgnoredFirstResourceEventsWorker, - resourceTypesMap: Map[String, ResourceType] -) { - - /** - * Finds the previous resource event by checking two possible sources: a) The implicitly terminated resource - * events and b) the explicit previous resource events. If the event is found, it is removed from the - * respective source. - * - * If the event is not found, then this must be for a new resource instance. - * (and probably then some `zero` resource event must be implied as the previous one) - * - * @param resource - * @param instanceId - * @return - */ - def findAndRemovePreviousResourceEvent(resource: String, instanceId: String): Option[ResourceEventModel] = { - // implicitly issued events are checked first - implicitlyIssuedStartEvents.findAndRemoveResourceEvent(resource, instanceId) match { - case some@Some(_) ⇒ - some - case None ⇒ - // explicit previous resource events are checked second - previousResourceEvents.findAndRemoveResourceEvent(resource, instanceId) match { - case some@Some(_) ⇒ - some - case _ ⇒ - None - } - } - } - - def updateIgnored(resourceEvent: ResourceEventModel): Unit = { - ignoredFirstResourceEvents.updateResourceEvent(resourceEvent) - } - - def updatePrevious(resourceEvent: ResourceEventModel): Unit = { - previousResourceEvents.updateResourceEvent(resourceEvent) - } - - def debugTheMaps(clog: ContextualLogger)(rcDebugInfo: ResourceEventModel ⇒ String): Unit = { - if(previousResourceEvents.size > 0) { - val map = previousResourceEvents.latestEventsMap.map { - case (k, v) => (k, rcDebugInfo(v)) - } - clog.debugMap("previousResourceEvents", map, 0) - } - if(implicitlyIssuedStartEvents.size > 0) { - val map = implicitlyIssuedStartEvents.implicitlyIssuedEventsMap.map { - case (k, v) => (k, rcDebugInfo(v)) - } - clog.debugMap("implicitlyTerminatedResourceEvents", map, 0) - } - if(ignoredFirstResourceEvents.size > 0) { - val map = ignoredFirstResourceEvents.ignoredFirstEventsMap.map { - case (k, v) => (k, rcDebugInfo(v)) - } - clog.debugMap("ignoredFirstResourceEvents", map, 0) - } - } - - // private[this] - // def allPreviousAndAllImplicitlyStarted: List[ResourceEvent] = { - // val buffer: FullMutableResourceTypeMap = scala.collection.mutable.Map[FullResourceType, ResourceEvent]() - // - // buffer ++= implicitlyIssuedStartEvents.implicitlyIssuedEventsMap - // buffer ++= previousResourceEvents.latestEventsMap - // - // buffer.valuesIterator.toList - // } - - /** - * Find those events from `implicitlyIssuedStartEvents` and `previousResourceEvents` that will generate implicit - * end events along with those implicitly issued events. Before returning, remove the events that generated the - * implicit ends from the internal state of this instance. - * - * @see [[gr.grnet.aquarium.charging.ChargingBehavior]] - */ - def findAndRemoveGeneratorsOfImplicitEndEvents( - aquarium: Aquarium, - /** - * 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]) = { - - val buffer = mutable.ListBuffer[(ResourceEventModel, ResourceEventModel)]() - val checkSet = mutable.Set[ResourceEventModel]() - - def doItFor(map: ResourceEventModel.FullMutableResourceTypeMap): Unit = { - val resourceEvents = map.valuesIterator - for { - resourceEvent ← resourceEvents - resourceType ← resourceTypesMap.get(resourceEvent.safeResource) - chargingBehavior = aquarium.chargingBehaviorOf(resourceType) - } { - if(chargingBehavior.supportsImplicitEvents) { - if(chargingBehavior.mustConstructImplicitEndEventFor(resourceEvent)) { - val implicitEnd = chargingBehavior.constructImplicitEndEventFor(resourceEvent, newOccuredMillis) - - if(!checkSet.contains(resourceEvent)) { - checkSet.add(resourceEvent) - buffer append ((resourceEvent, implicitEnd)) - } - - // remove it anyway - map.remove((resourceEvent.safeResource, resourceEvent.safeInstanceID)) - } - } - } - } - - doItFor(previousResourceEvents.latestEventsMap) // we give priority for previous - doItFor(implicitlyIssuedStartEvents.implicitlyIssuedEventsMap) // ... over implicitly issued... - - (buffer.view.map(_._1).toList, buffer.view.map(_._2).toList) - } -} - -object UserStateWorker { - def fromUserState(userState: UserState, resourceTypesMap: Map[String, ResourceType]): UserStateWorker = { - UserStateWorker( - userState.userID, - userState.latestResourceEventsSnapshot.toMutableWorker, - userState.implicitlyIssuedSnapshot.toMutableWorker, - IgnoredFirstResourceEventsWorker.Empty, - resourceTypesMap - ) - } -} diff --git a/src/main/scala/gr/grnet/aquarium/computation/state/parts/IMStateSnapshot.scala b/src/main/scala/gr/grnet/aquarium/computation/state/parts/IMStateSnapshot.scala deleted file mode 100644 index b4d3193..0000000 --- a/src/main/scala/gr/grnet/aquarium/computation/state/parts/IMStateSnapshot.scala +++ /dev/null @@ -1,185 +0,0 @@ -/* - * 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 -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 -import gr.grnet.aquarium.util.json.JsonSupport - -/** - * - * @author Christos KK Loverdos - */ - -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 -) extends JsonSupport { - - /** - * True iff the user has ever been activated even once. - */ - def hasBeenActivated: Boolean = { - userEarliestActivationMillis.isDefined - } - - def hasBeenCreated: Boolean = { - userCreationMillis.isDefined - } - - /** - * Given the newly arrived event, we compute the updated user earliest activation time, if any. - * We always update activation time if it is earlier than the currently known activation time. - */ - private[this] def updatedEarliestActivationTime(imEvent: IMEventModel): Option[Long] = { - this.userEarliestActivationMillis match { - case Some(activationMillis) if imEvent.isStateActive && activationMillis < imEvent.occurredMillis ⇒ - Some(imEvent.occurredMillis) - - case None if imEvent.isStateActive ⇒ - Some(imEvent.occurredMillis) - - case other ⇒ - other - } - } - - /** - * Given the newly arrived event, we compute the updated user creation time, if any. - * Only the first `create` event triggers an actual update. - */ - private[this] def updatedCreationTime(imEvent: IMEventModel): Option[Long] = { - // Allow only the first `create` event - if(this.userCreationMillis.isDefined) { - this.userCreationMillis - } else if(imEvent.isCreateUser) { - Some(imEvent.occurredMillis) - } else { - None - } - } - - /** - * Given the newly arrived event, we compute the updated role history. - */ - private[this] def updatedRoleHistory(imEvent: IMEventModel): RoleHistory = { - this.roleHistory.updatedWithRole(imEvent.role, imEvent.occurredMillis) - } - - /** - * Computes an updated state and returns a tuple made of four elements: - * a) the updated state, b) a `Boolean` indicating whether the user creation - * time has changed, c) a `Boolean` indicating whether the user activation - * time has changed and d) a `Boolean` indicating whether the user - * role history has changed. - * - * The role history is updated only if the `roleCheck` is not `None` and - * the role it represents is different than the role of the `imEvent`. - * The motivation for `roleCheck` is to use this method in a loop (as in replaying - * events from the [[gr.grnet.aquarium.store.IMEventStore]]). - */ - def updatedWithEvent(imEvent: IMEventModel, - roleCheck: Option[String]): (IMStateSnapshot, Boolean, Boolean, Boolean) = { - // Things of interest that may change by the imEvent: - // - user creation time - // - user activation time - // - user role - - val newCreationTime = updatedCreationTime(imEvent) - val creationTimeChanged = this.userCreationMillis != newCreationTime - - val newActivationTime = updatedEarliestActivationTime(imEvent) - val activationTimeChanged = this.userEarliestActivationMillis != newActivationTime - - val (roleChanged, newRoleHistory) = roleCheck match { - case Some(role) if role != imEvent.role ⇒ - (true, updatedRoleHistory(imEvent)) - - case _ ⇒ - (false, this.roleHistory) - } - - val newState = this.copy( - latestIMEvent = imEvent, - userCreationMillis = newCreationTime, - userEarliestActivationMillis = newActivationTime, - roleHistory = newRoleHistory - ) - - (newState, creationTimeChanged, activationTimeChanged, roleChanged) - } - - override def toString = { - "%s(\n!! %s\n!! %s\n!! %s\n!! %s)".format( - shortClassNameOf(this), - latestIMEvent, - userCreationMillis.map(new MutableDateCalc(_)), - userEarliestActivationMillis.map(new MutableDateCalc(_)), - roleHistory - ) - } -} - -object IMStateSnapshot { - def initial(imEvent: IMEventModel): IMStateSnapshot = { - IMStateSnapshot( - imEvent, - if(imEvent.isStateActive) Some(imEvent.occurredMillis) else None, - if(imEvent.isCreateUser) Some(imEvent.occurredMillis) else None, - RoleHistory.initial(imEvent.role, imEvent.occurredMillis)) - } -} diff --git a/src/main/scala/gr/grnet/aquarium/computation/state/parts/IgnoredFirstResourceEventsSnapshot.scala b/src/main/scala/gr/grnet/aquarium/computation/state/parts/IgnoredFirstResourceEventsSnapshot.scala deleted file mode 100644 index 285a80e..0000000 --- a/src/main/scala/gr/grnet/aquarium/computation/state/parts/IgnoredFirstResourceEventsSnapshot.scala +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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 -package state -package parts - -import gr.grnet.aquarium.event.model.resource.ResourceEventModel - -/** - * - * @author Christos KK Loverdos - */ - -case class IgnoredFirstResourceEventsSnapshot(ignoredFirstEvents: List[ResourceEventModel]) { - def toMutableWorker = { - val map = scala.collection.mutable.Map[ResourceEventModel.ResourceInstance, ResourceEventModel]() - for(ignoredFirstEvent <- ignoredFirstEvents) { - map(ignoredFirstEvent.safeResourceInstanceInfo) = ignoredFirstEvent - } - - IgnoredFirstResourceEventsWorker(map) - } -} diff --git a/src/main/scala/gr/grnet/aquarium/computation/state/parts/IgnoredFirstResourceEventsWorker.scala b/src/main/scala/gr/grnet/aquarium/computation/state/parts/IgnoredFirstResourceEventsWorker.scala deleted file mode 100644 index aaede1a..0000000 --- a/src/main/scala/gr/grnet/aquarium/computation/state/parts/IgnoredFirstResourceEventsWorker.scala +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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 -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 - -/** - * - * @author Christos KK Loverdos - */ -case class IgnoredFirstResourceEventsWorker(ignoredFirstEventsMap: FullMutableResourceTypeMap) { - def toImmutableSnapshot(snapshotTime: Long) = - IgnoredFirstResourceEventsSnapshot(ignoredFirstEventsMap.valuesIterator.toList) - - def findAndRemoveResourceEvent(resource: String, instanceId: String): Option[ResourceEventModel] = { - findAndRemoveFromMap(ignoredFirstEventsMap, (resource, instanceId)) - } - - def updateResourceEvent(resourceEvent: ResourceEventModel): Unit = { - ignoredFirstEventsMap((resourceEvent.resource, resourceEvent.instanceID)) = resourceEvent - } - - def size = ignoredFirstEventsMap.size - - def foreach[U](f: ResourceEventModel ⇒ U): Unit = { - ignoredFirstEventsMap.valuesIterator.foreach(f) - } -} - -object IgnoredFirstResourceEventsWorker { - final val Empty = IgnoredFirstResourceEventsWorker(scala.collection.mutable.Map()) -} \ No newline at end of file diff --git a/src/main/scala/gr/grnet/aquarium/computation/state/parts/ImplicitlyIssuedResourceEventsSnapshot.scala b/src/main/scala/gr/grnet/aquarium/computation/state/parts/ImplicitlyIssuedResourceEventsSnapshot.scala deleted file mode 100644 index 124e320..0000000 --- a/src/main/scala/gr/grnet/aquarium/computation/state/parts/ImplicitlyIssuedResourceEventsSnapshot.scala +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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 -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.state.UserState]]. - * - * @author Christos KK Loverdos - */ -case class ImplicitlyIssuedResourceEventsSnapshot(implicitlyIssuedEvents: List[ResourceEventModel]) { - /** - * The gateway to playing with mutable state. - * - * @return A fresh instance of [[gr.grnet.aquarium.computation.state.parts.ImplicitlyIssuedResourceEventsWorker]]. - */ - def toMutableWorker = { - val map = scala.collection.mutable.Map[ResourceEventModel.ResourceInstance, ResourceEventModel]() - for(implicitEvent <- implicitlyIssuedEvents) { - map(implicitEvent.safeResourceInstanceInfo) = implicitEvent - } - - ImplicitlyIssuedResourceEventsWorker(map) - } -} - -object ImplicitlyIssuedResourceEventsSnapshot { - final val Empty = ImplicitlyIssuedResourceEventsSnapshot(Nil) -} - diff --git a/src/main/scala/gr/grnet/aquarium/computation/state/parts/ImplicitlyIssuedResourceEventsWorker.scala b/src/main/scala/gr/grnet/aquarium/computation/state/parts/ImplicitlyIssuedResourceEventsWorker.scala deleted file mode 100644 index 0c67c9f..0000000 --- a/src/main/scala/gr/grnet/aquarium/computation/state/parts/ImplicitlyIssuedResourceEventsWorker.scala +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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 -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.state.parts.ImplicitlyIssuedResourceEventsSnapshot]]. - * - * @author Christos KK Loverdos - */ -case class ImplicitlyIssuedResourceEventsWorker(implicitlyIssuedEventsMap: FullMutableResourceTypeMap) { - - def toList: scala.List[ResourceEventModel] = { - implicitlyIssuedEventsMap.valuesIterator.toList - } - - def toImmutableSnapshot(snapshotTime: Long) = - ImplicitlyIssuedResourceEventsSnapshot(toList) - - def findAndRemoveResourceEvent(resource: String, instanceId: String): Option[ResourceEventModel] = { - findAndRemoveFromMap(implicitlyIssuedEventsMap, (resource, instanceId)) - } - - def size = implicitlyIssuedEventsMap.size - - def foreach[U](f: ResourceEventModel => U): Unit = { - implicitlyIssuedEventsMap.valuesIterator.foreach(f) - } -} - -object ImplicitlyIssuedResourceEventsWorker { - final val Empty = ImplicitlyIssuedResourceEventsWorker(scala.collection.mutable.Map()) -} \ No newline at end of file diff --git a/src/main/scala/gr/grnet/aquarium/computation/state/parts/LatestResourceEventsSnapshot.scala b/src/main/scala/gr/grnet/aquarium/computation/state/parts/LatestResourceEventsSnapshot.scala deleted file mode 100644 index eaaebfa..0000000 --- a/src/main/scala/gr/grnet/aquarium/computation/state/parts/LatestResourceEventsSnapshot.scala +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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 -package state -package parts - -import gr.grnet.aquarium.event.model.resource.ResourceEventModel - -/** - * Keeps the latest resource event per resource instance. - * - * - * @author Christos KK Loverdos - */ - -case class LatestResourceEventsSnapshot(resourceEvents: List[ResourceEventModel]) { - - /** - * The gateway to playing with mutable state. - * - * @return A fresh instance of [[gr.grnet.aquarium.computation.state.parts.LatestResourceEventsWorker]]. - */ - def toMutableWorker = { - val map = scala.collection.mutable.Map[ResourceEventModel.ResourceInstance, ResourceEventModel]() - for(latestEvent <- resourceEvents) { - map(latestEvent.safeResourceInstanceInfo) = latestEvent - } - LatestResourceEventsWorker(map) - } - - def findTheLatest: Option[ResourceEventModel] = { - resourceEvents.sortWith { - case (ev1, ev2) ⇒ ev1.occurredMillis <= ev2.occurredMillis - }.headOption - } - - def findTheLatestID = { - findTheLatest.map(_.id) - } -} - -object LatestResourceEventsSnapshot { - final val Empty = LatestResourceEventsSnapshot(Nil) -} diff --git a/src/main/scala/gr/grnet/aquarium/computation/state/parts/LatestResourceEventsWorker.scala b/src/main/scala/gr/grnet/aquarium/computation/state/parts/LatestResourceEventsWorker.scala deleted file mode 100644 index fa3594c..0000000 --- a/src/main/scala/gr/grnet/aquarium/computation/state/parts/LatestResourceEventsWorker.scala +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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 -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.state.parts.LatestResourceEventsSnapshot]]. - * - * @param latestEventsMap - * - * @author Christos KK Loverdos - */ -case class LatestResourceEventsWorker(latestEventsMap: FullMutableResourceTypeMap) { - - /** - * The gateway to immutable state. - * - * @param snapshotTime The relevant snapshot time. - * @return A fresh instance of [[gr.grnet.aquarium.computation.state.parts.LatestResourceEventsSnapshot]]. - */ - def toImmutableSnapshot(snapshotTime: Long) = - LatestResourceEventsSnapshot(latestEventsMap.valuesIterator.toList) - - def updateResourceEvent(resourceEvent: ResourceEventModel): Unit = { - latestEventsMap((resourceEvent.resource, resourceEvent.instanceID)) = resourceEvent - } - - def findResourceEvent(resource: String, instanceId: String): Option[ResourceEventModel] = { - latestEventsMap.get((resource, instanceId)) - } - - def findAndRemoveResourceEvent(resource: String, instanceId: String): Option[ResourceEventModel] = { - findAndRemoveFromMap(latestEventsMap, (resource, instanceId)) - } - - def size = latestEventsMap.size - - def foreach[U](f: ResourceEventModel => U): Unit = { - latestEventsMap.valuesIterator.foreach(f) - } -} - -object LatestResourceEventsWorker { - final val Empty = LatestResourceEventsWorker(scala.collection.mutable.Map()) - - /** - * Helper factory to construct a worker from a list of events. - */ - def fromList(latestEventsList: List[ResourceEventModel]): LatestResourceEventsWorker = { - LatestResourceEventsSnapshot(latestEventsList).toMutableWorker - } -} - diff --git a/src/main/scala/gr/grnet/aquarium/computation/state/parts/OwnedResourcesMap.scala b/src/main/scala/gr/grnet/aquarium/computation/state/parts/OwnedResourcesMap.scala deleted file mode 100644 index bc91fe6..0000000 --- a/src/main/scala/gr/grnet/aquarium/computation/state/parts/OwnedResourcesMap.scala +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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 -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.state.parts.OwnedResourcesSnapshot]] representation is convenient for JSON - * serialization. - * - * @author Christos KK Loverdos - */ - -class OwnedResourcesMap(resourcesMap: Map[(String, String), Double]) { - def toResourcesSnapshot(snapshotTime: Long): OwnedResourcesSnapshot = - OwnedResourcesSnapshot( - resourcesMap map { - case ((name, instanceId), value) ⇒ - ResourceInstanceAmount(name, instanceId, value) } toList - ) -} \ No newline at end of file diff --git a/src/main/scala/gr/grnet/aquarium/computation/state/parts/OwnedResourcesSnapshot.scala b/src/main/scala/gr/grnet/aquarium/computation/state/parts/OwnedResourcesSnapshot.scala deleted file mode 100644 index 6e024e5..0000000 --- a/src/main/scala/gr/grnet/aquarium/computation/state/parts/OwnedResourcesSnapshot.scala +++ /dev/null @@ -1,95 +0,0 @@ -/* - * 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 -package state -package parts - -/** - * - * @author Christos KK Loverdos - */ - -case class OwnedResourcesSnapshot(resourceInstanceSnapshots: List[ResourceInstanceAmount]) { - - def toResourcesMap: OwnedResourcesMap = { - val tuples = for(rc <- resourceInstanceSnapshots) yield ((rc.resource, rc.instanceID), (rc.instanceAmount)) - - new OwnedResourcesMap(Map(tuples.toSeq: _*)) - } - - def resourceInstanceSnapshotsExcept(resource: String, instanceId: String) = { - // 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)) - } - - def findResourceInstanceSnapshot(resource: String, instanceId: String): Option[ResourceInstanceAmount] = { - resourceInstanceSnapshots.find(x => resource == x.resource && instanceId == x.instanceID) - } - - def getResourceInstanceAmount(resource: String, instanceId: String, defaultValue: Double): Double = { - findResourceInstanceSnapshot(resource, instanceId).map(_.instanceAmount).getOrElse(defaultValue) - } - - def computeResourcesSnapshotUpdate(resource: String, // resource name - instanceId: String, // resource instance id - newAmount: Double, - snapshotTime: Long): (OwnedResourcesSnapshot, - Option[ResourceInstanceAmount], - ResourceInstanceAmount) = { - - val newResourceInstance = ResourceInstanceAmount(resource, instanceId, newAmount) - val oldResourceInstanceOpt = this.findResourceInstanceSnapshot(resource, instanceId) - - val newResourceInstances = oldResourceInstanceOpt match { - case Some(oldResourceInstance) ⇒ - // Resource instance found, so delete the old one and add the new one - newResourceInstance :: resourceInstanceSnapshotsExcept(resource, instanceId) - - case None ⇒ - // Resource not found, so this is the first time and we just add the new snapshot - newResourceInstance :: resourceInstanceSnapshots - } - - val newOwnedResources = OwnedResourcesSnapshot(newResourceInstances) - - (newOwnedResources, oldResourceInstanceOpt, newResourceInstance) - } -} - -object OwnedResourcesSnapshot { - final val Empty = OwnedResourcesSnapshot(Nil) -} \ No newline at end of file diff --git a/src/main/scala/gr/grnet/aquarium/computation/state/parts/ResourceInstanceAmount.scala b/src/main/scala/gr/grnet/aquarium/computation/state/parts/ResourceInstanceAmount.scala deleted file mode 100644 index 9e55145..0000000 --- a/src/main/scala/gr/grnet/aquarium/computation/state/parts/ResourceInstanceAmount.scala +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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 -package state -package parts - -/** - * Maintains the current state of a resource instance owned by the user. - * - * In order to have a uniform representation of the resource state for all - * resource types (complex or simple) the following convention applies: - * - * - 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.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.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.charging.ChargingBehavior]] - * - * @author Christos KK Loverdos - */ -case class ResourceInstanceAmount( - resource: String, - instanceID: String, - instanceAmount: Double -) { - - def isSameResourceInstance(resource: String, instanceId: String) = { - this.resource == resource && - this.instanceID == instanceId - } - - def toResourceInstanceAmountMapElement = (resource, instanceID) -> this -} diff --git a/src/main/scala/gr/grnet/aquarium/computation/state/parts/RoleHistory.scala b/src/main/scala/gr/grnet/aquarium/computation/state/parts/RoleHistory.scala deleted file mode 100644 index a7cd961..0000000 --- a/src/main/scala/gr/grnet/aquarium/computation/state/parts/RoleHistory.scala +++ /dev/null @@ -1,152 +0,0 @@ -/* - * 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.parts - -import gr.grnet.aquarium.logic.accounting.dsl.Timeslot -import scala.collection.immutable.{TreeMap, SortedMap} -import scala.collection.mutable.ListBuffer -import scala.annotation.tailrec - -/** - * - * @author Christos KK Loverdos - */ - -case class RoleHistory( - /** - * 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)): _*) - } - - def rolesByTimeslot: SortedMap[Timeslot, RoleHistoryItem] = { - TreeMap(roles.map(role ⇒ (role.timeslot, role)): _*) - } - - def updatedWithRole(role: String, validFrom: Long) = { - // TODO: Review this when Timeslot is also reviewed. - // Currently, we need `fixValidTo` because Timeslot does not validate when `validFrom` and `validTo` - // are equal. - def fixValidTo(validFrom: Long, validTo: Long): Long = { - if(validTo == validFrom) { - // Since validTo is exclusive, make at least 1ms gap - validFrom + 1 - } else { - validTo - } - } - - val newItems = roles match { - case Nil ⇒ - RoleHistoryItem(role, validFrom) :: Nil - - case head :: tail ⇒ - if(head.startsStrictlyAfter(validFrom)) { - // must search history items to find where this fits in - @tailrec - def check(allChecked: ListBuffer[RoleHistoryItem], - lastCheck: RoleHistoryItem, - toCheck: List[RoleHistoryItem]): List[RoleHistoryItem] = { - - toCheck match { - case Nil ⇒ - allChecked.append(RoleHistoryItem(role, validFrom, fixValidTo(validFrom, lastCheck.validFrom))) - allChecked.toList - - case toCheckHead :: toCheckTail ⇒ - if(toCheckHead.startsStrictlyAfter(validFrom)) { - allChecked.append(toCheckHead) - - check(allChecked, toCheckHead, toCheckTail) - } else { - allChecked.append(RoleHistoryItem(role, validFrom, fixValidTo(validFrom, lastCheck.validFrom))) - allChecked.toList - } - } - } - - val buffer = new ListBuffer[RoleHistoryItem] - buffer.append(head) - check(buffer, head, tail) - } else { - // assume head.validTo goes to infinity, - RoleHistoryItem(role, validFrom) :: head.copyWithValidTo(fixValidTo(head.validFrom, validFrom)) :: tail - } - } - - RoleHistory(newItems) - } - - /** - * Returns the first, chronologically, role. - */ - def firstRole: Option[RoleHistoryItem] = { - rolesByTimeslot.valuesIterator.toList.headOption - } - - /** - * Returns the name of the first, chronologically, role. - */ - def firstRoleName: Option[String] = { - roleNamesByTimeslot.valuesIterator.toList.headOption - } - - /** - * Returns the last, chronologically, role. - */ - def lastRole: Option[RoleHistoryItem] = { - rolesByTimeslot.valuesIterator.toList.lastOption - } - - /** - * Returns the name of the last, chronologically, role. - */ - def lastRoleName: Option[String] = { - roleNamesByTimeslot.valuesIterator.toList.lastOption - } -} - -object RoleHistory { - final val Empty = RoleHistory(Nil) - - def initial(role: String, validFrom: Long): RoleHistory = { - RoleHistory(RoleHistoryItem(role, validFrom) :: Nil) - } -} diff --git a/src/main/scala/gr/grnet/aquarium/computation/state/parts/RoleHistoryItem.scala b/src/main/scala/gr/grnet/aquarium/computation/state/parts/RoleHistoryItem.scala deleted file mode 100644 index 59d2344..0000000 --- a/src/main/scala/gr/grnet/aquarium/computation/state/parts/RoleHistoryItem.scala +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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.parts - -import gr.grnet.aquarium.util.date.MutableDateCalc -import gr.grnet.aquarium.logic.accounting.dsl.Timeslot -import gr.grnet.aquarium.Aquarium - -/** - * - * @author Christos KK Loverdos - */ - -case class RoleHistoryItem( - /** - * The role name. - */ - name: String, - - /** - * Validity start time for this role. The time is inclusive. - */ - validFrom: Long, - - /** - * Validity stop time for this role. The time is exclusive. - */ - validTo: Long = Long.MaxValue -) { - require( - validFrom <= validTo, - "validFrom(%s) <= validTo(%s)".format(new MutableDateCalc(validFrom), new MutableDateCalc(validTo))) - - require(name ne null, "Name is not null") - - require(!name.trim.isEmpty, "Name '%s' is not empty".format(name)) - - def timeslot = Timeslot(validFrom, validTo) - - def copyWithValidTo(newValidTo: Long) = copy(validTo = newValidTo) - - def isUpperBounded = { - validTo != Long.MaxValue - } - - def contains(time: Long) = { - validFrom <= time && time < validTo - } - - def startsStrictlyAfter(time: Long) = { - validFrom > time - } - - override def toString = - "RoleHistoryItem(%s, [%s, %s))". - format(name, new MutableDateCalc(validFrom), new MutableDateCalc(validTo)) -} diff --git a/src/main/scala/gr/grnet/aquarium/store/mongodb/MongoDBStore.scala b/src/main/scala/gr/grnet/aquarium/store/mongodb/MongoDBStore.scala index 97595a4..630457c 100644 --- a/src/main/scala/gr/grnet/aquarium/store/mongodb/MongoDBStore.scala +++ b/src/main/scala/gr/grnet/aquarium/store/mongodb/MongoDBStore.scala @@ -47,7 +47,6 @@ import com.mongodb._ import org.bson.types.ObjectId import gr.grnet.aquarium.util._ import gr.grnet.aquarium.converter.StdConverters -import gr.grnet.aquarium.computation.state.UserState import gr.grnet.aquarium.event.model.ExternalEventModel import gr.grnet.aquarium.computation.BillingMonthInfo import gr.grnet.aquarium.policy.PolicyModel @@ -55,7 +54,6 @@ import gr.grnet.aquarium.{Aquarium, AquariumException} import collection.immutable.SortedMap import gr.grnet.aquarium.logic.accounting.dsl.Timeslot import collection.immutable -import java.util.Date import gr.grnet.aquarium.charging.state.UserStateModel /** @@ -184,14 +182,14 @@ class MongoDBStore( 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, bmi.year). - add(UserState.JsonNames.theFullBillingMonth_month, bmi.month). + add(UserStateModel.Names.userID, userID). +// add(UserStateModel.Names.isFullBillingMonthState, true). FIXME + add(UserStateModel.Names.theFullBillingMonth_year, bmi.year). + add(UserStateModel.Names.theFullBillingMonth_month, bmi.month). get() // Descending order, so that the latest comes first - val sorter = new BasicDBObject(UserState.JsonNames.occurredMillis, -1) + val sorter = new BasicDBObject(UserStateModel.Names.occurredMillis, -1) val cursor = userStates.find(query).sort(sorter) @@ -317,10 +315,10 @@ object MongoDBStore { final val RESOURCE_EVENTS_COLLECTION = "resevents" /** - * Collection holding the snapshots of [[gr.grnet.aquarium.computation.state.UserState]]. + * Collection holding the snapshots of [[gr.grnet.aquarium.charging.state.UserStateModel]]. * - * [[gr.grnet.aquarium.computation.state.UserState]] is held internally within - * [[gr.grnet.aquarium.actor.service.user .UserActor]]s. + * [[gr.grnet.aquarium.charging.state.UserStateModel]] is held internally within + * [[gr.grnet.aquarium.actor.service.user.UserActor]]s. */ final val USER_STATES_COLLECTION = "userstates" @@ -399,25 +397,6 @@ object MongoDBStore { } } - def storeUserState(userState: UserState, collection: DBCollection) = { - storeAny[UserState](userState, collection, ResourceEventNames.userID, _.userID, MongoDBStore.jsonSupportToDBObject) - } - - def storeAny[A](any: A, - collection: DBCollection, - idName: String, - idValueProvider: (A) => String, - serializer: (A) => DBObject) : RecordID = { - - val dbObject = serializer apply any - val _id = new ObjectId() - dbObject.put("_id", _id) - val writeResult = collection.insert(dbObject, WriteConcern.JOURNAL_SAFE) - writeResult.getLastError().throwOnError() - - RecordID(dbObject.get("_id").toString) - } - def insertObject[A <: AnyRef](obj: A, collection: DBCollection, serializer: A ⇒ DBObject) : A = { collection.insert(serializer apply obj, WriteConcern.JOURNAL_SAFE) obj diff --git a/src/main/scala/gr/grnet/aquarium/store/mongodb/MongoDBUserState.scala b/src/main/scala/gr/grnet/aquarium/store/mongodb/MongoDBUserState.scala index 23f14e7..a1de9a6 100644 --- a/src/main/scala/gr/grnet/aquarium/store/mongodb/MongoDBUserState.scala +++ b/src/main/scala/gr/grnet/aquarium/store/mongodb/MongoDBUserState.scala @@ -35,11 +35,10 @@ package gr.grnet.aquarium.store.mongodb -import gr.grnet.aquarium.charging.state.{WorkingUserState, UserStateModel} +import gr.grnet.aquarium.charging.state.{AgreementHistory, WorkingUserState, UserStateModel} import gr.grnet.aquarium.computation.BillingMonthInfo import gr.grnet.aquarium.charging.reason.ChargingReason import gr.grnet.aquarium.event.model.resource.ResourceEventModel -import gr.grnet.aquarium.computation.state.parts.AgreementHistory import gr.grnet.aquarium.charging.wallet.WalletEntry import gr.grnet.aquarium.converter.{JsonTextFormat, StdConverters} import gr.grnet.aquarium.policy.ResourceType diff --git a/src/test/scala/gr/grnet/aquarium/user/UserStateComputationsTest.scala b/src/test/scala/gr/grnet/aquarium/user/UserStateComputationsTest.scala index dfd2957..2834534 100644 --- a/src/test/scala/gr/grnet/aquarium/user/UserStateComputationsTest.scala +++ b/src/test/scala/gr/grnet/aquarium/user/UserStateComputationsTest.scala @@ -44,11 +44,10 @@ import gr.grnet.aquarium.logic.accounting.algorithm.{ExecutableChargingBehaviorA import gr.grnet.aquarium.{Aquarium, ResourceLocator, AquariumBuilder, AquariumException} import gr.grnet.aquarium.util.date.MutableDateCalc import gr.grnet.aquarium.computation.BillingMonthInfo -import gr.grnet.aquarium.computation.state.UserState import gr.grnet.aquarium.charging._ import gr.grnet.aquarium.policy.{PolicyDefinedFullPriceTableRef, StdUserAgreement, EffectiveUnitPrice, EffectivePriceTable, FullPriceTable, ResourceType, StdPolicy, PolicyModel} import gr.grnet.aquarium.Timespan -import gr.grnet.aquarium.computation.state.UserStateBootstrap +import gr.grnet.aquarium.charging.state.UserStateBootstrap import gr.grnet.aquarium.charging.reason.{NoSpecificChargingReason, MonthlyBillChargingReason} import gr.grnet.aquarium.charging.state.WorkingUserState -- 1.7.10.4