Archive for the ‘Coding’ Category

Wild Bug in Date Conversion Code

Thursday, June 23rd, 2011

bug.gif

We came across a very wild bug today with date conversions. Basically, the problem is taking an option's expiration in the form YYYYMMDD and seeing if that date falls on a weekend. If it does, then back it off to the Friday before the weekend. The original code I had made use of mktime()'s ability to compute the "day of the week" given the year, month and date:

  struct tm  when;
  // will this struct up with the date as we know it
  when.tm_year = aDate/10000;
  when.tm_mon = (aDate - (when.tm_year*10000))/100;
  when.tm_day = (aDate - (when.tm_year*10000) - (when.tm_mon*/100);
  // correct the values for the call to mktime()
  when.tm_year -= 1900;
  when.tm_mon -= 1;
  // now call mktime() and let it fill in when.tm_wday...
  mktime(&when);
  if (when.tm_wday == 0) {
    // it's a Sunday!
  }

what we were seeing was that the day of the week was all wrong. In fact, the year, month and date coming back from mktime() were being randomly scrambled. Very odd.

The solution was simple - zero out the struct before using it. Sounds simple. But you'd think the compiler would do this for you. Nope. it's uninitialized memory. Silly me.

The fix looks remarkably similar - save one line:

  struct tm  when;
  bzero(&when, sizeof(when));
  // will this struct up with the date as we know it
  when.tm_year = aDate/10000;
  when.tm_mon = (aDate - (when.tm_year*10000))/100;
  when.tm_day = (aDate - (when.tm_year*10000) - (when.tm_mon*/100);
  // correct the values for the call to mktime()
  when.tm_year -= 1900;
  when.tm_mon -= 1;
  // now call mktime() and let it fill in when.tm_wday...
  mktime(&when);
  if (when.tm_wday == 0) {
    // it's a Sunday!
  }

Successfully Stopping a ZeroMQ Receiver

Thursday, June 23rd, 2011

ZeroMQ

Late yesterday I realized that I had a nasty problem with the ZeroMQ receiver component in my ticker plant codebase. Basically, if the publisher stopped before the client did, then there would be no clean exit for the client as it'd be stuck in a ZeroMQ zmq::socket_t::recv() call, and there's no timeouts or interruptions from that guy. I hadn't figured this out because ticker plants are almost always ticking, and so it was easy to stop the clients. Also, stopping and starting a publisher is easy, but I'd never planned on the use case of the publisher shutting down and not coming back up, and the client needing to quit. Well... my mistake, to be sure.

Now we have to fix it.

The idea I came up with was nothing special - have every new zmq::socket_t bind to a unique inproc: URL so that there exists a "back door" to send it messages - quickly. I can then continue on as normal, but in my shutdown() code I can tell the thread to stop, and on the off-chance that the thread is in zmq::socket_t::recv(), I'll connect to that same inproc: URL and send it a zero-length message. This will cause it to break out of the recv() call, and then it'll detect that it's supposed to shutdown.

The code is pretty simple, but even there, it took a few times to get all the pieces of the inproc: connections working. In my initialization code I now have:

  // nope... so let's make a new socket for this guy
  mSocket = new zmq::socket_t(cContext, ZMQ_SUB);
  if (mSocket == NULL) {
    error = true;
    cLog.error("[initialize] couldn't create the ZMQ socket!");
  } else {
    // ...and subscribe to all the messages
    mSocket->setsockopt(ZMQ_SUBSCRIBE, "", 0);
    // we need to set this guy up properly
    mSocket->setsockopt(ZMQ_SNDBUF, &__sndbuf, sizeof(__sndbuf));
    mSocket->setsockopt(ZMQ_RCVBUF, &__rcvbuf, sizeof(__rcvbuf));
    mSocket->setsockopt(ZMQ_RATE, &__rate, sizeof(__rate));
    mSocket->setsockopt(ZMQ_RECOVERY_IVL_MSEC, &__rec, sizeof(__rec));
    // let's get a new, unique instance number for this socket
    uint32_t   inst = __sync_fetch_and_add(&cInstance, 1);
    char    name[80];
    snprintf(name, 79, "inproc://sock_%d", inst);
    mBailOutURL = name;
    // now let's
    mSocket->bind(name);
  }

after I set the socket options with the calls to setsockopt(), I then atomically increment a class ivar that holds the next socket instance number. This, put on the end of the URL makes it unique, and then I save this so that my shutdown() code knows who to talk to.

Finally, I bind() the socket to this inproc: URL. This is important because in the case of OpenPGM/ZeroMQ, it's a callt o connect() regardless if you're a sender or receiver. Here, with the inproc: transport, it matters. The receiver has to bind() and the transmitter, as we shall see, has to connect(). OK. Got that cleared up.

In my shutdown() code, I now have something like this:

  void ZMQReceiver::shutdown()
  {
    // first, see if we're still running, and shut it down
    if (isRunning()) {
      // first, tell the thread it's time to stop processing
      setTimeToDie(true);
 
      // next, make the ZMQ socket for the inproc: transport
      zmq::socket_t    bail(cContext, ZMQ_PUB);
      // ...and set him up properly
      static int64_t   __rate = 500000;
      static int64_t   __rec = 100;
      bail.setsockopt(ZMQ_RATE, &__rate, sizeof(__rate));
      bail.setsockopt(ZMQ_RECOVERY_IVL_MSEC, &__rec, sizeof(__rec));
      // connect to the right inproc: URL
      bail.connect(mBailOutURL.c_str());
      // make a ZMQ message to send this guy
      zmq::message_t  msg(0);
      // ...and WHOOSH! out it goes
      bail.send(msg);
 
      // finally, wait for the thread to stop
      join();
    }
    // next, clear out all the channels and shut down the socket
    clearChannels();
    // ...but make sure the socket is really dropped
    if (mSocket != NULL) {
      delete mSocket;
      mSocket = NULL;
    }
    // let's drop the conflation queue and all it holds
    if (mMessageQueue != NULL) {
      delete mMessageQueue;
      mMessageQueue = NULL;
    }
    // ...and clear out the commands to the socket
    mCommandQueue.clear();
  }

It's a little complex, but it's really worth it. We have a way to use the blocking recv() for efficiency, but we also have a way to shut it down. That's pretty nice.

GitHub for Mac is Released!

Wednesday, June 22nd, 2011

GitHub Source Hosting

I have to admit that git is an amazing source control system. It's what I have been looking for for a long time, and it fits perfectly into the way I write code. So when GitHub sprang up, I loved it! What a great place. You can do issue tracking, forking... it's amazing. Well... today they outdid themselves. They released a Mac git client: GitHub for Mac.

It is a beautiful git client for the Mac with all the features you'd expect, but the added bonus is that they have complete knowledge of the GitHub API v3, and it's integrated into the app. This means all the things that might be hard, or time-consuming can be made very simple and easy with the client app because it has inside knowledge of the "other side" - sitting on GitHub.

Traditional and GitHub. Amazing combination.

I'm not a huge Git GUI user, but this is my preferred tool for sure. Simply amazing.

Fleshing Out a Few New Features

Wednesday, June 22nd, 2011

Building Great Code

Today I've spent a lot of the day working on a little checklist of things to add to my Greek Engine. They are all related to the big new features I've added recently and I needed to flesh out the supporting features so that the new time and sales data was supported as a first class citizen in the app. This meant making sure I had a message cache in the service, and then persisting it properly, loading it on restart, allowing queries against it, etc. It's a lot of little things, but integrating it all into the app in a consistent way took a little bit of time.

But it was fun. It's times like this where the really hard part is done and I can start playing with it a little that makes the 13 hr days worth it.

Doing Lots of Good Work Today

Tuesday, June 21st, 2011

Building Great Code

Today I've been doing a lot of things that aren't really focused towards one goal as much as it's all about things that folks have been asking for recently, and it's been nice to be able to clear the decks of these things and pretty much bring the supporting things up to snuff.

The first thing I tackled was the request for rolling the logs. I've gotten a request that all apps at The Shop need to have daily logs, and roll them so they can be maintained/archived/etc. by simple shell commands, etc. It turns out that the log4cpp RollingFileAppender can do this, but it sets the rolling based on the size of the file. There's also a manual roll() method, but while this was a possibility, I wanted to see if I could do it a little cleaner.

So I went into the start-up scripts and saw that it really was easy to just copy the file with the addition of the date/time and then writing over the existing files with a simple message. This was really far simpler than adding the necessary code for the RollingFileAppender. So I did that. The result is something that works just wonderfully, and can be placed in a crontab to run anytime they want.

Mark one off the list.

The next item on my list was to make a simple pub/sub example in C++ using The Broker. This was a little harder as the natural mode of the code I have for The Broker is not to be this simplistic, and it took a little bit of work to expose the right things in a clean way to make it simple for others to make traditional pub/sub messaging work. The end result was very nice - you can simply choose to respond to all subscription requests with something, and then you have the ability to "publish" out data and all the registered clients will get it.

It's not reliable messaging and it's not going to take the place of JMS or Tibco, but given that their needs are at that level, this makes it very easy for people to use The Broker in a new and different mode. It really turned out nicely.

Two down.

The next issue was that when the finance model can't calculate the implied vols for an option trade, it's supposed to fall back to the last known good calculation for that instrument on that exchange. The idea being that the differences in the trade prices should be small, and therefore the implieds - if they can't be calculated, should be close.

Adding them wasn't hard, but it's adding a little more to the memory footprint of the app because we need a couple of doubles for each exchange for each instrument. Kind of unavoidable if we want to make access fast and lockless, but it's still got to be done.

Not bad, but not nearly as fun as the other two.

The final task was the creation of a 'flex queue' for the ZeroMQ transmitter. The problem was that there would be cases where I'd want to conflate the outgoing messages, and then other times, I'd want to queue them without conflation. I didn't want to make two versions of the class, so I made a simple pseudo-union of the two types of queues: conflating and non-conflating.

This was interesting in that the struct I made had all the interface elements the queue needed, and then I simply had a union for the pointers, of which I'd create one and then use it. This then allowed me to include a defaulted value in the constructor for whether or not we'd use a conflating queue. With this, it just drops into the existing code and works wonderfully.

In all, four nice additions to the codebase. Good day.

Base 2.1 is Out

Tuesday, June 21st, 2011

Base 2.0

This morning I noticed that Base 2.1 was out. It's a very nice SQLite3 database tool for the Mac with some really nice looking graphics and very good speed. I've been a paid user since v1.0, and seen it get better and better. I just like SQLite3 and think there's a lot of smarts in using that for CoreData. Just wish I had more time to mess with it.

Nice tool. Great update.

Google Chrome dev 14.0.797.0 is Out

Tuesday, June 21st, 2011

Google Chrome

This morning I noticed that Google Chrome dev 14.0.797.0 was out, so I updated to see what's new. It seems that there's a new V8 engine (3.4.4.0) as well as improved print performance and a few Mac-specific things with the text areas and voice over. Nice, but nothing really amazing at this point in the game. Sad to say, but the browser has pretty much stagnated - with the exception of HTML5 and JavaScript, it's pretty much the same things it was a year ago. Nice to see things mature, but it takes a little fun out of it when the major browsers are all really the same.

Adding More New Features to Greek Engine

Monday, June 20th, 2011

High-Tech Greek Engine

Today I spent a good bit of time adding a significant new feature to the Greek Engine that is needed for the next significant phase of it's rollout. This part takes the option trades and calculates a little bit about the implied values and then generates a "sales" message with a lot of interesting data. This is used by the systems the traders use to see what's happening at the time of each option sale, and so it's really quite useful.

There were a few issues with the code - things that needed to be cleaned up, but for the most part, it was in decent shape. But the problems started when I started up the server and saw the load that was generated by this addition. It was too heavyweight for the threads that were feeding it, and it was causing speed issues that it didn't have to.

So I decided it was time to spin off the processing to a new thread, in fact, the thread that was doing the sending downstream just needed to do a larger portion of the work. So I had to fix up a few things, and refactor a few classes, but in the end I have something that's far better than before - far cleaner and clearer, and at the same time, it's a lot faster.

Good work indeed.

Skitch 1.0.6 is Out – On the Mac App Store

Monday, June 20th, 2011

Skitch.jpg

This morning I saw that Skitch 1.0.6 was out, so I went to my Skitch app and hit "Check for Updates...". I was then told "You're on the latest version - 1.0.4". OK, something's not right. So I went and did a little digging. It seems that the free version is crippled now, and the good version I had was no longer available in that format, so I had to purchase it again for a "mere" $25. Even though, it said on the web site it'd be $10. Hmmm...

OK, I like Skitch, and I'd probably have bought it without a grumble if I'd read about it in some email from the Skitch crew, but that's not how it happened, and I can't help but feel a little miffed at the way it was done. No warning, I'm stuck on an old version and not getting updates. No upgrade path, no continued support. Kinda bites.

I'm sure I'll get over it. I'm still a huge fan, but this is liable to prompt me to send them a letter and say "Hey guys... not nice. Try harder next time."

Tough Day of Adding Features

Friday, June 17th, 2011

It's been a long, tough, day of adding in several features to my Greek Engine for my clients, and then adding in the next big phase - the time and sales data which is really just the option data at every sales event on the market. It's quite a bit, but it's not a quote feed, still... it needed to be hooked in and in doing that, I found a bunch of little problems most of them honest mistakes by the original coder, but I blame myself for not being more hands-on in the coding phase.

Well... I paid for it today.

I had to rewrite significant parts of the code - thankfully, there wasn't all that much to rewrite, but still - I needed to make significant structural changes to the code. It took all day, but it's finally in and stable, and I need to monitor it for a while to see how it goes.

I hope I'm nearing the end of these kinds of sessions with this codebase. I'd rather not have to un-make someone else's problems only to make my updates.