Perian 1.1.4 is Out

July 30th, 2009

Perian.jpg

This morning, as I was finishing the re-build of my laptop, I got a notice from Perian that 1.1.4 was out, and so I updated that right away. Perian is the QuickTime plug-in that allows it to play a ton of additional file types, and since I still get a lot of media from family and friends that was created on PCs, this is a really nice thing to have.

Super nice thing to have.

My Drive is Dead – Long Live My Drive

July 29th, 2009

MacBookPro17.jpg

This morning I had a horrible feeling as my MacBook Pro had that annoying little "chirping" sound again. About every second for 10 or 20 seconds a little "chirp" came from the left-hand side of the laptop. Not good. This has happened on and off for a while now, and I just figured it was some odd software state, and when it didn't stop, and the apps stopped being responsive, I decided to reboot and clear it up.

Not bloody likely.

It wouldn't reboot. Not at all. Nothing. The machine would startup, and the "checking disk" would spin, but I'd never get the login screen, and I knew then that the culprit was the drive. At that point, it was clear that my drive was on the edge of death, if not already over the edge. So I shut the box off and let it sit for a while. I had a lot of work to do today, so I needed to get to it.

After about 30 mins., I tried again. It appeared to boot, and I thought "Holy Cow! What a lucky break!" But after only a few minutes, it was clear that it wasn't OK, in fact, it was really in trouble. Bad news. Thankfully, I had TimeMachine, and that was going to cover all the data I had on the box. Good to have that backup.

No, the problem was How to get a new drive? I called the Apple Store in Oak Brook, the closest one to my house, and asked them "Hey, let's say my drive is dead, do you have one in stock to replace it with?" - they diverted my to Apple Care. I can understand that, so I was patient and dealt with that guy, who agreed that it was a drive, and to have me get to an Apple Store.

So I called back the Apple Store in Oak Brook, and told them of my conversation with Apple Care. Again, the "best" they could do is to say I had to bring it in and then they can tell me if they have what is needed in stock. Arrgh. OK, I can see the logic here, most people aren't going to be able to ask a question, and then that makes Apple look bad when they say they have the part, and that's not the part that's needed. OK, not good, but OK.

So I make a Genius Bar appointment and go to the Oak Brook Apple Store.

The Genius there agreed on the assessment, and said that if they had the drive in stock they could replace it right then. So back into the "bowels" of the Store she went.

I waited.

She returned to say that no, they didn't have a drive to put in my laptop. She could order one and it'd take two days to get a replacement.

WHAT!?

I asked her to check the other stores in the area - maybe one of them had a drive. SHe called one store - no good. Didn't call any others. Clearly, I'm guessing that she wasn't able to get this level of information from anyone. She did say, however, that the Unibody MacBook Pros were designed to have user-serviceable drives. I asked her how, and she explained that by removing the screws on the bottom, the drive is easily accessible.

I decided to try a new drive myself. I got directions from Liza for how to get to Fry's from Oak Brook, and she helped out a lot. I got a Seagate 500GB 7200rpm drive - the same drive that is in the new 17-inch MacBook Pros, and went home to install it.

The screws are small, that's for sure, but they are almost all just small phillips-head screws. The exception to this are the "posts" on the side of the drive to hold it in place once in the machine. These look like very small torx drives. But since they were posts, a pair of pliers worked very nicely.

I got the drive in, had to use the restore disks for 10.5.6 as the 10.5 disks didn't have the hardware support that was needed for this "Early 2009" machine. Still, after about 30 mins I had OS X installed and was pulling in the accounts and files from the TimeMachine drive. I had to let it run overnight as it was time to get some sleep, but I had a good feeling that in the morning I'd be able to finish it all up and be back at work with a functioning laptop.

Adding Transactions to a Servlet-Based System

July 29th, 2009

WebDevel.jpg

Today I had the difficult task of trying to add in transactional integrity to a web system where the data is coming in as posts to the web server. If each post was a transaction, that wouldn't be so bad, but if I needed to have transactional integrity over multiple posts, then we get into a lot of trouble. Face it, web servers aren't noted for their state-maintenance - that's something you add on top of the web server in order to create the illusion of saved state for the user.

But in this case, we had one program feeding another. The sender wasn't passing in real markers for the beginning and end of a transaction, and that was the first thing that needed to change. We then needed to do something with this information, so I added that in. Now I had a place to handle the meat of starting and ending a transaction - but I needed to know what to put there.

The next problem I attacked was a little simpler, the market data service wasn't handling the blocks of data in a unit. Rather, as it was parsing data, it was sending it to it's cache. This would allow for inconsistent data as the instrument prices move but the greeks were in a buffer until the entire block was read. Also, the market data cache had no locking on it. So I added the locking and the buffering so that the market data was "clean" for each block.

But that still didn't solve the real problem - how to put multiple blocks in a transaction?

After thinking about all the alternatives, I came to realize that the only good way to do this is to have the sender "mark" each block of a transaction - including the BEGIN and END, so that the receiver can buffer the data by transactionID, and then release all that data and update the reports on the END. So I needed to figure out a way to get these transactionIDs.

From the UUID work I've done in the past, the IP address turned into a long was a good start. I didn't need to add in the time, as I wanted to have a transactionID per sequence, and not per transaction. So no need for the time. I did add in a simple three-digit sequence number on top of the IP address, and that should do it just fine.

Now the transactions needed to be tagged with this number. That meant modifying the payload format. Not something I was fond of doing, but it could not be helped. Did that, and decoded it on the receiver (web) side. Then I had to modify the buffering of the market data and the greeks to buffer by transactionID. I had to thread the transactionID into the code - passing it from the decoding through all the method calls all the way to the market data methods and greek cache methods. It wasn't more than three levels, but it required a ton of changes to the unit tests.

I then had the transactionID to the right places. I added that to the buffering in the market data and greeks cache, and then was ready to update the way the update events were sent. Previously, after each update of a block, the values would be recalculated. This almost guarantee problems with updates as the values would be recalculated within a "transaction". Bad. So I changed all that to only update if there was no transaction active - or at the end of a transaction.

The results are really impressive, but I want to do more testing tomorrow. It was really pretty simple once I had decided the best approach.

VelaClock 2.1.14 is Out

July 27th, 2009

VelaClock.gif

This morning I noticed that VelaClock 2.1.14 was released and the sum total of the release notes for this guy was:

  • Version 2.1.14: Updated Daylight Saving Time rules for Bangladesh.

and while I don't have a lot of need for knowing the time in Bangladesh, it's nice to know that should the need arise, I've got the tool to help me know the time.

Honestly, it's an invaluable tool for looking at the time in a lot of timezones. It's been very helpful more times than I can remember.

Miro 2.5 is Out

July 24th, 2009

miro.jpg

I'm still a bigger fan of the Hulu Desktop, but for the open source crowd, I'm guessing that Miro is the preferred choice as it's got the blessing of that organization. It's a sharp looking player, there's no doubt. And I really like the way it works - downloading without you having to get involved in the process... it's just the content that I'm not a huge fan of. I was looking for a place to watch House, M.D. and Hulu Desktop has it with limited commercial interruptions. Kinda hard to beat that.

But I like to see what Miro has to offer, certainly with an upgrade such as this.

Hammering Away Until the Rock Breaks

July 23rd, 2009

cubeLifeView.gif

If someone asked me what I felt was the most important thing to have to be a successful developer, I'd say it was determination. I was beating my head against these production configuration problems today and when I finally got them figured out, a new problem of a JavaScript menu bar popped up to bang at until I got it working.

In the end, the JavaScript menu bar I was looking at didn't really work as nicely as I'd have hoped. It worked, but the style was just too different from what we'd been using. So I re-organized the menus and that gave me the room I needed to make the page render nicely.

I'm pooped. There's not doubt about it. But as with all the other things I've been tackling lately, it's about not giving up. Working and working at it from different angles, from different ideas, to come up with some little crack that you can exploit to get the system to do what you want. It's just plain effort.

Digging into Noisy Data

July 22nd, 2009

cubeLifeView.gif

I've been digging into this problem of 'noisy' data coming out of one of the systems I've inherited here, and at first I thought it was a problem of loss of significance due to subtraction, but that turned out to be part, but not all of the problem.

Today I was digging again, trying to find out what was possibly causing this. I was looking at trade flow... and greeks being sent in... nothing seemed to explain it. I talked to the original developer of the system for a while and together we didn't some up with anything.

I left thinking that the best I was going to do was to shotgun the problem and hope I hit something that might be close enough to the problem to point out the solution.

I sat down and started to look at the code again, and then it hit me. At least I think it hit me. I have a very plausible reason in mind, but in order to know for certain, I'm going to have to reconfigure some machines and run them tomorrow.

Basically, I think we're getting into a situation where the multitude of portfolios are feeding data into a single collector for P/L calculations. The problem might be that because several of these portfolios are normalized to the same contract, we're get an increased feed rate on that normalizing contract, and that is upsetting the calculations.

My limited understanding of the messaging of data might be off. That's why I need the isolation test. If the data from my test is smooth, and the data in Test and Production is noisy, then we'll know that we have a solution to the problem. The wrinkle here is that this solution is going to mean that we need to have a lot more hardware to run these portfolios than originally thought.

We'll have to wait and see tomorrow.

Utter Shock and Amazement

July 21st, 2009

cubeLifeView.gif

Today has been spent primarily on getting the PRIVMSG capability working on this custom-developed chat system. Because of the nature of the system, that is not allowing private chats, it was a lot more difficult than it needed to be. While I might have done things differently in the implementation, I wasn't involved and this system is in place and there's very little interest in really looking at this critically. It's "done", it "works", let it go.

I had to work with what I had.

That included the sum total of the code. It was a combination of C#, Python and assorted scripts and was virtually undocumented. It was a mess. But as far as messes go, it was something that I could dig into and get a few hints.

My primary debugging tool was the log of the socket data coming from the IRC server. It was literally invaluable. In the end, this is the interchange I discovered I needed to use in order to get person-to-person chatting, and therefore code-to-person chatting, working.

First, my code had to issue a special command to a particular "Overlord" bot that controlled the users on the IRC server. This in and of itself was interesting. They chose not to implement the rules in the server, but rather in a Bot that existed alongside the server.

When I send the appropriate command to this bot, I need to include the nick of the user I want to talk to. The Overlord then creates a channel just for the two of us with a special prefix, and the two user's names separated by a special character. Both users then get INVITEs to this new channel.

I have to wait for the INVITE, parse the channel invitation into the two user names, see which one is me, and which one is the "other guy", and then cache this data so that when I want to chat to the particular user, I can look up the special channel for this guy, and chat there, instead.

There were a ton of wrinkles with this scheme. First, because the process is asynchronous, I have to buffer my chats to this person if I need to create this channel. That is a pain, but doable with a little thought. Once I get the INVITE, I simply see if I have any buffered messages for this guy, and if I do, then I send them in order to the (newly JOINed) channel and we're back up to date.

Another one was the reconnection scheme - I simply took the point of view that on reconnection we'll do the minimum and each operation will ensure that everything is set up for that operation. It works, but it might be doing a little more "lazy" set-up than a different approach that would cache the channels, etc.

I have to say that everyone I've talked to in this place about these technical details is amazed that it has been done this way. The simplest way would have been to log everything in the server. Period. Database or flat files, or MySQL (combination of the two) would have worked. Then add in a simple authentication method on the server and you're done. Leave private chats as-is, but log them. Done.

It wasn't done this way, and I'm not sure what's going to happen in the long run. I've got this working, and that's the most important thing.

Who’s Really Keeping an Eye on This?

July 20th, 2009

cubeLifeView.gif

I've spent the day working on getting a decent chat interface into a custom-developed chat server that a vendor wrote for us in response to the compliance regulations. I certainly am no stranger to this, having worked with MindAlign in a previous position. These are all chat systems where the logging and authentication is such that you can't spoof being someone you're not, and all conversations are logged. It makes sense for a place moving money.

Problem is, the system we're working with here (which can remain nameless) is really pretty horrible. First, there's no documentation on the protocol at all. None. Zippo. There was nothing in the code either. I could not find a thing to help me.

Thankfully, someone else had been working on this and realized that there was an XML file for the client that had what was needed. Basically, a bot would send a challenge PRIVMSG and you had to respond with the proper response PRIVMSG to this bot. If not, the bot would kick you off the server. Effective, if a little trivial. There's no server-level authorization so that's a hole, and there's no changing of these challenge/response phrases so that's not very secure either.

But after this is done, you can send messages to IRC channels without any modification of an IRC client. Pretty easy. Sending PRIVMSGs is another thing entirely, and I didn't get this solved today. Hopefully tomorrow.

But Boy! would some documentation have really helped.

There seems to have been no one at the time asking for this. I can't imagine what they were thinking.

Rough Deployments Getting a Little Easier

July 20th, 2009

cubeLifeView.gif

This afternoon I had to deploy an inherited app again, and this time it was a little smoother, but the fact that database changes made in one site aren't also done to another really bit me in the behind.

I had asked one of the DBAs to build this stored proc for me, and he did a great job. What I failed to realize is that he stopped right there. He didn't put it on the London copy of the same database, assuming, I guess, that if I'd wanted that, I'd have asked for it.

Silly me.

Well... it was a little harried and hurried to get things in place, but in the end I put the stored procs where they needed to be. Lesson learned, Bob... make sure to do it yourself.