You are viewing a plain text version of this content. The canonical link for it is here.
Posted to axkit-dev@xml.apache.org by ma...@sergeant.org on 2006/08/23 00:22:38 UTC
[SVN] [110] Initial AIO support
Revision: 110
Author: matt
Date: 2006-08-22 22:22:18 +0000 (Tue, 22 Aug 2006)
Log Message:
-----------
Initial AIO support
Made gallery a bit faster on resizes
Modified Paths:
--------------
trunk/NOTICE
trunk/lib/AxKit2.pm
trunk/plugins/demo/gallery
Added Paths:
-----------
trunk/plugins/aio/
trunk/plugins/aio/uri_to_file
Modified: trunk/NOTICE
===================================================================
--- trunk/NOTICE 2006-08-22 22:21:28 UTC (rev 109)
+++ trunk/NOTICE 2006-08-22 22:22:18 UTC (rev 110)
@@ -1,2 +1,5 @@
-This product includes software developed by
-The Apache Software Foundation (http://www.apache.org/).
\ No newline at end of file
+Apache AxKit (Version 2)
+Copyright 2006 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
Modified: trunk/lib/AxKit2.pm
===================================================================
--- trunk/lib/AxKit2.pm 2006-08-22 22:21:28 UTC (rev 109)
+++ trunk/lib/AxKit2.pm 2006-08-22 22:22:18 UTC (rev 110)
@@ -21,7 +21,10 @@
use AxKit2::Server;
use AxKit2::Config;
use AxKit2::Console;
+use AxKit2::Constants qw(LOGINFO);
+use constant AIO_AVAILABLE => eval { require IO::AIO };
+
our $VERSION = '1.0';
sub run {
@@ -40,6 +43,12 @@
AxKit2::Server->create($server);
}
+ if (AIO_AVAILABLE) {
+ AxKit2::Client->log(LOGINFO, "Adding AIO support");
+ Danga::Socket->AddOtherFds (IO::AIO::poll_fileno() =>
+ \&IO::AIO::poll_cb);
+ }
+
# print $_, "\n" for sort keys %INC;
Danga::Socket->EventLoop();
Added: trunk/plugins/aio/uri_to_file
===================================================================
--- trunk/plugins/aio/uri_to_file 2006-08-22 22:21:28 UTC (rev 109)
+++ trunk/plugins/aio/uri_to_file 2006-08-22 22:22:18 UTC (rev 110)
@@ -0,0 +1,156 @@
+#!/usr/bin/perl -w
+
+# Copyright 2001-2006 The Apache Software Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+=head1 NAME
+
+uri_to_file - Convert URIs to filenames, and other critical stuff
+
+=head1 SYNOPSIS
+
+ Plugin uri_to_file
+
+ # optionally:
+ DirectoryIndex index.html
+
+=head1 DESCRIPTION
+
+This plugin provides the filename for a given URI. It is absolutely required
+that you load this plugin if you wish to serve files off the filesystem, or else
+re-implement its functionality somehow.
+
+It also splits off the path_info off the URI, provides a redirect when a
+directory without a "/" is requested, and implements C<DirectoryIndex> (see below).
+
+=head1 CONFIG
+
+=head2 DirectoryIndex STRING
+
+A filename to append to directory requests. If the file exists then it will be
+the filename used instead of the directory itself.
+
+=cut
+
+use File::Spec::Functions qw(canonpath catfile);
+use AxKit2::Utils qw(uri_decode);
+
+sub register {
+ my $self = shift;
+ $self->register_hook('uri_translation' => 'hook_uri_translation1');
+ $self->register_hook('uri_translation' => 'hook_uri_translation2');
+}
+
+sub init {
+ my $self = shift;
+ $self->register_config('DirectoryIndex', sub { $self->set_dirindex(@_) });
+}
+
+sub set_dirindex {
+ my ($self, $config, $value) = @_;
+ my $key = $self->plugin_name . '::dirindex';
+ $config->notes($key, $value);
+}
+
+sub hook_uri_translation1 {
+ my ($self, $hd, $uri) = @_;
+
+ $self->log(LOGINFO, "translate: $uri");
+
+
+ $uri =~ s/(\?.*)//;
+ my $removed = $1 || '';
+
+ my $original_uri = $uri;
+
+ $uri = uri_decode($uri);
+
+ my $root = $self->config->path;
+
+ $uri =~ s/^\Q$root// || die "$uri did not match config path $root";
+
+ my $path = canonpath(catfile($self->config->docroot, $uri));
+ $path .= '/' if $uri =~ /\/$/; # canonpath will strip a trailing slash
+
+ my $path_info = '';
+
+ # set default return value
+ $self->client->notes('uri_to_file_retcode', DECLINED);
+
+ # the default will work in most cases, so we do this once here.
+ $hd->filename($path);
+
+ # save these so they get locked in for the closure.
+ my $client = $self->client;
+ my $config = $self->config;
+
+ IO::AIO::aio_stat($path, sub {
+ $self->log(LOGINFO, "aio_stat($path) returned ($_[0])");
+ if ($_[0]) {
+ # error (usually file didn't exist).
+ print "error\n";
+ while ($path =~ /\// && !-f $path) {
+ $path =~ s/(\/[^\/]*)$//;
+ $path_info = $1 . $path_info;
+ }
+ if ($path_info && -f _) {
+ $hd->path_info($path_info);
+ substr($original_uri, 0 - length($path_info)) = '';
+ $hd->request_uri($original_uri);
+ }
+ else {
+ $path .= $path_info;
+ $hd->path_info('');
+ }
+ }
+ elsif (-d _) {
+ print "dir\n";
+ # URI didn't end in a slash - need to redirect
+ if ($original_uri !~ /\/$/) {
+ $self->log(LOGINFO, "redirecting to $original_uri/$removed");
+ $client->headers_out->header('Location', "$original_uri/$removed");
+ $client->notes('uri_to_file_retcode', REDIRECT);
+ return;
+ }
+ if (my $dirindex = $config->notes($self->plugin_name . '::dirindex')) {
+ my $filepath = catfile($path, $dirindex);
+ $path = $filepath if -f $filepath;
+ }
+ }
+ elsif (-f _) {
+ print "file\n";
+ return;
+ }
+ else {
+ # neither a dir nor a file
+ die "Unknown entity type: $path";
+ }
+
+ print "Setting filename to $path\n";
+ $hd->filename($path);
+
+ $client->finish_continuation;
+ });
+
+ return CONTINUATION;
+}
+
+# This allows us to return REDIRECT above
+sub hook_uri_translation2 {
+ my $self = shift;
+
+ print "Continuation returns!\n";
+ return $self->client->notes('uri_to_file_retcode');
+}
Modified: trunk/plugins/demo/gallery
===================================================================
--- trunk/plugins/demo/gallery 2006-08-22 22:21:28 UTC (rev 109)
+++ trunk/plugins/demo/gallery 2006-08-22 22:22:18 UTC (rev 110)
@@ -57,8 +57,6 @@
use RDF::Core::Model::Serializer;
use AxKit2::Utils qw(uri_decode uri_encode);
-use constant EPEG_AVAILABLE => eval { require Image::Epeg };
-
our $DEFAULT_SIZE = '133 640 800 1024';
sub hook_xmlresponse {
@@ -136,18 +134,7 @@
my $out;
- if ($type eq 'jpeg' && EPEG_AVAILABLE) {
- my $epg = Image::Epeg->new($file);
- $epg->resize($size, $size, Image::Epeg::MAINTAIN_ASPECT_RATIO());
- $out = $epg->get_data();
- if (!$out) {
- # Epeg didn't work. Resort to Imager anyway
- $self->resize_image($size, $file, $type, \$out);
- }
- }
- else {
- $self->resize_image($size, $file, $type, \$out);
- }
+ $self->resize_image($size, $file, $type, \$out);
$cache->set("$file+$size", $out);
@@ -175,22 +162,36 @@
$quality = 'normal' if $quality ne 'preview';
$quality = 'normal' if $self->client->param('size') ne 'thumb';
- $self->log(LOGINFO, "Scaling to $size");
+ $self->log(LOGINFO, "Scaling to $size with quality: $quality");
+ my $doublesize = $size < (($w > $h ? $w : $h)/2);
+
+ if ($quality eq 'normal' && $doublesize) {
+ $self->log(LOGINFO, "Doing an initial shrinkage in preview mode");
+ my $thumb = $image->scale(qtype => "preview",
+ $w > $h ? (xpixels => $w/2)
+ : (ypixels => $h/2)
+ );
+
+ $image = $thumb;
+ }
+
my $thumb = $image->scale(qtype => $quality,
$w > $h ?
(xpixels => $size)
: (ypixels => $size)
);
- $self->log(LOGINFO, "sharpening $thumb");
+ if ($doublesize) {
+ $self->log(LOGINFO, "sharpening $thumb");
+
+ # Sharpen a bit with a convolve filter
+ $thumb->filter(
+ type=>'conv',
+ coef => [-0.2, 1, -0.2]
+ ) if $quality eq 'normal';
+ }
- # Sharpen a bit with a convolve filter
- $thumb->filter(
- type=>'conv',
- coef => [-0.2, 1, -0.2]
- ) if $quality eq 'normal';
-
$thumb->write(data => $out, type => $type)
or die "Cannot write to scalar: ", $thumb->errstr;
}