No more del.icio.us on Tempe.st
- A Tempest of Thoughts
- Wed, 27 Aug 2008 23:23:07 +0000
I have decided to remove the daily del.icio.us post with my links, it created too much noise and diluted good content.
I have decided to remove the daily del.icio.us post with my links, it created too much noise and diluted good content.
I’m about to go on holiday for a few days, here’s a screenshot I just took from Google News Italia, it seems like the service has been spammed…
Here’s a search for web2.0

Drupal is a great piece of software, unfortunately it stores so much stuff in the db that people struggle keeping in sync the development server/box and a staging server to show their customers how the work is proceeding.
Today I will share the Capistrano tasks I use to sync my development box with the staging server. What I basically do is dumping the development db, sending it to the server via capistrano and then use the dump to replace the server’s database.
The following tasks should be used together with the tasks in my Deploying drupal with Capistrano article. I took advantage of deploy:cold not being needed with Drupal, and added a callback to it, so if you want to do a deploy that also updated the database you should use deploy:cold.
You should also have two settings files (usually stored in drupal_root/sites/default), one called settings.development.php, with your local database setup and one called settings.production.php with the remote database setup, the capistrano tasks will take care of choosing the correct one.
# Callbacks before 'deploy:start', 'drupal:db:import:production' before 'deploy:restart', 'drupal:configure:production' before 'deploy:start', 'drupal:configure:production' before 'deploy:cold', 'drupal:db:dump:development' # DB Stuff set :mysqldump, "/path/to/mysqldump" set :local_db_user, "local_mysql_username" set :local_db_password, "local_mysql_password" set :local_db_name, "local_db_name" set :db_user, "remote_mysql_username" set :db_password, "remote_mysql_password" set :db_name, "remote_db_name" namespace :drupal do namespace :configure do task :production do sudo "cp #{latest_release}/sites/default/settings.production.php #{latest_release}/sites/default/settings.php" end task :development do sudo "cp #{latest_release}/sites/default/settings.development.php #{latest_release}/sites/default/settings.php" end end namespace :db do namespace :dump do task :development do raise RuntimeError.new("failed dump") unless system "#{mysqldump} -u #{local_db_user} --password=#{local_db_password} #{local_db_name} > dump.sql" end end namespace :import do task :production do ENV["FILES"] = "dump.sql" deploy::upload run "mysql -u #{db_user} --password=#{db_password} #{db_name} < #{latest_release}/dump.sql" end end end end
Mikamai, the company I work for, has just released Montalbano.tv, the companion site to one of the most successful TV shows in Italy.
I was the technical director of this Drupal based project, and while I was happy we chose Drupal, because it allowed us to deliver all the features they needed on time, I almost panicked when they told us the production setup would have two servers, both with database and web serving duties.
The database replication was standard MySql master-master setup, but I had to develop a strategy to keep the two code-bases on the two servers synchronized.
Being a Ruby programmer at heart, I selected the only tool that never fails me in circumstances like the one we had: Capistrano.
Unfortunately, while Capistrano is all easy to use with Rails, I had to write a custom Drupal-tailored Capfile.
Here it is, in its entirety, in case you ever need to deploy Drupal with cap (now I always deploy Drupal with cap, since I have the recipe ready :)):
load 'deploy' if respond_to?(:namespace) # cap2 differentiator # Standard configuration set :user, "username" set :password, "password" set :application, "application.name" # I like to deploy the code in /var/apps # and then link it to the webserver directory set :deploy_to, "/var/apps/#{application}" # SCM Stuff configure to taste, just remember the repository # here I used github as main repository set :repository, "git@github.com:username/project.git" set :scm, :git set :branch, "master" set :repository_cache, "git_master" set :deploy_via, :remote_cache set :scm_verbose, true # Two servers, double fun # You really don't need app, web and db here, # but I used all of them just to be sure. # Usually only web is ok. role :app, "first.server.address.com" role :app, "second.server.address.com", :primary => true role :web, "first.server.address.com" role :web, "second.server.address.com", :primary => true role :db, "first.server.address.com" role :db, "second.server.address.com", :primary => true after 'deploy:setup', 'drupal:setup' # Here we setup the shared files directory after 'deploy:symlink', 'drupal:symlink' # After symlinking the code we symlink the shared dirs # Before restarting the webserver we fix all the # permissions and then symlink it to production before 'deploy:restart', 'mikamai:permissions:fix', 'mikamai:symlink:application' namespace :drupal do # shared directories task :setup, :except => { :no_release => true } do sudo "mkdir -p #{shared_path}/files" sudo "chown -R #{user}:#{user} #{deploy_to}" end # symlink shared directories task :symlink, :except => { :no_release => true } do sudo "ln -s #{shared_path}/files #{latest_release}" end end namespace :deploy do # adjusted finalize_update, removed non rails stuff task :finalize_update, :except => { :no_release => true } do sudo "chmod -R g+w #{latest_release}" if fetch(:group_writable, true) end task :restart do # nothing to do here since we're on mod-php end end namespace :mikamai do # symlinking to production namespace :symlink do task :application, :except => { :no_release => true } do sudo "rm -rf /var/www/montalbano" sudo "ln -s #{latest_release} /var/www/montalbano" end end # change ownership namespace :permissions do task :fix, :except => { :no_release => true } do sudo "chown -R www-data:www-data #{latest_release}" end end end
If you’re a regular reader you will have noticed the new layout and the all-new top-notch site performance.
I’ve been looking for a new theme for a long time, because I needed a wider content column, and I’ve also implemented the superfast lighttpd + wp-supercache setup I described in a previous post.
I hope you’ll enjoy your stay on the new Tempest of Thoughts.
Last year Netwo organized a whole weekend with the most interesting experiences on the web Italian arena. This year we’re back to announce Techtalk Italia 2008!
Techtalk is an event originally organized by Martin Varsavsky for the best european/world web2.0 entrepreneurs. The whole weekend spent together, during a few sessions everyone participating will give a short presentation of her/his activity. Our families will be with us and we will take the time to have fun all together.
We think this is a really good formula, so with a few friends we decided to bring it to Italy.
For the second year in a row we will spend a whole weekend (from july 4th to july 6th) with the top Italian web entrepreneurs, discussing our projects but also having a great time together in a wonderful villa in Tuscany.
We will post more info shortly on the netwo blog, if you want to come, please write me.
Here are a few photos from the last edition.

Firenzuola, the wonderful Tuscan town there the Techtalk is held

The swimming pool is surrounded by a forest

Saturday morning session

Saturday night dinner
In my current rails project I need to upload photos and save some exif data taken from them. I use attachment_fu as uploading system that let me choose which image processor to use. Using rmagick and mini_magick I can extract exif data with the following code:
# rmagick image = Magick::ImageList.new(filename).first puts image['EXIF:Model'] # The camera model used to take the picture # mini_magick image = MiniMagick::Image.from_file(filename) puts image["EXIF:Model"]
The problem is that I can’t do the same thing with image_science, because it has no methods that return exif data, so I want to add a method to the ImageScience class to do that.
Looking the FreeImage documentation I found some helpful functions, FreeImage_GetMetadata and FreeImage_TagToString. With these 2 functions I’m able to get an exif tag and convert it to a readable string. Each one of the available tags belongs to one of the following meta models:
FI_ENUM(FREE_IMAGE_MDMODEL) {
FIMD_NODATA = -1,
FIMD_COMMENTS = 0, // single comment or keywords
FIMD_EXIF_MAIN = 1, // Exif-TIFF metadata
FIMD_EXIF_EXIF = 2, // Exif-specific metadata
FIMD_EXIF_GPS = 3, // Exif GPS metadata
FIMD_EXIF_MAKERNOTE = 4, // Exif maker note metadata
FIMD_EXIF_INTEROP = 5, // Exif interoperability metadata
FIMD_IPTC = 6, // IPTC/NAA metadata
FIMD_XMP = 7, // Abobe XMP metadata
FIMD_GEOTIFF = 8, // GeoTIFF metadata
FIMD_ANIMATION = 9, // Animation metadata
FIMD_CUSTOM = 10 // Used to attach other metadata types to a dib
};
Ok, now I can extract the model of the camera:
FreeImage_GetMetadata(FIMD_EXIF_MAIN, bitmap, "Model", &tag); printf(FreeImage_TagToString(FIMD_EXIF_MAIN, tag, NULL));
As you can see, I need to pass the model of the “Model” tag. But if I don’t know which model to use, I can loop through all of them until the returned value of the FreeImage_GetMetadata function is not NULL:
for(model = 0; model < 11; model++) {
if(FreeImage_GetMetadata(model, bitmap, tagName, &tag))
return rb_str_new2(FreeImage_TagToString(model, tag, NULL));
}
Finally I can write a ruby module that extends ImageScience and adds the ability to get an exif tag:
module ImageScienceExifData
def [](key)
if key =~ /^EXIF:(\w+)?/
get_exif($1)
end
end
inline do |builder|
if test ?d, "/opt/local" then
builder.add_compile_flags "-I/opt/local/include"
builder.add_link_flags "-L/opt/local/lib"
end
builder.add_link_flags "-lfreeimage"
builder.add_link_flags "-lstdc++" # only needed on PPC for some reason. lame
builder.include '"FreeImage.h"'
builder.prefix <<-"END"
#define GET_BITMAP(name) FIBITMAP *(name); Data_Get_Struct(self, FIBITMAP, (name)); if (!(name)) rb_raise(rb_eTypeError, "Bitmap has already been freed")
END
builder.c <<-"END"
VALUE get_exif(char *tagName) {
GET_BITMAP(bitmap);
FITAG *tag = NULL;
const char *value;
int model;
for(model = 0; model < 11; model++) {
if(FreeImage_GetMetadata(model, bitmap, tagName, &tag))
return rb_str_new2(FreeImage_TagToString(model, tag, NULL));
}
return Qnil;
}
END
end
end
ImageScience.send(:include, ImageScienceExifData)
ImageScience.with_image(filename) do |img|
puts img["EXIF:Model"]
end
The output with the picture I used is the following :
NIKON COOLPIX S3 2006:12:10 12:09:17
It doesn’t work with all the exif names but for now it’s ok for my needs. The next step is to add the code above in my rails application and use it with attachment_fu. I’ll write another post about that soon.
The github revolution has hit me too. I’m moving all my Radiant extension to my account on github. Follow me and fork my projects :)!
The NYT posted an interesting article about what seems to be the fading point of municipal wireless projects: many cities are rolling back their projects, as it seems there are no more hopes of revenues that can help sustain the infrastructure.
The problem was in the original approach that many cities had towards the creation of such projects:
“The entire for-profit model is the reason for the collapse in all these projects” says Sascha Meinrath on the NYT’s article. Many companies have seen those projects as a new way to enter the ISPs market. Obviously that market is pretty crowded, revenues are already fading away for traditional ISPs, and newcomers are having bad days.
Wireless technologies (both wifi and wimax) raise many infrastructure problems (radio signal issues, compatibility problems, small coverage range, ..) and many networks aren’t profitable at all (in most cases they represent a big loss for both companies and cities).
As a result of this situation many companies are pulling out from projects they were involved in (as Earthlink did in Philadelphia and other cities). This is a problem for cities who need solid partners to build such services. Residents are also concerned, especially low-income families who were expecting municipal networks as a way to get cheaper connections. This is particularly important for children, as Internet connection is tightly tied to their education.
Fortunately a new approach could be the solution to those issues.
Meraki jumped in the market with a different strategy: they are selling cheap devices that plugs into existing home connections
extending them with public wifi signal. Additionally they sell cheap devices to be used outside (mainly on light poles). As you probably know Fon has a very simlar approach since almost two years: they are offering cities free (or almost free) wifi routers for residents, that would allow the inhabitants to build their own networks. Routers installed on DSL connections at home team up to create a public network that could cover the entire city.
This grassroot approach could be a way to overcome failures. The fon city project is already active in five cities across Europe, while many others are interested in such projects.
Many ISPs do not allow their customers to share DSL connections, so this kind of networks could face a new problem in the near future.
While cities are still trying to find the right approach someone is already thinking about giving free wifi routers to homeless people, who can then sell connections to people who are around them for a small tip.
Some weeks ago Casper Fabricius sent me a patch for the Radiant Newsletter extension. He added a statistics system to track how many times sent emails are opened. I have finally found the time to apply it and make a commit to my repository. Thank you very very much for your work Casper! I’ll write an article about this extension as soon as possible.