Elucubrando

Abril 11, 2008

¿Programar en XML?

Archivado en: — rodrigo @ 10:16 am

Me llegó por ahí la pregunta, ¿es válido decir “Yo programo en XML”? Mi respuesta es que es tan válido como decir “Yo programo en ASCII”. Posiblemente cierto, pero bobo e irrelevante. Los márgenes de un twiterazo son demasiado pequeños para una explicación completa, así que mejor la pongo por acá.

XML no es un lenguaje. Y no dije “lenguaje de programación”, dije lenguaje. XML es metalenguaje, un juego de reglas para definir la sintáxis de otros lenguajes. Usar XML para definir un lenguaje le da un aspecto parecido al de todos los demás lenguajes definidos con él, pero no dice nada acerca de la semántica del lenguaje, es decir, del qué significa. Los lenguajes que se definan usando XML pueden ser lenguajes de programación, lenguajes de marcado de textos, lenguajes de intercambio de datos. XML no tiene nada que decir respecto a eso[1].

Un ejemplo relacionado lo da la familia de lenguajes “parecidos a C”. Si bien nadie se ha tomado la molestia de escribir con cuidado una descripción de la sintáxis común, todos los programadores la conocemos de uno u otro modo. Cosas como “los identificadores están formados de alfanuméricos”, “las palabras reservadas son cadenas de letras”, “los bloques se delimitan con {}”, “0x marca el inicio de un número en hexadecimal”. Todas estas reglas (y muchas otras, por supuesto) son parte del metalenguaje (no escrito) que describe la sintáxis de esa familia. Gracias a ellas es que C y C++ y Perl y Java tienen ese aspecto similar, ese “no se qué” que hace que quien ha programado en uno no se sienta intimidado al ver otro. A pesar de que los lenguajes en sí son sumamente distintos unos de otros.

Igualmente, XML es un juego de relgas del estilo: “El documento se estructura en bloques anidados con nombre”, “Los nombres no pueden contener espacios”, “El final del bloque repite el nombre del mismo”, “mayorque y menorque son caracteres reservados”, etc, etc. Mucha información acerca del aspecto, nada acerca del significado.

Las relgas de sintáxis son, por supuesto, importantes. XML destila la experiencia de mucha gente encontrando reglas útiles para lenguajes cuyo propósito principal es enmarcar un texto. De este modo, alguien que necesita diseñar un nuevo lenguaje puede saltarse esa parte (que es más bien aburrida) y evitar errores y ambiguedades de las que es difícil darse cuenta. Pero no son el lenguaje, así como no lo es el apegarse a la convención de representar un espacio con el número 32 y la letra ‘A’ con el 65, como en ASCII.



1. En general, las reglas de sintáxis definidas por XML están enfocadas a lenguajes de marcado de textos, en los que se espera que casi todo el documento sean datos (el texto) y las instrucciones pocas y esparcidas por ahí. Debido a esto, los lenguajes de programación definidos usando estas reglas tienden a ser más bien feos. Eso no impide que sean definidos, aunque sí tiende a impedir que sean usados, por lo menos voluntariamente.

Enero 28, 2008

La inferencia de tipos es tu amiga

Archivado en: — rodrigo @ 6:18 pm

Supongan que quieren hacer una estructura de datos para guardar una asignación de roles a permisos. Como lo van a usar para visualizar y editar, no basta con asociar a cada rol un conjunto de permisos, sino que necesitan asignar un booleano a cada par (rol, permiso) (Así, el código de visualización no tiene más que dibujar la matriz).

Como no estamos escribiendo C, lo que vamos a hacer es usar un Map (o hash table, o arreglo asociativo, o como le llamen en su lenguaje favorito) anidado. Vamos a tener un arreglo rolPermiso indexado por roles. La entrada asociada a cada rol es a su vez otro arreglo. Este segundo está indexado por permisos, y cada entrada es un booleano que nos dice si el rol tiene este permiso. ¿Limpio, no?

Dicho en perl, es algo parecido a

 $rolPermiso{$rol}{$permiso}

Muy bonito. Pero propenso a errores, por que tengo que tener mucho cuidado que $rol y $permiso tengan siempre algo válido. Si no, perl alegremente creará nuevas entradas en el arreglo con lo que sea que tengan esas variables.

De ese problema quien nos salva es el tipado estático. Si le avisamos al compilador que nuestro arreglo debe estar indexado por Roles, que el contenido deben ser arreglos de Booleanos indexados por Permisos, y creamos un par de enumeraciones para los Roles y los Permisos, el compilador se encarga de avisarnos «¡Oye, “Adninistrador” no es un rol válido!»

Claro que, para eso, necesitamos un sistema de tipos capaz de expresar ese párrafo. Y que al mismo tiempo no nos obligue a tonterías como el sistema de tipos de Pascal, que consideraba tipos diferentes a los arreglos de 4 enteros y a los de 5, y nos obligaba a escribir una función para ordenar arreglos de 4 enteros y otra para los de 5.

La solución, por supuesto, es el uso de tipos polimórficos (paramétricos, les llaman algunos). En Java 5 las funciones que toman arreglos asociativos genericos usan el tipo Map<K, V> en dónde K y V son variables de tipo, que expresan que a dichas funciones no les importa qué hay en el arreglo, sino sólo que la estructura es de arreglo.

La declaración de la variable que nos importa es entonces

 Map<Rol, Map<Permiso, Boolean>>

Hasta aquí, todo bonito. El problema, por supuesto, es en cuanto queremos inicializar dicha variable, usando una implementación específica de la interfaz Map y un wrapper que inicialize los valores de forma automática en el primer acceso. Como es necesario en cada punto decirle al compilador los tipos de todas las variables en cuestión la inicialización termina siendo el siguiente mounstruo:

    public Map<Rol, Map<Permiso, Boolean>> rolPermiso =
            new DefaultValueMap<Rol, Map<Permiso, Boolean>>(
                    new HashMap<Rol, Map<Permiso, Boolean>>(),
                    new DefaultValueMap.DefaultCreator<Rol, Map<Permiso, Boolean>>() {
                        public Map<Permiso, Boolean> create(Rol rol) {
                            EnumMap<Permiso, Boolean> tmp =
                                new EnumMap<Permiso, Boolean>(Permiso.class);
                            for (Permiso p : Permiso.values())
                                tmp.put(p, rol.tienePermiso(p));
                            return tmp;
                        }
                    });

(Con el problema exacerbado por que Java no tiene funciones de primer orden, así que el inicializador default tiene que quedar envuelto en un objeto de una clase anónima cuyo único propósito es pasar a su único método de un lado a otro. Fuchi.)

Una vez que se les pase el dolor de cabeza de tratar de leer eso, fijense que más o menos la mitad de esa inicialización consiste en reiterarle los tipos al compilador. Lo interesante es que el compilador sabe cuales deberían ser esos tipos (por que si los ponen mal, emite un error). Lenguajes como Haskell y ML se aprovechan de eso (y de un poco más de cosas, claro) y proporcionan inferencia de tipos. Basta con que le digan al compilador algunos de los tipos y él mismo averiguará cuales son todos los demás.

En nuestro caso, en Haskell bastaría con decir que
rolPermiso :: Map(Rol, Map(Permiso, Bool)

y luego seguirse usandolo casi igual que como lo haríamos en perl. El compilador inferirá entonces que si le pido

rolPermiso rol

“rol” debe ser una variable de tipo “Rol”, y si algúna parte del código la usé con un tipo incompatible (si le intenté asignar “Adninistrador”, por ejemplo) protestará ruidosamente por la inconsistencia, en lugar de fallar de formas misteriosas en algúna otra parte del código.

Claro que todo esto no es mucho consuelo cuando se ven obligados a usar Java, pero bueno.

Diciembre 18, 2007

Bug Squashing Party - Domingo 23 de diciembre, 10 AM, Nul Unu

Archivado en: — rodrigo @ 11:36 am

Para no perder el vuelo que ya ibamos agarrando el año pasado, el grupo de Debian México ha decidido organizar un BSP este 23 de diciembre. La ubicación es, como las veces anteriores, en las oficinas de Nul Unu.

Si están intesesados en asistir, anótense en la página de coordinación.

Como en ocasiones anteriores, hay varias recomendaciones para los asistentes:

  • De ser posible, lleven su propia laptop. ¡Con Debian, o de perdida Ubuntu, por supuesto! Tenemos disponibles uno o dos equipos para quien no tenga lap, pero por lo menos uno ya está apartado, así que no cuenten en realidad con ello.
  • No se trata de hacer un InstallFest, ni una sesión de “intenté configurar mi Debian para que lea mi USB formateado en VMS y no me salió”. Se trata de colaborar para corregir problemas. Dicho esto, si tienes ganas de colaborar pero no sabes por dónde empezar o como se le hace, eres más que bienvenido. Todos empezamos así.
  • Hay cafetera (y, contrario a lo que afirma gwolf, en realidad es bastante sencilla de usar). Lo que no hay es café. Apreciaríamos bastante a quien trajera un medio kilito.
  • Vamos a estar ahí desde las 10 AM y hasta por ahí de las 6 PM. Si no tienes tiempo de estar todo el día, puedes venir solo un rato, aunque sea a saludar.
  • Si tienes llave GPG, trae tu fingerprint y una identificación. Si no tienes, ¿que esperas? ¿No sabes como sacarla? ¡Acá te ayudamos también con eso!

A estas alturas, los que no viven cerca del DF (o sí, pero se van de vacaciones) han de estar quejandose del mugroso centralismo de los chilangos. Como no queremos eso, les recordamos que ustedes también están cordialmente invitados. Abran su cliente favorito de IRC, conecten al servidor irc.debian.org y unanse al canal #debian-mx donde los estaremos esperando para platicar, matar bugs, y tomarnos unas cuantas tasas de café virtual.

Junio 28, 2007

¡Esto es compresión!

Archivado en: — rodrigo @ 2:30 pm
$ git-svn multi-init https://liferea.svn.sourceforge.net/svnroot/liferea/trunk

$ git-svn multi-fetch
 [ como 5 horas viendo muchos mensajes con todo el historial de svn ]

$ du -sh .
84M     .

$ git repack -a -d
Generating pack...
Done counting 13754 objects.
Deltifying 13754 objects.
 100% (13754/13754) done
Writing 13754 objects.
 100% (13754/13754) done
Total 13754, written 13754 (delta 9817), reused 0 (delta 0)
Pack pack-6a7de5822f9f2f692e978674bdb5555778be8a1e created.

$ du -sh .
9.0M    .

Y sí, el historial sigue ahí.

Mayo 16, 2007

Disculpen ustedes

Archivado en: — rodrigo @ 7:36 pm

Para cumplir mejor con los lineamientos cambié la liga que tenía suscrita al Planeta Linux y eso causó que varios de mis artículos más viejos reaparecieran. Todos juntos, además. Prometo hacer todo lo posible por que no vuelva a ocurrir.

Noviembre 28, 2006

Puntos al infinito

Archivado en: — rodrigo @ 1:27 pm

Tomen R³. Digan que dos puntos son equivalentes si la linea que los une pasa por el origen.

Consideren ahora un plano P horizontal en el espacio y que no pase por el origen. ¿Que relación tiene con las clases de equivalencia? Piensen primero en un punto con z != 0. Su clase de equivalencia es la linea L que lo une con el origen. L no es horizontal (por que z != 0) así que tiene que cortar a P. Pero (0, 0, 0) no está en P, así que L no está contenida en P. Luego entonces, L corta a P en un único punto. Entonces, cada clase de equivalencia con z!= 0 corresponde a un punto en P, aquel en dónde L corta a P.

¿A que corresponde una linea dentro de P? Pues, cada uno de sus puntos es una linea L a travez del origen del espacio. Entonces la linea en P corresponde a un haz de lineas, todas por el origen. Y la intersección de ese haz con P es la linea original. Piensenlo un poquito y verán que entonces el haz tiene que ser por sí mismo un plano. Uno que pasa por el origen.

¿Qué hemos hecho hasta aquí? Hemos puesto en correspondencia los puntos de un plano P con lineas que pasan por el origen del espacio. Y las lineas de P con planos que pasan por el origen del espacio. ¿Qué pasa si las lineas en P se intersectan? Pues que los planos correspondientes también lo hacen, por supuesto.

Y, aquí viene lo bueno, ¿que pasa con dos lineas paralelas no colineales en P? No se cortan en P, por supuesto. ¿Y sus planos correspondientes? Tienen que cortarse, porque los dos pasan por el origen. Y dos planos que se cortan, lo hacen en una linea. ¿Dónde está esa linea? Tiene que existir y pasar por el origen. Pero no puede cortar a P. Y la única forma de lograr eso es que la linea sea horizontal. Es decir, está hecha de puntos con z=0, los que no consideramos arriba.

¿Que sale de todo esto? Sean L y L’ lineas en P, no colineales. Si son no paralelas, se cortan en un punto p. Y sus planos correspondientes se cortan en la linea correspondiente a p. Si son paralelas no se cortan. Pero sus planos correspondientes si lo hacen. En una linea que pasa por el origen. Y ya habiamos identificado que casi todas las lineas que pasan por el origen corresponden a puntos en P. Las únicas que nos faltaban eran, precisamente, las horizontales. ¿Por qué no entonces decir que las lineas horizontales corresponden a puntos en un ‘plano ampliado’? Uno con la maravillosa caracteristica de que todos los pares de lineas se cortan en un punto. Ese plano ampliado se llama plano proyectivo, el montón de puntos que añadimos (todas las lineas horizontales del plano) es la linea al infinito y el nuevo punto en el que se cruzan el par de lineas paralelas, ese es el punto al infinito del que habla damog.

Septiembre 7, 2006

bash es tu amigo

Archivado en: — rodrigo @ 8:13 pm

¿Te equivocaste al hacer un commit a subversion? ¿Y ahora hay un montón de archivos *.jar en el directorio equivocado? Por supuesto los quieres eliminar pero, tambien por supuesto, no pretendes escribir todos esos nombres tú. Y quieres que la eliminación se marque toda como un sólo cambio.

Entonces, lo que tienes que hacer es obtener desde el servidor la lista de archivos, convertir eso en una lista de URLs a eliminar y darselas otra vez a subversión a que las elimine:

eval "svn rm -m'import erroneo' svn://localhost/Qcotizador/trunk/{$(svn list svn://localhost/Qcotizador/trunk |grep jar$ |tr 'n' ',' | sed -e 's/,$//')}"

Creo que exageré llamando a sed solo para quitar una ‘,’ final, pero esto es sólo un quick’n’dirty hack, así que no me preocupo.

Septiembre 5, 2006

De sistemas operativos y emulaciones

Archivado en: — rodrigo @ 10:37 am

Siento desilusionarte, Hector, pero si tu profesor de sistemas operativos te dijo esto, cambiate de profesor.

La función de un sistema operativo es proporcionar abstracciones a los programas para el manejo del hardware. Esas abstracciones son presentadas en la forma de funciones (syscalls) que realizan las operaciones que el programa necesita. Diferentes sistemas operativos tienen diferentes operaciones que ofrecer a los programas, dependiendo de las decisiones de diseño del sistema.

Un programa compilado para un sistema operativo no ejecuta en el otro por que las llamadas al sistema que espera usar no están ahí. Esto no sólo funciona para Linux vs Windows. Linux y un BSD, por ejemplo, tienen básicamente las mismas funciones, pero como implementan de forma diferente el mecanismo para llamarlas, un programa compilado para uno no corre en el otro*.

Si solo fuera cuestión del acomodo en memoria, hacer una emulación (del sistema operativo, no de arquitectura de procesador o algo así) sería muy sencillo. Bastaría con cargar las piezas del programa en otro orden. Precisamente por que no se trata sólo de eso es que el proyecto wine lleva años trabajando en lograr esta emulación y todavía no termina.

* Sé que hay bibliotecas de emulación de unos en los otros. Estoy tratando de simplificar esto, ¿sí?

Agosto 10, 2006

Inflecciones

Archivado en: — rodrigo @ 5:55 pm

Para empezar, saludos a Iván y a los demás nuevos miembros del Planeta Linux México.

Averiguando quienes son y a que se dedican y esas cosas, me dí cuenta que Iván está tratando de mejorar el soporte para inflexiones de palabras en español de un módulo de Ruby llamado Inflector.

Hablo sin haber usado nunca Ruby (y mucho menos el mencionado Inflector, en consecuencia) pero sospecho que te falta, por lo menos, manejar las terminadas en z (pez -> peces). Y eliminar acentos (canción -> canciones). Y no sé que tanto más, la verdad.

El paquete ispell (y su reemplazo moderno, aspell) tiene listas de reglas para hacer eso de las inflecciones para muchos idiomas, el español incluido. Habías de echarle un ojo a usarlas/adaptarlas/algo-así.

Esta entrada, y la de hace unos días del ‘¿’, me hacen pensar que sería una buena idea abrir una nueva sección en Elucubrando para mis divagaciones lingüísticas. Me pregunto si valdrá la pena o si nada más es una racha temporal.

¡Ah, otra cosa! Iván, tu blog no parece aceptar comentarios (me pide hacer login) por eso contesto por acá.

Julio 14, 2006

svn, ssl y trac.

Archivado en: — rodrigo @ 1:14 pm

Como parte de la gran campaña Nul Unu para la mejora de los procesos (hola, Daniel), acabo de instalar un depósito central de subversion y una instalación generica de Trac para los proyectos. La intención es

  • Tener un control de los problemas y faltantes por cada proyecto.
  • Tener un punto central para la documentación.
  • Coordinar estas cosas con el control de versiones.

Ahora bien, como en cada proyecto participan diferentes personas, necesito tener controles de acceso más o menos finos. Y sería bueno que dichos controles estuvieran coordinados entre subversion y Trac. Entonces, documentando para la posteridad, a continuación mis elecciones de configuración para lograr eso:

  1. Todo debe quedar, por supuesto, en un servidor público. Por razones de llevarse bien con el proveedor, nuestro servidor usa RedHat. Enterprise 4, creo.
  2. Los controles de acceso finos requieren, o que use subversion via Apache, o svnserve pero con subversion 1.3. Usar apache significa darle permisos de leer y escribir en el depósito al usuario apache. En un servidor con mucho PHP. Eso es una muy mala idea, así que nos vamos por svn1.3. Como RHES4 tiene 1.1.algo, tenemos que instalarlo aparte. Afortunadamente para mi salud mental, alguien ya hizo paquetes de subversion, así que nada de andar compilando e instalando a mano.
  3. El punto malo de svnserve es que el protocolo no tiene opción para cifrar la comunicación. Hay dos formas de darle la vuelta a esto. O usamos svn+ssh, o usamos stunnel para encapsular el protocolo. Por ahora me fuí con stunnel, pero los métodos no son exclusivos, así que si veo que eso causa problemas intentaré lo del ssh. (¿Problemas, se preguntan? Pues sí, por que usar stunnel requiere que se configure en ambos extremos. Mi experiencia me dice que pedirle a personas externas que lo hagan en sus propias máquinas puede ser complicado. Por otro lado, ssh requeriría que configuren el acceso usando llaves públicas.)
  4. Hecho esto, genero un archivo de usuarios/contraseñas, lo pongo en un lugar accesible al svnserve y refiero la configuración de todos los depósitos a ese mismo. ¡Autenticación centralizada!
  5. Lo cual nos lleva al “todos los depósitos”. En realidad, en vez de colocar un depósito central, coloqué infraestructura para poner fácilmente un depósito por proyecto, accesibles todos con URLs similares. Eso permite controlar más fácilmente el acceso si hay situaciones especiales. Permite también simplificar la creación de respaldos y permite eliminar depósitos que se dejen de usar.
  6. Todos los depósitos se crearán usando fsfs y no db. Tiene un manejo más sencillo de los permisos.
  7. Ahora, Trac. Para esto no hay RPMs, así que hay que instalar a mano. Afortunadamente checkinstall nos permite generar un paquete que enlista lo que fué instalado. Antonces, aunque queden paquetes medio feos, sin dependencias y sin adecuarse muy bien al sistema, por lo menos hay un registro de qué se instaló dónde y como quitarlo.
  8. Usamos SQLite como base de datos. Más fácil de instalar y respaldar que usar PostgreSLQ. Y de cualquier forma, no creo que vayamos a tener en esta infraestructura proyectos con miles de bugs o algo así.
  9. La comunicación de Trac con el mundo está por ahora, con FastCGI. Pero esto tiene el problema de que obliga a darle al usuario de apache permiso de lectura a los depósitos de svn y de escritura a los de trac. Para evitar eso, próximamente(MR), cambiaremos a usar tracd corriendo como un usuario con privilegios reducidos, y lo expondrémos al mundo via mod_proxy.
  10. Trac no lo vamos a colocar tras https. Eso hace difícil colocar todo tras un dominio virtual. Entonces, para por lo menos no andar mandando contraseñas en claro, usamos autenticación ‘Digest’. Las contraseñas para este método se guardan cifradas con MD5, mientras que las de subversion están en texto claro. Entonces declaramos la lista de subversion como la maestra y generamos la de apache a partir de ahí.

Puntos a revisar:

  1. Todavía no acabo de entender los puntos finos de la autorización en svnserve. Y al parecer hay algunos bugs extraños en la implementación. Sería bueno que se pudieran incluir secciones comúnes.
  2. Hace falta diseñar e implementar un mecanismo para los respaldos. Hay que determinar la frecuencia y cuanto tiempo queremos guardarlos.

Noviembre 19, 2005

He claudicado

Archivado en: — rodrigo @ 6:53 pm

A partir de hoy mi máquina de trabajo tiene Gnome como sesión gráfica. Tiene tiempo que ando buscando una buena manera de leer RSS. Liferea me gustó. Tiene buena interfase y revisa periodicamente sin que yo le diga, a diferencia de sage. Pero entonces necesité una forma de que me avisara que hay cosas nuevas que leer. Y lo de que saque ventanas es demasiado intrusivo. Odio que una aplicación me robe el foco mientras trabajo con otra. ¿La solución? El área de iconitos en el panel de Gnome. Y, como me dió flojera averiguar si podía tener el panel sin correr el resto de gnome, le dí apt-get install gnome-desktop-environment y ya.

Noviembre 8, 2005

XSL para mi RSS

Archivado en: — rodrigo @ 8:29 pm

Siguiendo una idea de Mark Pilgrim, he añadido una hoja de estilo XSL al feed RSS del sitio. Si siguen el vínculo al final del menú que dice ‘rss 2.0’ verán una página más o menos decente, en vez del montón de XML que salía antes. El resto de este artículo explica los detalles técnicos.

Antes de explicar la implementación, explico el por que de la idea. Básicamente, se trata de usabilidad. Se supone que RSS debe facilitar a todo el mundo suscribirse a las actualizaciones de un sitio. Pero, ¿Qué pasa cuando un usuario no técnico sigue el vínculo? En su pantalla le sale un montón de XML, lleno de etiquetas raras. ¿Cómo se supone que va a saber que si le da ese vínculo a un lector de RSS se va a suscribir al sitio?

La solución propuesta es esta: Añadimos una hoja de estilo al RSS. Los lectores normales de RSS la ignoran, puesto que la hoja se añade por medio de una “instrucción de procesamiento” XML y las especificaciones de XML dicen que un procesador debe ignorar aquellas instrucciones que no conozca. Así, el uso normal del RSS no se ve afectado de ningún modo.

¿Y cuando ven el RSS en un navegador? La instrucción de procesamiento que usamos indica al navegador que descargue una hoja de estilo y la aplique al documento XML. Usando esa hoja de estilo transformamos el RSS en (X)HTML, que el navegador muestra como de costumbre. El HTML generado permite mostrar un aspecto más amigable al usuario, así como añadir algunas explicaciones respecto al uso del vínculo.

Pongamonos técnicos. El primer paso es añadir en el RSS la instrucción para que el navegador busque la hoja de estilo. Para eso debemos añadir, justo despues de la declaración XML, la siguiente línea:
< ?xml-stylesheet href="xsl.php" type="text/xsl"?>
dónde href debe ser la URL (relativa, si quieren) de la hoja de estilo. Eso es todo lo que hay que hacer en el RSS.

El siguiente paso es hacer la hoja de estilo en sí. Para esta implementación, lo que escribí es un script PHP que genera la hoja de estilo. Eso lo hice para poder incluir en el HTML generado contenido dinámico de WordPress. Por ejemplo la URL de la hoja CSS que se va a aplicar al HTML, así como la barra lateral con los menús. Un pequeño detalle es que el contenido de los resúmenes en el RSS viene códificado como entidades XML. Para resolver esto escribí un poco de JavaScript que corre una vez que se genera el HTML y decodifica las entidades.

¿Que dónde lo ven funcionando? Visiten el vínculo para el RSS de esta página.
Luego usen la función de ver el código fuente de su navegador. La versión actual funciona por lo menos en Mozilla y en Internet Explorer pero no en Opera. El javascript para decodificar entidades no funciona en IE, si alguien sabe como arreglarlo le agradeceré su ayuda.

La hoja de estilo y el javascript están disponibles bajo la GPL.

Julio 26, 2004

Linux Virtual Server

Archivado en: — Rodrigo @ 6:00 pm

Crear un cluster con LVS tiene varios detalles sutiles que hay que tomar en cuenta. Cuando termine este proyecto voy a juntar todas mis notas para publicarlas aquí.

Algo que ya me mordió es que (en LVS-NAT) la red de los servidores debe estar separada de la del cliente/ruteador, por lo menos lógicamente, para evitar que el servidor intente responder directamente al cliente, saltandose al director.

Eso significa que no puedo tener levantada la configuración para esto al mismo tiempo que una para hacer pruebas de rendimiento directas al servidor. Buuuu.

Actualización(24/ago/04): Ya terminé el proyecto. Las notas, a continuación.
________________________________________________________

Este archivo documenta los pasos tomados en la creación del cluster de
prueba para Ciudad Multimedia. Explica también las decisiones de
diseño tomadas y da su justificación.

El cluster se compone de las siguientes máquinas:

_director_

Recibe las peticiones de los clientes y las reparte a los servidores
que las atienden. Esta es la única máquina que necesita el software
de LVS.

_real servers_

Son los servidores que atienden las peticiones del cliente. El
requisito principal para ellos es que deben dar respuestas iguales a
peticiones iguales, puesto que un cliente puede conectar a cualquiera
de ellos en cualquier momento.

Además, el cluster de prueba instalado tiene otra máquina, un servidor
de base de datos.

La mayor parte de la configuración se lleva a cabo en el director.

* Instalación normal de un Debian/sarge: (20/jul/04)

o Usando el CD.

o Particionado genérico.

o Apuntado a un mirror y actualizado.

o Kernel 2.4.22-1 stock de Debian, que cambiará pronto.

* Paquetes modificados respecto a la configuración base

o Añadimos ssh, sudo, vim, less, grub, kernel-package,
kernel-source-2.4.26, fakeroot, libncurses5-dev, ntpdate,
netcat, tcpdump

o Eliminamos nvi, nano, pcmcia, lilo

* Configuración general, que no debería afectar.

o Instalamos grub en la partición de boot e install-mbr en
el sector de arranque del disco.

o Añadimos mi usuario a /etc/sudoers

o Activamos bash_completion

o Añadimos mi usuario al grupo src, para poder desempaquetar
y compilar el kernel con mi id.

o Cambios en la configuración de make-kpkg, para adaptarnos
a grub.

o Añadimos tulip y apm a /etc/modules

* Instalación de lvs.

o Compilamos un kernel 2.4.26, del paquete Debian
kernel-source-2.4.26-2. lvs viene como parte del kernel
oficial desde 2.4.23. Se configura como módulos. El paquete
de ipvsadm de Debian viene compilado para el kernel 2.4 lo
que nos obliga a usar este y no un 2.6, a menos que se esté
dispuesto a recompilar el paquete.

o Instalamos ipvsadm. Se quejó de que no hay soporte en el
kernel, hay que instalar el nuevo kernel y luego correr
dpkg-reconfigure ipvsadm. Una vez instalado el nuevo kernel
todo parece funcionar.

o Añadimos ip_vs a /etc/modules

* Configuración de LVS

o

+ Ponemos un servicio ‘dummy’ en el puerto 60600 que solo
responde con el nombre de la máquina. Creamos un servicio
virtual que balancea la carga de ese servicio.

+ La IP del servicio virtual debe ser un alias. LVS no
funciona si esta es la IP principal.

+ Los ?RealServers no deben tener IP en la red del
ruteador/cliente, por que en tal caso intentan
responder directamente, en ves de a travez del
director.

+ Es importante recordar encender ip_forward y apagar
send_redirects en /proc/sys/net/ipv4/conf/*. Configuro
esto en /etc/network/options y /etc/sysctl.conf

En los real servers no es necesario modificar la configuración del
kernel u otras. Sólo se debe asegurar la propiedad mencionada
anteriormente, de que respondan a peticiones iguales con respuestas
iguales. En particular eso significa que los servidores no deben
escribir nada en sistemas de archivos locales que modifique el
comportamiento de la aplicación.

* Adaptación de la aplicación para poder vivir en un cluster LVS.

Es importante que la aplicación no guarde estado en cada
servidor. La aplicación del club de compras, que usa el
soporte normal de PHP para sesiones hace esto, por lo que es
necesario modificarla. Haremos que las sesiones se guarden en
la base de datos. Notese que la aplicación incluye su propia
copia de PEAR. Los cambios realizados son

* Añadimos el script pear_session.php, que bajamos del
* proyecto pearsession en SourceForge.

* Modificamos /etc/php/apache/php.ini según las indicaciones
* del script:

o session.save_handler -> user

o session.save_path -> DSN de la base, en este caso la
misma de la aplicación.

o session.entropy_file -> /dev/urandom

o session.entropy_length -> 16

* Añadimos la tabla session a la base de datos. Es necesario
* otorgar permisos sobre la tabla al usuario que la aplicación
* usa para conectar. En este caso, y dado que no conozco la
* estructura de permisos de la aplicación, uso un GRANT ALL ON
* session TO pg_infocentro.

* Añadimos en ahqr/template.php, entre las lineas
* include_once(‘Permiso.inc.php’); y session_start(); la linea
* include_once(‘pear_session.php’);.

* Añadimos la linea anterior, justo antes del session_start a
* los siguientes archivos:

ahqr/admin/.depositos_cargado.php
ahqr/admin/hist_seguimiento.php
ahqr/admin/historico_empresa.php
ahqr/admin/prospectos_descarga.php
ahqr/admin/reportes.php
ahqr/centralcompradores/catalogo_proveedor.php
ahqr/centralcompradores/cotizacion_imprimir.php
ahqr/centralcompradores/email_contact_empresa.php
ahqr/centralcompradores/error.php
ahqr/centralcompradores/infobox.php
ahqr/centralcompradores/peticion_respuestasXLS.php
ahqr/centralcompradores/styles/template.php
ahqr/centralproveedores/.servicios_comprar.php
ahqr/centralproveedores/catalogo_descarga.php
ahqr/centralproveedores/cotizacion_imprimir.php
ahqr/centralproveedores/email_contact.php
ahqr/centralproveedores/email_contact_empresa.php
ahqr/centralproveedores/error.php
ahqr/centralproveedores/peticion_CSVcot.php
ahqr/centralproveedores/peticion_CSVpet.php
ahqr/centralproveedores/peticion_XLS.php
ahqr/debug.txt
ahqr/inicio/error.php
ahqr/logout.php
ahqr/pear_session.php
ahqr/print-new.php
ahqr/print.php
ahqr/template.php
ahqr/tools/_oferta_nueva.php

Junio 2, 2004

Emacs

Archivado en: — Rodrigo @ 12:46 pm

Estoy tratando de usar Emacs para actualizar este sitio. Si pueden ver
esto, es que por fin funcion�.

Excepto que este párrafo y el título los puse desde la interfaz web. El API 1.0 de Blogger no dice como ponerles título. Y los acentos no jalan, por alguna razón. Como en la última letra del primer párrafo.

Mayo 14, 2004

Programando mi Palm

Archivado en: — Rodrigo @ 6:13 pm

Por fin tengo instalado el emulador de palm (POSE). Realmente es toda una diferencia programar con él, en vez de mandar el programa a la Palm cada que lo recompilo.

También es mucho más facil crear la interfaz con guikachu y no editando el .rcp directamente. Ojalá hubiera algun soporte para auto alinear las cosas.

Gestionado con WordPress