Archive for October, 2009

Flip4Mac WMV 2.3.0.14 is Finally Released with Snow Leopard Support

Friday, October 16th, 2009

Flip4Mac WMV 2.3.0.14 was finally released today with Snow Leopard support. It's been in beta for a while, and I've been using it, but it's nice to see the guys actually feel it's "done" and release a final version. I don't look at that much windows media, but it's always nice to know that I can, if I need to.

When it Rains, it Pours

Thursday, October 15th, 2009

This morning I was hoping to see a nice, stable, web app that I had to patch together last night. Instead, I had a crashing app that wasn't working at all. Crud.

It seems that the report updating thread - that worker thread that updates all the reports for new data arriving in the system, was dead. And after a restart, it died in only a few minutes. Not good.

So the first thing I did was to put the HashMap back into the code for the LRUCache which gave us the stability, but it was a ticking time-bomb. Around 2:00 this afternoon it was going to run into that same 12 GB limit and we were going to be in a mess of trouble. Not good, but I had no choice.

Once the HashMap was back in the code, I started looking for the fall-out of using the LRUCache. Because, in theory, there's no reason that the LRUCache should not have worked just like the HashMap - it's a Map, after all. It's just a question of removing some aged entries.

The code was telling me that once again, we had optimistic coding and the problems were not as easily removed as switching out one Map for another. The problems came about because the code assumed that everything was going to exist - no checks whatsoever. With the LRUCache not having some data that was once there, we had an easy NullPointerException. With no try/catch block on the thread, it simply died. Wonderful.

The changes were that horrible - basically just putting in the checks that should have been in the code in the first place, but the idea of not having something like a try/catch block on the Thread's run() method is just amazing.

Why?

Oh... I know. It's never going to fail.

I finally got something that stays up, looks like it's all OK, and most importantly, the memory footprint is stable. It's been running in NYC for a few hours and the memory is flattening out nicely. One issue was that the LRUCache was really only needed on the archive storage for the reports. The other HashMap was really just a mapping of the report description to the last report instance. That makes sense to leave as a HashMap as it won't be growing without bound like the archive will.

The only way to know is to find out what tomorrow will bring.

Blender 2.49b is Out

Thursday, October 15th, 2009

Blender 2.49b was released this morning and I had to get it. Yeah, it was all about fixes for the game engine part, but I still love it. It's one of the only places that still has a download link for the Irix OS. Cool.

Apple Performance Update 1.0 is on Software Update

Thursday, October 15th, 2009

There's been a problem with the 500GB drives in Unibody MacBook Pros where there's a hardware delay due to the drive and the machine not quite understanding the spin-down and spin-up cycles. Well... this is the second update I know of for the MBP to try and fix this. I haven't seen it, but I'll certainly update on the off-chance that I have seen it and just not noticed it. That would be a funny one.

Firefox 3.5.3 is Out

Thursday, October 15th, 2009

With another round of security and stability fixes Firefox 3.5.3 is out. Pretty standard stuff, just needed to update and we're done. Simple, but very effective. Use it every day.

The Hidden Gotchas of Dodgey Design

Wednesday, October 14th, 2009

I've been working on this new deployment of this app I inherited and today I was nailed with a design decision that really shouldn't have been in the code in the first place, but was, and it had an ripple-effect that was really quite spectacular.

The design decision was to save every generated report for the lifetime of the web app. This was done so that anytime during the day a difference report could be made (on the server) between any two points in time. The reason for these difference reports was to enable the client to essentially freeze the report and then track the changes to the frozen state as time progresses.

One might say that this was the job of the client code - face it, it's already getting the data - it just needs to hold on to one dataset and then difference the incoming set to the saved set. It'd be minimal coding, easy, but it wasn't done. Nope.

So... when we added a lot of fields to this release, each report is now much larger, and we've added the roll-ups by product which only adds to the data per report. What happened was that by 2:20 pm the memory usage of the Tomcat instance was at 12 GB! It was slugging through Garbage Collection and I had to restart it. That helped, but I had to get a solution, and fast.

I talked to the original author and he suggested an LRU Cache on the data and not hold all the results - only the last n that have been accessed. It turns out, the implementation of an LRU Cache was pretty simple. I added that in place of the HashMap data structures for the retention of the reports and it appeared to work just fine. I checked that things worked, and that was what I put into production for tomorrow.

This should help a lot.

Implementing a Least Recently Used Cache in Java – Slick

Wednesday, October 14th, 2009

I have to admit that I'm not impressed by Java a lot. It's just the level of familiarity I have with the language. It's just not that often that something really surprises me. So when it happens, it really blows me away. Today is one of those days.

I was trying to implement a Least Recently Used (LRU) Cache, and a co-worker said it would be easy. I doubted it, it's not like it's that easy to make one. But he Googled a few places, and when you base it on the Java LinkedHashMap, it really is easy:

package one.bkit.util;
 
/**
 * Java System-level Imports
 */
import java.util.*;
import java.util.Map.*;
 
/**
 * Superclass Imports
 */
 
/**
 * Class Imports
 */
 
/**
 * This class is a simple implementation a Map where only the last
 * recently used entries are going to stay in the map. You can use
 * the default size of 100, or you can give it a size. In either case,
 * every <tt>get()</tt> and <tt>put()</tt> are put through the test
 * the 'most recently used' filter. If the next <tt>put()</tt> pushes
 * one out of the map, then it wasn't in the most recently used.
 */
public class BKLRUCache<K, V> extends LinkedHashMap<K, V> {
 
    /**
     * This is the size of the cache. No more elements will be held
     * in this map than this. After this, the oldest goes to make room
     * for the newest.
     */
    private int             _maxEntries = 100;
 
    // this is the serial version tag for this class
    private static final long serialVersionUID = 20091014;
 
 
    /**
     * ----------------------------------------------------------
     *		Constructors
     * ----------------------------------------------------------
     */
    /**
     * The default constructor assumes a default maximum size of 100
     * elements such that <b>only</b> the most recently used 100 entries
     * will be maintained in the map. After that, the oldest is discarded
     * to make room for the newer entries.
     */
    public BKLRUCache() {
        this(100);
    }
 
 
    /**
     * The general form of the constructor takes the maximum size of the
     * LRU cache, and uses that as opposed to any default.
     */
    public BKLRUCache(int maxEntries) {
        // fix the size, keep things flat for speed, and use access order
        super(maxEntries + 1, 1, true);
        _maxEntries = maxEntries;
    }
 
 
    /**
     * This version of the constructor takes a map and populates this
     * map with up to 100 entries - actually, it'll hold the <b>last</b>
     * 100 entries of the iterator on the argument. It's doing the
     * <tt>putAll()</tt> on the argument, and the way this works, only
     * the last 100 are saved.
     */
    public BKLRUCache(Map<? extends K, ? extends V> m) {
        this(m, 100);
    }
 
 
    /**
     * This version of the constructor takes a map and populates this
     * map with up to maxEntries entries - actually, it'll hold the
     * <b>last</b> entries of the iterator on the argument. It's doing
     * the <tt>putAll()</tt> on the argument, and the way this works,
     * only the last 'n' are saved.
     */
    public BKLRUCache(Map<? extends K, ? extends V> m, int maxEntries) {
        this(maxEntries);
        putAll(m);
    }
 
 
    /**
     * The magic happens here as the Java LinkedHashMap has a method
     * that we can intercept and tell it to keep (or not) the oldest
     * entry in the map. This is where we look at the size and then
     * see if it's a keeper or not. Simple.
     */
    @Override
    protected boolean removeEldestEntry(Entry<K, V> eldest) {
        return (size() > _maxEntries);
    }
}

This is the kind of code I love to see: simple... elegent... compact. It does something very useful and it does it without a lot of grief. Amazing.

Days like this make me want to do more Java coding and learn more of the newest language additions. It might be nice.

iMovie 8.0.5 is on Software Update

Wednesday, October 14th, 2009

This morning I noticed an update to iMovie was out - with an interesting list of features:

  • Improved compatibility with camcorders using the iFrame video format
  • Improved compatibility with importing video captured on the iPod nano
  • Fixed problems with resizing the iMovie window during playback

looks like there was a bit of incompatibility on the importing fixed up this time. SOunds good to me.

Bumpy Rollout and Flex Licensing Issues

Tuesday, October 13th, 2009

Today was a rough day. Yesterday evening we rolled out new hardware for this application. Should have gone smoothly, but there were a few little glitches. Even so, it was all running and looking OK when I left last night and I had a good (but tired) feeling that things were going to be just fine.

Looking back, I have to giggle at my silliness.

Part of the rollout was a Flex component that I was given and needed to build. At the time, I was given the tools by the original author, and it all seemed to work. You can see it coming, can't you? Anyway, when I built things for this release, a few of the graphs had watermarks saying "Hey, this isn't licensed".

There was nearly a panic.

Did it work with the watermark? If not, then it's a rollback - but we've done hours worth of work, it'll take hours to get it all back. Nightmare! So I kept with my plan - push forward not slide back.

What I needed was to get the Flex license codes so I could build this app without the watermarks. Simple, right? Ha! Silly me. I had to chase things around to first find out if the watermarked graphs worked (they did), and that took the gun away from my head. It was ugly, but not inoperable.

Next, I got the install package, but the problem was that there was no directions for getting it installed on Linux. The public domain Flex compiler was on linux (my build/deployment platform) so I knew it had to work there, but how?

I ended up finding a place on the Adobe web site about the different locations for different OSs for this license.properties file. I put it in two of the locations on linux (just to be sure) and tried it again.

Sweet! It worked. I could just deploy the compiled SWF file to the web servers and be done. I showed the users and things were fine. Whew! That was nasty for a while.

[10/15] UPDATE: I just saw the PO for Flex Pro, which is what I need, and it's $699! Amazing. I can't believe it's that expensive. Maybe there's a ton of widgets that I don't see, but that seems like a lot for a few widgets as the rest is Open Source and works just fine. Well... it's what the customer will pay.

For the Children – Don’t be an Optimistic Coder

Monday, October 12th, 2009

For the love of the Children... or your favorite religion... don't be an optimistic coder. That's the worst thing you can possibly be. This evening I've been struggling with the rollout of a new application and hitting a problem that defied explanation for at least two hours. This wasn't the only problem I had this evening, it was just the one that delayed me the most.

To start off, I was in the middle of the roll-out (London done, ready to do NYC) when I got a little "prairie dog" from my manager: "Hey Bob, can you hold off on the roll-out for a bit. I just want to check on something." Well... sure... I was 4 mins until the time I was to do the second of three phases of the roll-out, and somethings were already done from an infrastructural point of view, but sure, I'd hold off.

So I held.

For 45 mins.

Then he said "OK, go ahead." Nice guy, but really... the time to say "Hold off" is before I start the roll-out, not between phases I and II. It's a little bit of a problem when you do it that way. Since I didn't have control of the DNS entries, I was already at a point that rolling back phase I was going to be hard, so what's up? Never found out, but that's OK. We went ahead with it.

Then I got to the problem that held me up for a few hours.

I'm not one to give up easily. In fact, for a roll-out, I can't remember ever backing it out as opposed to fixing the issues right then and there. So I had to figure out why two of the four boxes in NYC were giving us grief. I was able to skip it and roll-out Chicago, but I came back to the problem boxes soon enough and had to face the music. It was nasty.

I looked at the evidence in the logs and it was as if the code simply stopped. It did one request, started another and that was it. Dead. No crash... no core... just stopped.

We tried network issues, DNS resolution issues... everything that might be a problem. In the end, I was just thinking of all the steps the code was doing and the memory popped into my head. I increased the memory on the JVM, and BINGO! It worked.

So here's the thing I can't stand about production coding: Optimistic Coders. The original coder of this little app had used a try/catch block in the code and 'swallowed' the Exceptions. He didn't think they'd ever be needed, I guess. Well... he was wrong. Had I been able to see a Java OutOfMemory exception, this would have held me up for about 2 mins and I'd never have wondered what was wrong - it would have been telling me what was wrong.

No, by hiding the true cause, this coder has hurt the reputation of Java, the developers in the group, and certainly himself. It's sad that the JVM can't take an arg that says "up to the limit of the box" for memory usage. But it can't. You have to "size" the apps. So be it. But when you assume that everything is going to be OK, and never check return values, never check to see if the thing you asked to create was, in fact, created, then you leave yourself open to all kinds of problems. All kinds.

It's over now, but I've lived through this so many times, I don't even bother trying to educate the unaware. I'll say something, in passing, and if he's interested in really understanding his problems, he'll ask. But I'll bet you he won't. If he was interested in doing a good job, then he'd have thought of it already. But he hasn't. He'll be like this as long as he's coding. Too bad.