Confession: I see people. They recognize me. I don't recognize them.
They'll remember me, I won't.
sucks to be me
2008-05-19
Non-Reciprocal Recognition
2008-05-04
A snack-sized bite of Java for tonight
With Java autoboxing, always pay attention to what your primitives get boxed into.
Here's an easy little bug to introduce if you don't pay attention: consider these methods of the Map<K, V> interface:
V put(K key, V value)V remove(Object key)
So you put a value into a map, and remove it. Easy enough.
Pop Quiz
So what does the following return?
public static String test() {
HashMap<Long, String> map = new HashMap<Long, String>();
final long some_key = 1;
map.put(some_key, "foo");
return map.remove(1);
}...
...
...
...
Answer: null.
This is why it's important to remember the definition of the put, get and remove methods. While the generified [nda - yes that's a word, according to the Sun docs] flavour of put(K, V) ensures the key is an instance of K, for whatever K you declared for this generic map, the get and remove methods weren't generified and simply take an Object. This can bite you, as in the above function, where autoboxing essentially caused the following calls to happen, though it probably wasn't the programmer's intent:
map.put(new Long(1), "foo");
map.remove(new Integer(1));
Even though Integer(1) and Long(1) have the same hashCode() value, they fail the equals() test, so key lookups when using the wrong wrapper class will always fail. The fix, of course, is to declare your keys as the right type when calling get() or remove(), and be careful, as the method signature will allow anything to be passed in, so you'll never know at compile-time you got it wrong.
Happy coding!
2008-04-29
Rogers vs Bell
So I was hanging out with a friend (who will remain nameless for reasons you'll see very soon) a while back, and I saw his new BlackBerry Pearl:
- So, you got a BlackBerry, huh?
- Yeah man, it's great!
- How do you find the Bell network?
- Actually I'm with Rogers. Cheaper.
- ...
- ...
- Dude, YOU WORK FOR BELL, don't you get service for free or something?
- Nope, it's still cheaper with Rogers
I was floored! If this isn't a great endorsement of Rogers Wireless, I don't know what is. (Yes, I know their data plans still suck, but it seems they "suck less" than the alternatives.) I can't imagine what it must be like working for a company that would treat its employees so poorly they'd sign a service contract with their biggest competitor.
2008-04-20
Argh! Missed it!
Totally non-techie post today for food geeks: it seems that La Bottega in Ottawa received a single Spanish jamón ibérico last Friday. I missed my chance to buy a few slices, reading about it only after the fact on Ron Eade's (the Citizen's food editor) blog, which I was only recently made aware of. Damn.
It is easy to underestimate the significance of this news item, but thankfully, in his video post, Eade reminds us that this is quite notable, as it is the first time jamón ibérico (made from pasture-fed black pigs of certified race) is available in Ottawa. In fact, until 2005, it was illegal to export it to North America, and since the ham must cure for three years before being ready to sell, it's only now starting to appear on our shores, and is a tad expensive (La Bottega was moving it at 200$ per kilogram).
[sure, I paid 30$ CAD for the plate above last month but look at that marbling!]
Ottawa food enthusiasts have no doubt noticed that much cheaper (but still delicious) jamón serrano has been available in local food shops for a while now, which is made from white pigs with less restrictions on feeding.
2008-04-13
Is Deploying a Wireless Network More Secure Than Not Deploying One?
Yes, I think it is. Long-winded explanation follows.
Me: I'm a guy who loves to work on a laptop. I've owned my little Thinkpad since 2004. I have dragged it between Ottawa and Montreal dozens of times, hauled it through Spain and the United States while vacationing, it's been through several coffee shops in Ottawa, and even tonight, with three other computers in my apartment much faster than this one, I'm in the living room, writing this post on the faithful machine. If you call me up and need help with a build script or a complicated subversion operation, I'll run over to your cube with it and we can hack on the problem together, each on our own screen. Or anyway, I would if there were wireless network access points at the office.
Which there aren't.
(Yes, I'm well aware of the irony of working for a company that makes network equipment. No need to point it out.)
The subject came up on Friday evening, as a bunch of us engineers were sitting around having a beer before leaving for the weekend. Someone (I swear it wasn't me this time) wondered out loud why in this day and age, we didn't have wireless APs at the office. Asked our CTO: "Why don't we just drive to Futureshop and spend the fifty bucks?"
I suppose it's always been a "nice to have" feature of the office, never a true requirement, and commercial-grade WAPs are more expensive than the consumer versions from Linksys. I've also heard mentions that there might be concerns about the security of the setup, given that we lease a floor on a building housing a bunch of other companies. I realized after the discussion, however, that the security argument was bunk, and having no WLAN could actually put us at much greater risk than having one.
It is an oft-repeated saying in security discussions that humans are often the weakest part of a security system. In his book Secrets and Lies, security guru Bruce Schneier again reminds us, as he has before, that an inconvenient security system is self-defeating because humans will simply end up not using it. In Chapter 17, he relates this story:
It has been said that the most insecure system is the one that isn't used. And more often than not, a security system isn't used because it's just too irritating.
Recently I did some work for the security group in a major multinational corporation. They were concerned that their senior management was doing business on insecure phones - land lines and cellular - sometimes in a foreign country. Could I help? There were several secure-voice products, and we talked about them and how they worked. The voice quality was not as good as normal phones. There was a several-second delay at the start of the call while the encryption algorithm was initialized. The phones were a little larger than the smallest and sexiest cellular phones. But their conversations would be encrypted.
Not good enough, said the senior executives. They wanted a secure phone, but they were unwilling to live with inferior voice quality, or longer call setup time. And in the end, they continued talking over insecure phones.
This is exactly the risk that an office takes by not deploying secure, properly configured WAPs managed by the IT team. Wireless networks are a convenience for many. There are some (albeit still rare) laptops appearing that don't even have a network jack anymore; and this is just the beginning of that design trend. Sooner or later, someone will get fed up and install a rogue access point, connected to the corporate LAN, and quite possibly insecurely configured and allowing routing to every resource on the network. It may already have happened. Wishfully thinking otherwise is simply ignoring the human part of the equation, hardly good practice of security.
2008-04-06
A Firefox Search Plugin for the Ottawa Public Library
The Ottawa Public Library has a very neat service where you can look up a book online, request it to be delivered to whichever branch is closest to you, and be notified by email when your the chosen tome is available for pickup. If a book is already checked out, you can simply request the next available copy to be delivered.
Seeing how I do quite a bit of reading these days, I set about creating a Firefox search plugin to easily search their catalog. In truth, I just wanted a quick way of looking up a book in the library catalog when I'm on Amazon.ca or I read a book recommendation on a blog.
Installing this search plugin
- Navigate to your Firefox profile directory (%APPDATA%\Mozilla\Firefox\Profiles\whatever).
- If it's not already created, create a new folder called "searchplugins" (without the quotes).
- Copy this file (ottawa_public_library.xml) to the searchplugins folder, then restart Firefox.
Usage
It's dead simple. Open the search engines drop down menu and choose the new "Ottawa Public Library" option:
Now type in keywords from the book's title and hit enter:
This plugin does a search using the "Keywords in TITLE" option, as I thought that was the most useful. Hope you find this useful! Tell your geeky friends!
Edit: ah yes, I forgot to say, the XML file includes a copy of the library's logo, taken from their favicon.ico file. I haven't asked the city of Ottawa for permission to redistribute the icon, but I'm quasi-certain it wouldn't cause a problem. If I get complaints I'll put a new icon in there.
Another update: There's been some interest in this, so here's an easier way to install: Click here to install the Firefox search plugin for the Ottawa Public Library
2008-04-03
Resolved: Boingo Refunds Their Double-Charge
A couple co-workers have been asking me for an update, so here...
Last weekend, I wrote a post (link) about how after logging on to the Boingo wireless service from two different airports on the same day, I was charged twice despite having purchased a 24-hour pass. At that time, I contacted their phone service, where a customer rep explained it was normal, and advised me to read the user agreement next time.
Luckily, I didn't have to do a credit card chargeback; as a result of my blog post, I was contacted by Boingo's PR firm, and apparently the phone rep I talked to was incorrect: what happened was simply a software glitch. They've refunded the second (erroneous) charge, so it looks like this was just a one-off problem, and not the shady business practice I initially suspected. Phew! All is now well.
2008-03-31
Read Jason's post about Stat(CVS|SVN) if you care about repository analysis
My good friend Jason, one of the two talented developers that form micro-ISV LavaBlast Software, just put up a post about exciting happenings in the StatCVS and StatSVN world. Although I'm no longer really involved with those projects, I'm happy to see these developments, and want to give a kudos to guys like Jason Kealey and Benoit Xhenseval and all their collaborators for all the great effort they've put in.
As for myself, I'll be involved in more SVN-related tooling projects in the coming months, but I can't talk about that just now... :)
I need to reply to Jason's conclusion about coming back to Java development, though, especially the note about explicitly creating Integer objects:
"Personally, I enjoy loading up a recent version of Eclipse and working in Java once in a while because it helps me observe the best in both worlds. I much prefer coding in C# because of the easier string manipulation and the fact that everything is an object so you don't have to explicitly create an Integer object from your int to insert it into a collection. However, when working in VS.NET, I dearly miss the automatic incremental compilation feature that Eclipse runs when you save a file."
If it's been a little while since you've looked at Java, know that J2SE 1.5 brought a lot of great improvements especially in the Concurrent and Collections namespaces, as well as new language features. One such usability improvement is known as autoboxing, which means basic numeric types like int or float are automatically "boxed" into their object containers (Integer, Float, etc.) when required, like when adding an element to a collection, and "unboxed" when the native type is required. Just thought you'd like to know, Jason ;)
[It goes without saying that you should always be mindful of the performance impact of creating a bunch of temporary objects like this! Operations on Integers are always going to be slow-ish because they're immutable, and new objects are created for every value you use.]
2008-03-29
Watch Out For Boingo Wireless in Airports (scam alert?)
Be very, very careful with Boingo Wireless hotspots.
On a recent trip from Madrid to Ottawa, I had a 6-hour layover in Newark Liberty Airport (EWR). I decided to go ahead and pay $7.95 USD for a 24-hour access pass on Boingo Wireless so I could catch up on news and mail, while passing the time. I didn't want to subscribe to anything (I'm not a frequent-flier, I just happened to want access that day), so I bought a day pass:
Here's what it says:
"Don't travel much? Get a Boingo AsYouGo account for just $7.95 per Connect Day for locations within the U.S. & Canada and $9.95 internationally. A Connect Day includes unlimited access in any location for 24 hours. No monthly fees apply."
I used the pass I bought on March 24th, 2 hours 35 minutes in Newark (EWR) and then 5 minutes in Ottawa (YOW) while waiting for checked luggage to arrive (email addict!). Note that the plan description says "in any location", not "in any single location". Imagine my surprise when I found two charges on my credit card bill: one on March 24th (expected), and another one two days later on March 26th! I called customer service, and they refused to reverse the second charge, informing me that it was incurred when I logged in for a second time in another airport.
I've reviewed the user agreement at [https://signup.boingo.com/signup/DisplayBCA.app], especially Section 3, "Locations and usage", and at time of this writing, it doesn't appear to me to contain any language restricting usage of a day pass to a single location, or any warning that logging in from a second location during the same 24 hour period will result in a new charge. I've since written to their customer service to explain the situation and request a refund of that second charge. I'll update this post when I hear back from them.
UPDATE: Sounds like it was simply a software glitch! I've been refunded.
2008-03-24
Metro Madrid: You Fail at the Internet
Exhibit A: Line 2 is closed between Banco Espana and Opera.
OK, no big deal, I heard about some sort of closure in the paper, but before I go out I want to look up which stations are closed, and what the current status of the line is. Should be some sort of notice on the website, right?
Exhibit B: Metro Madrid's landing page, with current news items (March 23rd, 2 days after the line was partially shut down)
You fail at the Internet.
2008-03-20
User-Hostile Design
This post is in the spirit of this fun one. I spent two nights in a hotel in beautiful Malaga (ES), and was confronted with these 'interesting' controls:
Here's the equipment:
Both rotating knobs have a small unmarked button on them, which can be pushed in, then comes back out by itself immediately. I was not able to figure out what either of those buttons did.
The left knob is marked with temperatures from 20C to 50C, so purportedly controls temperature, but there's no mark anywhere around it to act as a pointer, letting the user know which temperature is selected. Not that it matters much, I've tried spinning it in both directions, with and without holding the button, and never felt the temperature change from "warmish". It spins much more easily in one direction than the other, leading me to believe the direction with the most resistance must be doing something.
The right knob selects the flow and function (showerhead, telephone-style showerhead, bathtub spigot, those 3 body jets on top, and the 4 jets below those [which I never managed to turn on]), by turning in one direction, which you can do if the flow is on high. Keep turning (harder) when the flow is on high and it will switch functions (yes, think about it). The functions are marked 'T', 'C', 'C', 'L', 'E' (how clear!), I don't know in which language those letters might stand for something. The button apparently does nothing. Since switching functions can only happen by spinning one way, if you miss the one you wanted, you have to go through the whole array once more, spraying water out of every one of those holes.
WORST. SHOWER. CONTROLS. EVER.
2008-03-19
Must we really drive so fast on a narrow mountain road?
You know those stories you keep seeing filed under "miscellaneous" with titles like "35 tourists plunged to their deaths in some other country blablabla"?
Well now I get it. Took a bus ride in Spain - the roads are super narrow and winding, there's only a few feet between the road and certain death, and the driver is treating his bus like it's a sports car. I had white knuckles the first thirty minutes until I got desensitized to it.
2008-03-05
Best Blog I've Found This Year (So Far...)
The Odd Numbers blog by Zubin Jelveh. I find it similar in style to the winning formula of Freakonomics: a collection of tidbits of economic commentary about a variety of subjects, and the sometimes unexpected incentives that drive everyday trends. It's a bit American-centric, but still highly entertaining and informative. I just lost the last three hours reading the archives, so subscribe now, you'll thank me later!
2008-02-26
A Tip on Performing Geographic Price Discrimination
From: JP
To: Apple
Subject: Pro Tip
When doing geographic price discrimination, try not to spam the same email address with both mailings on the same day.
TomTom Improves the Wake-from-Standby Process
In February 2007, I left the following comment on a post about combined play/pause controls on the excellent History of the Button blog:
Jean-Philippe Daigle Says:
February 1st, 2007 at 8:51 pmThe problem with a combined start/stop button is that many devices fail to provide proper feedback that the keypress has registered.
If there’s significant lag between the keypress and the action it is supposed to initiate, and no immediate feedback, the frustrated user pushes again, thus reverting the state to whatever it was before the interaction began. Discrete start/stop buttons, on the other hand, are idempotent and can afford multiple presses.
Concrete examples (since you asked for some): This happens to me several times a week with my TomTom Go car-mounted GPS and the Motorola RAZR phone. Each of these devices has a single button for on/off, and requires holding it to invert the state of the device, but in both cases, there’s no feedback whatsoever for a few seconds.
Happily, more than a year after the TomTom Go 700 has been superceded by better models, TomTom is still showing commitment to its customers with updates! With the latest software upgrade, they've fixed this little issue. Now, instead of just sitting there silently during boot, the screen's backlight is powered on immediately while the unit wakes up. Granted, it's a subtle piece of feedback, but it works - I no longer power it off with an unnecessary second press.
2008-02-23
Performance Overhead of Non-Final Method Calls in Java
Working with developers who care deeply about application performance, you get around to having frequent interesting discussions about the subject. We end up reviewing every frequent temporary object allocation, scrutinizing every usage of a mutex in the fast-path for possible elimination, etc. Recently the topic was something really simple on the surface: people are afraid to call non-final instance methods, especially in situations where the method being called needs to be resolved to a particular superclass. Is this fear justified?
There is evidence and wisdom out there pointing to a non-trivial performance penalty of non-final method calls: articles like this one (PDF), my boss' repeated assertions, and the Java Platform Performance book, if I recall correctly.
Unfortunately (or fortunately?) I couldn't find, in a simple test, evidence to support these fears. I designed a test that performed a warm-up (to allow HotSpot to compile what it could after seeing how often I was calling specific methods), then used a System.nanoTime() call right before and after a ten-million iteration loop that just calls an "increment a counter" instance method on an object.
Test Cases
- There is a warmup period before any timing loop (it's also 10,000,000 calls).
- I'm not doing any object allocation in the timing loop, so the GC won't run and screw up our results.
- I ran the whole test suite 25 times and averaged the results.
- Just to be extra safe, I'm getting the counter value at the end of the 10,000,000-call loop to prevent any 'cleverness' from the compiler determining the end result is useless and not doing the call at all.
- The first two tests deal with trying a final counter incrementing method in SingleClass, as well as a non-final counter incrementing method. SingleClass is declared as final and cannot be subclassed.
- The second two test cases do the same as the first two, but calling all methods on SubClass.
The Results
The conclusion seems to be: it doesn't matter at all what you do. I see a few explanations:
- The common wisdom of there being a significant overhead to non-final method invocations may have been true in previous versions of the JVM, and modern JVMs may have levelled the playing field.
- My test was flawed in some way. (Doing a counter++ was so simple it got inlined?)
2008-02-19
Towards an Efficient Pancake-Serving Strategy in Office Environments
Background
I was invited to sit in on a "Social Committee Meeting" at work [Solace Systems - ze cool message routing company that allows me to pay the bills]. I provided some constructive criticism of last year's pancake breakfast by pointing out that although a delightful time was had by all, surely the quality of the food would have been even better if instead of thick store-bought pancake mix, we had prepared homemade batter for all the crêpes [if I recall correctly, it ended up being a mix of store / homemade, or perhaps it was all-store, I'm not 100% sure, but the dimensions of the final pancakes indicated the batter was likely a bit thick].
I was subsequently assigned the task of making the pancakes for all the engineering staff this year. Yay me and my big mouth.
Problem
After I expressed the opinion that the batter should be made fresh and cooked on the spot (just-in-time cooking), concerns were raised that it would be impossible to produce pancakes at an acceptable rate to feed all 30 or so expected attendees. Two options present themselves:
- Find a way to make pancakes fast enough with the single heating element available (let's say we are shooting for 60 pancakes in 20 minutes or so). This is hard because there is no possible parallelism.
- Find an acceptable way to preserve pre-cooked pancakes and reheat them in situ once at the office, without destroying their texture or flavour.
Test Procedure
jpdaigle@vitis:~$ make pancakes
make: *** No rule to make target `pancakes'. Stop.
This weekend, I endeavoured to measure the rate at which I could cook pancakes (evaluating the feasibility of option 1), and, should an acceptable rate prove unattainable, I would experiment with pancake reheating.
I used my usual batter recipe and a single well-seasoned pan at medium-high heat, starting to cook the first pancake at 13:15 EST on Sunday. I logged the time at which each pancake was completed and transferred to a holding plate.
I completed seven (7) pancakes in 13 minutes, for an average of 111 seconds per pancake. The graph above demonstrates that the output rate remained mostly constant over the course of the experiment, which I interpret to mean the pan had attained its nominal temperature before I started cooking the first pancake, and there were no noticeable speed gains to be had as time wore on.
At this rate, it would take nearly two hours to feed 30 engineers, assuming each desired two pancakes. Clearly, we had to consider Option 2.
I decided to eat three (3) pancakes on Sunday to establish the "fresh pancake" baseline, and refrigerate the other four (4) for consumption on Monday, to determine what they'd taste like after 24 hours, and a chill / reheat cycle. [Note: I am well aware that a better approach would have been to bake a fresh batch on the second day, so that it may be compared directly to the 24-hour-old batch instead of relying on memory, but I ran out of flour and could not purchase any more on Monday, as it was a holiday in Ontario and all the shops were closed. Even if this had worked, we'd still be comparing different batches of batter, with possible variations in the egg/milk/flour ratios that are hard to control for.]
Results and Conclusion
Day 2: Of the four (4) remaining pancakes, I reheated the first two (2) in a microwave to test the naive approach. The result, however, was disappointing: the pancakes came out warm, but too damp and mushy. They did not meet the high standards for what I'd feel comfortable serving to my coworkers.
The remaining two (2) pancakes were reheated in a very hot seasoned pan, about 15 seconds per side. I am pleased to report that although the final result is a pancake that is a bit drier than the original, it retained its taste and texture acceptably, and this method cuts the 111 seconds needed to cook a pancake down to 30 seconds to simply reheat it. It would allow us to feed 30 people in about a half hour, which points to a possible approach for the Solace pancake breakfast.
Future Work
Find how to accompany the food with good espresso; I don't have any proposals here.
2008-02-18
The Best Things in Life Are Free
I decided to go out and have some fun this weekend. I wanted to be active a bit, but didn't feel like driving all the way out to Kanata (KRP, ugh) just to get to the gym.
Earlier this week, a coworker was talking about snowshoeing, so the bug bit me - I hadn't gone snowshoeing yet this winter, and I resolved not to let the season end without going out at least once. On Saturday, the weather report showed -11C for the afternoon, so I figured it would be safe to go out on the river a bit and enjoy nature, as well as a bit of peace and quiet outdoors.
Most amazing weather all week:
I packed up my camera, some water, snowshoes (des raquettes, pour les francophones), and some warm clothing, and left home with no idea where exactly I was heading. I decided to start in Westboro and drive west on Richmond / Carling until I found an access to the river. Luckily, it didn't take long - I ended up parking in Britannia Park, and continued westward from there in the snow, on foot.
Ended up staying out until the sun started setting. I tested the ice a bit before venturing out, but it was thick, so no worries. Didn't cross paths with a whole lot of people, but the few I did meet were out hiking or skiing too, and quite friendly.
The weird thing about Ottawa is that the demographics really don't seem to be in my favour for meeting new people my age - Saturday was no exception; friendly people all around, but all in their 30s or 40s. I don't know where all the mid-twentysomethings are in this town.
2008-02-12
Reusable shopping bags are taking over the world!
(and that's a good thing)
The Globe and Mail on the worldwide phasing out of disposable plastic bags, praising the remarkable grassroots, bottom-up effort.
I went to Costco today (hence this post) to stock up on snacks for the office, and must say they deserve praise for coming around in the past year.
About a year ago, I was in a Costco warehouse, shopping with one of those tough plastic/nylon bags sold by Loblaws. A short while later, I was accosted by an employee from store security, who informed me it was prohibited to use these bags while shopping, and that I'd have to get a cart. (Ironically, Costco actually sells reusable nylon shopping bags.) None too pleased, I wrote to customer service, identifying myself as someone who often went in to pick up just a few items, and for whom using a huge cart really makes no sense. I asked if the distribution of transaction sizes might reveal more like myself, for whom it might be justified to provide an alternative to the large carts. Happily, they took me seriously and replied that the average transaction size justified offering only large carts:
Thank you for your recent inquiry through Costco.ca, in response, the
daily average transaction at Costco ranges from $130 to $150 which is
why we only have the large carts. We do appreciate the suggestion and
it has been sent to the appropriate management team for review and,
thank you again for taking the time to send this to us.[...]
The part about "been sent to the appropriate management team for review" sounds like typical corp-speak, but it was apparently true, for a year later...
Ahh, how nice it was today, when I decided to risk it and try again to shop with a Loblaws bag. I got to the register, declined the cashier's offer of a box, and she smiled warmly and said: "Ah! You've got a bag, even better!" Similar friendly attitude from the cart-inspection clerk at the exit.
Thanks, Costco, you got it right. Impressive.
2008-02-09
Westboro Market just died
In local Ottawa news, the Westboro Community Association's blog is reporting that Westboro Market has closed down.
(I took the picture a week before they announced the closure - I had no idea at the time)
This is a real loss for the community. Last year, Westboro Bakery, the lone bake shop in the neighbourhood, had to close its doors after seeing its rent raised to 3500$ a month. This year the still-young Westboro Market, which was the only source in the area for Art-Is-In bread, followed suit. Too bad, I really hope we don't get another sporting goods store.
2008-02-07
Signal to Noise: the tale of how the statsvn.org domain expired
It was really my fault, but I still blame Go Daddy :) Read on...
Go Daddy, probably the only domain registrar weird enough to make you think twice before opening one of their ads at work, tried to warn me by email that the statsvn.org domain was about to expire. In fact, they sent me 5 emails about it. Unfortunately, for reasons explained below, I had set a rule in Gmail to have emails from Go Daddy skip the inbox and get archived to a tag.
A few facts about the email I've received from them over the past year:
- Emails received from Go Daddy between April and December 2007: 74
- Legitimate emails warning of expiration or confirming a purchase: 3
- Quasi-"Spam" and promotional emails: 71
- Ratio of important emails to promotional ones: 0.0423
I think a ratio that incredibly low justifies having a rule to at least move those messages out of the way and defer reading to some later time. The statsvn.org domain expired on January 17, 2008, but kept resolving just fine for me, so I never noticed anything was wrong until I finally glanced at the 684 emails tagged "commercial" in my GMail account, sometime this afternoon. In a panic, I logged into the godaddy.com site to renew, only to discover that since my registration had expired, it had been removed from my admin panel. Crap.
I called up their customer service, and I'm happy to say this is where things started looking up: no long wait times, no Indian call centers with impossible-to-understand operators! After five minutes I spoke to José, who politely informed me Verisign had the domain in some sort of grace period pool, and I could get it back by paying an 80$ penalty, on top of the registration fee. He accepted a DIGG coupon code for 10% off too :)
Ka-ching. Renewed for two years, everything should be fixed in 72 hours. In this instance, due to the fees, it looks like the spam was profitable even if I never read a single line of it.
statsvn.org is the domain name for the statsvn project. The developer wiki is at svn.statsvn.org/statsvnwiki (DNS issues notwithstanding).
EDIT (2008-02-12): The domain and all the subdomain configuration has been restored, and the wiki is back up. (Even used it myself to copy-paste some command-line options when doing a StatSVN run yesterday.)
2008-02-05
Ant Tricks: how to find the SVN revision of a directory with Ant
Here's a neat little recipe I wrote when trying to get the current SVN revision of a checked-out project into an Ant property.
Why would you need to do this?
Well, for example, you might want Ant to get the revision number of the source going into the build it's making and use it to name the output directory it creates when deploying your load. (ie: deploy the built library to /projects/myproject/build_svnXXXX/) You might also want to echo that revision number into some resource file to implement a "--version" type of command line option in your application, etc.
Sample Ant Target
<target name="load-svn-revinfo" depends="init-stage1">
<property name="tmpfilename" value="tmpout.txt" />
<delete file="${tmpfilename}" failonerror="false" />
<exec executable="svn" dir="${basedir}/../" output="${tmpfilename}">
<arg line="info --xml --username ${svn.username} --password ${svn.password} ." />
</exec>
<xmlproperty file="${tmpfilename}" prefix="svnprops"/>
<delete file="${tmpfilename}" failonerror="false" />
<echo>REV IS: ${svnprops.info.entry(revision)}</echo>
</target>
How it Works
There are basically three steps:
- Run an "svn info --xml" on your project sandbox and store the result to a temp file.
- Load the temp file into an Ant <xmlproperty/>, with the prefix "svnprops", so we can refer to the revision later in our build script.
- Clean up the temp file.
Note that running "svn info --xml ." on your checkout directory will give you output like this:
C:\dev\eclipse_workspace\HEAD_solsuite>svn info --xml . |
Meaning that once that's loaded with <xmlproperty/>, we can refer to the SVN revision as ${svnprops.info.entry(revision)}. Pretty cool, huh?
2008-01-31
Testing my new 50mm f/1.8 lens and griping about the "Canadian Tax"
Frustrated by how difficult it is to take even passable handheld indoor pictures with the kit lens that comes with the Canon Rebel XTi (an EF-S 18-55mm f/3.5-5.6), tonight, on my way out from work, I decided to get Canon's 50mm f/1.8 EF lens. I didn't exactly splurge, at 120$ CAD, nevertheless I'm extremely impressed so far.
This captures a heckuva lot more light than the kit lens; I don't know why they don't package something like this with the camera, and sell you a cheap zoom lens later on if you need it...
What really gets my blood boiling though is the mysterious "Canadian Tax": the premium we pay for seemingly every imported product (even counting prices before any sales tax has been applied). It's all the more frustrating because no satisfying explanations have been offered: every time a retailer attempts to put forward a justification, it does so in condescending corporate-speak or advances arguments that are rapidly demolished by others in the know.
A few examples, starting with the very lens I bought tonight after shopping online and complaining about the local prices:
| Here in snowy Ontario | United States | |
| EF 50mm f/1.8 lens | 120 CAD at Henry's | 74.09 USD at Amazon.com (73.79 CAD) |
| 13" Macbook | 1249 CAD | 1099 USD (1094.60 CAD) |
| The excellent Code Complete book by Steve McConnell | 34.64 CAD at Amazon.ca | 29.99 USD at Amazon.com (29.87 CAD) |
Although, to be fair...
| Doctor's visit | 0 | Ha ha ha haa haa |
2008-01-28
Hiding .svn directories in the CruiseControl Status Page
If you've got a CruiseControl installation and you're anything like me, you won't be happy unless your entire CruiseControl setup is revision-controlled and lives in your subversion repository. (Here's a good article on how to get you started and auto-update CruiseControl's config.xml using bootstrappers.)
The Problem
There's a small problem, however, with your entire CC configuration living in source control, as you've realized if you've ever pulled up the status page and seen this:
The status page blindly slurps up every directory under /cruisecontrol/logs, including the .svn directory. Whoops. I can see a few options:
- Don't put the logs directory in source control, and remember to recreate it the next time we rebuild the machine.
- Do an svn export to deploy the CruiseControl setup on our build machine.
- Patch the status page code to not show the ".svn" entry.
I went with option 3.
The Patch (For CruiseControl 2.7.1, Binary Distribution)
Under $CC_INSTALL/webapps/cruisecontrol/, open the file index.jsp. It's a simple 4-line patch. Near the top, we will add 3 lines:
| final Date now = new Date(); |
Then, scroll down to line 460 and change it:
| else { |
Save, refresh the page to test your changes, and safely commit the new version:
Quick Note
Now, if we wanted to be really fancy and do the 100% solution, we'd fix the same thing on the individual project pages, in the left-hand panel where a drop-down menu allows navigating to other projects. To do this, however, we'd need to look at the ProjectNavigationTag source, and it's not in the binary CruiseControl distribution, so that's out of scope for today.
Western Digital My Book World Edition II Review
OK, that's a pretty retarded name, it should be called "WD 1TB NAS" or something. But anyway, this post exists to answer the question: how is it?
Shopping For a NAS
I recently started shooting in RAW mode and with every frame out of my DSLR taking ~9MB, I needed some safe storage options. My attention was drawn to the Western Digital My Book World Edition II (dear god the name!) because at 340$ CAD for a 500GB RAID-1 NAS device [or 1GB if configured as a spanning array], it's really cheap for what you get. I was almost put off by its dismal rating on Amazon (2 out of 5 stars), but from reading the reviews, it seems many are complaining about the poor sharing software, not the drive itself. [An aside: a hardware device with piss-poor bundled software? Gee, what a surprise! If you want to setup a streaming media server, just setup your own service on a real machine; that the masses would be crazy enough to expose a mostly closed machine, with upgrade availability at the vendor's discretion, to the public Internet forces upon me the sad realization of how little people understand or care about tech. Ahem. Revenons à nos moutons.]
The product page isn't particularly helpful, as it doesn't really tell you about the modes you can configure the device for, or the storage protocols it exposes.
Here's the info you need
- 2 disks, 500GB each. ~455GiB available in RAID-1 mode, double that in spanning mode.
- Comes configured in a single 1TB spanning volume. For RAID-1 mode, you need to switch the mode and let it reformat the drives, which takes a few hours. (I went to bed after 2.5 hours, I didn't get to see the process complete, but it was done the next day.)
- Exposed Protocols: Storage is accessible through CIFS / SMB only. In fact, nmap tells us the only ports open on it are 80 and 139.
Setup
You'll want to configure it to use static IP settings rather than the default (acquire an address through DHCP). The setup can be performed through a web interface and it's pretty simple. Googling for how to mount it under Linux will point you to a few mostly unhelpful, ill-informed, blind-leading-the-blind-style forum threads [though to be honest I didn't peruse many of them], so here's what works. They seem to use Samba with CIFS unix extensions with everything owned by UID/GID 33, so I had to mount with noperm to get write access as an unprivileged user on my box:
| mount -t cifs \ -o username=jp,password=,rw,uid=jp,noperm \ //192.168.1.104/PUBLIC ./wd |
Test
As an informal test, I generated a 100MiB file with dd and copied it to a Windows Server 2003 CIFS share and to the WD My Book's CIFS share, using time to measure real (wall) time. I'm only on a 100mbit switch, but I don't think the network is the bottleneck here:
- To W2K3 server's IDE disk: 34.8s (2.9 MiB/s)
- To WD My Book NAS: 23.4s (4.3 MiB/s)
Read speeds were very similar so I didn't include them. While not exactly blazing fast, it beats copying to other machines on the LAN, so it will do nicely as a storage box for RAW camera files. At that speed, you could probably even do HD video playback over the network, but I haven't tested that. There's an included disk with some sort of subscription service for remote access, and I have no desire to test that either.
All in all, don't let the negative Amazon comments spook you, it's a decent consumer-oriented storage box for the price.
2008-01-27
The Wake Up Apparatus
My colleagues wouldn't exactly describe me as an "early riser". Some spring out of bed, fully energized, at the first ring of their alarm - my boss, for example, I've caught bragging about his ability to be up at 5:30.
As for myself, I appreciate the value of redundancy. Here's my setup; alas, I still don't wake up on schedule 100% of the time. Maybe we need a fourth stimulus?
Sequence is:
07:15 Halogen Floodlight
07:30 Alarm 1
07:35 Alarm 2
PS: I'm not kidding.
2008-01-21
Oh baby, why don't you call? I'm here by the phone
Dear EVERY COMPANY EVER,
Why is it so hard, when you promise to call, to actually do it? Oh, you break this promise all the time, and you survive year after year and get away with it because each and every last one of your competitors is equally bad. We care about customer service, but, one might suppose, not enough for it to actually make a difference.
Off the top of my head, here's a list of those who have failed.
Bell Canada: You promised to call me within 72h after opening a ticket to make an appointment for a tech to come out and test my dry loop line. Took you five days, and you never made an appointment, he just showed up à l'improviste at 10:00 AM on a Saturday morning. Lucky I was home.
Starbucks Canada: I called you to get a quote for how much it would cost to supply beans, an automatic coffee machine, maintenance, etc for an office of 50 people. You promised to hand off my info to the Ottawa account manager, who'd call me right back. It's probably been a year. Still waiting.
Purolator: You lost a really expensive package headed for me a few years back. Over two weeks, promised 3 times to call me back with updates, never managed to do it even once without me calling you.
Enbridge / DirectEnergy: You assured me the repairman would call an hour before getting to my home, so I could leave work and head home to let him in. I must be getting wiser - I didn't believe it and stayed home from work. Good thing, too, as the phone never rang before the guy showed up.
Philip van Leeuwen: You guys take the cake, you did it to me on two separate transactions. 2006: sofa delivery, instructions to call 60 minutes prior. I got a call on my cell from the delivery guys, waiting in front of my apartment, when no one answered the door. Rushed home fast enough. 2008: table delivery, 10am-2pm window, instructions to call 60 minutes prior. So of course they showed up at 9:30 without calling.
Apple Canada: You actually called me back when you said you would. En français impeccable. <3 Apple.














