root / src / main / scala / gr / grnet / aquarium / logic / events / ResourceType.scala @ 87caa095
History | View | Annotate | Download (6.9 kB)
1 |
/* |
---|---|
2 |
* Copyright 2011 GRNET S.A. All rights reserved. |
3 |
* |
4 |
* Redistribution and use in source and binary forms, with or |
5 |
* without modification, are permitted provided that the following |
6 |
* conditions are met: |
7 |
* |
8 |
* 1. Redistributions of source code must retain the above |
9 |
* copyright notice, this list of conditions and the following |
10 |
* disclaimer. |
11 |
* |
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. |
16 |
* |
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. |
29 |
* |
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. |
34 |
*/ |
35 |
|
36 |
package gr.grnet.aquarium.logic.events |
37 |
|
38 |
import gr.grnet.aquarium.util.TimeHelpers.nowMillis |
39 |
import gr.grnet.aquarium.user._ |
40 |
|
41 |
|
42 |
/** |
43 |
* This is an object representation for a resource name, which provides convenient querying methods. |
44 |
* |
45 |
* Also, a `ResourceType` knows how to compute a state change from a particular `ResourceEvent`. |
46 |
* |
47 |
* @author Christos KK Loverdos <loverdos@gmail.com> |
48 |
*/ |
49 |
sealed abstract class ResourceType(_name: String) { |
50 |
def resourceName = _name |
51 |
|
52 |
/** |
53 |
* Return true if the resource type must lead to wallet entries generation and, thus, credit diffs. |
54 |
* |
55 |
* Normally, this should always be the case. |
56 |
*/ |
57 |
def isBillableType = true |
58 |
|
59 |
/** |
60 |
* A resource type is independent if it can, by itself only, create a finalized wallet entry (that is, |
61 |
* it can create, by itself only, credits). |
62 |
* |
63 |
* It is dependent if it needs one or more other events of he same type to |
64 |
*/ |
65 |
def isIndependentType = true |
66 |
|
67 |
def isKnownType = true |
68 |
def isDiskSpace = false |
69 |
def isVMTime = false |
70 |
def isBandwidthUpload = false |
71 |
def isBandwidthDownload = false |
72 |
|
73 |
/** |
74 |
* Calculates the new `UserState` based on the provided resource event, the calculated wallet entries |
75 |
* and the current `UserState`. |
76 |
* |
77 |
* This method is an implementation detail and is not exposed. The actual user-level API is provided in `ResourceEvent`. |
78 |
*/ |
79 |
private[events] final |
80 |
def calcStateChange(resourceEvent: ResourceEvent, walletEntries: List[WalletEntry], userState: UserState): UserState = { |
81 |
val otherState = calcOtherStateChange(resourceEvent, walletEntries, userState) |
82 |
val newCredits = calcNewCreditSnapshot(walletEntries, userState) |
83 |
otherState.copy(credits = newCredits) |
84 |
} |
85 |
|
86 |
private[events] |
87 |
def calcOtherStateChange(resourceEvent: ResourceEvent, walletEntries: List[WalletEntry], userState: UserState): UserState |
88 |
|
89 |
private[events] final |
90 |
def calcNewCreditSnapshot(walletEntries: List[WalletEntry], userState: UserState): CreditSnapshot = { |
91 |
val newCredits = for { |
92 |
walletEntry <- walletEntries if(walletEntry.finalized) |
93 |
} yield walletEntry.value.toDouble |
94 |
|
95 |
val newCreditSum = newCredits.sum |
96 |
val now = System.currentTimeMillis() |
97 |
|
98 |
CreditSnapshot(userState.credits.data + newCreditSum, now) |
99 |
} |
100 |
} |
101 |
|
102 |
/** |
103 |
* Companion object used to parse a resource name and provide an object representation in the form |
104 |
* of a `ResourceType`. |
105 |
* |
106 |
* Known resource names, which represent Aquarium resources, are like "bndup", "vmtime" etc. and they are all |
107 |
* defined in `ResourceNames`. |
108 |
* |
109 |
* @author Christos KK Loverdos <loverdos@gmail.com> |
110 |
*/ |
111 |
object ResourceType { |
112 |
def fromName(name: String): ResourceType = { |
113 |
name match { |
114 |
case ResourceNames.bnddown ⇒ BandwidthDown |
115 |
case ResourceNames.bndup ⇒ BandwidthUp |
116 |
case ResourceNames.vmtime ⇒ VMTime |
117 |
case _ ⇒ UnknownResourceType(name) |
118 |
} |
119 |
} |
120 |
|
121 |
def fromResourceEvent(resourceEvent: ResourceEvent): ResourceType = fromName(resourceEvent.resource) |
122 |
} |
123 |
|
124 |
case object BandwidthDown extends ResourceType(ResourceNames.bnddown) { |
125 |
override def isBandwidthDownload = true |
126 |
|
127 |
private[events] |
128 |
def calcOtherStateChange(resourceEvent: ResourceEvent, walletEntries: List[WalletEntry], userState: UserState) = { |
129 |
val oldBandwidthDownValue = userState.bandwidthDown.data |
130 |
val bandwidthDownDiff = resourceEvent.value |
131 |
|
132 |
val newBandwidth = BandwidthDownSnapshot(oldBandwidthDownValue + bandwidthDownDiff, nowMillis) |
133 |
|
134 |
userState.copy(bandwidthDown = newBandwidth) |
135 |
} |
136 |
} |
137 |
|
138 |
case object BandwidthUp extends ResourceType(ResourceNames.bndup) { |
139 |
override def isBandwidthUpload = true |
140 |
|
141 |
private[events] |
142 |
def calcOtherStateChange(resourceEvent: ResourceEvent, walletEntries: List[WalletEntry], userState: UserState) = { |
143 |
val oldBandwidthUpValue = userState.bandwidthUp.data |
144 |
val bandwidthUpDiff = resourceEvent.value |
145 |
|
146 |
val newBandwidth = BandwidthUpSnapshot(oldBandwidthUpValue + bandwidthUpDiff, nowMillis) |
147 |
|
148 |
userState.copy(bandwidthUp = newBandwidth) |
149 |
} |
150 |
} |
151 |
|
152 |
case object VMTime extends ResourceType(ResourceNames.vmtime) { |
153 |
override def isVMTime = true |
154 |
|
155 |
override def isIndependentType = false |
156 |
|
157 |
def isVMTimeOn(eventDetails: ResourceEvent.Details) = eventDetails.get(ResourceEvent.JsonNames.action) match { |
158 |
case Some("on") ⇒ true |
159 |
case Some("up") ⇒ true |
160 |
case _ ⇒ false |
161 |
} |
162 |
|
163 |
def isVMTimeOff(eventDetails: ResourceEvent.Details) = eventDetails.get(ResourceEvent.JsonNames.action) match { |
164 |
case Some("off") ⇒ true |
165 |
case Some("down") ⇒ true |
166 |
case _ ⇒ false |
167 |
} |
168 |
|
169 |
private[events] def calcOtherStateChange(resourceEvent: ResourceEvent, walletEntries: List[WalletEntry], userState: UserState) = { |
170 |
// FIXME: implement |
171 |
userState |
172 |
} |
173 |
} |
174 |
|
175 |
case object DiskSpace extends ResourceType(ResourceNames.dsksp) { |
176 |
override def isDiskSpace = true |
177 |
|
178 |
private[events] def calcOtherStateChange(resourceEvent: ResourceEvent, walletEntries: List[WalletEntry], userState: UserState) = { |
179 |
val oldDiskSpaceValue = userState.diskSpace.data |
180 |
val diskSpaceDiff = resourceEvent.value |
181 |
val newDiskSpace = DiskSpaceSnapshot(oldDiskSpaceValue + diskSpaceDiff, nowMillis) |
182 |
userState.copy(diskSpace = newDiskSpace) |
183 |
} |
184 |
} |
185 |
|
186 |
case class UnknownResourceType(originalName: String) extends ResourceType(ResourceNames.unknown) { |
187 |
override def isKnownType = false |
188 |
|
189 |
private[events] def |
190 |
calcOtherStateChange(resourceEvent: ResourceEvent, walletEntries: List[WalletEntry], userState: UserState) = userState |
191 |
} |