Statistics
| Branch: | Tag: | Revision:

root / src / main / scala / gr / grnet / aquarium / store / memory / MemStore.scala @ f9c6a8eb

History | View | Annotate | Download (8.1 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.store.memory
37

    
38
import gr.grnet.aquarium.user.UserState
39
import gr.grnet.aquarium.Configurable
40
import com.ckkloverdos.props.Props
41
import com.ckkloverdos.maybe.{NoVal, Just, Maybe}
42
import gr.grnet.aquarium.store._
43
import scala.collection.JavaConversions._
44
import java.util.Date
45
import collection.mutable.ConcurrentMap
46
import gr.grnet.aquarium.logic.events.{WalletEntry, ResourceEvent, UserEvent, PolicyEntry}
47
import java.util.concurrent.ConcurrentHashMap
48
import gr.grnet.aquarium.util.date.DateCalculator
49

    
50
/**
51
 * An implementation of various stores that persists data in memory
52
 * 
53
 * @author Christos KK Loverdos <loverdos@gmail.com>
54
 * @author Georgios Gousios <gousiosg@gmail.com>
55
 */
56

    
57
class MemStore extends UserStateStore
58
  with Configurable with PolicyStore
59
  with ResourceEventStore with UserEventStore
60
  with WalletEntryStore
61
  with StoreProvider {
62

    
63
  private[this] val userStateByUserId = new ConcurrentHashMap[String, Just[UserState]]()
64
  private val policyById: ConcurrentMap[String, PolicyEntry] = new ConcurrentHashMap[String, PolicyEntry]()
65
  private[this] val walletEntriesById: ConcurrentMap[String, WalletEntry] = new ConcurrentHashMap[String, WalletEntry]()
66
  private val userEventById: ConcurrentMap[String, UserEvent] = new ConcurrentHashMap[String, UserEvent]()
67
  private[this] val resourceEventsById: ConcurrentMap[String, ResourceEvent] = new ConcurrentHashMap[String, ResourceEvent]()
68

    
69
  def configure(props: Props) = {
70
  }
71

    
72
  //+ StoreProvider
73
  def userStateStore = this
74

    
75
  def resourceEventStore = this
76

    
77
  def walletEntryStore = this
78

    
79
  def userEventStore = this
80

    
81
  def policyStore = this
82
  //- StoreProvider
83

    
84

    
85
  def storeUserState(userState: UserState): Maybe[RecordID] = {
86
    val userId = userState.userId
87
    val userStateJ = Just(userState)
88
    userStateByUserId.put(userId, userStateJ)
89
    Just(RecordID(userId))
90
  }
91

    
92
  def findUserStateByUserId(userId: String) = {
93
    userStateByUserId.get(userId) match {
94
      case null       ⇒ NoVal
95
      case userStateJ ⇒ userStateJ
96
    }
97
  }
98

    
99
  def deleteUserState(userId: String) {
100
    if (userStateByUserId.containsKey(userId))
101
      userStateByUserId.remove(userId)
102
  }
103

    
104
  //- WalletEntryStore
105
  def storeWalletEntry(entry: WalletEntry): Maybe[RecordID] = {
106
    walletEntriesById.put(entry.id, entry)
107
    Just(RecordID(entry.id))
108
  }
109

    
110
  def findWalletEntryById(id: String): Maybe[WalletEntry] = {
111
    Maybe(walletEntriesById.apply(id))
112
  }
113

    
114
  def findUserWalletEntries(userId: String): List[WalletEntry] = {
115
    walletEntriesById.valuesIterator.filter(_.userId == userId).toList
116
  }
117

    
118
  def findUserWalletEntriesFromTo(userId: String, from: Date, to: Date): List[WalletEntry] = {
119
    walletEntriesById.valuesIterator.filter { we ⇒
120
      val receivedDate = we.receivedDate
121

    
122
      we.userId == userId &&
123
      ( (from before receivedDate) || (from == receivedDate) ) &&
124
      ( (to   after  receivedDate) || (to   == receivedDate) )
125
      true
126
    }.toList
127
  }
128

    
129
  def findLatestUserWalletEntries(userId: String): Maybe[List[WalletEntry]] = NoVal
130

    
131
  def findPreviousEntry(userId: String,
132
                        resource: String,
133
                        instanceId: String,
134
                        finalized: Option[Boolean]): List[WalletEntry] = Nil
135

    
136
  def findWalletEntriesAfter(userId: String, from: Date): List[WalletEntry] = {
137
    walletEntriesById.valuesIterator.filter { we ⇒
138
      val occurredDate = we.occurredDate
139

    
140
      we.userId == userId &&
141
            ( (from before occurredDate) || (from == occurredDate) )
142
    }.toList
143
  }
144
  //- WalletEntryStore
145

    
146
  //+ ResourceEventStore
147
  def storeResourceEvent(event: ResourceEvent) = {
148
    resourceEventsById(event.id) = event
149
    Just(RecordID(event.id))
150
  }
151

    
152
  def findResourceEventById(id: String) = {
153
    Maybe(resourceEventsById(id))
154
  }
155

    
156
  def findResourceEventsByUserId(userId: String)
157
                                (sortWith: Option[(ResourceEvent, ResourceEvent) => Boolean]): List[ResourceEvent] = {
158
    val byUserId = resourceEventsById.valuesIterator.filter(_.userId == userId).toArray
159
    val sorted = sortWith match {
160
      case Some(sorter) ⇒
161
        byUserId.sortWith(sorter)
162
      case None ⇒
163
        byUserId
164
    }
165

    
166
    sorted.toList
167
  }
168

    
169
  def findResourceEventsByUserIdAfterTimestamp(userId: String, timestamp: Long): List[ResourceEvent] = {
170
    resourceEventsById.valuesIterator.filter { ev ⇒
171
      ev.userId == userId &&
172
      (ev.occurredMillis > timestamp)
173
    }.toList
174
  }
175

    
176
  def findResourceEventHistory(userId: String,
177
                               resName: String,
178
                               instid: Option[String],
179
                               upTo: Long): List[ResourceEvent] = {
180
    Nil
181
  }
182

    
183
  def findResourceEventsForReceivedPeriod(userId: String,
184
                                          startTimeMillis: Long,
185
                                          stopTimeMillis: Long): List[ResourceEvent] = {
186
    resourceEventsById.valuesIterator.filter { ev ⇒
187
      ev.userId == userId &&
188
      ev.receivedMillis >= startTimeMillis &&
189
      ev.receivedMillis <= stopTimeMillis
190
    }.toList
191
  }
192

    
193
  def countOutOfSyncEventsForBillingMonth(userId: String, yearOfBillingMonth: Int, billingMonth: Int): Maybe[Long] = Maybe {
194
    val billingMonthDate = new DateCalculator(yearOfBillingMonth, billingMonth)
195
    val billingDateStart = billingMonthDate
196
    val billingDateEnd = billingDateStart.endOfThisMonth
197
    resourceEventsById.valuesIterator.filter { case ev ⇒
198
      // out of sync events are those that were received in the billing month but occurred in previous months
199
      val receivedMillis = ev.receivedMillis
200
      val occurredMillis = ev.occurredMillis
201

    
202
      billingDateStart.afterEqMillis(receivedMillis) && // the events that...
203
      billingDateEnd.beforeEqMillis (receivedMillis) && // ...were received withing the billing month
204
      (                                                 //
205
        billingDateStart.afterMillis(occurredMillis)    // but occurred before the billing period
206
        )
207
    }.size.toLong
208
  }
209
  //- ResourceEventStore
210

    
211
  def storeUserEvent(event: UserEvent) = {userEventById += (event.id -> event); Just(RecordID(event.id))}
212

    
213
  def findUserEventById(id: String) = Maybe{userEventById.getOrElse(id, null)}
214

    
215
  def findUserEventsByUserId(userId: String) = userEventById.values.filter{v => v.userId == userId}.toList
216

    
217
  def loadPolicies(after: Long) = policyById.values.foldLeft(List[PolicyEntry]()){
218
    (acc, v) => if(v.validFrom > after) v :: acc else acc
219
  }
220

    
221
  def storePolicy(policy: PolicyEntry) = {policyById += (policy.id -> policy); Just(RecordID(policy.id))}
222

    
223
  def updatePolicy(policy: PolicyEntry) = storePolicy(policy)
224
}