"resourceTypes":[
{
+ "name":"addcredits",
+ "unit":"credits",
+ "chargingBehavior":"gr.grnet.aquarium.charging.OnceChargingBehavior"
+ },
+ {
"name":"bandwidth",
"unit":"MB/Hr",
"chargingBehavior":"gr.grnet.aquarium.charging.DiscreteChargingBehavior"
}
]
}
+ "addcredits":{
+ "priceOverrides":[
+ {
+ "unitPrice":1
+ }
+ ]
+ }
}
}
}
-}
\ No newline at end of file
+}
import gr.grnet.aquarium.charging.state.{WorkingAgreementHistory, WorkingUserState, UserStateModel}
import gr.grnet.aquarium.charging.reason.{InitialUserActorSetup, RealtimeChargingReason}
import gr.grnet.aquarium.policy.{PolicyDefinedFullPriceTableRef, StdUserAgreement}
-import gr.grnet.aquarium.event.model.resource.ResourceEventModel
+import gr.grnet.aquarium.event.model.resource.{StdResourceEvent, ResourceEventModel}
import message.GetUserBalanceRequest
import message.GetUserBalanceResponse
import message.GetUserBalanceResponseData
//this._latestIMEventID = imEvent.id
return
}
+ if(imEvent.isAddCredits) {
+ if(!hadUserCreationIMEvent && haveUserCreationIMEvent)
+ loadWorkingUserStateAndUpdateAgreementHistory()
+ onHandleAddCreditsEvent(imEvent)
+ } else {
updateAgreementHistoryFrom(imEvent)
updateLatestIMEventIDFrom(imEvent)
+ }
}
// Must also update user state if we know when in history the life of a user begins
logSeparator()
}
+ /* Convert astakos message for adding credits
+ to a regular RESOURCE message */
+ def onHandleAddCreditsEvent(imEvent : IMEventModel) = {
+ val credits = -imEvent.details(IMEventModel.DetailsNames.credits).toInt.toDouble
+ val event = new StdResourceEvent(
+ imEvent.id,
+ imEvent.occurredMillis,
+ imEvent.receivedMillis,
+ imEvent.userID,
+ imEvent.clientID,
+ imEvent.eventType,
+ imEvent.eventType,
+ credits,
+ imEvent.eventVersion,
+ imEvent.details
+ )
+ //Console.err.println("Event: " + event)
+ //Console.err.println("Total credits before: " + _workingUserState.totalCredits)
+ onProcessResourceEvent(new ProcessResourceEvent(event))
+ //Console.err.println("Total credits after: " + _workingUserState.totalCredits)
+ //Console.err.println("OK.")
+ }
+
def onProcessResourceEvent(event: ProcessResourceEvent): Unit = {
val rcEvent = event.rcEvent
else {
computeBatch()
}
- if(oldTotalCredits * this._workingUserState.totalCredits < 0)
+ var newTotal = this._workingUserState.totalCredits
+ if(oldTotalCredits * newTotal < 0)
aquarium.eventBus ! new BalanceEvent(this._workingUserState.userID,
- this._workingUserState.totalCredits>=0)
+ newTotal>=0)
DEBUG("Updated %s", this._workingUserState)
logSeparator()
}
package gr.grnet.aquarium.connector.rabbitmq
-import conf.RabbitMQConsumerConf
-import conf.RabbitMQConsumerConf
import conf.{RabbitMQKeys, RabbitMQConsumerConf}
import conf.RabbitMQKeys.{RabbitMQConfKeys, RabbitMQConKeys}
import gr.grnet.aquarium._
import com.rabbitmq.client._
-import java.util.concurrent.atomic.{AtomicBoolean, AtomicReference}
import com.ckkloverdos.props.Props
import gr.grnet.aquarium.converter.StdConverters
-import gr.grnet.aquarium.util.{Lock, Tags}
+import gr.grnet.aquarium.util.Lock
import gr.grnet.aquarium.store.memory.MemStoreProvider
import java.io.File
import com.ckkloverdos.resource.FileStreamResource
import scala.Some
-import collection.immutable.{TreeMap, SortedSet, TreeSet}
-import java.util.Collections
+import collection.immutable.{TreeMap, TreeSet}
/*
build()
aquarium(Aquarium.EnvKeys.rabbitMQProducer).sendMessage("Test string !!!!")
Console.err.println("Message sent")
- aquarium.stop()
+ //aquarium.start()
()
}
}
\ No newline at end of file
def isModifyUser = eventType.equalsIgnoreCase(IMEventModel.EventTypeNames.modify)
+ def isAddCredits = eventType.equalsIgnoreCase(IMEventModel.EventTypeNames.addcredits)
+
def userCreationMillisOption = if(isCreateUser) Some(this.occurredMillis) else None
override def toDebugString = {
trait EventTypeNamesT {
final val create = "create"
final val modify = "modify"
+ final val addcredits = "addcredits"
}
object EventTypeNames extends EventTypeNamesT
+
+ trait DetailsNamesT {
+ final val credits = "credits"
+ }
+ object DetailsNames extends DetailsNamesT
+
}
)
}
-}
+}
\ No newline at end of file
* contained in the timeslot are trimmed to this timeslot's
* start and end time.
*/
- def align(l: List[Timeslot]): List[Timeslot] = {
+ private[this] def align0(l: List[Timeslot]): List[Timeslot] = {
if (l.isEmpty) return List()
val result : Option[Timeslot] =
}
}
+ def align(l: List[Timeslot]): List[Timeslot] = {
+ Timeslot.mergeOverlaps(align0(l))
+ }
+
/* align a time slot in "bound_size" boundaries so that
* start0 <= start and end0 >= end */
def align(bound_size : Long) : Timeslot = {
logger.debug("%s %s %s".format(method, request.getProtocolVersion, uri))
type URIPF = PartialFunction[String, TFuture[THttpResponse]]
-
+ def pong(ok:Boolean) = {
+ val now = TimeHelpers.nowMillis()
+ val nowFormatted = ISODateTimeFormat.dateTime().print(now)
+ val reply = if(ok) "PONG" else "DOWN"
+ stringResponseOK("%s\n%s\n%s".format(reply,now, nowFormatted), TEXT_PLAIN)
+ }
val PingHandler: URIPF = {
- case RESTPaths.PingPath() ⇒
- val now = TimeHelpers.nowMillis()
- val nowFormatted = ISODateTimeFormat.dateTime().print(now)
- stringResponseOK("PONG\n%s\n%s".format(now, nowFormatted), TEXT_PLAIN)
+ case RESTPaths.AquariumPingPath() ⇒
+ pong(true)
+ case RESTPaths.RabbitMQPingPath() ⇒
+ pong(aquarium(Aquarium.EnvKeys.rabbitMQService).areConsumersLive)
+ case RESTPaths.IMStorePingPath() ⇒
+ pong(aquarium(Aquarium.EnvKeys.storeWatcherService).isIMAlive)
+ case RESTPaths.RCStorePingPath() ⇒
+ pong(aquarium(Aquarium.EnvKeys.storeWatcherService).isRCAlive)
}
val UserActorCacheHandler: URIPF = {
* @author Christos KK Loverdos <loverdos@gmail.com>.
*/
object RESTPaths {
- final val PingPath = "/ping".r
+ final val AquariumPingPath = "/ping/aquarium".r
+ final val RabbitMQPingPath = "/ping/rabbitmq".r
+ final val IMStorePingPath = "/ping/imstore".r
+ final val RCStorePingPath = "/ping/rcstore".r
final val AdminPrefix = "/admin"
}
}
+ def areConsumersLive() : Boolean = {
+ for(consumer ← this._consumers)
+ if(!consumer.isAlive()) return false
+ return true
+ }
+
+
def stop() = {
safeStop()
}
def propertyPrefix = Some(StoreProvider.Prefix)
+ def isRCAlive() : Boolean = _rcIsAlive.get
+ def isIMAlive() : Boolean = _imIsAlive.get
+
/**
* Configure this instance with the provided properties.
*