Objetos Distribuidos en AjTalk

He agregado objetos distributos a mi proyecto AjTalk (una virtual machine interpretada tipo Smalltalk, escrita en C#). Estoy usando .NET Remoting para serializar objetos de un proceso a otra, y tengo proxies a objetos remotos. Como siempre, pueden bajar el código fuente actual de:

http://code.google.com/p/ajtalk/

Primero, puse un nuevo método en objetos:

nil subclass: #Object
!Object methods!
asRemote
    ^@AjTalk.Hosting.RemoteObject new: self
! !

(Estoy usando la notación AjTalk para acceder a tipos y métodos .NET, ver AjTalk: accediendo a objetos y tipos .NET)

La clase RemoteObject es un decorador alrededor de IObject (interface implementada por los objetos de AjTalk), que hereda desde MarshalByRefObject. En .NET, esos objetos no son serializados: una referencia es enviada al otro proceso. Cada llamada a ese proxy, envía la invocación al objeto original, que todavía reside en su proceso, donde fue creado:

    public class RemoteObject : MarshalByRefObject, IObject
    {
        private IObject obj;
        private Machine machine;
        public RemoteObject(IObject obj)
        {
            this.obj = obj;
            this.machine = Machine.Current;
        }
    // ...    
    }


Hay un host, que puede recibir llamadas desde otros procesos. Podemos lanzarlo en el proceso A:



Object subclass: #Host nativeType: @AjTalk.Hosting.RemotingHostServer
!



host := Host new: @AjTalk.Machine !!current with: 20000 with: ‘Server2000′
!



Desde otro proceso, podemos conectarnos a ese host. Ejecutamos en el proceso B:



Object subclass: #RemoteHost nativeType: @AjTalk.Hosting.RemotingHostClient
!RemoteHost methods!
export: aClass
    self execute: (aClass !!toOutputString)
! !



remote := RemoteHost new: ‘localhost’ with: 20000 with: ‘Server2000′
!



Ahora, remote es un objeto en el proceso B que puede ser usado para comunicarse con el proceso remoto A.



El método export serializa en un string la definición de una clase. De esta manera, si tenemos una nueva clase en el proceso B, podemos enviar su definición al proceso A remoto. Una vez hecho esto, podemos crear objetos en el host remoto, que sean de esa clase. Veamos un ejemplo. Definimos una nueva clase en el proceso B:



Object subclass: #Rectangle instanceVariableNames: ‘width height’
!Rectangle methods!
width
    ^width
!
height
    ^height
!
width: newWidth
    width := newWidth
!
height: newHeight
    height := newHeight
! !



Entonces, podemos exportar la clase al proceso A:



remote export: Rectangle
!



Ahora, creamos un nuevo Rectangle, en el proceso A, ejecutando el siguiente código desde el proceso B:



remote execute: ‘rect := Rectangle new. rect width: 100. rect height: 20′
!



El método execute envía un string, que es ejecutado en la máquina remota. Podemos recibir objetos serializados. De nuevo, ejecutando en el proceso B:



rect := remote evaluate: ‘rect’.
rect width: 200.
rect height: 30
!



El método evaluate envía un string al proceso A, lo evalúa, y el resultado (en este caso, el objeto Rectangle) es serializado y reificado (en una copia) en el proceso B. Entonces, los cambios en su tamaño son evaluados sobre la copia en el proceso B. Pero tenemos otro camino: recuperar un proxy al objeto rect, que sigue residiendo en el proceso A:



rect2 := remote evaluate: ‘rect asRemote’.
rect2 width: 300.
rect2 height: 40
!



asRemote es la clave: en vez de retornar un objeto serializado, retorna una referencia al objeto que sigue residiendo en el proceso A. Los cambios en el tamaño de rect2 (en realidad, la invocación de métodos width: y height:) son enviados y ejecutados en el ambiente del objeto remoto.



En resumen, con estas clases y métodos, podemos:



- Crear un host, y conectarnos a él desde otro proceso/máquina.
- Enviar un string para ser ejecutado en el host remoto.
- Exportar una definición de clase local al host remoto
- Evaluar una expresión en el host remoto y recuperarla como resultado serializado
- Evaluar una expresión en el host remoto y recuperar su resultado como objeto remoto accesible via un proxy



Debería escribir un caso de uso con esta funcionalidad.



Nos leemos!



Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

This entry was posted in 11722, 12677, 1389, 3462, 8870. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>