Práctica: Callbacks en ForkManager

El módulo Parallel::ForkManager permite el uso de llamadas diferidas o callbacks. Las callbaks se establecen mediante los métodos del objeto Parallel::ForkManager run_on_start, run_on_wait y run_on_finish. Estas reciben como argumentos las referencias a las subrutinas que se ejecutarán en las correspondientes situaciones. Consulte el manual de Parallel::ForkManager.

Modifique el ejemplo en la sección anterior para que disponga de un hash con claves en los PID y cuyos valores sean un hash anónimo conteniendo la información asociada al proceso: enlace a descargar, estatus de finalización y el PID. Para actualizar el hash use callbacks en el arranque y en la finalización de cada proceso. Añada al programa un parámetro $limite que controla el tiempo límite de descarga. Si el tiempo es superado elimine los procesos de descarga que no hayan terminado. Use para ello un callback de espera (run_on_wait).

Un manejador instalado con run_on_start será ejecutado cada vez que se crea con éxito un nuevo proceso hijo. El manejador es llamado con dos argumentos:

  1. El PID del proceso
  2. El identificador del proceso (si fué proveído en la llamada a start)

El formato de llamada de run_on_wait es run_on_wait($code, [$period]). La rutina referenciada por $code es llamada por el proceso padre cada vez que se crea un nuevo hijo. Si se provee el segundo argumento $period entonces la subrutina referenciada por $code es llamada periódicamente, aproximadamente cada $period segundos. No se le pasan parámetros a $code.

El siguiente ejemplo muestra la instalación de manejadores on_start y on_wait.

$pm->run_on_start(
   sub {
      my ($pid, $link)=@_;
      $pid_table{$pid} = {link => $link, pid => $pid, exit => undef};
   }
);

$pm->run_on_wait(
   sub {
     print "Time: ".(time()-$start_time)."\n";
     for (keys %pid_table) {
       print "$_ => $pid_table{$_}->{link}\n";
     }
     print "\n";
   }, $period
);

El manejador instalado mediante run_on_wait muestra el tiempo transcurrido desde $start_time asi como el contenido del hash %pid_table:

Casiano Rodríguez León
2010-03-22
x2html2767" HREF="node310.html"> index PP2PP2 moodlepsmodulosperlmonksperldocgoogleetsiiullpcgull
Sig: Práctica: Callbacks en ForkManager Sup: Fork y Señales Ant: El Módulo Parallel::Simple
Casiano Rodríguez León
2010-04-19
/PRE> El operador eq devuelve TRUE si las dos cadenas asociadas son iguales:
  DB<8> p $u eq $z
1
  DB<9> p $u eq $w

Recuerde que las componentes que describen el fichero y directorio diferencian entre el uso de mayúsculas y minúsculas (si es que el S.O. lo hace) Esto no ocurre con la componente que define el dominio.

Métodos Auxiliares

Métodos auxiliares de utilidad son path_query, path_segments, host_port y default_port:

pp2@nereida:~/src/perl/LWP$ perl -MURI -wde 0
main::(-e:1):   0
  DB<1> $u = URI->new('http://user:pass@example.com:992/animal/bird?species=seagull#wings')
  DB<2> x $u->path_query
0  '/animal/bird?species=seagull'
  DB<3> x $u->path_segments                      # contexto de lista
0  ''
1  'animal'
2  'bird'
  DB<4> x scalar($u->path_segments)              # contexto escalar
0  '/animal/bird'
  DB<5> x $u->host_port
0  'example.com:992'
  DB<6> x $u->default_port
0  80



Ausencia de Ciertas Componentes

En general, cuando una componente no existe el correspondiente método devuelve undef:

  DB<7> $v = URI->new('http://example.com/index.html')
  DB<8> print "not defined" unless defined($v->query)
not defined

Sin embargo ciertas componentes no tiene sentido en ciertas clases de URLs. Por ejemplo un URL del tipo mailto: no dispone de una componente host. En tal caso, la llamada al método host produce una excepción:

  DB<9> $m = URI->new('mailto:name@domain.es')
  DB<10> print $m->host
Can't locate object method "host" via package "URI::mailto" \
   at (eval 18)[/usr/share/perl/5.8/perl5db.pl:628] line 2.
La excepción puede evitarse comprobando el esquema o usando el método UNIVERSAL can:
 DB<11> $x = $m->can('host')? $m->host : "No host"
 DB<12> print $x
No host

Argumentos de una LLamada

En los primeros tiempos de internet los argumentos de una llamada a un procesador de un formulario (queries) eran cadenas separadas por el signo '+'

pp2@nereida:~/src/perl/LWP$ perl -MURI -wde 0
  DB<1> $v = URI->new('http://www.example.com/search.pl?LWP+module+perl')
  DB<2> x $v->query_keywords()
0  'LWP'
1  'module'
2  'perl'
El método query_keywords permite obtener la lista de argumentos cuando la llamada ocurre de acuerdo con este protocolo. Posteriormente se ha adoptado una forma de llamada con nombres:

  DB<4> $w = URI->new('http://www.example.com/search.pl?lib=LWP&word=module&language=perl')
  DB<5> x $w->query_form()
0  'lib'
1  'LWP'
2  'word'
3  'module'
4  'language'
5  'perl'
en este caso usamos el método query_form

Conversión de una URL Relativa en una Absoluta

Una URL absoluta comienza con el esquema y contiene todas las componentes que el esquema requiere. Por ejemplo, la URL

http://nereida.deioc.ull.es/~pp2/perlexamples/node37.html
es absoluta.

Cualquier URL que no comienza con un esquema es relativa. Para determinar el recurso al que se refiere una URL relativa es necesario prefijar una URL base absoluta. Se usa una notación que semeja la notación Unix para describir la jerarquía de archivos:

Las siguientes URL son relativas:

El método new_abs permite la conversión de URLs relativas en absolutas:
        $abs = URI->new_abs($relative, $base);
Por ejemplo:
casiano@beowulf:/tmp/Net-Server-0.96/examples$ perl -MURI -dwe 0
  DB<1> $base = 'http://nereida.deioc.ull.es/~pp2/perlexamples/node37.html'
  DB<2> $can = URI->new_abs('../apuntes/node127.html', $base)->canonical
  DB<3> x $can
0  URI::http=SCALAR(0x83e75c0)
   -> 'http://nereida.deioc.ull.es/~pp2/apuntes/node127.html'
  DB<4> p $can
http://nereida.deioc.ull.es/~pp2/apuntes/node127.html

Conversión de una URL Absoluta en una Relativa

El método rel permite la conversión de URLs absolutas en relativas:

        $rel = $absolute->rel($absolute_base);
Por ejemplo:
casiano@beowulf:/tmp/Net-Server-0.96/examples$ perl -MURI -dwe 0
DB<1> $pp2_37 = URI->new('http://nereida.deioc.ull.es/~pp2/perlexamples/node37.html')
DB<2> $pl_37 = URI->new('http://nereida.deioc.ull.es/~pl/perlexamples/node37.html')
DB<3> p $pl_37->rel($pp2_37)
../../~pl/perlexamples/node37.html



Subsecciones
Casiano Rodríguez León
2010-05-05