Páginas

Mostrando entradas con la etiqueta plugins. Mostrar todas las entradas
Mostrando entradas con la etiqueta plugins. Mostrar todas las entradas

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

miércoles, 29 de septiembre de 2010

[0.2.2] El log de Schindler

Hoy debido a la huelga he decidido quedarme en casa, no por apoyarla y no ir a trabajar, sino que ayer me hice una copia de seguridad y he trabajado desde aquí debido al miedo que tenia a los piquetes (no estoy de acuerdo con las reformas, pero tampoco con los sindicatos como la mayoría de la población).

Al final ha sido mas ruido que otra cosa y podría haber ido sin problemas, pero el caso es que como he terminado pronto me he puesto a darle un empujón al sistema de archivos y bueno... hemos alcanzado otro checkpoint :-D Ahora modulo de log esta operativo, he limpiado el modulo de symlinks (ya no hay funciones mapeadas, todas son lanzadas por eventos gracias a louie :-) ) y empieza a discernirse un borrador de como implementar el sistema de plugins. Esto ultimo es debido a que en el modulo de log no tenia manera de tener una referencia para acceder a la base de datos, ya que antes accedía a través del objeto del sistema de archivos (como se puede ver en symlinks, aunque lo voy a cambiar en breve para unificarlo) y ahora al tener el objeto otra estructura perdía toda referencia a ella, y guardarlo en una variable global me decía el bicho que nanai. ¿Como hacerlo? Pues construyendo una clase. Era reacio a hacerlo a pesar de mi gusto por la orientación a objetos porque entonces ya no bastaría con cargar el modulo para tenerlo habilitado, sino que ademas tendría que meterme dentro, leer la clase y crear un objeto, y eso ya es mucho engorro. Por el momento lo he solucionado con la chapuza de crear una instancia del objeto al final del modulo (niños, no miréis :-P ) pero la ventaja de usar orientación a objetos es que mi idea de en un futuro implementar un sistema de dependencias entre plugins (inspirado en APT para mas señas... ;-) ) va a ser mucho mas sencillo :-)

En fin, en cualquier caso el modulo de logs ya esta listo, aunque tendré que diseñar algún método para agrupar los eventos y así poder discernir cuales son validos para loggear y cuales no, porque cuando ya estaba operativo con solo hacer un ls me ha salido todo esto...


[piranna@Tontodelculo:~/Proyectos/FUSE/PirannaFS/test]
> sqlite3 db.sqlite
SQLite version 3.6.22
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> select * from log;
|__init__|DB|2010-09-29 18:34:31||{'self': , 'db_name': '../test/db.sqlite'}||
|readlink|FileSystem|2010-09-29 18:34:32||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:32||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:32||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:33||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:33||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:33||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:33||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:33||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:33||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:34||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:34||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:34||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:34||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:34||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:34||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:34||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:35||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:35||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:35||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:35||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:35||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:35||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:35||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:36||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:36||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:36||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:36||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:36||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:36||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:36||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:37||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:37||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:37||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:37||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:37||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:37||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:37||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:38||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:38||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:38||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:38||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:38||{'path': '/nano_link.txt', 'self': }||
|readlink|FileSystem|2010-09-29 18:34:39||{'path': '/nano_link.txt', 'self': }||
sqlite>


Si, efectivamente, FUSE hace muchas llamadas al sistema... ;-)


P.D.: entrada libre de faltas de "hortográfia" ;-) dedicada a Pau y su muy buen consejo :-)

sábado, 25 de septiembre de 2010

[0.2.1] Symlinks, Plugins y cintas de video

Aunque he tardado algun tiempo en actualizar cosas debido a lo saturada que tengo la agenda este año entre el trabajo y la carrera (aunque segun he visto en los blogs de los demas no soy el unico, bien por nosotros :-) ) al fin ha llegado el viernes tarde y para desconectar de una semana demasiado corta en tiempo (se me ha pasado volando sin darme cuenta, con lo que me jode...) y demasiado larga en estress en la que incluso he perdido mi maravilloso Android (snif...) me he puesto a darle un pequeño empujon al proyecto y a falta de uno hay dos: primero, ya tenemos links simbolicos, y segundo, ya tenemos una plataforma seria de plugins, aunque por ironico que parezca no por culpa del codigo para generar los links simbolicos, sino por culpa de la creacion de su tabla.

En primer lugar, los links simbolicos tienen sus propias funciones dentro de FUSE (symlink para crearlos y readlink para parsearlos), los cuales hasta ahora no las habia implementado porque no eran necesarias para el nucleo del sistema de archivos, asi que como primera aproximacion al sistema de plugins decidi mapearlas directamente dentro de la clase, al igual que he hecho con sus equivalentes en la base de datos.

Sin embargo para la creacion de la tabla no podia mapear ninguna funcion sino que tenia que ejecutarse cuando terminara de hacerse la base de datos entera, asi que buscando algun ejemplo de como hacer un sistema de notificacion de eventos en python (podia hacermelo yo y los ejemplos que encontre eran muy parecidos, pero queria ver si ya habia algo bien hecho y probado que poder reutilizar. Al menos esa es una de las ventajas del software libre, que si ya hay algo bien hecho no hay porque duplicar esfuerzos, ¿no?) y entre todo lo que encontre el que mas se parecia a lo que necesitaba para el sistema de plugins fue este codigo. Sin embargo aparte de que no me gustaba mucho como tenia implementado el sistema de carga de plugins (¿un archivo de configuracion? Por favor... con lo comodo y practico que es tener un directorio desde donde cargarlos al igual que se hacia con las extensiones del sistema del MacOS Classic...) tambien hacia referencia a PyDispatcher, el cual tambien hacia referencia a Louie. ¿Cual escoger? Al final como muchas otras veces en que tengo alternativas de codigo y me da igual uno que otro, deje que Ubuntu eligiera por mi para ver cual era el metodo mas estandar, y como Louie era el unico que tenia paquetes dentro de los repositorios oficiales, pues me decante por el :-)

Asi que aunque ha sido por algo completamente accidental, ahora tenemos un sistema de notificacion de eventos bastante avanzado. Puede que sea un problema con vistas a una futura implementacion como sistema de ficheros nativo (mas librerias externas, mas problemas de integracion), pero como apenas todavia estamos en las primeras fases de desarrollo todavia hay tiempo de modificarlo mas adelante si hace falta. De momento en cualquier caso hara falta una plataforma de plugins mas solida que la que tengo actualmente de mapear las funciones directamente, asi que a lo mejor con suerte incluso consigo matar dos pajaros de un tiro y consigo desarrollar un sistema de plugins lo suficientemente bueno como para que me lo incluyan en la libreria estandar de python (y eso si que seria un puntazo... ;-) ).

Proximo paso, aprender un poco mas como funciona Louie y desarrollar el plugin de log :-D