Main

January 29, 2010

Clarifications about AnyEvent::Mojo

It seems that I need to clarify some stuff, based on Sebastian comments in my last post and via Twitter. I really hope this is the last time I have to talk about it. I rather spend my time coding.

First, you can look at the code of AnyEvent::Mojo::Server::Connection: no private Mojo APIs are being used.

They might have been with early releases, but as Sebastian says, I did work with him to improve Mojo so that I didn't have to depend on private APIs. That would be wrong.

In fact, given that I was able to write a AnyEvent-based Mojo server proves that the code was properly structured.

Second, I have no problems with changing state machines. I like state machines and expect them to change. I was eager to see Sebastian add a "pause" state, that would greatly simplify my own work regarding long-pooling. And the first break included changes in the state machine that I fixed on my side.

But the second break was caused not by the introduction of new states, but the abstraction of some code into the new Mojo::IOLoop. After the notification of no changes until 1.0.

Now, I totally accept that Sebastian needs to evolve his code base to support the new stuff he wants to support, like WebSockets. But it was nonetheless new code, and a re-factoring of all the Server interface.

I was pissed at having my code broken in that way after the "no changes" declaration, but only for a couple of days, but, and significantly more importantly, that has nothing to do with my deprecation of AnyEvent::Mojo.

I'm deprecating my module because there is a better way to do it now. I no longer need to keep this module up-to-date, I just have to work with the larger community of the PSGI/Plack, the Perl Web Server. It just makes sense to drop one-off module and switch to a system that is being reused by so many projects.

In a nutshell, I'm deprecating AnyEvent::Mojo because you have better solutions now. Solutions that I will move to and recommend to others. Solutions based on the PSGI/Plack stack, the Perl Web Server.

I am glad to see a clarification about the deprecation policy in the Changes and the http://github.com/kraih/mojo/commit/89fc6baf390d0065ad319abc540dc6a47e0bc812 for the Mojo project, I think it is a big step in the right direction; it can only give assurance to potential users of Mojolicious, and help the project.

I did learn a lot about HTTP that I hadn't pay attention before, the tiny details in the protocol. I do like Mojolicious MVC stuff, I just think that the Plack HTTP stack is better than the Mojo HTTP stack.

And I might get the cake and eat it too. I'll wait for Mojo 1.0 but it should be possible to use Mojolicious, the best part of the project, with Plack.

Anyevent::Mojo update

The current version of AnyEvent::Mojo is failing some tests. The Mojo API that I was using changed yet again and I don't have the tuits to fix it right now. I'll explain how we got here, what are the next steps, and finally I'll comment on lessons learned.

A long, long time ago...

When I wrote AE::M, I was looking for a way to do long-polling in Perl, with decent performance and cool stuff like epoll/kqueue support. At the time, the only solution might have been POE, but I have other problems with that module, so I decided I wanted a AnyEvent-based solution.

I went looking for a HTTP-stack that I could extend and found Mojo. The code was working and ready in a afternoon, and I was happy.

But then we had the famous 0.991250 release. A lot of backwards incompatible changes, and AE::M broke. I was caught at a bad time and could not update my own module for some weeks. In the Changes file, Sebastian explained why he broke backwards compatibility and that it would be the last time before 1.0; so I finally found the time and updated my code.

CPAN Testers was giving me green lights once more, and I was happy.

Until 2 months later that is, when we got the new Mojo::IOLoop code. AE::M broke again, and its broken since then. The place where I was using AE::M needed some fixes, and the work to adjust my code to the new Mojo is not as simple as it was the first time around.

So I took the dirty way out: included the last pre-Mojo::IOLoop code with my project, implemented the new features, and shipped. Not pretty. At all.

Meanwhile, in a distant planet, miyagawa was busy changing the Perl landscape with regards to HTTP integration. He wrote the PSGI spec, and the Plack toolkit. It is a wonderful piece of work, and the Perl Web Server of choice.

And after some API work, with the help of nothingmuch, it included a very decent support for asynchronous HTTP servers, including all the bits to make long-pooling work right.

Then in December, we got Mojo::Server::PSGI, native support for PSGI inside Mojo.

Next steps

Right now, I'm waiting for the next release of Mojo, and then I'll immediately release a new version of AnyEvent::Mojo, deprecating it.

With the native support for PSGI, there is no reason to maintain the AE::M interface, just use the Plack::Server::AnyEvent (or AnyEvent::HTTPD::PSGI when miyagawa finishes the cleanup he talked about).

But I will update the AE::M one last time to make it compatible with Mojo::IOLoop, as soon as I have the time. I don't want to leave it broken.

In the meantime, if you are using AE::M, I suggest that you bundle an earlier version of Mojo. I'll run a git-bisect to figure out which version is best and update this post.

Lessons learned

Not sure. On one hand, it is a version below 1.0 so we can expect some breakage.

On the other hand, the Changes file mentions that no more backwards incompatible changes would be made to Mojo before 1.0.

I still like the Mojolicious MVC framework and the dispatcher behind it, but I fear the Mojo stack and deprecation policy of the project now.

For now, all my async work is moving to Plack. I still need a asynchronous MVC framework, but I can wait a bit, or even write a very simple one if need be. Maybe steal code that I like from the others.

But I'm back to Catalyst (and I plan to talk about my feelings about the attribute-based dispatcher soon) because I feel safer. A lot safer. I know that there are other people out there that depend on Catalyst every day and in with big sites, much bigger than mine. And I trust the Cat developers not to break my code.

I do hope to see Mojo 1.0 soon, and I hope it goes well for all the gang at #mojo, but I will also look for some form of backwards compatibility policy before I even mention Mojo ever again in my presentations about Perl.

November 27, 2009

Muito obrigado

I'm not American so officially I don't get a Thanksgiving holiday. Still, we are reaching the end of 2009 and looking back I think we do have a lot of things to be grateful for.

Giving thanks, like Christmas, doesn't need a special day, and for us perl hackers our favorite team, the perl-porters, giving thanks couldn't be easier.

So lets all, no matter where you are, run the perlthanks command line today, and celebrate our new schedule for Perl5 releases and happy days and long lives to our pumpkins.

On a more individual note, I can't forget three little big persons: cog, ambs and Magda. YAPC::EU raised the bar on so many levels.

But we don't live without CPAN, and so we acknowledge the PAUSE and CPAN teams, and all individuals that keep the mirror network up and running.

Finally, to those teams that make my day-to-day simpler and fun: the Moose cabal and the Plack gang (with a note of envy for miyagawa productivity...).

To all, a very big Muito Obrigado.

November 19, 2009

Feed generator

I was mostly away from Perl this last days, and I'm eager to get back to it next week.

The small work I did was to start a script that converts a directory of files into a RSS or Atom feed.

For now it sits at the app-files2feed repository. I need to fix the last bugs with enclosure support and add documentation before releasing it to CPAN.

Non-perl work sucks.

November 10, 2009

More Browser::Open

I pushed to CPAN a new release of Browser::Open.

I've added more commands to test (courtesy of code "borrowed" from SD, and the Launchy gem), and made the test suite more robust in case we don't find a suitable command.

<rant>
I'm amazed that something as simple as opening a URL is such a complicated task on most UNIX-based systems.

I have a single command to use on Mac OS X and on Windows based systems, but there seems to be no standard way of doing this simplest of things on UNIX systems.
</rant>

November 01, 2009

Perl testing and git pre-commit hooks

An article on Colin's blog mentioned a technique that I also use, using your test suite as a git pre-commit hook. I'll expand on some of his ideas, showing my own setup.

Before each commit you should run the full test-suite of your code. If your test-suite has grown so much that it takes a long time to run, it makes more sense to run a smaller part of it, and let the continuous integration system (you do have one, right?) report back any problems with your tree later.

At the very least you should make sure that all your modules compile correctly. And that means checking the 00-compile.t test file.

To make the whole process automatic, I use the following pre-commit-hook:

#!/bin/sh

## Set any ENV vars that your test suite requires here

exec prove -l -Q t/00*

I usually write a script called my-git-pre-commit-hook and exec that one from the .git/hook/pre-commit file, this way I can run it by hand if I need to.

I also assume that all tests named 00-* are important enough to run before each commit, which lets me add more specific tests at any point.

This solves half of the problem. I also don't want to keep editing the 00-compile.t file each time I add another module to my project. So I wrote it like this:

#!perl

use strict;
use warnings;
use Test::More;
use Path::Class;
use File::Find;

my $lib = dir('lib')->absolute->resolve;
find({
  bydepth => 1,
  no_chdir => 1,
  wanted => sub {
    my $m = $_;
    return unless $m =~ s/[.]pm$//;

    $m =~ s{^.*/lib/}{};
    $m =~ s{/}{::}g;
    use_ok($m) || BAIL_OUT("***** PROBLEMS LOADING FILE '$m'");
  },
}, $lib);

done_testing();

This code uses File::Find to list all the .pm files in your lib/ directory, and then tries to use them. It also use submodules before using the main module, courtesy of the bydepth switch.

If a problem is found, it immediately bail out of the entire test suite, mentioning the file that has problems. On previous versions it would test all modules and only bail out at the end if any had problems. I found that version less productive because the same problem would be reported multiple times.

This works out fine for my projects. It adds at most a couple of seconds to each commit (in the current project it adds less than 4 seconds) but I find that acceptable.

It would be interesting to write a 00-test-commited-files.pl file that would look at the files being updated by the commit and run the tests that cover them. This could be done with the help from Devel::CoverX::Covered but I haven't done it yet.

October 24, 2009

A faster configuration for CPAN::Reporter

The idea of CPAN::Reporter is great: take advantage of all those daily uses of the cpan shell to collect reports from a large network of users.

I tried several times to enable CPAN::Reporter but I always found that it delayed just enough of my workflow that I found it a nuisance. After each test phase, it would start a SMTP connection and send the report. Those 3 or 4 seconds where a bit too much for me.

After a bit of reading I found a good compromise to report my test runs without affecting the performance. The setup is simple: make CPAN::Reporter write the test results to a directory and create a command to send them later.

To set this up, first you install CPAN::Reporter as usual and then you tweak the configuration to store the reports in a directory. My ~/.cpanreporter/config.ini looks like this:

email_from = "Pedro Melo" 
edit_report = no
send_report=unknown:yes fail:yes pass:yes na:no

transport=File /Users/melo/.cpan/reports

The trick is to use the File transport. You configure it with the directory where the test reports will be stored. In my case I choose /Users/melo/.cpan/reports. You need to make sure that directory exists.

From now on, every time you use the cpan shell to install a module, the test reports will be stored in you test report directory.

The final step is sending them. I wrote a simple script to take care of that, that you can find on my scripts repository: x-perl-send-test-reports (download).

How and when you run it is up to you. You can run it manually from time to time, or from a cron, or use something like folder actions to monitor the directory and start the script whenever a new file is placed there. I run it manually for now.

My command line to use the script is this:

x-perl-send-test-reports         \
    --from melo@simplicidade.org \
    --server smtp.gmail.com      \
    --transport 'Net::SMTP::TLS
         User melo@simplicidade.org
         Password my_password
         Port 587'               \
    ~/.cpan/reports

So one less excuse not to report your test results. If you are not using CPAN::Reporter, start now.

October 18, 2009

Just another data point

(Update: I've pushed my code, including three new scripts, to the nfsd_report_bench/ directory on my examples repository. See below for some clarifications based on comments I received).

A former colleague of mine at PT had a small reporting problem, and he ended up comparing several languages for the job: C, Perl, PHP, and Python.

I was curious about the results, so I took the latest version of the Perl script that he was using and set off to work.

The first thing that you should be aware is where your bottleneck is. Take a look at this small script:

#!/usr/bin/env perl

use strict;
use warnings;

my $lines;
while () {
#  my @fields = split / /;
  $lines++;
}
print "$lines\n";

A basic line counter. Compare it to the system wc:

$ gzcat nfsd.gz | time wc -l
 12236390
       16.86 real        16.24 user         0.43 sys
$ gzcat nfsd.gz | time ./wc_simple.pl 
12236390
       10.13 real         8.51 user         0.84 sys

So, a bit faster than the C version, doing 1.2M lines per second on my laptop.

But if you remove the comment on the split(), we have:

$ gzcat nfsd.gz | time ./wc_simple_with_split.pl
12236390
       228.78 real       224.39 user         2.34 sys

A lot less: 53k lines per second.

So the first bottleneck is the split(). Lets improve on that. After some attempts I came up with this:

my $lines;
while () {
  my ($ts)    = /^(\d+)/gc;
  my ($type)  = /(\w)\sV/gc;
  my ($op)    = /\s(\d\d?)\s\w/gc;
  my ($bytes) = /\w\s(\d+)\s/gc;
  $lines++;
}

I make use of the gc flags to start the next match where the previous one ended. I also take advantage of patterns in the lines that I need to match, like the V in the NFS version.

With this version we get:

$ gzcat nfsd.gz | time ./wc_simple_with_regexps.pl
12236390
      109.62 real       107.42 user         1.55 sys

A bit better: 111k lines per second, a bit over 2x the previous result.

If we apply this gain to the reported times for the Perl script (419m11.267s), we get 200m49.97 which places Perl 1st, even above the C version by a minute or so.

My adjusted version of the stats_basic_optimized.pl script is melo_stats_basic.pl.

This was good enough I think, but I wanted to study the I/O gains that could be made. Stop reading here if you are already bored, it will only get worse. We did manage to get a few more minutes back, though... ;)

So I went after the I/O performance. Fist I wanted to rule out the pipe as the bottleneck.

$ cat /dev/zero | pv | cat > /dev/null
4.61GB 0:00:10 [ 498MB/s]

$ gzcat nfsd.gz | pv | cat > /dev/null 
1GB 0:00:04 [ 242MB/s]

So the pipe is not the bottleneck but we will never reach the full speed, gzcat will be our limitation.

I did try to read the gzip file directly into the Perl script and uncompressing it there, but it was very slow.

So assuming a limit of 242MB/s on the input side, how fast are we chopping lines? The size of the input is 1073743224 bytes, and our simple wc_simple.pl (no split, no regexp) took 10.13 seconds above, so we are chopping the input at a rate of 101MB/s.

So there is room to grow there (101MB/s to 242MB/s). I did some experiments:

$ gunzip nfsd.gz
$ time wc_simple.pl < nfsd
12236390

real    1m23.212s
user    0m7.434s
sys 0m2.166s

Yeah, the file doesn't fit in the cache like the gziped version, so there is real I/O, and the times go through the roof.

There is no point doing experiments with the big nfsd file. All of them will result in real I/O, and that is always slower than memory.

Lets try to do bigger reads and parse the results:

use strict;
use warnings;

my $size = shift || 2 ** 20; ## 1Mb default
my $offset = 0;
my $buf = '';
my $lines = 0;

while () {
  my $n = sysread(\*STDIN, $buf, $size, length($buf));

  while ($buf =~ /.+\n/gc) {
    $lines++;
  }
  last unless $n > 0;

  print "$lines $n\n" unless $lines & 0x1ffff;
  $buf = substr($buf, pos($buf));
}
print "$lines\n";

I tried several block sizes but with my OS the most I could read in one call was 64k. So asking 1MB and getting 64k reads we get:

$ gzcat nfsd.gz | time  ./wc_batch.pl
12236390
    8.37 real         7.52 user         0.58 sys

We get 1.46M lines per second, a 17% improvement. Lets adjust to retrieve our fields. The inner loop becomes:

while ($buf =~ /(.+)\n/gc) {
  $_ = $1;
  my ($ts)    = /^(\d+)/gco;
  my ($type)  = /(\w)\sV/gco;
  my ($op)    = /\s(\d\d?)\s\w/gco;
  my ($bytes) = /\w\s(\d+)\s/gco;

  $lines++;
}

and the runtime:

$ gzcat nfsd.gz | time  ./wc_batch_with_regexps.pl
12236390
   95.58 real        93.21 user         1.14 sys

So from 109.62s to 95.58s, 12% better (or comparing with our baseline wc_simple_with_split.pl at 228.78s, 58% better). Adjusting this to the reported results we would go from 419m11.267s down to 175m5.6842s.

I don't think I can improve on this unless we can have a bigger pipe reads. For example, forcing the reads to 8k:

$ gzcat nfsd.gz | time  ./wc_batch.pl 8192
12236390
       12.08 real        10.93 user         0.70 sys

A lot worse compared with the 8.37s we got with 64k reads. So the size of the pipe is the next factor we could explore, if that is even an option with your kernel.

But I'm happy now.

The next day

Or so I though. First there was doubts that the split() was faster than regexps. I wrote bench_splitters.pl (output on my laptop, download link) to compare split with my regexps. The regexps are a bit over twice as fast, but I found big differences between the Mac OS system perl (5.8.8 on my Leopard OS) and the 5.10.1 that I compiled: system perl was between 20 and 30% faster.

The same bench_splitters.pl gives you the max rate of extraction that you can expect from the global script. I also included timing of the bookkeeping parts of the original script. The only noteworthy detail is the fact than when you hit the second level condition, you pay the price of the modulus operator big time. I also think that something is wrong with the input. Those time stamps don't look like normal second-precision time stamps. They are too big. So I don't know if $ts % 3600 is the proper way to group performance by hour.

Second I wrote a max_line_rate.pl (output on my laptop, download link) that gives you the upper bound on the max rate that you can expect while parsing the required fields. You can run this script, and stop it at any point in time with ctrl-c, and it will print a performance report up to that point. Every 128k lines, a single line performance report is also printed.

You can use this max_line_rate.pl to compare your system perl with the 5.10.1 you compiled. I had much better performance with 5.8.8 in this particular application.

Finally I rewrote the statistics script. I did that to deal with the report that my previous version was consuming 7.5Gb of RAM. The reason is simple enough: I don't have access to the original input, only to a six-line excerpt that was posted. Therefore the regexps I use to extract the required fields might fail.

The new script, fast_stats.pl (output on my laptop, download link), is more robust, and should deal with lines that cannot be parsed: it will print the line that couldn't be matched and ignore it. Also: I've included the output of the ps command at the start and end of both fast_stats.pl and max_line_rate.pl to show that the RSS doesn't change that much.

To compare the original stats_basic_optimized.pl with my fast_stats.pl I wrote a small shell script bench.sh (output on my laptop). The nfsd.gz input file was generated with the build_source_file.pl script with the command:

build_source_file.pl 1073741824 | gzip --best > nfsd.gz

The new fast_stats.pl is almost twice as fast as the old one on my laptop.

On a final note (I wasted too much time already on this...), I'm not out to compare Perl with Python or Ruby or even PHPO. But I would like to know how we measure up against C though. The reason is simple: when Perl programmers feel that something is slow, they turn to C, not another scripting language.

This experiment is mostly to show that writing fast perl will sometimes take you to unexpected paths (like regexps beating a split), and that you should benchmark carefully if performance is critical to you.

October 17, 2009

CPAN::Shell 's' command

I'm playing with a new command for the CPAN::Shell: 's' for search on http://search.cpan.org.

It takes a single argument (can be a module, distribution, bundle or author name), checks the CPAN indexes to see which type it is, creates the proper URL for it at search.cpan.org and opens your browser with it.

The last bit, opening a browser with it, is very very immature. Right now it only works on Mac OS X. I'm hopping to get the experience to do it right from the Browser::Open distribution.

If no object is found, sends the user to the generic search interface.

The current hackish implementation can be found on my s_command topic branch (its a topic branch, I will rebase it on occasion onto master).

Browser::Open

I've uploaded a small module to CPAN, Browser::Open (give it a couple of minutes to show up).

It does one simple thing: given a $url, it opens the default browser with it.

The difficult part is deciding how to open the "default browser". On Mac OS X, this is easy: just execute the open command.

On Windows, there is a start command that should do the trick, but I'm not a Windows user so I cannot test this. Any Windows users out there that can point me to the relevant information on how to open a URL with a simple command, I would appreciate it.

For Linux, you have too many choices it seems: you could use gnome-open but your user might be using KDE. There is a xdg-open command described at the FreeDesktop site that seems to do what I want. We can always fallback to firefox though. Fragmentation++!

October 07, 2009

Dist::Zilla::Plugin::LatestPrereqs

This all started with an article by Marcel Gruenauer "hanekomu", "Repeatedly installing Task::* distributions".

What he wants is a way to tell CPAN this: "install the latest versions of my dependencies".

His solution wont work unfortunately. The code that he gives us will prevent the Task:: module from being installed but it will not guarantee that the latest version of the prereqs will be installed in the following runs.

the reason is simple: if you don't ask for a specific version of your prereqs, CPAN will accept any version, so it will only install each prereq once, the first time.

The perfect solution would be to create a marker on each prereq that would tell the CPAN tool chain that you want the latest version. This does not exist yet. You could probably standardize on version -1 meaning the last one (on a twisted parallel with the last index of Perl lists), but its all speculation. Its just not supported yet.

The next best thing would be to include the version required on each of your prereqs, and keep those values up-to-date to the latest available on CPAN whenever you rebuild your package.

This is a half-way solution. It wont guarantee the latest version at the time your package is installed but it would make sure you get the latest version at the time your package was built on your system before uploading to PAUSE.

This is actually a good compromise given that you are probably listing the versions of the prereqs that you tested your package with on your system.

And, better yet, this half-solution can be automatized. I wrote a Dist::Zilla plugin to do just that. The code is very simple and you can just adapt this into a Module::Install plugin or whatever you use to build your packages.

You can find the code for Dist::Zilla::Plugin::LatestPrereqs at my Github repository for Dist::Zilla tools. Its not on CPAN yet, and for now there are no plans to publish it. The reason is simple: it requires a small patch to the core Dist::Zilla. The patch is a single commit that you can find on Dist::Zilla fork. I've asked Ricardo Signes to accept the patch. If he likes the code, I'll release my plugin after the next Dist::Zilla release.

If you look at the LatestPrereqs code, you'll notice that it is very simple, but it does load the CPAN package and that is a big one. You could write this code directly on your Makefile.PL and have the very latest versions of your prereqs at install time, but this would assume that the system as a properly configured CPAN.

That was a risk that I'm not willing to take on my distributions. If you do it that way, ping me. I would like to follow your module CPAN Testers feed for a while.

Back to Marcel post, if you do need to prevent the install phase for your distribution, then I've also uploaded a Dist::Zilla plugin to do just that: Dist::Zilla::Plugin::MakeMaker::SkipInstall. It might be handy sometimes.

October 04, 2009

AnyEvent::Mojo 0.8

I've uploaded to PAUSE release 0.8 of AnyEvent::Mojo. It should be on your local CPAN mirror in a little while.

This was a long time coming unfortunately, and I accumulated FAIL test reports on CPANTS, but its here now.

Given that it uses the latest Mojo release, it supports HTTP keep-alive and pipelining, chunked-encoding and 100-Continue requests.

Although the test suite passes, I'm not fully confident on the pipelining code. My next step is to write a client with a slow network reader to exercise some corner cases of that part of the code. In particular, I'm concerned about the interaction of Mojo pipeline code with my request pause functionality that I use to implement long-polling servers.

It could be argued that long-polling and pipeline don't mix, but I think that the pause functionality could also be used on regular requests. For example, if one request needs an answer from a memcached server, the handler can start the memcached GET, pause the Mojo transaction, and resume it when the memcached response arrives. While that is going on, the server should be able to keep writing out previous requests, and reading the next ones.

Maybe thats a bit extreme, but I do hope to have this working, for complex pipelining situations.

September 26, 2009

Generating charset_table maps for Sphinx

At work, I wanted to improve the back-office search engine and installed Sphinx.

On a regular basis, it indexes all our users, courses, teachers and other important tables. It works great, low install barrier, low maintenance, and it is very very fast. Perfect.

One of the problems that we found, that limited the usefulness of the full-text search engine, is that a lot of our text has accents, and it would be better to ignore those. Also we don't need case-sensitive-ness.

So I needed to generate a charset_table map, what Sphinx uses to normalize the text that you give him to index.

And being a (very) lazy person, I prefer to write a Perl script to do it. The result is the x-sphinx-charset-generator, now part of my script stash.

It takes an optional parameter, the charset that you are using on your text defaulting to 'utf8', the loose version of UTF-8, and generates a charset_table for the most common accented characters, mapping them to the lower-case version of the same letter without the accent.

I've only include the common Portuguese characters. Patches accepted for others characters that you might need.

The only part that I don't really like is that I need to apply the same logic to cleanup the strings that users use to search. I would prefer to have a module that would take the characters that I want to allow as valid, and have that module provide the charset_table and a function to clean search inputs. Interesting, but for now this will solve the important 80% of the problem.

September 19, 2009

A new look at Mason

On my way to E5, I have to deal with all the legacy sites that came before it, and the vast majority of them are written in Mason.

At the time, we used HTML::Mason 1.05, and only after 1.30-ish (when the internal buffering changes introduced in the 1.10 release where reverted) did we upgraded to something more recent. To get an idea of the size of this Mason project, the current sites have a little over 450 different components across 7 sites (different layouts but same content) and 1 management site. A lot of those components are no longer in use, and where left there due to bad VCS practices. I would estimate about 200 actual useful components. And it makes heavy use of autohandlers, dhandlers, and multiple component roots, to implement site inheritance.

The E5 template discussion is also still on my mind, without a clear winner yet.

And finally, last week I read Jonathan Swartz article about what Mason 2.0 would look like.

So I took the time last night to re-evaluate Mason. As most powerful tools (and be sure that it is a very powerful tool), the problem with Mason is that you can easlly make a big mess of things. More than with other solutions like Catalyst and Mojo, that provide you with a clear separation of Controller, Model and View, Mason make is very easy to mix the three. You could end up with a lot of logic that should be in your models inside your templates.

But it has several advantages:

  • its easy to start and add a new page. Just create the file and start typing: no need to jump between controller and template, and a restart (this alone makes for speedy development);
  • it has decent wrapper functionality for skinning: autohandlers are great;
  • the multiple component roots logic is very powerful, and its used both during the dispatch phase and component calls;
  • the view logic is Perl: no need to learn a new language and be exasperated with their limitations like TT.

There are several downsides of course: for one, the split of Controller/View of modern frameworks allows you to reuse controller logic with multiple views. For example, you could output HTML, JSON and XML with the same controller code.

But the biggest downside is this: deployment is a bitch.

For production environments, deployment usually means mod_perl but I find FastCGI easier to deploy now-a-days. Yet, this option is only briefly mentioned on the MasonHQ site.

So I created a small experimental project (you can find all the files at the exp-mason-fcgi project on GitHub). It has a FastCGI startup script to power two virtual hosts. Each one shares a master component root, and has a local per-site component root to override the master site behavior when needed.

The setup works just fine under nginx+FastCGI (partial nginx.conf included), but I did get into some trouble. Mason usually delegates some stuff to Apache and without his big daddy around, he can get lost.

The first problem is directory index files. When you request a directory, Apache will help Mason out and point it to the proper index.html file. Without Apache, request to http://your-fastcgi-mason-site/ will just fail, because Mason cannot find the component for /. It has no logic to map / into /index.html for example.

You could implement this with a global dhandler, and it is probably the best solution, because it can also deal with 404 situations (another one that Apache could cleanup after).

I have a proof of concept hack in the repo that mimics the Apache DirectoryIndex directive. It is a hack, it should be in the Interp.pm and not in the Request. I'll clean it up later. But it does work, and it might be useful in some scenarios.

This patch makes a / request work just fine.

The second problem I have with Mason is the order of evaluation of templates. The current order for a request to /index.html is /autohandler which calls $m->call_next and that calls the /index.html component.

This makes it hard to influence the wrapper with content generated by the /index.html component.

The solution was to create a new HTML::Mason::Request method called scall_next(). It merges the $m->call_next() and the $m->scomp() calls into one, and allows me to use it in a autohandler like this. The $m->scall_next() will call the next component, get the generated HTML, and only then generate the HTML wrapper.

The last piece of the puzzle is a way for the /index.html and the parent autohandler to communicate, for example, to pass along the title for the page.

The Mason-recommended way is to use $m->notes() API, similar to the Catalyst stash concept. It works very well, but I prefer to take advantage of the fact that all components live inside the HTML::Mason::Commands namespace and just declare a shared %stash there and clean it up per request. With this, its easy to implement dynamic page titles.


All in all, I keep coming back to Mason. I do like most of what it provides, and for quick sites, it beats all the other alternatives in Perl-land.

A couple of months ago there was some discussion about a option to give web developers that was FTP friendly, in that you could upload your pages to a server and it would just work. Mason is the closest that Perl has to that goal.

But the deployment must be made simpler, and that I one of the things that Mason 2.0 should focus on: make it simpler to deploy.

So my laundry list for Mason 2.0 (and most of them can be implemented on 1.x):

  • FastCGI support out-of-the-box;
  • support for directory index files (without using dhandlers);
  • $m->scall_next;
  • better hooks for debugging and 404 errors.

I don't know. I'm strongly considering go Mason all the way for E5, and if that goes forward, I guess I'll have to write these four pieces myself.

September 16, 2009

Bitten by prototypes

I just spent the best part of an hour around a problem caused by the behavior of Perl prototypes.

I used the following test case to figure it out:

use Test::More tests => 1;
use Encode qw( encode decode );

sub u8l1 {
  return encode('iso-8859-1', @_);
}

my $ola_u8 = decode('utf8', 'Olá');
my $ola_l1 = encode('iso-8859-1', $ola_u8);
is(u8l1($ola_u8), $ola_l1);

The output of prove x.t is this:

t/x.t .. 1/1 
#   Failed test at t/x.t line 12.
#          got: '1'
#     expected: 'Ol?'
# Looks like you failed 1 test of 1.
t/x.t .. Dubious, test returned 1 (wstat 256, 0x100)
Failed 1/1 subtests

The got: '1' had me for quite some time. Until I changed the u8l1() helper to this:

sub u8l1 {
  return encode('iso-8859-1', $_[0]);
}

And it just works.

The problem is the definition of the Encode::encode() function. It has a prototype like this:

sub encode($$;$)

So our @_ is interpreted in scalar context, and so evaluates to the number of parameters, 1.

I don't like it at all because it changes the standard Perl behavior of expanding lists. Its action at the distance. The fact that you cannot pass a single element list is also not mentioned in the documentation.

The only really useful use of Perl prototypes is using a & as the initial char, that allows you to write a function that looks like some built-ins like sort or map, that take a anonymous sub as the first parameter.

September 10, 2009

Log::Log4perl tip

I use Log::Log4perl for all my logging needs. Ok, I lie. I use a wrapper that deals with some stuff that I just don't like with Log::Log4perl, but that is a story for another day.

One thing that we inherited from log4j was the notion that a message can match multiple loggers in your logging hierarchy.

The logic is simple and explained in detail on a Log::Log4perl FAQ entry. If you write something like this in your logger configuration file:

log4perl.logger.Cat        = ERROR, Screen
log4perl.logger.Cat.Subcat = WARN, Screen

which define two loggers. Cat and Cat.Subcat, the second a subcategory of the first, and then use:

my $logger = get_logger("Cat.Subcat");
$logger->warn("Warning!");

you'll get a duplicate message in your log file because it matches both loggers.

I knew that and I always added a line saying:

log4perl.additivity.Cat.Subcat = 0

that prevented this behavior, but this required a line like that per logger. Pain. Not lazy, at all.

But for some reason (stupidity comes to mind) I didn't read the FAQ completely, because at the end, there is a solution. Just put this in your logger configuration file:

log4perl.oneMessagePerAppender = 1

Bliss, pure bliss.

Mind you that oneMessagePerAppender is not compatible with log4j, something that Log::Log4perl tries very hard to be, and therefore this feature is not documented at all except on this FAQ entry.

September 06, 2009

Bootstrap Perl

Whenever a new version of Perl is released, I install it in a separate directory and re-install all my modules into a new local::lib-powered directory.

This takes a lot of time, but I had most of the process already in auto-pilot.

But still it was a hack, so I decided to take the opportunity of the 5.10.1 release and make something more pretty and reliable.

The result is my Perl bootstrap repo.

There are two scripts. The first, bootstrap.sh, will install the local::lib module and prepare the environment. Its still not finished, it doesn't alter the .bashrc file, but it will get there.

The second, install_deps.sh will use the cpan shell to install a local Task::Bootstrap module. This Task has all the modules that I want installed.

There are still some problems. I still lack some distro prefs for a couple of them that pause the process and ask for user input. And some of the modules won't install without force (Mac::Carbon is the one that fails the most).

Other modules just don't install correctly on Mac OS X. Danga::Socket for example, requires Sys::Syscall, but this one fails the tests because Mac OS X lies about sendfile support: the sys/syscalls.ph includes the SYS_sendfile constant, but when you actually call it, we get a Function not implemented. I'm sure I could work around it, and probably fix it, but I no longer use Danga::Socket so I'll probably just remove that dependency.

The other was Mac::AppleEvents::Simple. Finder.app has a different naming scheme for its windows, and t/simple.t was failing. I've send a patch to the module RT Queue.

I still have small failures, but right now, I can mostly use this two scripts to setup a Perl environment from bare metal.

Update: I removed my ~/.perl5/5.10.1/ directory and ran time ./bootstrap.sh. The results:

real 56m4.598s
user 37m17.724s
sys  7m51.923s

So about an hour on a MacBook Pro 2.16Ghz Core Duo, running Leo.

August 25, 2009

Template systems

I have a love/hate relationship with Template systems for quite some time. The following is a brain-dump about where I stand right now regarding which system to use in the E5 project.

When I started using them at work (circa 1998 or 99) the goal was simple: separate programmers logic from the layout so that designers can tweak the templates without breaking the code.

It was a simple and very worthwhile goal. And for the most part, it worked. You still need to coordinate which templates will be created, and how will the page be broken up into pieces to enable reuse of common parts, but it mostly worked.

The template systems where designed to be used by web designers, and given that those where accustomed to HTML tags, the more powerful template system that needed loops and decision constructs opted to create those with a simple syntax. The template systems became domain specific languages (DSL).

But, with the improvement of the HTML, CSS and JS capabilities, I don't know if the designers are still the target audience of template systems. As I split a set of HTML pages into a set of reusable templates, I try to create blocks that make sense in terms of caching, data-store life cycles, and other subtle factors that a web designer just doesn't care about. The page breakout is becoming a engineering exercise.

As programmers/engineers, we don't need the comfy world of a DSL. We want to work in the same language that we use to code. Templates are, at most, a small macro language that gets compiled into source code, in the same language that we have the rest of the system.

So I'm starting to move away from Template Toolkit, my preferred template system, into something that uses native Perl as the DSL. I don't know where I'll end up yet. I'm looking at Tenjin, Text::MicroMason, and Mojo::Template. There aren't many template systems that use Perl as the control language, actually.

The first two should be the most stable ones, older ones. Tenjin is also the fastest template system I've tested, although speed wouldn't be a deal breaker.

Controller-centric or View-centric render process

But we can't judge template systems without considering where and how they will be used. In my case they will the last step of a web request, handled by a web framework.

I'll use a BBC site page to illustrate my current dilemma, an article about Wikipedia page controls. Things of interest to me:

  • the central part of the page is the main content, and directly related the the URL. This is the content that you came here to get. It has a lot of HTML before and after that are present to add value to the site (we hope), and provide exit destinations (the navigation and related stories);
  • the title of the page, early in the HTML, is also directly related to the URL and the story: this is important because the template system must support inside-out rendering (first the central part, and then the wrappers), or have all the information in memory before starting the render process;
  • some parts (the header, footer, and left-hand sidebar) are mostly static, and with low or no relation to the main content: in this case only the category of the article influences the navigation. It might also influence the related BBC sites;
  • the right-hand side shows related stories. The "related" part might be highly dynamic, or static per category or a mix in between. The related external links are probably part of the story.

The path for a typical request (like /2/hi/technology/8220220.stm) looks like this:

  1. collect all the important data from the URL: in this case the it seems to react to the hi/low part to pick the version of the master template, the category (controls the right-hand side column) and the article ID;
  2. fetch the correct article and related informations (author, publish date, picture URL, caption...);
  3. fetch the related articles for the right-hand sidebar;
  4. call the view renderer with all of this.

Pretty basic and straight forward. Steps 1, 2 and 4 don't pose to many questions, they are required on any pipeline I can think of.

But the proper way to do 3 is a matter of discussion. On one hand you can put enough information on the URL to decide what the right-hand sidebar needs and fetch it in with some calls inside the Controller (I'm assuming here a MVC-style framework). In this model the controller prepares everything that we need to display the page.

But this makes the view a bit inflexible because if we need to had another box the top or bottom of the page, we would need to tweak the controller code.

On the other hand if our template system is powerful enough, we can have a small API that we can call back into Perl land, and have these little reusable boxes generated for us. The view controls the entire process of display.

The advantage of having a decent view system, even a object oriented view framework, is the extensibility that you get. Imagine a Moose-based template system: view are classes that you can extend, override, add before and after processing. Rendering is just creating an instance and calling a small method, as_string() or even stream_to_socket().

A system that brings the full power of Perl to the template world is Template::Declare. It treats templates as classes that you can subclass and extend. It seems very similar to what I like but I have zero experience with it so far.

No decisions have been made yet. I need to evaluate Template::Declare and see if it really fits my brain.

August 21, 2009

Start

A beginning is the time for taking the most delicate care that the balances are correct.

from Manual of Muad'Dib by the Princess Irulan

extracted from Dune, by Frank Herbert

In the next weeks I'll be publishing a series of articles about a new project that I'm starting. Actually, I started this project once already, but I didn't like the path it was taking, so I'm restarting it.

The new system will replace the current EVOLUI.COM code base. Why rewrite a system that is in production for 8/9 years and that works reasonably well? There are several reasons actually.

The first reason is code rot: the current system is spread across 3 code bases (called internally E1 through E3). E1 was the first stab (who would guess, right?), and grew organically inside the company, without much planning, and coded by several programmers. E2 added a better management interface, and E3 added a new LMS and forum system.

A lot has changed in the last 8 years. And my inexperience in certain topics shows by the lack of proper tests and documentation. Also, it has grown to 850 Perl packages. Yes, eight hundred and fifty packages. I expect that more than half of those are no longer in active use.

The second, and more important reason, is that the new business requirements require a deep restructuring of the code, but given that we don't have a decent test suite, it would be madness to change stuff in one of those 850 packages.

The way I see it, I can write the new system properly, using a test-driven methodology, making sure that all the business logic is properly tested.

I'm not starting from scratch, I plan to reuse certain small but critical parts of the old system, but going over them to add tests and documentation.

The failed attempt was called E4, so this new version will be called E5.

I plan to cover the following topics (not sure of the order yet):

  • source control, and ticketing systems;
  • project directory layout;
  • documentation techniques;
  • business layer techniques;
  • databases used and ORM layers;
  • web frameworks;
  • template systems;
  • logging;
  • smoke testing;
  • deployment.

Hope you enjoy the ride.

June 18, 2009

Where to put you validation

Yesterday I saw a question by fREW Schmidt regarding where to place the validation code in your apps. I made a mental note to answer it, but as most of my mental notes, it was quickly forgotten.

Today, a new article describes the answer he got. In the end he decided to put the validation inside the model. I can only say: good for you.

But one of the reasons against the validation-inside-the-model that he received baffled me: Models don’t know about the current user (or other higher level information).

If your models don't know who is the person authenticated (and please read Yuval article about modelling identity to understand how complex it can become), then you are doing it wrong.

Models must know who is the authenticated user. They must know it because that is the only sane way to implement authorization inside your methods, and to generate a audit log of operations.

What I usually do is to create a Session class. For each request (be it Catalyst request, incoming email message, or XMPP request), I create a new Session instance initialized with the current user information plus some tidbits like channel (Web, email, XMPP) and IP address (if available).

Then all accesses to my API are either via the session object (create methods to access most important parts of your API), or by passing this session object to the API you are calling.

You should also use your Session as the access point to your logging and auditing capabilities.

The article mentions other issues like error messages. I haven't add the necessity of developing an application with multiple language support yet, but I think that the current throw-exception-objects strategy, with all the information (including the authorized user to figure our preferred language) will be able to deal with the problems that I can think of now.

In the end, I'm actually really curious about why would people think that putting your validation code in the controllers is a good idea.

Update: a lot of stuff in the comments if you care about this topic.

May 23, 2009

local::lib bootstrap

The local::lib module is an essential piece of my workflow nowadays. It allows me to easily keep each project Perl modules separate, and therefore minimize breakage.

Bootstrapping local::lib was reasonably simple but it got a lot simpler with the latest 1.004001 version. Basically you can just pipe the output of a URL into perl to bootstrap it.

The URL is some long beast in the cpansearch.perl.org site, impossible for me to memorize, so I created a shorter version, http:://bit.ly/local-lib. To bootstrap local::lib you now can:

wget -O- http://bit.ly/local-lib | TARGET=target_dir perl

or if you are a curl user:

curl -L http://bit.ly/local-lib | TARGET=target_dir perl

I wish I didn't have to specify the TARGET environment. It should assume, like the previous bootstrap process, ~/perl5. I'll whip up a patch tomorrow.

There is no permalink to the latest version of the bootstrap script, so until I can find a way to alter the destination URL, we are stuck with the current version of it. I do hope a more definitive URL shows up, like the suggested http://install.local-lib.pl/.

The process worked fine for me in a couple of servers around here, but it is not a complete bootstrap. This process installs the local::lib module but doesn't adjust your shell configuration to make the settings stick.

So after you need to run this:

TARGET=perl6 echo "eval  \$(perl -I$TARGET/lib/perl5 \
    -Mlocal::lib)" >>~/.bashrc

(see the local::lib bootstraping section for csh instructions)

Its an excellent service, and it can only get better.

May 20, 2009

Fixing the POD synopsis in OSX – take 3 (take your groff and run)

Marcus started it, Tim teased me. I was bitten so many times by this that I had to take a stab at it.

Following Tim's leads, I checked that the pod2man was producing proper nroff, with a \- for each -. It was. I tried to understand the groff tmac files, but I think we have here the first real proof that there are aliens out there, and they speak wonderful languages...

Anyway, we turned to Google and after a bit of digging we ended up at the groff CVS and a recent change (rev 1.39), just 4 months old so recent enough not to be included with Mac OS X. The description was promising:

tmac/an-old.tmac, tmac/doc.tmac: For -Tutf8, map -, -, ', and ` conservatively to ASCII for the sake of easy cut and paste.

The doc.tmac is important. When pod2man calls nroff, it asks for the an package. The an.tmac basically includes the andoc.tman and that one includes the doc.tman package.

At first I took the diff and tried to blindly apply it to the local doc.tman file. I don't speak alien, so although nroff didn't complain after my changes, it also keep on using the unicode hyphen symbol.

So I've downloaded the latest groff package (1.20.1) and did:

tar zxf groff-1.20.1.tar.gz
cd groff-1.20.1
./configure --prefix=$HOME/bin/groff-1.20.1 \
   --with-appresdir=/tmp/gxditview
make -j 4
make install

You now have your own local groff install, including a brand new nroff.

To test it, I run:

perldoc -n ~/bin/groff-1.20.1/bin/nroff local::lib

Copy and paste something in there with hyphens, like my nemesis --bootstrap, and you should see that your hyphens stay in glorious ASCII, no more of that unicode mumbo-jumbo.

So stick this into your .bashrc:

alias perldoc='/usr/bin/perldoc -n ~/bin/groff-1.20.1/bin/nroff'

And live long and prosper.

Maybe it is possible to take the changes and port them successfully to groff 1.19.2, but I couldn't do it. If you do speak alien and you do port them to the groff shipped with Mac OS X 10.5, leave me a comment. Sticking a new doc.tmac in the `site_tmac/´ directory is a lot simpler than installing groff.

Update: the PROBLEMS file (kudos to this thread where you can follow the whole argument with the same problem in Linux man pages) that is included with groff mentions this problem:

  • The UTF-8 output of grotty has strange characters for the minus, the hyphen, and the right quote. Why?

The used Unicode characters (U+2212 for the minus sign and U+2010 for the hyphen) are the correct ones, but many programs can't search them properly. The same is true for the right quote (U+201D). To map those characters back to the ASCII characters, insert the following code snippet into the `troffrc' configuration file:

.if '\*[.T]'utf8' \{\
.  char \- \N'45'
.  char  - \N'45'
.  char  ' \N'39'
.\}

If you stick the above code into /usr/lib/groff/site-tmac/troffrc the output will be ASCII, even with the default Mac OS X groff, but the perldoc output starts with a couple of blank pages and a warning:

<standard input>:138: warning: can't find font `CW'

So compiling groff is still the best solution.

May 06, 2009

Fast DNS queries with Perl

For some jobs, you need to quickly resolve large amounts of DNS queries.

The AnyEvent::DNS module allows you to resolve DNS queries fast and in parallel.

To test this, I wrote a simple command line tool to check XMPP SRV records of a list of domains. Both server-to-server and client-to-server records will be checked and results printed out. All queries will be made in parallel.

The code is at my Ironman repository. Click the "Raw" link to download (sorry, no direct link, GitHub lacks permalinks to the latest raw version of a file).

April 24, 2009

Asynchronous extension hooks with Perl

My usual projects involve event-driven asynchronous servers, and as a general guideline I try to make them as a set of loosely coupled components, running on the same process space.

To tie them together, I create a set of extension hooks on each component. Those hooks can be used for notification, or for delegation of responsibilities.

For example, in a XMPP component, the Roster controller usually has two hooks, new_buddy, and accept_as_budy.

The first can be hooked by other components to be notified of new contacts that where accepted as buddies. For example, if you wanted to send a welcome message, or create some files or directories per buddy, this is the hook to use.

The accept_as_budy is different. The Roster component wants to delegate the responsibility of deciding if a specific JID should be allowed or not to become your buddy. When we receive a <presence type='subscribe' /> request, the Roster would execute this hook, and all other components that want to weight in on the decision can give their opinion, accepting, refusing, or ignoring the request.

The usual system for these type of extension points is a set of coderef's that you register per hook. Those coderef's are executed in turn, and have some way to signal back their decision, either by returning a specific return code, or by calling a method in a event object that the hook system creates per invocation.

There are a lot of such systems at CPAN. Some examples, in no particular order, are: Event::Notify, Object::Event, Class::Observable and Class::Publisher.

All of those modules allow you to create hooks, accept registrations from other components, and then invoke the hooks with a set of parameters that all of those handlers will have access to.

The problem starts when you want to use these approach inside an event-driven asynchronous application, and one of the handlers of a hook needs to block. For example, if one of my components needs to do a couple of HTTP or memcached queries to decide if a specific buddy can be accepted, the above classes wont work anymore. The usual implementation of these systems keeps the execution control inside themselves with a loop over all the registered handlers, calling them one by one in turn.

In an asynchronous app, we would like to allow each handler to start some asynchronous request and make the decision after he gets the response. We should be able to start an HTTP request to check a specific JID, and then, when we get the response back, decide if we want to accept, reject or ignore this buddy.

The first time I found something like this was inside DJabberd code base. DJabberd is a XMPP server where everything is a plugin. The server has a lot of hook points that you can register handlers for. Each handler gets the parameters, and a set of functions that he can call to accept, deny or ignore the current event. Each handler can do whatever he wants, including starting other requests, and when he has all the information to decide, call one of the functions.

The problem is that the code was not isolated for reuse by other projects. So I took most of the ideas, and created Async::Hooks.

Async::Hooks allows you to create hooks or extensions points in your code. Other interested parties can hook a coderef that will be called whenever the hook is used.

Each handler receives a control object. The control object has access to all arguments passed at the time of the hook invocation, and a set of methods to move to the next element in the chain, or to stop processing altogether. You are required to call one of those methods when you are done with the event. The next handler will only be called if you do that.

Usage is simple. You start by creating a Async::Hooks instance. This acts as a registry for hooks and its handlers. There is no need to pre-declare hooks. Usually I use a singleton pattern for my registry, and hide everything inside a small class:

package App::Hooks;

use strict;
use warnings;
use base qw( Exporter );
use Async::Hooks;

@App::Hooks::EXPORT = qw( hooks );

{
  # Hide my hooks
  my $hooks;

  sub hooks {
    return $hooks ||= Async::Hooks->new;
  }
}

1;

This gives us a hooks() function that returns the same Async::Hooks instance every time.

Registering a handler is simple:

hooks()->hook('accept_as_budy', \&check_bad_jids);

Handlers will be called in first-come-first-served order. There are no mechanisms to alter the order of handlers. I never needed such features, but the plan is to include a simple Async::Hooks::WithRank class in the next release, that will provide a simple rank-based order. Other mechanism would be possible after that, you just need to subclass the main class and implement a sort() method.

To invoke a hook, you simply do:

hooks()->call(
    'accept_as_budy',
    [ @args ],
    \&reply_to_presence_subscribe
);

The reply_to_presence_subscribe coderef is optional. If present it will be called last.

Each handler receives a control object and a copy of the arguments:

sub check_bad_jids {
  my ($ctl, $args) = @_;
  ...
}

The $ctl object provides you with the tools to communicate your decision. You can $ctl->next or $ctl->decline to move forward in the chain, or you can stop processing with $ctl->stop or $ctl->done.

So if your keep a web service for bad JIDs, you could do something like this:

sub check_bad_jids {
  my ($ctl, $args) = @_;
  my $jid = $args->[0];

  http_get("$webservice_endpoint/jid/$jid/is_bad", sub {
       my ($resp) = @_;

       if (defined($resp) && $resp eq 'BAD') {
         $ctl->done;
       }
       else {
         $ctl->next;
       }
  });
}

The http_get() function is part of the AnyEvent::HTTP module, and performs a non-blocking asynchronous HTTP GET request. The callback is called when the response arrives with the data in the first parameter. If the call was successful, the response is defined and contains the body of the response.

The call to done() will skip all other possible handlers and call the \&reply_to_presence_subscribe given in the call() invocation. This cleanup callback will receive the same arguments as all other handlers, and a third parameter, a $is_done flag. It the chain ended with a call to done() this flag will be true.

I really like this approach to hooks. Although there is a lot more responsability on the side of handler programmers (they must remember to call $ctl->next() or $ctl->done() sometime), it also allows for several different scenarios. In the example above, the hook is for delegation of responsibility so it makes sense to call next() only after a decision has been made, but you could also have handlers that are only interested on the fact that someone requested to be your buddy, not the outcome, and those handlers can start a background process and call $ctl->next() immediately.

In fact, you can use Async::Hooks even inside a more synchronous program: you are not required to delay your calls to next() or done().

Currently at version 0.5, it has most of what I need. Next versions will have the possibility of ordered handlers, with a basic rank-based example, and a better way to communicate our decision to stop, or ignore the current event.

Walk like an iron man

Matt Trout and friends came up with an idea of a small game to start people blogging about Perl.

The rules are simple:

  • blog once per week;
  • every week.

The definition of week is a bit lax, allowing you have at most 10 days between posts.

Mine will appear under the Perl category, and if you want to follow just those, you can subscribe to the Perl category feed.

March 08, 2009

My own entry to the UGFWIINI contest

Some weeks ago, Johannes Schindelin talked about the UGFWIINI (Use Git For What It Is Not Indended) contest. You can read the initial candidates in the git mailing list thread.

A couple of months ago, I had this idea of writting a script that would constantly watch over a directory (including subdirectories) and commit the changes every time anything would change.

At the time, the tought of battling the FSEvents interface was not appealing at all, and it was just a joke anyway. But in the since then several things happened:

So I had no chance but to write such a script.

My version is a quick hack, but already works perfectly. It watches a specific directory, and commits all the changes to a standalone Git repository.

To use just do:

cacm --repo dir_of_git_repo --watch dir_to_watch

and it will start recording your changes with git commits.

Right now, it commits at most once per 5 seconds, but you can tweak that using the command line option --latency latency_in_seconds.

I've uploaded version 0.01 to CPAN. To install just do cpan App::CMAM (it might take 24 hours to spread to your CPAN mirror).

For version 0.02 I'll clean some small details:

  • ignore .git and other common directories;
  • cleanup git invocation: all the output should be hidden from you.

Fun!

March 06, 2009

Easy yak shaving with git-cpan-init

In a decent sized session of yak shaving, I found a new beautiful tool: git-cpan-init. If need to hack on a CPAN Perl module, git-cpan-init will:

  1. init a new git repository in the current directory;
  2. fetch the module tarball;
  3. unpack it, and commit that version to git, tagging it with the version number.

This leaves you with a ready-to-hack git repo. But it doesn't end there. After you added your fix or feature, you can use git-cpan-sendpatch and this will:

  1. create a patch with your modifications;
  2. create a RT ticket with the patch.

Instant gratification!

So I had no excuse to patch Net::Libdnet to use dnet-config to find the location of the libraries and include files. It was easy as pie.

In the process I also fixed a warning with git-cpan-import, but yannick was already using git to host Git::CPAN::Patch, so it was even easier.

December 22, 2008

Perl switched to Git

I was following the conversion process for some time now, but the final switch was done today. The development of Perl is now maintained using Git.

The repository includes all released versions of perl up to the most recent 5.10.0 and will take 219Mb of your hard disk.

"Higher-Order Perl" available as free PDF

The best Perl book in recent years is now available as a free PDF download.

If you are a Perl programmer, even an experienced Perl programmer, you should read this book. Chapter 3 in particular.

Go and get your copy of Higher-Order Perl, by Mark Jason Dominus. And if you end up with your mind blown away, buy a copy.

November 06, 2008

AnyEvent::Mojo 0.6

Uploaded to PAUSE AnyEvent::Mojo 0.6, should hit the CPAN mirrors throughout the day.

Update: uploaded 0.6001, with an attempted fix for some 100% CPU usage cases.

The major change is the renaming of AnyEvent::Mojo to AnyEvent::Mojo::Server.

There are two reasons for this change. The first is to prepare the release of AnyEvent::Mojo::Client in the next release, wrapping the Mojo::Client API.

The second is to free the AnyEvent::Mojo to be used with the new functional API.

Starting a Mojo server inside your AnyEvent apps is now very simple:

use AnyEvent;
use AnyEvent::Mojo;

my $server; $server = mojo_server undef, 4323, sub {
  my ($self, $tx) = @_;

  $tx->res->body('Cool!');  
};

$server->run;

The interface is similar to AnyEvent::Socket.

This is the first beta release. I don't expect to change the API in a backwards incompatible way until 1.0.

I do plan the following for the next releases:

  • implement AnyEvent::Mojo::Client and the correspondent mojo_client function;
  • implement support for 100 Continue.

Mojo is fun!

Oh, and please vote for the Perl Foundation grant to improve Mojo.

November 04, 2008

AnyEvent::Mojo now with resumable requests

I've uploaded to PAUSE (give it a couple of hours to appear on your local CPAN mirrors) the latest release (0.5) of AnyEvent::Mojo.

The biggest change is the new resumable requests. After your handler is called, you can pause the connection, do other stuff using the AnyEvent asynchrounous nature, and when you are ready to send back the response, you can resume the request.

In pratical terms, this is now possible:

sub my_handler_cb {
    my ($self, $tx) = @_;

  # Pause the connection while we HTTP GET our information
  $tx->connection->pause;

  # This HTTP get is done asynchronously
  http_get $status_url, sub {
      my ($data) = @_;
    my $res = $tx->res;


      if (!defined $data) {
        $res->code(503);
      }
      else {
        $res->body($data);
      }

      # Ok, the response will be sent now
      $tx->connection->resume;
  }

  # We paused the connection so we can return
  return;
}

While the inner http_get is going on, the AnyEvent::Mojo server can handle other requests.

This allows you to keep several thousands of requests going on without any effort at all.

I'm still labeling AnyEvent::Mojo as alpha. The interface will change one last time for 0.6. After that it should be beta time until 1.0.

I need to find a decent WebSockets client implementation (or some sort of long-pooling client) to make a decent application with this. Any recomendations?

October 25, 2008

AnyEvent::Mojo uploaded

Update: uploaded version 0.04, fixes two small things: I was using pre-release 0.8 of Mojo, and apparently I don't know how to use requires in Makefile.PL, causing a stream of CPAN tester failures.

Sebastian Riedel released version 0.7 of his new HTTP stack Mojo (also includes a tiny web-framework called Mojolicious).

The code is very very nice and clean, and in the future you might be able to run Catalyst apps on top of it.

Given that I was looking for a small web framework to run inside my long-lived AnyEvent daemons, I wrote a small glue module to run Mojo-apps using the AnyEvent::Socket/AnyEvent::Handle goodness.

The module is AnyEvent::Mojo, and I've just uploaded release 0.2, that includes keep-alive support.

There are three features that I want to do before a 1.0 release:

  • Support for 100 Continue handling: I don't use it but the other Mojo::Server classes have it;
  • Asynchronous processing of requests: you start processing a request, but decide that you need something from a network service somewhere. You can start that request, pause the Mojo transaction, and when you receive the response from the network service, you complete the Mojo transaction;
  • build a AnyEvent HTTP client using Mojo::Client.

Fun stuff, specially the second one.

Performance-wyse, I'm happy with the result so far. The most simple Mojo::HelloWorld application is capable of this numbers:

# Start a server
perl -MEV -MAnyEvent::Mojo -e 'AnyEvent::Mojo->new->run' &

# Benchmark
ab -k -c 10 -n 5000 http://127.0.0.1:3000/

# Executive summary
Concurrency Level:      10
Time taken for tests:   6.935770 seconds
Complete requests:      5000
Failed requests:        0
Write errors:           0
Keep-Alive requests:    0
Total transferred:      795000 bytes
HTML transferred:       190000 bytes
Requests per second:    720.90 [#/sec] (mean)
Time per request:       13.872 [ms] (mean)
Time per request:       1.387 [ms] (mean, across all concurrent requests)
Transfer rate:          111.88 [Kbytes/sec] received

# (Quad-core 2.6Ghz, Mac OS X 10.5.4, stock perl 5.8.8)

At 700 requests per second with a 1.3 ms delay, the overhead seems to be pretty low, for a pure Perl based HTTP 1.1 compliant server.

October 18, 2008

Stitcho

There is this new network notification service called Stitcho. Think Growl (which they support) but with a HTTP-based API.

Its still in beta, but works pretty well. I've found some problems with UTF8 encoded strings and I have an open ticket on that.

I've released a Perl client library to CPAN, Net::Stitcho. It allows you to use it from your Perl programs easily. Its not feature complete yet, only the send message API is supported, but it should have the signup API today.

Its not clear to me the business model behind Stitcho, and getting this deployed widely enough to make a difference is also a challenge, but I like the concept so lets see how it goes.

Update: the Net::Stitcho module is, as of version 0.03, feature complete.

September 19, 2008

Perl and database access

The base of all database work with Perl is the DBI module. There is no possible argument about this.

If you need something more high-level, things get dicey.

For the last 2 years I've been using the most excellent DBIx::Class. From all the ORM's that I've used so far, it is the best one out there and I still recommend it if you want to get up and running fast (quick tip: start with DBIx::Class::Schema and the load_namespaces() API, do not use load_classes()).

DBIx::Class has some great features:

  • comprehensive test suite: self-explanatory;
  • extensible: you can add pretty complex things on top of DBIx::Class. You can override every method using the magical Class::C3 foundation;
  • manage schema versions: you can use your DBIx::Class::Schema to manage your SQL schema, including versioning and updates. Some manual tweaking is required, no out-of-the-box tool to do this for you, but that's expected anyway;
  • nested transactions: this is killer feature for me. I've worked on a system (IPGng::SQL for those who know what that is) in the past (2001/2003 timeframe) that has this also, and it makes your code much more robust and simple.

Not everything is a good fit for me, though. There are two main sticky points.

The first is the use of SQL::Abstract as the query representation language.

Learning a new language that I can only use in the context of Perl is a personal waste of time. I have been using SQL with Oracle, MySQL, Postgres and SQLite for quite some time, and I can pretty much do whatever I need with it. Even when I hit a wall, I have a couple of Celko books behind me that usually help me jump over them.

So for me, the SQL::Abstract advantages aren't actually.

The second sticky point is a mismatch between DBIx::Class and my needs in terms of Object-oriented modeling.

Usually I have one entity in my object model (say for example Members) that is mapped to multiple tables (personal data, login information).

With DBIx::Class, I have the business logic dispersed into Result and ResultSet classes, per table, not per entity. This sort of works, but I find it messy for more complex projects.

So for a new project that I'm starting, I'm not using DBIx::Class. I don't have a full replacement, just parts that I'm enjoying putting together.

The first two modules that will be part of the final solution are DBIx::Simple and SQL::Interp.

They provide the minimal set of tools that such lower layer over DBI should have.

Above that, I'm still working on it. So far I have a wish list:

  • transactions: nested transactions with commit/rollback hooks;
  • DSL for schema versions: must have data dictionary features.

The first part will probably be a small Transaction module. I'll most likely use code like the txn_do of DBIx::Class::Storage, I like the syntax very very much.

The commit/roolback hooks are required because I need a "almost" two-phase commit protocol.

Picture this: you have two systems, a transactional database and a non-transaction messaging/pubsub system. Inside a DB transaction, you publish some events. If those events reach subscribers before the DB transaction is committed, they will not find the DB up-to-date.

What I need is to delay the actually publishing of the events until the final commit of the DB.

The second wish is a DSL that I can use to generate the SQL, with tools to manage upgrades between versions. This will be a SQL::Translator-based project, with a Parser class for my DSL.

This allows me to use all the Producers that the SQL::Translator project already has, and also the tools to diff SQL schemas.

The data dictionary part is the important feature. I want to declare types, including Perl code to validate and format values, in a central place, and then use them in the schema.

This DSL must generate also some base set of classes that you can extend with custom behaviors. This also provides a introspection interface that can be used to generate HTML forms and validation profiles.

Its seems a lot of work, and it is. But its also an incremental process going back some years, and I don't mind the wait.

September 04, 2008

Need script: extract common .pm files from multiple directories

I'm re-factoring an old site where the art of source control went out the window somewhere in the past.

The current problem I'm trying to solve is multiple versions of the lib/ directory, each one with their own copies of the same .pm files, but some of them with local modifications.

As a first step I want to create a single central lib/ that will take files that are the same on all the other directories.

We can automate the process by using Digest::SHA1 on each file. If their signatures match, then they are the same file, and can be moved to the central lib/.

Before I write this, does anybody has this script written? Thanks!

September 02, 2008

Pretty and useful

If you thrive to achieve a stress free life, and keep programming at the same time, I assume that you know how automated testing and test-driven development are an essential tool.

I've been using them for most (not all) of what I do in the last year or so. Basic stuff, using Test::More and friends, and more recently Test::Most and using the basic prove tool and Devel::Cover for extra peace of mind.

I was reading the latest edition of the Test Automation Tips and they mentioned Smolder and another Perl module. I knew Smolder already. It is one of those tools that I always keep on my list to install someday, but never get to do it because I expect it to be hard (without any reason to think that, mind you).

The other module is TAP::Formatter::HTML and it just blew my mind. Simple installation with cpan TAP::Formatter::HTML, a single tweak to my run_all_tests.sh script and gorgeous looking HTML reports. I don't have them online but you can look at a sample report (be sure to click around).

Strongly recommended.

August 22, 2008

CPAN::Mini::Webserver++

The CPAN::Mini::Webserver module is getting a lot of love in the last few weeks.

The most recent 0.40 version includes a lot of goodies including:

  • act as a true CPAN mirror so that you can point you cpan client to it;
  • syntax highlight of Perl code;
  • Bonjour registration: easy to find on a local lan;
  • shows which modules are installed locally;
  • A lot more meta information shown about each module.

Getting everything right is easy.

Installing CPAN::Mini

First, you need a CPAN::Mini mirror of the full CPAN. Right now it takes 862Mb of my disk.

Create a .minicpanrc in your $HOME directory with the following:

local: /Users/melo/Documents/cpan
remote: http://cpan.perl.pt/
also_mirror: authors/00whois.xml

Adjust the local and remote settings to a local directory where the mirror will be placed and the CPAN mirror you wish to use.

Then run minicpan. You can stick this in your own crontab, also . I run mine each morning at 10:20.

The first time will take a bit of time, but updates are very fast. Recent versions of CPAN::Mini use HTTP keep-alive, so I recommend that you use a HTTP-based mirror.

You can take the opportunity and update your cpan configuration to use this module. To do that, run the cpan client, and use o conf init /urllist/. Keep you current mirror and add the new local directory at the end of the list. Don't forget o conf commit to make your changes persistent.

My configuration looks like this:

cpan[1]> o conf urllist                                                                                                                                                                                      
    urllist           
       0 [http://cpan.perl.pt/]
       1 [file:///Users/melo/Documents/cpan/]

Having a HTTP mirror and your local mirror this way triggers an optimization in the cpan client. He will always keep the module indexes up-to-date using the external mirror, but for each module that he needs to install, the local mirror is tried first.

Installing CPAN::Mini::Webserver

Install tht CPAN::Mini::Webserver. You will also need to install the plugin HTTP::Server::Simple::Bonjour and a proper Net::Rendezvous::Publish::Backend module for your operating system (I use Net::Rendezvous::Publish::Backend::Apple).

Running CPAN::Mini::Webserver

You can now run minicpan_webserver and open http://localhost:2963/. You can change the port number with minicpan_webserver -p PORT.

You can also keep it running by sticking this on the inittab or if you use a Mac, use Lingon and create a "My Agents" entry to keep it running. I use the second option.

Bonjour workaround

On a last note, the Bonjour stuff doesn't work since 0.39. CPAN::Mini::Webserver is overriding the print_banner method that the Bonjour plugin uses. I've reported this as a bug.

There is no easy way out. Probably the best way is to add a new init_plugins hook to HTTP::Server::Simple that gets called before the print_banner and then change the Bonjour plugin to use that.

On my copy I patched CPAN::Mini::Webserver directly and commented the print_banner function. I prefer to have Bonjour than a prettier banner I never get to see anyway.

August 05, 2008

XML::LibXML braindead, or is it just me?

I spent the last 30 minutes chasing down this bug. The following tests should all pass but the last one doesn't:

use strict;
use warnings;
use Test::More 'no_plan';

use XML::LibXML;
use XML::LibXML::XPathContext;

my $parser = XML::LibXML->new;
ok($parser, 'XML::LibXML parser created');

my $xml = '<x:me xmlns:x="some_namespace" />';
my $xdoc = $parser->parse_string($xml);
ok($xdoc, 'Valid XML parsed');

$xdoc = XML::LibXML::XPathContext->new($xdoc);
ok($xdoc, 'Converted to XPathContext');

my ($node) = $xdoc->findnodes('/me');
ok(!$node, 'Not found because no prefix means NULL namespace');

($node) = $xdoc->findnodes('/x:me');
ok($node, 'Found because using document prefix');

$xdoc->registerNs( new => 'some_namespace' );
($node) = $xdoc->findnodes('/new:me');
ok($node, 'Found because using new specific prefix');

# Notice the change of namespace
my $uri = $xdoc->lookupNs('x');
is($uri, 'some_namespace', 'x prefix is some_namespace');
$xdoc->registerNs( x => 'other_namespace' );
$uri = $xdoc->lookupNs('x');
is($uri, 'some_namespace', 'x prefix is still some_namespace');

($node) = $xdoc->findnodes('/x:me');
ok(!$node, 'Not found because using document prefix was changed to diff namespace');

The basic problem is this: you get a XML document in which a namespace N is tied to a prefix P. I was expecting that if I set in my own parser prefix P to something else, that my local prefix P would take precedence over the document P. Apparently it does not.

Right now, what I did was this: before using XPath to match anything, I always used registerNs method of XML::LibXML::XPathContext to make sure I was getting the right elements. Now, I use this new function instead:

sub _safe_ns_register {
  my ($xpc, $prefix, $ns) = @_;

  while ($xpc->lookupNs($prefix)) {
    $prefix++;
  }
  $xpc->registerNs($prefix => $ns);

  return $prefix;
}

This function makes sure that the prefix I choose does not clash with any prefixes on the document. It returns the prefix I must use on my XPath expressions.

It solved my problem, but I still think that my local prefix should take precedence over the document one.

June 30, 2008

Behind the scenes of Tarpipe XMPP

Alex and Adam asked me to elaborate on the tools I used to implement the Tarpipe XMPP gateway.

I used the Net::XMPP2 Perl module, in particular the Net::XMPP2::Component class. It uses the AnyEvent async framework, which in turn support the EV library , giving you all the love of kernel polling.

Until the Net::XMPP2 author releases a new version, you should use my own copy if you plan on doing external component work (check the component-reply-with-from branch). Net::XMPP2 is widely used for bots, but not that many components, and some methods need some love to work properly in a component environment.

The HTTP part was done using the excellent AnyEvent::HTTP class. I'm using my own version, which includes a bug fix to the http_post function (on its way to release 1.03 of AnyEvent::HTTP) and adds support for HTTP::Request to http_request. I hope to see this included in the main AnyEvent::HTTP distribution but I still need to update the documentation.

The rest is just glue code.

May 11, 2008

Yada, yada, yada

From the quickies department, the Stubby exception generators (search for stubby) made it to Perl 5.

April 12, 2008

Rethinking CPAN

Andy Lester wrote an article a couple of days back about rethinking the CPAN interface. The key part of the argument is:

We don't want to "make CPAN easier to search." What we're really trying to do is help with the selection process. We want to help the user find and select the best tool for the job

I though a bit about this and my own CPAN usage over the years. I've started with Perl around 91 or 92 so I've used it a bit.

I don't know the answer for this one, but I would start with the Perl module version of the iusethis site: each person could select the list of modules that they use.

This first approach would start shuffling modules to the top.

You could then ask each person to classify why are they using the module. This is the hard part because you would need to come up with a classification scheme, like the one we still have for CPAN module, actually. It will never be perfect but I prefer to have 10 or 20 common things like "Parsing XML", or "Sending MIME email" than nothing.

An optional improvement would be to have a 4 or 5 level rank, inside your own module list, to allow you to say that, DBI is much more important than CPAN::Mini.

Another layer would be some sort of social angle. This is not to make the site look hype and fresh, but to help find new modules. I could watch a couple of persons I trust and see what are the modules they are using and the most recently added. Instead of looking through 50+ modules updates per day, I just see a filtered list of potential targets.

A final twist - a aging digg-like system: I can "This saved my bacon today"-vote on any module, but my vote would only be counted for a month, giving rise the the Bacon Savers list.

But as always, you need a carrot to make all those perl programmers compile their module list. There are two immediate carrots that I can see:

  • selective CPAN announcements: if a module on your list gets an update, you would get a notification (daily email, weekly email, or personalized RSS feed);
  • a automatic Bundle module, or Task module to install all your modules: I would not upload all this modules to CPAN, but we could create a perl script that downloads my Bundle or Task and calls the classic cpan to do the heavy lifting.

Anyhow, this are my €.02 to the conversation.

March 13, 2008

Link files in Catalyst error messages to Textmate

When you develop with Catalyst, if you have an error condition, you get a pretty interface with access to all the major objects in the request.

At the top, Catalyst will place the classical perl error message like "Caught exception in MODULE, at FILE line LINE."

This hack takes that classical format and links the "FILE line LINE" with a txmt: link. If clicked, it will open directly into your project in TextMate.

The code is simple. Stick this into your main application class:

sub finalize_error {
  my $c = shift;

  $c->NEXT::finalize_error(@_);
  return unless $c->debug;

  my $error_msg = $c->response->output;
  return unless $error_msg;

  $error_msg =~ s{(\s+at\s+)([\/]\S+)\s+line\s+(\d+)}
                 {"$1<a href='"._mk_textmate_link($2, $3)."'>$2 line $3</a>"}ge;
  $c->response->body($error_msg);
}

use Cwd qw( abs_path );
sub _mk_textmate_link {
  my ($file, $line) = @_;

  my $abs_file = abs_path($file);
  return "txmt://open/?url=file://$abs_file&line=$line";
}

It works for me so far. If this breaks anything for you, you get to keep both parts.

Here is a sample of the output with this hack applied (click for bigger version):

Safariscreencapture004

Update: a new version. The big change is the use of the abs_path method to make sure you get the absolute path. This solves problems that I was having with symbolic links. TextMate was opening a new window, because the project and the file path in the error message had different prefixes.

March 07, 2008

perl warnings

You have to learn to ignore the forrest.

There are some perl warnings that hide the real problem. My most hated perl warning is this, the first three lines below:

"my" variable @prob masks earlier declaration in same scope at sbin/some_script line 1640.
"my" variable $count masks earlier declaration in same scope at sbin/some_script line 1641.
"my" variable $t masks earlier declaration in same scope at sbin/some_script line 1642.
syntax error at sbin/some_script line 1504, near "next "

Those lines are there because the parser had to bail out after detecting the error on line 4, and failed to notice the end of scopes.

This could be less of a problem if the warnings and errors where ordered by line number, but they are not. So learn to look at the line numbers first to decide which warning to pay attention to.

March 04, 2008

Perl hackers using Git

I was wondering if all Perl hackers that are using Git, do you keep a separate repository for each module, or a single repository for all your modules?

February 04, 2008

You'll be assimilated...

... eventually :).

I actually did use IPC::MorseSignals to try a stupid idea. It worked as advertised, although it did not solve the idiotic nature of the solution.

But it sure was fun.

January 25, 2008

Bug of the day

In a project for a client:

# remove duplicate raw lines
my $dups = $self->dups;
return if $dups->{raw}++;

Should have been:

# remove duplicate raw lines
my $dups = $self->dups;
return if $dups->{$raw}++;

No wonder all lines except the first where dups...

January 11, 2008

Help.pm

Amazing article by Mark Dominus, explaining the code of a simple but very useful class Help.pm.

January 08, 2008

DTrace'ed perl

Cool. Bleadperl runs without delays with dtrace enabled.

I wonder if this will make it to 5.10.1, hope so.

December 20, 2007

cpan tricks

Our beloved cpan command line has some tricks up his sleave. In case you haven't read the fine CPAN manual in a while, let me point out some features I'm using right now to install all the needed modules for my day-to-day operation.

cpan .

You have a local directory with a module already unpacked, or your own personal module. The usual way to install them is doing the dance:

perl Makefile.PL
(manually deal with missing dependencies here)
make
make test
make install

The second step, the missing dependencies part, is the not so good part of the whole experience. Module::Build authors and users would suggest that the first step is the really not so good part, but I digress.

A better way is to do:

cpan .

This will start a CPAN shell, and run the install process on the local directory, including fetching dependencies from you preferred CPAN site.

failed command

Inside the shell, after you installed a long list of modules, the failed command will list all the modules that failed the tests and did not install.

o conf init /REGEXP/

The command o conf init will go through the entire configuration process. In recent versions it has become a long process and one of the things I tweak from time to time, the URL list of CPAN mirrors, is the last item asked.

To speed up the process you can o conf init /urllist/ and only configuration options matching urllist will be asked.

Don't forget to o conf commit at the end.

The smart CPAN urllist

The urllist parameter lists the CPAN mirror sites that the shell will try to use to fetch the packages.

My favorite site is a local CPAN::Mini mirror, the best 750Mb used space I have on my systems. It allows me to install any module from CPAN even when I'm offline.

But this requires that I keep updating the mirror, and sometimes, I just forget. And I don't want to cron it because I don't want to run it while I'm connected via UMTS.

A trick here is to set urllist to several CPAN mirrors in your country and include your local CPAN::Mini mirror at the end with a file: URL.

CPAN is smart and will fetch the CPAN indexes from one of the sites (see o conf init /random/ for some fun) but will always try to download the actual package from the file: url first.

So you get up-to-date indexes for free.

5.10

Just a quick word pointing out that perl 5.10 was released the 18th, 20 years after the first perl release. As Grubber says, Perl is the best language in the world. At least to both of us.

The 5.10 release adds a lot of improvements to Perl over the 5.8.x series. I would recommend that you take the time to read through perl5100delta, it should take less than an hour, but its definitively worth it.

My list of favorite features, in order:

The first will make DBIx::Class, Catalyst, and Moose faster and the second provides a clean path to add new features in future versions of perl.

The third is just too cool for words. You have to see it in action. It's a back-port of a Perl6 operator. As always, Perl has no shame to copy from the [rb]est, even from projects still in development.

The last one brings perl on par with other engines out there, and adds a nice non-recursive implementation and other performance improvements.

Congratulations to all perl-porters out there.

December 04, 2007

Catalyst Advent Calendar

It's back! The new and improved 2007 Catalyst Advent Calendar. (Un)Fortunately its not a swim-suit edition yet.

The entry for today is about using the Open Flash Chart component, my favorite Flash-based chart component. It also uses the recent OFC::Chart module.

I just wish that the Calendar had a title attribute on each daily link. Finding the correct article can be painful without that.

December 02, 2007

Perl preforce-to-git conversion

Very cool job by Sam, the current status of the Perl preforce-to-git conversion.

Preforce was indeed very advanced ten years ago.

November 20, 2007

Wide-Finder and Perl

The Wide-Finder project has been a lot of fun. For those who think that it is not a real-world problem I'll leave you with a quote from the Wide-Finder results page:

Worth Doing · There is a steady drumbeat of commentary along the lines of “WTF? This is a trivial I/O-bound hack you could do on the command line, ridiculously inappropriate for investigating issues of parallelism.” To which I say “Horseshit”. It’s an extremely mainstream, boring, unglamorous file-processing batch job. There’s not the slightest whiff of IT Architecture or Social Networking or Service-Orientation about it. Well, that’s how lots of life is. And the Ruby version runs faster on my Mac laptop than on the mighty T5120. The T5120 is what most of the world’s future computers are going to look like! Houston, we have a problem, and the Wide Finder is a useful lens to examine it.

Anyway, last night I noticed that the top spot is now a Perl program by Sean O'Rourke. Its an extremely simple program, about 60 lines long. Worth a quick read.

Congrats Sean!

November 08, 2007

Test::Harness and Devel::Cover

I've been using the alpha/beta's versions of Test::Harness for a couple of weeks now, and I'm very happy with them.

This week, Test::Harness 3.0 was released so it should start to flow naturally to all of you unsuspecting users. There are people more qualified than me to tell you what was changed and why it is a worthy upgrade.

One thing that I noticed during the beta phase was that the HARNESS_PERL_SWITCHES environment variable is no longer supported, so the classic way to run your tests under Devel::Cover:

 HARNESS_PERL_SWITCHES=-MDevel::Cover prove -l t/*.t

no longer works.

Until bug 25559 is fixed (patch is available in the ticket), the last recipe in the Devel::Cover perldoc works:

PERL5OPT=-MDevel::Cover prove -l

(you no longer need t/*.t with the new prove).

Happy testing!

October 10, 2007

MySQL Community server with CentOS 5

In case I need this again. After installing the official RPMs from the MySQL site for Redhat Enterprise Linux 5 on a fully patched CentOS 5, the startup script does not work properly, failing to start the server:

[root@centos5 log]# /sbin/service mysql start
Starting MySQL Couldn't find MySQL manager or server        [FAILED]

One possible solution is this patch. To apply do:

cd /etc/rc.d/init.d
patch -p0 < PATH_TO/mysql.rc.patch

And be done with it.

Also useful for DBI-related work is this. Log in to MySQL server as root and do:

grant all privileges on test.*  to 'melo'@'localhost';

Adjust melo for your local username.

This will make the installation of DBI and DBD::mysql work out of the box with cpan, testing everything in the process.

September 13, 2007

Sane policy for cyclic module dependencies

In medium-to-large Perl projects (case in point has 164 .pm files, far from over), cyclic module dependencies can become a issue.

Usually I use a lot of Module::Pluggable stuff, coupled with registry-style approaches. So each module is dynamically loaded based on his namespace using Module::Pluggable and registers itself into the core application.

The problem usually crops up when some registry class also requires a module that uses its services. For example, a registry module that uses a DBIx::Class schema, and some of the Tables use that same registry.

If your Registry class uses the your Schema, to make sure it is loaded, then the definition of the registry method will not be available when the Table classes are loading.

There are several possible solutions to this.

First, you could simple split your Registry class into a simple Registry and Registry::DB methods. This way, the Registry will not have the Schema dependency and all will just work. I don't like this much because the split is not natural in some situations.

Another approach is to limit the uses on each module to the minimal number of classes you need to load the module. In this case, the Registry doesn't need to use the Schema class if he doesn't require it during the compilation phase. If you only use the Schema in some methods, you only need to make sure it is loaded at the time of the method call. This can be scary if you look at the code and see a module being used without the proper use first.

A third approach is to do the least amount of stuff during compile time and use the INIT or CHECK blocks to do the proper initialization of your modules. This would be my favorite but I'm uncertain of the problems with mod_perl. (on a side note, be sure to check the proper documentation to learn about these Perl blocks: the begincheck program in there is very enlightening).

In the end, I usually use a combination of the first two. I do plan to see what are the caveats with INIT and CHECK in mod_perl, given that it would be a much better approach.

September 06, 2007

if unless

In Perl, you can do something like VERB if CONDITION or VERB unless CONDITION.

There is not clear rule about which one to use, and I can say that I've preferred one of the other at different parts of my Perl-life.

Recently, I've settled on a simple rule to decide which one to use. The decision is based on the type of CONDITION that follows.

For me, something like 'CONDITION && CONDITION' is much easier to read and understand than 'CONDITION || CONDITION'. The reason is simple: the first, using &&, has less positive outcomes, and usually thats the one you are testing for, so my brain doesn't need to keep several possible options in my memory. I can short-circuit and forget what was before the && as soon as I decide that it is true.

So my current rule is simple: use the one who converts your condition to a &&.

So if I have:

return unless $estado eq 'clean' || $estado eq 'dirty';

I rewrite it as:

return if $estado ne 'clean' && $estado ne 'dirty';

update: I need sleep, really. Updated the examples to make some sense. Thanks to Pedro Leite.

August 22, 2007

XMPP-based notification of incoming emails

A nice tool that you can use to receive XMPP notification on incoming mails.

Some facts:

  • uses inotify to detect new emails, so Linux only;
  • Maildir-based deliveries only;
  • Perl script.

My personal attempt at this was not as simple as this one. The current idea is based on qpsmtpd and ActiveMQ but its still in the "back of the brain"-stage.

August 21, 2007

I need some sleep...

I just wrote this:

  $value =~ s/(\s)\s+/$1/g; # Highlander filter for white-space

Yeah, sleep deprivation does that to you...

August 18, 2007

DBI and Async loops

Most of my time, I program inside async event loops like Danga::Socket or POE.

Accessing DBI inside those loops is not a straight forward thing. Most solutions involve forking worker threads and using pipes to communicate between my script and those workers. There are a couple of components for POE that do most of the work out of the box, like POE::Component::EasyDBI, but still, it feels a lot like an hack.

For Danga::Socket loops, I've been working with two "simple" solutions:

  • split the work between sync and async tasks, using disk-based storage to move work from one side to the other;
  • use HTTP-based REST web services.

There are two more solutions that might work now. The first is the amazing DBD::Gofer. I haven't played with it yet (look over the Tim Bunce presentation at CPAN to get an overview) but it simplifies the client side of things that it might just be possible to tweak it into a async DBD driver. The DBI API would have to be slashed a bit, I don't think it has a async version.

Gofer is nice, but will still require a HTTP server for the Gofer servers. And if I have a HTTP server, I might prefer to have a higher level API that can also group some queries in a single call, some of them could even involve a transaction that Gofer does not support.

The other solution is to use Gearman. Its fast, and seems to have all the niceties for scale (multiple workers, multiple managers). But it is not reliable, at least not until the client decides to make it so with code.

All in all, I think both solutions are good, and you can even use Gofer for some things, and Gearman for others. Heck, you can even use Gearman as back-end for Gofer.

For now, I think I'll try Gearman, it seems less work, and I'm extremely lazy. But I'll get back to Gofer soon. I would love to see a asyncronous DBI API, and DBD::Gofer might just be the door.

Startup performance of DBIx::Class

In a project I was working on, I had some performance problems to startup a DBIx::Class schema with about 75 sources. It took about 19 seconds to startup.

After a quick thread in the mailing list, the startup time is now 2 seconds.

The two-part solution is this:

  1. move all your load_components() into a common class and use that class as the base for your sources;
  2. use the schema provided load_classes(), its very fast. If you need per-source tweaking, do it afterwards looping over Schema->sources().

Many thanks to the dbix-class mailing list, in particular mst and Hartmaier Alexander for the tips in the right direction.

May 22, 2007

Module of the Day: Text::Unidecode

For all of those moments where you would write:

s/áéíóúàèìòùãõâêîôûç/aeiouaeiouaoaeiouc/g;

Now you can do the right thing with Text::Unidecode.

April 20, 2007

Module of the day: IPC::JobQueue

There I was cleaning up my "presentation inbox" when I came across the Scary Jifty presentation by Jesse Vincent. He's crazy, in a very sane sort of way.

Anyway in the middle of the presentation he mentions IPC::PubSub which is a nice publish/subscribe system that you can embed into your own applications.

But the prize came in the SEE ALSO section of IPC::PubSub: IPC::DirQueue. I can't remmember how many times I needed something like this. Amazing stuff.

It allows you to create a set of worker processes sharing a single job queue. Clients queue jobs, and a worker gets it. The system assures you that each job will only be processed by a single worker.

Very simple and nice.

I need to read the code and compare it to Gearman, given that IPC::DirQueue also includes a TCP-based server.

April 16, 2007

Tip: XML::LibXML and Debian

If even after you apt-get install libxml2 libxml2-dev you still can't install XML::LibXML, look for this error message:

CPAN.pm: Going to build P/PH/PHISH/XML-LibXML-Common-0.13.tar.gz

enable native perl UTF8
running xml2-config... ok
looking for -lxml2... no
looking for -llibxml2... no
libxml2 not found
Try setting LIBS and INC values on the command line
Or get libxml2 from 
  http://www.libxml.org/
If you install via RPMs, make sure you also install the -devel
RPMs, as this is where the headers (.h files) are.

Basically, the installation of XML::LibXML::Common failed.

To solve, try this:

apt-get install zlib1g zlib1g-dev

Aparently libxml2 depends on -lz but the .deb doesn't notice or something.

February 23, 2007

Module of the day: encoding::warnings

Today I was tracing a double-encoding error in a web app. The Fun never ends!

Anyway, with encoding::warnings the problem was easily spotted.

So, if you are getting "garbage" output on some of your Perl scripts. do yourself a favor and try it. A good tip from an excellent write up about UTF8 and Perl.

And remember, boys, girls, and mix-ins, $1 after m/(.)/ is a character, no matter how fat he is.

February 22, 2007

Module of the day: File::Inplace

The task was simple enough: edit a already existing file, to change something, keeping the name intact, and if possible doing a backup of the original version.

We could start dealing with all sorts of errors in open, rename and friends, dealing with temporary files and all that stuff.

Or we could just jump to CPAN:

cpan File::Inplace
perldoc File::Inplace

In my case, I wanted to remove a line from a file. A regexp matching the line in question was something like this:

qr/src="trivantis-titlemgr.js"/

So the code becomes:

  my $editor = File::Inplace->new(file => catfile($path, 'titlemgr.html'), suffix => '-'.time().'.bak' );
  while (my ($line) = $editor->next_line) {
    $editor->replace_line(undef) if $line =~ qr/src="trivantis-titlemgr.js"/;
  }
  $editor->commit;

Nice and sweet.

'update:' to clarify some point raised in the comments, yes I know about perl -i.bak, but I needed this inside a Catalyst web application, and thus this module.

February 05, 2007

Tip: given a coderef, show me where the code is

In Perl, sometimes you have a coderef, normally a callback, and you need to know where is that code located in your source.

This will do the trick:

sub _dude_wheres_my_coderef {
    use Devel::Peek;
    $code = \&$code; # guarantee a hard reference
    my $gv = Devel::Peek::CvGV ($code) or return;
    return *$gv{PACKAGE} . '::' . *$gv{NAME};
}

Taken from dump_vars.pl. BTW, $name also includes filename and line number.

January 02, 2007

Tip: deleting all objects in a many-to-many relation with DBIx::Class

This might be obvious to many of you, but it wasn't for me, so here it is.

If you have a many-to-many relation in DBIx::Class, you can remove all the relations with:

$self->set_RELATION_NAME([]);

The set_RELATION_NAME method is created automatically for each many-to-many relation you setup. It can receive a list of objects that will become related to $self.

The obvious

$self->set_RELATION_NAME();

will croak on you.

GraphViz under Mac OS X

In case you are trying to install the Perl module GraphViz under Mac OS X 10.4.x, you might need this script.

First, install a decent version of GraphViz. I use this snapshots of Graphviz by Ryan Schmidt. Be careful not to use this version on MacIntel's, the package is PPC-only.

After this is done, add /usr/local/graphviz-2.12/bin to your PATH.

Second, while installing the GraphViz module via CPAN, one of the dependencies is IPC::Run, which might fail on your system. It's a know issue with FreeBSD that seems to also be present on Mac OS X. It hangs while testing t/pty.t.

To skip those tests, do this:

  1. inside cpan shell, type look IPC::Run;
  2. edit t/pty.t, go to line 97 (looks something like this: my $platform_skip = $^O =~ /(?:aix|freebsd|openbsd)/? ...;
  3. add |darwin after opendbsd, save and exit;
  4. type the usual perl Makefile.PL && make && make test;
  5. if all goes well, type sudo make install or the version that works for you.

After that, you should be able to install GraphViz without any problems.

December 31, 2006

MySQL and UTF8 support

I've talked about this before. Basically, if you use UTF8 in your database, the scalars returned by DBD::mysql wouldn't have the utf8 flag turned on for text fields.

Until now.

With the latest release (DBD-mysql-4.0000), things have changed. A patch from Dominic Mitchell was applied (in DBD-mysql-3.0008_1 according to the changelog) that does the right thing regarding UTF8 text fields.

Check the documentation (search for mysql_enable_utf8) to see how it works. You can also look at the utf8.t test script for examples of usage.

I'll post back my findings after I play with it.

May 06, 2006

Tip: reset the TOP format in Perl

Here is something that took me a while to get.

If you are writing scripts in Perl to do some reports and statistic analysis, and you are not using format, stop right now, do a perldoc perlform.

Then, in case you need to switch reports in the middle of the script, for example if your script dumps the data collected in three different layouts, use this code between each report:

$~ = 'REPORT_NAME';
$^= 'REPORT_NAME_TOP';
$= = 100;  # Number of lines on each page
$- = 0;    # Force the print of the new header

You can use English and use the long versions of these variables. See perldoc perlvar for those.

The $- is the one that had me pulling my hair. If you switch to a new layout and start writing data, the system doesn't know that this is a new layout, and will not print a header until he needs to switch the page. Setting this variable to 0 forces a page feed, and forces the new header to be printed.

Technorati Tags: ,

March 11, 2006

Lisbon.pm: tech meeting and a new course

Last thursday we had another technical meeting of the Lisbon.pm group. It was a great success, with 29 people attending.

There where three presentations: one by João Gomes about Catalyst, another by me about POE with an example of process control, and the last one by Miguel Duarte about when not to use Perl, which was, as you can expect, a hot topic.

If you are interested in Perl and live or work around Lisboa, please join our mailing list (instructions can be found at the Lisbon.pm website).

The meeting was organized by José Castro, and the space (and first round of drinks afterwards) was sponsored by Log. Kudos to them both.

I've been the Lisbon.pm leader for some time now, and since the reactivation of the group last September, our social meetings have been better each time and our technical meetings have also been great.

Yet most of the work of organizing our events is being done by José, so it's only fair to make him the leader of the group. So after forcing^H^H^H^H^Htalking with him about this, he finally accepted.

I think the group is now in better hands.

Technorati Tags: ,

December 29, 2005

utf-8 and DBD::mysql

After an afternoon trying to understand why some of my output from a utf8 table in MySQL was coming out garbled, I finally realize that:

  • even if your tables and database are all created with utf8 charset;
  • even if you set your connection charset to utf8 with SET NAMES 'utf8';

your scalar results in perl will not have the utf8 flag set, so any print, concatenation or XML generation further on will result in a mess, when finally printed out to a XMPP stream, for example.

So, on all your code, after you retrieve data from MySQL, you must set the utf8 flag on that scalar.

For now I'm using this code. Probably not the best one, but it suffices for now.

if (! utf8::is_utf8($message)) {
  utf8::decode($message);
}

There is some discussion about this online. It seems that the DBD::mysql people are waiting for a general solution for the problem to appear in a future version of DBI. There is also a patch floating around that sets the flag on utf8 content.

If you use Class::DBI, you can also look at Class::DBI::utf8 that does the right thing.

Regarding support for this in DBI itself, there is a thread by Tim Bunce that talks about utf8 support in DBI in a future version, in particular bullet 4 of the initial post. But the next bullet points the responsibility of the utf8 flag to the drivers.

This quote in particular should self explanatory about Tim's reasoning:

Some features, like charsets, vary greatly in how they're handled by database APIs. For these kind of features the DBI usually lags the drivers. Once a few drivers have implemented their own driver-specific interfaces, and had them proven as practical by users, then I can work with driver authors to see how best to extend the DBI API in a way that'll work well for those drivers and others.

And a more specific one regarding DBD::mysql:

Basically it should be the job of the drivers to set the uft8 flag on data being retrieved if it is utf8. I believe that the new mysql v4.1 protocol does provide information about the characterset of each colum. DBD::mysql can use that.

I would like to see that patch into the DBD::mysql mainline. It seems that Tim Bunce is passing on the responsibility of the utf8 flag to the driver author. It makes some sense. If the DBI layer was responsible to set the flag, it would need to obtain charset information from the DBD driver anyway. In that case, if the driver already knows which charset it is using, why not just set the flag? This would make it easier to work with utf8 in the meantime...

Stay tuned for the next chapters in the utf8+DBD::mysql saga...

Update: another interesting link about MySQL, utf8, and Moveable Type.

Technorati Tags: , , ,

December 14, 2005

Ruby on Rails 1.0

Ruby on Rails hits 1.0. Congratulations to all in the core team.

Since discovering Catalyst, I've left Ruby on Rails behind me, but it was RoR that got me hooked in Ruby, and for that I thank them. Ruby really is a lovely and clean language.

I can only hope that Perl6 cleans some of the "issues" with Perl5. And from what I can see from the presentations I've seen in the last year, it will :).

Technorati Tags: , , , ,

September 30, 2005

The state of the Onion

As usual, a must read. The State of the Onion n. 9 is here.

Favorite quotes:

Wu-Li isn't actually Chinese. He only thinks he's Chinese because when he was young his parents told him that every third child born into the world was Chinese, and he was a third child.

and another:

As I was thinking about the intelligence community and its recent obvious failures, it kinda put a new spin onto the phrase, "Information wants to be free," or my own version of it, which is that "Information wants to be useful."

and this rings some bells:

We often think that intelligence failures are caused by having too little information. But often, in retrospect, we find that the problem is too much information, and that in fact, we had the data available to us, if only it had been analyzed correctly.

So I'm just wondering if we're getting ourselves into a similar situation with open source software. More software is not always better software. Google notwithstanding, I think it's actually getting harder and harder over time to find that nugget you're looking for. This process of re-inventing the wheel makes better wheels, but we're running the risk of getting buried under a lot of half-built wheels.

Perl6 polyglot

Very nice article on O'ReillyNet about Perl6.

Perl6 Polyglot by Geoff Broadwell -- What Perl 6 is learning from other languages -- and why you should learn a few too.

Go! Read!

August 26, 2005

Week summary

No, I'm not going to talk more about Google Talk :).

I'm going to bed now, I've been up since 5am to do an upgrade to our XMPP server platform. It went pretty well, but we still have some glitches with S2S. They should be solved real soon now.

I wanted to talk you about the stack of perl books I have here, from Higher-Order Perl to Perl Testing going through Perl Best Practices, but it will have to wait until next week. I need to make them justice, they deserve it. It's really nice to see very good books about Perl being published.

I've also been reading the Programming Ruby and the Rails book. Yeah, I know, some of you think it's just a fad. Indulge me, ok? I'm still recommending anybody who wants to pick up a language, to try Ruby. I've collected some presentations about it from OSCon'05 that I'll link next week.

I've also finished my Trac setup, and it is now totally automated to keep me using darcs or, at work, CVS, and have all the niceties of the great Wiki, Tickets and Source browser integration. I'll be moving my lost projects to it in the coming weeks.

Finally, I updated my personal Jabber server to the latest Jive Messenger. I had been using ejabberd for some time now, but I wanted something that I could just install, run a script and be done with it. I can only say that I was able to do just that with Jive Messenger, I think it took me 15 to 20 minutes to have a fully featured XMPP server. The newest version, 2.2, it's the first one I can use since it's the first to have S2S. They don't have TLS, but it's not important to me right now: my client of choice, Psi (who incidentally also had a new release today, check the new Psi wiki, btw), does not support TLS for now. But if TLS is important to you, don't despair: adding TLS to Jive Messenger is a Google Summer of Code project.

Also, Moveable Type 3.2 is out, looking good. For those of us who still like to run and waste our time tinkering with our blog software, it's seems a worthy upgrade. I was very impressed with the upgrade demo. I was thinking on upgrading my software, lot's of bugs, and more trackback spam than I can read in a lifetime, and I was shopping around for software. MT 3.2 seems to be crawling back to the top of my list of choices, followed by typo and wordpress, in that order.

With all the Google Talk, I've been a bit away from Apple news. The IDF conference this week had a lot of cool stuff (my favorite, the end of the north bridge on Intel chipsets, you should check AnandTech site for all the goodies. I didn't have the time to read to much into it, regarding Apple future hardware offers, but it looks promising.

Yet, my interest regarding Apple news will grow in the coming weeks. The Apple Paris Expo is coming up in late September, and I would like to see a last rev of G4 Powerbooks coming out of Mr. Jobs keynote. I would be a happy camper to see a dual-core G4 17" or bigger Powerbook... But I'll try to keep my expectations low.

All in all, a fun week. My only regret is that my coding time is getting to be a lot less than it usually was. And now that it was getting to be fun again. I've been making an effort to do more developer testing, and so far I'm loving it. It can be hard sometimes, with the pressure of every day, but it's a great stress reliever for me. I should join Phalanx some day, I really should.

Have a nice weekend.

Technorati Tags: , , , ,

August 23, 2005

The future is here

If you don't have the time to keep up with all that going on in the perl6 world, you can get a taste of the language now. Rafael Garcia Suarez has written a IRC bot named Shakti.

July 02, 2005

Weaken references in Perl

In case you need circular structures in Perl, you should known about Scalar::Util and it's weaken function.

See this example:

package T;

sub DESTROY {
  my $self = shift;
  print STDERR "Bye bye: $self->{name}\n";
}

package main;
use Scalar::Util qw( weaken );

{
  my $a = bless { name => 'a' }, 'T';
  my $b = bless { name => 'b' }, 'T';

  $a->{b} = $b;
  $b->{a} = $a;
}
print "Should see a destroy 'a' and 'b', but you wont...\n";

{
  my $c = bless { name => 'c' }, 'T';
  my $d = bless { name => 'd' }, 'T';

  $c->{d} = weaken($d);
  $d->{c} = weaken($c);
}
print "Should see a destroy 'c' and 'd'!\n";
print "Now you'll see a destroy 'a' and 'b'\n";

The output is this:

Should see a destroy 'a' and 'b', but you wont...
Bye bye: d
Bye bye: c
Should see a destroy 'c' and 'd'!
Now you'll see a destroy 'a' and 'b'
Bye bye: b
Bye bye: a

The problem is that in the first block, although the $a and $b are no longer in scope, each one holds a reference to the other, and that prevents them both from being destroyed.

In the second block, each one of $c and $d takes a weak reference to each other. Weak references don't increment the reference count internal to all Perl variables, so at the end of the block, they are correctly destroyed.

You've warned.

June 04, 2005

Ruby on Rails, and Catalyst

So, after having learned a bit about Ruby, the next logical step for me was to try Ruby-On-Rails.

A bit of background: before going to work at Sapo in the XMPP Messenger product, I was a lead-developer at Novis. My main task there, was to build websites and provisioning systems, and the glue that ties billing systems with technical databases. We used a framework that was developed internally since '99, and in it's latest generation was called Apache::WAF. It was a MVC-style framework, with a strict separation between code and layout. The View was Template Toolkit, but it was extensible to other technologies (we used Mason a lot also). The Model where our own provisioning system libraries and other stuff. Apache::WAF allowed us to build the Controller very quickly. Also, it was pretty fast, using mod_perl.

So using MVC-style frameworks in web development is nothing new to me.

Except that Ruby-On-Rails is much more than that, and in a extremely clean package. You can get up-to-speed in no time, thanks in part to the generation of code that is the base of RoR, and also to the Screencasts available at the Ruby-On-Rails website.

Also, having a clean and powerful language behind it, it sure helps.

It's not perfect. The part of mapping URLs to controllers could be better. RoR uses the same setup that Apache::WAF uses: you register URL namespaces on a special config file and associate them with controllers. The main advantage I see with this approach is that you can look at this single config file and know all the URLs of your app, so clashes are less likely.

The Model part of RoR is just excellent. As far as I can tell, there is no Perl equivalent to ActiveRecord. Yes, yes, I know about Class::DBI and Alzabo, and the others. But those solutions solve the CRUD problem: creating, retrieving, updating and deleting one object at a time. They all have solution for forging relations between tables and objects. But ActiveRecord does all that and more. It's the first framework (and I really expect and would love to see some perl guru to jump on me on this one and say "Have you looked at X on CPAN?"...) I've seen that solves the 1+100 queries problem efficiently.

The 1+100 queries problem is simple to understand: suppose you have a Books table and a Authors table (for simplicity, a book can only have one author), and you want to list all the books with the respective authors.

With a basic CRUD framework, you do a Books->find_all or Books->search to get all the books and for each one, you do something like $book->author->name to get the author name. If the first query for books returns 100 books, you'll then do 100 queries for authors. Yes, yes, you could cache ID->name of authors, but that really is not the point. The point is that something that should be done with a simple join at the database level with a single query, is now being done with multiple queries (and if you write to me saying that "Yeah, but my MySQL is fast enough you wont even notice", I'll warn you right now that I'll verbally abuse you. Real world is a lot different).

ActiveRecord is able to solve this. You can say that "Please give me all the books, and also their respective authors" and with a single query to the database, you'll get a list of Book object with the author method returning a pre-created object. You can even specify which fields you need from author.

It's very very good! The Model in Ruby-On-Rails is for me the part that makes the most difference to the other MVCs I've used in the past.

Ruby and Perl

I've been learning Ruby for the last couple of weeks. I bought the book some time ago, and I've been reading and rereading it several sections.

Ruby is a very very good language. Blocks are one of the most productive features I ever used in a programming language.

Yet, I use Perl everyday. I'm a Perl user since 4.something patch level 35 or 36, and I really like perl5. Also, at work, I need Perl and POE to build XMPP components. It's a very productive setup. Also, after more than 10 years in Perl-land, you get to know the language, the modules and the community very well, and that helps.

But I can't stop thinking that Ruby would be useful in a lot of situations at work. Right now, I think there are 4 or 5 people there looking at Ruby, but all with a "Wouldn't it be great to use this?" type of thinking, and no "Let's use this right now". I understand exactly why we think like that, it's a very big company, a long-lived project, with a lot of legacy, and frankly, the right project for Ruby doesn't seem to have emerged yet.

I've been looking for XMPP stuff in Ruby. There is Jabber4R which is very good to do a bot in a hurry, but I lack a event-driven framework like POE in Ruby so that I can write my external components.

So I'll keep using it for small things, to keep the language alive in my brain. I'll try to figure out how to achieve critical mass around me to start using it in a big way.

Of course, I must also think about perl6. But I'll confess: for a long time perl5 programmer like me, perl6 is more scarier than Ruby. It seems (I haven't read that much about it, I just keep up with the Mailing list summaries) very powerful, but I think that the language is getting more cryptic. I don't know if that's a language feature, or the current perl6 guru's showing off the power and expressiveness of the language. Anyway, for me, it's scary. I've been fighting the last 4 or 5 years to write and teach other people to write good maintainable perl5 code, and I haven't seen examples of maintainable code in perl6.

This year I'll be attending YAPC::EU and probably YAPC::NA later this month. And my main goal is to see what perl6 is all about, and if it is as scary as it seems.

May 28, 2005

Perl6 example

Perl6 JAPH:

say [~] (-> @c is copy {gather { while @c[0] { for @c -> {take(.shift)} } } }(['Joec','utrk','shle','te6r',' r .','a h.','nPa.'].map:{[split "",$_]}));

Something tells me that learning Perl6 is going to be an adventure. And totally different from my perl4 to perl5 conversion.

Either that, or I'll be sticking with perl5/ponie for a looong time.

April 30, 2005

XMPP and Perl

I'm writing an external component in POE::Component::Jabber. It's a custom development that will link to a XMPP server.

POE::Component::Jabber is nice, but it seems to me that I'm investing in something that I won't be able to reuse.

There is no clear way to create a standalone module or plugin to hide the details of a certain protocol (like the jabber:iq:register).

I have some old code, XMPP::Session, that should solve this problem. The module is network agnostic: you can use STDIN/STDOUT, POE::Component::Client::TCP or even a Socket. I really need to clean it up and share it to see if there is any interest in it.

Tiger notes

As I said before, I'm not upgrading to Tiger until sometime next month. Yet, I need to keep some links to things that I need to test or fix in my Tiger setup.

The good news in Tiger for scripting fans like me, is that Perl and Ruby have decent and recent versions. The bad news is that at least Ruby has a bad configuration file. From what I could understand, it seems that they left a CFLAGS=-arch i386 in a config file... I can't wait the rumor sites to get this one... A fix is available.

One thing I want to test is the new CoreData framework. Cocoa Dev Central has two articles entitled "Core Data Class Overview" and "Build a Core Data App" that seem very nice.

I'll keep this post updated with all my things-to-see in Tiger-land.

April 24, 2005

Clarification about last post

The fact that I had to write so little code is a tribute to two things: the design of Apple APIs is very clean; and Ruby integration with ObjectiveC runtime is almost perfect.

Doing a web browser with XCode is equivalent to the early 90's 'Hello world'.

One interesting thing. I'm almost sure that I can reuse the same NIB file with a CamelBones project. I'll try it next week and write the same app with it.

April 01, 2005

POE and Rendezvous

You can find on CPAN my recent itch. I wanted to add discovery to some POE servers I have running on my laptop and on local servers at the office.

Enter POE::Component::Rendezvous::Publish. It's now super-easy to make all those nice web-interfaces to your own POE servers available in the local network.

It's alpha for now, I haven't decided the final API yet.

POE and Rendezvous

You can find on CPAN my recent itch. I wanted to add discovery to some POE servers I have running on my laptop and on local servers at the office.

Enter POE::Component::Rendezvous::Publish. It's now super-easy to make all those nice web-interfaces to your own POE servers available in the local network.

It's alpha for now, I haven't decided the final API yet.

March 08, 2005

It depends

When writing Perl, should you use this:

  if (!unlink($file)) {
   $log_main->warn("Could not delete temp file '$file'");
 }

or this?

$log_main->warn("Could not delete temp file '$file'") unless unlink($file);

The second one is shorter, and has extra-geek-points, but I say that "it depends".

In this case I settled on the first form because the important part, the important action, is the unlink() call. You should always put the important action first.

January 22, 2005

RSS your yum updates

If you like RSS and use Fedora Core 3, then you can have the nightly yum update reports delivered to you via RSS.

The following setup requires: * using fedora core 3, or having the command rss-generate in yum (check man yum); * your mail is delivered via qmail; * you can install .qmail files.

You probably could workaround the last two. I might do that someday. For now, consider this as a quick (took me less than 20 minutes after I noticed rss-generate in yum manpage :) ) hack.

The setup is simple: each night, a cron runs on each server, and generates the RSS file. The file is then sent to a special mailbox, and there we filter the message and place it in a public HTTP site. You then configure your favorite RSS reader with that URL.

First I created a email address with .qmail file in my homedir:

cat > ~/.qmail-yum <<EOF'
|/home/melo/bin/convert_yum_rss_mails_to_http.pl
& youraddress@yourdomain.top
EOF

The second line should be a good email address. If something goes wrong with the script, it will fallback to the email address. At least you'll know that something has gone bad.

Then you place the perl script in the correct place. You can download the convert\yum\rss\mails\to\_http.pl script, or paste it:

#!/usr/bin/perl -w

# Where to place RSS files? Should be available via Web
my $dir_for_rss_files = "/var/httpd/htdocs/yum_rss";
my $server;

while (<>) {
  $server = $1 if /^Subject: Yum changes for (.+)/;
  last if /^$/;
}

fallback('no_server') unless $server;

my $filename = "$dir_for_rss_files/$server.xml";

umask(022);
fallback("could not create file '$filename.new'") unless open(RSS, ">$filename.new");
print RSS <>;
close(RSS); 

sucess() if rename("$filename.new", $filename);

unlink("$filename.new");
fallback("could not rename file '$filename.new'");

# qmail exit codes, see qmail-command man page
sub sucess   { exit(99) }
sub fallback { my $m = shift; print STDERR "Err: $m\\n"; exit(0)  }

That's it. If something goes wrong, check your qmail-send logs. A message is written there.

Now you only need to generate the mails on each server. To do that download the script yum-rss-report.cron. It looks like this:

#!/bin/sh

/usr/bin/yum --rss-filename=/dev/fd/1 -R 120 -d 0 -e 0 generate-rss |  \\
/bin/mail -s "Yum changes for `hostname`" youraddress-yum@yourdomain.top

This command will generate the RSS (the -R 120 will make sure that each server will wait a random number of seconds), and mail it to your address that you set up before. Make sure you change the address in this script, and make sure you can receive mail at that address.

Then, copy the edited script to all the servers that you want to report to you. On each one, copy the script to /etc/cron.daily and make sure you make it executable:

cp yum-rss-report.cron /etc/cron.daily
chmod 555 /etc/cron.daily/yum-rss-report.cron

That's it! Just subscribe each server in you favorite RSS reader and each morning you'll know which servers got upgraded and to which versions.

I have some improvements to make to these scripts, but they are good enough for now.

Enjoy!

January 21, 2005

Line noise

I was editing some Perl code and I needed to comment the function I was working on, from the cursor till the end.

My editor of choice is vim for quite some years now, so I typed this:

:.,/^}/-1s/^/#/

It never ceases to amaze me as line noise can be so productive and intuitive if you know your editor and your regexps.

December 30, 2004

darcs2rss now at 0.5

Real life has kept me from posting what's going on at simplicidade.

I just sent a mail to darcs mailing list announcing version 0.5. I switched to a proper XML::Parser and added command line options to change RSS metadata.

In my personal copy I have two big changes: - generating RSS 2.0; - filtering comments: current filters are 'simple' and 'markdown'.

Both these features are optional, of course.

I really like markdown and I'm using it more and more everywhere, so this is mostly a feature that I use a lot and I needed fast. But to use HTML formating in your item descriptions, you need to move to RSS 2.0.

In order to do that I'll have to deal with meta-information. Using command line parameters is not such a good idea. My current script to generate a feed for darcs2rss itself is 4 lines long! I'll have to code support for a config file.

Will see.

About darcs, it's been really great. Much more simple to use than arch, my previous favorite CVS replacement, and fast enough. I've been lurking the mailing list and there seem to be some situations where darcs can be very slow, but my projects are very small, so it's not an issue for me. The darcs developers are working on this, but I admit that I don't even try to follow those discussions, that usually evolve into mathematical discussions :).

December 08, 2004

darcs2rss

I've been using darcs for some weeks now, and I like it a lot. I'll write more about darcs and why I like it in a future post, but I'm switching from CVS to darcs for my current and future pet projects.

Last friday, Bennett Todd was asking in the darcs-users mailing list for a script to generate a RSS feed of darcs changelog. I send him a quick perl script to do just that. I also got some sugestions and improvements.

So I created a darcs repo for this project. You can find it at http://darcs.simplicidade.org/repos/darcs2rss/. You can browse all my repos at http://darcs.simplicidade.org/.

Next, I have to make a small page about it. Not today, though. Real life is waiting. Meanwhile, you can use the readme to know more, specially the roadmap.

November 12, 2004

RPC and Perl

During the last couple of years, the idea of a simple to use RPC system for Perl has been on my mind. I've done several designs, mostly focused in object oriented perl, but never did one I really like.

It's been a challenge that I pick up whenever I can.

Today, Ricardo pointed me to mod_perlservice, a very simple RPC system for Perl. I'm still looking into it, it seems to be function-oriented, not object-oriented, but it also seems extremely simple to use. As a added bonus, it has clients in C and Flash out of the box.

I'll have to do something with it to test it out, don't know what yet.

If you want to follow the project, you can subscribe the freshmeat entry for this project.

September 07, 2004

Perl 6 Periodic Table of the Operators

I confess that I'm a bit scared at all those operators, but the arrangement is just perfect. I'm now a proud owner of a A3 copy of it, thanks to a co-worker with access to a large format printer.

Now I only need a A3 Color Printer... Any one? :)

August 29, 2004

Mirroring CPAN in your laptop

For some years now, I always have a full CPAN mirror on my laptop. I work a lot offline and I like to have it around.

Until today I did a full rsync from a public mirror from my ISP, but Nuno sent me a script to mirror only the latest versions of each module but I never got around to use it.

But I noticed that the script he sent me is now (well, I noticed it today...) on CPAN itself, so I just did:

$ sudo bash
# cpan CPAN::Mini
# cd /sw
# mv cpan cpan.full
# mkdir cpan
# minicpan -l /sw/cpan/ -r file://sw/cpan.full/ 
# du -hs cpan cpan.full
409M    cpan
3.2G    cpan.full

hmms... 1.8Gb free space... nice... I keep it up-to-date with minicpan -l /sw/cpan/ -r ftp://ftp.ip.pt/pub/perl/.

August 18, 2004

The Douglas Adams release

42

I was looking at the new CPAN releases and saw a new release of version.

Me thinks we should call all the x.42 releases a Adams release in tribute.

July 27, 2004

Ambrosio is useful now

The latest version of Ambrosio is now useful. You can now send notifications from scripts or applications you write.

I did this last sunday but I needed to write a small manual for notifications.

July 23, 2004

New version of Ambrosio

Ambrosio is almost ready for major deployment. A new version is available (0.3), and now you can subscribe the bots presence.

The roadmap is something like this:

  1. Finish Notice plugin: you drop small files in a specific directory, the local bot will pick them up and forward them to the JID's specified in the file - this allows for other scripts or applications in each one of your servers to send notifications;
  2. Better management of notifications and presence: don't send notifications to people that are away or disconnected.
  3. Multi-User chat support: its going to be nice to enter a room filled with your webservers and tell them all, restart apache, or having bots talking to one another like people, bloody harvest at IP_ADDRESS and have all the others block that IP via iptables
  4. Log watcher: probably just a gateway to a local swatch application?
  5. Start to think about a meta-bot: a bot controlling the other bots - he can receive notifications for disconnected users, and decide what to do with them:
    • forward part of the notification via SMS?
    • send a URL pointing to the note?
    • keep a log of unread notices?
  6. Each plugin could have variables that he was willing to supply to some one: uptime can have the load, df can have free_kb_partition. These variables can be watched (you get some notification if they change, or if they trigger some threshold), or even logged (sql or rrdtool).

I have more ideas, some totally crazy (like having a pam_bot that asks the admin of the machine if the person trying to logging can do so before allowing it :) ), others more useful.

Remember that the core of Ambrosio is likely to change in the near future. The plugins will most likely be compatible. But the core will change a lot!.

July 21, 2004

MT-Blacklist

I never used MT-Blacklist. I started with MT3 so I really didn't feel the need.

But the screenshots of the new version (MT3 ready) are nice. I'll have to check it out :).

Ambrosio

Ambrosio is a POE Jabber bot that you can run on each server you manage.

It gives you three commands: uptime, df and ps. It also responds to help.

It's pluging based, you can extend it easily. In the few days, I should post plugins to control access to those bots, notification of events on other applications, and more commands.

It's a proof of concept only. I'm doing it to gain some experience with POE::Component::Jabber::Client and other stuff. It will evolve into a small framework for making multi-network bots.

You can find it here.

Oh, BTW, it requires a modified POE::Component::Jabber::Client::Legacy module (included in version 0.2 and above). The CPAN version doesn't seem to allow automatic registration, and I needed that. I have to cleanup my patch and send it upstream to Nick.

July 17, 2004

Java and Perl: inline is evil

Will the madness never end?

Came across Inline::Java via Jeremy Smith.

At least now I can say to the people at work who do Java all day, that there is still hope for them :).

July 16, 2004

IO::All is evil

So I was reading IO::All documentation. It seems pretty powerfull and can save me some time whenever I need to read text and parse it.

Until I came to this:

    A Tiny Web Server

Here is how you could write a simplistic web server that works with
static and dynamic pages:

perl -MIO::All -e 'io(":8080")->fork->accept->(sub { $_[0] < io(-x $1 ? "./$1 |" : $1) if /^GET \/(.*) / })'

No, I won't tell you how it works. I had to read the explanation three times to understand it all. See for yourself in the IO::All perldoc.

use.perl

Hi have a id at use.perl that I never really use.

I decided to crosspost the perl category from this site to use.perl. I'm still fighting the script that Casey West did, it seems that it does not like MT3.

More updates in the next days, I hope.

BTW, in case you where wondering why the sudden silence, lots of work but also lots of progress in my little pet projects. More to come.

June 26, 2004

Kiwi will be based on Kwiki

I've been thinking about my personal content management system. It's one of my top priorities because a lot of stuff is waiting for it.

To speed things up, I decided to take a look at Kwiki. And all I can say, I'm sold. It's a wonderful architecture, everything is a plugin (like I wanted to do in Kiwi), and it's easy to extend.

So next steps are:


  1. get to know Kwiki: I got a copy running, and I'll be looking into it

  2. add the object-oriented database system to it

  3. make the database hierarchical

We'll see how it goes.

June 21, 2004

Typekey

The spec of TypeKey is available. And the mandatory perl module is also available :).

I really like web-based "centralized" authentication systems. It's a nice stepping stone to more useful SIM-card or Smart-card based ones. It will keep me happy for a couple of months until I get decent support for smart cards in my OS of choice.

Update: and something new, at least for me, MyUID. Same thing, it seems, diferent implementation. From a quick glance to the PHP implementation (they don't have a perl module), it seems to be a little bit more intrusive than TypeKey. You can pull a user profile from the MyUID server. Will see.

June 16, 2004

PerlTk

I always wanted to learn PerlTk, it seems the most portable way to do a quick GUI for some perl script. My problem with it is that, being a Mac user for sometime now, I really don't want to run X11 to use it.

Apparently, my problem is solved... TclTk Aqua Batteries-Included is a Tcl/Tk distribution (binary with source available) that runs native in Aqua. I'm going to install it, and then I'll try to compile PerlTk against it.

I let you all know how it goes.

May 26, 2004

My CTRL is stuck

I use a Logitech wireless desktop everywhere. I like the keyboard feel very much. It's not as good as the old PS2 IBM keyboard (BTW, if you have one of those for sale, let me know :) ), but it's better than most.

I use it with my Powerbook for two years now, and I always had this glitch with the CTRL key and a specific key combination. I use the portuguese layout, by the way.

Try this: in a Terminal.app window, type AltGr+2 (should print @) and AltGr+_ (in my case, it erases the @). The kick is that from then on, your CTRL is stuck. Type 'd' to do a CTRL-d and leave the shell :).

It's the combination AltGr+(@ then _) that triggers this. You need to plug out/in the USB keyboard connector to reset this.

The most infuriating part: I type that sequence *very* frequently. @_ is the default array in perl....

Does anybody has this problem? Or is it just me?

Pod::Webserver

The python folks had for sometime this tool that would convert the locally installed documentation into HTML and give you a small HTTP server to publish it. Can't remember the name, though.

Perl folks didn't. Until today. TorgoX has been working on that, and today he upload Pod::Webserver to CPAN. You need a very recent version of Pod::Simple (I had to force an update on my local CPAN mirror), but apart from that, works great!

Recommended.

May 20, 2004

My moment of zen of today

Calling this work-safe depends a lot on where you work :)...

Who said perl can't be fun?

Thank you gav.

May 17, 2004

Kiwi

I really don't know what Kiwi is. Well, I know it's a project I've been working on and off for quite sometime now.

But if you ask me what it is, well, it's difficult to say.


Kiwi is a Wiki-style system with rich meta-data, with a object-oriented full-text search back-end. It also has some blog-like features. And you can also syndicate it's changes.

You would write nodes or pages with a language wiki-style (actually the parser is pretty extendable, so the actual format could be changed easily). You can include in each node live queries to the back-end. Those queries can target the meta-data or the full-text of the nodes. New markup can be genrerated from the results.

You can also put objects inside each node. You could put your DVD collection inside Kiwi, a node for each DVD, with special fields for Title, Rating, Actors, Director, etc. And then reference those objects from anywhere in other Kiwi nodes. You could also query the back-end for DVD object matching specific criteria.

Right now, I'm working on the parser. I'm trying to make not a parser for Kiwi, but a generic extendable parser. There are no core elements in the Kiwi language. Everything is a plugin. The parser only job is to select a set of plugins that, based on the context, are asked to match the current line. The chosen one gets to influence the context for the next round.

I made some progress last week, but this week I hadn't had the time to work on it. I'm expecting to get back to this next weekend and finish the parser.

After that, it should be able to transform Kiwi nodes in HTML, with full meta-data collection and storage.

I expect that someday Kiwi will replace MT as my blog platform.

SAF

SAF is a temporary name for one of my projects.

I'm a big fan of event-driven programming, usually found in GUI programming. I always wanted to use it in systems or application programming.

The idea behind SAF is this: you take a system or application and split into several modules. Each module exports a specific API. The API is then implemented by each module as a event thats sent to a channel. All the modules hook up into that module, and can get involved in the processing of the event.

Let's see a simple example: imagine a user registration module and a comment system module.

Each user has a username, password and karma level. Karma starts at 0. It increases with good comments, and decreases with bad ones. The karma level of each comment is taken from a average of ratings done by other users of the comments.

You've seen this in a lot of places, slashdot probably being the most famous one.

To implement this with SAF, we would build a user registration module, with common methods like create user, login and change password. This module would also listen to "karma changed" events.

The comment module, would accept new comments, either fresh ones, or replies to other comments. It's only logical that it would generate events for each of those operations. It would also allow one to rate other peoples comments. That API, rate_comment, would send a event "karma changed" whenever a rate_comment event is completed successfully. The event would include previous and the new karma levels, the author of the comment, and the user that did the rating.

The system would work very well. One important aspect of this is the possibility of evolution without the need of complex changes everywhere. If we decide to give a karma reward for people who rate a lot, we don't need to change the comment module, only the user module.

Also, if you decide to allow the possibility to request that reply's to my comments are sent to me via email, or a notification of that reply is sent to me via Jabber, the only thing I really need is to add a new module, comment notification, with an API "request notification". This module would listen to events, and trigger the appropriate notifications whenever a proper reply is seen to a post from a user who requested notification.

This is possible because the modules are not tightly integrated with each other. The SAF architecture can grow as we evolve our system. Sometimes we need to go back to a previous module and add another event generated under certain conditions, but those changes are typically very simple, and unlikely to introduce many bugs.

The system "forces" you to split your problem in manageable pieces, and to take a systematic approach to the API each one will provide.

I already used this system in some applications. It works pretty well. I'm now cleaning the code, adding some documentation, and uploading to CPAN. I expect this to happen in the next few days. Expect a 0.1 release sometime this week. The full version 1.0 will follow in June probably, with full documentation and tests.

Right now, I don't have any plans post-1.0.

A arch archive will be available sometime tomorrow. I'll post details then.

Contacts

melo@simplicidade.org (XMPP/email)
+351 302 029 050 (voice)
melopt (Skype)

IronMan challenge

Iron Man badge Are you ready to be an Iron Man? Join the challenge and find out! (what is the meaning of this little man?)

Moosaico

Junta-te!

Recent Comments

Powered by Disqus
Creative Commons License
This weblog is licensed under a Creative Commons License.
Powered by
Movable Type 3.2