<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0' version='2.0'><channel><atom:id>tag:blogger.com,1999:blog-4576039096616564465</atom:id><lastBuildDate>Mon, 21 May 2012 06:20:50 +0000</lastBuildDate><title>compmoc blog</title><description>A pragmatic scala blog by a Scala enthusiast</description><link>http://www.crosson.org/</link><managingEditor>noreply@blogger.com (david crosson)</managingEditor><generator>Blogger</generator><openSearch:totalResults>45</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-4576039096616564465.post-6743876518260620892</guid><pubDate>Tue, 08 May 2012 19:54:00 +0000</pubDate><atom:updated>2012-05-08T21:54:21.209+02:00</atom:updated><title>SCALA TIPS : remove unnecessary tests when working with collections...</title><description>Thanks to scala Option type and scala returning the right type behavior, many various kinds of checks can be removed. Example : &lt;pre class="brush: scala;highlight: [7,8,12,13]"&gt;&lt;br /&gt;&lt;br /&gt;val m = Map("A" -&gt; 1, "B" -&gt;3)&lt;br /&gt;&lt;br /&gt;var l1 = List.empty[Int]&lt;br /&gt;var l2 = List.empty[Int]&lt;br /&gt;&lt;br /&gt;// Don't write such thing :&lt;br /&gt;if (m.contains("A")) l1 ::= m.get("A").get&lt;br /&gt;if (m.contains("Z")) l1 ::= m.get("Z").get&lt;br /&gt;println(l1)&lt;br /&gt;&lt;br /&gt;// Instead just write something like :&lt;br /&gt;l2 ++:= m.get("A")&lt;br /&gt;l2 ++:= m.get("Z")&lt;br /&gt;println(l2)&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt; Because concatenating List[Int] with Option[Int] will get you a List[Int], and if the Option[Int] type value is None, nothing will be added to the list :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4576039096616564465-6743876518260620892?l=www.crosson.org' alt='' /&gt;&lt;/div&gt;</description><link>http://www.crosson.org/2012/05/scala-tips-remove-unnecessary-tests.html</link><author>noreply@blogger.com (david crosson)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-4576039096616564465.post-3346791862464941527</guid><pubDate>Tue, 01 May 2012 05:59:00 +0000</pubDate><atom:updated>2012-05-01T07:59:51.823+02:00</atom:updated><title>Variance and bounds example</title><description>&lt;pre class="brush: scala;highlight: []"&gt;&lt;br /&gt;class A&lt;br /&gt;class B extends A&lt;br /&gt;class C extends B&lt;br /&gt;class D extends C&lt;br /&gt;&lt;br /&gt;class E&lt;br /&gt;&lt;br /&gt;class X[+T] {                        // T covariant for input types&lt;br /&gt;  def add[U &gt;: T](x: U): X[U] = this // U contravariant for return type&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class Y[+T &lt;: A] {                   // This time with an upper bound A&lt;br /&gt;  def add[U &gt;: T &lt;: A](y: U): Y[U] = this&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;val a = new A&lt;br /&gt;val b = new B&lt;br /&gt;val c = new C&lt;br /&gt;val d = new D&lt;br /&gt;&lt;br /&gt;val x = new X[C]&lt;br /&gt;val x2 = x.add(b)    // x2 type becomes X[B]&lt;br /&gt;val x3 = x.add(d)    // x3 remains of type X[C]&lt;br /&gt;val x4 = x.add(10)   // x4 type becomes X[Any]&lt;br /&gt;val x6 = x.add("Z")  // x5 type becomes X[java.lang.Object]&lt;br /&gt;&lt;br /&gt;val y = new Y[C]&lt;br /&gt;val y2 = y.add(b)    // y2 type becomes X[B]&lt;br /&gt;val y3 = y.add(d)    // y3 remains of type X[C]&lt;br /&gt;//val y4 = y.add(2)  // Won't compile as Y has an upper bound, it must inherits from A&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;class Z {&lt;br /&gt;  def add[T&lt;%E](e:T) = this  // View Bound, it exists an implicit conversion to E&lt;br /&gt;}&lt;br /&gt;val z  = new Z&lt;br /&gt;//val z1 = z.add(a)  // Won't compile as there no implicit conversion from A to E&lt;br /&gt;implicit def a2E(a:A) = new E&lt;br /&gt;val z2 = z.add(a)&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4576039096616564465-3346791862464941527?l=www.crosson.org' alt='' /&gt;&lt;/div&gt;</description><link>http://www.crosson.org/2012/05/variance-and-bounds-example.html</link><author>noreply@blogger.com (david crosson)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-4576039096616564465.post-151765103881318595</guid><pubDate>Thu, 26 Apr 2012 21:51:00 +0000</pubDate><atom:updated>2012-04-30T13:01:44.684+02:00</atom:updated><title>sbt scala drools expert system skeleton project</title><description>Just released a simple &lt;a href="https://github.com/dacr/scala-drools-dummy-project"&gt;scala drools project skeleton&lt;/a&gt;. The Knowledge base is used to evaluate drools-mvel / scala interaction. &lt;br/&gt;The Knowledge Base :  &lt;pre class="brush: text;highlight: []"&gt;&lt;br /&gt;package dummy;&lt;br /&gt;&lt;br /&gt;dialect "mvel"&lt;br /&gt;&lt;br /&gt;import java.util.LinkedList;&lt;br /&gt;&lt;br /&gt;// --------------------------------------------------------------&lt;br /&gt;&lt;br /&gt;rule "who is young"&lt;br /&gt;  when&lt;br /&gt;    Someone($name:name, age &lt; 30)&lt;br /&gt;  then&lt;br /&gt;    System.out.println($name+" is very young")&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;// --------------------------------------------------------------&lt;br /&gt;&lt;br /&gt;rule "people cars"&lt;br /&gt;  when&lt;br /&gt;    $someone:Someone($name:name)&lt;br /&gt;    $car : Car(someone == $someone)&lt;br /&gt;  then&lt;br /&gt;    System.out.println("One of "+$name+"'s car is "+$car.color.name+" "+$car.model)&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;// --------------------------------------------------------------&lt;br /&gt;&lt;br /&gt;rule "who own at least one red car"&lt;br /&gt;  when&lt;br /&gt;    $someone:Someone($name:name)&lt;br /&gt;    exists Car(someone == $someone, color == Color.red)&lt;br /&gt;  then&lt;br /&gt;    System.out.println($name+" has at least one red car")&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;// --------------------------------------------------------------&lt;br /&gt;&lt;br /&gt;rule "who doesn't have a home"&lt;br /&gt;  when&lt;br /&gt;    $someone:Someone($name:name)&lt;br /&gt;    not Home(someone == $someone)&lt;br /&gt;  then&lt;br /&gt;    insert(new InformationRequest($someone, $name+"'s home is unknown"))&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;// --------------------------------------------------------------&lt;br /&gt;&lt;br /&gt;rule "who doesn't have an address"&lt;br /&gt;  when&lt;br /&gt;    $someone:Someone($name:name)&lt;br /&gt;    Home(someone == $someone, !address.isDefined)&lt;br /&gt;  then&lt;br /&gt;    insert(new InformationRequest($someone, $name+" address is unknown"))&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;// --------------------------------------------------------------&lt;br /&gt;&lt;br /&gt;rule "process information requests"&lt;br /&gt;  when&lt;br /&gt;    InformationRequest($who:someone, $what:message)&lt;br /&gt;  then&lt;br /&gt;    System.out.println("INFORMATION REQUESTED FOR "+$who+" : "+$what)&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;// --------------------------------------------------------------&lt;br /&gt;&lt;br /&gt;rule "who owns more than 1 car"&lt;br /&gt;  when&lt;br /&gt;    $someone : Someone($name:name)&lt;br /&gt;    $cars    : LinkedList( size&gt;1 ) from collect(Car(someone == $someone))&lt;br /&gt;  then&lt;br /&gt;    System.out.println($name+" has "+$cars.size+" cars")  &lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;// --------------------------------------------------------------&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt; And the startup code :  &lt;pre class="brush: scala;highlight: []"&gt;&lt;br /&gt;package dummy&lt;br /&gt;&lt;br /&gt;// ----------------------------------------------------------------&lt;br /&gt;// DOMAIN MODEL&lt;br /&gt;&lt;br /&gt;case class Someone(name:String, age:Int)&lt;br /&gt;&lt;br /&gt;case class Car(someone:Someone, model:String, year:Int, color:Color)&lt;br /&gt;&lt;br /&gt;case class Color(name:String)&lt;br /&gt;&lt;br /&gt;object Color {&lt;br /&gt;  val red = Color("red")&lt;br /&gt;  val blue = Color("blue")&lt;br /&gt;  val green = Color("green")&lt;br /&gt;  val black = Color("black")&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;case class Address(street:String, town:String, country:String)&lt;br /&gt;&lt;br /&gt;case class Home(someone:Someone, address:Option[Address]) &lt;br /&gt;&lt;br /&gt;case class InformationRequest(someone:Someone, message:String)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// ----------------------------------------------------------------&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;import java.io.FileInputStream&lt;br /&gt;import java.io.InputStreamReader&lt;br /&gt;import org.drools.RuleBaseFactory&lt;br /&gt;import org.drools.audit.WorkingMemoryFileLogger&lt;br /&gt;import org.drools.compiler.PackageBuilder&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;object Dummy {&lt;br /&gt;&lt;br /&gt;  def main(args: Array[String]) {&lt;br /&gt;    System.setProperty("drools.dialect.mvel.strict", "false")&lt;br /&gt;    &lt;br /&gt;    val rulesfilename = "src/main/resources/KBExpertise.drl"&lt;br /&gt;    val source = new InputStreamReader(new FileInputStream(rulesfilename))&lt;br /&gt;    &lt;br /&gt;    val builder = new PackageBuilder()&lt;br /&gt;    builder.addPackageFromDrl(source)&lt;br /&gt;    if (builder.hasErrors()) {&lt;br /&gt;      System.out.println(builder.getErrors().toString())&lt;br /&gt;      throw new RuntimeException("Unable to compile " + rulesfilename + ".")&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    val pkg = builder.getPackage()&lt;br /&gt;    val ruleBase = RuleBaseFactory.newRuleBase()&lt;br /&gt;    ruleBase.addPackage(pkg)&lt;br /&gt;&lt;br /&gt;    val session = ruleBase.newStatefulSession()&lt;br /&gt;    //session.addEventListener(new org.drools.event.DebugAgendaEventListener())&lt;br /&gt;    //session.addEventListener(new org.drools.event.DebugWorkingMemoryEventListener())&lt;br /&gt;    &lt;br /&gt;    // setup the audit logging&lt;br /&gt;    val logger:WorkingMemoryFileLogger = new WorkingMemoryFileLogger(session)&lt;br /&gt;    logger.setFileName("drools")&lt;br /&gt;    logger.writeToDisk()&lt;br /&gt;&lt;br /&gt;    val martine = Someone(name="Martine", age=30)&lt;br /&gt;    val martin  = Someone(name="Martin", age=40)&lt;br /&gt;    val jack    = Someone(name="Jack", age=12)&lt;br /&gt;    val martineCar = Car(martine, "Ford", 2010, Color.blue)&lt;br /&gt;    val martinCar  = Car(martin, "GM", 2010, Color.black)&lt;br /&gt;    val martinCar2 = Car(martin, "Ferrari", 2012, Color.red)&lt;br /&gt;    val martinCar3 = Car(martin, "Porshe", 2011, Color.red)&lt;br /&gt;    &lt;br /&gt;    val martinHome = Home(martin, None)&lt;br /&gt;    val jackHome   = Home(jack, Some(Address("221B Baker Street", "London", "England")))&lt;br /&gt;    &lt;br /&gt;    List(martine, martin, jack, &lt;br /&gt;        martineCar, martinCar, martinCar2, martinCar3,&lt;br /&gt;        martinHome, jackHome&lt;br /&gt;    ).foreach(session.insert(_)) &lt;br /&gt;&lt;br /&gt;    session.fireAllRules()&lt;br /&gt;&lt;br /&gt;    session.dispose()&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt; To finish, the build.sbt file, to build and run the project :   &lt;pre class="brush: scala;highlight: []"&gt;&lt;br /&gt;import AssemblyKeys._&lt;br /&gt;&lt;br /&gt;seq(assemblySettings: _*)&lt;br /&gt;&lt;br /&gt;name := "ScalaDroolsDummyProject"&lt;br /&gt;&lt;br /&gt;version := "0.0.1"&lt;br /&gt;&lt;br /&gt;scalaVersion := "2.9.2"&lt;br /&gt;&lt;br /&gt;mainClass in assembly := Some("dummy.Dummy")&lt;br /&gt;&lt;br /&gt;jarName in assembly := "dummy.jar"&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;libraryDependencies += "org.drools" % "drools-compiler" % "5.3.1.Final"&lt;br /&gt;&lt;br /&gt;libraryDependencies += "org.drools" % "drools-core" % "5.3.1.Final"&lt;br /&gt;&lt;br /&gt;libraryDependencies += "org.drools" % "drools-jsr94"  % "5.3.1.Final"&lt;br /&gt;&lt;br /&gt;libraryDependencies += "org.drools" % "drools-decisiontables"  % "5.3.1.Final"&lt;br /&gt;&lt;br /&gt;libraryDependencies += "org.drools" % "knowledge-api"  % "5.3.1.Final"&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;libraryDependencies += "com.thoughtworks.xstream" % "xstream" % "1.4.2"&lt;br /&gt;            &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;libraryDependencies += "org.scalatest" %% "scalatest" % "1.7.2" % "test"&lt;br /&gt;&lt;br /&gt;libraryDependencies += "junit" % "junit" % "4.10" % "test"&lt;br /&gt;&lt;br /&gt;resolvers += "JBoss third party releases repository" at "https://repository.jboss.org/nexus/content/repositories/thirdparty-releases"&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt; Test it by your self :  &lt;pre class="brush: bash;highlight: []"&gt;&lt;br /&gt;$ sbt run&lt;br /&gt;INFORMATION REQUESTED FOR Someone(Martin,40) : Martin address is unknown&lt;br /&gt;One of Martin's car is red Porshe&lt;br /&gt;Martin has 3 cars&lt;br /&gt;Martin has at least one red car&lt;br /&gt;One of Martin's car is red Ferrari&lt;br /&gt;One of Martin's car is black GM&lt;br /&gt;One of Martine's car is blue Ford&lt;br /&gt;Jack is very young&lt;br /&gt;INFORMATION REQUESTED FOR Someone(Martine,30) : Martine's home is unknown&lt;br /&gt;[success] Total time: 6 s, completed 27 avr. 2012 22:35:37&lt;br /&gt;&lt;/pre&gt; And for those who don't know about &lt;a href="https://github.com/harrah/xsbt/wiki"&gt;SBT&lt;/a&gt; or &lt;a href="http://git-scm.com/"&gt;GIT&lt;/a&gt; :  &lt;ul&gt;&lt;li&gt;Download &lt;a href="http://typesafe.artifactoryonline.com/typesafe/ivy-releases/org.scala-tools.sbt/sbt-launch/0.11.2/sbt-launch.jar"&gt;SBT jar file&lt;/a&gt;&lt;ul&gt;&lt;li&gt;You'll get a java jar executable named sbt-launch.jar&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Download the &lt;a href="https://github.com/dacr/scala-drools-dummy-project/zipball/master"&gt;scala drools skeleton zip archive&lt;/a&gt;&lt;ul&gt;&lt;li&gt;You'll get a file which will look like : "dacr-scala-drools-dummy-project-6b43143.zip"&lt;/li&gt;&lt;li&gt;unzip the content and rename the unzipped directory to scala-drools-dummy-project&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;pre class="brush: bash;highlight: [1,23,24,25, 34,35,36,37,38,39,40,41,42]"&gt;&lt;br /&gt;test@localhost /tmp/test $ unzip dacr-scala-drools-dummy-project-6b43143.zip &lt;br /&gt;Archive:  dacr-scala-drools-dummy-project-6b43143.zip&lt;br /&gt;6b43143f369bda03361ca2c5f2376d51ba7d5524&lt;br /&gt;   creating: dacr-scala-drools-dummy-project-6b43143/&lt;br /&gt;  inflating: dacr-scala-drools-dummy-project-6b43143/.gitignore  &lt;br /&gt;  inflating: dacr-scala-drools-dummy-project-6b43143/README  &lt;br /&gt; extracting: dacr-scala-drools-dummy-project-6b43143/RELEASE-NOTES  &lt;br /&gt;  inflating: dacr-scala-drools-dummy-project-6b43143/build.sbt  &lt;br /&gt;  inflating: dacr-scala-drools-dummy-project-6b43143/cleanup.sh  &lt;br /&gt;   creating: dacr-scala-drools-dummy-project-6b43143/project/&lt;br /&gt;  inflating: dacr-scala-drools-dummy-project-6b43143/project/plugins.sbt  &lt;br /&gt;   creating: dacr-scala-drools-dummy-project-6b43143/src/&lt;br /&gt;   creating: dacr-scala-drools-dummy-project-6b43143/src/main/&lt;br /&gt;   creating: dacr-scala-drools-dummy-project-6b43143/src/main/resources/&lt;br /&gt;  inflating: dacr-scala-drools-dummy-project-6b43143/src/main/resources/KBExpertise.drl  &lt;br /&gt;   creating: dacr-scala-drools-dummy-project-6b43143/src/main/scala/&lt;br /&gt;   creating: dacr-scala-drools-dummy-project-6b43143/src/main/scala/dummy/&lt;br /&gt;  inflating: dacr-scala-drools-dummy-project-6b43143/src/main/scala/dummy/Dummy.scala  &lt;br /&gt;   creating: dacr-scala-drools-dummy-project-6b43143/src/test/&lt;br /&gt;   creating: dacr-scala-drools-dummy-project-6b43143/src/test/scala/&lt;br /&gt;   creating: dacr-scala-drools-dummy-project-6b43143/src/test/scala/dummy/&lt;br /&gt;  inflating: dacr-scala-drools-dummy-project-6b43143/src/test/scala/dummy/DummyTest.scala  &lt;br /&gt;test@localhost /tmp/test $ mv dacr-scala-drools-dummy-project-6b43143 scala-drools-dummy-project&lt;br /&gt;test@localhost /tmp/test $ cd scala-drools-dummy-project&lt;br /&gt;test@localhost /tmp/test/scala-drools-dummy-project $ java -jar ~/Downloads/sbt-launch.jar run&lt;br /&gt;[info] Loading project definition from /tmp/test/scala-drools-dummy-project/project&lt;br /&gt;[info] Set current project to ScalaDroolsDummyProject (in build file:/tmp/test/scala-drools-dummy-project/)&lt;br /&gt;[info] Updating {file:/tmp/test/scala-drools-dummy-project/}default-d556eb...&lt;br /&gt;[info] Resolving org.scala-lang#scala-library;2.9.2 ...&lt;br /&gt;[info] Resolving org.drools#drools-compiler;5.3.1.Final ...&lt;br /&gt;...&lt;br /&gt;[info] Compiling 1 Scala source to /tmp/test/scala-drools-dummy-project/target/scala-2.9.2/classes...&lt;br /&gt;[info] Running dummy.Dummy &lt;br /&gt;INFORMATION REQUESTED FOR Someone(Martin,40) : Martin address is unknown&lt;br /&gt;One of Martin's car is red Porshe&lt;br /&gt;Martin has 3 cars&lt;br /&gt;Martin has at least one red car&lt;br /&gt;One of Martin's car is red Ferrari&lt;br /&gt;One of Martin's car is black GM&lt;br /&gt;One of Martine's car is blue Ford&lt;br /&gt;Jack is very young&lt;br /&gt;INFORMATION REQUESTED FOR Someone(Martine,30) : Martine's home is unknown&lt;br /&gt;[success] Total time: 8 s, completed 30 avr. 2012 12:59:17&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4576039096616564465-151765103881318595?l=www.crosson.org' alt='' /&gt;&lt;/div&gt;</description><link>http://www.crosson.org/2012/04/sbt-scala-drools-expert-system-skeleton.html</link><author>noreply@blogger.com (david crosson)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-4576039096616564465.post-5732091187200662523</guid><pubDate>Fri, 20 Apr 2012 21:36:00 +0000</pubDate><atom:updated>2012-04-20T23:36:24.428+02:00</atom:updated><title>JAJMX scala script to list remote JVM threads using JMX...</title><description>A new example script using &lt;a href="http://code.google.com/p/janalyse-jmx/"&gt;JAJMX API&lt;/a&gt;. This script, named &lt;a href="http://code.google.com/p/janalyse-jmx/source/browse/trunk/scripts/lsthreads"&gt;lsthreads&lt;/a&gt;, connects to a remote JVM using just the host adress and the used JMX port, and then list all active threads and theirs current states. Some java options (JAVA_OPTS) have been added to allow using this script against itself.  &lt;pre class="brush: scala;highlight: [1]"&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;JAVA_OPTS=""&lt;br /&gt;JAVA_OPTS=$JAVA_OPTS" -Dcom.sun.management.jmxremote"&lt;br /&gt;JAVA_OPTS=$JAVA_OPTS" -Dcom.sun.management.jmxremote.port=9999"&lt;br /&gt;JAVA_OPTS=$JAVA_OPTS" -Dcom.sun.management.jmxremote.authenticate=false"&lt;br /&gt;JAVA_OPTS=$JAVA_OPTS" -Dcom.sun.management.jmxremote.ssl=false"&lt;br /&gt;exec java $JAVA_OPTS -jar jajmx.jar -nocompdaemon -usejavacp -savecompiled "$0" "$@"&lt;br /&gt;!#&lt;br /&gt;import jajmx._&lt;br /&gt;import javax.management.openmbean.CompositeData&lt;br /&gt;&lt;br /&gt;val host = if (args.size&gt;=1) args(0) else "localhost" &lt;br /&gt;val port = if (args.size&gt;=2) args(1).toInt else 9999&lt;br /&gt;&lt;br /&gt;case class ThreadLock(name:String, ownerId:Option[Long], ownerName:Option[String])&lt;br /&gt;&lt;br /&gt;case class ThreadInfo(name:String, id:Long, state:String,lock:Option[ThreadLock],&lt;br /&gt;                      blockedCount:Long, waitedCount:Long)&lt;br /&gt;&lt;br /&gt;object ThreadInfo {&lt;br /&gt;  def apply(ti:CompositeData) :ThreadInfo = {&lt;br /&gt;   val id           = ti.get("threadId").toString.toLong&lt;br /&gt;   val name         = ti.get("threadName").toString&lt;br /&gt;   val state        = ti.get("threadState").toString&lt;br /&gt;   val blockedCount = ti.get("blockedCount").toString.toLong&lt;br /&gt;   val waitedCount  = ti.get("waitedCount").toString.toLong&lt;br /&gt;   val lock = Option(ti.get("lockName")) map {_.toString} filter {_.size&gt;0} collect {&lt;br /&gt;                case lockName =&gt;&lt;br /&gt;                    val lockOwnerId = Option(ti.get("lockOwnerId")) map {_.asInstanceOf[Long]} filterNot {_ == -1}&lt;br /&gt;                    val lockOwnerName = Option(ti.get("lockOwnerName")) map {_.toString.trim}&lt;br /&gt;                    ThreadLock(lockName, lockOwnerId, lockOwnerName)&lt;br /&gt;              }&lt;br /&gt;   ThreadInfo(name, id, state, lock, blockedCount, waitedCount)&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;JMX.once(host,port) { jmx =&gt;&lt;br /&gt;  for (threading &lt;- jmx.threading) {&lt;br /&gt;    val ids = threading.get[Array[Long]]("AllThreadIds")&lt;br /&gt;    val rawThreadsInfos = threading.call[Array[CompositeData]]("getThreadInfo", ids).get&lt;br /&gt;    val threadsInfos = rawThreadsInfos map {ThreadInfo(_)} toList&lt;br /&gt;    val countByState = threadsInfos groupBy {_.state} map { case (s,l) =&gt; s -&gt; l.size}&lt;br /&gt;    val countByStateStr = countByState map {case (s,l) =&gt; s+":"+l} mkString " "&lt;br /&gt;    println("Total %d  %s".format(threadsInfos.size, countByStateStr))&lt;br /&gt;    for ( ti &lt;- threadsInfos sortBy {_.id } ) {&lt;br /&gt;      println("%d - %s - %s".format(ti.id, ti.state, ti.name) )&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt; Usage examples, with itself and then with a remote apache tomcat:  &lt;pre class="brush: bash;highlight: [1, 17]"&gt;&lt;br /&gt;$ lsthreads&lt;br /&gt;Total 13  TIMED_WAITING:4 WAITING:2 RUNNABLE:7&lt;br /&gt;1 - RUNNABLE - main&lt;br /&gt;2 - WAITING - Reference Handler&lt;br /&gt;3 - WAITING - Finalizer&lt;br /&gt;4 - RUNNABLE - Signal Dispatcher&lt;br /&gt;9 - RUNNABLE - RMI TCP Accept-0&lt;br /&gt;10 - RUNNABLE - RMI TCP Accept-9999&lt;br /&gt;11 - RUNNABLE - RMI TCP Accept-0&lt;br /&gt;12 - RUNNABLE - RMI TCP Connection(1)-127.0.0.1&lt;br /&gt;13 - TIMED_WAITING - RMI Scheduler(0)&lt;br /&gt;14 - TIMED_WAITING - RMI RenewClean-[127.0.0.1:45376]&lt;br /&gt;15 - TIMED_WAITING - GC Daemon&lt;br /&gt;16 - RUNNABLE - RMI TCP Connection(2)-127.0.0.1&lt;br /&gt;17 - TIMED_WAITING - JMX server connection timeout 17&lt;br /&gt;&lt;br /&gt;$ lsthreads 192.168.1.10 1099&lt;br /&gt;Total 17  TIMED_WAITING:6 WAITING:2 RUNNABLE:9&lt;br /&gt;1 - RUNNABLE - main&lt;br /&gt;2 - WAITING - Reference Handler&lt;br /&gt;3 - WAITING - Finalizer&lt;br /&gt;4 - RUNNABLE - Signal Dispatcher&lt;br /&gt;10 - RUNNABLE - RMI TCP Accept-0&lt;br /&gt;11 - RUNNABLE - RMI TCP Accept-1099&lt;br /&gt;12 - RUNNABLE - RMI TCP Accept-0&lt;br /&gt;13 - TIMED_WAITING - GC Daemon&lt;br /&gt;16 - TIMED_WAITING - ContainerBackgroundProcessor[StandardEngine[Catalina]]&lt;br /&gt;17 - RUNNABLE - http-bio-8080-Acceptor-0&lt;br /&gt;18 - TIMED_WAITING - http-bio-8080-AsyncTimeout&lt;br /&gt;19 - RUNNABLE - ajp-bio-8009-Acceptor-0&lt;br /&gt;20 - TIMED_WAITING - ajp-bio-8009-AsyncTimeout&lt;br /&gt;22 - RUNNABLE - RMI TCP Connection(5)-127.0.0.1&lt;br /&gt;23 - TIMED_WAITING - RMI Scheduler(0)&lt;br /&gt;24 - RUNNABLE - RMI TCP Connection(6)-127.0.0.1&lt;br /&gt;27 - TIMED_WAITING - JMX server connection timeout 27&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4576039096616564465-5732091187200662523?l=www.crosson.org' alt='' /&gt;&lt;/div&gt;</description><link>http://www.crosson.org/2012/04/jajmx-scala-script-to-list-remote-jvm.html</link><author>noreply@blogger.com (david crosson)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-4576039096616564465.post-8716922569728989653</guid><pubDate>Tue, 17 Apr 2012 22:10:00 +0000</pubDate><atom:updated>2012-04-18T00:35:24.822+02:00</atom:updated><title>First nasdaq stock query using scala and JASeries</title><description>The following script is a first attempt to make a stock query over nasdaq using &lt;a href="http://code.google.com/p/janalyse-series/"&gt;JASeries&lt;/a&gt; (scala time series API).  &lt;pre class="brush: scala;highlight: [33,34,35]"&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;exec java -jar jaseries.jar -nocompdaemon -usejavacp -savecompiled "$0" "$@"&lt;br /&gt;!#&lt;br /&gt;&lt;br /&gt;import io.Source&lt;br /&gt;import fr.janalyse.series._&lt;br /&gt;&lt;br /&gt;// Get nasdaq codes&lt;br /&gt;val codes = &lt;br /&gt;  Source.fromURL("http://www.nasdaqtrader.com/dynamic/SymDir/nasdaqlisted.txt")&lt;br /&gt;    .getLines&lt;br /&gt;    .map(_.split("[|]",2).head)&lt;br /&gt;    .toList.tail.init //.take(10)&lt;br /&gt;&lt;br /&gt;// Get nasdaq stocks history&lt;br /&gt;val stocks =&lt;br /&gt;  codes.flatMap(code =&gt;&lt;br /&gt;    try {&lt;br /&gt;     Some(code -&gt; CSV2Series.fromURL("http://ichart.finance.yahoo.com/table.csv?s="+code))&lt;br /&gt;    } catch {&lt;br /&gt;      case x:java.io.FileNotFoundException =&gt; &lt;br /&gt;        println("Could'nt find %s stock data".format(code))&lt;br /&gt;        None&lt;br /&gt;    }&lt;br /&gt;  )&lt;br /&gt;&lt;br /&gt;// get close series&lt;br /&gt;val closes = stocks flatMap { case (code, allSeries) =&gt; &lt;br /&gt;  allSeries.get("Close").map(_.rename(code+" Close"))&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;val top10incr =&lt;br /&gt;  closes&lt;br /&gt;    .sortBy( _.stat.linearApproximation.slope)&lt;br /&gt;    .take(20)&lt;br /&gt;    &lt;br /&gt;// print highest slope top20, but remember that all history data is taken into&lt;br /&gt;// account, so the last value may not be quiter higher than the first one.&lt;br /&gt;for(stock &lt;- top10incr) {&lt;br /&gt;  println("%s : %f -&gt; %f".format(stock.name, stock.head.value, stock.last.value))&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt; This script is the starting point to next JASeries improvements and new features.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4576039096616564465-8716922569728989653?l=www.crosson.org' alt='' /&gt;&lt;/div&gt;</description><link>http://www.crosson.org/2012/04/first-nasdaq-stock-query-using-scala.html</link><author>noreply@blogger.com (david crosson)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-4576039096616564465.post-7327742320285990796</guid><pubDate>Fri, 13 Apr 2012 22:02:00 +0000</pubDate><atom:updated>2012-04-20T23:50:35.427+02:00</atom:updated><title>JAJMX scala script to list all available JVM numerical JMX values</title><description>Using &lt;a href="http://code.google.com/p/janalyse-jmx/"&gt;JAJMX&lt;/a&gt; it becomes very easy to list all available numerical values of a given JVM JMX plateform :  &lt;pre class="brush: scala;highlight: [15,16,17,18,19]"&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;JAVA_OPTS=""&lt;br /&gt;JAVA_OPTS=$JAVA_OPTS" -Dcom.sun.management.jmxremote"&lt;br /&gt;JAVA_OPTS=$JAVA_OPTS" -Dcom.sun.management.jmxremote.port=9999"&lt;br /&gt;JAVA_OPTS=$JAVA_OPTS" -Dcom.sun.management.jmxremote.authenticate=false"&lt;br /&gt;JAVA_OPTS=$JAVA_OPTS" -Dcom.sun.management.jmxremote.ssl=false"&lt;br /&gt;exec java $JAVA_OPTS -jar jajmx.jar -nocompdaemon -usejavacp -savecompiled "$0" "$@"&lt;br /&gt;!#&lt;br /&gt;&lt;br /&gt;import fr.janalyse.jmx._&lt;br /&gt;&lt;br /&gt;val host  = args.headOption.getOrElse("localhost")&lt;br /&gt;val port  = if (args.size&gt;1) args.tail.head.toInt else 9999&lt;br /&gt;&lt;br /&gt;JMX.once(host, port) { jmx =&gt;&lt;br /&gt;  for(mbean &lt;- jmx.mbeans ;&lt;br /&gt;      attr  &lt;- mbean.attributes collect {case n:RichNumberAttribute =&gt; n};&lt;br /&gt;      value &lt;- mbean.getLong(attr)) {&lt;br /&gt;    println("%s - %s = %d".format(mbean.name, attr.name, value))&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt; Some jvm parameters (JAVA_OPTS) have been added in order to make possible to test this script against itself. So without any arguments it will give you such results :  &lt;pre class="brush: bash;highlight: [1]"&gt;&lt;br /&gt;$ ./lsnum&lt;br /&gt;java.lang:type=Memory - ObjectPendingFinalizationCount = 0&lt;br /&gt;java.lang:type=MemoryPool,name=PS Eden Space - CollectionUsageThreshold = 0&lt;br /&gt;java.lang:type=MemoryPool,name=PS Eden Space - CollectionUsageThresholdCount = 0&lt;br /&gt;java.lang:type=MemoryPool,name=PS Survivor Space - CollectionUsageThreshold = 0&lt;br /&gt;java.lang:type=MemoryPool,name=PS Survivor Space - CollectionUsageThresholdCount = 0&lt;br /&gt;java.lang:type=MemoryPool,name=Code Cache - UsageThreshold = 0&lt;br /&gt;java.lang:type=MemoryPool,name=Code Cache - UsageThresholdCount = 0&lt;br /&gt;java.lang:type=GarbageCollector,name=PS MarkSweep - CollectionCount = 1&lt;br /&gt;java.lang:type=GarbageCollector,name=PS MarkSweep - CollectionTime = 90&lt;br /&gt;java.lang:type=Runtime - StartTime = 1334354060679&lt;br /&gt;java.lang:type=Runtime - Uptime = 5497&lt;br /&gt;java.lang:type=ClassLoading - LoadedClassCount = 4806&lt;br /&gt;java.lang:type=ClassLoading - UnloadedClassCount = 0&lt;br /&gt;java.lang:type=ClassLoading - TotalLoadedClassCount = 4806&lt;br /&gt;java.lang:type=Threading - DaemonThreadCount = 12&lt;br /&gt;java.lang:type=Threading - PeakThreadCount = 13&lt;br /&gt;java.lang:type=Threading - CurrentThreadCpuTime = 40000000&lt;br /&gt;java.lang:type=Threading - CurrentThreadUserTime = 40000000&lt;br /&gt;java.lang:type=Threading - ThreadCount = 13&lt;br /&gt;java.lang:type=Threading - TotalStartedThreadCount = 13&lt;br /&gt;java.lang:type=Compilation - TotalCompilationTime = 7144&lt;br /&gt;java.lang:type=MemoryPool,name=PS Perm Gen - CollectionUsageThreshold = 0&lt;br /&gt;java.lang:type=MemoryPool,name=PS Perm Gen - CollectionUsageThresholdCount = 0&lt;br /&gt;java.lang:type=MemoryPool,name=PS Perm Gen - UsageThreshold = 0&lt;br /&gt;java.lang:type=MemoryPool,name=PS Perm Gen - UsageThresholdCount = 0&lt;br /&gt;java.lang:type=GarbageCollector,name=PS Scavenge - CollectionCount = 3&lt;br /&gt;java.lang:type=GarbageCollector,name=PS Scavenge - CollectionTime = 57&lt;br /&gt;java.lang:type=OperatingSystem - MaxFileDescriptorCount = 4096&lt;br /&gt;java.lang:type=OperatingSystem - OpenFileDescriptorCount = 19&lt;br /&gt;java.lang:type=OperatingSystem - CommittedVirtualMemorySize = 4598407168&lt;br /&gt;java.lang:type=OperatingSystem - FreePhysicalMemorySize = 10819850240&lt;br /&gt;java.lang:type=OperatingSystem - FreeSwapSpaceSize = 10742177792&lt;br /&gt;java.lang:type=OperatingSystem - ProcessCpuTime = 13030000000&lt;br /&gt;java.lang:type=OperatingSystem - TotalPhysicalMemorySize = 16816541696&lt;br /&gt;java.lang:type=OperatingSystem - TotalSwapSpaceSize = 10742177792&lt;br /&gt;java.lang:type=OperatingSystem - AvailableProcessors = 6&lt;br /&gt;java.lang:type=OperatingSystem - SystemLoadAverage = 0&lt;br /&gt;java.lang:type=MemoryPool,name=PS Old Gen - CollectionUsageThreshold = 0&lt;br /&gt;java.lang:type=MemoryPool,name=PS Old Gen - CollectionUsageThresholdCount = 0&lt;br /&gt;java.lang:type=MemoryPool,name=PS Old Gen - UsageThreshold = 0&lt;br /&gt;java.lang:type=MemoryPool,name=PS Old Gen - UsageThresholdCount = 0&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4576039096616564465-7327742320285990796?l=www.crosson.org' alt='' /&gt;&lt;/div&gt;</description><link>http://www.crosson.org/2012/04/list-all-available-jvm-numerical-jmx.html</link><author>noreply@blogger.com (david crosson)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-4576039096616564465.post-6580306348969797387</guid><pubDate>Fri, 13 Apr 2012 20:11:00 +0000</pubDate><atom:updated>2012-04-13T22:11:27.657+02:00</atom:updated><title>JASeries (JAnalyseSeries) 1.1.0 released</title><description>&lt;p&gt;JASeries is a time numeric series operations API. The goal is to make simple, time series summaries generation, using sampling and various kind of cells merging. (&lt;a href="http://code.google.com/p/janalyse-series/"&gt; ** project page **&lt;/a&gt;) &lt;/p&gt; &lt;h3&gt;Latest changes :&lt;/h3&gt; &lt;ul&gt;&lt;li&gt;Statistics : alive added = OpenCell.time - CloseCell.time = series alive period of time&lt;/li&gt;&lt;li&gt;realias() without any argument means take the name as the alias.&lt;/li&gt;&lt;li&gt;added braces to delta, compact, zeroBased &lt;/li&gt;&lt;li&gt;Chart seriesScales method renamed to scales&lt;/li&gt;&lt;li&gt;Chart new method : colors which returns a map of [Series[Cell], Color]&lt;/li&gt;&lt;li&gt;Added a package object jaseries to define shortcuts to     fr.janalyse.series.CSV2Series, fr.janalyse.series.view.Chart classes and objects&lt;/li&gt;&lt;/ul&gt;  &lt;h3&gt;Google stock summary catchup scala script&lt;/h3&gt;&lt;pre class="brush: scala;highlight: []"&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;exec java -jar jaseries.jar -nocompdaemon -usejavacp -savecompiled "$0" "$@"&lt;br /&gt;!#&lt;br /&gt;&lt;br /&gt;val allSeries = jaseries.CSV2Series.fromURL("http://ichart.finance.yahoo.com/table.csv?s=GOOG")&lt;br /&gt;val closeSeries = allSeries("Close")&lt;br /&gt;&lt;br /&gt;println("GOOGLE stock summary")&lt;br /&gt;println("Higher : "+closeSeries.max)&lt;br /&gt;println("Lowest : "+closeSeries.min)&lt;br /&gt;println("Week Trend : "+closeSeries.stat.linearApproximation.daySlope*7)&lt;br /&gt;println("Latest : "+closeSeries.last)&lt;br /&gt;&lt;/pre&gt;   &lt;h3&gt;Apple trend chart generation scala script&lt;/h3&gt;&lt;pre class="brush: scala;highlight: []"&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;exec java -jar jaseries.jar -nocompdaemon -usejavacp -savecompiled "$0" "$@"&lt;br /&gt;!#&lt;br /&gt;&lt;br /&gt;val allSeries = jaseries.CSV2Series.fromURL("http://ichart.finance.yahoo.com/table.csv?s=AAPL")&lt;br /&gt;val closeSeries = allSeries("Close").realias("Apple stock value")    &lt;br /&gt;jaseries.Chart(closeSeries).toFile("AppleStockTrend.jpg")&lt;br /&gt;&lt;/pre&gt; &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-HVx8r6VFfDk/T4iHybMrPRI/AAAAAAAAFi4/MUu5VSQk0Bc/s1600/AppleStockTrend.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="225" width="400" src="http://3.bp.blogspot.com/-HVx8r6VFfDk/T4iHybMrPRI/AAAAAAAAFi4/MUu5VSQk0Bc/s400/AppleStockTrend.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4576039096616564465-6580306348969797387?l=www.crosson.org' alt='' /&gt;&lt;/div&gt;</description><link>http://www.crosson.org/2012/04/jaseries-janalyseseries-110-released.html</link><author>noreply@blogger.com (david crosson)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-HVx8r6VFfDk/T4iHybMrPRI/AAAAAAAAFi4/MUu5VSQk0Bc/s72-c/AppleStockTrend.jpg' height='72' width='72'/><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-4576039096616564465.post-810744935534532222</guid><pubDate>Fri, 13 Apr 2012 19:15:00 +0000</pubDate><atom:updated>2012-04-13T21:15:56.410+02:00</atom:updated><title>JAJMX (JAnalyseJMX) 0.3.0 released</title><description>&lt;p&gt;JAJMX is high level scala JMX API. The goal is to simplify to the maximum JMX operations. (&lt;a href="http://code.google.com/p/janalyse-jmx/"&gt; ** project page **&lt;/a&gt;) &lt;/p&gt; Latest changes :  &lt;ul&gt;&lt;li&gt;JMXOptions now contains an extra field "name" which allow user to friendly identify a remote jmx system&lt;/li&gt;&lt;li&gt;added a package object jajmx to define shortcuts to fr.janalyse.jmx.JMX class and object&lt;/li&gt;&lt;li&gt;JMX.connect renamed to JMX.once&lt;/li&gt;&lt;li&gt;scaladoc generation now works fine, follow hack described here : https://github.com/harrah/xsbt/issues/85&lt;/li&gt;&lt;/ul&gt; &lt;/br&gt;&lt;h3&gt;jvm force gc script&lt;/h3&gt;&lt;pre class="brush: scala;highlight: [4]"&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;exec java -jar jajmx.jar -nocompdaemon -usejavacp -savecompiled "$0" "$@"&lt;br /&gt;!#&lt;br /&gt;&lt;br /&gt;jajmx.JMX.once("127.0.0.1", 1099) { _.memory map {_ call "gc"} }&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;/pre&gt; &lt;h3&gt;jmx grep script&lt;/h3&gt;&lt;pre class="brush: scala;highlight: []"&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;exec java -jar jajmx.jar -nocompdaemon -usejavacp -savecompiled "$0" "$@"&lt;br /&gt;!#&lt;br /&gt;&lt;br /&gt;import jajmx._&lt;br /&gt;&lt;br /&gt;if (args.size &lt; 2) {&lt;br /&gt;  println("Usage   : jmxgrep host port searchMask1 ... searchMaskN")&lt;br /&gt;  System.exit(1)&lt;br /&gt;}&lt;br /&gt;val host  = args(0)&lt;br /&gt;val port  = args(1).toInt&lt;br /&gt;val masks = args.toList.drop(2) map {s=&gt;("(?i)"+s).r}&lt;br /&gt;&lt;br /&gt;def truncate(str:String, n:Int=60) = if (str.size&gt;n) str.take(n)+"..." else str&lt;br /&gt;&lt;br /&gt;JMX.once(host, port) { jmx =&gt;&lt;br /&gt;  for(mbean &lt;- jmx.mbeans ; attr &lt;- mbean.attributes; value &lt;- mbean.getString(attr)) {&lt;br /&gt;    val found = List(mbean.name, attr.name, value) exists { &lt;br /&gt;         item =&gt; masks exists {_.findFirstIn(item).isDefined }&lt;br /&gt;    }&lt;br /&gt;    if (found) println("%s - %s = %s".format(mbean.name, attr.name, truncate(value)))&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4576039096616564465-810744935534532222?l=www.crosson.org' alt='' /&gt;&lt;/div&gt;</description><link>http://www.crosson.org/2012/04/jajmx-janalysejmx-030-released.html</link><author>noreply@blogger.com (david crosson)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-4576039096616564465.post-3315712509034037314</guid><pubDate>Thu, 12 Apr 2012 06:53:00 +0000</pubDate><atom:updated>2012-04-12T15:02:43.710+02:00</atom:updated><title>JASSH (JAnalyseSSH) 0.7.3 released</title><description>&lt;p&gt;JASSH is a high level scala SSH API for easy and fast operations on remote servers. (&lt;a href="http://code.google.com/p/janalyse-ssh/"&gt; ** project page **&lt;/a&gt;) &lt;/p&gt; Latest changes :  &lt;ul&gt;&lt;li&gt;JSCH updated to release 0.1.47&lt;/li&gt;&lt;li&gt;SSHOptions now contains an extra field "name" which allow user to friendly identify a remote ssh system&lt;/li&gt;&lt;li&gt;SSHOptions password type is now of SSHPassword type instead of String. Implicit conversions are provided from String, Option[String]&lt;/li&gt;&lt;li&gt;SSHShell batch method renamed to execute&lt;/li&gt;&lt;/ul&gt;&lt;/br&gt;&lt;h3&gt;hello scala script&lt;/h3&gt;&lt;pre class="brush: scala;highlight: [4]"&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;exec java -jar jassh.jar -nocompdaemon -usejavacp -savecompiled "$0" "$@"&lt;br /&gt;!#&lt;br /&gt;&lt;br /&gt;print(jassh.SSH.shell("localhost", "test", "testtest") {_ execute "echo Hello `hostname`" } )&lt;br /&gt;  &lt;br /&gt;  &lt;br /&gt;&lt;/pre&gt; &lt;h3&gt;remote vmstat scala script&lt;/h3&gt;&lt;pre class="brush: scala;highlight: [5,6]"&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;exec java -jar jassh.jar -nocompdaemon -usejavacp -savecompiled "$0" "$@"&lt;br /&gt;!#&lt;br /&gt;&lt;br /&gt;jassh.SSH.once("localhost", "test", "testtest")  {&lt;br /&gt;  _.run("vmstat 1 10", println(_.getOrElse("")).waitForEnd&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4576039096616564465-3315712509034037314?l=www.crosson.org' alt='' /&gt;&lt;/div&gt;</description><link>http://www.crosson.org/2012/04/jassh-janalysessh-073-released.html</link><author>noreply@blogger.com (david crosson)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-4576039096616564465.post-8623242202517065808</guid><pubDate>Fri, 06 Apr 2012 19:57:00 +0000</pubDate><atom:updated>2012-04-12T15:03:36.079+02:00</atom:updated><title>JASSH (JAnalyseSSH) 0.7.2 released</title><description>&lt;p&gt;JASSH is a high level scala SSH API for easy and fast operations on remote servers. (&lt;a href="http://code.google.com/p/janalyse-ssh/"&gt; ** project page **&lt;/a&gt;) &lt;/p&gt; Latest changes : &lt;ul&gt;&lt;li&gt;added a package object jassh to define shortcuts to fr.janalyse.ssh.SSH class and object&lt;/li&gt;&lt;li&gt;SSHOptions, host parameter is now in first position !&lt;/li&gt;&lt;/ul&gt;&lt;br/&gt;These small changes enable even simpler scripts :&lt;br/&gt;&lt;/br&gt;&lt;h3&gt;hello scala script&lt;/h3&gt;&lt;pre class="brush: scala;highlight: [5]"&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;exec java -jar jassh.jar -nocompdaemon -usejavacp -savecompiled "$0" "$@"&lt;br /&gt;!#&lt;br /&gt;&lt;br /&gt;println(jassh.SSH.shell("localhost", "test", Some("testtest")) { _ execute "echo -n Hello `hostname`"})&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt; &lt;h3&gt;remote vmstat scala script&lt;/h3&gt;&lt;pre class="brush: scala;highlight: [5,6]"&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;exec java -jar jassh.jar -nocompdaemon -usejavacp -savecompiled "$0" "$@"&lt;br /&gt;!#&lt;br /&gt;&lt;br /&gt;jassh.SSH.once("localhost", "test", password=Some("testtest"))  {&lt;br /&gt;  _.run("vmstat 1 10", println(_.getOrElse("")).waitForEnd&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4576039096616564465-8623242202517065808?l=www.crosson.org' alt='' /&gt;&lt;/div&gt;</description><link>http://www.crosson.org/2012/04/jassh-janalysessh-072-released.html</link><author>noreply@blogger.com (david crosson)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-4576039096616564465.post-2293323134132259509</guid><pubDate>Sun, 01 Apr 2012 20:28:00 +0000</pubDate><atom:updated>2012-04-01T22:34:00.570+02:00</atom:updated><title>Leave it crash, akka will restart it for you !!!</title><description>Akka is an awesome tool, even using default configuration, you do not have anymore to worry about failure management and recovery details. I've been bluffed to discover that my new monitoring system prototype (akka/scala based) was able to recovery by itself from errors, while I didn't yet implement such features !!&lt;br/&gt;&lt;br/&gt;So In order to illustrate this feature, I've written a simple example that illustrates this behavior. The RobustActor actor keeps a ssh connection to a remote system (&lt;a href="http://www.crosson.org/2012/04/janalysessh-070-released.html"&gt;using janalyse-ssh scala ssh api&lt;/a&gt;), and execute/print every 5s the "date" command :  &lt;pre class="brush: scala;highlight: [23,26,34]"&gt;&lt;br /&gt;package dummy&lt;br /&gt;&lt;br /&gt;import akka.actor.ActorSystem&lt;br /&gt;import akka.actor.Actor&lt;br /&gt;import akka.util.duration._&lt;br /&gt;import com.typesafe.config.ConfigFactory&lt;br /&gt;import akka.actor.Props&lt;br /&gt;&lt;br /&gt;import fr.janalyse.ssh._&lt;br /&gt;&lt;br /&gt;object DummySSH {&lt;br /&gt; def main(args:Array[String]) {&lt;br /&gt;      val system=ActorSystem("DummySSHSystem",ConfigFactory.load.getConfig("dummySSH"))&lt;br /&gt;      system.actorOf(&lt;br /&gt;        Props(new RobustActor(system)),&lt;br /&gt;        name="RobustActor")&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;class RobustActor(system:ActorSystem) extends Actor {&lt;br /&gt;  &lt;br /&gt;  val sh = SSH(host="localhost", username="test", password=Some("testtest")).newShell&lt;br /&gt;  &lt;br /&gt;  override def preStart() {&lt;br /&gt;    system.scheduler.schedule(1 seconds, 5 seconds, self, "doit")&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  override def postStop() {&lt;br /&gt;    sh.close()&lt;br /&gt;  }&lt;br /&gt;    &lt;br /&gt;  def receive = {&lt;br /&gt;    case "doit" =&gt; print(sh execute "date")&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;  If we start this example code, we wait a little, we identify the sshd process that manages the established ssh connection and then we kill the sshd process, akka will intercept RobustActor internal exception and restart this actor for us !  &lt;pre class="brush: bash;highlight: [18,40]"&gt;&lt;br /&gt;$ sbt run&lt;br /&gt;[info] Loading project definition from /home/dcr/dev-new/akka-sandbox/project&lt;br /&gt;[info] Set current project to AkkaSandbox (in build file:/home/dcr/dev-new/akka-sandbox/)&lt;br /&gt;[info] Compiling 1 Scala source to /home/dcr/dev-new/akka-sandbox/target/scala-2.9.1/classes...&lt;br /&gt;&lt;br /&gt;Multiple main classes detected, select one to run:&lt;br /&gt;&lt;br /&gt; [1] dummy.Dummy&lt;br /&gt; [2] dummy.DummySSH&lt;br /&gt;&lt;br /&gt;Enter number: 2&lt;br /&gt;&lt;br /&gt;[info] Running dummy.DummySSH &lt;br /&gt;dim. avril  1 22:15:32 CEST 2012&lt;br /&gt;dim. avril  1 22:15:37 CEST 2012&lt;br /&gt;dim. avril  1 22:15:42 CEST 2012&lt;br /&gt;dim. avril  1 22:15:47 CEST 2012&lt;br /&gt;[ERROR] [04/01/2012 22:15:53.92] [DummySSHSystem-akka.actor.default-dispatcher-3] [akka://DummySSHSystem/user/RobustActor] Pipe closed&lt;br /&gt;java.io.IOException: Pipe closed&lt;br /&gt; at java.io.PipedInputStream.checkStateForReceive(PipedInputStream.java:244)&lt;br /&gt; at java.io.PipedInputStream.receive(PipedInputStream.java:210)&lt;br /&gt; at java.io.PipedOutputStream.write(PipedOutputStream.java:132)&lt;br /&gt; at java.io.OutputStream.write(OutputStream.java:58)&lt;br /&gt; at fr.janalyse.ssh.SSHShell$Producer.sendCommand(SSHAPI.scala:480)&lt;br /&gt; at fr.janalyse.ssh.SSHShell.sendCommand(SSHAPI.scala:475)&lt;br /&gt; at fr.janalyse.ssh.SSHShell.execute(SSHAPI.scala:448)&lt;br /&gt; at dummy.RobustActor$$anonfun$receive$1.apply(DummySSH.scala:34)&lt;br /&gt; at dummy.RobustActor$$anonfun$receive$1.apply(DummySSH.scala:33)&lt;br /&gt; at akka.actor.Actor$class.apply(Actor.scala:290)&lt;br /&gt; at dummy.RobustActor.apply(DummySSH.scala:21)&lt;br /&gt; at akka.actor.ActorCell.invoke(ActorCell.scala:617)&lt;br /&gt; at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:179)&lt;br /&gt; at akka.dispatch.Mailbox.run(Mailbox.scala:161)&lt;br /&gt; at akka.dispatch.ForkJoinExecutorConfigurator$MailboxExecutionTask.exec(AbstractDispatcher.scala:505)&lt;br /&gt; at akka.jsr166y.ForkJoinTask.doExec(ForkJoinTask.java:259)&lt;br /&gt; at akka.jsr166y.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:997)&lt;br /&gt; at akka.jsr166y.ForkJoinPool.runWorker(ForkJoinPool.java:1495)&lt;br /&gt; at akka.jsr166y.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:104)&lt;br /&gt;&lt;br /&gt;dim. avril  1 22:15:54 CEST 2012&lt;br /&gt;dim. avril  1 22:15:58 CEST 2012&lt;br /&gt;&lt;/pre&gt; &lt;br/&gt;&lt;br/&gt;To identify the process which manages our example ssh connection, just use the following commands, list all sshd processes which belongs to test user, then take the process that do not use your current test shell session.  &lt;pre class="brush: bash;highlight: [1,8,10]"&gt;&lt;br /&gt;test@lanfeust ~ $ ps -ef | grep "^test"&lt;br /&gt;test      8824  8815  0 11:20 ?        00:00:00 sshd: test@pts/7 &lt;br /&gt;test      8825  8824  0 11:20 pts/7    00:00:00 -bash&lt;br /&gt;test     32468 32458  0 22:15 ?        00:00:00 sshd: test@pts/8 &lt;br /&gt;test     32469 32468  0 22:15 pts/8    00:00:00 -bash&lt;br /&gt;test     32474  8825  0 22:15 pts/7    00:00:00 ps -ef&lt;br /&gt;test     32475  8825  0 22:15 pts/7    00:00:00 grep --colour=auto ^test&lt;br /&gt;test@lanfeust ~ $ tty&lt;br /&gt;/dev/pts/7&lt;br /&gt;test@lanfeust ~ $ kill -9 32468&lt;br /&gt;test@lanfeust ~ $ &lt;br /&gt;&lt;/pre&gt; &lt;br/&gt;This example source code is available here : &lt;a href="https://github.com/dacr/akka-sandbox"&gt;akka-sandbox&lt;/a&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4576039096616564465-2293323134132259509?l=www.crosson.org' alt='' /&gt;&lt;/div&gt;</description><link>http://www.crosson.org/2012/04/leave-it-crash-akka-will-restart-it-for.html</link><author>noreply@blogger.com (david crosson)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-4576039096616564465.post-6859050171570899820</guid><pubDate>Sun, 01 Apr 2012 13:50:00 +0000</pubDate><atom:updated>2012-04-13T21:29:48.420+02:00</atom:updated><title>JASSH (JAnalyseSSH) 0.7.0 released</title><description>&lt;a href="http://code.google.com/p/janalyse-ssh/"&gt;JAnalyseSSH&lt;/a&gt; is a jsch based scala SSH API which aims to simplify SSH operations.&lt;br/&gt;&lt;br/&gt;&lt;h2&gt;The hello world script...&lt;/h2&gt;&lt;i&gt;(It requires a local user named "test" with password "testtest", remember that you can remove the password, if your public key has been added in authorized_keys file of the test user)&lt;/i&gt; &lt;br/&gt;&lt;pre class="brush: scala;highlight: []"&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;exec java -jar jassh.jar -usejavacp "$0" "$@"&lt;br /&gt;!#&lt;br /&gt;import fr.janalyse.ssh._&lt;br /&gt;SSH.shell(host="localhost", username="test", password=Some("testtest")) { sh =&gt;&lt;br /&gt;  println(sh.execute("""echo -n "Hello World from `hostname`" """))&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt; &lt;h2&gt;... and the remote vmstat script&lt;/h2&gt;&lt;pre class="brush: scala;highlight: []"&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;exec java -jar jassh.jar -usejavacp "$0" "$@"&lt;br /&gt;!#&lt;br /&gt;import fr.janalyse.ssh._&lt;br /&gt;SSH.once(host="localhost", username="test", password=Some("testtest"))  { ssh =&gt;&lt;br /&gt;  val executor = ssh.run("vmstat 1 10", (l)=&gt; l foreach {println(_)})&lt;br /&gt;  executor.waitForEnd&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt; &lt;br/&gt;&lt;br/&gt;&lt;h2&gt;Releases notes for 0.7.0&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;Added new method to SSH : newShell &amp; newSftp for user to manage themselves shell and sftp session&lt;/li&gt;&lt;li&gt;Some internal changes to SSHExec class, in order to try to remove actor dependency. Mixing actors systems looks problematic&lt;/li&gt;&lt;li&gt;SSHShell new implementation, no more actors used, better performances and behavior, ... (throughput : 504 cmd/s using persistency)&lt;/li&gt;&lt;li&gt;SSHExec last result line is no longer lost&lt;/li&gt;&lt;li&gt;SSHOptions : new parameter : "prompt" to enable custom shell or console command to be use.&lt;br/&gt;                prompt provide to SSHShell the way to separate command results&lt;/li&gt;&lt;li&gt;SSHOptions : connectionTimeout renamed into timeout &lt;li&gt;Various cleanup and enhancements&lt;/li&gt;&lt;li&gt;Tests : compare performances persistent SSHShell versus SSHExec  commands throughputs&lt;/li&gt;&lt;li&gt;SSH : Add an execute immediate method which rely on SSHExec, not SSHShell ! (throughput : 93cmd/s) &lt;br/&gt;         execOnce &amp; execOnceAndTrim&lt;/li&gt;&lt;li&gt;SSHExec : Do not rely on DaemonActor/Actor anymore&lt;/li&gt;&lt;li&gt;SSHShell : Removed init Thread.sleep =&gt; Better performances (throughput : 37 cmd/s instead 1cmd/s)&lt;/li&gt;&lt;li&gt;SSH.connect becomes SSH.once&lt;/li&gt;&lt;li&gt;Removing apply in SSH class as it may encourage bad usage, and close not called&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4576039096616564465-6859050171570899820?l=www.crosson.org' alt='' /&gt;&lt;/div&gt;</description><link>http://www.crosson.org/2012/04/janalysessh-070-released.html</link><author>noreply@blogger.com (david crosson)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-4576039096616564465.post-4831769060146592619</guid><pubDate>Sun, 11 Mar 2012 13:57:00 +0000</pubDate><atom:updated>2012-03-11T14:57:38.997+01:00</atom:updated><title>Dependency injection using scala traits</title><description> Consider the following code example which does not depend on any kind of configuration system. We've just defined a trait, XConfiguration, which describes how we can get simple configuration data.   &lt;pre class="brush: scala;highlight: []"&gt;&lt;br /&gt;trait XConfigurable {&lt;br /&gt;  def getSetting(key:String):Option[String] = None&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;trait XPlugin extends XConfigurable {&lt;br /&gt;  def domain:String&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;trait XSniffPlugin extends XPlugin {&lt;br /&gt;  val period=getSetting("period") map {_.toLong} getOrElse 5000L&lt;br /&gt;  val periodInS=period/1000&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;abstract class XSSHPlugin extends XSniffPlugin {&lt;br /&gt;  val host = getSetting("host") getOrElse "127.0.0.1"&lt;br /&gt;  val username = getSetting("username") getOrElse util.Properties.userName&lt;br /&gt;  val password = getSetting("password") &lt;br /&gt;  val port = getSetting("port") map {_.toInt} getOrElse 22&lt;br /&gt;  def cmd:String&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;case class XTopPlugin(domain:String) extends XSSHPlugin {&lt;br /&gt;  val ignoreKeywords = getSetting("ignoreKeywords")&lt;br /&gt;  def cmd="top -c -b -d %d".format(periodInS)&lt;br /&gt;  override def toString = &lt;br /&gt;    "top each %ds through ssh to %s%s@%s".format(&lt;br /&gt;        period/1000, username, password map {":"+_} getOrElse "", host&lt;br /&gt;        )&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt; Now I would like to modify XTopPlugin behavior in order to let it takes its configuration through &lt;a href="https://github.com/typesafehub/config"&gt;typesafe config library&lt;/a&gt;, BUT without modifying anything in the code.&lt;br/&gt;&lt;br/&gt;The idea here is to create a new trait which inheritates from XConfigurable :  &lt;pre class="brush: scala;highlight: [20,21,22,23,24,25,26,27,28,29,30]"&gt;&lt;br /&gt;object PlayWithTrait {&lt;br /&gt;  import com.typesafe.config.Config&lt;br /&gt;  import com.typesafe.config.ConfigFactory&lt;br /&gt;  import com.typesafe.config.ConfigException.{Missing,WrongType}&lt;br /&gt;    &lt;br /&gt;  private lazy val context = ConfigFactory.parseString("""&lt;br /&gt;        |Defaults {&lt;br /&gt;        |  period=5000&lt;br /&gt;        |}&lt;br /&gt;        |SSHPlugin = ${Defaults}&lt;br /&gt;        |SSHPlugin = {&lt;br /&gt;        |  host:"127.0.0.1"&lt;br /&gt;        |  port:22&lt;br /&gt;        |}&lt;br /&gt;        |TopPlugin = ${SSHPlugin}&lt;br /&gt;        |TopPlugin = {&lt;br /&gt;        |  ignoreKeywords:"tty$"&lt;br /&gt;        |} """.stripMargin).resolve()&lt;br /&gt;&lt;br /&gt;  trait XConfigurableUsingConfig extends XConfigurable {&lt;br /&gt;    def config:Config&lt;br /&gt;    override def getSetting(key:String):Option[String] = {&lt;br /&gt;      try {&lt;br /&gt;        Some(config.getString(key))&lt;br /&gt;      } catch {&lt;br /&gt;        case x:Missing =&gt; None&lt;br /&gt;        case x:WrongType =&gt; None&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt; And then we'll take advantage of scala trait feature which allow us to stack a new behavior to an object at instanciation time :  &lt;pre class="brush: scala;highlight: [12]"&gt;&lt;br /&gt;  def main(args: Array[String]) {&lt;br /&gt;    import collection.JavaConversions._&lt;br /&gt;    &lt;br /&gt;    val localCfg = Map(&lt;br /&gt;        "host" -&gt; "192.168.2.1",&lt;br /&gt;        "username" -&gt; "test",&lt;br /&gt;        "password" -&gt; "testtest"&lt;br /&gt;        )&lt;br /&gt;    &lt;br /&gt;    val topConfig = ConfigFactory.parseMap(localCfg).withFallback(context.getConfig("TopPlugin"))&lt;br /&gt;    &lt;br /&gt;    val top = new XTopPlugin("myserver") with XConfigurableUsingConfig {def config=topConfig}&lt;br /&gt;    &lt;br /&gt;    println(top)&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt; So now our XTopPlugin instance is taking its configuration through typesafe "Config" library, using a kind of closure to give the configuration context (topConfig).&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;One can object that it is less flexible than using for example spring and its xml configuration files, but remember that scala compiler can be easily embedded in any application, so you just have to use a scala configuration file which will get compiled at runtime... it will bring you very awesome dependencies injection features using pure scala. &lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4576039096616564465-4831769060146592619?l=www.crosson.org' alt='' /&gt;&lt;/div&gt;</description><link>http://www.crosson.org/2012/03/dependency-injection-using-scala-traits.html</link><author>noreply@blogger.com (david crosson)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-4576039096616564465.post-2459461029043761844</guid><pubDate>Thu, 01 Mar 2012 21:17:00 +0000</pubDate><atom:updated>2012-03-01T22:17:52.821+01:00</atom:updated><title>Akka actors : 10 millions messages processed (1s / message) in 75 seconds !</title><description>In the previous POST, &lt;a href="http://www.crosson.org/2012/02/akka-actors-versus-scala-actors-control.html"&gt;Akka actors versus Scala actors : control the message throughput of actors&lt;/a&gt;, we've seen how to control message throughput and avoid OutOfMemory problem in particular when actors doesn't have the same messages processing rate. &lt;br/&gt;&lt;br/&gt;Now we have to find a way to find a better way to simulate our 1 second delay, because using Thread.sleep breaks actors management as it will monopolize all threads of the used executor. In fact we would like to simulate a not-blocking 1s processing time.&lt;br/&gt;&lt;br/&gt;So we should remove the following Thread.sleep call :  &lt;pre class="brush: scala;highlight: [3]"&gt;&lt;br /&gt;class MyMessageProcessor extends Actor {&lt;br /&gt;  def receive = {&lt;br /&gt;    case _:DoItMessage =&gt; Thread.sleep(1000)&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br/&gt;The solution is straightforward as Akka comes with a scheduler system which allow you to send a message after a given delay.  &lt;pre class="brush: scala;highlight: [4]"&gt;&lt;br /&gt;class MySimulator(system:ActorSystem) extends Actor {&lt;br /&gt;  def receive = {&lt;br /&gt;    case _:DoItMessage =&gt;&lt;br /&gt;      system.scheduler.scheduleOnce(1000 milliseconds, sender, "Done") &lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Using scheduleOnce, we didn't monopolize system resources, no thread is used, in fact we achieve a fake processing which simulates an asynchronous response which come 1s later. In the following code, the response is even received asynchronously by a future :    &lt;pre class="brush: scala;highlight: [53,54,55,56]"&gt;&lt;br /&gt;package dummy&lt;br /&gt;&lt;br /&gt;import akka.actor._&lt;br /&gt;import akka.util.duration._&lt;br /&gt;import akka.util.Timeout&lt;br /&gt;import akka.pattern.ask&lt;br /&gt;import akka.dispatch.Future&lt;br /&gt;&lt;br /&gt;sealed trait MyMessage&lt;br /&gt;case class DoItMessage(cmd:String) extends MyMessage&lt;br /&gt;case class DoneMessage extends MyMessage&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;object Dummy {&lt;br /&gt;  def main(args:Array[String]) {&lt;br /&gt;    &lt;br /&gt;    val howmanyjob=10*1000000&lt;br /&gt;    &lt;br /&gt; import com.typesafe.config.ConfigFactory&lt;br /&gt;    implicit val system=ActorSystem("DummySystem",ConfigFactory.load.getConfig("dummy"))&lt;br /&gt;    &lt;br /&gt;    val simu = system.actorOf(&lt;br /&gt;        Props(new MySimulator(system))&lt;br /&gt;        .withDispatcher("simu-dispatcher"),&lt;br /&gt;        name="simulator")&lt;br /&gt;&lt;br /&gt;    val appManager = system.actorOf(&lt;br /&gt;        Props(new ApplicationManager(system, howmanyjob))&lt;br /&gt;        .withDispatcher("simu-dispatcher"),&lt;br /&gt;        name="application-manager")&lt;br /&gt;&lt;br /&gt;        &lt;br /&gt;    import akka.routing.RoundRobinRouter&lt;br /&gt;    val processor = system.actorOf(&lt;br /&gt;        Props(new MyMessageProcessor(appManager, simu))&lt;br /&gt;        .withDispatcher("workers-dispatcher")&lt;br /&gt;        .withRouter(RoundRobinRouter(10)),&lt;br /&gt;        name="default")&lt;br /&gt;        &lt;br /&gt;    for(i &lt;- 1 to howmanyjob) {&lt;br /&gt;      processor ! DoItMessage("Do the job with ID#%d now".format(i))&lt;br /&gt;    }&lt;br /&gt;    print("All jobs sent")&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class MyMessageProcessor(appManager:ActorRef, simu:ActorRef) extends Actor {&lt;br /&gt;  def receive = {&lt;br /&gt;    case msg:DoItMessage =&gt;&lt;br /&gt;      implicit val timeout = Timeout(5 minutes)&lt;br /&gt;      val receivedTime = System.currentTimeMillis()&lt;br /&gt;      val future = simu ? msg&lt;br /&gt;      future.onComplete { &lt;br /&gt;        case result:Either[Throwable, String] =&gt;&lt;br /&gt;          assert(System.currentTimeMillis()-receivedTime &gt;= 1000)&lt;br /&gt;          appManager ! DoneMessage&lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class MySimulator(system:ActorSystem) extends Actor {&lt;br /&gt;  def receive = {&lt;br /&gt;    case _:DoItMessage =&gt;&lt;br /&gt;      // Fake processing, somewhere, the job is executed and we get &lt;br /&gt;      // the results 1s later asynchronously&lt;br /&gt;      system.scheduler.scheduleOnce(1000 milliseconds, sender, "Done") &lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class ApplicationManager(system:ActorSystem, howmanyjob:Int) extends Actor {&lt;br /&gt;  val startedTime = System.currentTimeMillis()&lt;br /&gt;  var count=0&lt;br /&gt;  def receive = {&lt;br /&gt;    case DoneMessage =&gt; &lt;br /&gt;      count+=1&lt;br /&gt;      if (count%(howmanyjob/20)==0) println("%d/%d processed".format(count, howmanyjob))&lt;br /&gt;      if (count == howmanyjob) {&lt;br /&gt;        val now=System.currentTimeMillis()&lt;br /&gt;        println("Everything processed in %d seconds".format((now-startedTime)/1000))&lt;br /&gt;        system.shutdown() &lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt; The application configuration is the following (application.conf file) :  &lt;pre class="brush: text;highlight: []"&gt;&lt;br /&gt;dummy {&lt;br /&gt;  akka {&lt;br /&gt;    loglevel = WARNING&lt;br /&gt;    actor {&lt;br /&gt;      default-dispatcher {&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;    scheduler {&lt;br /&gt;      tick-duration = 50ms&lt;br /&gt;      ticks-per-wheel = 1000&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  simu-dispatcher {&lt;br /&gt;    type = Dispatcher&lt;br /&gt;    mailbox-capacity = 100000&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  workers-dispatcher {&lt;br /&gt;    mailbox-capacity = 10000&lt;br /&gt;    executor = "fork-join-executor"&lt;br /&gt;    fork-join-executor {&lt;br /&gt;      parallelism-min = 0&lt;br /&gt;      parallelism-max = 6000&lt;br /&gt;      parallelism-factor = 3.0      &lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt; The build.sbt SBT file (To get dependencies, build, test &amp; run) is the following :   &lt;pre class="brush: scala; highlight: []"&gt;&lt;br /&gt;name := "AkkaSandbox"&lt;br /&gt;&lt;br /&gt;version := "0.1"&lt;br /&gt;&lt;br /&gt;scalaVersion := "2.9.1"&lt;br /&gt;&lt;br /&gt;libraryDependencies += "com.typesafe.akka" % "akka-actor" % "2.0-RC3"&lt;br /&gt;&lt;br /&gt;resolvers += "Typesafe Repository" at "http://repo.typesafe.com/typesafe/releases/"&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt; &lt;b&gt;&lt;u&gt;Everything is processed in 75 seconds using : &lt;/u&gt;&lt;/b&gt;&lt;ul&gt;  &lt;li&gt;linux 3.2.1-gentoo-r2 64bits&lt;/li&gt;  &lt;li&gt;AMD Phenom(tm) II X6 1090T  (6 CPU cores)&lt;/li&gt;  &lt;li&gt;Java HotSpot(TM) 64-Bit Server 1.6.0.31&lt;/li&gt;&lt;/ul&gt;CPU usage ~80%, java memory footprint is below 300Mo; each message is requiring 50-60 bytes, so the 10 million messages are requiring at least 480Mb (but not simultaneously).  &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-WxwoehcVe9k/T0_iNoVsOzI/AAAAAAAAEik/1mIK1DnIp4c/s1600/figure.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="281" width="400" src="http://4.bp.blogspot.com/-WxwoehcVe9k/T0_iNoVsOzI/AAAAAAAAEik/1mIK1DnIp4c/s400/figure.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4576039096616564465-2459461029043761844?l=www.crosson.org' alt='' /&gt;&lt;/div&gt;</description><link>http://www.crosson.org/2012/03/akka-actors-10-millions-messages.html</link><author>noreply@blogger.com (david crosson)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-WxwoehcVe9k/T0_iNoVsOzI/AAAAAAAAEik/1mIK1DnIp4c/s72-c/figure.png' height='72' width='72'/><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-4576039096616564465.post-3707830712996237842</guid><pubDate>Thu, 23 Feb 2012 17:50:00 +0000</pubDate><atom:updated>2012-03-11T12:11:13.600+01:00</atom:updated><title>Akka actors versus Scala actors : control the message throughput of actors</title><description>&lt;i&gt;In the post following this one, I show how to enhance the example code in order to be able to process a very high number of messages : &lt;a href="http://www.crosson.org/2012/03/akka-actors-10-millions-messages.html"&gt;Akka actors : 10 millions messages processed (1s / message) in 75 seconds !&lt;/a&gt;&lt;/i&gt;&lt;br/&gt;&lt;br/&gt;Scala default actor system doesn't come with any mechanism to control messages throughput between actors, so it is up to you to implement such feature in order to avoid OutOfMemory problem, in particular when actors are not processing messages at the same rate.&lt;br/&gt;Akka framework is very interesting because it brings you all the features to control and manage throughputs. Let's see how it work through a simple example :  &lt;pre class="brush: scala;highlight: []"&gt;&lt;br /&gt;import akka.actor._&lt;br /&gt;&lt;br /&gt;sealed trait MyMessage&lt;br /&gt;case class DoItMessage(cmd:String) extends MyMessage&lt;br /&gt;&lt;br /&gt;object Dummy {&lt;br /&gt;  def main(args:Array[String]) {&lt;br /&gt;    val system=ActorSystem("DummySystem")&lt;br /&gt;    val processor = system.actorOf(Props[MyMessageProcessor],name="default")&lt;br /&gt;    for(i &lt;- 1 to 10000000) {&lt;br /&gt;      processor ! DoItMessage("Do the job with ID#%d now".format(i))&lt;br /&gt;    }&lt;br /&gt;    println("All jobs sent")&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class MyMessageProcessor extends Actor {&lt;br /&gt;  def receive = {&lt;br /&gt;    case _:DoItMessage =&gt; Thread.sleep(1000)&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt; Each message sent is more than 50 bytes, so a JVM with a 512Mo of maximum heap size will quickly run out of memory.&lt;br/&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-hv-gBZRNRqY/T0Zu1ehsseI/AAAAAAAAEhY/31Wo1sntHIw/s1600/OutOfMemory.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="292" width="400" src="http://2.bp.blogspot.com/-hv-gBZRNRqY/T0Zu1ehsseI/AAAAAAAAEhY/31Wo1sntHIw/s400/OutOfMemory.png" /&gt;&lt;/a&gt;&lt;/div&gt;  &lt;br/&gt;The good news is that akka support bounded actor mailboxes, just add a configuration file with such content : &lt;pre class="brush: text;highlight: [5,6]"&gt;&lt;br /&gt;dummy {&lt;br /&gt;  akka {&lt;br /&gt;    loglevel = WARNING&lt;br /&gt;    actor {&lt;br /&gt;      default-dispatcher {&lt;br /&gt;         mailbox-capacity = 10000&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;And make this configuration file taken into account with the following code update :  &lt;pre class="brush: scala;highlight: [2]"&gt;&lt;br /&gt;    import com.typesafe.config.ConfigFactory&lt;br /&gt;    val system=ActorSystem("DummySystem",ConfigFactory.load.getConfig("dummy"))&lt;br /&gt;&lt;/pre&gt; This time if you run again the previous code, you'll get a stable memory footprint :&lt;br/&gt; &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-a2_b4QVP5HU/T0ZwdMeyCrI/AAAAAAAAEhk/FYjZ6GMevn8/s1600/good.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="277" width="400" src="http://3.bp.blogspot.com/-a2_b4QVP5HU/T0ZwdMeyCrI/AAAAAAAAEhk/FYjZ6GMevn8/s400/good.png" /&gt;&lt;/a&gt;&lt;/div&gt; &lt;br/&gt;Of course it will take a long time to process as each message requires 1s (and actors are blocked during 1s because of Thread.sleep call, which monopolize a thread during the same duration =&gt; waste of resources)... If we want to reduce the processing time although each message requires 1s to be taken into account, we'll have to load-balance message processing accross a high number of actors.  &lt;br/&gt; &lt;br/&gt; &lt;br/&gt;&lt;i&gt;CONTEXT : Scala 2.9.1 / SBT 0.11.2 / AKKA 2.0-rc2 / sbteclipse 2.0.0 &lt;/i&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4576039096616564465-3707830712996237842?l=www.crosson.org' alt='' /&gt;&lt;/div&gt;</description><link>http://www.crosson.org/2012/02/akka-actors-versus-scala-actors-control.html</link><author>noreply@blogger.com (david crosson)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-hv-gBZRNRqY/T0Zu1ehsseI/AAAAAAAAEhY/31Wo1sntHIw/s72-c/OutOfMemory.png' height='72' width='72'/><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-4576039096616564465.post-7146598496988600065</guid><pubDate>Thu, 23 Feb 2012 10:24:00 +0000</pubDate><atom:updated>2012-02-23T11:28:42.678+01:00</atom:updated><title>Revisiting Git/SVN Update script... and let's try to make it faster</title><description>The following script is an enhancement of the one shown in the previous post. It now detects all git or svn projects in the current directory, and then update and compile them.&lt;br/&gt;&lt;/br&gt;It could have been straightforward to make it faster by just turning "project" collection into a parallel one (projects.par) but unfortunately, it won't work because of the use of a global mutable variable used to store the current worker directory (Classical trap) ! So more work is mandatory to make this faster.  &lt;pre class="brush: scala;highlight: [16,34]"&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;exec scala -deprecation -savecompiled "$0" "$@"&lt;br /&gt;!#&lt;br /&gt;import java.io.File&lt;br /&gt;import sys.process.Process&lt;br /&gt;import sys.process.ProcessBuilder._&lt;br /&gt;&lt;br /&gt;// ======================================================================&lt;br /&gt;case class CurDir(cwd:File)&lt;br /&gt;def file(f:String)=new File(f)&lt;br /&gt;def file(d:File, f:String)=new File(d, f)&lt;br /&gt;implicit def stringToCurDir(d:String) = CurDir(file(d))&lt;br /&gt;implicit def fileToCurDir(d:File) = CurDir(d)&lt;br /&gt;implicit def stringToFile(f:String) = file(f)&lt;br /&gt;implicit def stringToProcess(cmd: String)(implicit curDir:CurDir) = Process(cmd, curDir.cwd)&lt;br /&gt;implicit var cwd:CurDir=file(".").getPath&lt;br /&gt;def cd(dir:File=file(util.Properties.userDir)) = cwd=CurDir(dir)&lt;br /&gt;// ======================================================================&lt;br /&gt;&lt;br /&gt;trait Project {&lt;br /&gt;  val dir:File&lt;br /&gt;}&lt;br /&gt;case class GitProject(dir:File) extends Project&lt;br /&gt;case class SvnProject(dir:File) extends Project&lt;br /&gt;&lt;br /&gt;// Find GIT or SVN project directories&lt;br /&gt;val projects = file(".").listFiles filter { _.isDirectory} flatMap { d =&gt;&lt;br /&gt;  if (file(d, ".git").exists) Some(GitProject(d))&lt;br /&gt;  else if (file(d, ".svn").exists) Some(SvnProject(d))&lt;br /&gt;  else None&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Update compile project (update also eclipse conf files generated by sbteclipse plugin)&lt;br /&gt;for(project&lt;- projects) {&lt;br /&gt;  println(project)&lt;br /&gt;  cd(project.dir)&lt;br /&gt;  project match {&lt;br /&gt;    case GitProject(_) =&gt; "git pull" !&lt;br /&gt;    case SvnProject(_) =&gt; "svn update" !&lt;br /&gt;  }&lt;br /&gt;  "sbt eclipse compile" !&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt; Let's now revisit the current directory hack to make it compatible with parallel processing and avoid border side effect. &lt;br/&gt;Therefore, we have to modify the "cd" command hack in order to remove the mutable cwd variable :  &lt;pre class="brush: scala;highlight: [16,33,35]"&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;exec scala -deprecation -savecompiled "$0" "$@"&lt;br /&gt;!#&lt;br /&gt;import java.io.File&lt;br /&gt;import sys.process.Process&lt;br /&gt;import sys.process.ProcessBuilder._&lt;br /&gt;&lt;br /&gt;// ======================================================================&lt;br /&gt;case class CurDir(cwd:File)&lt;br /&gt;def file(f:String)=new File(f)&lt;br /&gt;def file(d:File, f:String)=new File(d, f)&lt;br /&gt;implicit def stringToCurDir(d:String) = CurDir(file(d))&lt;br /&gt;implicit def fileToCurDir(d:File) = CurDir(d)&lt;br /&gt;implicit def stringToFile(f:String) = file(f)&lt;br /&gt;implicit def stringToProcess(cmd: String)(implicit curDir:CurDir) = Process(cmd, curDir.cwd)&lt;br /&gt;def cd[A](dir:File=file(util.Properties.userDir)) (indir:(CurDir)=&gt;A) = indir(CurDir(dir))&lt;br /&gt;// ======================================================================&lt;br /&gt;&lt;br /&gt;trait Project {&lt;br /&gt;  val dir:File&lt;br /&gt;}&lt;br /&gt;case class GitProject(dir:File) extends Project&lt;br /&gt;case class SvnProject(dir:File) extends Project&lt;br /&gt;&lt;br /&gt;// Find GIT or SVN project directories&lt;br /&gt;val projects = file(".").listFiles filter { _.isDirectory} flatMap { d =&gt;&lt;br /&gt;  if (file(d, ".git").exists) Some(GitProject(d))&lt;br /&gt;  else if (file(d, ".svn").exists) Some(SvnProject(d))&lt;br /&gt;  else None&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Update compile project (update also eclipse conf files generated by sbteclipse plugin)&lt;br /&gt;for(project&lt;- projects.par) {&lt;br /&gt;  println(project)&lt;br /&gt;  cd(project.dir) { implicit cwd =&gt;&lt;br /&gt;    project match {&lt;br /&gt;      case GitProject(_) =&gt; "git pull" !&lt;br /&gt;      case SvnProject(_) =&gt; "svn update" !&lt;br /&gt;    }&lt;br /&gt;    "sbt eclipse compile" !&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;println("%d project updated".format(projects.size))&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt; So we couln't keep the classical shell cd behavior, because it implies a mutable state, so in this script we turn the cd "classical" definition into a new one, with a new argument, a function which will take as argument, the given working directory to use.&lt;br/&gt;&lt;br/&gt;In my case (7 projects), &lt;b&gt;using "projects.par", the script executes in 10s instead of 33s&lt;/b&gt; ! &lt;br/&gt;&lt;br/&gt;&lt;i&gt;CONTEXT : Scala 2.9.1&lt;/i&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4576039096616564465-7146598496988600065?l=www.crosson.org' alt='' /&gt;&lt;/div&gt;</description><link>http://www.crosson.org/2012/02/revisiting-gitsvn-update-script-and.html</link><author>noreply@blogger.com (david crosson)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-4576039096616564465.post-2879869280930996613</guid><pubDate>Wed, 01 Feb 2012 20:53:00 +0000</pubDate><atom:updated>2012-02-01T21:53:51.710+01:00</atom:updated><title>Small script to update &amp; compile a list of svn project</title><description>Scala script skeleton to update a set of subversion projects.  &lt;pre class="brush: scala;highlight: []"&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;exec scala -deprecation -savecompiled "$0" "$@"&lt;br /&gt;!#&lt;br /&gt;&lt;br /&gt;// ======================================================================&lt;br /&gt;import sys.process.Process&lt;br /&gt;import sys.process.ProcessBuilder._&lt;br /&gt;&lt;br /&gt;case class CurDir(cwd:java.io.File)&lt;br /&gt;implicit def stringToCurDir(d:String) = CurDir(new java.io.File(d))&lt;br /&gt;implicit def stringToProcess(cmd: String)(implicit curDir:CurDir) = Process(cmd, curDir.cwd)&lt;br /&gt;implicit def stringSeqToProcess(cmd:Seq[String])(implicit curDir:CurDir) = Process(cmd, curDir.cwd)&lt;br /&gt;&lt;br /&gt;implicit var cwd:CurDir=scala.util.Properties.userDir&lt;br /&gt;def cd(dir:String=util.Properties.userDir) = cwd=dir&lt;br /&gt;// ======================================================================&lt;br /&gt;&lt;br /&gt;val updateList=List("project1", "project2", "project3")&lt;br /&gt;&lt;br /&gt;for(dir&lt;- updateList) {&lt;br /&gt;  println("----------------------------------------")&lt;br /&gt;  println("Processing %s".format(dir))&lt;br /&gt;&lt;br /&gt;  cd(dir)&lt;br /&gt;&lt;br /&gt;  "svn update" !&lt;br /&gt;&lt;br /&gt;  "sbt eclipse compile" !&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4576039096616564465-2879869280930996613?l=www.crosson.org' alt='' /&gt;&lt;/div&gt;</description><link>http://www.crosson.org/2012/02/small-script-to-update-compile-list-of.html</link><author>noreply@blogger.com (david crosson)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-4576039096616564465.post-195038438885724173</guid><pubDate>Mon, 30 Jan 2012 22:30:00 +0000</pubDate><atom:updated>2012-01-30T23:42:59.016+01:00</atom:updated><title>Simplifying scala scripts : Adding #include support to your scripts</title><description>Test a #include support example by executing the following 5 lines :  &lt;pre class="brush: bash;highlight: []"&gt;&lt;br /&gt;$ wget http://dnld.crosson.org/bootstrap.tar.gz&lt;br /&gt;$ tar xvfz bootstrap.tar.gz&lt;br /&gt;$ cd bootstrap&lt;br /&gt;$ sbt assembly&lt;br /&gt;$ ./scripts/test.scala&lt;br /&gt;&lt;/pre&gt; The test.scala example script is the following :  &lt;pre class="brush: scala;highlight: []"&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;DIRNAME=`dirname "$0"`&lt;br /&gt;exec java -jar "$DIRNAME"/bootstrap.jar "$0" "$@"&lt;br /&gt;!#&lt;br /&gt;&lt;br /&gt;#include "shell.scala"&lt;br /&gt;&lt;br /&gt;cd("/etc/")&lt;br /&gt;&lt;br /&gt;"ls" #| "grep net" !&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt; go to /etc directory, and prints files which contain net keyword in their names.  &lt;br/&gt;&lt;br/&gt; test.scala script includes the following file : scripts/include/shell.scala  &lt;pre class="brush: scala;highlight: []"&gt;&lt;br /&gt;import sys.process.Process&lt;br /&gt;import sys.process.ProcessBuilder._&lt;br /&gt; &lt;br /&gt;case class CurDir(cwd:java.io.File)&lt;br /&gt;implicit def stringToCurDir(d:String) = CurDir(new java.io.File(d))&lt;br /&gt;implicit def stringToProcess(cmd: String)(implicit curDir:CurDir) = Process(cmd, curDir.cwd)&lt;br /&gt;implicit def stringSeqToProcess(cmd:Seq[String])(implicit curDir:CurDir) = Process(cmd, curDir.cwd)&lt;br /&gt;&lt;br /&gt;implicit var cwd:CurDir=scala.util.Properties.userDir&lt;br /&gt;def cd(dir:String=util.Properties.userDir) = cwd=dir&lt;br /&gt;&lt;/pre&gt;This file contains some definitions to make possible for the user to change current directory. &lt;br/&gt;&lt;br/&gt;All the include mechanism logic in defined as follow :  &lt;pre class="brush: scala;highlight: []"&gt;&lt;br /&gt;package fr.janalyse.script&lt;br /&gt;&lt;br /&gt;import scala.tools.nsc.ScriptRunner&lt;br /&gt;import scala.tools.nsc.GenericRunnerCommand&lt;br /&gt;import scala.io.Source&lt;br /&gt;import java.io.File&lt;br /&gt;&lt;br /&gt;object Bootstrap {&lt;br /&gt;  val defaultOptions = List("-nocompdaemon","-usejavacp","-savecompiled", "-deprecation")&lt;br /&gt;  val defaultExpandedScriptExt = ".pscala"&lt;br /&gt;  &lt;br /&gt;  val includeRE = """\s*#include\s+"(.+)"\s*"""r&lt;br /&gt;  &lt;br /&gt;  def expand(file:File, availableIncludes:List[File]) : List[String] = {&lt;br /&gt;    val content=Source.fromFile(file).getLines().toList&lt;br /&gt;    // First we remove "shell" startup lines, everything between #! and !#&lt;br /&gt;    val cleanedContent = content.indexWhere { _.trim.startsWith("!#") } match {&lt;br /&gt;      case -1 =&gt; content&lt;br /&gt;      case i  =&gt; content.drop(i+1)&lt;br /&gt;    }&lt;br /&gt;   // Then we expand #include directives&lt;br /&gt;   cleanedContent flatMap {&lt;br /&gt;     case includeRE(filename) =&gt;&lt;br /&gt;       val fileOpt = availableIncludes find {_.getName() == filename}&lt;br /&gt;       fileOpt orElse {&lt;br /&gt;          throw new RuntimeException("%s : Couln't find include file '%s' ".format(file.getName, filename))&lt;br /&gt;       }&lt;br /&gt;       fileOpt map { file =&gt; expand(file, availableIncludes)} getOrElse List.empty[String]  &lt;br /&gt;     case line =&gt; line::Nil&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;    &lt;br /&gt;  def main(cmdargs:Array[String]) {&lt;br /&gt;    val command = new GenericRunnerCommand(defaultOptions ++ cmdargs.toList)&lt;br /&gt;    val scriptDir = new File(cmdargs(0)).getParentFile()&lt;br /&gt;    val includePath = List(new File(scriptDir, "include"), scriptDir)&lt;br /&gt;    val availableIncludes = includePath filter {_.exists()} flatMap {_.listFiles()}&lt;br /&gt;    val scriptname = command.thingToRun &lt;br /&gt;    val script = new File(scriptname)&lt;br /&gt;    val richerScript = new File(scriptname.replaceFirst(".scala", defaultExpandedScriptExt))&lt;br /&gt;    &lt;br /&gt;    if (script.exists()) {&lt;br /&gt;      val jars = util.Properties.javaClassPath.split(File.pathSeparator) map {new File(_)} collect {&lt;br /&gt;        case f if (f.exists() &amp;&amp; f.isFile()) =&gt; f &lt;br /&gt;      }&lt;br /&gt;      val jarsLastModified = (jars map {_.lastModified()} max)&lt;br /&gt;      &lt;br /&gt;      if (!richerScript.exists ||  // -- nothing already available&lt;br /&gt;          (jarsLastModified &gt; richerScript.lastModified) ||   // -- Bootstrap jar is newer&lt;br /&gt;          (script.lastModified &gt; richerScript.lastModified)) { // -- Script has been modified&lt;br /&gt;        val newcontent =  expand(script, availableIncludes).mkString("\n")&lt;br /&gt;        new java.io.FileOutputStream(richerScript) {&lt;br /&gt;          write(newcontent.getBytes())&lt;br /&gt;        }.close()&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;    ScriptRunner.runScript(command.settings, richerScript.getPath, command.arguments)&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt; &lt;u&gt;How does it work&lt;/u&gt; :&lt;br&gt;The principle is to override scala standard script startup mechanism by introducing an additionnal step which consist to expand the script with all includes it contains, and then gives to scala the new script resulting of expansion process.&lt;br/&gt;&lt;b&gt;test.scala&lt;/b&gt; becomes &lt;b&gt;test.pscala&lt;/b&gt; which will generate the savedcompile file &lt;b&gt;test.pscala.jar&lt;/b&gt;. No recompilation will be required as soon as no change occured on test.scala or bootstrap.jar file. &lt;br/&gt;&lt;br/&gt; You should also notice that the script is started using 'exec java -jar "$DIRNAME"/bootstrap.jar "$0" "$@"' and not 'exec scala ...' because bootstrap is an assembly jar which contains everything to run and compile scala scripts, and even more if you want, as it can include any third parties you may need, just add library dependencies ! So you only need one file, bootstrap.jar, to run any scala scripts, nothing to install, just one file to upload.  &lt;br/&gt;&lt;br/&gt;  SBT build configuration : bootstrap/build.sbt   &lt;pre class="brush: scala;highlight: []"&gt;&lt;br /&gt;import AssemblyKeys._&lt;br /&gt;&lt;br /&gt;seq(assemblySettings: _*)&lt;br /&gt;&lt;br /&gt;name := "bootstrap"&lt;br /&gt;&lt;br /&gt;version := "0.1"&lt;br /&gt;&lt;br /&gt;scalaVersion := "2.9.1"&lt;br /&gt;&lt;br /&gt;libraryDependencies &lt;++=  scalaVersion { sv =&gt;&lt;br /&gt;   ("org.scala-lang" % "scala-swing" % sv) ::&lt;br /&gt;   ("org.scala-lang" % "jline"           % sv  % "compile") ::&lt;br /&gt;   ("org.scala-lang" % "scala-compiler"  % sv  % "compile") ::&lt;br /&gt;   ("org.scala-lang" % "scala-dbc"       % sv  % "compile") ::&lt;br /&gt;   ("org.scala-lang" % "scalap"          % sv  % "compile") ::&lt;br /&gt;   ("org.scala-lang" % "scala-swing"     % sv  % "compile") ::Nil   &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;mainClass in assembly := Some("fr.janalyse.script.Bootstrap")&lt;br /&gt;&lt;br /&gt;jarName in assembly := "bootstrap.jar"&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;   SBT Plugins configuration : bootstrap/project/plugins.sbt file  &lt;pre class="brush: scala;highlight: []"&gt;&lt;br /&gt;resolvers += Classpaths.typesafeResolver&lt;br /&gt;&lt;br /&gt;addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.0.0-M3")&lt;br /&gt;&lt;br /&gt;addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.7.2")&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4576039096616564465-195038438885724173?l=www.crosson.org' alt='' /&gt;&lt;/div&gt;</description><link>http://www.crosson.org/2012/01/simplifying-scala-scripts-adding.html</link><author>noreply@blogger.com (david crosson)</author><thr:total>1</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-4576039096616564465.post-4968904094495684442</guid><pubDate>Thu, 26 Jan 2012 22:42:00 +0000</pubDate><atom:updated>2012-01-26T23:42:52.535+01:00</atom:updated><title>Simplifying scala scripts</title><description>I've already written several dozens of scala scripts (series computations, ssh automation, various jmx operations, remote administration, garbage collector log analysis, ...) and found this language quite interesting for use as a script language. There's many reasons for that :&lt;br/&gt;&lt;ul&gt;&lt;li&gt; Script automatic compilation reduce runtime error. I am often amazed at the first attempt to get a script that works and without any runtime error !&lt;/li&gt;&lt;li&gt; Take benefits of scala powerfull collections that make possible to write "sql" like operations&lt;/li&gt;&lt;li&gt; It becomes straightforward to parallelize tasks using Actors; one of my favorite use case is a short script that trigger an explicit garbage collection on several dozens of remote jvm in a very short time&lt;/li&gt;&lt;/ul&gt; But I miss some features that will help to make scala scripts even simpler and concise : &lt;ul&gt;  &lt;li&gt;A #include like feature within script&lt;/li&gt;  &lt;li&gt;A way to modify default imports, to avoid adding always the same imports in all scripts&lt;/li&gt;  &lt;li&gt;the #! !# shell scala bootstrap can become long (and not DRY) once you want to add many external java dependencies&lt;/li&gt;&lt;/ul&gt; In fact those missing features are no so difficult to implement, the following source code is a proof of concept that shows it no so difficult to implement those features. It defines a class, Bootstrap, which can be use to start a scala script and that will bring new imports and definitions to your script.  &lt;pre class="brush: scala;highlight: []"&gt;&lt;br /&gt;package fr.janalyse.script&lt;br /&gt;&lt;br /&gt;import scala.tools.nsc.ScriptRunner&lt;br /&gt;import scala.tools.nsc.GenericRunnerCommand&lt;br /&gt;import scala.io.Source&lt;br /&gt;&lt;br /&gt;object Bootstrap {&lt;br /&gt;&lt;br /&gt;  val header = &lt;br /&gt;"""// WARNING&lt;br /&gt;// Automatically generated file - do not edit !&lt;br /&gt;import sys.process.Process&lt;br /&gt;import sys.process.ProcessBuilder._&lt;br /&gt; &lt;br /&gt;case class CurDir(cwd:java.io.File)&lt;br /&gt;implicit def stringToCurDir(d:String) = CurDir(new java.io.File(d))&lt;br /&gt;implicit def stringToProcess(cmd: String)(implicit curDir:CurDir) = Process(cmd, curDir.cwd)&lt;br /&gt;implicit def stringSeqToProcess(cmd:Seq[String])(implicit curDir:CurDir) = Process(cmd, curDir.cwd)&lt;br /&gt;&lt;br /&gt;implicit var cwd:CurDir=scala.util.Properties.userDir&lt;br /&gt;def cd(dir:String=util.Properties.userDir) = cwd=dir&lt;br /&gt;&lt;br /&gt;"""&lt;br /&gt;&lt;br /&gt;  val footer = &lt;br /&gt;"""&lt;br /&gt;"""&lt;br /&gt;&lt;br /&gt;  def main(cmdargs:Array[String]) {&lt;br /&gt;&lt;br /&gt;    def f(name:String) = new java.io.File(name)&lt;br /&gt;    &lt;br /&gt;    val na = List("-nocompdaemon","-usejavacp","-savecompiled", "-deprecation") ++ cmdargs.toList&lt;br /&gt;    &lt;br /&gt;    val command = new GenericRunnerCommand(na)&lt;br /&gt;    &lt;br /&gt;    import command.settings&lt;br /&gt;    &lt;br /&gt;    val scriptname = command.thingToRun &lt;br /&gt;    val script = f(scriptname)&lt;br /&gt;    val richerScript = f(scriptname.replaceFirst(".scala", ".scala-plus"))&lt;br /&gt;    &lt;br /&gt;    if (script.exists()) {&lt;br /&gt;      if (!richerScript.exists || (script.lastModified &gt; richerScript.lastModified)) {&lt;br /&gt;        val content=Source.fromFile(script).getLines().toList&lt;br /&gt;        val cleanedContent = content.dropWhile(x =&gt; !x.startsWith("!#")).tail.mkString("\n")&lt;br /&gt;        val newcontent =  List(header, cleanedContent, footer).mkString("\n")&lt;br /&gt;        new java.io.FileOutputStream(richerScript) {&lt;br /&gt;          write(newcontent.getBytes())&lt;br /&gt;        }.close()&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    val args = command.arguments&lt;br /&gt;    &lt;br /&gt;    ScriptRunner.runScript(settings, richerScript.getName, args)&lt;br /&gt;  }  &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;  Then generate a standalone executable jar with this class and all needed dependencies, thanks to such SBT build specification :   &lt;pre class="brush: scala;highlight: []"&gt;&lt;br /&gt;import AssemblyKeys._&lt;br /&gt;&lt;br /&gt;seq(assemblySettings: _*)&lt;br /&gt;&lt;br /&gt;name := "bootstrap"&lt;br /&gt;&lt;br /&gt;version := "0.1"&lt;br /&gt;&lt;br /&gt;scalaVersion := "2.9.1"&lt;br /&gt;&lt;br /&gt;libraryDependencies &lt;++=  scalaVersion { sv =&gt;&lt;br /&gt;   ("org.scala-lang" % "scala-swing" % sv) ::&lt;br /&gt;   ("org.scala-lang" % "jline"           % sv  % "compile") ::&lt;br /&gt;   ("org.scala-lang" % "scala-compiler"  % sv  % "compile") ::&lt;br /&gt;   ("org.scala-lang" % "scala-dbc"       % sv  % "compile") ::&lt;br /&gt;   ("org.scala-lang" % "scalap"          % sv  % "compile") ::&lt;br /&gt;   ("org.scala-lang" % "scala-swing"     % sv  % "compile") ::Nil   &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;mainClass in assembly := Some("fr.janalyse.script.Bootstrap")&lt;br /&gt;&lt;br /&gt;jarName in assembly := "bootstrap.jar"&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;  you'll be able to directly run any scala script like that :  &lt;pre class="brush: scala;highlight: []"&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;exec java -jar bootstrap.jar "$0" "$@"&lt;br /&gt;!#&lt;br /&gt;&lt;br /&gt;cd("/etc/")&lt;br /&gt;&lt;br /&gt;"ls" #| "grep net" !&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt; Thanks to the assembly SBT plugin, you've generated a standalone executable jar, which contains the scala compiler, and our custom scala script startup mechanism. &lt;br/&gt;In a next POST, I'll describe more in detail a new bootstrap implementation that will bring #include feature to scala script.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4576039096616564465-4968904094495684442?l=www.crosson.org' alt='' /&gt;&lt;/div&gt;</description><link>http://www.crosson.org/2012/01/simplifying-scala-scripts.html</link><author>noreply@blogger.com (david crosson)</author><thr:total>1</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-4576039096616564465.post-5444191917258324301</guid><pubDate>Tue, 24 Jan 2012 21:19:00 +0000</pubDate><atom:updated>2012-01-24T22:19:14.593+01:00</atom:updated><title>A simple approach to generate reports using scala</title><description>I was wondering if it was possible to create one executable script containing both the report template and its configuration. So I tried to write a scala script to test this idea :   &lt;pre class="brush: scala;highlight: []"&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;exec scala -nocompdaemon -usejavacp -savecompiled -deprecation "$0" "$@"&lt;br /&gt;!#&lt;br /&gt;&lt;br /&gt;import sys.process._&lt;br /&gt;import java.io.{File, FileOutputStream}&lt;br /&gt;&lt;br /&gt;println("Let's generate and display a report")&lt;br /&gt;&lt;br /&gt;val message = "hello"&lt;br /&gt;val guys = List("Marge", "Bart", "Omer")&lt;br /&gt;&lt;br /&gt;val smallreport = &lt;br /&gt;&lt; html&gt;&lt;br /&gt;  &lt; head&gt;&lt;br /&gt;    &lt; title&gt;Hello guys report&lt; /title&gt;&lt;br /&gt;  &lt; /head&gt;&lt;br /&gt;  &lt; body&gt;&lt;br /&gt;    &lt; h1&gt;{message}&lt; /h1&gt;&lt;br /&gt;    {guys map {guy=&gt; &lt;br /&gt;      &lt; h2&gt;{guy}&lt; /h2&gt;&lt;br /&gt;    } }&lt;br /&gt;  &lt; /body&gt;&lt;br /&gt;&lt; /html&gt;&lt;br /&gt;&lt;br /&gt;val reportfile = File.createTempFile("report", ".html")&lt;br /&gt;reportfile.deleteOnExit&lt;br /&gt;&lt;br /&gt;new FileOutputStream(reportfile) {&lt;br /&gt;  write(smallreport.toString.getBytes)&lt;br /&gt;}.close()&lt;br /&gt;&lt;br /&gt;List("firefox", "-new-window", reportfile.toURI.toURL.toString) !&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt; Note: &lt;i&gt;I've added one space inside each HTML TAG, looks like SyntaxHighlighter doesn't like HTML or XML embedded within scala&lt;/i&gt;&lt;br/&gt;&lt;br/&gt; Make this script executable (chmod u+x reportingScript.scala) and execute it (./reportingScript.scala),  if firefox is available on your operating system, the following window will be displayed :  &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-Ul_pPRWlpRo/Tx8cThsFr_I/AAAAAAAAEHM/fmDgo3gasjQ/s1600/Capture%2Bd%2527%25C3%25A9cran%2B-%2B24012012%2B-%2B22%253A06%253A17.png" imageanchor="1" style="clear:left; float:left;margin-right:1em; margin-bottom:1em"&gt;&lt;img border="0" height="215" width="400" src="http://1.bp.blogspot.com/-Ul_pPRWlpRo/Tx8cThsFr_I/AAAAAAAAEHM/fmDgo3gasjQ/s400/Capture%2Bd%2527%25C3%25A9cran%2B-%2B24012012%2B-%2B22%253A06%253A17.png" /&gt;&lt;/a&gt;&lt;/div&gt; &lt;br/&gt;Now we can say :&lt;br/&gt;- it is possible to combine a report template, and data access in a single executable script !&lt;br/&gt;- By using a custom scala startup command, it should be possible to simplify many operations, extending defaults imports, ... &lt;br/&gt;&lt;br/&gt;In a next post I'll try to make such script simpler.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4576039096616564465-5444191917258324301?l=www.crosson.org' alt='' /&gt;&lt;/div&gt;</description><link>http://www.crosson.org/2012/01/simple-approach-to-generate-reports.html</link><author>noreply@blogger.com (david crosson)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-Ul_pPRWlpRo/Tx8cThsFr_I/AAAAAAAAEHM/fmDgo3gasjQ/s72-c/Capture%2Bd%2527%25C3%25A9cran%2B-%2B24012012%2B-%2B22%253A06%253A17.png' height='72' width='72'/><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-4576039096616564465.post-5068472690560312665</guid><pubDate>Sun, 22 Jan 2012 17:25:00 +0000</pubDate><atom:updated>2012-01-22T18:25:33.893+01:00</atom:updated><title>How to generate google stock trend chart in 3 lines...</title><description>Using &lt;a href="http://code.google.com/p/janalyse-series/"&gt;janalyse-series scala API&lt;/a&gt;, it becomes very simple to generate a trend chart, 3 lines are enough in order to download, parse CSV data and then generate the chart.  &lt;pre class="brush: scala;highlight: [8,9,10]"&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;exec java -jar jaseries.jar -nocompdaemon -usejavacp -savecompiled "$0" "$@"&lt;br /&gt;!#&lt;br /&gt;&lt;br /&gt;import fr.janalyse.series.CSV2Series&lt;br /&gt;import fr.janalyse.series.view.Chart&lt;br /&gt;&lt;br /&gt;val allSeries = CSV2Series.fromURL("http://ichart.finance.yahoo.com/table.csv?s=GOOG")&lt;br /&gt;val closeSeries = allSeries("Close").rename("Google stock value")    &lt;br /&gt;Chart(closeSeries).toJpgFile(new java.io.File("googleStockTrend.jpg"), 800, 400)&lt;br /&gt;&lt;/pre&gt; The following chart is created.  &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-SowjYDsAVPU/TxxFuzEbeeI/AAAAAAAAEG4/GMVoCx_OrWM/s1600/googleStockTrend.jpg" imageanchor="1" style="clear:left; float:left;margin-right:1em; margin-bottom:1em"&gt;&lt;img border="0" height="200" width="400" src="http://1.bp.blogspot.com/-SowjYDsAVPU/TxxFuzEbeeI/AAAAAAAAEG4/GMVoCx_OrWM/s400/googleStockTrend.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4576039096616564465-5068472690560312665?l=www.crosson.org' alt='' /&gt;&lt;/div&gt;</description><link>http://www.crosson.org/2012/01/how-to-generate-google-stock-trend.html</link><author>noreply@blogger.com (david crosson)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-SowjYDsAVPU/TxxFuzEbeeI/AAAAAAAAEG4/GMVoCx_OrWM/s72-c/googleStockTrend.jpg' height='72' width='72'/><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-4576039096616564465.post-5818666197699113607</guid><pubDate>Sun, 22 Jan 2012 08:45:00 +0000</pubDate><atom:updated>2012-01-22T09:45:52.109+01:00</atom:updated><title>CSV files merge, based on series names...</title><description>This example illustrates how &lt;a href="http://code.google.com/p/janalyse-series/"&gt;janalyse-series API&lt;/a&gt; can be use to merge CSV files together while respecting series names. It takes a set of directory containing CSV files, merge all series and write results in a new directory. The merge is only based on series names, not file names, so if for one series, different file names were used, then only one of them will be chosen in the final destination directory, the shortest one.  &lt;pre class="brush: scala;highlight: []"&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;exec jaseries -deprecation -savecompiled "$0" "$@"&lt;br /&gt;!#&lt;br /&gt;/*&lt;br /&gt; * Copyright 2011 David Crosson&lt;br /&gt; * &lt;br /&gt; * Licensed under the Apache License, Version 2.0 (the "License");&lt;br /&gt; * you may not use this file except in compliance with the License.&lt;br /&gt; * You may obtain a copy of the License at&lt;br /&gt; * &lt;br /&gt; *   http://www.apache.org/licenses/LICENSE-2.0&lt;br /&gt; * &lt;br /&gt; * Unless required by applicable law or agreed to in writing, software&lt;br /&gt; * distributed under the License is distributed on an "AS IS" BASIS,&lt;br /&gt; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&lt;br /&gt; * See the License for the specific language governing permissions and&lt;br /&gt; * limitations under the License.&lt;br /&gt; */&lt;br /&gt;import fr.janalyse.series._&lt;br /&gt;import java.io.File&lt;br /&gt;&lt;br /&gt;if (args.size &lt; 2) {&lt;br /&gt;  println("usage : csv-merge srcDir1 ... srcDirN destNewDir")&lt;br /&gt;  println("  Merge and reduce numeric series stored in CSV files")&lt;br /&gt;  System.exit(0)&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;case class InputSeries(name:String, filebasename:String, series:Series[Cell])&lt;br /&gt;def file(filename:String) = new File(filename)&lt;br /&gt;def file(dirname:String, filename:String) = new File(dirname, filename)&lt;br /&gt;def file(dir:File, filename:String) = new File(dir, filename)&lt;br /&gt;&lt;br /&gt;def csvFileFilter(f:String):Boolean = {f.endsWith(".csv") ||f.endsWith(".jxtcsv")}&lt;br /&gt;val basename1RE="""(.*)(?:[-_]\d+)[.].+"""r&lt;br /&gt;val basename2RE="""(.*)[.].+"""r&lt;br /&gt;def basename(filename:String) = filename match {&lt;br /&gt;  case basename1RE(basename) =&gt; basename&lt;br /&gt;  case basename2RE(basename) =&gt; basename&lt;br /&gt;  case other =&gt; other&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;val toMerge = args.init&lt;br /&gt;val destNewDir = file(args.last)&lt;br /&gt;&lt;br /&gt;destNewDir.mkdirs()&lt;br /&gt;&lt;br /&gt;// --- Read everything&lt;br /&gt;var inputSeriesList=List.empty[InputSeries]&lt;br /&gt;for( dirname&lt;-toMerge ; &lt;br /&gt;     filename&lt;-file(dirname).list filter csvFileFilter;&lt;br /&gt;     (seriesname, series)&lt;-CSV2Series.fromFile(file(dirname, filename))) {&lt;br /&gt;  val filebasename = basename(filename)&lt;br /&gt;  inputSeriesList = InputSeries(seriesname, filebasename, series)::inputSeriesList&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// --- Merge and Reduce&lt;br /&gt;val seriesGroupByName=inputSeriesList groupBy {is =&gt; is.name}&lt;br /&gt;val mergedSeriesList = for( (seriesname, inputSeriesList4Name) &lt;- seriesGroupByName) yield {&lt;br /&gt;  val mergedseries   = inputSeriesList4Name.map(_.series) reduceLeft {_ &lt;&lt;&lt; _}&lt;br /&gt;  val mergedbasename = inputSeriesList4Name.map(_.filebasename).min&lt;br /&gt;  (mergedseries, mergedbasename)&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// --- Write everything&lt;br /&gt;val mergedSeriesGroupByBasename = mergedSeriesList groupBy { case (_, basename) =&gt; basename}&lt;br /&gt;for( (mergedbasename, mergedTuples) &lt;- mergedSeriesGroupByBasename) {&lt;br /&gt;  val seriesList = mergedTuples map {case (series,_) =&gt; series}&lt;br /&gt;  CSV2Series.toFile(seriesList, file(destNewDir, mergedbasename+".csv"))&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4576039096616564465-5818666197699113607?l=www.crosson.org' alt='' /&gt;&lt;/div&gt;</description><link>http://www.crosson.org/2012/01/csv-files-merge-based-on-series-names.html</link><author>noreply@blogger.com (david crosson)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-4576039096616564465.post-6350918716232118590</guid><pubDate>Thu, 05 Jan 2012 13:31:00 +0000</pubDate><atom:updated>2012-01-05T14:34:33.285+01:00</atom:updated><title>Build Play20 with latest sources, and let's play.</title><description>All the steps to run your first play 2 web application using latest play improvements; until the first stable release will be ready. The idea here is to build yourself Play.   Eclipsify is now taken into account, so once all the steps described here are done, you can import it into eclipse IDE.  &lt;pre class="brush: bash;highlight: [1,3,5,7,11,13,15,46,48]"&gt;&lt;br /&gt;$ cd ~/workdir&lt;br /&gt;&lt;br /&gt;$ git clone https://github.com/playframework/Play20.git&lt;br /&gt;&lt;br /&gt;$ cd Play20/framework&lt;br /&gt;&lt;br /&gt;$ ./build&lt;br /&gt;&gt; build-repository&lt;br /&gt;&gt; exit&lt;br /&gt;&lt;br /&gt;$ export PATH=$PATH~/workdir/Play20&lt;br /&gt;&lt;br /&gt;$ cd ~/workdir&lt;br /&gt;&lt;br /&gt;$ play new firstapp&lt;br /&gt;&lt;br /&gt;Getting play console_2.9.1 2.0-RC1-SNAPSHOT ...&lt;br /&gt;:: retrieving :: org.scala-tools.sbt#boot-app&lt;br /&gt; confs: [default]&lt;br /&gt; 5 artifacts copied, 0 already retrieved (5161kB/19ms)&lt;br /&gt;       _            _ &lt;br /&gt; _ __ | | __ _ _  _| |&lt;br /&gt;| '_ \| |/ _' | || |_|&lt;br /&gt;|  __/|_|\____|\__ (_)&lt;br /&gt;|_|            |__/ &lt;br /&gt;             &lt;br /&gt;play! 2.0-RC1-SNAPSHOT, http://www.playframework.org&lt;br /&gt;&lt;br /&gt;The new application will be created in /home/dcr/experiments/firstapp&lt;br /&gt;&lt;br /&gt;What is the application name? &lt;br /&gt;&gt; firstapp&lt;br /&gt;&lt;br /&gt;Which template do you want to use for this new application? &lt;br /&gt;&lt;br /&gt;  1 - Create a simple Scala application&lt;br /&gt;  2 - Create a simple Java application&lt;br /&gt;  3 - Create an empty project&lt;br /&gt;&lt;br /&gt;&gt; 1&lt;br /&gt;&lt;br /&gt;OK, application firstapp is created.&lt;br /&gt;&lt;br /&gt;Have fun!&lt;br /&gt;&lt;br /&gt;$ cd firstapp&lt;br /&gt;&lt;br /&gt;$ play &lt;br /&gt;&gt; eclipsify&lt;br /&gt;&gt; run&lt;br /&gt;--- (Running the application from SBT, auto-reloading is enabled) ---&lt;br /&gt;&lt;br /&gt;[info] play - Listening for HTTP on port 9000...&lt;br /&gt;&lt;br /&gt;(Server started, use Ctrl+D to stop and go back to the console...)&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt; Now everything is ready, to test and modify the simple scala project application using eclipse. More information can be found on : &lt;a href="http://scala-ide.org/docs/tutorials/play20scalaide20/index.html"&gt;play20 and scala ide 20 tutorial&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4576039096616564465-6350918716232118590?l=www.crosson.org' alt='' /&gt;&lt;/div&gt;</description><link>http://www.crosson.org/2012/01/build-play20-with-latest-sources-and.html</link><author>noreply@blogger.com (david crosson)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-4576039096616564465.post-5097580887840166231</guid><pubDate>Wed, 14 Dec 2011 22:46:00 +0000</pubDate><atom:updated>2012-01-09T22:15:11.952+01:00</atom:updated><title>Easy SSH scala scripting</title><description>Visit &lt;a href="http://code.google.com/p/janalyse-ssh/"&gt;janalyse-ssh&lt;/a&gt;, and download "jassh.jar" standalone executable jar.&lt;br/&gt; In the same directory where you've downloaded "jassh.jar"file, create a file named "helloworld", and copy&amp;paste the following content in it :  &lt;pre class="brush: scala;highlight: []"&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;exec java -jar jassh.jar -nocompdaemon -usejavacp -savecompiled "$0" "$@"&lt;br /&gt;!#&lt;br /&gt;import fr.janalyse.ssh._&lt;br /&gt;SSH.connect(host="localhost", username="test", password="testtest") { ssh =&gt;&lt;br /&gt;  println(ssh.execute("""echo -n "Hello World from `hostname`" """))&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt; Change the specified user to an existing user, or create a "test" user. Give the right password or remove it if you've exported your public SSH key in remote user ~test/.ssh/authorized_keys file&lt;br/&gt; Then make your "helloworld" file executable (chmod u+x helloworld), and execute it :  &lt;pre class="brush: bash;highlight: []"&gt;&lt;br /&gt;toto@myhost $ ./helloworld &lt;br /&gt;Hello World from myhost&lt;br /&gt;&lt;/pre&gt; Easy ! And you'll take all benefits of the scala language using just vi, in order to make any kind of remote operations ! No graphical user interface required, no compiler (automatic &amp; transparent compilation on the fly when needed), high performances (I've reached a command throughput up to 545 cmd/s on my host), parallelism using actors, easy parsing using combinators, ...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4576039096616564465-5097580887840166231?l=www.crosson.org' alt='' /&gt;&lt;/div&gt;</description><link>http://www.crosson.org/2011/12/easy-ssh-scala-scripting.html</link><author>noreply@blogger.com (david crosson)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-4576039096616564465.post-8734090956818228594</guid><pubDate>Sun, 11 Dec 2011 20:36:00 +0000</pubDate><atom:updated>2011-12-23T08:11:28.903+01:00</atom:updated><title>JMX grep scala script</title><description>A simple script to search for mbeans/attributes-names/attribute-values matching regular expressions given as script parameters. This script is using &lt;a href="http://code.google.com/p/janalyse-jmx/"&gt;janalyse-jmx scala API&lt;/a&gt;; jajmx.jar java executable is used to startup the script.&lt;br/&gt; This jmx grep script can be used against itself, with its own embedded jmx platform. This feature is enabled through java options (JAVA_OPTS) specified within script startup header.&lt;br/&gt; &lt;pre class="brush: bash;highlight: [1,16]"&gt;&lt;br /&gt;$ ./jmxgrep localhost 9999  operating&lt;br /&gt;java.lang:type=OperatingSystem - MaxFileDescriptorCount = 4096&lt;br /&gt;java.lang:type=OperatingSystem - OpenFileDescriptorCount = 18&lt;br /&gt;java.lang:type=OperatingSystem - CommittedVirtualMemorySize = 4520407040&lt;br /&gt;java.lang:type=OperatingSystem - FreePhysicalMemorySize = 7900864512&lt;br /&gt;java.lang:type=OperatingSystem - FreeSwapSpaceSize = 10742177792&lt;br /&gt;java.lang:type=OperatingSystem - ProcessCpuTime = 1490000000&lt;br /&gt;java.lang:type=OperatingSystem - TotalPhysicalMemorySize = 16848113664&lt;br /&gt;java.lang:type=OperatingSystem - TotalSwapSpaceSize = 10742177792&lt;br /&gt;java.lang:type=OperatingSystem - Name = Linux&lt;br /&gt;java.lang:type=OperatingSystem - AvailableProcessors = 6&lt;br /&gt;java.lang:type=OperatingSystem - Arch = amd64&lt;br /&gt;java.lang:type=OperatingSystem - SystemLoadAverage = 0.0&lt;br /&gt;java.lang:type=OperatingSystem - Version = 3.0.6-gentoo&lt;br /&gt;&lt;br /&gt;$ ./jmxgrep localhost 9999 threadcount&lt;br /&gt;java.lang:type=GarbageCollector,name=PS MarkSweep - LastGcInfo = javax.management.openmbean.CompositeDataSupport(compositeTyp...&lt;br /&gt;java.lang:type=Runtime - SystemProperties = javax.management.openmbean.TabularDataSupport(tabularType=ja...&lt;br /&gt;java.lang:type=Threading - DaemonThreadCount = 12&lt;br /&gt;java.lang:type=Threading - PeakThreadCount = 13&lt;br /&gt;java.lang:type=Threading - ThreadCount = 13&lt;br /&gt;java.lang:type=Threading - TotalStartedThreadCount = 13&lt;br /&gt;java.lang:type=GarbageCollector,name=PS Scavenge - LastGcInfo = javax.management.openmbean.CompositeDataSupport(compositeTyp...&lt;br /&gt;&lt;/pre&gt;  jmxgrep code (just copy paste this code into a file named jmxgrep, and make it executable using chmod a+x jmxgrep) :  &lt;pre class="brush: scala;highlight: []"&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;JAVA_OPTS=""&lt;br /&gt;JAVA_OPTS=$JAVA_OPTS" -Dcom.sun.management.jmxremote"&lt;br /&gt;JAVA_OPTS=$JAVA_OPTS" -Dcom.sun.management.jmxremote.port=9999"&lt;br /&gt;JAVA_OPTS=$JAVA_OPTS" -Dcom.sun.management.jmxremote.authenticate=false"&lt;br /&gt;JAVA_OPTS=$JAVA_OPTS" -Dcom.sun.management.jmxremote.ssl=false"&lt;br /&gt;SCA_OPTS="-nocompdaemon -usejavacp -savecompiled"&lt;br /&gt;exec java $JAVA_OPTS -jar jajmx.jar $SCA_OPTS "$0" "$@"&lt;br /&gt;!#&lt;br /&gt;&lt;br /&gt;import fr.janalyse.jmx._&lt;br /&gt;import JMXImplicits._&lt;br /&gt;&lt;br /&gt;if (args.size &lt; 2) {&lt;br /&gt;  println("Usage   : jmxgrep host port searchMask1 ... searchMaskN")&lt;br /&gt;  println("Example : jmxgrep localhost 1099  vendor")&lt;br /&gt;  println("   will self connect to jmx server, and looks for vendor keyword")&lt;br /&gt;  System.exit(1)&lt;br /&gt;}&lt;br /&gt;val host  = args(0)&lt;br /&gt;val port  = args(1).toInt&lt;br /&gt;val masks = args.toList.drop(2) map {s=&gt;("(?i)"+s).r}&lt;br /&gt;&lt;br /&gt;def truncate(str:String, n:Int=60) = if (str.size&gt;n) str.take(n)+"..." else str&lt;br /&gt;&lt;br /&gt;JMX.connect(host, port) { implicit jmx =&gt;&lt;br /&gt;  for(on &lt;- jmx.browse ; attr &lt;- on.browse) {&lt;br /&gt;    val value = try { on.get[Any](attr).toString} catch { case _ =&gt; "**error**"}&lt;br /&gt;    val found = List(on.toString, attr, value) exists { item =&gt;&lt;br /&gt;      masks exists {re =&gt; (re findFirstIn item).isDefined} &lt;br /&gt;    }&lt;br /&gt;    if (found || masks.isEmpty) println("%s - %s = %s".format(on, attr, truncate(value)))&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt; Notice the "-savecompiled" scala option which enable the script compilation result to be stored in a file named "jmxgrep.jar". When started, already compiled code will be reuse if the script hasn't been modified since last compilation time. This allow very fast script startup.&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4576039096616564465-8734090956818228594?l=www.crosson.org' alt='' /&gt;&lt;/div&gt;</description><link>http://www.crosson.org/2011/12/jmx-grep-scala-script.html</link><author>noreply@blogger.com (david crosson)</author><thr:total>0</thr:total></item></channel></rss>
