<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss'><id>tag:blogger.com,1999:blog-174903826897473842</id><updated>2009-11-11T09:26:05.458Z</updated><title type='text'>miau.biz</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://blog.miau.biz/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default'/><link rel='alternate' type='text/html' href='http://blog.miau.biz/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default?start-index=26&amp;max-results=25'/><author><name>Miaubiz</name><uri>http://www.blogger.com/profile/06950334298510471857</uri><email>miaubiz@gmail.com</email></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>103</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-174903826897473842.post-2519531276127798943</id><published>2009-11-08T06:44:00.003Z</published><updated>2009-11-08T06:55:11.141Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='concurrency'/><title type='text'>shows what I know</title><content type='html'>ruby 1.9.1 is blazing fast I hear.  and  it doesn't segfault when I run our build on it, unlike 1.8.  it uses native threads. they all acquire the &lt;a href="http://www.infoq.com/news/2009/07/future-ruby-gc-gvl-gil"&gt;giant interpreter/vm lock&lt;/a&gt;. and I finally rediscovered the &lt;a href="http://www.artima.com/forums/flat.jsp?forum=281&amp;amp;thread=211839"&gt;ruby isn't erlang&lt;/a&gt; post I've been talking about.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://jruby.org/2009/11/02/jruby-1-4-0.html"&gt;jruby 1.4.0&lt;/a&gt; is out and buildr 1.3.5.  and java5 is dead.&lt;br /&gt;&lt;br /&gt;--&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/174903826897473842-2519531276127798943?l=blog.miau.biz' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.miau.biz/feeds/2519531276127798943/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=174903826897473842&amp;postID=2519531276127798943' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/2519531276127798943'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/2519531276127798943'/><link rel='alternate' type='text/html' href='http://blog.miau.biz/2009/11/shows-what-i-know.html' title='shows what I know'/><author><name>Miaubiz</name><uri>http://www.blogger.com/profile/06950334298510471857</uri><email>miaubiz@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05794848006157778693'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-174903826897473842.post-4804566690402517655</id><published>2009-11-07T06:38:00.003Z</published><updated>2009-11-07T07:01:22.195Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='ambient monad'/><category scheme='http://www.blogger.com/atom/ns#' term='ec2'/><category scheme='http://www.blogger.com/atom/ns#' term='wave protocol'/><category scheme='http://www.blogger.com/atom/ns#' term='misko'/><title type='text'>cpus</title><content type='html'>cpu benchmarks usually have identical elements across different review sites.  on the same site it is certainly important to use the same benchmarks for every cpu but all site have games, video encoding, raytracing and a few synthetic benchmarks.&lt;br /&gt;&lt;br /&gt;no one posts benchmarks of compilation and automated test runs.  and it's rather expensive to benchmark cpus yourself.&lt;br /&gt;&lt;br /&gt;ec2 added the m2.4xlarge which is 2x x5550 and 64gb memory. they count each core as 3.25 ECU &lt;span style="font-size:78%;"&gt;(their own generic cpu performance comparison unit)&lt;/span&gt; versus 2.5ECU per core on the c1.xlarge which is 2x e5410.&lt;br /&gt;&lt;br /&gt;x5550 is a 2.66ghz 95w nehalem with a slight turbo and 2x QPI. i think HT is disabled on ec2.&lt;br /&gt;&lt;br /&gt;our 3 minute test run ran in 2 minutes flat over there.&lt;br /&gt;&lt;br /&gt;since memory was not an issue in launching multiple jvms for striped_junit, I tried a bunch of different thread counts but they didn't make a difference between 3 and 6.  beyond that performance started to deteriorate.&lt;br /&gt;&lt;br /&gt;meawhile I was happy to find google's wave protocol using a &lt;a href="http://code.google.com/p/wave-protocol/source/browse/src/org/waveprotocol/wave/crypto/TimeSource.java"&gt;TimeSource&lt;/a&gt; only to have it kicked out of our own code base half a day later. I learned that global state is the &lt;a href="http://work.tinou.com/2009/07/one-big-ambient-monad.html"&gt;ambient monad&lt;/a&gt;. and I'd like to see what Misko has to say about &lt;a href="http://wave-protocol.googlecode.com/hg/src/org/waveprotocol/wave/model/operation/Transform.java"&gt;Transform.java&lt;/a&gt;...&lt;br /&gt;&lt;br /&gt;in &lt;strike&gt;soviet russia&lt;/strike&gt; japan you are the &lt;a href="http://www.theglasshammer.com/news/2008/07/11/the-nail-that-sticks-out-adventures-of-a-female-gaijin-attorney-in-corporate-japan/"&gt;worm&lt;/a&gt; and the early bird eats you.&lt;br /&gt;&lt;br /&gt;Dr. Odersky, would it please be possible to add the following sugar to scalac:&lt;br /&gt;&lt;br /&gt;def lol(list: List) = { list.first }&lt;br /&gt;&lt;br /&gt;is the same as:&lt;br /&gt;&lt;br /&gt;def lol[A](list: List[A]) = { list.first }&lt;br /&gt;&lt;br /&gt;--&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/174903826897473842-4804566690402517655?l=blog.miau.biz' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.miau.biz/feeds/4804566690402517655/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=174903826897473842&amp;postID=4804566690402517655' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/4804566690402517655'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/4804566690402517655'/><link rel='alternate' type='text/html' href='http://blog.miau.biz/2009/11/cpus.html' title='cpus'/><author><name>Miaubiz</name><uri>http://www.blogger.com/profile/06950334298510471857</uri><email>miaubiz@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05794848006157778693'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-174903826897473842.post-4179520032007436105</id><published>2009-11-03T13:07:00.004Z</published><updated>2009-11-03T13:30:58.451Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='awesome'/><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>implicit type conversions</title><content type='html'>the more I think about them the awesomer they are.&lt;br /&gt;&lt;br /&gt;compared to ruby's monkey patching they are delightfully unobtrusive and safe.&lt;br /&gt;&lt;br /&gt;compared to explicit conversions.&lt;br /&gt;&lt;br /&gt;--&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/174903826897473842-4179520032007436105?l=blog.miau.biz' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.miau.biz/feeds/4179520032007436105/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=174903826897473842&amp;postID=4179520032007436105' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/4179520032007436105'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/4179520032007436105'/><link rel='alternate' type='text/html' href='http://blog.miau.biz/2009/11/implicit-type-conversions.html' title='implicit type conversions'/><author><name>Miaubiz</name><uri>http://www.blogger.com/profile/06950334298510471857</uri><email>miaubiz@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05794848006157778693'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-174903826897473842.post-3616427923883913751</id><published>2009-10-16T18:31:00.007+01:00</published><updated>2009-10-17T09:59:38.643+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='data structures'/><category scheme='http://www.blogger.com/atom/ns#' term='lockfree'/><category scheme='http://www.blogger.com/atom/ns#' term='dcas'/><category scheme='http://www.blogger.com/atom/ns#' term='cas'/><category scheme='http://www.blogger.com/atom/ns#' term='hardware'/><category scheme='http://www.blogger.com/atom/ns#' term='optimistic'/><category scheme='http://www.blogger.com/atom/ns#' term='concurrency'/><title type='text'>I'm tellin' y'all it's double cas</title><content type='html'>double compare and swap is the ability to atomically update two &lt;span style="font-weight: bold;"&gt;independent&lt;/span&gt; memory locations if both of them remain unchanged. no mainstream hardware architecture supports this.&lt;br /&gt;&lt;br /&gt;x86 has  cmpxchg8b for two &lt;span style="font-weight: bold;"&gt;sequential&lt;/span&gt; 32 bit words and  cmpxchg16b for two 64 bit words.  the sequential variant enables some interesting operations but is generally &lt;a href="http://lwn.net/Articles/258154/"&gt;not very useful&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;researchers are busy inventing &lt;a href="http://research.sun.com/techrep/2002/abstract-111.html"&gt;algorithms&lt;/a&gt; that could be implemented if dcas existed.  &lt;a href="http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;amp;Sect2=HITOFF&amp;amp;d=PALL&amp;amp;p=1&amp;amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;amp;r=1&amp;amp;f=G&amp;amp;l=50&amp;amp;s1=7583687.PN.&amp;amp;OS=PN/7583687&amp;amp;RS=PN/7583687"&gt;sweet&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;simplified, the 'hat trick' lock free deque is a doubly linked list. each end of the list also has a hat. the hat points to the same location as the head of the queue. this location points to null.&lt;br /&gt;&lt;br /&gt;when pushing or popping, if both the hat and the null remain unchanged, no one interfered during your operation. you update the hat and the value the hat pointed to previously.&lt;br /&gt;&lt;br /&gt;the proposed deque with the dcas on independent pointers also avoids the dereferencing problem mentioned by LWN.&lt;br /&gt;&lt;br /&gt;-&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/174903826897473842-3616427923883913751?l=blog.miau.biz' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.miau.biz/feeds/3616427923883913751/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=174903826897473842&amp;postID=3616427923883913751' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/3616427923883913751'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/3616427923883913751'/><link rel='alternate' type='text/html' href='http://blog.miau.biz/2009/10/im-tellin-yall-its-double-cas.html' title='I&apos;m tellin&apos; y&apos;all it&apos;s double cas'/><author><name>Miaubiz</name><uri>http://www.blogger.com/profile/06950334298510471857</uri><email>miaubiz@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05794848006157778693'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-174903826897473842.post-6429035949964002533</id><published>2009-09-06T08:25:00.005+01:00</published><updated>2009-09-06T08:34:49.783+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='deidentification'/><category scheme='http://www.blogger.com/atom/ns#' term='paranoia'/><category scheme='http://www.blogger.com/atom/ns#' term='information'/><category scheme='http://www.blogger.com/atom/ns#' term='sensors'/><category scheme='http://www.blogger.com/atom/ns#' term='temperature'/><title type='text'>privacy and such</title><content type='html'>temperature data seemed innocent enough at first thought.  no harm in letting people know what the temperature is at my house. I was fascinated when I saw this appear.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_US30JXBRJSI/SqNk3ta0xiI/AAAAAAAAACU/vTKiuX7ZshA/s1600-h/temperatures.png"&gt;&lt;img style="cursor: pointer; width: 320px; height: 133px;" src="http://4.bp.blogspot.com/_US30JXBRJSI/SqNk3ta0xiI/AAAAAAAAACU/vTKiuX7ZshA/s320/temperatures.png" alt="" id="BLOGGER_PHOTO_ID_5378253288258192930" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;the graph shows the temperature measured by two sensors on windows facing the same direction on three consecutive days.  at the same time every day a distinct M-shape appears.  unless it's a systematic bug in my measurements or code, I &lt;span style="font-style: italic;"&gt;guess&lt;/span&gt; it has to do with the way the sun shines in through the windows when it passes between two buildings.  the drop in the middle is a tree or other obstacle.&lt;br /&gt;&lt;br /&gt;this kind of peculiar shape could be used to fingerprint data, determine what latitude the measurements were taken at, what direction the windows are facing, or even identify the windows where the measurements were made.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/174903826897473842-6429035949964002533?l=blog.miau.biz' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.miau.biz/feeds/6429035949964002533/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=174903826897473842&amp;postID=6429035949964002533' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/6429035949964002533'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/6429035949964002533'/><link rel='alternate' type='text/html' href='http://blog.miau.biz/2009/09/privacy-and-such.html' title='privacy and such'/><author><name>Miaubiz</name><uri>http://www.blogger.com/profile/06950334298510471857</uri><email>miaubiz@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05794848006157778693'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_US30JXBRJSI/SqNk3ta0xiI/AAAAAAAAACU/vTKiuX7ZshA/s72-c/temperatures.png' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-174903826897473842.post-635537664773663719</id><published>2009-08-11T10:17:00.012+01:00</published><updated>2009-10-03T08:39:18.233+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='arduino'/><category scheme='http://www.blogger.com/atom/ns#' term='sensor networks'/><category scheme='http://www.blogger.com/atom/ns#' term='wireless'/><title type='text'>a wireless sensor network</title><content type='html'>&lt;span style="font-weight: bold;"&gt;update&lt;/span&gt;: when not using encryption or any sleep modes I am able to remotely reset the funnelio and upload the firmware automatically.  it's awesome.&lt;br /&gt;&lt;br /&gt;I jumpered DTR from UARTSB to DIO3 of the UARTSB.  (and solder SJ1 on the funnelio) with that simple setup it is possible to use the end_device.pro / coordinator_auto_reset.pro from funnel as is.&lt;br /&gt;&lt;br /&gt;--&lt;br /&gt;&lt;br /&gt;the 1980s were characterized by the chips that made computers affordable for households. lasers that enabled long range high speed communications in optic fiber defined the 1990s.   ubiquituous sensors may be the defining technology of the current decade.  mobile phones  contain a number of sensors. android and iphone development environments allow easy access to the collected data, and soon even &lt;a href="https://playsim.dev.java.net/"&gt;SIM cards&lt;/a&gt; will have sensors and be easier to program than some phones.&lt;br /&gt;&lt;br /&gt;I went for a simpler sensor network.    the network has four nodes that measure temperature and report to a central collector which publishes the data.&lt;br /&gt;&lt;br /&gt;I used &lt;a href="http://funnel.cc/Hardware/FIO"&gt;funnelIO&lt;/a&gt; boards, xbee series 1 radios, an &lt;a href="http://www.seeedstudio.com/depot/uartsb-v21-a-much-more-powerful-usb-to-serial-converter-p-272.html"&gt;uartsb&lt;/a&gt;, and &lt;a href="http://datasheets.maxim-ic.com/en/ds/DS18B20.pdf"&gt;ds18b20&lt;/a&gt; temperature sensors.&lt;br /&gt;&lt;br /&gt;I chose the original funnelios from &lt;a href="http://www.sparkfun.com/commerce/product_info.php?products_id=8957"&gt;sparkfun&lt;/a&gt;, over the &lt;a href="http://www.seeedstudio.com/depot/funnel-io-remixed-remixed-p-253.html"&gt;remixed&lt;/a&gt; ones from seeedstudio.  the seeedstudio version has a 2.54mm jst plug for the power.  they don't sell batteries with those plugs, and neither does anyone else.&lt;br /&gt;&lt;br /&gt;there are a &lt;a href="http://www.ladyada.net/make/xbee/arduino.html"&gt;number&lt;/a&gt; of &lt;a href="http://www.sparkfun.com/commerce/tutorial_info.php?tutorials_id=122"&gt;tutorials&lt;/a&gt; on uploading your program wirelessly to an arduino.  the tutorials go into much detail but they require you to do exactly what they do with exactly the same hardware and software.  there are alternative ways of uploading wirelessly, but they aren't covered.  the sparkfun tutorial actually requires you to reprogram your microcontroller.  which is difficult in the case of the funnelio.&lt;br /&gt;&lt;br /&gt;everything starts with the closing of the solder jumper on the funnelio.  the explanation is in the &lt;a href="http://www.sparkfun.com/datasheets/DevTools/Arduino/FIO-v13.pdf"&gt;schematic&lt;/a&gt; of the funnelio.   sj1 connects dio3 of the xbee with the rst pin of the arduino.  the arduino is reset when digital input/output number 3 of the xbee is triggered. dio3 of the receiver is configured as DO HIGH (digital out), which is equivalent to holding down the reset button until that pin is triggered.  the rest deals with setting up the sending side so that when a request to send(&lt;a href="http://en.wikipedia.org/wiki/RS-232"&gt;RTS&lt;/a&gt;), not the same thing as RST(reset) is sent to the serial on the sending side, that information is passed on to the receiver's reset pin.&lt;br /&gt;&lt;br /&gt;if everything works out, you can upload your arduino stuff as if the remote device was connected to your computer with the usb cable. unsurprisingly there are a number of caveats.  the xbee must be powered on, it must associate with the network, it cannot be using encryption, the arduino can connect to a single serial port at a time: either xbee or the wired one.&lt;br /&gt;&lt;br /&gt;the uartsb actually has 5 pins instead of 6 on the serial port.  RTS is not available.  RTS is however wired to DIO6, which is right next to DIO3.  when using the wired connection for uploading to a funnelio, the DTR can be connected to the RST pin and everything will work.  I tried all combinations of connecting DTR and RTS to DIO3 and DIO6 and configuring DIO6 and DIO3 as inputs on the sending side, and configuring the change detect on the receiving side to 8, 0x40, and 0xff.  but I could not get the arduino ide to reset the funnelio properly.  but!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;you can upload your arduino code without autoreset!&lt;/span&gt; you just have to make sure that the xbee is powered on, it is associated, encryption is disabled, you press the reset button by hand and you release it at a good time.  further, you have to setup DIO3 and change detect so that the default setting of DO HIGH does not hold your reset line high all the time.  or avoid closing the solder jumper.  the thing to watch out for is the tx and rx lights on the uartsb. when the leds first blink one after the other and then start blinking continuously you're doing good!&lt;br /&gt;&lt;br /&gt;I ended up not uploading wirelessly, instead I used the wired interface.  all you have to do is unplug the xbee everytime you upload because the funnelio has no switch to choose the serial interface and the xbee has priority over the wires.&lt;br /&gt;&lt;br /&gt;802.15.4 or zigbee does not support mesh networks.  in this context a mesh networks would be one that allowed multihop routing and self-healing properties.  instead there is a coordinator and end devices. my coordinator is the uartsb and the end devices are the sensors.&lt;br /&gt;&lt;br /&gt;I wanted to conserve power and to use encryption.  I went through a number of different combinations of who should wake up who and whether I wanted to buffer data before sending and so on.  it turns out that it is easier for the xbee to wakeup the arduino than the arduino to wakeup the xbee. especially with the way the funnelio's xbee socket is wired.  pin 9 is not connected to anything, and it's not trivial to jumper it to the pins of the at168.&lt;br /&gt;&lt;br /&gt;I use sleep mode 4, or cyclic sleep - the remote xbees periodically wake up, send a packet to the coordinator, and the coordinator either sends a buffered packet to them or tells them to go back to sleep.  after a period of inactivity the xbee goes back to sleep.  if a packet is received it is given to the arduino.  if the arduino was sleeping, the serial activity wakes it up.  the arduino can keep sending on the xbee as long as it doesn't allow the xbee to time out. in case of timeout, the connection is lost, and sent data is not buffered. with cyclic sleep the remotes also become hard to reprogram wirelessly as the xbee radio may be off or unassociated at the time the sender wishes to upload the program. with a short sleep timeout and a long sleep period reconfiguring the xbees with X-CTU also becomes difficult because the xbees will go to sleep and become unavailable.  eventually the only way to reprogram them is to unplug the uartsb, shutdown x-ctu, plugin uartsb, start x-ctu, and choose "always update firmware".&lt;br /&gt;&lt;br /&gt;The xbee uses 60mA  at 3.3v when it is active, 0mA when it sleeping, and the multimeter flashes to about 15mA for a split second when it checks for the packet.  the funnelio is an atmega168 running at 8mhz on 3.3v.  it uses 6ma when it is calling delay(1000) and 2.5mA when it is sleeping.  in this sleep mode wakeup is instantaneous.  the batteries I am using are 1000mAh or 1100mAh depending on who you believe.  sending a packet back and forth every minute, with timeout at 250ms and temperature measurement taking about 200ms, approximately 200mAseconds are consumed every minute giving an average consumption of 3mA.  the batteries should therefore last for about 2 weeks.  ofcourse it will take atleast two weeks to find out, unless the batteries run out earlier.&lt;br /&gt;&lt;br /&gt;the ds18b20 is a solid state non-thermistor temperature sensor.  it uses a proprietary protocol called 1-wire.  it has 3 wires, and requires "no external components".  that's excluding the 4.7kohm resistor which it requires.  the sensor seems to heat up faster than it cools down.  I don't know how that's possible.  the sensor returns the temperature as a two-byte fixed point reading.  it takes 750ms to "convert" the temperature to a 12-bit value, with 4 bits after the decimal point.  3 bits of resolution takes 375ms, 2 bits takes 187,5ms and so forth.  I am using the 2 bit resolution, so I get readings in quarter degrees celcius.  the accuracy of the sensor is +/- 0.5 degrees and the maximum resolution is 1/16th of a degree.  apparently the accuracy discrepancy is fixed over the measurement range, or atleast between consecutive measurements, so there is no noise in consecutive readings.  if the measurement changes 1/16th of a degree, the temperature really changed, but it might be between 25.0 and 25.0625 or 24.5 and 24.5625.  my four sensors produce results within one degree of each other if placed nearby on a table.   the &lt;a href="http://www.arduino.cc/playground/Learning/OneWire"&gt;onewire&lt;/a&gt; library for arduino doesn't live in &lt;a href="http://waffle.netlogistics.com.au/arduino/OneWire8.zip"&gt;version control&lt;/a&gt;, and there have been some bugs that have been fixed, but not in the official release.   unlike the other examples floating around I didn't use parasite power for the ds18b20.  measurement takes the same fixed time, but instead of calling delay(200), I call sensor.read() and wait for it to return something other than zero.&lt;br /&gt;&lt;br /&gt;the default mode for xbee is a delightful abstraction: there is no way to tell whether you are connected via radio or if you are at the end of a cable.  there are however two problems, and these are addressed by Digi's &lt;a href="http://www.digi.com/support/kbase/kbaseresultdetl.jsp?kb=184"&gt;API mode&lt;/a&gt;.  in cyclic sleep mode, broadcasting is not supported.  the coordinator has to address messages to each remote separately.  API mode allows this to be performed without entering command mode.  when receiving messages, the identity of the sender is unknown.  the data would have to be somehow tagged with the sender identity, and the data might further have to be tagged with some semantic information: for example high byte or low byte of temperature measurement.  doing both of these at byte level would require significant overhead.  entering command mode to change recipient addresses would also be difficult if there were concurrent incoming messages from remotes, and while in command mode some data might be lost.  API mode, whose use is easy enough with the &lt;a href="http://code.google.com/p/xbee-arduino/"&gt;xbee-arduino&lt;/a&gt; library, allows data to be grouped into packets which are delivered atomically and with the sender identity automatically present.&lt;br /&gt;&lt;br /&gt;I ended up having to set Mac mode to 1. The default mode of zero, which has ACKs and a Digi header got screwy when AES was enabled.  Messages would be delivered as double to the remotes, even though only one ACK would be received on the sender side, and worse, after a couple of messages the sender would somehow get clogged and unable to send any more messages or even to reset itself.&lt;br /&gt;&lt;br /&gt;I wrote the coordinator code in Ruby with the &lt;a href="http://ruby-serialport.rubyforge.org/"&gt;serialport&lt;/a&gt; gem.  on Linux and Windows usb-to-serial stuff works out of the box but on OSX a separate driver is required.  the driver is included in the arduino download for osx.  I send out a message to the remotes every minute or so, they respond with the current temperature and I write it out in json.  I rsync the JSON to a server and draw some graphs with HTML5's delightful &lt;a href="https://developer.mozilla.org/en/HTML/Canvas"&gt;canvas&lt;/a&gt; tag.&lt;br /&gt;&lt;br /&gt;updated: &lt;a href="http://github.com/miaubiz/snet/tree/master"&gt;the code&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/174903826897473842-635537664773663719?l=blog.miau.biz' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.miau.biz/feeds/635537664773663719/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=174903826897473842&amp;postID=635537664773663719' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/635537664773663719'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/635537664773663719'/><link rel='alternate' type='text/html' href='http://blog.miau.biz/2009/08/wireless-sensor-network.html' title='a wireless sensor network'/><author><name>Miaubiz</name><uri>http://www.blogger.com/profile/06950334298510471857</uri><email>miaubiz@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05794848006157778693'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-174903826897473842.post-4456082440555370072</id><published>2009-08-11T10:01:00.006+01:00</published><updated>2009-08-12T18:59:41.813+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='open source'/><category scheme='http://www.blogger.com/atom/ns#' term='arduino'/><category scheme='http://www.blogger.com/atom/ns#' term='hardware'/><category scheme='http://www.blogger.com/atom/ns#' term='microcontrollers'/><title type='text'>open source hardware</title><content type='html'>I completely slept on this.  besides software, hardware is also open source.  there are several iniatives.  I'll focus on &lt;a href="http://www.arduino.cc/"&gt;arduino&lt;/a&gt; and its derivatives, but that is by no means the only relevant one.&lt;br /&gt;&lt;br /&gt;Important for me personally is that &lt;span style="font-weight: bold;"&gt;you don't &lt;span style="font-style: italic;"&gt;need&lt;/span&gt; to solder&lt;/span&gt;.  you may end up soldering, as I did, and find that it can be easy and fun.  but it feels good to know that it's totally optional and when I do it, it's because I choose to do it.&lt;br /&gt;&lt;br /&gt;arduino is a combination of a microcontroller, which is a tiny computer that runs at 16mhz and has 32kb of ram on it, some standard pins for input and output, a usb-to-serial connector which both powers the device and allows communications with a computer and a development environment which provides high level abstractions for interfacing with devices: reading inputs from temperature sensors, controlling servos and leds.&lt;br /&gt;&lt;br /&gt;arduino is aimed at making everything easy and accessible and it works perfectly for that.  99% of the work is still accidental complexity, but otherwise it would be more like 99.999%.&lt;br /&gt;&lt;br /&gt;a cool product family for the non-soldery people is &lt;a href="http://www.seeedstudio.com/depot/electronic-brick-family-c-48.html"&gt;electronic bricks&lt;/a&gt; from seeedstudio.&lt;br /&gt;&lt;br /&gt;communication is often done via serial, aka rs-232.  although it is the same protocol as that 9-pin thing you used to connect your mouse to the computer before ps2 came along, these days rs-232 is physically in a usb cable, in 5 or 6 separate pins or even just a &lt;a href="http://en.wikipedia.org/wiki/Bit-banging"&gt;single&lt;/a&gt; physical pin.&lt;br /&gt;&lt;br /&gt;communication speeds are typically around 19200 or 57600 bps.  compared to usb2.0's 400mbps and pci-express' 10gbps this is low.  low enough to rule out many applications, especially around video or high resolution imaging.  but it's fast enough for applications such as lcds, gps, accelerometers, temperature, color sensors, motors, servos.   encoding video, audio or images within the constraints of bandwidth, power and processing requires specialized circuitry or an fpga.&lt;br /&gt;--&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/174903826897473842-4456082440555370072?l=blog.miau.biz' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.miau.biz/feeds/4456082440555370072/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=174903826897473842&amp;postID=4456082440555370072' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/4456082440555370072'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/4456082440555370072'/><link rel='alternate' type='text/html' href='http://blog.miau.biz/2009/08/open-source-hardware.html' title='open source hardware'/><author><name>Miaubiz</name><uri>http://www.blogger.com/profile/06950334298510471857</uri><email>miaubiz@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05794848006157778693'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-174903826897473842.post-4325023723380088353</id><published>2009-07-16T19:33:00.006+01:00</published><updated>2009-11-05T12:45:06.069Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='caching'/><category scheme='http://www.blogger.com/atom/ns#' term='wicket'/><category scheme='http://www.blogger.com/atom/ns#' term='building'/><category scheme='http://www.blogger.com/atom/ns#' term='junit'/><title type='text'>profilin'</title><content type='html'>wicket's Application has Settings which has a PropertiesFactory which has a &lt;a href="http://java.sun.com/javase/6/docs/api/java/util/Map.html"&gt;Map&lt;/a&gt; which maps paths to the corresponding &lt;a href="http://wicket.apache.org/docs/1.4/org/apache/wicket/resource/Properties.html"&gt;Properties&lt;/a&gt;.  non-existing Properties, which is most of them, are identified with a marker object, so they don't have to be constantly rechecked.  Application is a ThreadLocal so it has a semi singletonish global state kind of flavor to it.  Most properties don't exist because Wicket by default looks in a lot of places for a component's localization data: by language and country, in properties and xml files, in parent components.&lt;br /&gt;&lt;br /&gt;The caching works great in production.  In unit tests Application is constantly re-initialized and the cache is flushed all the time.  Changing the properties cache to static makes our test suite run twice as fast overall.  From 25 minutes to 12 and a half.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;update:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;here's the code:&lt;br /&gt;&lt;br /&gt;public class MyDummyWebApplication extends BaseWicketTester.DummyWebApplication {&lt;br /&gt;   private static final Map&lt;string,&gt; propertiesCache = new ConcurrentHashMap&lt;string,&gt;();&lt;br /&gt;&lt;br /&gt;   @Override&lt;br /&gt;   protected void init() {&lt;br /&gt;       optimizePropertyLoading();&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private void optimizePropertyLoading() {&lt;br /&gt;       PropertiesFactory propertiesFactory = (PropertiesFactory) getResourceSettings().getPropertiesFactory();&lt;br /&gt;       propertiesFactory.getPropertiesLoaders().remove(1);&lt;br /&gt;       Inject.field("propertiesCache").of(propertiesFactory).with(propertiesCache);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;--&lt;/string,&gt;&lt;/string,&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/174903826897473842-4325023723380088353?l=blog.miau.biz' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.miau.biz/feeds/4325023723380088353/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=174903826897473842&amp;postID=4325023723380088353' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/4325023723380088353'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/4325023723380088353'/><link rel='alternate' type='text/html' href='http://blog.miau.biz/2009/07/profilin.html' title='profilin&apos;'/><author><name>Miaubiz</name><uri>http://www.blogger.com/profile/06950334298510471857</uri><email>miaubiz@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05794848006157778693'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-174903826897473842.post-219375035639018385</id><published>2009-07-15T09:22:00.007+01:00</published><updated>2009-07-15T09:41:06.297+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='FastForward'/><category scheme='http://www.blogger.com/atom/ns#' term='actors'/><category scheme='http://www.blogger.com/atom/ns#' term='queue'/><category scheme='http://www.blogger.com/atom/ns#' term='cache'/><category scheme='http://www.blogger.com/atom/ns#' term='concurrency'/><title type='text'>a fast queue</title><content type='html'>threads aren't the most natural way to think about concurrency.  actor implementations are free to map between actors and threads, but with X cores, it helps to have atleast X-1 threads used by the actors.&lt;br /&gt;&lt;br /&gt;the threads need to pass data to the next thread in the chain.  this can be slow with memory barriers, blocking, cache trashing.  a single thread must do a large amount of work to offset the overhead.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.cs.colorado.edu/department/publications/reports/docs/CU-CS-1023-07.pdf"&gt;FastForward&lt;/a&gt; is a &lt;a href="http://ce.colorado.edu/Publications/ppopp08_ff.pdf"&gt;sweet&lt;/a&gt; queue that solves exactly this problem.  blocking queue + dequeue operations required by each thread can be performed in 30ns on a 2.66ghz opteron.  that comes out to roughly 80 cycles.  in the example, one pointer's worth of data is passed between the cores.  other data can also be passed along, and that data may also qualify for prefetching on the receiving core.&lt;br /&gt;--&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/174903826897473842-219375035639018385?l=blog.miau.biz' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.miau.biz/feeds/219375035639018385/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=174903826897473842&amp;postID=219375035639018385' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/219375035639018385'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/219375035639018385'/><link rel='alternate' type='text/html' href='http://blog.miau.biz/2009/07/fast-queue.html' title='a fast queue'/><author><name>Miaubiz</name><uri>http://www.blogger.com/profile/06950334298510471857</uri><email>miaubiz@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05794848006157778693'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-174903826897473842.post-5524161676670166654</id><published>2009-06-07T09:24:00.004+01:00</published><updated>2009-06-07T18:38:44.387+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='stm'/><category scheme='http://www.blogger.com/atom/ns#' term='transactional memory'/><category scheme='http://www.blogger.com/atom/ns#' term='htm'/><title type='text'>transactional memory</title><content type='html'>concurrent programming with shared memory is complicated.  if there was a way to make such programming easy, shared memory could remain an alternative to message passing in the presence of large amounts of thin cores.&lt;br /&gt;&lt;br /&gt;transactional memory aims to automate the selection and acquisition of locks.  whether transactional memory can be done efficiently, and adopted incrementally is still uncertain.&lt;br /&gt;&lt;br /&gt;there are both software and hardware implementations of transactional memory.  at first they seemed to me sequential evolutionary steps but that is not the case.  Most HTM implementations operate at cache line granularity and use cache coherence protocols to track and maintain different copies of shared memory areas.  most STMs operate at object level and use locks, temporary copies of objects, and additional data structures to keep track of transactions and mutated state.  the fundamental problem of HTM is transactions that exceed cache sizes or that last longer than one scheduling quantum.  the fundamental problem of STM is overhead. it seems natural to expect a balanced hybrid to offer the best of both worlds.&lt;br /&gt;&lt;br /&gt;transactional memory implementations differ in certain key attributes.  the choices often depend on whether commits or aborts are expected to be more frequent.&lt;br /&gt;&lt;br /&gt;shared state can be modified in place or on a separate copy.  in place modification requires a second copy to be created to maintain the original state in case of an abort.  in place modification makes commits cheap.&lt;br /&gt;&lt;br /&gt;concurrency can be handled optimistically - several threads can enter the same critical section concurrently.  if the threads do not conflict the locking would have been overhead. if a conflict is detected all but one thread are aborted.&lt;br /&gt;&lt;br /&gt;conflicts can be detected as soon as they occur or only at commit time.  late detection saves overhead in the absense of contention.  early detection involves more bookkeeping work, but when a conflict occurs it skips the useless computation in the doomed portion of the transaction.  late detection can also allow computation on inconsistent state. th results will eventually be discarded but it can result in exceptions that wouldn't occur otherwise.&lt;br /&gt;&lt;br /&gt;the semantics of nested transactions can be defined in two ways&lt;br /&gt;for aborts:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;a nested transaction aborts the parent transaction.&lt;/li&gt;&lt;li&gt;a nested transaction allows the parent to proceed.&lt;/li&gt;&lt;/ul&gt;and for commits:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;changes committed in a nested transaction become visible to the parent transaction.&lt;/li&gt;&lt;li&gt;changes committed in a nested transaction become visible in global state.&lt;/li&gt;&lt;/ul&gt;IO and cooperation between transactional and non-transactional software are some of the challenges for the future.  The classic chicken-and-egg problem is naturally a key blocker.  Intel has a lot of eggs in this basket if they expect anyone to buy 1000 core chips.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/174903826897473842-5524161676670166654?l=blog.miau.biz' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.miau.biz/feeds/5524161676670166654/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=174903826897473842&amp;postID=5524161676670166654' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/5524161676670166654'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/5524161676670166654'/><link rel='alternate' type='text/html' href='http://blog.miau.biz/2009/06/transactional-memory.html' title='transactional memory'/><author><name>Miaubiz</name><uri>http://www.blogger.com/profile/06950334298510471857</uri><email>miaubiz@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05794848006157778693'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-174903826897473842.post-4905023501082777655</id><published>2009-05-23T10:08:00.004+01:00</published><updated>2009-05-23T10:52:49.189+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='management'/><category scheme='http://www.blogger.com/atom/ns#' term='pants'/><category scheme='http://www.blogger.com/atom/ns#' term='anger'/><title type='text'>yeah</title><content type='html'>I bought a pair of pants.  Six days later I notice the stitching has come apart.  No need for vexation.  I go to the store, I show the pants and the receipt to the nice guy behind the counter.  He calls the manager just to be sure.  The manager decides to come over and look at the pants.&lt;br /&gt;&lt;br /&gt;The manager then says the pants are fine, the hole is probably of my own doing, but she's not saying it is, she's merely examining the threading.  In the end she tells the cashiers to refund me and she leaves.  I get my refund.  When the cashier ends with "I'm sorry about your pants, they really should last more than six days," I realize that I'm not mad at the cashiers, I'm mad at the manager.&lt;br /&gt;&lt;br /&gt;Flip the tables.  &lt;span style="font-style: italic;"&gt;You're the cashier.&lt;/span&gt;  A calm customer comes in for a routine refund of a defective good. Suddenly, your boss butts in, she tells the customer to fuck off, she orders you to finish the transaction, and she retreats to the office.&lt;br /&gt;&lt;br /&gt;-&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/174903826897473842-4905023501082777655?l=blog.miau.biz' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.miau.biz/feeds/4905023501082777655/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=174903826897473842&amp;postID=4905023501082777655' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/4905023501082777655'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/4905023501082777655'/><link rel='alternate' type='text/html' href='http://blog.miau.biz/2009/05/yeah.html' title='yeah'/><author><name>Miaubiz</name><uri>http://www.blogger.com/profile/06950334298510471857</uri><email>miaubiz@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05794848006157778693'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-174903826897473842.post-1387769271301582404</id><published>2009-05-21T14:58:00.005+01:00</published><updated>2009-05-22T07:18:09.239+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='speculation'/><category scheme='http://www.blogger.com/atom/ns#' term='clarksdale'/><category scheme='http://www.blogger.com/atom/ns#' term='nehalem'/><title type='text'>clarksfield turbo</title><content type='html'>though clarksfield chips are reported to be clocked at measly 1.6, 1.8, and 2.0ghz, nehalem's turbo boosts them up to &lt;a href="http://xtreview.com/addcomment-id-8880-view-Clarksfield-processors-characteristics.html"&gt;3,2ghz&lt;/a&gt; for a lone running thread.&lt;br /&gt;&lt;br /&gt;the current top of the line mobile &lt;a href="http://en.wikipedia.org/wiki/Intel_Core_%28microarchitecture%29#Laptops_2"&gt;core2&lt;/a&gt; chips x9100 and qx9300 are dualcore @ 3,06ghz and quad core @ 2,53ghz, both with 1066mhz fsb.  clarksfield uses dual channel 1333mhz memory, and has DMI instead of the desktop variant's QPI.&lt;br /&gt;&lt;br /&gt;conclusion: a 2ghz clarksfield will beat an x9100 in &lt;a href="http://en.wikipedia.org/wiki/File:AmdahlsLaw.svg"&gt;single-thread&lt;/a&gt; performance, and a qx9300 in parallel performance.  clarksfieldy macbook pros should be out right around the time my summer vacation ends.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/174903826897473842-1387769271301582404?l=blog.miau.biz' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.miau.biz/feeds/1387769271301582404/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=174903826897473842&amp;postID=1387769271301582404' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/1387769271301582404'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/1387769271301582404'/><link rel='alternate' type='text/html' href='http://blog.miau.biz/2009/05/clarksfield-turbo.html' title='clarksfield turbo'/><author><name>Miaubiz</name><uri>http://www.blogger.com/profile/06950334298510471857</uri><email>miaubiz@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05794848006157778693'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-174903826897473842.post-8598537712212083467</id><published>2009-05-21T13:57:00.003+01:00</published><updated>2009-05-21T14:41:57.348+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cryptography'/><category scheme='http://www.blogger.com/atom/ns#' term='germany'/><category scheme='http://www.blogger.com/atom/ns#' term='des'/><title type='text'>how bad is DES?</title><content type='html'>DES was kicked out of srs bsns over a decade ago, yet there are no bruteforce des crackers available for home PCs.   DES encryption/decryption is not well suited for the instruction set of a general purpose computer.  in 1999 distributed.net harnessed the idle cpu time of around &lt;a href="http://n0cgi.distributed.net/statistics/des3/"&gt;100.000&lt;/a&gt; computers together with EFF's deep crack to &lt;a href="http://www.distributed.net/des/release-desiii.txt"&gt;break&lt;/a&gt; des within 24 hours.  the peak of 170 billion decryptions every second on 100.000 computers averages out to 1,7 million decryptions per second per computer.&lt;br /&gt;&lt;br /&gt;for computers 10 times as fast now as those of 1999,  a large amount of botnet time would be consumed in cracking just a single key.  the current &lt;a href="http://www.cs.virginia.edu/%7Eskadron/Papers/che_sasp08.pdf"&gt;GPGPU&lt;/a&gt;s aren't particularly well suited for DES cracking either.  a single decryption takes a lot of cycles and a lot of power. &lt;br /&gt;&lt;br /&gt;FPGAs are &lt;a href="http://www.dice.ucl.ac.be/%7Efstandae/PUBLIS/13.pdf"&gt;optimal&lt;/a&gt; for DES.  the described implementation is a 37 stage pipeline composed of single cycle steps that changes keys, plaintext, ciphertext and operation mode on every cycle without stalls.&lt;br /&gt;&lt;br /&gt;in 2006, &lt;a href="http://www.hyperelliptic.org/tanja/SHARCS/talks06/copacobana.pdf"&gt;german researchers&lt;/a&gt; implemented a 9000 euro &lt;a href="http://www.copacobana.org/"&gt;device&lt;/a&gt; with a total power consumption of 600 watts consisting of 120 FPGAs, each capable of 400 million encryptions per second.  they eventually raised the clock speed so that an exhaustive search of the DES keyspace takes 12.8 days.  DES is futher susceptible to &lt;a href="http://www.hyperelliptic.org/tanja/SHARCS/talks/JJQ_FXS.pdf"&gt;time/memory tradeoff&lt;/a&gt; attacks which copacabana &lt;a href="http://www.copacobana.org/paper/TC_COPACOBANA.pdf"&gt;performs&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;-&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/174903826897473842-8598537712212083467?l=blog.miau.biz' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.miau.biz/feeds/8598537712212083467/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=174903826897473842&amp;postID=8598537712212083467' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/8598537712212083467'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/8598537712212083467'/><link rel='alternate' type='text/html' href='http://blog.miau.biz/2009/05/how-bad-is-des.html' title='how bad is DES?'/><author><name>Miaubiz</name><uri>http://www.blogger.com/profile/06950334298510471857</uri><email>miaubiz@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05794848006157778693'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-174903826897473842.post-5618224359388188324</id><published>2009-05-19T09:17:00.007+01:00</published><updated>2009-05-19T15:23:24.622+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='csrf'/><category scheme='http://www.blogger.com/atom/ns#' term='wicket'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><title type='text'>how wicket protects you from CSRF</title><content type='html'>the beauty of wicket finally became apparent to me when I wrote my first delete operation.&lt;br /&gt;&lt;br /&gt;the traditional delete works like this:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;miau.biz/delete.php?id=5&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;instead, wicket sets up a bounded number of continuations that the user can invoke.  each continuation corresponds to one of the allowed deletions.  if an item isn't allowed to be deleted, that continuation does not exist, and neither does there exist a way to invoke it.&lt;br /&gt;&lt;br /&gt;an attacker can however induce a victim to invoke any existing continuation against their will.&lt;br /&gt;&lt;br /&gt;say the url to delete id 5 is:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;miau.biz/::wicket::invokeContinuation:2&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;putting that url in an img tag will make the browser load it automatically.  oops.&lt;br /&gt;&lt;br /&gt;the suggested &lt;a href="http://www.owasp.org/index.php/Testing_for_CSRF_%28OWASP-SM-005%29#How_to_Review_Code_for_CSRF_Vulnerabilities"&gt;solution&lt;/a&gt; is to include a hard to guess token with each link, and requiring separate login for dangerous operations.&lt;br /&gt;&lt;br /&gt;wicket uses null as the name of the default PageMap, and sequential numbering for page id's, page versions and markup id's.&lt;br /&gt;&lt;br /&gt;wicket has a builtin &lt;a href="http://issues.apache.org/jira/browse/WICKET-1782"&gt;fix&lt;/a&gt; against csrf.  you aren't forced to use their solution however.  in fact nextPageId() in Session is protected and not final; I can override that with&lt;br /&gt;&lt;br /&gt;private static SecureRandom random = new SecureRandom();&lt;br /&gt;&lt;code&gt;&lt;br /&gt;synchronized protected int nextPageId() {&lt;br /&gt;  return random.nextInt(Integer.MAX_VALUE);&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;not every request gets a unique id, but many requests do.  and the whole thing is fairly transparent.&lt;br /&gt;&lt;br /&gt;Wicket's CryptedUrlWebRequestCodingStrategy has a fallback mechanism to allow you to also use urls that aren't gibberish:&lt;br /&gt;&lt;pre&gt;   public RequestParameters decode(final Request request)&lt;br /&gt;  {&lt;br /&gt;      String url = request.decodeURL(request.getURL());&lt;br /&gt;      String decodedQueryParams = decodeURL(url);&lt;br /&gt;      if (decodedQueryParams != null)&lt;br /&gt;      {&lt;br /&gt;          // The difficulty now is that this.defaultStrategy.decode(request)&lt;br /&gt;          // doesn't know the just decoded url which is why must create&lt;br /&gt;          // a fake Request for.&lt;br /&gt;          Request fakeRequest = new DecodedUrlRequest(request, url, decodedQueryParams);&lt;br /&gt;          return defaultStrategy.decode(fakeRequest);&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      return defaultStrategy.decode(request);&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;*cough*&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/174903826897473842-5618224359388188324?l=blog.miau.biz' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.miau.biz/feeds/5618224359388188324/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=174903826897473842&amp;postID=5618224359388188324' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/5618224359388188324'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/5618224359388188324'/><link rel='alternate' type='text/html' href='http://blog.miau.biz/2009/05/how-wicket-protects-you-from-csrf.html' title='how wicket protects you from CSRF'/><author><name>Miaubiz</name><uri>http://www.blogger.com/profile/06950334298510471857</uri><email>miaubiz@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05794848006157778693'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-174903826897473842.post-7913004754217940787</id><published>2009-05-17T09:17:00.003+01:00</published><updated>2009-05-17T10:02:13.901+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='classpath'/><category scheme='http://www.blogger.com/atom/ns#' term='pde'/><category scheme='http://www.blogger.com/atom/ns#' term='plugin'/><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='undo'/><category scheme='http://www.blogger.com/atom/ns#' term='building'/><title type='text'>eclipse containers for fun and profit</title><content type='html'>&lt;span style="font-style: italic;"&gt;given&lt;/span&gt; a multi module project in eclipse, where project X depends on project Y,&lt;br /&gt;&lt;span style="font-style: italic;"&gt;when&lt;/span&gt; I close project Y,&lt;br /&gt;&lt;span style="font-style: italic;"&gt;I want&lt;/span&gt; project X to depend on a jar of project Y.&lt;br /&gt;&lt;br /&gt;eclipse classpath containers are a mechanism for &lt;a href="http://en.wikipedia.org/wiki/Law_enforcement_jargon"&gt;dynamic late binding&lt;/a&gt; of classpath elements.&lt;br /&gt;&lt;br /&gt;ibm has a &lt;a href="http://www.ibm.com/developerworks/edu/os-dw-os-eclipse-classpath.html"&gt;tutorial&lt;/a&gt; that requires you to register on their site.  &lt;a href="http://stackoverflow.com/questions/27818/how-can-i-manage-osgi-build-dependencies/45786#45786"&gt;m2eclipse&lt;/a&gt; does the whole thing for maven projects, but also 99 other things, most of which involve running random maven tasks when your trying to write code.&lt;br /&gt;&lt;br /&gt;despite all the static methods and integers enumerations, eclipse makes the whole thing easy; including creating your own plugin and publishing an update-site for it.&lt;br /&gt;&lt;br /&gt;the heart of the class path container is the is the &lt;a href="http://help.eclipse.org/ganymede/topic/org.eclipse.jdt.doc.isv/reference/api/org/eclipse/jdt/core/IClasspathContainer.html"&gt;IClasspathContainer&lt;/a&gt;.  The getClasspathEntries() method returns whatever is relevant for that situation.  in my case it's either a JavaCore.newProjectEntry() or a JavaCore.newLibraryEntry() depending on whether the referenced project is open or closed at the time.  For some reason JavaCore.newVariableEntry() comes out as K_SOURCE which doesn't work for a jar.  so I use wrapped the resolved path from newVariableEntry() into a newLibraryEntry to make it a K_BINARY.  your type is K_APPLICATION, your path is your unique identifier, and stuff after the slash in the path is parameters for your container.  in my case the parameters might be the other projects that this project depends on.&lt;br /&gt;&lt;br /&gt;then you need a &lt;a href="http://help.eclipse.org/ganymede/topic/org.eclipse.jdt.doc.isv/reference/api/org/eclipse/jdt/core/ClasspathContainerInitializer.html"&gt;ClasspathContainerInitializer&lt;/a&gt;, which will call JavaCore.setClasspathContainer with a new instance of YourContainer on the dependent projects everytime you open or close one the dependee projects.   this then sends an &lt;a href="http://mobius.inria.fr/eclipse-doc/org/eclipse/jdt/core/IJavaElementDelta.html"&gt;F_CLASSPATH_CHANGED&lt;/a&gt; signal to those concerned.&lt;br /&gt;&lt;br /&gt;you'll know that a project was opened or closed, because you added an &lt;a href="http://help.eclipse.org/ganymede/topic/org.eclipse.jdt.doc.isv/reference/api/org/eclipse/jdt/core/IElementChangedListener.html"&gt;IElementChangedListener &lt;/a&gt;with JavaCore.addElementChangedListener().&lt;br /&gt;&lt;br /&gt;Your initializer is registered by adding it at the extension point &lt;a href="http://help.eclipse.org/ganymede/topic/org.eclipse.jdt.doc.isv/reference/extension-points/org_eclipse_jdt_core_classpathContainerInitializer.html"&gt;org.eclipse.jdt.core.classpathContainerInitializer&lt;/a&gt;.  never mind the xml, eclipse will generate it for you.&lt;br /&gt;&lt;br /&gt;to allow the addition of containers from the build path configuration menu, eclipse requires a classpathContainerPage.  either create a dummy one and register it, or add your container to the classpath file by hand.&lt;br /&gt;&lt;br /&gt;Finally, I exported my plugin, and then binary imported the same.  This is a nonrecoverable operation that replaces the source code of the plugin with the class files.&lt;br /&gt;*cough*&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/174903826897473842-7913004754217940787?l=blog.miau.biz' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.miau.biz/feeds/7913004754217940787/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=174903826897473842&amp;postID=7913004754217940787' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/7913004754217940787'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/7913004754217940787'/><link rel='alternate' type='text/html' href='http://blog.miau.biz/2009/05/eclipse-containers-for-fun-and-profit.html' title='eclipse containers for fun and profit'/><author><name>Miaubiz</name><uri>http://www.blogger.com/profile/06950334298510471857</uri><email>miaubiz@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05794848006157778693'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-174903826897473842.post-3204651006638208394</id><published>2009-05-10T20:03:00.004+01:00</published><updated>2009-05-10T21:13:25.557+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='libnotify'/><category scheme='http://www.blogger.com/atom/ns#' term='money'/><category scheme='http://www.blogger.com/atom/ns#' term='ssd'/><category scheme='http://www.blogger.com/atom/ns#' term='building'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>throwing money at it</title><content type='html'>sometime in &lt;a href="http://kirk.blog-city.com/java_on_apple_catching_up.htm"&gt;the future&lt;/a&gt; apple will get past the awful &lt;span style="font-size:85%;"&gt;1.6.0_07&lt;/span&gt;.  meanwhile &lt;a href="http://www.joelonsoftware.com/items/2009/03/27.html"&gt;joel on software&lt;/a&gt;, did a wonderful piece on using money/&lt;a href="http://kirk.blog-city.com/can_ssd_deliver_on_its_promises.htm"&gt;ssd drives&lt;/a&gt; to speed up their build.  I wasn't able to test this myself so I am glad joel did it for me, and confirmed my expectations that compiling/testing is cpu/memory bandwidth bound rather than io bound.  our whole build takes up around 200 megabytes of physical space with all its dependencies and the jdk takes another 200 megs.  further, a good part of both chunks is probably never loaded.  so with enough memory there would be virtually no need for disk io.&lt;br /&gt;&lt;br /&gt;what would be interesting beyond this would be to figure out if ssd could help in the overall workloads we use, that is (again): reading email, im'ing, running virtualbox, using an IDE, building, using the browser, profiling, running jetty.  all at once.  and that could hard to measure unless the difference was so great it would be obvious in actual use.&lt;br /&gt;&lt;br /&gt;then I had the chance to work on a &lt;span style="font-style: italic;"&gt;brand new&lt;/span&gt; windows box with a t5500 &lt;span style="font-size:78%;"&gt;(a 1,66ghz core2duo)&lt;/span&gt;, 2gigs of ram, and corporate antivirus software set to scan all class files, and read michael feather's excellent book &lt;a href="http://www.informit.com/store/product.aspx?isbn=0131177052"&gt;working effectively with legacy code&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;by the time I highlighted a block of code in eclipse, held down alt and hit the up arrow and nothing happened. 5 seconds elapsed, there was screech from the harddrive for a few seconds and then my method moved up a few lines. I was just smiling from the absurdity.&lt;br /&gt;&lt;br /&gt;michael feathers points out the importance of having a fast feedback cycle and his book also alleviated my fears that, while i am waiting for the computer to do something it's natural for my mind to wander off and get frustrated, rather than spending that time subconciously processing the customer's business logic.  I've actually found myself trying to optimize my day so that when I have to go to the bathroom, I'll hold out a bit so I can start a build, or get an update from version control before I go.  then I realized I was &lt;span style="font-weight: bold;"&gt;way&lt;/span&gt; off putting any mental effort into this.&lt;br /&gt;&lt;br /&gt;we now have some good steam going into getting our sprawling build back under control.  the experience so far has reminded me of the importance of communication.  I just can't guess what others are thinking from just looking at them and watching them act.  I really need to make the effort to conciously communicate with people in the same room, the next room, and farther away to find out.  and it is often very enlighting to do so.&lt;br /&gt;&lt;br /&gt;as an example, it turns out part of the frustration of the slow build was of my own doing.  the whole issue could be circumvented not by cleaning up the build, getting faster hardware, optimizing our continuous integration environment, switching to a more branch friendly version control system, but by the simplest solution of all.  it all goes away if you just stop running the build.&lt;br /&gt;&lt;br /&gt;I also started using a remote git repository on my own server to move scripts around between home and work.  I'm expecting it to be even better than posting stuff on my blog and copypasting it at work.&lt;br /&gt;&lt;br /&gt;for those on jaunty, who do run the build:&lt;br /&gt;&lt;pre class="brush: bash"&gt;#!/bin/bash&lt;br /&gt;function notify {&lt;br /&gt; test -x "`which notify-send`" &amp;amp;&amp;amp; `which notify-send` -u $1 -c $2 -i $3 "$4" "$5"&lt;br /&gt;}&lt;br /&gt;/usr/bin/time -f "%E real" -o ./time.txt buildr $@&lt;br /&gt;if [ $? -eq 0 ]&lt;br /&gt;then&lt;br /&gt; notify normal transfer.complete sunny "successful build" "`cat time.txt`"&lt;br /&gt;else&lt;br /&gt; notify critical transfer.error error  "failed build" "`tail -1 time.txt`"&lt;br /&gt;fi&lt;br /&gt;rm ./time.txt&lt;br /&gt;&lt;/pre&gt;and this too, because it uses the totally sweet erlang icon in the notifications!&lt;br /&gt;&lt;pre class="brush: plain"&gt;       case regexp:match(ServerName, "compute.amazonaws.com") of&lt;br /&gt;               nomatch -&gt; ets:delete(instances, Nick),&lt;br /&gt;                       os:cmd("/usr/bin/notify-send -i erlang -c device.error -u normal 'joe experienced an error'"),&lt;br /&gt;                       bot:irc_privmsg(Socket, Nick, "some kind of error occurred.");&lt;br /&gt;&lt;/pre&gt;enjoy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/174903826897473842-3204651006638208394?l=blog.miau.biz' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.miau.biz/feeds/3204651006638208394/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=174903826897473842&amp;postID=3204651006638208394' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/3204651006638208394'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/3204651006638208394'/><link rel='alternate' type='text/html' href='http://blog.miau.biz/2009/05/throwing-money-at-it.html' title='throwing money at it'/><author><name>Miaubiz</name><uri>http://www.blogger.com/profile/06950334298510471857</uri><email>miaubiz@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05794848006157778693'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-174903826897473842.post-8876589363006741196</id><published>2009-05-08T19:52:00.000+01:00</published><updated>2009-05-08T19:54:54.640+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='findbugs'/><category scheme='http://www.blogger.com/atom/ns#' term='static analysis'/><category scheme='http://www.blogger.com/atom/ns#' term='buildr'/><title type='text'>static analysis</title><content type='html'>&lt;pre class="brush: ruby"&gt;&lt;br /&gt;module FindBugs&lt;br /&gt;  include Extension&lt;br /&gt;&lt;br /&gt;  first_time do&lt;br /&gt;    desc 'run findbugs on your project'&lt;br /&gt;    Project.local_task('findbugs')&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  before_define do |project|&lt;br /&gt;    project.recursive_task 'findbugs'&lt;br /&gt;    Rake::Task.define_task 'findbugs' do |task|&lt;br /&gt;      fail "you must set FINDBUGS_HOME" unless ENV['FINDBUGS_HOME']&lt;br /&gt;      findbugs_home=ENV['FINDBUGS_HOME']&lt;br /&gt;      Buildr.ant 'findbugs' do |ant|&lt;br /&gt;        ant.taskdef :name=&gt;'findbugs', :classname=&gt;'edu.umd.cs.findbugs.anttask.FindBugsTask', :classpath=&gt;File.join(findbugs_home, "findbugs-ant.jar")&lt;br /&gt;        ant.findbugs :home=&gt;findbugs_home, :outputFile=&gt;project.path_to(:target, "findbugs.xml") do&lt;br /&gt;          ant._class(:location =&gt; project.path_to(:target))&lt;br /&gt;          ant.sourcePath(:location =&gt; project.path_to(:source, :main, :java))&lt;br /&gt;          ant.sourcePath(:location =&gt; project.path_to(:source, :test, :java))&lt;br /&gt;          project.test.dependencies.each do |dependency|&lt;br /&gt;            ant.auxClasspath(:location =&gt; dependency)&lt;br /&gt;          end&lt;br /&gt;        end&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  after_define do |project|&lt;br /&gt;    findbugs = task('findbugs'=&gt; project.test.compile)&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class Buildr::Project&lt;br /&gt;  include FindBugs&lt;br /&gt;end&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/174903826897473842-8876589363006741196?l=blog.miau.biz' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.miau.biz/feeds/8876589363006741196/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=174903826897473842&amp;postID=8876589363006741196' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/8876589363006741196'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/8876589363006741196'/><link rel='alternate' type='text/html' href='http://blog.miau.biz/2009/05/static-analysis.html' title='static analysis'/><author><name>Miaubiz</name><uri>http://www.blogger.com/profile/06950334298510471857</uri><email>miaubiz@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05794848006157778693'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-174903826897473842.post-7196684707026533590</id><published>2009-05-06T17:11:00.003+01:00</published><updated>2009-05-06T17:17:06.114+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='tsocks'/><category scheme='http://www.blogger.com/atom/ns#' term='ipv6'/><category scheme='http://www.blogger.com/atom/ns#' term='ec2'/><category scheme='http://www.blogger.com/atom/ns#' term='buildr'/><title type='text'>bugs</title><content type='html'>so I really kicked myself in the nuts with that TMPDIR stuff.&lt;br /&gt;&lt;br /&gt;since I have my m2 repository on the EBS volume, I should really have $TMPDIR on the volume too, instead of in my home directory.  and the AMI I was using is geared towards &lt;a href="http://java.sun.com/j2se/1.5.0/docs/guide/net/ipv6_guide/index.html"&gt;IPv6.&lt;/a&gt;  and my version of tsocks doesn't play too well with that so.  add &lt;code&gt;-Djava.net.preferIPv4Stack=true&lt;/code&gt; to java options to get back within the realm of transparent proxying.&lt;br /&gt;&lt;br /&gt;I sure am glad I can delete all those broken ebs volumes now.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/174903826897473842-7196684707026533590?l=blog.miau.biz' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.miau.biz/feeds/7196684707026533590/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=174903826897473842&amp;postID=7196684707026533590' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/7196684707026533590'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/7196684707026533590'/><link rel='alternate' type='text/html' href='http://blog.miau.biz/2009/05/bugs.html' title='bugs'/><author><name>Miaubiz</name><uri>http://www.blogger.com/profile/06950334298510471857</uri><email>miaubiz@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05794848006157778693'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-174903826897473842.post-777980635206706397</id><published>2009-05-04T06:57:00.006+01:00</published><updated>2009-05-04T10:05:43.175+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='parallelism'/><category scheme='http://www.blogger.com/atom/ns#' term='ec2'/><category scheme='http://www.blogger.com/atom/ns#' term='shell'/><category scheme='http://www.blogger.com/atom/ns#' term='buildr'/><title type='text'>the missing pieces of the puzzle</title><content type='html'>here's the rest.  btw, controlling the ebs volumes as shown in the previous post has the added benefit of making changes simple when problems/fixes are discovered.&lt;br /&gt;&lt;br /&gt;here's stop.sh which maps an amazon host to an instanceid.&lt;br /&gt;&lt;pre class="brush:plain;"&gt;#!/bin/bash&lt;br /&gt;set -e&lt;br /&gt;echo "stopping $1" &gt;&gt; log.txt&lt;br /&gt;ec2-describe-instances | grep $1 | cut -f 2 | ec2-terminate-instances - &gt;&gt; log.txt&lt;br /&gt;echo "completed"&lt;br /&gt;&lt;/pre&gt;here's the user end script:&lt;br /&gt;&lt;pre class="brush:bash"&gt;#!/bin/sh&lt;br /&gt;if [ ! -e "./buildfile" ]&lt;br /&gt;then&lt;br /&gt;echo "no buildfile in this directory"&lt;br /&gt;exit 1&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;if [ -z "$EC2_HOST" ]&lt;br /&gt;then&lt;br /&gt;echo "set the EC2_HOST environment variable lol"&lt;br /&gt;exit 2&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;chmod 600 keys/id_dsa_ec2_buildr&lt;br /&gt;export EC2_HOST_AND_USER="buildr@$EC2_HOST"&lt;br /&gt;export SSH_COMMAND="ssh -i keys/id_dsa_ec2_buildr"&lt;br /&gt;echo "syncing"&lt;br /&gt;rsync -rt -e "$SSH_COMMAND" --delete-excluded --exclude target --exclude .svn --exclude bin --exclude "/*/reports" . $EC2_HOST_AND_USER:teh-build&lt;br /&gt;echo "'n sync.  building"&lt;br /&gt;$SSH_COMMAND -R 10022:a_host_on_your_network:22 $EC2_HOST_AND_USER ./build.sh $@ &amp;amp;&amp;amp; echo "build successful"&lt;br /&gt;rsync -rt -e "$SSH_COMMAND" $EC2_HOST_AND_USER:teh-build/reports .&lt;br /&gt;echo "the end"&lt;br /&gt;&lt;/pre&gt;this is setup.sh on the ebs volume:&lt;br /&gt;&lt;pre class="brush:plain;"&gt;#!/bin/bash&lt;br /&gt;useradd -m buildr&lt;br /&gt;dpkg -i /mnt/super/debs/* &gt; /dev/null&lt;br /&gt;rsync -rt /mnt/super/buildr_home/ /home/buildr&lt;br /&gt;chown -R buildr /home/buildr&lt;br /&gt;chmod 700 /home/buildr/.ssh&lt;br /&gt;chmod 600 /home/buildr/.ssh/authorized_keys&lt;br /&gt;&lt;/pre&gt;this is the directory structure of the ebs:&lt;br /&gt;&lt;pre class="brush:plain;"&gt;buildr_home  debs  jdk  jruby  m2&lt;br /&gt;&lt;/pre&gt;debs contains tsocks and vim-nox .deb files, jdk is openjdk7 b54, m2 is a populated repository, jruby is jruby patched with a different version of &lt;a href="http://jira.codehaus.org/browse/JRUBY-3559"&gt;jodatime&lt;/a&gt;. and finally buildr_home is the prototype home directory for the build user.&lt;br /&gt;&lt;br /&gt;here's the directory:&lt;br /&gt;&lt;pre class="brush:plain;"&gt;build.sh  scratch  tasks  teh-build  tsocks.conf&lt;br /&gt;&lt;/pre&gt;scratch is empty, tasks contains some additional tasks that are not needed in the regular build, more specifically stripedjunit and the monkey patch to ant.rb.  teh-build is a prepopulated copy of the build directory, so the first rsync doesn't take as long.&lt;br /&gt;&lt;br /&gt;here's build.sh:&lt;br /&gt;&lt;pre class="brush:bash;"&gt;#!/bin/bash&lt;br /&gt;echo "start"&lt;br /&gt;export EBS_MOUNT=/mnt/super&lt;br /&gt;export LD_PRELOAD=/usr/lib/libtsocks.so&lt;br /&gt;export JAVA_HOME=$EBS_MOUNT/jdk&lt;br /&gt;export M2_REPO=$EBS_MOUNT/m2/repository&lt;br /&gt;export PATH=$JAVA_HOME/bin:$EBS_MOUNT/jruby/bin:/usr/local/bin:/usr/bin:/bin&lt;br /&gt;export BUILDR_PARALLEL=true&lt;br /&gt;export TSOCKS_CONF_FILE=$HOME/tsocks.conf&lt;br /&gt;export TMPDIR=$HOME/scratch&lt;br /&gt;export JAVA_OPTS="-XX:+UseCompressedOops -noverify"&lt;br /&gt;export JAVA_OPTIONS=$JAVA_OPTS&lt;br /&gt;mkdir -p $TMPDIR&lt;br /&gt;cp -r $HOME/tasks teh-build/super&lt;br /&gt;cd teh-build&lt;br /&gt;echo "in directory"&lt;br /&gt;ssh -fN localhost&lt;br /&gt;echo "ssh established."&lt;br /&gt;sed -i "s/svn_revision/99999/" super/buildfile.rb&lt;br /&gt;sed -i "s/\(define \"toplevel\" do\)/\1\ntest.using :stripedjunit/" super/buildfile.rb&lt;br /&gt;echo "start build."&lt;br /&gt;time tsocks buildr $@&lt;br /&gt;export BUILDR_EXIT=$?&lt;br /&gt;echo "that's it"&lt;br /&gt;ssh -O exit localhost&lt;br /&gt;echo "killed ssh"&lt;br /&gt;exit $BUILDR_EXIT&lt;br /&gt;&lt;/pre&gt;I use a separate temp dir, because jruby is can't move files &lt;a href="http://jira.codehaus.org/browse/JRUBY-3381"&gt;across devices&lt;/a&gt;.  I don't copy the .svn files along so I use 99999 for the revision instead.&lt;br /&gt;&lt;br /&gt;tsocks.conf, and server_type can be 5 for openssh DynamicForward contrary to what I claimed earlier:&lt;br /&gt;&lt;pre class="brush:plain;"&gt;server = 127.0.0.1&lt;br /&gt;# Server type defaults to 4 so we need to specify it as 5 for this one&lt;br /&gt;server_type = 5&lt;br /&gt;# The port defaults to 1080 but I've stated it here for clarity&lt;br /&gt;server_port = 50505&lt;br /&gt;&lt;/pre&gt;and .ssh config:&lt;br /&gt;&lt;pre class="brush:plain;"&gt;Host localhost&lt;br /&gt;User commonuser&lt;br /&gt;DynamicForward 50505&lt;br /&gt;Port 10022&lt;br /&gt;ExitOnForwardFailure yes&lt;br /&gt;ControlMaster auto&lt;br /&gt;ControlPath ~/.ssh/master-%r@%h:%p&lt;br /&gt;IdentityFile ~/teh-build/keys/id_dsa_commonuser&lt;br /&gt;&lt;/pre&gt;here you need to have a host on the local network that has a user that allows logins with a shared key, from version control in our case.&lt;br /&gt;&lt;br /&gt;but after all this, the user shouldn't need to do more than, get a hostname from the ircbot, do&lt;br /&gt;&lt;pre class="brush:bash"&gt;export EC2_HOST=the.host.compute.amazonaws.com&lt;br /&gt;&lt;/pre&gt;and they can run, in the toplevel directory:&lt;br /&gt;&lt;pre class="brush:bash"&gt;super/scripts/ec2-build.sh build_and_report&lt;br /&gt;&lt;/pre&gt;or any other build command.  which reminds of build_and_report, and explains the rsync backwards after the build is finished.&lt;br /&gt;&lt;pre class="brush:ruby"&gt; task :resources do&lt;br /&gt; #great&lt;br /&gt; test.using :fail_on_failure=&gt;false&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;def report_failures&lt;br /&gt;failed_tests = projects.map { |project| project.test.failed_tests }.compact.flatten &lt;br /&gt;report_files = []&lt;br /&gt;projects.each { |project| project.test.failed_tests.each do |failure|&lt;br /&gt; report_file = File.join(project.test.report_to.to_s, "TEST-#{failure}.txt")&lt;br /&gt; report_files &amp;lt;&amp;lt; report_file&lt;br /&gt;end unless project.test.failed_tests.nil?&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;projects_with_tests = projects.reject { |project| project.test.tests.nil? }.join(", ")&lt;br /&gt;&lt;br /&gt;puts "ran tests from #{projects_with_tests}"&lt;br /&gt;unless failed_tests.empty?&lt;br /&gt; failed_tests.each { |failure| puts "fail: #{failure}" }&lt;br /&gt; report_files.each do |report|&lt;br /&gt;   FileUtils.cp(report, project('toplevel')._("reports/#{File.basename(report)}"))&lt;br /&gt; end&lt;br /&gt; fail "you have #{failed_tests.length} test failures"&lt;br /&gt;end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;task :build_and_report do&lt;br /&gt;task(:build).invoke&lt;br /&gt;report_failures&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;that is, 1) run all the tests even if there is a failure, but 2) fail the build at the end in case there were failures, 3) report on the failures, 4) put all the failure reports in toplevel/reports/&lt;br /&gt;&lt;br /&gt;enjoy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/174903826897473842-777980635206706397?l=blog.miau.biz' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.miau.biz/feeds/777980635206706397/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=174903826897473842&amp;postID=777980635206706397' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/777980635206706397'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/777980635206706397'/><link rel='alternate' type='text/html' href='http://blog.miau.biz/2009/05/missing-pieces-of-puzzle.html' title='the missing pieces of the puzzle'/><author><name>Miaubiz</name><uri>http://www.blogger.com/profile/06950334298510471857</uri><email>miaubiz@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05794848006157778693'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-174903826897473842.post-663717320336652686</id><published>2009-05-03T18:06:00.017+01:00</published><updated>2009-05-04T08:48:48.637+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='irc'/><category scheme='http://www.blogger.com/atom/ns#' term='erlang'/><category scheme='http://www.blogger.com/atom/ns#' term='ec2'/><category scheme='http://www.blogger.com/atom/ns#' term='shell'/><title type='text'>clouditude</title><content type='html'>there's no easy way to share ebs volumes between accounts, and there are no corporate ec2 accounts.  and I don't want to share my personal login.  and people don't want to do mystifying stuff.  so a shell script to set the thing up:&lt;br /&gt;&lt;pre class="brush:plain;"&gt;#!/bin/bash&lt;br /&gt;set -e&lt;br /&gt;if [ -z $EC2_PRIVATE_KEY ]&lt;br /&gt;then&lt;br /&gt; echo "you must set EC2_PRIVATE_KEY" &gt;&gt; log.txt&lt;br /&gt; exit 4&lt;br /&gt;fi&lt;br /&gt;if [ -z $EC2_CERT ]&lt;br /&gt;then&lt;br /&gt; echo "you must set EC2_CERT" &gt;&gt; log.txt&lt;br /&gt; exit 2&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;export EC2_URL=https://eu-west-1.ec2.amazonaws.com&lt;br /&gt;export EC2_ZONE=eu-west-1b&lt;br /&gt;echo "getting volume" &amp;gt;&amp;gt; log.txt&lt;br /&gt;export EC2_VOLUME=`ec2-describe-volumes |grep $EC2_ZONE | grep available | head -1 | cut -f 2`&lt;br /&gt;if [ -z $EC2_VOLUME ]&lt;br /&gt;then&lt;br /&gt; echo "no volume available in $EC2_ZONE" &amp;gt;&amp;gt; log.txt&lt;br /&gt; exit 1&lt;br /&gt;fi&lt;br /&gt;echo "volume selected: $EC2_VOLUME"  &amp;gt;&amp;gt; log.txt&lt;br /&gt;echo "starting instance in $EC2_ZONE" &amp;gt;&amp;gt; log.txt&lt;br /&gt;export EC2_INSTANCE=`ec2-run-instances ami-4acfe73e -t c1.xlarge -g default -g "ssh allowed" -k super-key -z $EC2_ZONE | grep INSTANCE| cut -f 2`&lt;br /&gt;echo "instance started $EC2_INSTANCE" &amp;gt;&amp;gt; log.txt&lt;br /&gt;while [ -z $EC2_HOST_NAME ]&lt;br /&gt;do&lt;br /&gt; sleep 3&lt;br /&gt; export EC2_HOST_NAME=`ec2-describe-instances $EC2_INSTANCE | grep INSTANCE | cut -f 4`&lt;br /&gt; echo "host name is $EC2_HOST_NAME" &amp;gt;&amp;gt; log.txt&lt;br /&gt;done&lt;br /&gt;echo "attaching volume" &amp;gt;&amp;gt; log.txt&lt;br /&gt;ec2-attach-volume $EC2_VOLUME -i $EC2_INSTANCE -d /dev/sdf &amp;gt;&amp;gt; log.txt&lt;br /&gt;sleep 1&lt;br /&gt;echo "running setup script" &amp;gt;&amp;gt; log.txt&lt;br /&gt;ssh -o StrictHostKeyChecking=no -i ~/ec2/super-key.pem root@$EC2_HOST_NAME "mkdir -p /mnt/super; mount /dev/sdf /mnt/super; /mnt/super/setup.sh" 2&amp;gt;&amp;gt; log.txt&lt;br /&gt;echo "great success" &amp;gt;&amp;gt; log.txt&lt;br /&gt;echo $EC2_HOST_NAME&lt;br /&gt;&lt;/pre&gt;but, I don't want to be running shellscripts all day.  so an &lt;a href="http://blog.jroes.net/2007/08/simple-erlang-irc-bot.html"&gt;ircbot&lt;/a&gt;&lt;pre class="brush:plain; tab-size:2"&gt;&lt;br /&gt;connect(Host, Port) -&amp;gt;&lt;br /&gt;  ets:new(instances, [named_table, public]),&lt;br /&gt;  {ok, Sock} = gen_tcp:connect(Host, Port, [{packet, line}]),&lt;br /&gt;  Ec2Controller = spawn_link(ec2, loop, [Sock]),&lt;br /&gt;  register(ec2_controller, Ec2Controller),&lt;br /&gt;&lt;/pre&gt;bla bla bla&lt;br /&gt;&lt;pre class="brush:plain; tab-size:2"&gt;respond(Nick, Channel, Sock, ["!"|TheRest]) -&amp;gt;&lt;br /&gt;  case TheRest of&lt;br /&gt;          ["hello"] -&amp;gt; irc_privmsg(Sock, Channel, Nick ++ " ! hello");&lt;br /&gt;          ["palkka"] -&amp;gt; irc_privmsg(Sock, Channel, "9,5k nettona");&lt;br /&gt;          ["halp"] -&amp;gt; irc_privmsg(Sock, Channel, "use 'joe ! start' and 'joe ! stop' to control your ec2 server"),&lt;br /&gt;                  irc_privmsg(Sock, Channel, "use 'joe ! check' to see your current status");&lt;br /&gt;          ["check"] -&amp;gt; check_ec2_status(Nick, Sock);&lt;br /&gt;          ["start"] -&amp;gt; io:format("start received~n"), start_ec2_server(Sock, Nick);&lt;br /&gt;          ["stop"] -&amp;gt; stop_ec2_server(Sock, Nick);&lt;br /&gt;          _ -&amp;gt; 0&lt;br /&gt;  end;&lt;br /&gt;&lt;/pre&gt;and then...&lt;br /&gt;&lt;pre class="brush:plain; tab-size:2"&gt;start_ec2_server(Sock, Nick) -&amp;gt;&lt;br /&gt;  Status = ets:lookup(instances, Nick),&lt;br /&gt;  case Status of&lt;br /&gt;          [] -&amp;gt; ets:insert(instances, {Nick, starting}), Ec2Controller = whereis(ec2_controller), Ec2Controller ! {start, Sock, Nick};&lt;br /&gt;          [{Nick,Value}] -&amp;gt; case Value of&lt;br /&gt;                          starting -&amp;gt; irc_privmsg(Sock, Nick, "plz hold I am already processing a request from you.");&lt;br /&gt;                          {running, ServerName} -&amp;gt; irc_privmsg(Sock, Nick, "you already have instance " ++ ServerName)&lt;br /&gt;                  end&lt;br /&gt;  end.&lt;br /&gt;&lt;br /&gt;stop_ec2_server(Sock, Nick) -&amp;gt;&lt;br /&gt;  Status = ets:lookup(instances, Nick),&lt;br /&gt;  case Status of&lt;br /&gt;          [] -&amp;gt; irc_privmsg(Sock, Nick, "you dont have a running server.");&lt;br /&gt;          [{Nick,Value}] -&amp;gt; case Value of&lt;br /&gt;                          starting -&amp;gt; irc_privmsg(Sock, Nick, "your server isn't even started yet.");&lt;br /&gt;                          {running, ServerName} -&amp;gt; Ec2Controller = whereis(ec2_controller), Ec2Controller ! {stop, Sock, Nick, ServerName}&lt;br /&gt;                  end&lt;br /&gt;  end.&lt;br /&gt;&lt;br /&gt;check_ec2_status(Nick, Sock) -&amp;gt;&lt;br /&gt;  Status = ets:lookup(instances, Nick),&lt;br /&gt;  case Status of&lt;br /&gt;          [] -&amp;gt; irc_privmsg(Sock, Nick, "you dont have a running server.  use 'joe ! start' to start one.");&lt;br /&gt;          [{Nick,Value}] -&amp;gt; case Value of&lt;br /&gt;                          starting -&amp;gt; irc_privmsg(Sock, Nick, "your server is starting, I will notify you when it is available.");&lt;br /&gt;                          {running, ServerName} -&amp;gt; irc_privmsg(Sock, Nick, "you have a running server at: " ++ ServerName), irc_privmsg(Sock, Nick, "you can use 'joe ! stop' when you don't need it anymore.")&lt;br /&gt;          end&lt;br /&gt;end.&lt;br /&gt;&lt;/pre&gt;yeah.  finally:&lt;br /&gt;&lt;pre class="brush:plain; tab-size:2"&gt;loop(Sock) -&amp;gt;&lt;br /&gt;      receive&lt;br /&gt;              {start, Sock, Nick} -&amp;gt; io:format("received start~n"),&lt;br /&gt;                      start(Sock, Nick),&lt;br /&gt;                      loop(Sock);&lt;br /&gt;              {stop, Sock, Nick, ServerName} -&amp;gt; io:format("received stop~n"),&lt;br /&gt;                      stop(Sock, Nick, ServerName),&lt;br /&gt;                      loop(Sock)&lt;br /&gt;      end.&lt;br /&gt;&lt;br /&gt;stop(Sock, Nick, ServerName) -&amp;gt;&lt;br /&gt;      os:cmd("./stop.sh " ++ ServerName),&lt;br /&gt;      ets:delete(instances, Nick),&lt;br /&gt;      bot:irc_privmsg(Sock, Nick, "your server has been stopped.").&lt;br /&gt;&lt;br /&gt;start(Sock, Nick) -&amp;gt;&lt;br /&gt;      io:format("launching instance for ~s~n", [Nick]),&lt;br /&gt;      bot:irc_privmsg(Sock, Nick, "started a server for you.  I will send you the hostname when it is up and running"),&lt;br /&gt;      register_server(Sock, Nick, os:cmd("./launch.sh")).&lt;br /&gt;&lt;br /&gt;register_server(Sock, Nick, ServerName) -&amp;gt;&lt;br /&gt;      io:format("server is ready ~s - ~s~n", [Nick, ServerName]),&lt;br /&gt;      case regexp:match(ServerName, "compute.amazonaws.com") of&lt;br /&gt;              nomatch -&amp;gt; ets:delete(instances, Nick),&lt;br /&gt;                      bot:irc_privmsg(Sock, Nick, "some kind of error occurred.");&lt;br /&gt;              _ -&amp;gt; ets:insert(instances, {Nick, {running, ServerName}}),&lt;br /&gt;                      bot:irc_privmsg(Sock, Nick, "your server is " ++ ServerName)&lt;br /&gt;      end.&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/174903826897473842-663717320336652686?l=blog.miau.biz' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.miau.biz/feeds/663717320336652686/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=174903826897473842&amp;postID=663717320336652686' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/663717320336652686'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/663717320336652686'/><link rel='alternate' type='text/html' href='http://blog.miau.biz/2009/05/clouditude.html' title='clouditude'/><author><name>Miaubiz</name><uri>http://www.blogger.com/profile/06950334298510471857</uri><email>miaubiz@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05794848006157778693'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-174903826897473842.post-7531049374557585368</id><published>2009-04-28T19:05:00.002+01:00</published><updated>2009-04-28T19:15:36.252+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='jdk7'/><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='buildr'/><title type='text'>eclipse and buildr</title><content type='html'>the eclipse .classpath is a lot more involved than I originally estimated.&lt;br /&gt;&lt;pre&gt;module Buildr&lt;br /&gt; module Eclipse&lt;br /&gt;   class ClasspathEntryWriter&lt;br /&gt;     alias :old_src_from_absolute_paths :src_from_absolute_paths&lt;br /&gt;     def src_from_absolute_paths absolute_paths, output=nil&lt;br /&gt;       old_src_from_absolute_paths absolute_paths&lt;br /&gt;     end&lt;br /&gt;&lt;br /&gt;     def lib libs&lt;br /&gt;     end&lt;br /&gt;&lt;br /&gt;     alias :old_relative :relative&lt;br /&gt;     def relative path&lt;br /&gt;       string_path = old_relative path&lt;br /&gt;       return string_path unless string_path=~(/target/)&lt;br /&gt;       @paths_written &lt;&lt; "dummy"&lt;br /&gt;       "dummy"&lt;br /&gt;     end&lt;br /&gt;   end&lt;br /&gt; end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;task :rename_target_to_bin do&lt;br /&gt; projects.each do |project|&lt;br /&gt;   if !project.compile.target.nil?&lt;br /&gt;     bin_target=project.compile.target.to_s.sub(/target\/classes/, "bin")&lt;br /&gt;     project.compile.into(bin_target)&lt;br /&gt;   end&lt;br /&gt; end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;in brief, I don't want &lt;span style="font-weight: bold;"&gt;target&lt;/span&gt; anywhere in my .classpath file.  one of the issues is that compile.target and it's friends have already been invoked and appended into the dependencies before my task gets run.  and that also messes with all the uniq's that happen later in there.&lt;br /&gt;&lt;br /&gt;maybe I'm halfway done so far.    and maybe I can take fold all of the above into a single block later on.&lt;br /&gt;&lt;br /&gt;the javac on jdk1.7.0 b54 is really fast compared to 1.6u12.  b55 and b56 have a broken headless which doesn't work well for remote builds.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/174903826897473842-7531049374557585368?l=blog.miau.biz' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.miau.biz/feeds/7531049374557585368/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=174903826897473842&amp;postID=7531049374557585368' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/7531049374557585368'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/7531049374557585368'/><link rel='alternate' type='text/html' href='http://blog.miau.biz/2009/04/eclipse-and-buildr.html' title='eclipse and buildr'/><author><name>Miaubiz</name><uri>http://www.blogger.com/profile/06950334298510471857</uri><email>miaubiz@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05794848006157778693'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-174903826897473842.post-1516804531374755498</id><published>2009-04-26T19:00:00.002+01:00</published><updated>2009-04-26T19:02:57.619+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><category scheme='http://www.blogger.com/atom/ns#' term='junit'/><category scheme='http://www.blogger.com/atom/ns#' term='buildr'/><category scheme='http://www.blogger.com/atom/ns#' term='concurrency'/><title type='text'>one more spell</title><content type='html'>&lt;pre&gt;&lt;br /&gt;test.using :stripedjunit&lt;br /&gt;&lt;br /&gt;class StripedJunit &lt; Buildr::JUnit&lt;br /&gt;  def run(tests, dependencies)&lt;br /&gt;    passed=[]&lt;br /&gt;    max_thrads=4&lt;br /&gt;    if tests.length&lt;100&lt;br /&gt;      max_thrads=1&lt;br /&gt;    end&lt;br /&gt;    threads = (0..(max_thrads-1)).collect { |count|&lt;br /&gt;      Thread.new(count) { |partition_number| teh_tests = tests.select{|test| test.hash%max_thrads==partition_number};  passed &lt;&lt; super(teh_tests, dependencies) unless teh_tests.empty? }&lt;br /&gt;    }&lt;br /&gt;    threads.each { |t| t.join }&lt;br /&gt;    passed.flatten&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;Buildr::TestFramework &lt;&lt; StripedJunit&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;you get the idea.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/174903826897473842-1516804531374755498?l=blog.miau.biz' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.miau.biz/feeds/1516804531374755498/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=174903826897473842&amp;postID=1516804531374755498' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/1516804531374755498'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/1516804531374755498'/><link rel='alternate' type='text/html' href='http://blog.miau.biz/2009/04/one-more-spell.html' title='one more spell'/><author><name>Miaubiz</name><uri>http://www.blogger.com/profile/06950334298510471857</uri><email>miaubiz@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05794848006157778693'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-174903826897473842.post-2946671776022528091</id><published>2009-04-26T17:34:00.005+01:00</published><updated>2009-04-28T19:05:26.089+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='monkey patching'/><category scheme='http://www.blogger.com/atom/ns#' term='jruby'/><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='rake'/><category scheme='http://www.blogger.com/atom/ns#' term='buildr'/><category scheme='http://www.blogger.com/atom/ns#' term='concurrency'/><title type='text'>ruby duby duu</title><content type='html'>as a &lt;a href="http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/4589"&gt;french guy&lt;/a&gt; pointed out in 2000, ruby's &lt;a href="http://redmine.ruby-lang.org/issues/show/921"&gt;autoload&lt;/a&gt; is not thread safe,  and neither is &lt;a href="http://redmine.ruby-lang.org/issues/show/920"&gt;require&lt;/a&gt;.&lt;br /&gt;there's been &lt;a href="http://www.ruby-forum.com/topic/172385"&gt;some discussion&lt;/a&gt; about it.  but it doesn't seem to bother normal people.&lt;br /&gt;&lt;br /&gt;for people using rake's multitask, autoload fails rather deterministically.  two similar tasks, &lt;span style="font-size:85%;"&gt;a natural parallelization,&lt;/span&gt; will block on the same dependency task, and consequently unblock at exactly the same time, launching at the exact same time.  ka-boom.&lt;br /&gt;&lt;br /&gt;you could synchronize require yourself with just this monkey patch:&lt;br /&gt;&lt;pre&gt;module Kernel&lt;br /&gt;@@lock=Mutex.new&lt;br /&gt;alias :old_require :require&lt;br /&gt;def require requirement&lt;br /&gt;@@lock.synchronize do&lt;br /&gt; old_require requirement&lt;br /&gt;end&lt;br /&gt;end&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;autoload however is a different beast.  autoloads are already done before your buildfile starts to execute, you can't introspect existing autoloads, and if you could, you can't require the autoload stuff eagerly because you might not be in state that allows the specified module to be required.  further, since autoload is in &lt;a href="http://www.ruby-doc.org/doxygen/1.8.4/variable_8c-source.html"&gt;variable.c&lt;/a&gt; in MRI and somewhere else in JRuby, you'd be fiddling with stuff you're not meant to touch, even ruby wise!&lt;br /&gt;&lt;br /&gt;personally I've been using this monkey patch for Antwrap, and then avoid using parallel for the eclipse task:&lt;br /&gt;&lt;pre&gt;module Buildr&lt;br /&gt;module Ant&lt;br /&gt;@@lock=Mutex.new&lt;br /&gt;def ant(name, &amp;amp;block)&lt;br /&gt;  options = { :name=&gt;name, :basedir=&gt;Dir.pwd, :declarative=&gt;true }&lt;br /&gt;  options.merge!(:logger=&gt; Logger.new(STDOUT), :loglevel=&gt; Logger::DEBUG) if Buildr.application.options.trace&lt;br /&gt;  Java.load&lt;br /&gt;  ant_project=create_project(options)&lt;br /&gt;  ant_project.tap do |project|&lt;br /&gt;    project.project.getBuildListeners().get(0).&lt;br /&gt;      setMessageOutputLevel((Buildr.application.options.trace &amp;amp;&amp;amp; 4) || (verbose &amp;amp;&amp;amp; 2) || 0)&lt;br /&gt;    yield project if block_given?&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;def create_project(options)&lt;br /&gt;  @@lock.synchronize do&lt;br /&gt;    Antwrap::AntProject.new(options)&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;end&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;god speed.&lt;br /&gt;&lt;br /&gt;and I use this for my eclipse layout:&lt;br /&gt;&lt;strike&gt;task :bin_target do&lt;br /&gt;projects.each do |project|&lt;br /&gt; bin_target=project.compile.target.to_s.sub(/target\/classes/, "bin")&lt;br /&gt; project.compile.into(bin_target)&lt;br /&gt; project.test.compile.into(bin_target)&lt;br /&gt; project.resources.filter.into(bin_target)&lt;br /&gt; project.test.resources.filter.into(bin_target)&lt;br /&gt;end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;task :eclipse =&gt; :bin_target&lt;br /&gt;&lt;/strike&gt;and finally:&lt;br /&gt;&lt;pre&gt;Buildr.application.options.rakelib="super/tasks"&lt;br /&gt;mkdir super&lt;br /&gt;mv buildfile super/buildfile.rb&lt;br /&gt;echo "require 'super/buildfile'" &gt; buildfile&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/174903826897473842-2946671776022528091?l=blog.miau.biz' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.miau.biz/feeds/2946671776022528091/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=174903826897473842&amp;postID=2946671776022528091' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/2946671776022528091'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/2946671776022528091'/><link rel='alternate' type='text/html' href='http://blog.miau.biz/2009/04/ruby-duby-duu.html' title='ruby duby duu'/><author><name>Miaubiz</name><uri>http://www.blogger.com/profile/06950334298510471857</uri><email>miaubiz@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05794848006157778693'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-174903826897473842.post-6675501830809479035</id><published>2009-04-24T07:41:00.004+01:00</published><updated>2009-04-24T08:23:54.839+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='coverage'/><category scheme='http://www.blogger.com/atom/ns#' term='wicket'/><category scheme='http://www.blogger.com/atom/ns#' term='cobertura'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><category scheme='http://www.blogger.com/atom/ns#' term='junit'/><title type='text'>heads up display</title><content type='html'>cobertura finally came out with &lt;a href="http://www.nabble.com/Release-1.9.1-p21839930.html"&gt;1.9.1&lt;/a&gt; so you don't have to build it yourself or use some alpha maven plugin.  hooray!&lt;br /&gt;&lt;br /&gt;then some guy released &lt;a href="http://sourceforge.net/tracker/?func=detail&amp;amp;aid=2581839&amp;amp;group_id=130558&amp;amp;atid=720017"&gt;a patch&lt;/a&gt; that apparently does what you always wished cobertura would do: tell you which test method and class exercised which line and which branch.  combine that with the excellent stuff in last year's &lt;a href="http://www.youtube.com/watch?v=Pug_5Tl2UxQ"&gt;gtac keynote&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;instrument your application, listen in on wicket component instantiation, record coverage, cross reference the data with your test coverage report.  show data about the tests or lack thereof in a hover on each component of your web page.  while you're at it, why not add coverage reports of software in m2 repositories, next to the source jar.  then you can see which of your dependencies are tested.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/174903826897473842-6675501830809479035?l=blog.miau.biz' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.miau.biz/feeds/6675501830809479035/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=174903826897473842&amp;postID=6675501830809479035' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/6675501830809479035'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/6675501830809479035'/><link rel='alternate' type='text/html' href='http://blog.miau.biz/2009/04/heads-up-display.html' title='heads up display'/><author><name>Miaubiz</name><uri>http://www.blogger.com/profile/06950334298510471857</uri><email>miaubiz@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05794848006157778693'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-174903826897473842.post-1091082832576023237</id><published>2009-04-18T07:34:00.004+01:00</published><updated>2009-04-19T08:40:31.253+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='cloud'/><category scheme='http://www.blogger.com/atom/ns#' term='nehalem'/><category scheme='http://www.blogger.com/atom/ns#' term='building'/><category scheme='http://www.blogger.com/atom/ns#' term='amazon'/><category scheme='http://www.blogger.com/atom/ns#' term='ec2'/><category scheme='http://www.blogger.com/atom/ns#' term='cloud computing'/><category scheme='http://www.blogger.com/atom/ns#' term='buildr'/><title type='text'>how high</title><content type='html'>so high that I can kiss the clouds&lt;br /&gt;&lt;br /&gt;the story so far:&lt;br /&gt;our project has about 7500 unit tests.&lt;br /&gt;it takes too long to build&lt;br /&gt;refactoring the build requires you to:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;run the build&lt;/li&gt;&lt;li&gt;see it in eclipse&lt;/li&gt;&lt;li&gt;see it in idea&lt;/li&gt;&lt;li&gt;repeat&lt;/li&gt;&lt;/ol&gt;so a catch22 in the current context.  to refactor the build into something you can work with, you need a lot of resources, which you don't have.  more hardware to the &lt;span style="font-style: italic;"&gt;temporary&lt;/span&gt; rescue!&lt;br /&gt;&lt;br /&gt;faster computers come in two flavors:  faster cpus with more memory bandwidth, and more cores.  the former is available in roughly 4x the current speed in the W5580, and 2x the current speed in more available iron.  8 cores is the reasonable upper limit of cores discounting HT.  compared to the current 2.  but already using 2 somewhere else leaves the two at home available for anything else.&lt;br /&gt;&lt;br /&gt;I should mention that during the build we'll want to access private m2 repositories as well as some webservices on our private network.&lt;br /&gt;&lt;br /&gt;getting clunky desktop computers or noisy server iron in our workspace are not practical options.  so we're left with:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;our own servers in a datacenter&lt;/li&gt;&lt;li&gt;servers in the customer datacenter&lt;/li&gt;&lt;li&gt;virtual servers in a cloud&lt;/li&gt;&lt;/ol&gt;the epigraph will tell you what I end up with...  at first I was very skeptical about anything off site, for two reasons: 1) VPNs and 2) the overhead of getting the buildable stuff to the server over the network.  further, getting dedicated hardware for this and coordinating it between 20 odd developers would be a huge hassle and the requirements might change quickly.  if the cloud option worked reasonably, it would be our primary choice.  the cloud could further be broken down into a public cloud, and our own cloud based on &lt;a href="http://eucalyptus.cs.ucsb.edu/"&gt;eucalyptus&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;the geographically closest thing amazon ec2 has to our site is eu-west-1, which seems like a long ways away from us.  but rsync really works miracles.  with rsync -rt --delete --delete-excluded --exclude target --exclude .svn --exclude junit* blahblahblah. &lt;span style="font-weight: bold;"&gt;rsync between typical svn revisions takes about 3 seconds.&lt;/span&gt;  and when you --delete-excluded you don't have to run clean on your build either because it will essentially remove the target directories.   &lt;span style="font-size:85%;"&gt;btw.  we had a java package named reports,  if you have a package named junit, target or reports, mind this.  if you're unlucky your build might pass without a specific package&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;rsync should work great also when you're going to make sure stuff works in eclipse and idea, as you can make the changes on one machine quickly, then rsync them to the other to see if they work in the other IDE aswell.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;the following voids your warranty.&lt;/span&gt;  the VPN.  given that when you start the remote build, you are inside the private network, the firewall and so on, you don't need to connect your remote server to the vpn, you can instead proxy everything through your own computer.&lt;br /&gt;&lt;br /&gt;start an incoming ssh tunnel into your own computer's ssh server:&lt;br /&gt;ssh -R 50505:localhost:22 blahblah.compute.amazonaws.com&lt;br /&gt;then, on the remote host connect to your own computer through the tunnel you just created, and specify a DynamicForward:&lt;br /&gt;&lt;pre&gt;ssh -Nf -D 30303 -p 50505 localhost&lt;br /&gt;&lt;/pre&gt;(Nf goes to the background)&lt;br /&gt;this starts a socks4 proxy on port 30303 of the remote computer (bound to localhost) that proxies to the private network you are on.&lt;br /&gt;now you can use &lt;a href="http://tsocks.sourceforge.net/"&gt;tsocks&lt;/a&gt; which hasn't been developed since 2002, but works quite nicely to transparently force your build to use the proxy.&lt;br /&gt;&lt;pre&gt;export TSOCKS_CONF_FILE=$HOME/tsocks.conf&lt;br /&gt;tsocks buildr clean build&lt;br /&gt;&lt;/pre&gt;before logging off you need to kill the background ssh you started:&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;updated&lt;/span&gt;&lt;br /&gt;&lt;strike&gt;kill -9 `lsof -i @localhost:50505 -t`&lt;/strike&gt;&lt;br /&gt;&lt;br /&gt;in .ssh/config:&lt;br /&gt;&lt;pre&gt;ControlMaster auto&lt;br /&gt;ControlPath ~/.ssh/master-%r@%h:%p&lt;/pre&gt;and on the commandline:&lt;br /&gt;&lt;pre&gt;ssh -p 50505 localhost -O exit&lt;/pre&gt;if you're using ProxyCommand and nc, you might need to specify -q 0 or -w 1 in there to avoid leaving a dangling nc, and to fix some other problematic bits.&lt;br /&gt;with tsocks, you need to configure your networks and proxies, especially match the port you opened the proxy on (30303 in this example) and the tsocks configuration, and use "4" as your proxy type, short for socks4.&lt;br /&gt;&lt;br /&gt;if more than one person will be using the machine, you need to make sure everyone uses different ports for both the proxy and the return channel (50505 in this example)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;you're now ready to choose your cloud servers.&lt;/span&gt;  there are two interesting ones on ec2, the medium high-cpu, and the xlarge high-cpu.  in short they are 2x 2,33ghz e53XX series with 1,7gb ram and a 32bit kernel (and thus jvm) and 8x the same cpu, with 7,5gb ram and a 64bit kernel.&lt;br /&gt;&lt;br /&gt;the prices are $0.22 and $0.88 per &lt;span style="font-style: italic;"&gt;starting&lt;/span&gt; hour, respectively.  &lt;span style="font-size:85%;"&gt;(so you'll want to start one server when you get to work and shut it down when you leave for the day)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;if you can get 4 people on your team to use the same machine, you should not do much worse on the 8way machine than the 2way machine even if everyone starts their build at the same time.  the only performance loss would be due to the 64 bit stuff, and in your build &lt;a href="http://blogs.sun.com/dagastine/entry/java_rocks_intel_nehalem1"&gt;compressed oops&lt;/a&gt; would likely do nothing to help you as it is not active in interpreted code.&lt;br /&gt;&lt;br /&gt;but when the 4 people don't start their build at the same time, you should always do better on the 8 way machine assuming you can get your build to use more than 2 threads for any amount of time.  I've gotten our fairly serial build to momentarily use 75% of cpu on an 8way box, so it's using 6 threads at that point.&lt;br /&gt;&lt;br /&gt;the total build time difference is 3 vs. 5 minutes of wall time on the 8 and 2 way ec2 boxes.  overall, the build uses 2,6 times user+sys vs. real time on the 8way box.  but as part of refactoring the build, this could go way up.  it's already somewhere south of 1.5x with just a single threaded build as even the c1 compiler now uses a background thread to compile bytecode to native.&lt;br /&gt;&lt;br /&gt;last but not least, on ec2 you can use &lt;span style="font-weight: bold;"&gt;ebs&lt;/span&gt; to create your own persistent filesystem on which you can store your m2 repository, your JDKs, your .debs, jruby with the appropriate gems, and a prepopulated build directory.&lt;br /&gt;&lt;br /&gt;you can leave everything except the build on your ebs volume.  I've made a copy of the initial build onto local storage just to be sure performance wise.  this also simplifies things when you have several people using the same server, as they can share everything except the build directory.  you might want to sync the build directory back to ebs every now and then, especially if you've made big changes, but just having the bulk of it persisted will save you a couple of minutes at start up, and a few cents each day.  with eucalyptus you might be able to something similar for persistent storage.&lt;br /&gt;&lt;br /&gt;enjoy your flight.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/174903826897473842-1091082832576023237?l=blog.miau.biz' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.miau.biz/feeds/1091082832576023237/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=174903826897473842&amp;postID=1091082832576023237' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/1091082832576023237'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/174903826897473842/posts/default/1091082832576023237'/><link rel='alternate' type='text/html' href='http://blog.miau.biz/2009/04/how-high.html' title='how high'/><author><name>Miaubiz</name><uri>http://www.blogger.com/profile/06950334298510471857</uri><email>miaubiz@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05794848006157778693'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry></feed>