From: Prodromos Gerakios Date: Thu, 23 Aug 2012 13:24:30 +0000 (+0300) Subject: Refactored BillEntry and relevant classes. X-Git-Url: https://code.grnet.gr/git/aquarium/commitdiff_plain/dbba44ce85341c52702c848317a5bd8c513475bf Refactored BillEntry and relevant classes. --- diff --git a/bill.sh b/bill.sh index 79eb27a..371b038 100755 --- a/bill.sh +++ b/bill.sh @@ -59,6 +59,8 @@ RESOURCE1="{ echo $USERCREATE | rabbitmqadmin -H dev82.dev.grnet.gr -P 55672 -u rabbit -p r@bb1t publish routing_key=astakos.user exchange=astakos echo $ADDCREDITS | rabbitmqadmin -H dev82.dev.grnet.gr -P 55672 -u rabbit -p r@bb1t publish routing_key=astakos.user exchange=astakos echo $RESOURCE1 | rabbitmqadmin -H dev82.dev.grnet.gr -P 55672 -u rabbit -p r@bb1t publish routing_key=pithos.resource.diskspace exchange=pithos + +#read MAINCLASS=gr.grnet.aquarium.charging.bill.BillEntry /home/pgerakios/jdk1.6.0_33/bin/java -Dfile.encoding=UTF-8 -classpath /home/pgerakios/jdk1.6.0_33/jre/lib/rt.jar:/home/pgerakios/jdk1.6.0_33/jre/lib/resources.jar:/home/pgerakios/jdk1.6.0_33/jre/lib/jce.jar:/home/pgerakios/jdk1.6.0_33/jre/lib/plugin.jar:/home/pgerakios/jdk1.6.0_33/jre/lib/deploy.jar:/home/pgerakios/jdk1.6.0_33/jre/lib/jsse.jar:/home/pgerakios/jdk1.6.0_33/jre/lib/management-agent.jar:/home/pgerakios/jdk1.6.0_33/jre/lib/javaws.jar:/home/pgerakios/jdk1.6.0_33/jre/lib/charsets.jar:/home/pgerakios/jdk1.6.0_33/jre/lib/ext/sunpkcs11.jar:/home/pgerakios/jdk1.6.0_33/jre/lib/ext/localedata.jar:/home/pgerakios/jdk1.6.0_33/jre/lib/ext/dnsns.jar:/home/pgerakios/jdk1.6.0_33/jre/lib/ext/sunjce_provider.jar:/home/pgerakios/aquarium/target/classes:/home/pgerakios/.m2/repository/org/scala-lang/scala-library/2.9.1/scala-library-2.9.1.jar:/home/pgerakios/.m2/repository/org/slf4j/slf4j-api/1.6.1/slf4j-api-1.6.1.jar:/home/pgerakios/.m2/repository/ch/qos/logback/logback-classic/0.9.29/logback-classic-0.9.29.jar:/home/pgerakios/.m2/repository/ch/qos/logback/logback-core/0.9.29/logback-core-0.9.29.jar:/home/pgerakios/.m2/repository/org/scala-lang/scala-compiler/2.9.1/scala-compiler-2.9.1.jar:/home/pgerakios/.m2/repository/com/fasterxml/jackson/core/jackson-core/2.0.2/jackson-core-2.0.2.jar:/home/pgerakios/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.0.2/jackson-databind-2.0.2.jar:/home/pgerakios/.m2/repository/com/fasterxml/jackson/core/jackson-annotations/2.0.2/jackson-annotations-2.0.2.jar:/home/pgerakios/.m2/repository/com/fasterxml/jackson/module/jackson-module-scala/2.0.2/jackson-module-scala-2.0.2.jar:/home/pgerakios/.m2/repository/org/scalastuff/scalabeans/0.2/scalabeans-0.2.jar:/home/pgerakios/.m2/repository/com/thoughtworks/paranamer/paranamer/2.3/paranamer-2.3.jar:/home/pgerakios/.m2/repository/com/google/guava/guava/12.0/guava-12.0.jar:/home/pgerakios/.m2/repository/net/liftweb/lift-json_2.9.1/2.4/lift-json_2.9.1-2.4.jar:/home/pgerakios/.m2/repository/org/scala-lang/scalap/2.9.1/scalap-2.9.1.jar:/home/pgerakios/.m2/repository/net/liftweb/lift-json-ext_2.9.1/2.4/lift-json-ext_2.9.1-2.4.jar:/home/pgerakios/.m2/repository/commons-codec/commons-codec/1.4/commons-codec-1.4.jar:/home/pgerakios/.m2/repository/net/liftweb/lift-common_2.9.1/2.4/lift-common_2.9.1-2.4.jar:/home/pgerakios/.m2/repository/org/yaml/snakeyaml/1.9/snakeyaml-1.9.jar:/home/pgerakios/.m2/repository/com/kenai/crontab-parser/crontab-parser/1.0.1/crontab-parser-1.0.1.jar:/home/pgerakios/.m2/repository/com/rabbitmq/amqp-client/2.8.4/amqp-client-2.8.4.jar:/home/pgerakios/.m2/repository/com/ckkloverdos/jbootstrap/3.0.0/jbootstrap-3.0.0.jar:/home/pgerakios/.m2/repository/com/ckkloverdos/streamresource/0.5.1/streamresource-0.5.1.jar:/home/pgerakios/.m2/repository/com/ckkloverdos/maybe/0.5.0/maybe-0.5.0.jar:/home/pgerakios/.m2/repository/com/ckkloverdos/sysprop/0.5.1/sysprop-0.5.1.jar:/home/pgerakios/.m2/repository/com/ckkloverdos/converter/0.5.0/converter-0.5.0.jar:/home/pgerakios/.m2/repository/com/ckkloverdos/typedkey/0.5.0/typedkey-0.5.0.jar:/home/pgerakios/.m2/repository/com/thoughtworks/xstream/xstream/1.4.1/xstream-1.4.1.jar:/home/pgerakios/.m2/repository/xmlpull/xmlpull/1.1.3.1/xmlpull-1.1.3.1.jar:/home/pgerakios/.m2/repository/xpp3/xpp3_min/1.1.4c/xpp3_min-1.1.4c.jar:/home/pgerakios/.m2/repository/org/mongodb/mongo-java-driver/2.7.2/mongo-java-driver-2.7.2.jar:/home/pgerakios/.m2/repository/com/typesafe/akka/akka-actor/2.0.2/akka-actor-2.0.2.jar:/home/pgerakios/.m2/repository/com/typesafe/akka/akka-remote/2.0.2/akka-remote-2.0.2.jar:/home/pgerakios/.m2/repository/io/netty/netty/3.3.0.Final/netty-3.3.0.Final.jar:/home/pgerakios/.m2/repository/com/google/protobuf/protobuf-java/2.4.1/protobuf-java-2.4.1.jar:/home/pgerakios/.m2/repository/net/debasishg/sjson_2.9.1/0.15/sjson_2.9.1-0.15.jar:/home/pgerakios/.m2/repository/net/databinder/dispatch-json_2.9.1/0.8.5/dispatch-json_2.9.1-0.8.5.jar:/home/pgerakios/.m2/repository/org/apache/httpcomponents/httpclient/4.1/httpclient-4.1.jar:/home/pgerakios/.m2/repository/org/apache/httpcomponents/httpcore/4.1/httpcore-4.1.jar:/home/pgerakios/.m2/repository/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.jar:/home/pgerakios/.m2/repository/org/objenesis/objenesis/1.2/objenesis-1.2.jar:/home/pgerakios/.m2/repository/commons-io/commons-io/1.4/commons-io-1.4.jar:/home/pgerakios/.m2/repository/voldemort/store/compress/h2-lzf/1.0/h2-lzf-1.0.jar:/home/pgerakios/.m2/repository/com/typesafe/akka/akka-slf4j/2.0.2/akka-slf4j-2.0.2.jar:/home/pgerakios/.m2/repository/com/twitter/finagle-core_2.9.1/4.0.2/finagle-core_2.9.1-4.0.2.jar:/home/pgerakios/.m2/repository/com/twitter/util-core_2.9.1/4.0.1/util-core_2.9.1-4.0.1.jar:/home/pgerakios/.m2/repository/com/twitter/util-collection_2.9.1/4.0.1/util-collection_2.9.1-4.0.1.jar:/home/pgerakios/.m2/repository/commons-collections/commons-collections/3.2.1/commons-collections-3.2.1.jar:/home/pgerakios/.m2/repository/com/twitter/util-hashing_2.9.1/4.0.1/util-hashing_2.9.1-4.0.1.jar:/home/pgerakios/.m2/repository/com/twitter/finagle-http_2.9.1/4.0.2/finagle-http_2.9.1-4.0.2.jar:/home/pgerakios/.m2/repository/com/twitter/util-codec_2.9.1/4.0.1/util-codec_2.9.1-4.0.1.jar:/home/pgerakios/.m2/repository/com/twitter/util-logging_2.9.1/4.0.1/util-logging_2.9.1-4.0.1.jar:/home/pgerakios/.m2/repository/commons-lang/commons-lang/2.6/commons-lang-2.6.jar:/home/pgerakios/.m2/repository/com/google/code/findbugs/jsr305/1.3.9/jsr305-1.3.9.jar:/home/pgerakios/.m2/repository/joda-time/joda-time/2.0/joda-time-2.0.jar:/home/pgerakios/.m2/repository/org/joda/joda-convert/1.1/joda-convert-1.1.jar:/home/pgerakios/.m2/repository/org/quartz-scheduler/quartz/2.1.5/quartz-2.1.5.jar:/home/pgerakios/.m2/repository/c3p0/c3p0/0.9.1.1/c3p0-0.9.1.1.jar:/home/pgerakios/.m2/repository/org/quartz-scheduler/quartz-oracle/2.1.5/quartz-oracle-2.1.5.jar:/home/pgerakios/.m2/repository/org/quartz-scheduler/quartz-weblogic/2.1.5/quartz-weblogic-2.1.5.jar:/home/pgerakios/.m2/repository/org/quartz-scheduler/quartz-jboss/2.1.5/quartz-jboss-2.1.5.jar:/home/pgerakios/idea-IC-117.418/lib/idea_rt.jar $MAINCLASS & PID=$! diff --git a/src/main/scala/gr/grnet/aquarium/actor/message/GetUserBillResponse.scala b/src/main/scala/gr/grnet/aquarium/actor/message/GetUserBillResponse.scala index d18cc7d..f6129be 100644 --- a/src/main/scala/gr/grnet/aquarium/actor/message/GetUserBillResponse.scala +++ b/src/main/scala/gr/grnet/aquarium/actor/message/GetUserBillResponse.scala @@ -36,7 +36,7 @@ package gr.grnet.aquarium.actor.message import gr.grnet.aquarium.AquariumInternalError -import gr.grnet.aquarium.charging.bill.BillEntry +import gr.grnet.aquarium.charging.bill.{AbstractBillEntry, BillEntry} /** * @@ -59,4 +59,4 @@ case class GetUserBillResponse( } } -case class GetUserBillResponseData(userID: String, billEntry: BillEntry) \ No newline at end of file +case class GetUserBillResponseData(userID: String, billEntry: AbstractBillEntry) \ No newline at end of file diff --git a/src/main/scala/gr/grnet/aquarium/actor/service/user/UserActor.scala b/src/main/scala/gr/grnet/aquarium/actor/service/user/UserActor.scala index 476f3ce..f969671 100644 --- a/src/main/scala/gr/grnet/aquarium/actor/service/user/UserActor.scala +++ b/src/main/scala/gr/grnet/aquarium/actor/service/user/UserActor.scala @@ -71,7 +71,7 @@ import scala.Some import scala.Right import gr.grnet.aquarium.policy.StdUserAgreement import gr.grnet.aquarium.charging.state.UserStateBootstrap -import gr.grnet.aquarium.charging.bill.BillEntry +import gr.grnet.aquarium.charging.bill.{AbstractBillEntry, BillEntry} /** * @@ -439,7 +439,7 @@ class UserActor extends ReflectiveRoleableActor { try{ val timeslot = event.timeslot val state= if(haveWorkingUserState) Some(this._workingUserState) else None - val billEntry = BillEntry.fromWorkingUserState(timeslot,this._userID,state) + val billEntry = AbstractBillEntry.fromWorkingUserState(timeslot,this._userID,state) val billData = GetUserBillResponseData(this._userID,billEntry) sender ! GetUserBillResponse(Right(billData)) } catch { diff --git a/src/main/scala/gr/grnet/aquarium/charging/bill/BillEntry.scala b/src/main/scala/gr/grnet/aquarium/charging/bill/BillEntry.scala index 5de5905..a449e13 100644 --- a/src/main/scala/gr/grnet/aquarium/charging/bill/BillEntry.scala +++ b/src/main/scala/gr/grnet/aquarium/charging/bill/BillEntry.scala @@ -5,19 +5,23 @@ import gr.grnet.aquarium.util.json.JsonSupport import com.ckkloverdos.resource.FileStreamResource import java.io.File import com.ckkloverdos.props.Props -import gr.grnet.aquarium.converter.{PrettyJsonTextFormat, StdConverters} +import gr.grnet.aquarium.converter.{CompactJsonTextFormat, PrettyJsonTextFormat, StdConverters} import gr.grnet.aquarium.{Aquarium, ResourceLocator, AquariumBuilder} import gr.grnet.aquarium.store.memory.MemStoreProvider import gr.grnet.aquarium.converter.StdConverters._ -import scala.Some +import scala._ import gr.grnet.aquarium.logic.accounting.dsl.Timeslot import java.util.concurrent.atomic.AtomicLong import java.util.{Date, Calendar, GregorianCalendar} import gr.grnet.aquarium.charging.wallet.WalletEntry -import collection.parallel.mutable -import collection.mutable.ListBuffer +import scala.collection.parallel.mutable +import scala.collection.mutable.ListBuffer import gr.grnet.aquarium.Aquarium.EnvKeys import gr.grnet.aquarium.charging.Chargeslot +import scala.collection.immutable.TreeMap +import scala.Some +import gr.grnet.aquarium.charging.Chargeslot + /* * Copyright 2011-2012 GRNET S.A. All rights reserved. @@ -59,23 +63,30 @@ import gr.grnet.aquarium.charging.Chargeslot * @author Prodromos Gerakios */ -class EventEntry(val id:String, - val unitPrice:String, - val startTime:String, - val endTime:String, - val ellapsedTime:String, - val credits:String) extends JsonSupport { +case class ChargeEntry(val id:String, + val unitPrice:String, + val startTime:String, + val endTime:String, + val ellapsedTime:String, + val credits:String) + extends JsonSupport {} + + +class EventEntry(val eventType : String, + val details : List[ChargeEntry]) + extends JsonSupport {} -} -class ResourceEntry(val resourceName : String, - val resourceType : String, - val unitName : String, - val totalCredits : String, - val eventType:String, - val details : List[EventEntry]) extends JsonSupport { +case class ResourceEntry(val resourceName : String, + val resourceType : String, + val unitName : String, + val totalCredits : String, + val details : List[EventEntry]) +extends JsonSupport {} -} + +abstract class AbstractBillEntry + extends JsonSupport {} class BillEntry(val id:String, val userID : String, @@ -85,11 +96,11 @@ class BillEntry(val id:String, val startTime:String, val endTime:String, val bill:List[ResourceEntry] - ) extends JsonSupport { + ) + extends AbstractBillEntry {} -} -object BillEntry { +object AbstractBillEntry { private[this] val counter = new AtomicLong(0L) private[this] def nextUIDObject() = counter.getAndIncrement @@ -104,21 +115,28 @@ object BillEntry { Timeslot(dstart,dend) } */ - private[this] def toEventEntry(c:Chargeslot) : EventEntry = { + private[this] def toChargeEntry(c:Chargeslot) : ChargeEntry = { val unitPrice = c.unitPrice.toString val startTime = c.startMillis.toString val endTime = c.stopMillis.toString val difTime = (c.stopMillis - c.startMillis).toString val credits = c.creditsToSubtract.toString - new EventEntry(counter.getAndIncrement.toString,unitPrice, + new ChargeEntry(counter.getAndIncrement.toString,unitPrice, startTime,endTime,difTime,credits) - } + private[this] def toEventEntry(eventType:String,c:Chargeslot) : EventEntry = + new EventEntry(eventType,List(toChargeEntry(c))) + private[this] def toResourceEntry(w:WalletEntry) : ResourceEntry = { assert(w.sumOfCreditsToSubtract==0.0 || w.chargslotCount > 0) - val rcName = w.resource.toString + val rcName = w.currentResourceEvent.clientID match { + case "pithos" => + w.currentResourceEvent.details("path") + case _ => + w.currentResourceEvent.instanceID + } val rcType = w.resourceType.name val rcUnitName = w.resourceType.unit val eventEntry = new ListBuffer[EventEntry] @@ -147,19 +165,20 @@ object BillEntry { for { c <- w.chargeslots }{ if(c.creditsToSubtract != 0.0) { //Console.err.println("c.creditsToSubtract : " + c.creditsToSubtract) - eventEntry += toEventEntry(c) + eventEntry += toEventEntry(eventType.toString,c) //credits += c.creditsToSubtract } } //Console.err.println("TOTAL resource event credits: " + credits) - new ResourceEntry(rcName,rcType,rcUnitName,credits.toString,eventType.toString,eventEntry.toList) + new ResourceEntry(rcName,rcType,rcUnitName,credits.toString,eventEntry.toList) } private[this] def resourceEntriesAt(t:Timeslot,w:WorkingUserState) : (List[ResourceEntry],Double) = { val ret = new ListBuffer[ResourceEntry] var sum = 0.0 //Console.err.println("Wallet entries: " + w.walletEntries) - for { i <- w.walletEntries} { + val walletEntries = w.walletEntries + for { i <- walletEntries} { if(t.contains(i.referenceTimeslot) && i.sumOfCreditsToSubtract != 0.0){ //Console.err.println("i.sumOfCreditsToSubtract : " + i.sumOfCreditsToSubtract) sum += i.sumOfCreditsToSubtract @@ -172,7 +191,22 @@ object BillEntry { (ret.toList,sum) } - def fromWorkingUserState(t:Timeslot,userID:String,w:Option[WorkingUserState]) : BillEntry = { + private[this] def addResourceEntries(a:ResourceEntry,b:ResourceEntry) : ResourceEntry = { + assert(a.resourceName == b.resourceName) + val totalCredits = (a.totalCredits.toDouble+b.totalCredits.toDouble).toString + a.copy(a.resourceName,a.resourceType,a.unitName,totalCredits,a.details ::: b.details) + } + + private[this] def aggregateResourceEntries(re:List[ResourceEntry]) : List[ResourceEntry] = + re.foldLeft(TreeMap[String,ResourceEntry]()){ (map,r1) => + map.get(r1.resourceName) match { + case None => map + ((r1.resourceName,r1)) + case Some(r0) => (map - r0.resourceName) + + ((r0.resourceName, addResourceEntries(r0,r1))) + } + }.values.toList + + def fromWorkingUserState(t:Timeslot,userID:String,w:Option[WorkingUserState]) : AbstractBillEntry = { val ret = w match { case None => new BillEntry(counter.getAndIncrement.toString, @@ -183,19 +217,39 @@ object BillEntry { Nil) case Some(w) => val (rcEntries,rcEntriesCredits) = resourceEntriesAt(t,w) + val resMap = aggregateResourceEntries(rcEntries) new BillEntry(counter.getAndIncrement.toString, userID,"ok", w.totalCredits.toString, rcEntriesCredits.toString, t.from.getTime.toString,t.to.getTime.toString, - rcEntries) + resMap + ) } //Console.err.println("JSON: " + ret.toJsonString) ret } - // + val jsonSample = "{\n \"id\":\"2\",\n \"userID\":\"loverdos@grnet.gr\",\n \"status\":\"ok\",\n \"remainingCredits\":\"3130.0000027777783\",\n \"deductedCredits\":\"5739.9999944444435\",\n \"startTime\":\"1341090000000\",\n \"endTime\":\"1343768399999\",\n \"bill\":[{\n \"resourceName\":\"diskspace\",\n \"resourceType\":\"diskspace\",\n \"unitName\":\"MB/Hr\",\n \"totalCredits\":\"2869.9999972222217\",\n \"eventType\":\"object update@/Papers/GOTO_HARMFUL.PDF\",\n\t \"details\":[\n\t {\"totalCredits\":\"2869.9999972222217\",\n\t \"details\":[{\n\t \"id\":\"0\",\n\t \"unitPrice\":\"0.01\",\n\t \"startTime\":\"1342735200000\",\n\t \"endTime\":\"1343768399999\",\n\t \"ellapsedTime\":\"1033199999\",\n\t \"credits\":\"2869.9999972222217\"\n\t \t}]\n\t }\n\t ]\n },{\n \"resourceName\":\"diskspace\",\n \"resourceType\":\"diskspace\",\n \"unitName\":\"MB/Hr\",\n \"totalCredits\":\"2869.9999972222217\",\n \"eventType\":\"object update@/Papers/GOTO_HARMFUL.PDF\",\n \"details\":[\t {\"totalCredits\":\"2869.9999972222217\",\n\t \"details\":[{\n\t \"id\":\"0\",\n\t \"unitPrice\":\"0.01\",\n\t \"startTime\":\"1342735200000\",\n\t \"endTime\":\"1343768399999\",\n\t \"ellapsedTime\":\"1033199999\",\n\t \"credits\":\"2869.9999972222217\"\n\t \t}]\n\t }\n\t]\n }]\n}" + def main(args: Array[String]) = { + val b : BillEntry = StdConverters.AllConverters.convertEx[BillEntry](CompactJsonTextFormat(jsonSample)) + val l0 = b.bill + val l1 = aggregateResourceEntries(l0) + + Console.err.println("Initial resources: ") + for{ i <- l0 } Console.err.println("RESOURCE: " + i.toJsonString) + Console.err.println("Aggregate resources: ") + for{ a <- l1 } { + Console.err.println("RESOURCE: %s\n %s\nEND RESOURCE".format(a.resourceName,a.toJsonString)) + } + + val aggr = new BillEntry(b.id,b.userID,b.status,b.remainingCredits,b.deductedCredits,b.startTime,b.endTime,l1) + Console.err.println("Aggregate:\n" + aggr.toJsonString) + } + + // + def main0(args: Array[String]) = { //Console.err.println("JSON: " + (new BillEntry).toJsonString) val propsfile = new FileStreamResource(new File("aquarium.properties")) var _props: Props = Props(propsfile)(StdConverters.AllConverters).getOr(Props()(StdConverters.AllConverters)) diff --git a/src/main/scala/gr/grnet/aquarium/connector/rabbitmq/RabbitMQProducer.scala b/src/main/scala/gr/grnet/aquarium/connector/rabbitmq/RabbitMQProducer.scala index 04c659e..b591287 100644 --- a/src/main/scala/gr/grnet/aquarium/connector/rabbitmq/RabbitMQProducer.scala +++ b/src/main/scala/gr/grnet/aquarium/connector/rabbitmq/RabbitMQProducer.scala @@ -56,9 +56,9 @@ import collection.mutable private class RabbitMQProducerActor extends Actor { def receive = { - case sendMessage:(() => Unit) => + case sendMessage:Function1[_,_] => //Console.err.println("Executing msg ... " + sendMessage.hashCode) - sendMessage() + sendMessage.asInstanceOf[()=>Unit]() case x : AnyRef => //Console.err.println("Dammit ..." + x.getClass.getSimpleName) ()