Archive for the ‘Coding’ Category

Creating a Solid, Reliable C++ Wrapper for hiredis Library

Tuesday, October 25th, 2011

Redis Database

Most of today has been spent trying to get my simple C++ wrapper around the hiredis C library for redis working in a way that allows for a significantly more robust usage pattern than I originally had. Specifically, all was fine until I shut off the redis server, and then my client would try to recover and reconnect and end up dumping core. The problems are only made worse by the fact that I really had no support docs on the hiredis site - only the source code, which is optimistic in the extreme. No argument checks, etc. make it ripe for a problem if it's not used exactly right.

Clearly, I wasn't using it exactly right, and those misusage patterns were what was causing the code dumps. So the first thing was to track down what I was doing wrong, and that meant that I really needed to become much more familiar with the hiredis source code. To be fair, it's a decent open source library, but it's missing so much that would have added so little to the runtime load and would have made it far more robust to the kinds of misusage patterns I had in place. After all, my code worked, so it's not that it was totally wrong, it's just that when things started to go badly, the things that you needed to do become far more important than when things are going well.

For example, if I wanted to send multiple commands to the redis server at once, you can run several redisAppendCommand() calls, but each really needs to be checked for it's return value. This isn't clear in the code, but it's very important in the actual system. Then there's the calls to redisGetReply() - typically one for each call to redisAppendCommand() - but not always. Again, you need to check for the critical REDIS_ERR_IO error that indicates that the redis context (connection object) is now so far gone that it has to be abandoned.

Then there's the reconnection logic. It's not horrible, but you have to be careful that you don't pass in any NULLs. There simply is no checking on the hiredis code to ensure that NULL arguments are skipped. It's simple to do, but it's not there - not at all.

In the end, I got something working, but it was hours of code dissection and gdb work to figure out what was going wrong and what needed to be done to handle the disconnected server and then the proper reconnection. Not fun, and several times I was wondering if it just wouldn't be easier to write my own as it's all TCP/telnet based anyway… but I kept going and in the end I have something that's reliable and solid. But it was nasty to get here.

Rounding Can Really Be a Pain in the Rump

Tuesday, October 25th, 2011

bug.gif

This morning I had a funny little bug in the Greek Engine that was really a hold-over from my Ticker Plants, regarding the creation of the security ID - the 128-bit version of the complete instrument description for use in maps, keys, etc. The problem was that the exchange codecs were correct in their work, it was the creation of the security ID that was at fault, and I needed to dig there to find the solution.

Basically, I pack the components of the instrument definition into a 128-bit unsigned integer, and to so this efficiently, I need to have a pointer that points to where the next component needs to be "dropped in". When I got to the strike, which was passed in as a double, I had the code:

  // finally, slam down the strike
  *((uint32_t *)ptr) = htonl((uint32_t)(aStrike * 1000));
  // swap the network order bytes to host order
  byteSwap();

and because of the (aStrike * 1000), I was getting 64.099 when I should have been getting 64.10, among other rounding errors. What I needed to do was pretty simple, but essential to get the right answer:

  // finally, slam down the strike
  *((uint32_t *)ptr) = htonl((uint32_t)(aStrike * 1000.0 + 0.5));
  // swap the network order bytes to host order
  byteSwap();

and with that, we got the right numbers. We even got the right thousandths place in the case of 8.125, for example. I'm sure there was partly the need to cast the 1000 into a double, but the additional movement by a half was the thing that brought it home.

Now we're OK.

Getting C++ Constructors Right is Vitally Important

Monday, October 24th, 2011

bug.gif

I ran into a problem that completely reinforces my belief that coding standards are a very good thing. And I was the culprit here - but only because I missed it, not by choice. What I had was a constructor for a Dividends set - basically dates and values in a table that needs to be treated as a single unit. The copy constructor for the instance looked like this:

  Dividends::Dividends( const Dividends & anOther )
  {
    // let the '=' operator do all the heavy lifting
    this->operator=((Dividends &)anOther);
  }

and the operator=() method looked like this:

  Dividends & Dividends::operator=( Dividends & anOther )
  {
    if (this != & anOther) {
      boost::detail::spinlock::scoped_lock   lock(mDivsMutex);
      mSetName = anOther.mSetName;
      mSecurityKey = anOther.mSecurityKey;
      mDivs = anOther.mDivs;
      mUpdateTimestamp = anOther.mUpdateTimestamp;
    }
    return *this;
  }

Now the trick here is to realize that the Boost spin lock is really just an atomic integer that they wrap with CAS operations. It's good, but it really needs to be initialized properly or it's not going to function well. What I'm doing in the copy constructor isn't wrong in the sense that it's logic is wrong, but the implementation is horrible.

When I saw this, it was clear to me what the bug was: the spin lock wasn't initialized properly, and the use of it in the operator=() method was locking the thread. Bad news. The solution was simple:

  Dividends::Dividends( const Dividends & anOther ) :
      mSetName(anOther.mSetName),
      mSecurityKey(anOther.mSecurityKey),
      mDivs(anOther.mDivs),
      mDivsMutex(),
      mUpdateTimestamp(anOther.mUpdateTimestamp)
  {
    // the initialized values do everything I need
  }

and the advantages are clear: since we're constructing a new instance, locking the new instance isn't necessary - no one knows it's there. Also, we properly initialize the mutex, and that's everything in this problem.

Standards. Get them. Live with them.

Breaking Out Fundamental Data for Greek Engine

Monday, October 24th, 2011

High-Tech Greek Engine

This morning we realized that some of the fundamental data we are using in the Greek Engine is not fixed for each security, but in fact, is dependent on the prime broker for that trade. This means that we needed to take that piece of data out of the security definitions table, and make it a separate data table, with set names, and all that noise, so that we could define the right rate in the profiles.

It's a complicated way of saying we took what we believed to be a dependent variable in the Greek Engine and made it independent. The upshot of that is that we needed to be able to handle data source updates as well, and that means threading this new independent variable's updating scheme through out the code. Not horrible, but it takes time to do it right and update all the classes where the control logic needs to flow.

In the end, I wanted to get this done before lunch, and I just made it. Nicely done, as the last time I did this it took me all day.

Finally Figured Out Nasty TBB/Uninitialized/Locking Bug

Friday, October 21st, 2011

bug.gif

Today my co-worker and I finally figured out the last, nasty bug in the Greek Engine that I've been working on for quite a while, and it's brought to a close a stage in my life that brings with it a lot more questions than answers. I've been working on this project for about six months, and while that's not very long for a project of this type, it's a long time to be getting a lot of grief from upper management about the time this project is taking, and the fact that it's not already in production.

I'm no idiot, I know that the finance industry is focused on What have you done for me today?, but when I'm asked to build something like this Greek Engine, and it's clear that it's not a four week project, then it's tough to sit here and take the accusations of incompetence and neglect when what I'm building is for the benefit of the name callers. I'm thrown back to the Little Red Hen: Who will help me back the bread?

In the end, it doesn't really matter because I did this for me, and not for them. I choose to not deliver crap, and they are the hapless beneficiaries of my morality. It's not something I'm necessarily proud of, but it's what I've come to see as the way things often are. I make a choice, and for the most part, there are detractors, and many of those detractors are in fact beneficiaries of my work. I do the work under their critical and harassing eye, word, and act, and in the end, they are the ultimate winners in this game.

Which, of course, isn't true at all, is it? They don't really win, because they don't have the ability to do what I've done, and they probably don't even have the ability to maintain the work I've started. But they benefit because they get to use the software I've written, and as long as I'm willing to allow them to play their sad, little role, they believe themselves to be my master.

But they aren't.

And it's not even close.

But today I've finished the last major problem on this project. It's now going to be a bunch of little features that are pretty easy to put in the code. Nothing major, and there's no real performance issues to deal with. It's pretty much done. I can sit back and look at the work I've done and smile. It's amazing work, really. I never thought it'd come together in six months, but it has. That's an impressive delivery schedule in my book.

And that's the only one that matters.

Google Chrome dev 16.0.912.4 is Out

Friday, October 21st, 2011

This morning I saw that Google Chrome dev 16.0.912.4 was out, and includes the new V8 engine 3.6.6.5 as well as quite a few nice Mac improvements including OpenGL. It's getting faster on the redraw, that's for sure, so I'm happy about that. Keep them coming, guys!

Google Chrome dev 16.0.904.0 is Out

Tuesday, October 11th, 2011

This morning I saw that Google Chrome dev 16.0.904.0 was out, and there were not a boatload of happy folks about it. Seems there's a recurring theme of not working with twitter.com, and there's a good number of folks that are plenty miffed about it. They changed quite a few things, and it riled the masses. So it goes, hopefully, they'll have it figured out soon.

OK, PostgreSQL 9.1 is just COOL!

Monday, October 10th, 2011

PostgreSQL.jpg

OK, so I ran into what I thought was a bug in a user-defined PostgreSQL function regarding the holiday date for today. It's a Bank Holiday, but it's not a Market Holiday. I was able to prove this and fix it (temporarily) by changing the status of today's date:

  UPDATE calendar
  SET bank_holiday=TRUE
  WHERE calendar_date='2011-10-10';

and then the function I was counting on for telling me if today is a holiday started working.

So I knew the problem. But how to fix it? Well… it wasn't clear from the psql command-line how to do just that. I did a lot of googling to try and find out how to list functions, create functions, etc., and in the end, as luck would have it, PostgreSQL itself had the answer: \ef get_market_hours_for_date

The format is 'e' for edit, and 'f' for function, and then the name. If you just have the '\e', then it pops out into your EDITOR of choice for the last SQL command that was executed. If you give it the 'f' and a name, it'll pop you into your EDITOR and then let you edit the function.

Very nice!

These are the kinds of tools I'd expect from a commercial vendor, but I suppose, this is also what I'd want if I were working on PostgreSQL databases all day. I'm just really surprised and happy that these developers are thinking along the same lines. It's a great feeling to use such a fantastic database for my work - Mac and linux. It's nice to see the progress in time as well. It's really coming along.

Once Again, an Important Realization

Thursday, October 6th, 2011

This morning, as I was getting ready, I realized that I was really worrying far too much about what was happening at work. In a technology all-hands meeting yesterday, the CTO presented the status and plans for a bunch of projects that are happening in the group. In fact, I think he hit on everyone that's more than a couple of days long - it was pretty exhaustive. So when I heard there that several projects didn't include the work I was doing - even though I was told my work was critical to these efforts, I got upset. Really upset.

If I'm working 13 hour days for this project, and it's not critical, what am I killing myself for? What's the rush? Why work so hard? No, I was told that this work I was doing was fundamentally important to the effort, and what's why I've been working this way. In short, I've been a Good Team Player - internalizing the external needs of the Team even though they are painful for me.

But in the show this morning I realized that there's no reason for any of this worry and concern. I'm giving it everything I can, and if it's not enough, then they need to replace me. If they think I'm doing a decent job, then I think things are just fine. After all, this is the place where it's expected that everyone be extraordinary (got this in my last review).

So I realized in the shower that there's no reason to get upset. I've been angry at management for quite a while, and in the end, the fact that they haven't fired me, or moved me onto a different project, means that they must think I'm "meeting expectations", and by their own definition, delivering extraordinary results.

I know they don't think this, but I'm tired that once again it seems that I've forgotten the most important lesson of working in a group - do your best, and if that's not good enough, then it's time to move on.

I'm ready to make them make that call.

BBEdit 10.1 is Out

Wednesday, October 5th, 2011

BBEdit.jpg

Just got a tweet that BBEdit 10.1 was out with a few interesting new features. There are several that sound interesting, and they're doing a bang-up job of getting the word out on twitter and YouTube about the speed of the search and replace, and the new features. It's just that I'm not doing a ton of Mac work right now, and so I haven't had a lot of time to mess with these features, but I'll get to it. Just a matter of time.

I'm still waiting to see them put in the vanishing Lion scrollbars, as that would be fantastic in my opinion. One of the singularly nicest additions in Lion are the vanishing scroll bars. They allow you to tell what you need to know, when you need to know it - but get out of your way when you don't. Very slick.

So it's downloaded and running - just need a little time to play with it.