Tuesday, May 8, 2012

Are moose heavy? There's mouse.

I happened across Mouse in the dependency chart of an Amazon Route53 module, so I looked it up.
  • Mouse is meant to be lighter than Moose, and compile faster (for CLI and primordial CGI).
  • Mouse wants to let you do s/Mouse/Moose/g and have nothing break, if it turns out Mouse isn't heavy enough.
  • Mouse also exports warnings and strict for you when you use it.
  • Mouse basically doesn't want to have MouseX.
  • Any::Moose gives you Moose if that is already loaded, or Mouse otherwise.
So there you have it: Mouse is a lightweight Moose.  Without antlers.

Sunday, May 6, 2012

Python: Slicing in reverse, in the middle of a sequence

When slicing forwards, it's relatively simple to understand: s[7:9] returns a 2-item sequence of elements 7 and 8.  This works pretty much like any other half-open interval, in which one side (the 7) is included and the other (the 9) excluded.  The resulting length is simply the difference between the end and start indexes, 9-7=2.

What about backward? If you reverse the numbers and add a stride value, s[9:7:-1] gives you elements 9 and 8.  Since the interval is still half-open, now 9 is on the closed end and included, and 7 is open and excluded.  So s[8:6:-1] is the reverse of s[7:9].  You're getting two elements, starting at 8 and ending before 6, going backwards.

What happens if you want to get the reverse of s[0:5]?  The above math would suggest s[4:-1:-1] but negative indexes are way at the other end of the sequence, so this produces an empty result.  The correct answer is actually omitting the end index, as in s[4::-1].  That invokes the regular "all items remaining in sequence" meaning, that is also used in s[9:].

Wednesday, May 2, 2012

PPTP is legacy

Unlike IPSec and L2TP+IPSec, a PPTP VPN tunnel is carried over TCP, which means all packets traveling inside the tunnel are delivered reliably—including any tunneled TCP traffic.  Therefore, the inner TCP layer never sees packet loss, wreaking havoc with its congestion control mechanisms.

Consider L2TP+IPSec first.  (At least, my experience with vanilla IPSec has been less than recommendable.)

Monday, April 30, 2012

Uncontrolled Mutation: An Example of Inefficiency

I pruned /etc/apt/sources.list a bit tonight, because it annoys me when I have to wait for a lot of data just to answer the question, "So do I need to upgrade anything?"  Really, when a handful of updates are published, I should not have to get a fresh 4.6 MB copy of the entire multiverse package tree.

Since the scope of potential mutation is the entire index file, all clients only get file-level granularity for controlling the amount of data they download.

Tuesday, April 24, 2012

A New Way to Write Broken Perl

I called $cls->SUPER::new in a package constructor that was erroneously missing a base class, which issues the helpful diagnostic:
Can't locate object method "new" via package "The::Package::Name" at .../The/Package/Name.pm line 12.
So Perl says it can't find the method at the exact site of the definition, which is weird enough, but the real problem is triggered by the line with the SUPER call.  Once I added the use parent 'The::Parent'; line to the package, everything was fine.

This behavior was observed Perl 5.10.1 as presently available through the repository for CentOS 6.2.

Monday, April 16, 2012

AmazonS3 'headers' and 'meta' options in the PHP SDK

When you're using create_object, or several other methods of the AmazonS3 class, the $opts parameter often allows for both headers and meta keys.  Although headers is documented as "HTTP headers to send along with the request", it turns out that they are returned with the object (i.e. in the response) when that object is requested from S3.  In contrast, keys in meta are canonicalized, prepended with x-amz-meta-, and returned that way.

That is, if you want to upload filenames like "$id-$md5.pdf" but deliver them to the user as "ContosoUserAgreement.pdf" in the Save-As dialog, then headers should contain a Content-Disposition key with a value of attachment; filename="ContosoUserAgreement.pdf".

If you put it in meta instead, then the HTTP headers on retrieval will contain a x-amz-meta-content-disposition header instead, which will not be honored by the browser.

I found all this out by uploading something like 12,000 files with the wrong metadata.  I then wrote a script to fix it, which ran straight into the problem that update_object doesn't work, so you have to use copy_object instead.  Note that when using copy_object with 'metadataDirective' => 'REPLACE', you need to specify all the metadata you want, because it does what it says: it deletes all old metadata before adding the new metadata from the copy_object request, so that only the new metadata exists afterwards.

Tuesday, March 27, 2012

Triumphs of the Worse

I know I seem like an irrelevant dinosaur to you node.js hipsters, but there are some valuable lessons floating around there that the next+1 new hotness would be wise to consider.  They all stem from the questions: what were the popular web languages?  And why?