Los orígenes…borrando barreras del software privativo de manera visible, resumiéndolo en preguntas:
¿Cómo empezó el movimiento?, ¿dónde se creó la confusión?, ¿qué es lo que nos estorba a la hora de pensar en el software libre?, ¿qué es lo bueno y lo justo para nosotros?
Una importante charla acerca de la filosofía ética del sofware libre, los motivos para aprender utilizando con programas libres, o para divertirse jejeje
Introducción
Como ya hemos dicho, unos de los lenguajes de entrada es Slice, donde se pueden especificar las interfaces de los objetos que van a entrar en juego en nuestro sistema distribuido. Sin embargo, el programador debe poder especificar un escenario de objetos distribuidos y, de esta forma, poder programar un dispositivo. La idea es que el programador especifique qué va a ir incluido en el dispositivo y qué es lo que tiene alrededor (objetos con los que puede interactuar).
Para ello fue concebido IPK, un lenguaje para describir escenarios distribuido constituido por objetos. En él se deben poder especificar sus relaciones y los mensajes que se mandan unos a otros.
Necesidades del middleware
IPK debe proporcionar una semántica lo suficientemente flexible como para representar el escenario sin casarse con ningún middleware en particular. Sin embargo, existen entidades comunes a prácticamente todos los middlewares orientados a objetos:
Muy importante es que NO puede estar acoplado a ninguna tecnología en particular. Las anteriores necesidades son básicas en cualquier sistema orientado a objetos, por lo que pueden estar y deben estar representadas en IPK.
EBNF de IPK
Una buena forma de especificar la estructura de un lenguaje es mediante la notación EBNF (Extended Backus–Naur Form), muy parecida (sintácticamente) a la forma en que se especifican las gramáticas libres de contexto en herramientas como Bison y CUPS. El EBNF diseñado es el siguiente:
PROG ::= DECLS BLOCKS
| DECLS
DECLS ::= DECL {DECL}
DECL ::= USE | ADAPTER
USE ::= uses lit ;
ADAP ::= ADAPTYPE id '(' lit ')'
| ADAPTYPE id '(' lit ')' '{' ADAPDEF '}'
ADAPTYPE ::= local | remote
ADAPDEF ::= OBJDECL ; {OBJDECL ;}
OBJDELC ::= INTER id '(' lit ')'
| INTER id '(' lit ')' '{' OBJDEF '}'
INTER ::= id . id {. id}
OBJDEF ::= KEYVAL ; {KEYVAL ;}
KEYVAL ::= mode = MODE
| id = lit
| id = id
MODE ::= twoway | oneway | datagram
BLOCKS ::= [LABEL] BLOCK {[LABEL] BLOCK}
LABEL ::= id :
BLOCK ::= WHEN | BOOT | EVENT | REPEAT
WHEN ::= when id . id do '{' [INVOCATIONS] '}'
BOOT ::= boot '{' [INVOCATIONS] '}'
EVENT ::= event id do '{' [INVOCATIONS] '}'
REPEAT ::= repeat '(' int ')' '{' [INVOCATIONS] '}'
INVOCATIONS ::= INVOCATION ; {INVOCATION ;}
INVOCATION ::= id . id '(' [PARAMS] ')'
| (start | stop) id
PARAMS ::= PARAM {, PARAM}
PARAM ::= true | false
| id | id . id
| lit | int | INVOCATION
Los elementos no terminales de la gramática están expresados en mayúscula y los terminales en minúscula. No tiene mucho sentido hacer una descripción detallada de lo anterior. Simplemente se hará una breve descripción de cada una de las partes del lenguaje.
Estructura general
IPK tiene 3 partes fundamentales:
Los métodos que se pueden utilizar en las invocaciones de los bloques son los definidos en Slice (o en el lenguaje de especificación de interfaces que hayamos utilizado).
En la siguiente entrega veremos ejemplos de archivos IPK, viendo su utilidad en distintos ámbitos de aplicación.
Para sacar el máximo beneficio posible de una red social de Internet orientada a los estudios hacía falta mucho proceso de digitalización, por suerte, Google se encargará de digitalizar los libros que pueda ,esperemos que no se caiga cuando dependamos de ello jaja
No es el mismo caso que con los exámenes, que o bien los profesores los ponen a disposición, o tenemos que vernos inmersos en la búsqueda de estos o bien por la fotocopiadora de la Universidad, en los foros de nuestra Facultad o bien en plataformas como el rincón del vago o la plataforma de exámenes de algún alumno desesperado por aprobar jaja.
Las acciones de los usuarios de las webs de asignaturas empezaron a cobrar una importancia cada vez mayor, al participar de forma masiva, en la organización de la información, la producción del conocimiento, esta participación y la digitalización de los datos se reforzaban mutuamente, lo que dió a una especie de florecimiento que nos permite plantearnos el paso de la sobrecarga de información a la comprensión y nos abre de nuevo universos imprevisibles como PIE.
El proyecto es tan simple que funciona justamente por eso.
Recientemente se ha actualizado la versión de Bison en Debian; se ha pasado de la versión 2.3 a la 2.4. Bison es un generador de analizadores LARL(1) para gramáticas libres de contexto. En IcePick se utiliza para parsear los lenguajes de entrada (tanto IPK como SIS).
El problema es que, debido a cambios importantes entre ambas versiones, IcePick dejó de compilar con la nueva versión. Gracias al soporte proporcionado en la lista de ayuda de Bison por los propios desarrolladores he podido solventar el problema. Y, la verdad, es que era bastante simple.
Básicamente, en Bison 2.3 si necesitabas incluir sentencias #include en el analizador generado bastaba con encerrarlo en un bloque parecido a:
%{
#include
#incluade
}%
En Bison 2.4 se debe hilar un poco más fino y especificarlo en distintas secciones. Por ejemplo, %code top incluye el código al principio del programa, %code require depende del lugar donde se declare irá a un sitio u otro.
Para más información se puede ver en el manual de Bison 2.4 incluido en el paquete de tu versión GNU, en la sección “Prologue Alternatives”, una descripción detallada de esta nueva “feature”.
Desde hace tiempo , se ven movimientos , oscuros y un rumor sin nombre crece en el oeste,¿puede Pentaho dejar de dar soporte a su versión libre?,pues parece que si ,por diversos motivos.
Esto puede ser la muerte del producto , pentaho había hecho movimientos para hacerse fuerte y ser el referente en el BI Opensource[] comprando kettle y mondrian y a sus desarolladores .Con esto da un cambio radical a el planteamiento .
Lo que esta claro es que si piensan en dejar algo a la comindad se apollan en hilelo fino.
Introducción
Antes de poner un ejemplo básico de uso del middleware Ice, debemos ver unos cuantos conceptos básicos que, al menos, nos servirán como terminología.
En Ice una aplicación es “servidor” si exporta objetos para que otras aplicaciones (las clientes) accedan a ellos. Por tanto, una aplicación puede servidor y cliente a la vez (exporta objetos y además accede a objetos remotos).
Básicamente, para exportar objetos en Ice necesitamos una estructura llamada adaptador de objetos. El servidor utilizará dicha estructura para añadir objetos y hacerlos accesibles al resto del mundo. Un adaptador escucha una o varias interfaces y en los puertos correspondientes. Esto se conoce como el “endpoint” del adaptador. Por ejemplo:
tcp -h 123.123.123.123 -p 8000
Sería un endpoint que escucha en la interfaz con la dirección 123.123.123.123 y en el puerto 8000. Por tanto, el servidor puede añadir objetos a ese adaptador y estarán accesibles a través del endpoint.
Para añadir un objeto a un adaptador, al objeto hay que ponerle una identidad (ya que puede haber varios objetos en el mismo adaptador. Una vez añadido, ya tendríamos un proxy completo al objeto, es decir, su identidad + endpoint del adaptador.
El servidor
Utilizando la definición de interfaces, vamos a escribir el código fuente del servidor en Python. Suponiendo que la implementación de la clase la tenemos en el archivo “miobjeto.py” y que la definición de interfaz se encuentra en “Ejemplo.ice”, el código sería el siguiente:
import Ice
Ice.loadSlice("Ejemplo.ice")
import Ejemplo
from miobjeto import MiObjeto
import sys
class Servidor(Ice.Application):
def run(self, argv):
ic = self.communicator()
adap = ic.createObjectAdapterWithEndpoints("Adatador",
"tcp -h localhost -p 9090")
adap.activate()
prx = adap.add(MiObjeto(), ic.stringToIdentity("Saludador"))
print "Proxy al objeto:", prx
ic.waitForShutdown()
app = Servidor()
sys.exit(app.main(sys.argv))
El servidor, como vemos, hereda de una clase llamada “Ice.Application” que nos facilita las cosas a la hora de crear aplicaciones Ice. Para arrancar una aplicación sólo tenemos que implementar el método run() al que se le pasan los argumentos de entrada. Dentro de run vemos que existe un método llamado “communicator()” que nos devuelve el núcleo de comunicaciones de Ice. No entraremos más en detalle, simplemente decir que es el encargado de realizar todas las operaciones de entrada/salida en la red.
A continuación creamos un adaptador de objetos con un endpoint determinado (fijado por nosotros). Obviamente, se puede parametrizar y crearse de otras muchas formas, pero para este ejemplo es suficientemente visual. Activamos el adaptador y le añadimos una instancia de un objeto de tipo MiObjeto con la identidad “Saludador”. La identidad se maneja realmente con un objeto, por lo que el comunicador nos proporciona un constructor que pasa de string a un objeto Ice.Identity.
Imprimimos el proxy y esperamos a que el comunicador finalice. Este hecho se puede forzar pulsando Control-c. La salida del programa sería:
Proxy al objeto: Saludador -t:tcp -h localhost -p 9090
El cliente
Ya tenemos el servidor ejecutándose y esperando invocaciones de objetos remotos a través de la interfaz “localhost”. Hagamos un cliente sencillo que mande una cadena al servidor para que la imprima a través del método “saludar”:
import Ice
Ice.loadSlice("Ejemplo.ice")
import Ejemplo
import sys
class Cliente(Ice.Application):
def run(self, argv):
ic = self.communicator()
obj = ic.stringToProxy(argv[1])
print obj.ice_id()
print obj.ice_ids()
prx = Ejemplo.SaludadorPrx.checkedCast(obj)
prx.saluda("Cliente")
app = Cliente()
sys.exit(app.main(sys.argv))
El cliente, como vemos, es mucho más sencillo. Utilizamos el núcleo de comunicaciones para, a partir de un parámetro del programa, constuir un proxy a un objeto. No sabemos aún de qué tipo es, simplemente es un objeto remoto (un objeto Ice.Object). A este objeto le podemos realizar consultas del tipo ice_ids e ice_id, que nos devuelven las interfaces que implementa el objeto remoto.
Como realmente queremos un objeto de tipo “Saludador” tenemos que hacer un casting desde un proxy Ice.Object a un proxy Ejemplo.Saludador. Para ello se utiliza el método checkedCast() de la clase Ejemplo.SaludadorPrx que, al parsear el Slice, se ha creado para tal fin. Una vez realizado, ya tenemos el objeto remoto “como si estuviera en nuestra propia máquina” y le podemos invocar los métodos que implementa.
Ejecución de la prueba
Lanzamos el servidor:
$ python server.py
Proxy al objeto: Saludador -t:tcp -h localhost -p 9090
Copiamos el proxy “Saludador -t:tcp -h localhost -p 9090″ y se lo pasamos al cliente:
$ python cliente.py "Saludador -t:tcp -h localhost -p 9090"
::Ejemplo::Saludador
['::Ejemplo::Saludador', '::Ice::Object']
Como vemos ha ejecutado los métodos generícos y nos devuelve la interfaz y la lista de interfaces que implementa el objeto remoto. Obviamente, se puede realizar esta tarea mediante ficheros de configuración pero para ilustrar el funcionamiento es más que suficiente con este ejemplo.
En el servidor se produce la siguiente salida, tras la ejecución del cliente:
Hola, Cliente
En la próxima entrega veremos el diseño del lenguaje de entrada IPK, que especifica un escenario distribuido.
A pesar de que consideramos que esta fase ya la hemos superado veo de interés plantear aquí los problemas e inquietudes que nos fueron surgiendo a lo largo del desarrollo de Ideldes.
Para lograr encarrilar el proyecto decidimos realizar una serie de reuniones (no digitales) en las cuales planteamos diversos puntos de vista e intercambiamos opiniones, la verdad es que fueron de mucha utilidad, sobre todo para tener los objetivos y métodos más claros. Estas reuniones no fueron únicamente realizadas entre los miembros del proyecto sino que contamos con la ayuda y el apoyo de una Intérprete profesional de la Lengua de Signos, Tamara Corral para solventar aquellas dudas más complejas sobre el correcto uso e interpretación de la Lengua de Signos.
De momento llevamos 2 reuniones hechas y vamos a exponer aquí los resultados obtenidos de su realización:
Primera reunión: (Con Podcast)
Principales problemas:
Segunda reunión: (Sin Podcast)
PSD: Agradecer tanto a Tamara por su apoyo y profesionalidad como a Javier Azcuna por su aporte musical al podcast.
Enlaces | Tamara Corral | Javier Azcuna
Feliz año! La última entrada decía que el trabajo se demuestra andando, pero lo cierto es que si bien nosotros hemos andado mucho en meshias, ha sido en la sombra porque no hemos publicado nada en el blog. Sólo un post! Está claro que a estas alturas ya lo único que podemos hacer es.. documentar mediante el weblog. Y eso intentaré hacer.
¿Qué es Meshias?
Meshias por ahora pretende ser una implementación del RFC experimental 3561, que se refiere al protocolo AODV. AODV es un protocolo de red que permite implementar una red mesh, que es básicamente una red wifi descentralizada que no necesita de puntos de acceso, y cuyo radio de cobertura de la red no es el del punto de acceso/los puntos de acceso de la red como en una red wifi normal (porque como he dicho, no existen puntos de acceso), sino que el radio de cobertura de la red es la unión del radio de todos los nodos de la red.
¿Cómo funciona AODV?
Hablaré muchas veces de AODV y de Meshias indistintamente, pero que quede claro que AODV es el protocolo, Meshias una implementación de éste. Bien. AODV trabaja sobre una red wifi en modo Ad-Hoc. AODV es un protocolo de enrutado, y entra en acción cuando se va a enviar un paquete a una dirección IP hacia la cual no tenemos una ruta conocida. Si tenemos 3 equipos A-B-C y cada equipo solo tiene enlace con los que tiene a su lado, en una red Ad-Hoc normal A nunca podría enviar paquetes a C porque no tiene enlace con él. Con AODV, todos los nodos de la red pasan a ser enrutadores en caso necesario. Así, si A quiere enviar un paquete a C, B haría de paso intermedio, recibiría los paquetes de A y los enviaría a C.
El problema radica en encontrar el camino de A a C, porque puede haber cualquier número de nodos intermedios entre los dos equipos: A-B1-B2-B3…BN-C. AODV se encarga de calcular la ruta de A a C cuando se detecta un paquete dirigido a un equipo (C) cuya ruta es desconocida. Una vez Meshias encuentra la ruta, añade a la tabla de rutas del kernel (puedes consultarla con el comando route -n) y ya está, todo funciona sólo sin necesidad de Meshias, Linux lo hace todo sólito. Meshias deja que se envíe el paquete que había capturado dirigido a C, y el kernel lo enruta y todo funciona de forma transparente.
Meshias volverá a capturar sucesivos paquetes dirigidos a C (y en general captura paquetes dirigidos a cualquier equipo de la red mesh), pero comprobará que ya existe una ruta a C en la tabla de rutas del kernel, y “aceptará” etos paquetes, los dejará pasar de largo para que el kernel de Linux se encargue de enrutarlos.
Encontrando la ruta
Bien, y ahora viene la gran pregunta ¿cómo demonios encuentro la ruta del arroz? Ahí está el quit de la cuestión. La idea es enviar una petición de ruta por broadcast para que todos los equipos que estén dentro de mi rango de cobertura la reciban y la procesen. De esa manera, si desde A queremos encontrar la ruta a C, B recibiría una petición broadcast de A preguntando “¿donde está C?”. B en un principio no sabría donde está C, así que haría exactamente lo mismo. Pero antes se apunta que tiene enlace directo con la ip de A en su tabla de rutas, aprovechando que le ha llegado tráfico de A.
Despues de eso, B renviaría la petición broadcast que le llega de A. C recibiría una petición de ruta por broadcast enviada por B en nombre de A diciendo “¿donde está C?”, y como Ć lo sabe (es él!), se apunta que tiene una ruta hacia A, que es exactamente la ruta inversa que ha seguido la petición broadcast. Luego de eso, C envia una respuesta a la petición de ruta: una respuesta de ruta. Se la envía directamente con destino A. Al enviar ese paquete, como ya tenemos la ruta hacia A, el paquete se envía. B lo procesa, y se guarda la ruta hacia C igual que hacemos cada vez que recibimos un paquete AODV. Finalmente esa misma respuesta de ruta llega a A, y se apunta la ruta hacia C en la tabla de rutas. Por fin, despues de eso, Meshias acepta el paquete inicial que iba dirigido a C, y el kernel lo enruta adecuadamente. B recibe ese mismo paquete, y como también conoce una ruta hacia C, hace de router reenviando el paquete, que finalmente llega a C.
Este es, a muy groso modo por supuesto el funcionamiento de AODV.
State of the art
Actualmente tenemos creada la infraestructura y enviamos y procesamos peticiones de rutas, falta poder procesar respuesta de rutas para que AODV funcione mínimamente. El desarrollo de meshias estuvo parado unos meses por navidades y Enero pero luego, pese a no haber estado publicando en el blog, hemos estado programando, que es lo que realmente nos gusta. El código no lo hemos subido aun sin embargo a la forja de RedIRIS, porque hemos tenido problemas con ella (mi usuario no funciona!). Mientras tanto hemos estado usando Launchpad con bazaar que funcionan muy bien. Podéis descargaros el código de meshias con el siguiente comando:
bzr branch lp:meshias
Para compilarlo, las instrucciones están (en inglés, como todo el código de Meshias) en el fichero COMPILE. Comprobaréis que compila. Se puede ejecutar, pero lo cierto es que actualmente no hemos creado ningún fichero con instrucciones de cómo usar meshias porque aun no es usable. Pronto (esta semana o la siguiente!) lo será, y subiremos instrucciones para poder probarlo en casa. Be tunned!
Buenas,
como ya habéis visto se nos ha unido Juanjo al blog, esto va viento en popa a toda vela ¿encendida? pues claro!.
Ya he finalizado el control de colisiones. Para los objetos que no se mueven por si solos como edificios, comida, obstáculos… se marcan las casillas del mapa para que sean casillas no válidas a la hora de generar el camino. Para los demás muñecos que se pueden mover en cualquier momento y en cualquier dirección en cada paso que da nuestro personaje se comprueba que no haya ninguna colisión y si es posible da el paso, sino se queda parado.
Lo siguiente es hacer que los personajes puedan dejar objetos por el terreno.
… and I feeling good… xDD