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}
}
if(haveAgreements) {
- DEBUG("Initial %s", this._workingAgreementHistory.toJsonString)
+ DEBUG("Initial agreement history %s", this._workingAgreementHistory.toJsonString)
logSeparator()
}
}
// 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)
}
}
loadWorkingUserStateAndUpdateAgreementHistory()
if(haveWorkingUserState) {
- DEBUG("Initial %s", this._workingUserState.toJsonString)
+ DEBUG("Initial working user state %s", this._workingUserState.toJsonString)
logSeparator()
}
}
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
}
/**
- * 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.
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}
* 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.
}
/**
- * 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] = {
object AgreementHistory {
final val Empty = AgreementHistory(Nil)
- def initial(userAgreement: UserAgreementModel): AgreementHistory ={
+ def initial(userAgreement: UserAgreementModel): AgreementHistory = {
AgreementHistory(userAgreement :: Nil)
}
}
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
* 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 <loverdos@gmail.com>
*/
case class UserStateBootstrap(
- userID: String,
+ userID: String,
userCreationMillis: Long,
- initialAgreement: UserAgreementModel,
- initialCredits: Double
+ initialAgreement: UserAgreementModel,
+ initialCredits: Double
)
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
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
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
/**
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 <loverdos@gmail.com>
*/
+++ /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.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 <loverdos@gmail.com>
- */
-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
- )
- }
-}
+++ /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
-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 <loverdos@gmail.com>
- */
-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
- )
- }
-}
+++ /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
-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 <loverdos@gmail.com>
- */
-
-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))
- }
-}
+++ /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
-package state
-package parts
-
-import gr.grnet.aquarium.event.model.resource.ResourceEventModel
-
-/**
- *
- * @author Christos KK Loverdos <loverdos@gmail.com>
- */
-
-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)
- }
-}
+++ /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
-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 <loverdos@gmail.com>
- */
-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
+++ /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
-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 <loverdos@gmail.com>
- */
-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)
-}
-
+++ /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
-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 <loverdos@gmail.com>
- */
-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
+++ /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
-package state
-package parts
-
-import gr.grnet.aquarium.event.model.resource.ResourceEventModel
-
-/**
- * Keeps the latest resource event per resource instance.
- *
- *
- * @author Christos KK Loverdos <loverdos@gmail.com>
- */
-
-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)
-}
+++ /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
-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 <loverdos@gmail.com>
- */
-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
- }
-}
-
+++ /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
-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 <loverdos@gmail.com>
- */
-
-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
+++ /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
-package state
-package parts
-
-/**
- *
- * @author Christos KK Loverdos <loverdos@gmail.com>
- */
-
-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
+++ /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
-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 <loverdos@gmail.com>
- */
-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
-}
+++ /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.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 <loverdos@gmail.com>
- */
-
-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)
- }
-}
+++ /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.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 <loverdos@gmail.com>
- */
-
-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))
-}
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
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
/**
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)
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"
}
}
- 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
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
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