Archive for June, 2011

Adium 1.4.3b1 is Out

Monday, June 27th, 2011

Adium.jpg

This morning I got a tweet from the Adium developers that 1.4.2b1 was out with some of the "lost" MSN features restored. It's not a surprise, with 1.4.2 taking a few away, it's not at all surprising to see them respond quickly with a new release. I was a little surprised that they added in the Facebook connectivity, and with a web page authentication. Interesting, but a little odd. I'm glad I'm not a big Facebook fan. Kinda creepy the way these guys are requiring web page-based authentication.

Anyway, it's running fine, looks OK, and glad they are on top of these updates.

Cleaning Up the Java Code a Bit

Friday, June 24th, 2011

Code Clean Up

This morning I was taking another pass at the Java client code for my Ticker Plants. The problem was that the original author didn't have any real experience with Java, and while it works, it's not working how it really should. Take as an example, the use of threads. In boost, which was the source for the Java port, creating threads is very simple:

  t = boost::thread(&MyClass::method, this, arg1);

and away it goes. Very simple, very clean.

In Java you can go the Thread or the Runnable route, and what had happened was the coder had created subclasses of Thread whose constructor took a class instance and then the run() method was simply:

  public void run() {
    mClass.unspool();
  }

where the unspool() method on the class does all the looping, etc. to get the job done. The problem is, there are literally dozens of lines of code overhead to accomplish this. I went in and simplified this to look like:

  mUnspoolThread = new Thread(new Runnable() {
                                 public void run() {
                                     unspool();
                                 }
                             }, "Unspooler");
  if (mUnspoolThread != null) {
    mUnspoolThread.setDaemon(true);
    mUnspoolThread.start();
  }

and this allowed me to drop probably 180 lines of code. It was pretty shocking.

I'm not done, but with every change I've gone through the code and tests to make sure I haven't changed the behavior any, and so far it's clean. I just need to keep going over it and over it to get it to the point that it's ready to really be used for the kinds of applications we have.

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.

Relationships Really are Built on Trust and Honesty

Wednesday, June 22nd, 2011

I know it sounds silly. It really does. But relationships really are built on trust and honesty. There's no other way. OK, sure... healthy relationships. I've been struggling with something for a few days, and it's come to a head this morning and it's got me a little concerned. The situation is this: the new group I'm in is meant to develop applications and systems quickly. In order to do this, we are meant to own every aspect of the system - including production operation and support for at least six months. In order to achieve this we are specifically not meant to be slowed down by the traditional QA and deployment system.

After we have been in production for the necessary time, then it'll be up to us to decide what to transition to other groups in the Shop - and then work towards those goals. But certainly not to make those kinds of plans early in the game.

The catch is that this group is a "do or die" existence. I'm either treated well or I'm out. There is no in-between. So, the group has to be able to control their own destiny, and not be stuck with rules and conditions that would make it easy for a person with a grudge to slow the progress down enough to make it more likely the "die" comes about.

So this morning I'm looking at a 109 point list of what needs to be done for production status on the project I'm working on. Interestingly, this shouldn't be possible in the scheme presented to me, but I'm willing to be flexible - to a point. The problem with the list is that it's riddled with incomplete requirements and based on a system that is so horribly flawed that my system had to be written to replace it.

Oh... and did I mention that the guy creating the list is the manager of the legacy system that was so bad off that it couldn't be saved? Yeah... he's got no axe to grind... Not.

So I'm sitting here thinking "Hey... this wasn't supposed to happen!" and feeling like I've been hung out to dry. Would I have signed up for this group if I knew that anyone with a grudge could do exactly what I warned might happen? Nope. Not a chance. Some might say I should have known better, but I trusted the people telling me this. It's feeling very much like I'm getting the shaft.

Yeah... this is not a nice feeling at all.

Unfortunately, I have no idea what I'm going to do about it. Confrontation is not really a great idea, and doing nothing could put me in a situation that I'm looking for a new job in six months. Very uncomfortable.

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.