Gant is Awesome

August 19, 2009

If you have never heard of Gant, its a tool that lets you write Ant scripts in Groovy. Rather than being a replacement to Groovy, it actually empowers your Ant scripts by letting you use Ant and Groovy easily and seamlessly.

I have been playing with Memcached for a while now. So once in a while, I had to flush the cache from all Memcached servers in development. Since I am using a cluster of servers, its tedious to telnet to each of them and issue the flush_all command.

$ telnet localhost 11211
Trying ::1...
Connected to localhost.
Escape character is '^]'.
flush_all
OK

If I wanted to view the stats, I had to telnet to the server and issue the stats command to each.

The SpyMemcached Java Client that I am using provides those APIs in Java for interacting with the servers.

Since I kept doing it so often, I decided to add a couple of targets in my build script written in Gant.

1. flush-all:

Ant provides you an optional telnet task using the Apache Commons Net library so that you can issue any command over telnet. So to use the library, lets put it into Ant’s path first.

$ cp commons-net-2.0.jar ~/.ant/lib/

If you were to do in Ant, the task would be like:

<telnet port=11211 server="localhost">
<write>flush_all</write>
<write>quit</write>
</telnet>

I can do the same thing in Gant:

ant.telnet( port:11211, server:"localhost") {
       write("flush_all")
       write("quit")
}

Nothing fancy, but its a lot more readable in Java code than in XML.

2. stats:

We can do a similar thing for stats by issuing the stats command over telnet. But instead, lets use the SpyMemcached library to get stats of each server in the cluster. So lets put the library in Ant’s path first:

$ cp memcached-2.3.1.jar ~/.ant/lib/
MemcachedClient cache=new MemcachedClient(
                 AddrUtil.getAddresses("server6:11211 server7:11211 server8:11211"));
cache.getStats();

Thats it. I can write this Java code from my Gant script.

Putting together everything and with a little bit of formatting, here’s what my build.gant now looks like:

import org.apache.commons.net.telnet.TelnetClient
import net.spy.memcached.MemcachedClient
import net.spy.memcached.BinaryConnectionFactory
import net.spy.memcached.AddrUtil

target ( 'cache-flush' : "Flush cache on all servers") {
     for(int i=6; i < 9; i++){
          ant.telnet( port:11211, server:"server${i}") {
               write("flush_all")
               write("quit")
               println "Flushing Cache on server${i}"
          }
     }
     println "Successfully flushed cache on all servers"
}

target ( 'cache-stats' : "Cache stats on all servers") {
     try {
          MemcachedClient cache=new MemcachedClient(
                AddrUtil.getAddresses("server6:11211 server7:11211 server8:11211"))
          Map allStats = cache.getStats()

          println("CACHE STATS FOR ALL SERVERS")
          System.out.printf("%30s", "")
          allStats.keySet().each {
               System.out.printf("%-30s", it)
          }

          List list = new ArrayList()
          allStats.keySet().each {
               Map stats = allStats.get(it)
               list.add(stats)
          }

          list.get(0).keySet().each { a->
               System.out.printf("%-30s %-30s %-30s %-30sn",
                    a, list.get(0).get(a), list.get(1).get(a), list.get(2).get(a));
          }

     } catch(Exception e) {
          println "Exception caught while getting cache stats ${e}"
     }
}

Notice how seamlessly I was able to use Ant, Groovy and Java all in one. Super powerful.

Now, by going to the location of my build.gant file, I can just do :

$ gant cache-flush

$ gant cache-stats

Bottomline – Gant is awesome.

2 Comments on Gant is Awesome

Respond | Trackback

  1. Chris says:

    As usual, you have both enlightened me and energized my enthusiasm.

  2. geo says:

    Nice article! I would have wrote the for in the cache-flush target using a range. It seems clearer to me that way.

Respond

Comments

Comments