Fixing Rflickr and Xmlrpc to Handle Bignums

3 minute read

Flickr has become one of the more popular online photo storage sites and consequently has billions of picture on there. I use my Flickr account, in conjunction with a modded rflickr gem, to display all my photos on my website. It uses the Flickr API to get the pictures by ID, the downloads and caches the pics. Lets talk about these Flickr photos and their identifying ID's. Every time a new pic is added, it is assigned a numerical ID number, and that ID number has been counting up since day one. In fact, there are so many pics, and the IDs are so big that the ID number of the pics can no longer fit into an Integer container, but now need a Bignum or Bigint to hold the value. Let me explain... for example, one of my more recent pics:
Me and Di - Spinaker Way
... has an id number of 2153550206. This number in hex is 0x805C917E but more importantly, in binary it is:
1
2
3
Decimal: 2153550206
Hex:     0x805C917E
Binary:  1000 0000 0101 1100 1001 0001 0111 1110
"So what" you ask? Let me talk a little bit about signed integers. All modern computers use a binary counting method called two's compliment to create a signed integer, as in, the integer has a negative sign or a positive sign. In this system, the first bit determines the sign, 0 for positive and 1 for negative. This limits the value of the most positive int to be a 0, followed by 31 1's, A.K.A. 2^31-1. This maximum value is 2147483647. Uh-oh... The number id of my picture is bigger than that... how can I represent this value using an int? The answer (in ruby) is using a Bignum which is simply twice as long (64 bits) so that there is plenty of room to spare. For example, my number above would become:
1
2
3
Decimal: 2153550206
Hex:     0x00000000 0x805C917E
Binary:  0000 0000 0000 0000 0000 0000 0000 0000 1000 0000 0101 1100 1001 0001 0111 1110
... Giving us 2^63-1 positive numbers instead of 2^31-1. Luckily for us, most of ruby detects and switches to the Bignum seamlessly. That cannot be said for all of the ruby libraries though. I recently came across a problem in which this large picture ID was throwing up an exception because it could not be contained in a 32-bit integer container:

        
Bignum is too big! Must be signed 32-bit integer!
Tracing the error stack, I was able to look into where the error was generated... /opt/local/lib/ruby/1.8/xmlrpc/create.rb
1
2
3
4
5
6
7
8
9
10
when Bignum
  if Config::ENABLE_BIGINT
    @writer.tag("i4", param.to_s)
  else
    if param >= -(2**31) and param <= (2**31-1)
      @writer.tag("i4", param.to_s)
    else
      raise "Bignum is too big! Must be signed 32-bit integer!"
    end
  end
It seems that for some reason, the xmlrpc library doesn't switch over by itself... I can either 1) ask Flickr to change how they represent a photo, 2) rewrite a bunch of code to handle the photos in a different way, or 3) I must set this "Config::ENABLE_BIGINT" value to be true. Lucky for us, option 3 is a one-line fix over in /opt/local/lib/ruby/1.8/xmlrpc/config.rb, line 26:
Change this:

        
ENABLE_BIGINT = false
... To this:

        
ENABLE_BIGINT = true
Now save and restart your server and all should work. This should work fine if you are on your own server or running locally, but if you are on Dreamhost or another shared server, you must first install your own copy of ruby to make the change to as you do not have permission to change the servers copy of ruby. If you use this method, your file to change will be located somewhere different than /opt/local/lib/ and you will have to do a:

        
find . -name config.rb
... from your home directory to find the file and make the change. After following all the instructions, my file was located at ~/run/lib/ruby/1.8/xmlrpc/config.rb Good Luck!
EDIT: Just for fun... the last pic whose ID fits into an integer (ID = 2147483647) is:
102_4573
And the first Bigint pic (ID = 2147483648) is strangely not found...

The requested Flickr photo was not found.
Photo ID: 2147483648

Was this page helpful for you? Buy me a slice of 🍕 to say thanks!

Updated:

Comments