New Trackpad Drivers from Apple for Recent MacBook Pros

July 28th, 2010

MacBookPro17.jpg

This morning Apple dropped new drivers for the new Magic Trackpad on Software Updates, and as a consequence, added inertial scrolling to the existing MacBook Pro users - like me. I installed it primarily because I'm a guy that believes in staying up to date, but when I started to use the inertial scrolling I was simply blown away.

This is what I love about the iPhone, and now it's on my Mac. This makes it so much less effort to scroll around things. Very nice. Very slick.

There is only one Apple. Long live the King.

BBEdit 9.5.1 is Out

July 28th, 2010

BBEdit.jpg

This morning I noticed that BBEdit 9.5.1 was released and while it didn't fix the one problem I had with it, it did seem to fix a lot of bugs other people had with it.

My problem is that when you open a C++ header file, you can, with a click of a widget on the window, open up the corresponding implementation file. Previously, this allowed you to open it up in the same window, but now it seems to respect the global defaults of opening it up in a new window. In general, I want new files in new windows, but when it's the header/implementation file pair, it's a different story.

It'd be easy to add, I'm sure, but I'm guessing they aren't going to change it back. I've sent them an email once, I'll send it to them again this morning.

UPDATE: I sent along the description of the issue. We'll see if they respond. I'd really like to have that feature back.

[7/29] UPDATE: they don't have this, but they do have something that's almost as good: If you set the default to "Open in Front Window" you can get the file opening up where you need it. Problem is everything will be opening there. The way around that is the View menu: "Move to New Window". I put in the keyboard shortcut command-option-O. Now if there's a file you want "split out", it's a single keystroke. Not bad. Not what I wanted, but it's not bad.

Upgraded to Git 1.7.2 on MacBook Pro – Pro Git Tips

July 28th, 2010

gitLogo.gif

I saw a nice tweet from GitHub this morning about some really nice pro git tips, and at the top of the page, it points out that some of these features require git 1.7.2. That got me thinking about what version I was on because I know I updated a little while ago. So again, I did the magic:

  $ git --version
  git version 1.7.0.3

and it looked like I needed to spend a few minutes getting up to date.

I'm a fan of the Mac OS X Git installer on Google Code as it's a clean package to download and get installed.

Took only a few minutes and now:

  $ git --version
  git version 1.7.2

Perfect!

I'll need to get this installed on my other boxes in my office tonight.

Cool Method for Milliseconds Since Midnight for C/C++

July 27th, 2010

cplusplus.jpg

I was working with exchange data today, and realized that the "timestamp in microseconds since epoch" wasn't really a great timestamp, and, in fact, the exchanges are using the reference point of midnight, and only to milliseconds. The problem was, I didn't have a simple method that could give me the time with respect to midnight. I didn't see anything that was really helpful on google either.

Then it hit me... It was like a flash - like all great insights are: use the seconds in the response from gettimeofday() as the input to localtime_r() and then you have one time "instant" defined, but you can pick off the hours, minutes, and secons and then add in the milliseconds by dividing the microseconds.

Like this:

  uint32_t TransferStats::msecSinceMidnight()
  {
    /*
     * This is really interesting. I need to get the msec since midnight,
     * and the cleanest way I could think to do this was to get the
     * timeval struct and then take the tv_sec component of it and pass
     * it to localtime_r to get the hour, min, sec parts of the time and
     * then piece it all together again. Kinda slick.
     */
    // get the time now as the (sec + usec) since epoch
    struct timeval tv;
    gettimeofday(&tv, NULL);
    // now take the seconds component and get the current hour, min, sec
    struct tm   now;
    localtime_r(&tv.tv_sec, &now);
    // now let's calculate the time since midnight...
    return (tv.tv_usec/1000 + ((now.tm_hour * 60 + now.tm_min) * 60
                                + now.tm_sec) * 1000);
  }

Fleshing Out a few Concrete Messages for My Ticker Plant

July 26th, 2010

Today I spent most of the day trying to flesh out the infrastructure for a few concrete message classes of exchange data in my new ticker plant. The initial work I'd been doing was focused on simple message types, and just about anything would work there - so I used my simple 'Hello' and 'GoodBye' TCP handshaking messages, and they worked fine. But now, I've got people wanting to test components that require the sequence number from exchange messages, and that means I needed a lot more infrastructure than I had built up.

The first thing was the idea of the conflation, or 'compression', key on the messages. This is something that I know I'm going to need in the client code as the current system has historically had a serious problem of not being able to handle a slow consumer very well at all. I settled on a simple uint64_t as the conflation key type and added a very nice little string hash method to get decently diverse integer values from strings:

  static const size_t    __initialFNV = 2166136261U;
  static const size_t    __fnvMultiple = 16777619;
  size_t Message::hash( const std::string & aString ) const
  {
    size_t   hash = __initialFNV;
    size_t   len = aString.length();
    const char *p = aString.data();
    for (size_t i = 0; i < len; ++i) {
      hash = hash ^ (*(p++));
      hash *= __fnvMultiple;
    }
    return hash;
  }

and from what I've read, this Fowler, Noll, Vo algorithm is pretty decent at creating a diverse mapping of strings into the integer space. It's not something I'm going to count on as unique, but it's decent enough for some message types.

Now that I had something to put into the getConflationKey() for my existing messages, I started with the exchange messages. I needed to make a base message for exchange data, and then a faux price message that I could use for testing. This is going to be something that is very close to a "real" message, but will be strictly used for testing.

Why? Because I can control everything about it and it'll never change. This is the kind of test framework we need for the performance testing and comparison runs. True, we'll also need real-world exchange data for some additional testing, but that doesn't negate the value of this kind of test framework.

Then I realized that I needed to make a final determination on how to integrate the "parsing" of the external data into msg::Message instances. I decided to go with a very simplistic API. The MessageFactory has three basic methods - the create() method to take external data into our messages, the extractSequenceNumber() to extract just the sequence number from said external data, and the masquerade() method to be the inverse of the create() method and attempt to make external data from the message.

I then had to put this all in place and write the faux price message and it's data conversion class. It was a lot of coding and I didn't quite get it all done today, but should be able to finish it up tomorrow.

Using Multiple Connections on a ZeroMQ Socket (cont.)

July 26th, 2010

I was able to spend another 20 mins on the code conversion to a single ZeroMQ socket for my ZMQ receiver this morning. I then ran the tests, and BINGO! it worked like a charm! Excellent. I still need to do a lot more tests, but this is an amazing step in the right direction.

Today I need to test multiple multicast channels sending to a single receiver, and then I need to get a little deeper into the actual data messages that we'll be sending as I need to do some load tests to see what it's all capable of.

Very exciting times.

Using Multiple Connections on a ZeroMQ Socket

July 23rd, 2010

ZeroMQ

The design we have for my ticker plant is to have the different products and exchanges spread out over a large number of reliable multicast channels, address and port combinations. In order to do this with ZeroMQ, I was under the impression that I needed to have a zmq::socket_t for each channel - which in ZeroMQ terms is really a URL like: epgm://eth0;225.1.1.1:55555. After all, the basic code for a multicast receiver looks like:

  #include <zmq.hpp>
 
  // make a ZeroMQ context to handle all this - use one thread for I/O
  zmq::context_t   context(1);
  // make a simple socket, and connect it to the multicast channel
  zmq::socket_t    socket(context, ZMQ_SUB);
  socket.connect("epgm://eth0;225.1.1.1:55555");
  // now set it up for all subscriptions
  socket.setsockopt(ZMQ_SUBSCRIBE, "", 0);
  // receive a single message
  zmq::message_t   msg;
  socket.recv(&msg);

So in many ways, the ZeroMQ socket looks and acts like a regular socket. But I've read in many of the mailing list posts, and even talking to a guy here at The Shop that has dug into the code, that these aren't really sockets - they are just the logical way the ZeroMQ guys made their code appear to the users of their stuff.

This is never more obvious than the mailing list post I read today about having multiple connections to a single zmq::socket_t. The maintainer of the library said that there can be multiple connections to a single socket:

  #include <zmq.hpp>
 
  // make a ZeroMQ context to handle all this - use one thread for I/O
  zmq::context_t   context(1);
  // make a simple socket, and connect it to the multicast channel
  zmq::socket_t    socket(context, ZMQ_SUB);
  socket.connect("epgm://eth0;225.1.1.1:55555");
  socket.connect("epgm://eth0;225.1.1.1:55666");
  socket.connect("epgm://eth0;225.1.1.1:77777");
  socket.connect("epgm://eth0;225.1.1.1:88888");
  // now set it up for all subscriptions
  socket.setsockopt(ZMQ_SUBSCRIBE, "", 0);
  // receive a single message
  zmq::message_t   msg;
  socket.recv(&msg);

and the recv() will then pick off the first available message on any one of the connected sockets. That's great news! As opposed to needing n sockets for n channels, I can have just one, and that simplifies my code a huge amount.

So that's what I'm working on. I'm nearly done, and then I can test. Can't wait to see how this works.

MarsEdit 3.0.4 is Out

July 23rd, 2010

MarsEdit 3

I just got a tweet from MarsEdit to say that 3.0.4 is out with a few nice little changes - especially for the rich text editor users:

  • Fix a bug that caused strange ? characters at ends of pasted paragraphs
  • Fix Drupal authentication issues by preserving cookies when connecting
  • Fixes to Tags field to handle whitespace better, and keep insertion point visible

As a WordPress user, I'm not really hit by this, and I don't use the rich text editor, but it's nice to see improvements. It's been a slow week, and any reason to work on my Mac is a welcome one.

Google Chrome dev 6.0.472.4 is Out

July 23rd, 2010

GoogleChrome.jpg

This morning I checked, and Google Chrome was updated to 6.0.482.4 with some interesting new features for the Mac:

All

  • [r52790] Chromium stops saving files for any large downloads (Issue 49216)
  • [r52693] Fix crash with SSL client auth (Issue 49197)
  • [r52850] Option clicking a link now saves a resource directly without triggering a “Save As...” dialog (Issue 36775)

Mac

  • [r52911] Implement the upgrade available notification on the Wrench menu (Issue 45147)
  • [r52485] Implement the new, unified Wrench menu (Issue 47848)

And I have to say, the new, unified "wrench" menu is pretty interesting:

Google Chrome Wrench Menu

I'm not sure how the non-standard menu items like cut, copy & paste, and the zoom are going to go over. It seems like they went for the "common denominator" here, but even then, the edit operations are all pretty standard on all the platforms - only the shortcut key-bindings are different. Hard to see why they went this way, but they did.

Anyway, it's nice to be up to date.

Running ZeroMQ Applications – Not a Trivial Thing

July 22nd, 2010

ZeroMQ

I finally got ZeroMQ integrated into my application library and wrote a few test clients - one to send and the other to receive. When I tried to run them I got the following error:

  $ zmqReceiver
  ..(startup)...
  (process:8444): Pgm-WARNING **: DSCP setting requires CAP_NET_ADMIN of ADMIN
  capability.

I seemed to remember something about this in the mailing list, but try as I might, I wasn't able to find that bloody reference again, and so I was stuck trying to figure this out from scratch.

Basically, because of the way OpenPGM runs, it essentially requires "privileged" access on the network drivers. OK, I can believe that. So how to I accomplish that? My limited google fu yields that the command setcap should do the trick, but that command is not on the CentOS 5 install I have, and yet the command execcap is.

It seems that the execcap runs the single command with the specified capabilities, so if I do:

  $ sudo /usr/sbin/execcap 'cap_net_admin=eip' ./zmqReceiver

then all runs well.

Sort of.

We still run into the problem of LD_LIBRARY_PATH not being transferred, so I ended up making a simple script that set the LD_LIBRARY_PATH and then called the command and that script I put in the execcap command to get things working.

And they worked wonderfully.

Now I need to find a way to make it "stick" without running it as root.

[7/26] UPDATE: when I came in this morning, the linux server I code on had been rebooted. Odd... so I decided to check and see what the state of the CAP_NET_ADMIN capabilities was. Lo and behold... it was fixed! Seems the admin guy had to reboot the box to make the change, and made it he did. I can now launch these processes without the grief of the launch script or execcap. Sweet!