Sunday, July 15, 2012

GPars DataflowQueues

//source: http://jaxenter.com/tutorial-gpars-making-parallel-systems-groovy-and-java-friendly-43529-2.html
//a sample code build process //

//source: http://jaxenter.com/tutorial-gpars-making-parallel-systems-groovy-and-java-friendly-43529-2.html
//a sample code build process //

import static groovyx.gpars.dataflow.Dataflow.operator
import groovyx.gpars.dataflow.*


def _checkout = { String a ->
    Thread.sleep( (Long)Math.random() * 5 ); // a bit of random delay for fun
    println ">checking out...$a"
    return "checkout-$a"
}
def _compileSources = { a ->
    println ">compiling...$a"
    return "compileSources-$a"
}
def _generateAPIDoc = { a ->
    println ">api Docs...$a"
    return "generateAPIDoc-$a"
}
def _generateUserDocumentation = { a ->
    println ">user Docs...$a"
    return "generateUserDocumentation-$a"
}
def _packageProject = { project, api, doc ->
    println ">packaging...$project $api $doc"
    return "packageProject-$project $api $doc"
}
def _deploy = { a ->
    println ">deploying...$a"
    return (!!Math.round(Math.random()))
}


/* We need a Broadcaster and Queues to wire elements together */
def checkedOutProjects_B = new DataflowBroadcast()
def urls_Q = new DataflowQueue()
def compiledProjects_Q = new DataflowQueue()
def apiDocs_Q = new DataflowQueue()
def userDocs_Q = new DataflowQueue()
def packages_Q = new DataflowQueue()
def done_Q = new DataflowQueue()



/* Here's the composition of individual build steps into a process */
operator(inputs: [urls_Q], outputs: [checkedOutProjects_B], maxForks: 3) { url ->
    bindAllOutputs _checkout(url)
}
operator([checkedOutProjects_B.createReadChannel()], [compiledProjects_Q]) { projectRoot ->
    bindOutput _compileSources(projectRoot)
}
operator(checkedOutProjects_B.createReadChannel(), apiDocs_Q) { projectRoot ->
    bindOutput _generateAPIDoc(projectRoot)
}
operator(checkedOutProjects_B.createReadChannel(), userDocs_Q) { projectRoot ->
    bindOutput _generateUserDocumentation(projectRoot)
}
operator([compiledProjects_Q, apiDocs_Q, userDocs_Q], [packages_Q]) { project, api, doc ->
    bindOutput _packageProject(project, api, doc)
}

def deployer = operator(packages_Q, done_Q) { packagedProject ->
    boolean ok = _deploy(packagedProject)
    println "! Deployed? $ok"
    bindOutput (ok)
}


/* add data, start the machine a rollin! */
5.times { urls_Q << "url #$it" }
5.times { urls_Q << "url #${++it*5}" }


/* Now we're set up, and can just wait for the build to finish */
println "==Starting the build process. This line MIGHT NOT be printed out first ...=="

//deployer.join()  //Wait for the last operator in the network to finish??

Thursday, July 12, 2012

GBench - easy code benchmarking

//source: http://nagaimasato.blogspot.jp/2012/07/gbench-031-released.html
//requires Groovy 2.0.0+

@Grab('com.googlecode.gbench:gbench:0.3.1-groovy-2.0') 
import gbench.BenchmarkBuilder
import groovy.transform.CompileStatic
 
int fib(int n) {
    if (n < 2) return n 
    return fib(n - 1) + fib(n - 2)  
} 
 
@CompileStatic 
int fib2(int n) { 
    if (n < 2) return n 
    return fib2(n - 1) + fib2(n - 2)  
} 
 
new BenchmarkBuilder().run { 
    int n = 20  
    "Normal Version" { fib n } 
    "@CompileStatic Version" { fib2 n } 
}.prettyPrint() 

Wednesday, July 11, 2012

Conceptual Map/Reduce Example

//inspiration: http://hamletdarcy.blogspot.ca/2008/01/mapreduce-for-mere-mortals.html

// general purpose function
def mapReduceFunc = { data, mapFunction, reduceFunction ->
  def mappedData = data.collect(mapFunction)
  reduceFunction(mappedData)
}

// the data
Map dictionary = [
  abacus: "a device for making arithmetic calculations", 
  arc: "any unbroken part of the circumference of a circle", 
  beaver: "a large, amphibious rodent of the genus Castor"
]

// the mapping function impl
def startingCharacter = { pair ->
  pair.value = pair.key[0].toLowerCase()
  return pair
}

// the reducing function impl
def countCharacters = { dataMap ->
  Map result = [:]
  ('a'..'z').each{ result[it] = 0 }
  dataMap.each { pair -> result[pair.value]++ }
  return result
}

// put it all together!
def result1 = mapReduceFunc(dictionary, startingCharacter, countCharacters)
println result1

//// TWEAK THE I/O FUNCS!  ////

// the mapping function impl
startingCharacter = { pair ->
  return pair.key[0].toLowerCase()
}

// the reducing function impl
countCharacters = { dataList ->
  Map result = [:]
  ('a'..'z').each{ result[it] = 0 }
  dataList.each { it -> result[it]++ }
  return result
}

// put it all together!
def result2 = mapReduceFunc(dictionary, startingCharacter, countCharacters)
println result2

assert result1 == result2

Saturday, June 23, 2012

MockFor

//http://groovy.codehaus.org/Using+MockFor+and+StubFor

import groovy.mock.interceptor.*

/*sample data class*/
class Movie {
    // Lots of expensive method calls, etc.
}

/*helper class*/
class MovieAnalyzer {
    def isGood( movie ) {
        if( movie.hasGalifinakis() )
            return true;
        else if( movie.hasSparklyVampires() )
            return false;

        return ( new Date().getTime() / 2 ) == 0 
    }
}

/*unit test the helper class by mocking the data class*/
def testTwitlightMovie(){
    def mock = new MockFor(Movie)
    //StubFor is similar to MockFor except that 
    //the expectaion of methods called is order independent ...
    mock.demand.hasGalifinakis { true }
    mock.demand.hasSparklyVampires( 0..1 ) { true } // demand the method 0 or 1 times
    mock.use {
       assert true == new MovieAnalyzer().isGood( new Movie() )
    }
}

testTwitlightMovie()

Tuesday, May 22, 2012

Quartz Job Scheduler

//a better Groovy DSL example: https://gist.github.com/1505600
//Note: a simple timer implementation with runAfter(): http://mrhaki.blogspot.ca/2009/11/groovy-goodness-run-code-at-specified.html

@Grapes(
    @Grab(group='org.quartz-scheduler', module='quartz', version='2.1.5')
)
import org.quartz.*
import org.quartz.impl.*
import static org.quartz.JobBuilder.*
import static org.quartz.TriggerBuilder.*
import static org.quartz.SimpleScheduleBuilder.*

class HelloJob implements Job {
    public void execute(JobExecutionContext context) {
        println "Hello "+(new Date().getTime())
    }
}

try {
    // Grab the Scheduler instance from the Factory 
    Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler()

    // Start it!
    scheduler.start()

     JobDetail job = newJob(HelloJob)
         .withIdentity("myJob"+(new Date().getTime()), "group1")
         .build()
         
     Trigger trigger = newTrigger()
         .withIdentity(new TriggerKey("myTrigger"+(new Date().getTime()), "group1"))
         .withSchedule(simpleSchedule()
             .withIntervalInSeconds(5)
             .repeatForever())
         .startNow()
         .build()

    // Tell quartz to schedule the job using our trigger
    scheduler.scheduleJob(job, trigger)
    
    // Pause thread for 60 seconds
    Thread.sleep(60000)
    
    // End it!
    scheduler.shutdown()
}
catch (SchedulerException se) {
    se.printStackTrace()
}

Beep Sound

java.awt.Toolkit.getDefaultToolkit().beep() // doesn't always work

println ("\007"*3) //3 beeps

Tuesday, April 24, 2012

self-referenced tree, in one line!

//source: https://gist.github.com/2478499

def tree = { [:].withDefault{ owner.call() } } // ta-da!

users = tree()

users.harold.username = 'hrldcpr'
users.yates.username = 'tim'

users.with {
    al.username = 'al1'
    derek.username = 'skinnyk1d'
    
    frier.with {
        username = 'great1'
        password = 'changeme1'
        updatedOn = '4/26/2012'
    }
    
    bob.with {
        age = 4
        isOld = false
    }
}

println new groovy.json.JsonBuilder( users ).toPrettyString()