Implemented PolicyHistory.scala (a cache that wraps Database calls) and modified...
authorProdromos Gerakios <pgerakios@grnet.gr>
Fri, 13 Jul 2012 10:06:53 +0000 (13:06 +0300)
committerProdromos Gerakios <pgerakios@grnet.gr>
Fri, 13 Jul 2012 10:06:53 +0000 (13:06 +0300)
src/main/scala/gr/grnet/aquarium/Aquarium.scala
src/main/scala/gr/grnet/aquarium/policy/PolicyHistory.scala
src/main/scala/gr/grnet/aquarium/store/PolicyStore.scala
src/main/scala/gr/grnet/aquarium/store/memory/MemStoreProvider.scala
src/main/scala/gr/grnet/aquarium/store/mongodb/MongoDBStore.scala

index a71c08e..9dc1fb2 100644 (file)
@@ -63,8 +63,6 @@ final class Aquarium(env: Env) extends Lifecycle with Loggable {
 
   @volatile private[this] var _chargingBehaviorMap = Map[String, ChargingBehavior]()
 
-  private[this] val policyHistory = new PolicyHistory
-
   private[this] val _isStopping = new AtomicBoolean(false)
 
   override def toString = "%s/v%s".format(getClass.getName, version)
@@ -286,7 +284,7 @@ final class Aquarium(env: Env) extends Lifecycle with Loggable {
 
   def userStateStore = apply(EnvKeys.storeProvider).userStateStore
 
-  def policyStore = apply(EnvKeys.storeProvider).policyStore
+  def policyStore = new PolicyHistory(apply(EnvKeys.storeProvider).policyStore)
 
   def eventsStoreFolder = apply(EnvKeys.eventsStoreFolder)
 
index e15a901..7442df1 100644 (file)
 
 package gr.grnet.aquarium.policy
 
-import scala.collection.immutable.TreeSet
+import collection.immutable.{SortedMap, TreeSet}
 import gr.grnet.aquarium.Timespan
 import gr.grnet.aquarium.util.Lock
+import gr.grnet.aquarium.store.PolicyStore
+import gr.grnet.aquarium.logic.accounting.dsl.Timeslot
+import collection.immutable
 
 /**
  * A mutable container of policy models.
  *
  * @author Christos KK Loverdos <loverdos@gmail.com>
+ * @author Prodromos Gerakios <pgerakios@grnet.gr>
  */
 
-class PolicyHistory {
+class PolicyHistory(policyStore: PolicyStore) extends PolicyStore {
+  override type Policy = PolicyModel
   private[this] val lock = new Lock()
-  @volatile private[this] var _policies = TreeSet[PolicyModel]()
+  @volatile private[this] var _policies = TreeSet[Policy]()
+  private def emptyMap = immutable.SortedMap[Timeslot,Policy]()
+
+  private[this] def synchronized[A](f: => A) : A =
+    lock.withLock {
+      if(_policies.isEmpty)
+        _policies ++= policyStore.loadAndSortPoliciesWithin(0,Long.MaxValue).values
+      f
+    }
+
+  private[this] def policyAt(s:Long) : PolicyModel =
+    new StdPolicy("", None, Timespan(s), Set(), Set(), Map())
+
+  def loadAndSortPoliciesWithin(fromMillis: Long, toMillis: Long): SortedMap[Timeslot, Policy] =
+    synchronized {
+        val range = Timeslot(fromMillis,toMillis)
+        /* ``to'' method: return the subset of all policies.from <= range.to */
+        _policies.to(policyAt(range.to.getTime)).foldLeft (emptyMap) { (map,p) =>
+          if(p.validityTimespan.toTimeslot.to.getTime >= range.from.getTime)
+            map + ((p.validityTimespan.toTimeslot,p))
+          else
+            map
+        }
+    }
 
-  def insertNewPolicy(newPolicy: PolicyModel): Unit = {
-    lock.withLock(_policies += newPolicy)
-  }
 
   /**
    * Return the last (ordered) policy that starts before timeMillis
    *
-   * @param timeMillis
+   * @param atMillis
    * @return
    */
-  def findPolicyAt(timeMillis: Long): Option[PolicyModel] = {
-    lock.withLock {
+  def loadValidPolicyAt(atMillis: Long): Option[Policy] =
+    synchronized {
       // Take the subset of all ordered policies up to the one with less than or equal start time
       // and then return the last item. This should be the policy right before the given time.
       // TODO: optimize the creation of the fake StdPolicy
-      _policies.to(new StdPolicy("", None, Timespan(timeMillis), Set(), Set(), Map())).lastOption
+      _policies.to(policyAt(atMillis)).lastOption
     }
-  }
+
+
+  /**
+   * Store an accounting policy.
+   */
+  def insertPolicy(policy: PolicyModel): Policy =
+   synchronized {
+      var p = policyStore.insertPolicy(policy)
+      _policies += p
+      p
+   }
 }
index 7e41a9d..a58e95d 100644 (file)
@@ -48,29 +48,13 @@ import gr.grnet.aquarium.policy.PolicyModel
 trait PolicyStore {
   type Policy <: PolicyModel
 
-  /**
-   * Load all accounting policies valid after the specified time instance.
-   * The results are returned sorted by PolicyEntry.validFrom
-   */
-  def loadPoliciesAfter(afterMillis: Long): List[Policy]
+  def loadAndSortPoliciesWithin(fromMillis: Long, toMillis: Long): SortedMap[Timeslot, Policy]
 
-  def loadAndSortPoliciesWithin(fromMillis: Long, toMillis: Long): SortedMap[Timeslot, Policy] = {
-    // FIXME implement
-    throw new UnsupportedOperationException
-  }
-  
-  def loadValidPolicyAt(atMillis: Long): Option[Policy] = {
-    // FIXME implement
-    throw new UnsupportedOperationException
-  }
+  def loadValidPolicyAt(atMillis: Long): Option[Policy]
 
   /**
    * Store an accounting policy.
    */
   def insertPolicy(policy: PolicyModel): Policy
 
-  /**
-   * Find a policy by its unique id.
-   */
-  def findPolicyByID(id: String): Option[Policy]
 }
\ No newline at end of file
index e513606..8120df5 100644 (file)
@@ -49,6 +49,8 @@ import gr.grnet.aquarium.computation.state.UserState
 import gr.grnet.aquarium.util.Tags
 import gr.grnet.aquarium.computation.BillingMonthInfo
 import gr.grnet.aquarium.policy.{PolicyModel, StdPolicy}
+import collection.immutable.SortedMap
+import gr.grnet.aquarium.logic.accounting.dsl.Timeslot
 
 /**
  * An implementation of various stores that persists parts in memory.
@@ -57,6 +59,7 @@ import gr.grnet.aquarium.policy.{PolicyModel, StdPolicy}
  * 
  * @author Christos KK Loverdos <loverdos@gmail.com>
  * @author Georgios Gousios <gousiosg@gmail.com>
+ * @author Prodromos Gerakios <grnet.gr>
  */
 
 class MemStoreProvider
@@ -262,14 +265,6 @@ extends StoreProvider
   }
   //- IMEventStore
 
-  def loadPoliciesAfter(afterMillis: Long) =
-    _policies.filter(p => p.validFrom > afterMillis)
-            .sortWith((a,b) => a.validFrom < b.validFrom)
-
-  def findPolicyByID(id: String) = {
-    _policies.find(p => p.id == id)
-  }
-
   /**
    * Store an accounting policy.
    */
@@ -286,6 +281,14 @@ extends StoreProvider
 
     localPolicy
   }
+
+  def loadValidPolicyAt(atMillis: Long): Option[Policy] = {
+    throw new UnsupportedOperationException
+  }
+
+  def loadAndSortPoliciesWithin(fromMillis: Long, toMillis: Long): SortedMap[Timeslot, Policy] = {
+    throw new UnsupportedOperationException
+  }
 }
 
 object MemStoreProvider {
index 61e53db..48b5a2d 100644 (file)
@@ -53,12 +53,15 @@ import gr.grnet.aquarium.event.model.ExternalEventModel
 import gr.grnet.aquarium.computation.BillingMonthInfo
 import gr.grnet.aquarium.policy.PolicyModel
 import gr.grnet.aquarium.{Aquarium, AquariumException}
+import collection.immutable.SortedMap
+import gr.grnet.aquarium.logic.accounting.dsl.Timeslot
 
 /**
  * Mongodb implementation of the various aquarium stores.
  *
  * @author Christos KK Loverdos <loverdos@gmail.com>
  * @author Georgios Gousios <gousiosg@gmail.com>
+ * @author Prodromos Gerakios <pgerakio@grnet.gr>
  */
 class MongoDBStore(
     val aquarium: Aquarium,
@@ -278,6 +281,14 @@ class MongoDBStore(
     val dbPolicy = MongoDBPolicy.fromOther(policy, new ObjectId().toStringMongod)
     MongoDBStore.insertObject(dbPolicy, policies, MongoDBStore.jsonSupportToDBObject)
   }
+
+  def loadValidPolicyAt(atMillis: Long): Option[Policy] = {
+    throw new UnsupportedOperationException
+  }
+
+  def loadAndSortPoliciesWithin(fromMillis: Long, toMillis: Long): SortedMap[Timeslot, Policy] = {
+    throw new UnsupportedOperationException
+  }
   //-PolicyStore
 }