2 * Copyright 2011-2012 GRNET S.A. All rights reserved.
4 * Redistribution and use in source and binary forms, with or
5 * without modification, are permitted provided that the following
8 * 1. Redistributions of source code must retain the above
9 * copyright notice, this list of conditions and the following
12 * 2. Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials
15 * provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
18 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
30 * The views and conclusions contained in the software and
31 * documentation are those of the authors and should not be
32 * interpreted as representing official policies, either expressed
33 * or implied, of GRNET S.A.
36 package gr.grnet.aquarium.event.model
39 import gr.grnet.aquarium.event.model.ExternalEventModel
40 import gr.grnet.aquarium.util.date.MutableDateCalc
44 * The model of any resource event.
46 * @author Christos KK Loverdos <loverdos@gmail.com>
49 trait ResourceEventModel extends ExternalEventModel {
51 * Identifies the client that sent this event.
56 * String representation of the resource type (e.g. "bndup", "vmtime").
61 * String representation of the resource instance id
63 def instanceID: String
71 def withDetails(newDetails: Map[String, String], newOccurredMillis: Long): ResourceEventModel
73 def withDetailsAndValue(newDetails: Map[String, String], newValue: Double, newOccurredMillis: Long): ResourceEventModel
75 def safeResource = if(resource eq null) "" else resource
76 def safeInstanceID = if(instanceID eq null) "" else instanceID
78 def safeResourceInstanceInfo = (safeResource, safeInstanceID)
80 def occurredDate = new Date(occurredMillis)
82 def isOccurredWithinMillis(fromMillis: Long, toMillis: Long): Boolean = {
83 require(fromMillis <= toMillis, "fromMillis <= toMillis")
84 fromMillis <= occurredMillis && occurredMillis <= toMillis
87 def isReceivedWithinMillis(fromMillis: Long, toMillis: Long): Boolean = {
88 require(fromMillis <= toMillis, "fromMillis <= toMillis")
89 fromMillis <= receivedMillis && receivedMillis <= toMillis
92 def isOccurredOrReceivedWithinMillis(fromMillis: Long, toMillis: Long): Boolean = {
93 isOccurredWithinMillis(fromMillis, toMillis) ||
94 isReceivedWithinMillis(fromMillis, toMillis)
97 def isOutOfSyncForBillingMonth(yearOfBillingMonth: Int, billingMonth: Int) = {
98 val billingStartDateCalc = new MutableDateCalc(yearOfBillingMonth, billingMonth)
99 val billingStartMillis = billingStartDateCalc.toMillis
100 // NOTE: no need to `copy` the mutable `billingStartDateCalc` here because we use it once
101 val billingStopMillis = billingStartDateCalc.goEndOfThisMonth.toMillis
103 isOutOfSyncForBillingPeriod(billingStartMillis, billingStopMillis)
106 def isOutOfSyncForBillingPeriod(billingStartMillis: Long, billingStopMillis: Long): Boolean = {
107 // Out of sync events are those that were received within the billing period
108 // but actually occurred outside the billing period.
109 isReceivedWithinMillis(billingStartMillis, billingStopMillis) &&
110 !isOccurredWithinMillis(billingStartMillis, billingStopMillis)
113 override def toDebugString: String = {
114 val instanceInfo = "%s::%s".format(resource, instanceID)
115 val occurredFormatted = new MutableDateCalc(occurredMillis).toYYYYMMDDHHMMSS
116 if(occurredMillis == receivedMillis) {
117 "%sEVENT(%s, [%s], %s, %s, %s, %s, %s)".format(
118 if(isSynthetic) "*" else "",
128 "%sEVENT(%s, [%s], [%s], %s, %s, %s, %s, %s)".format(
129 if(isSynthetic) "*" else "",
132 new MutableDateCalc(receivedMillis),
143 * `Synthetic` means that Aquarium has manufactured this resource event for some purpose. For example, the implicitly
144 * issued resource events at the end a a billing period.
146 * @return `true` iff this resource event is synthetic.
149 details contains ResourceEventModel.Names.details_aquarium_is_synthetic
153 object ResourceEventModel {
155 * A `ResourceInstance` is the type of a specific resource instance and it is contains the name of the
156 * [[gr.grnet.aquarium.policy.ResourceType]] and the instance `ID`.
158 type ResourceInstance = (String, String)
159 type FullResourceTypeMap = Map[ResourceInstance, ResourceEventModel]
160 type FullMutableResourceTypeMap = scala.collection.mutable.Map[ResourceInstance, ResourceEventModel]
162 trait NamesT extends ExternalEventModel.NamesT {
163 final val clientID = "clientID"
164 final val resource = "resource"
165 final val instanceID = "instanceID"
166 final val value = "value"
168 // This is set in the details map to indicate a synthetic resource event (ie not a real one).
169 // Examples of synthetic resource events are those that are implicitly generated at the
170 // end of the billing period (e.g. `OFF`s).
171 final val details_aquarium_is_synthetic = "__aquarium_is_synthetic__"
173 final val details_aquarium_is_implicit_end = "__aquarium_is_implicit_end__"
175 final val details_aquarium_is_dummy_first = "__aquarium_is_dummy_first__"
177 final val details_aquarium_is_realtime_virtual = "__aquarium_is_realtime_virtual__"
179 final val details_aquarium_reference_event_id = "__aquarium_reference_event_id__"
181 final val details_aquarium_reference_event_id_in_store = "__aquarium_reference_event_id_in_store__"
184 object Names extends NamesT
186 def setAquariumSyntheticAndImplicitEnd(map: Map[String, String]): Map[String, String] = {
188 updated(Names.details_aquarium_is_synthetic, "true").
189 updated(Names.details_aquarium_is_implicit_end, "true")
192 def setAquariumSyntheticAndDummyFirst(map: Map[String, String]): Map[String, String] = {
194 updated(Names.details_aquarium_is_synthetic, "true").
195 updated(Names.details_aquarium_is_dummy_first, "true")