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
40 import gr.grnet.aquarium.util.date.MutableDateCalc
43 * The model of any resource event.
45 * @author Christos KK Loverdos <loverdos@gmail.com>
48 trait ResourceEventModel extends ExternalEventModel {
50 * Identifies the client that sent this event.
55 * String representation of the resource type (e.g. "bndup", "vmtime").
60 * String representation of the resource instance id
62 def instanceID: String
70 def withDetails(newDetails: Map[String, String], newOccurredMillis: Long): ResourceEventModel
72 def withDetailsAndValue(newDetails: Map[String, String], newValue: Double, newOccurredMillis: Long): ResourceEventModel
74 def safeResource = if(resource eq null) "" else resource
75 def safeInstanceId = if(instanceID eq null) "" else instanceID
77 def fullResourceInfo = (safeResource, safeInstanceId)
79 def occurredDate = new Date(occurredMillis)
81 def isOccurredWithinMillis(fromMillis: Long, toMillis: Long): Boolean = {
82 require(fromMillis <= toMillis, "fromMillis <= toMillis")
83 fromMillis <= occurredMillis && occurredMillis <= toMillis
86 def isReceivedWithinMillis(fromMillis: Long, toMillis: Long): Boolean = {
87 require(fromMillis <= toMillis, "fromMillis <= toMillis")
88 fromMillis <= receivedMillis && receivedMillis <= toMillis
91 def isOccurredOrReceivedWithinMillis(fromMillis: Long, toMillis: Long): Boolean = {
92 isOccurredWithinMillis(fromMillis, toMillis) ||
93 isReceivedWithinMillis(fromMillis, toMillis)
96 def isOutOfSyncForBillingMonth(yearOfBillingMonth: Int, billingMonth: Int) = {
97 val billingStartDateCalc = new MutableDateCalc(yearOfBillingMonth, billingMonth)
98 val billingStartMillis = billingStartDateCalc.toMillis
99 // NOTE: no need to `copy` the mutable `billingStartDateCalc` here because we use it once
100 val billingStopMillis = billingStartDateCalc.goEndOfThisMonth.toMillis
102 isOutOfSyncForBillingPeriod(billingStartMillis, billingStopMillis)
105 def isOutOfSyncForBillingPeriod(billingStartMillis: Long, billingStopMillis: Long): Boolean = {
106 isReceivedWithinMillis(billingStartMillis, billingStopMillis) &&
107 (occurredMillis < billingStartMillis || occurredMillis > billingStopMillis)
110 def toDebugString(useOnlyInstanceId: Boolean = false): String = {
111 val instanceInfo = if(useOnlyInstanceId) instanceID else "%s::%s".format(resource, instanceID)
112 val occurredFormatted = new MutableDateCalc(occurredMillis).toYYYYMMDDHHMMSS
113 if(occurredMillis == receivedMillis) {
114 "%sEVENT(%s, [%s], %s, %s, %s, %s, %s)".format(
115 if(isSynthetic) "*" else "",
125 "%sEVENT(%s, [%s], [%s], %s, %s, %s, %s, %s)".format(
126 if(isSynthetic) "*" else "",
129 new MutableDateCalc(receivedMillis),
140 * `Synthetic` means that Aquarium has manufactured this resource event for some purpose. For example, the implicitly
141 * issued resource events at the end a a billing period.
143 * @return `true` iff this resource event is synthetic.
146 details contains ResourceEventModel.Names.details_aquarium_is_synthetic
151 object ResourceEventModel {
152 type ResourceType = String
153 type ResourceIdType = String
154 type FullResourceType = (ResourceType, ResourceIdType)
155 type FullResourceTypeMap = Map[FullResourceType, ResourceEventModel]
156 type FullMutableResourceTypeMap = scala.collection.mutable.Map[FullResourceType, ResourceEventModel]
158 trait NamesT extends ExternalEventModel.NamesT {
159 final val clientID = "clientID"
160 final val resource = "resource"
161 final val instanceID = "instanceID"
162 final val value = "value"
164 // This is set in the details map to indicate a synthetic resource event (ie not a real one).
165 // Examples of synthetic resource events are those that are implicitly generated at the
166 // end of the billing period (e.g. `OFF`s).
167 final val details_aquarium_is_synthetic = "__aquarium_is_synthetic__"
169 final val details_aquarium_is_implicit_end = "__aquarium_is_implicit_end__"
172 object Names extends NamesT
174 def setAquariumSyntheticAndImplicitEnd(map: Map[String, String]): Map[String, String] = {
176 updated(Names.details_aquarium_is_synthetic, "true").
177 updated(Names.details_aquarium_is_implicit_end, "true")