From 7912b2e765c8dc3e320f55c9473c29ac6b4ee891 Mon Sep 17 00:00:00 2001 From: Christos KK Loverdos Date: Fri, 20 Apr 2012 15:29:50 +0300 Subject: [PATCH] WIP: Remodeling events --- .gitignore | 1 + .../gr/grnet/aquarium/events/AquariumEvent.scala | 13 +++-- .../grnet/aquarium/events/AquariumEventModel.scala | 59 ++++++++++++++++++++ .../scala/gr/grnet/aquarium/events/IMEvent.scala | 18 ++++-- .../gr/grnet/aquarium/events/IMEventModel.scala | 51 +++++++++++++++++ .../gr/grnet/aquarium/events/ResourceEvent.scala | 11 ++-- .../gr/grnet/aquarium/events/WalletEntry.scala | 2 + .../aquarium/simulation/ResourceInstanceSim.scala | 2 +- .../simulation/StdBandwidthInstanceSim.scala | 2 +- .../simulation/StdDiskspaceInstanceSim.scala | 8 +-- .../aquarium/simulation/StdVMTimeInstanceSim.scala | 6 +- .../aquarium/store/mongodb/MongoDBStore.scala | 7 ++- 12 files changed, 149 insertions(+), 31 deletions(-) create mode 100644 src/main/scala/gr/grnet/aquarium/events/AquariumEventModel.scala create mode 100644 src/main/scala/gr/grnet/aquarium/events/IMEventModel.scala diff --git a/.gitignore b/.gitignore index edaf413..d7a52a5 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,7 @@ doc/arch/aquarium.ent doc/arch/arch.texshop build.log _gitstats/ +_localrest *.aquarium.properties sshfs/ aquarium-dist/ diff --git a/src/main/scala/gr/grnet/aquarium/events/AquariumEvent.scala b/src/main/scala/gr/grnet/aquarium/events/AquariumEvent.scala index 96fb1e5..96076be 100644 --- a/src/main/scala/gr/grnet/aquarium/events/AquariumEvent.scala +++ b/src/main/scala/gr/grnet/aquarium/events/AquariumEvent.scala @@ -37,7 +37,6 @@ package gr.grnet.aquarium package events -import util.json.JsonSupport import util.xml.XmlSupport import util.Loggable @@ -51,7 +50,7 @@ abstract class AquariumEvent( val id: String, // The id at the client side (the sender) TODO: Rename to remoteId or something... val occurredMillis: Long, // When it occurred at client side (the sender) val receivedMillis: Long) // When it was received by Aquarium - extends JsonSupport + extends AquariumEventModel with XmlSupport with Loggable { @@ -61,9 +60,11 @@ abstract class AquariumEvent( toJson.getBytes("UTF-8") } - /** - * Return a new instance with all state the same as this one except for `receivedMillis`, which - * acquires the new value. - */ + def storeID: Option[AnyRef] = Some(id) + + def details: Map[String, String] = Map() + + def eventVersion = "1.0" + def copyWithReceivedMillis(receivedMillis: Long): AquariumEvent } diff --git a/src/main/scala/gr/grnet/aquarium/events/AquariumEventModel.scala b/src/main/scala/gr/grnet/aquarium/events/AquariumEventModel.scala new file mode 100644 index 0000000..5358bcd --- /dev/null +++ b/src/main/scala/gr/grnet/aquarium/events/AquariumEventModel.scala @@ -0,0 +1,59 @@ +/* + * 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.events + +import gr.grnet.aquarium.util.json.JsonSupport + +/** + * The base model for all events coming from external systems. + * + * @author Christos KK Loverdos + */ + +trait AquariumEventModel extends JsonSupport { + def id: String + def occurredMillis: Long + def receivedMillis: Long +// def userID: String + def eventVersion: String + def details: Map[String, String] + + /** + * The ID given to this event if/when persisted to a store. + * The exact type of the id is store-specific. + */ + def storeID: Option[AnyRef] +} diff --git a/src/main/scala/gr/grnet/aquarium/events/IMEvent.scala b/src/main/scala/gr/grnet/aquarium/events/IMEvent.scala index e729ed6..60478af 100644 --- a/src/main/scala/gr/grnet/aquarium/events/IMEvent.scala +++ b/src/main/scala/gr/grnet/aquarium/events/IMEvent.scala @@ -55,17 +55,25 @@ case class IMEvent( clientID: String, isActive: Boolean, role: String, - eventVersion: String, + override val eventVersion: String, eventType: String, - details: IMEvent.Details, - _id: AnyRef = new ObjectId()) - extends AquariumEvent(id, occurredMillis, receivedMillis) { + override val details: Map[String, String], + _id: ObjectId = new ObjectId()) + extends AquariumEvent(id, occurredMillis, receivedMillis) with IMEventModel { + // assert(eventType.equalsIgnoreCase(IMEvent.EventTypes.create) || // eventType.equalsIgnoreCase(IMEvent.EventTypes.modify)) // assert(!role.isEmpty) + override def storeID = { + _id match { + case null ⇒ None + case _ ⇒ Some(_id) + } + } + /** * Validate this event according to the following rules: * @@ -117,8 +125,6 @@ object IMEvent { val modify = "modify" } - type Details = Map[String, String] - def fromJson(json: String): IMEvent = { StdConverters.StdConverters.convertEx[IMEvent](JsonTextFormat(json)) } diff --git a/src/main/scala/gr/grnet/aquarium/events/IMEventModel.scala b/src/main/scala/gr/grnet/aquarium/events/IMEventModel.scala new file mode 100644 index 0000000..72bb1fa --- /dev/null +++ b/src/main/scala/gr/grnet/aquarium/events/IMEventModel.scala @@ -0,0 +1,51 @@ +/* + * 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.events + +/** + * The model of any event sent from the `Identity Management` (IM) external system. + * + * We use this to not reveal storage-specific stuff, like IDs. + * + * @author Christos KK Loverdos + */ + +trait IMEventModel extends AquariumEventModel { + def clientID: String + def isActive: Boolean + def role: String + def eventType: String +} diff --git a/src/main/scala/gr/grnet/aquarium/events/ResourceEvent.scala b/src/main/scala/gr/grnet/aquarium/events/ResourceEvent.scala index bc8da01..353facd 100644 --- a/src/main/scala/gr/grnet/aquarium/events/ResourceEvent.scala +++ b/src/main/scala/gr/grnet/aquarium/events/ResourceEvent.scala @@ -58,9 +58,9 @@ case class ResourceEvent( clientID: String, // The unique client identifier (usually some hash) resource: String, // String representation of the resource type (e.g. "bndup", "vmtime"). instanceID: String, // String representation of the resource instance id - eventVersion: String, + override val eventVersion: String, value: Double, - details: ResourceEvent.Details) + override val details: Map[String, String]) extends AquariumEvent(id, occurredMillis, receivedMillis) { def validate() : Boolean = { @@ -241,9 +241,6 @@ case class ResourceEvent( } object ResourceEvent { - type Details = Map[String, String] - final val EmptyDetails: Details = Map() - type ResourceType = String type ResourceIdType = String type FullResourceType = (ResourceType, ResourceIdType) @@ -258,11 +255,11 @@ object ResourceEvent { StdConverters.StdConverters.convertEx[ResourceEvent](JsonTextFormat(makeString(bytes))) } - def setAquariumSynthetic(map: ResourceEvent.Details): ResourceEvent.Details = { + def setAquariumSynthetic(map: Map[String, String]): Map[String, String] = { map.updated(JsonNames.details_aquarium_is_synthetic, "true") } - def setAquariumSyntheticAndImplicitEnd(map: ResourceEvent.Details): ResourceEvent.Details = { + def setAquariumSyntheticAndImplicitEnd(map: Map[String, String]): Map[String, String] = { map. updated(JsonNames.details_aquarium_is_synthetic, "true"). updated(JsonNames.details_aquarium_is_implicit_end, "true") diff --git a/src/main/scala/gr/grnet/aquarium/events/WalletEntry.scala b/src/main/scala/gr/grnet/aquarium/events/WalletEntry.scala index d9ca998..9453852 100644 --- a/src/main/scala/gr/grnet/aquarium/events/WalletEntry.scala +++ b/src/main/scala/gr/grnet/aquarium/events/WalletEntry.scala @@ -38,6 +38,7 @@ package events import java.util.Date import converter.{JsonTextFormat, StdConverters} +import util.json.JsonSupport /** * A WalletEntry is a derived entity. Its data represent money/credits and are calculated based on @@ -61,6 +62,7 @@ case class WalletEntry( finalized: Boolean) extends AquariumEvent(id, occurredMillis, receivedMillis) { + assert(occurredMillis > 0) assert(value >= 0F) assert(!userId.isEmpty) diff --git a/src/main/scala/gr/grnet/aquarium/simulation/ResourceInstanceSim.scala b/src/main/scala/gr/grnet/aquarium/simulation/ResourceInstanceSim.scala index 059668a..3866765 100644 --- a/src/main/scala/gr/grnet/aquarium/simulation/ResourceInstanceSim.scala +++ b/src/main/scala/gr/grnet/aquarium/simulation/ResourceInstanceSim.scala @@ -54,7 +54,7 @@ class ResourceInstanceSim (val resource: ResourceSim, def newResourceEvent(occurredMillis: Long, receivedMillis: Long, value: Double, - details: ResourceEvent.Details, + details: Map[String, String], eventVersion: String = "1.0") = { val event = ResourceEvent( diff --git a/src/main/scala/gr/grnet/aquarium/simulation/StdBandwidthInstanceSim.scala b/src/main/scala/gr/grnet/aquarium/simulation/StdBandwidthInstanceSim.scala index aba19e3..b7be463 100644 --- a/src/main/scala/gr/grnet/aquarium/simulation/StdBandwidthInstanceSim.scala +++ b/src/main/scala/gr/grnet/aquarium/simulation/StdBandwidthInstanceSim.scala @@ -53,7 +53,7 @@ case class StdBandwidthInstanceSim(override val resource: StdBandwidthResourceSi extends ResourceInstanceSim(resource, instanceId, owner, client) { def useBandwidth(occurredDate: Date, megaBytes: Double, - details: ResourceEvent.Details = Map(), + details: Map[String, String] = Map(), eventVersion: String = "1.0"): RecordID = { newResourceEvent( diff --git a/src/main/scala/gr/grnet/aquarium/simulation/StdDiskspaceInstanceSim.scala b/src/main/scala/gr/grnet/aquarium/simulation/StdDiskspaceInstanceSim.scala index a940009..5b62d5f 100644 --- a/src/main/scala/gr/grnet/aquarium/simulation/StdDiskspaceInstanceSim.scala +++ b/src/main/scala/gr/grnet/aquarium/simulation/StdDiskspaceInstanceSim.scala @@ -53,7 +53,7 @@ case class StdDiskspaceInstanceSim(override val resource: StdDiskspaceResourceSi extends ResourceInstanceSim(resource, instanceId, owner, client) { def consumeMB(occurredDate: Date, megaBytes: Double, - details: ResourceEvent.Details = ResourceEvent.EmptyDetails, + details: Map[String, String] = Map(), eventVersion: String = "1.0"): RecordID = { newResourceEvent( occurredDate.getTime, @@ -67,7 +67,7 @@ extends ResourceInstanceSim(resource, instanceId, owner, client) { def freeMB(occurredDate: Date, megaBytes: Double, - details: ResourceEvent.Details = ResourceEvent.EmptyDetails, + details: Map[String, String] = Map(), eventVersion: String = "1.0"): RecordID = { consumeMB(occurredDate, -megaBytes) @@ -76,7 +76,7 @@ extends ResourceInstanceSim(resource, instanceId, owner, client) { def consumeMB_OutOfSync(occurredDate: Date, outOfSyncHours: Int, megaBytes: Double, - details: ResourceEvent.Details = ResourceEvent.EmptyDetails, + details: Map[String, String] = Map(), eventVersion: String = "1.0"): RecordID = { val occurredDateCalc = new MutableDateCalc(occurredDate) @@ -95,7 +95,7 @@ extends ResourceInstanceSim(resource, instanceId, owner, client) { def freeMB_OutOfSync(occurredDate: Date, outOfSyncHours: Int, megaBytes: Double, - details: ResourceEvent.Details = ResourceEvent.EmptyDetails, + details: Map[String, String] = Map(), eventVersion: String = "1.0"): RecordID = { consumeMB_OutOfSync(occurredDate, outOfSyncHours, -megaBytes) diff --git a/src/main/scala/gr/grnet/aquarium/simulation/StdVMTimeInstanceSim.scala b/src/main/scala/gr/grnet/aquarium/simulation/StdVMTimeInstanceSim.scala index fd363b3..1295d19 100644 --- a/src/main/scala/gr/grnet/aquarium/simulation/StdVMTimeInstanceSim.scala +++ b/src/main/scala/gr/grnet/aquarium/simulation/StdVMTimeInstanceSim.scala @@ -55,7 +55,7 @@ case class StdVMTimeInstanceSim(override val resource: StdVMTimeResourceSim, extends ResourceInstanceSim(resource, instanceId, owner, client) { def newON(occurredDate: Date, - details: ResourceEvent.Details = ResourceEvent.EmptyDetails, + details: Map[String, String] = Map(), eventVersion: String = "1.0"): RecordID = { newResourceEvent( occurredDate.getTime, @@ -67,7 +67,7 @@ extends ResourceInstanceSim(resource, instanceId, owner, client) { } def newOFF(occurredDate: Date, - details: ResourceEvent.Details = ResourceEvent.EmptyDetails, + details: Map[String, String] = Map(), eventVersion: String = "1.0"): RecordID = { newResourceEvent( occurredDate.getTime, @@ -88,7 +88,7 @@ extends ResourceInstanceSim(resource, instanceId, owner, client) { def newOFF_OutOfSync(occuredDate: Date, outOfSyncHours: Int, - details: ResourceEvent.Details = ResourceEvent.EmptyDetails, + details: Map[String, String] = Map(), eventVersion: String = "1.0"): RecordID = { val occurredDateCalc = new MutableDateCalc(occuredDate) 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 bf73d35..0edecd8 100644 --- a/src/main/scala/gr/grnet/aquarium/store/mongodb/MongoDBStore.scala +++ b/src/main/scala/gr/grnet/aquarium/store/mongodb/MongoDBStore.scala @@ -87,7 +87,7 @@ class MongoDBStore( db.getCollection(name) } - private[this] def _sortByTimestampAsc[A <: AquariumEvent](one: A, two: A): Boolean = { + private[this] def _sortByTimestampAsc[A <: AquariumEventModel](one: A, two: A): Boolean = { if (one.occurredMillis > two.occurredMillis) false else if (one.occurredMillis < two.occurredMillis) true else true @@ -442,7 +442,8 @@ object MongoDBStore { PolicyEntry.fromJson(JSON.serialize(dbObj)) } - def findById[A >: Null <: AquariumEvent](id: String, collection: DBCollection, deserializer: (DBObject) => A) : Maybe[A] = Maybe { + def findById[A >: Null <: AnyRef](id: String, collection: DBCollection, deserializer: (DBObject) => A) : Maybe[A] = + Maybe { val query = new BasicDBObject(ResourceJsonNames.id, id) val cursor = collection find query @@ -456,7 +457,7 @@ object MongoDBStore { } } - def runQuery[A <: AquariumEvent](query: DBObject, collection: DBCollection, orderBy: DBObject = null) + def runQuery[A <: AquariumEventModel](query: DBObject, collection: DBCollection, orderBy: DBObject = null) (deserializer: (DBObject) => A) (sortWith: Option[(A, A) => Boolean]): List[A] = { val cursor0 = collection find query -- 1.7.10.4