Cómo perder un bit

Un proyecto que hicimos a principio de año es un soft que maneja una PC para una rockola con su respectiva interfaz de hardware («la caja» de ahora en más) para interactuar con la botonera. En estos días el cliente nos pidió que agregaramos alguna validación para que la caja y el programa se aseguren que son «originales» (no es algo que me agrade agregar, pero el software es del cliente).

En fin, la cosa es que estuve todo el viernes y todo el lunes sin poderlo hacer andar. La caja me respondía perfecto salvo en un caso: cuando me llegaba 0x3F pinchaba. Lo peor es que era un valor que me llegaba sospechosamente seguido para ser aleatorio.

Le dimos mil vueltas con Tulku hasta que finalmente encontramos el problema, que obviamente era yo :), o más bien la implementación de SerialPort de .NET (de Microsoft al menos, el programa no corre en Mono todavía) que tiene defaults ridículos :).

El problema era que yo estaba usando un método que lee todo lo que está pendiente, pero justo ese método pasa los bytes por un Encoder, ¿y a que no adivinan? … Si, el Encoder por default es ASCII7BIT, por lo que me tiraba a la basura el bit más significativo del byte leído, haciendo que no hubiera chance de responder correctamente para terminar el handshaking.

Reemplazando el método por un while y leyendo byte a byte de manera RAW, el problema se solucionó.

Refactoring de «Fat Methods» – Episodio 4

En la última entrega habíamos logrado separar las notificaciones del controlador. Una de las cosas que todavía me seguían molestando eran los métodos donde obtengo las direcciones de email, como por ejemplo :

@notifications = @match.players.select {|p| p.user.notify_new_match_comment? }.collect {|p| p.user.email}

Lo que busca esto es obtener los emails de los usuarios para notificar ante un evento dado (un nuevo partido creado, un nuevo comentario, una petición de amistad, etc). Me molesta principalmente porque se ven horribles mis controllers :).

La respuesta que motiva este episodio llegó por casualidad. Intentando solucionar un bug que tenía en uno de los plugins que uso (has_many_friends, que es feo pero cómodo para un proyecto como este de prueba) vi algo que no conocía : las asociaciones (has_many, has_one, etc) aceptan un bloque donde podemos agregar funcionalidad extra.

Entonces, por ejemplo, si yo quisiera que el ejemplo anterior pueda ser escrito como @match.players.notificables (si, el nombre no es de lo mejor, pero es a modo ilustrativo) simplemente debería agregar ese método como sigue :

class Match < ActiveRecord::Base
  has_many :players  do
    def notificables
      collect {|p| p.user.email if !p.user.email.blank? && p.user.notify_new_match_comment? }
    end
  end
end

# Ejemplo de uso
@notifications = @match.players.notificables

El método que agregamos trabaja directamente sobre la asociación, que en este caso es una colección de Player, por lo que el collect nos dará todos los emails de los usuarios que se anotaron al partido y tienen activa la opción de recibir notificaciones cuando alguien deja un comentario nuevo en ese partido.

Los métodos que agregamos pueden aceptar parámetros también, con lo cual podría aceptar un symbol con el tipo de permiso a verificar y tener todos los emails de los usuarios para un tipo de notificación dada. Ahora si se hace un refactor de las opciones de notificación de los usuarios tenemos centralizada la lógica en los modelos en lugar de tenerla en los controladores u observers.

Ruby Argentina – Resumen

Ya pasó la reunión planeada para hoy, y la verdad que fue todo un éxito :). A pesar del calor y de ser un sábado tuvimos unas 25 personas que vinieron, un gran avance contra las 4 de la primera reunión.

Arrancamos a las 11hs donde íbamos a tener una charla de introducción a ruby. Lamentablemente por un caso de fuerza mayor se suspendió pero improvisamos Lightning Talk y para que la gente que venía por primera vez se diera a conocer.

Luego Luis nos presentó Rake Compiler, que tiene como objetivo simplificar la construcción de gemas que tienen extensiones nativas y permite además a los programadores hacer cross-compiling.

Siguiendo Pelle Braendgaard dio una charla de OAuth muy interesante. La idea básica es poder proveer identificación entre sitios sin necesidad de introducir passwords (al estilo de OpenID) pero teniendo mayor flexibilidad, pudiendo revocar esos permisos o que expiren por período de tiempo.

Para terminar Pedro dio una charla de cómo ser freelance, los miedos y desafíos, que fue muy interactiva con el público. La dio como en la vieja escuela con un proyectos de diapositivas :).

Para el cierre hicimos el sorteo de los libros que aportó Cafelug y una remera de aportada por Pedro.

http://picasaweb.google.com/s/c/bin/slideshow.swf

Monsters vs Aliens

El martes pasado fui a cubrir un evento que realizaba la gente de Dreamworks en Argentina, en simultáneo con «no me acuerdo cuantos otros países«, donde presentaban su tecnología para hacer películas 3D. Acá no voy a hablar de eso, pero pueden leer la nota de prensa que publiqué acá.

Es muy groso que se avance en este sentido, la experiencia de ver una película en 3D es genial (y hablo de sensación de 3D posta, no un cheatmode a la iMAX). La película pinta grosa, muy histérica al estilo de Shrek.

httpv://www.youtube.com/watch?v=P9kCMfZBZUo

De lo que sí quiero hablar es del gran FAIL del evento : los sistemas anticopia :), que les atrasó toda la movida casi una hora.

Según me comentaba la gente de la organización las películas viajan encriptadas y para poder reproducirlas te manda un «key» que es válido solo por N horas de reproducción.

En este caso tuvieron que mandar 4 llaves diferentes, ya que la primera había expirado, la segunda llegó vacía, la tercera corrupta y finalmente con la cuarta pudimos ver la película. Lo que llama la atención es que tarde tanto en llegar. Cada una demoraba como 15 minutos desde que decían «ahí está bajando» hasta el «vamos a ver si anda«. Suponiendo que bajás a 200kBytes/sec, y tardás 900 segundos .. tenés un archivo de unos 175Mb. ¿Cómo te llegan 175Mb «vacíos»?

En fin, no solo demostraron lo malo que son este tipo de cosas para el consumidor, sino que también les pueden perjudicar a ellos mismos cuando necesitan resultados. Fue medio papelón, aunque con todo lo que nos dieron para comer y tomar se puede perdonar un poco 🙂

Llegaron los 30

Y si, algún día iba a tocar. Es una realidad innegable que la edad es una de las pocas cosas que no discrimina en este mundo :).

Ya dejo de ser ese «adolescente» para convertirme en un hombre de bien (?) sea lo que eso signifique 😛 … ¿dejar los fichines? Ni borracho! …. ¿empezar a vestirme «como persona»? Seguí soñando 🙂 …. ¡¿madrugar?! Creo que la sociedad espera demasiado de mi.

Me faltó hacer un release de Oregano como otros años, pero la Tesis no me deja tiempo :(. Quedará para los 31.

Pattern matching made easy

Siguiendo en carrera para ir cerrando problemas para mi tesis en esta oportunidad necesité buscar una manera simple de hacer pattern matching. El uso que le iba a dar era muy simple y no necesitaba mucho poder a la hora de las expresiones que se iban a definir.

La idea es poder definir qué métodos quiere uno interceptar usando algún patrón. Por ejemplo, si queremos ejecutar cierto código antes de cualquier método de la clase Test, simplemente debería bastar con poder especificar «Test:* (*)». En este caso acepto cualquier método con cualquier cantidad de parámetros (puede ser vacío). O si queremos anticipar las llamadas a ToString podríamos definir «*:ToString ()».

Haciendo una rápida búsqueda en Mr. G. caí primero en en la documentación de la GNU C Library. Tiene más o menos lo que necesitaba, específicamente la sección de «wildcard matching», pero no encontré como precompilar el patrón. Es algo requerido ya que se evalúa para cáda método que el JIT está por ejecutar por lo que si quiero que sea más o menos «performante» no puedo darme el lujo.

Estaba a punto de ir por una solución usando expresiones regulares cuando me encontré con que la biblioteca glib soporta «glob-style pattern matching«. Tiene menos operadores que la otra (solo * y ?) pero es más que suficiente para empezar. Como glib es usada por Mono internamente por todos lados no agrega una dependencia extra así que por ahora estoy usándola.

La API es bastante cómoda (aunque siguiendo el fiel estilo de glib los nombres son largos), siendo un simple ejemplo de uso :

GPatternSpec *pattern = g_pattern_spec_new ("Test:* (*)");
g_pattern_match_string (pattern, "Test:Bar ()"); // true
g_pattern_match_string (pattern, "Test:Foo (int)"); // true
g_pattern_match_string (pattern, "System.Console:WriteLine (string)"); // false

En mi código no uso g_pattern_match_string ya que recomiendan que si uno tiene varios wildcards se obtienen mejores resultados pasando también el string invertido, por lo que uso directamente g_pattern_match que acepta más parámetros, incluido el string invertido. Lo bueno es que no tengo que preocuparme por strings multibytes porque hasta ahora no conozco ningún lenguaje que corra sobre .NET que permita usar caracteres extendidos para nombrar clases y métodos :).

Me queda como tarea analizar ambas bibliotecas para ver si efectivamente la implementación de glib es más óptima a la hora de hacer repetidas consultas sobre un patrón.

Reunión Mensual de Ruby Argentina

Hoy anunciamos la próxima reunión mensual que se va a desarrollar la semana que viene. Cualquier interesado en dar alguna charla puede dejarme un comentario.

El día 29/11 se presentará un conjunto de charlas y se lanzará el ciclo mensual de conferencias sobre Ruby y Ruby on Rails y organizado por Argentina on Rails y Ruby Argentina.

El evento se llevará a cabo entre las 11 y las 16hs, con un break para almorzar sobre las 13hs. Al momento contamos con la presencia de Luis Lavena, actual mainteiner del one-click installer de Ruby para Windows, Pedro Vistinin de Argentina on Rails. A medida que tengamos confirmación de los demás oradores la iremos comunicando.

Luis hablará del rake-compiler y draco
rake-compiler es una serie de tareas de rake que simplifican la compilacion de tanto extensiones como gemas en Ruby, cosa que hasta ahora viene bastante descuidada y caoticamente un desastre entre developers. Cositas lindas para que no tengan mas excusas de no hacer cosas para Windows…

Pedro Visintin hablará de como hacerse freelance (trabajando con rails
🙂 ) y no morir en el intento.

Si estás interesado en dar alguna charla referida a Ruby o Rails, mandá un mail  que veremos como proveerte un espacio en ésta o próximas ediciones del evento.

Lugar
La cita es en la Facultad de Ingeniería de la UBA, Paseo Colón 850 en el Aula 402, 4to Piso. Capital Federal

La entrada es libre y gratuita y no requiere registración previa.

Además, CaFeLug sorteará 2 libros de Ruby/Rails de la editorial O’Reilly entre los asistentes.

Flash Player 10 para Linux

Esta semana hice un update de mi Ubuntu Intrepid ya que tenía varias cosas en espera de actualización. Uno de los paquetes que entró fue el Flash Player (nonfree) 10 de Adobe. Como me pasa siempre que aparece una nueva versión del player para Linux, mi estado de ánimo fue pasando de «contento» a «frustrado» :).

Flash parece que se va a quedar un rato largo, es una realidad innegable. También es una realidad que debemos evitar que se propague a donde el contenido importa, pero no veo mal que si alguien quiere hacer una campaña de marketing se haga un mega sitio en Flash, es problema de esa empresa (y al final tal vez me pagan por hacerlo, así que está doblemente bien :P). Otro nicho de Flash son los juegos casuales. Yo, como ex «hardcore gamer», migré a kongregate.com hace rato :).

Lo que más molesta es lo poco que hacen avanzar el plugin en cada release. En este caso se nota que lo único que agregaron es el soporte de los nuevos chiches (que dicho sea de paso el soporte de Bones para animar está muy groso para hacer videojuegos), pero no arreglaron ninguno de los problemas ni dan soporte a los «viejos chiches». Un ejemplo, todavía no hay soporte de V4L para poder usar las webcams desde Linux, es muy frustrante, sobre todo cuando hay Webcam Games que para pasar el rato son entretenidos.

Los problemas de performance también siguen, es imposible usar el «Pantalla Completa», sigue consumiendo mucho CPU, a veces el Firefox explota, etc. Historia conocida.

Parseando HTML desde Ruby

Con todo este lío de la crisis mundial, corridas bancarias y demás en la oficina los días tranquilos jugamos a «Adiviná cuánto va a salir el dolay hoy». Como es muy molesto entrar a «Dolar hoy dot com» donde miramos el valor oficial del juego, me puse a armar un script para robarme el valor actual y así ir tirando el dato minuto a minuto.

Siempre es una molestia tener que parsear HTML, sobre todo cuando es tan feo como el del sitio en cuestión, que no solo no tiene un solo class de CSS ni id, sino que usa el tag FONT, dios. Por suerte Hpricot está para ayudarnos :).

Hpricot es «a fast, flexible HTML parser written in C» con su interfaz a Ruby, obvio :). Hace cosas muy copadas, como por ejemplo agarrar un HTML, buscar todos los <a> que tengan el class custom, o todos los P seguidos de un DIV seguidos de un IMG, etc. Podemos consultar por ID, borrar, agregarle class a las cosas que encontramos y muchas cosas más, útiles para manipular HTML.

Lo primero que tuve que hacer fue saltear la «protección» del sitio, ya que para acceder a la página con las cotizaciones verifican que vengas del dominio principal. Un básico chequeo contra el HTTP_REFERER. Como suelo usar open-uri, a ésta le puedo pasar el referer que yo quiero enviar en el header, como cualquier biblioteca para manejar URIs que tenga auto-respeto :).

Para encontrar los valores fue fácil. Mirando el HTML de la página se ve que el valor del dolar está dentro de un «div/font/b/font», por lo que solo tuve que buscarlo. Después hago un cleanup para sacarle un non-breaking space que me molestaba y los espacios que también quedan feos.

Y eso es todo. Ahora puedo consultar el valor del dolar desde mi consola :). Seguramente hay miles de formas más cómodas de hacerlo, algún widget para Gnome, página que te de un RSS, etc, pero fue un lindo ejercicio.

Dejo acá el script para el que quiera jugar un rato.

require 'rubygems'
# gem install hpricot si no lo tienen instalado
require 'hpricot'
require 'open-uri'


doc = Hpricot(open("http://dolarhoy.com/indexx.php", "Referer" => "http://dolarhoy.com/"))

div = (doc/"div/font/b/font")[1]

dolar = div.inner_html

dolar = dolar.gsub(/[ |$]/, "")
dolar.strip!

puts "Dolar Hoy : $#{dolar}"

Generando assembler

En esta oportunidad para mi Tesis necesité ver cómo modificar el assembler generado por el JIT para agregar instrucciones antes y después de la llamada a un método. El código assembler generado originalmente es el siguiente :

00000000 (Test_Bar):
(bb):3
   0:   55                      push   %ebp
   1:   8b ec                   mov    %esp,%ebp
   3:   83 ec 08                sub    $0x8,%esp
   6:   83 ec 0c                sub    $0xc,%esp
   9:   68 c0 8f 05 00          push   $0x58fc0
   e:   e8 e5 fd ff ff          call   fffffdf8 (Test_Bar +0xfffffdf8)
  13:   83 c4 10                add    $0x10,%esp
(bb):1
  16:   c9                      leave  
  17:   c3                      ret    

Mi primer intento fue fácil y consistió en ejecutar una función desde assembler antes de cada método generado por el JIT usando los macros x86_push_reg y x86_call_reg. El primero permite poner un valor en un registro y el segundo hacer un call usando la dirección en el registro como punto de entrada. El paso siguiente fue pasarle un parámetro a la función, cosa que no fue tan fácil :).

Encontré que durante la compilación (en un método llamado mono_codegen) se llama a mono_arch_emit_prolog, que dependiendo de la arquitectura se linkea un método diferente. Como yo estoy haciendo todo para x86, me fui a buscar la función para esta arquitectura.

El método en cuestión se encarga de generar un bloque básico de instrucciones para llamar una función, resolviendo ya el problema del pasaje de argumentos, salvar los registros, asegurar alineaciones de memoria y otro tanto código que no se que hace :). Intenté un buen rato meter assembler a mano ahí sin mucho éxito, generando uno loops y segfaults muy bonitos.

Mi problema de insertar assembler antes del código generado por emit_prolog venía a la deriva hasta que caí en la cuenta que Mono tiene una opción de profiling y me puse a investigarla.

Encontré que si el profiler está activo en un momento se llama a mono_arch_instrument_prolog que permite pasarle una función y un MonoMethod (estructura interna que tiene toda la información de un método en código intermedio) y este genera el assembler para ejecutar esa llamada, que en este caso el profiler usa para contar cuantas veces se llama a cada método, entre otras cosas. Esta función me permitió cumplir mi cometido.

Simplemente agregué un método propio tomando como ejemplo cómo se llama al profiler, y el resultado fue que ahora el assembler generado queda :

00000000 (Test_Bar):
(BB):3
   0:   55                      push   %ebp
   1:   8b ec                   mov    %esp,%ebp
   3:   83 ec 08                sub    $0x8,%esp
   /* Acá empieza lo insertado */
   6:   83 ec 08                sub    $0x8,%esp
   9:   55                      push   %ebp
   a:   68 34 58 2f 08          push   $0x82f5834
   f:   e8 64 6e 87 50          call   50876e78 (Test_Bar+0x50876e78)
  14:   83 c4 10                add    $0x10,%esp
  /* Acá termina */
  17:   83 ec 0c                sub    $0xc,%esp
  1a:   68 c0 9f 05 00          push   $0x59fc0
  1f:   e8 64 fd ff ff          call   fffffd88 (Test_Bar+0xfffffd88)
  24:   83 c4 10                add    $0x10,%esp
(BB):1
  27:   c9                      leave  
  28:   c3                      ret    

De a poco las cosas van andando y se va cerrando el ciclo. Estoy más cerca que hace 2 semanas de poder ejecutar algo útil :P.