Páginas

domingo, 17 de octubre de 2010

[0.2.3] Checksums de Octubre

Casi 20 dias despues... nueva release :-D

Este mes ha sido de aúpa, entre el trabajo y la demostración de este miércoles (que FSM nos coja confesaos...), los estudios (de los cuales todavía no tengo todos los apuntes), los compromisos sociales (aunque algunos han merecido la pena... aunque podrian haberlo merecido mas :-P ) y que los [auto-censurado] checksums se me habian atragantado no he parado quieto, pero bueno, tal y como dijo Mao "una revolución a la vez" al final esta saliendo todo adelante :-D

En primer lugar estaba el tema de los plugins. Los checksums no aportaban simplemente funcionalidad no existente como pasaba con los symlinks sino que trabajaban directamente con los datos, por lo que ya no se podia usar un simple mapeo como antes sino que habia que empezar a desarrollar el sistema de plugins, y a ser posible de una forma un poco mas consistente que como lo habia hecho antes. Por suerte fue facil y ademas el codigo ha quedado bastante limpio, pero tengo la sospecha de que en el futuro voy a tener que hacerle profundos cambios para darle mas potencia y versatilidad (conflictos entre modulos es lo primero que se me viene a la cabeza, luego vereis porque).

Pero el principal problema que tenia con los checksums (y que no identifique hasta hace poco) no estaba relaccionado directamente con ellos, sino que mas bien era un pequeño fallo de diseño (mas bien de falta de planificación) que tuve cuando desarrolle el codigo de escritura y modificación de los archivos (el cual en su momento ya me dio bastante guerra hasta el punto de tener que modificar el diseño de la base de datos tres veces...). Este fallo consistia por un lado que accedia desde distintos puntos del codigo directamente a las funciones DB.Split_Chunks y a LL.Write, con lo que a la hora de generar los eventos para los plugins tendria que generarlos desde multitud de sitios distintos. Sin embargo su funcionalidad era muy parecida y de hecho el codigo era casi el mismo en muchos sitios (como ya indique en mi anterior post entre DB.truncate y DB.Split_Chunks), asi que finalmente he conseguido encarrilar a todo el ganado a través de una nueva función (File.__Split_Chunks) que se encarga efectivamente de llamar a DB.Split_Chunks y de generar el evento correspondiente en caso de que haya producido alguna división.

Al menos todo este follón me ha servido para varias cosas: en primer lugar, una revisión a fondo del código de los archivos, de la base de datos y del acceso a bajo nivel (este al fin es una clase y es instanciada en FileSystem, con lo que ya no abrirá y cerrara el dispositivo en cada llamada. La ventaja es que el acceso es mucho mas rápido, el inconveniente que usara los buffers de archivo del sistema y no escribirá los datos directamente a disco y todavía no estoy usando las transacciones, que es justo una de las razones por las que decidí usar un motor de bases de datos, para aprovechar las que ya tiene... :-/ ). Esta revisión me ha permitido aplicarle muchas mejoras menores y reutilizar mucho código duplicado, con lo que ahora el tamaño y las posibilidades de error son menores, pero sobretodo he quitado "inteligencia" a la base de datos (ahora solo ejecuta sentencias SQL, apenas toma decisiones por si misma aunque lo cierto es que se podría "estupidizar" aun mas) y he eliminado la notificación de eventos desde la base de datos y el acceso a bajo nivel, con lo que por un lado permite mayor control de quien envía realmente los eventos (todo se esta perfilando a que la comunicación entre los plugins va a ser realmente sencilla... :-) ) y también permite mayor portabilidad en el futuro a otros motores de bases de datos o sistemas de almacenamiento o incluso a sacar el código SQL a archivos externos y que los parsee en el arranque en lugar de estar directamente dentro del código Python (esta idea la tengo desde hace tiempo, pero aunque permitiría un mejor mantenimiento al poder tenerlo aislado y que sea mas fácil procesarlo con un editor de texto con coloreado de sintaxis -me encantan :-D - todavía no me he planteado en serio el realizarlo porque consumiría mas memoria y seria un poco mas lento... :-/ )

Ademas todos estos cambios me han hecho replantearme en serio la necesidad de hacer modulos de prueba, por lo que voy a empezar a usar PyUnit, que es el estandar en Python. Nunca he desarrollado ninguno y ademas siempre he sido reaccio a hacerlos (si funciona, ¿para que comprobarlo?) pero un proyecto tan complejo como este lo necesita. Por suerte hace tiempo cuando estaba buscando los codigos de error de los sistemas de archivos tratando de averiguar porque fallaba me encontre con esta pagina que contiene la definición de todas las funciones UNIX con sus parametros, errores y limitaciones, con lo que me vendra de perlas para desarrollar los modulos de test (espero que no me pidan comprar una licencia de POSIX o que Linux Tordvalds me preste la suya... :-D ). Tambien aprovechare a documentar todo el codigo con vistas a liberar publicamente la version 0.3 a ver si se apunta alguien a echarme una mano, y tambien aprovechare a cambiar la filosofia de la API, ya que hasta hace poco (bendito trabajo que tambien lo estoy haciendo en Python y me permite aprender de forma intensiva... :-D ) no entendia correctamente uno de los aspectos mas extraños del lenguaje: en Python no hay metodos o atributos privados, todo es publico. Sin embargo por convenio los atributos y metodos que empiezan con un guión bajo (_) no se muestran en el completado de sintaxis, aunque se sigue podiendo acceder normalmente a ellos. Aparte tambien estan los que empiezan por dos guiones bajos (__) que aqui si el lenguaje los considera como atributos especiales y su firma es distinta, haciendo por tanto que sea mucho mas dificil acceder a ellos. Hasta ahora solo usaba este ultimo metodo para emular los atributos privados, pero realmente era un engorro cuando me encontraba con que queria acceder a algo que habia ocultado demasiado hasta que descubri en que se basaba esta diferencia: la filosofia en Python es la confianza en el programador, por lo tanto no tiene sentido pensar en atributos publicos, protegidos y privados, sino en mostrar (normal), no mostrar (_) y ocultar (__), teniendo en cuenta por ambas partes que si quieres acceder a algun sitio siempre vas a poder pero que necesitas tener buenas razones para ello (por ejemplo, en los debuggers). Despues de tanto tiempo con C++ cuesta acostumbrarse, pero la posibilidad de ver el codigo de los demas para ver que es lo que esta haciendo realmente es de gran ayuda... :-D

Y bueno, ese es el toston de hoy. Espero que cuando este aprendiendo a usar las unidades de test y documentando el codigo no me encuentre con demasiados problemas como hasta ahora, porque entonces esto va a parecer la biblia... :-P Por el momento para mi desgracia acabo de descubrir que ZFS si tiene bloques de tamaño variable (lo que yo creia que era una feature exclusivamente mia... ¬¬) pero por otro lado tambien he descubierto que su algoritmo de compresion tiene una implementación en Python, asi que no hay mal que por bien no venga... :-D
Published with Blogger-droid v1.6.2