Persistencia en Zero

Persistence in the Zero virtual machine
Zero (el avión)

Índice(index)

  1. Soporte de persistencia en Zero (persistence support in Zero)
  2. Cómo funciona (how it works)
  3. Un ejemplo sencillo (a simple example)
  4. Interioridades (internals)


Soporte de persistencia transparente en Zero

(Support of transparent persistence in Zero)

Persistencia es la capacidad de un sistema de salvaguardar objetos de manera que puedan ser recuperados posteriormente, asi que los objetos pueden sobrevivir al proceso que los creó. En el caso de Zero, este soporte de persistencia es transparente, de manera que no es necesario utilizar ningún método o clase especial para guardar o acceder a los objetos en el almacenamiento persistente.
Persistence is the capability of a system of saving objects in a way that they can be restored later, so objects can outlive the process that created them. Persistence support in Zero is managed transparently, so it is not necessary to use any special method or special class in order to save or restore objects in the persistent store.

Tanto es así que los lenguajes de alto nivel diseñados para la máquina virtual Zero no tienen noción alguna de que estén tratando en algún momento con objetos persistentes o no persistentes. No existe ninguna construcción especial, ni un tipo especial de referencia, ni siquiera un objeto especial que represente el almacenamiento persistente.
Moreover, the programming languages designed for the Zero virtual machine don't have any notion about persistence, or about when they are dealing with persistent or not persistent objects. There isn't an special constructions, nor a special

El sistema identifica aquellos objetos que deben ser hechos persistentes por alcanzabilidad. Es decir, si un objeto es alcanzable desde otro que es persistente (si hay alguna referencia del primero al segundo, o que a partir del primero, desde varios objetos intermedios, se puede llegar al segundo), entonces el sistema hará que el objeto sea persistente. Como se ha comentado, ésto se llama persistencia por alcanzabilidad (persistence by reachability), y explica por qué los lenguajes de programación de la máquina no necesitan ninguna construcción especial para manejarse con persistencia.
The virtual machine identifies those objects that must be made persistent by reachability. This means that if an object is reachable from another object that is a persistent object (i.e. a reference from the first object points to the second object directly, or through any number of intermediate objects), then the system will make it persistent. As explained before, this is called persistence by reachability and explains why the programming languages created dor this virtual machine doesn't need any special construction for persistence.


Cómo funciona

(How it works)

Los objetos en Zero son guardados en directorios de objetos, que en terminología Zero se conocen como contenedores (containers). Estos directorios existen como objetos totalmente normales en el modelo de objetos de Zero, sólo que cuando la máquina virtual se encuentra con estos objetos, conoce, por semántica, que se trata de una parte del almacenamiento persistente. El almacenamiento persistente es jerárquico, de manera que existe un contenedor root del que cuelgan todos los demás, especialmente el contenedor de la librería estándar, IntStdLib.
Objects in Zero are saved in directory objects, which in Zero terminology are known as containers. These directories wxist as regular objects in the Zero's object model. The only difference comes inside the virtual machine, as Zero recognizes them as they actual meaning, parts of the persistent store. The persistent store is hierarchical, presenting a container, namely root, which is the parent one of the reamining ones, specially IntStdLib.

Para guardar objetos, el programador lo único que ha de hacer es crear un contenedor, enlazar los objetos que desea guardar en ese contenedor (tal cual se enlazan cualesquiera otros objetos entre sí), y finalmente enlazar el contenedor con algún otro contenedor ya presente en el almacenamiento persistente, lo que garantiza que esos objetos se hagan, por alcanzabilidad, persistentes a su vez. La mecánica de ésto se puede ver en el siguiente ejemplo.
In order to store objects, programmers do only need to create a container, link the objects he or she whises to save in that container (as any other object is linked with others, using references), and finally link the container with any other container present in the persistent store, which will guarantee that these objects will be made, because of reachability, also persistent. The mechanism exposed here is shown in the following example.


Un ejemplo sencillo (a simple example)

En este ejemplo (desarrollado mediante el macroensamblador zm), se utilizarán varios objetos relacionados entre sí que permitirán representar a personas y a parejas. El primero objeto, Persona, será el que acumule los rasgos de todos los objetos representando a personas en la aplicación:
In this example (developed by means of the macroassembler zm), various objects related with each other are used, representing persons and couples.  The first object, Persona, shown below, will contain all traits of persons:

object Persona
       attribute + nombre = "juan nadie"
       attribute + email  = Nothing
 
       method + ponNombre(n)
                nombre = n
                return
       endMethod
        
       method + ponEmail(e)
                email = e
                return
       endMethod
 
       method + toString()
                __rr = nombre.toString()
 
                email.isTheSameAs( Nothing )
                jumpOnTrueTo fin
                     __rr = __rr.concat( ": " )
    
                __rr = __rr.concat( email.toString() )
 
        :fin
                return
        endMethod
endObject

Para representar a parejas, se utilizará un objeto que se asocie con personas:
In order to represent couples, an object related to persons will be used:

object Pareja
        attribute + hombre = Persona
        attribute + mujer  = Persona
        attribute + dependientes = Nothing
 
        method + ponPareja(a, b)
                hombre = a
                mujer  = b
                return
        endMethod
 
        method + ponDependiente(x)
                dependientes.isTheSameAs( Nothing )
                jumpOnFalseTo mas
                     dependientes = VectorInstance.copy( "" )
        :mas
                dependientes.add( x )
                return
        endMethod
 
        method + toString()
                __rr = "Pareja formada por: "
                __rr = __rr.concat( hombre.toString() )
                __rr = __rr.concat( ", y " )
                __rr = __rr.concat( mujer.toString() )
 
                dependientes.isTheSameAs( Nothing )
                jumpOnTrueTo Fin
 
                __rr = __rr.concat( "\nDependientes: " )
                __rr = __rr.concat( dependientes.toString() )
 
        :Fin
                __rr = __rr.concat( "." )
                return
        endMethod
endObject

Finalmente, en el objeto de la aplicación se crearán varias personas, relacionándolas mediante una pareja: 
Finally, in the application object a few persons will be created, being related by a couple:

object PruebaPersistente : ConsoleApplication
        method + doIt()
               reference disney       = ContainerInstance.copy( "Disney" )
               reference mascotas     = VectorInstance.copy( "mascotas" )
               reference donaldYdaisy = Pareja.copy( "" )
               reference donald       = Persona.copy( "" )
               reference daisy        = Persona.copy( "" )
               reference jorgito      = Persona.copy( "" )
               reference juanito      = Persona.copy( "" )
               reference jaimito      = Persona.copy( "" )
 
               donald.ponNombre( "Donald" )
               donald.ponEmail( "donald@disney.com" )
               daisy.ponNombre( "Daisy" )
               daisy.ponEmail( "daisy@disney.com" )
 
               jorgito.ponNombre( "Jorgito" )
               jaimito.ponNombre( "Jaimito" )
               juanito.ponNombre( "Juanito" )
 
               donaldYdaisy.ponPareja( donald, daisy )
               donaldYdaisy.ponDependiente( jorgito )
               donaldYdaisy.ponDependiente( jaimito )
               donaldYdaisy.ponDependiente( juanito )
               mascotas.add( "Pluto" )
               mascotas.add( "Goofy" )
               donaldYdaisy.ponDependiente( mascotas )
 
               System.console.write( "\nComenzando guardado ...\n" )
 
               System.console.write( donaldYdaisy )
               System.console.lf()
 
               disney.addRenamedObject( "donaldYdaisy", donaldYdaisy )
               psRoot.add( disney )
 
               System.console.write( "\nGuardado de manera persistente\n" )
               return
        endMethod
endObject

Una vez que se ejecuta este programa, los objetos relacionados con la pareja donaldYdisney han sido guardados en el almacenamiento persistente. La máquina virtual sigue todos los enlaces desde la pareja, asegurándose de que todos los objetos necesarios son guardados, de manera que puedan ser recuperados más tarde.
Once this program is executed, all objects related to the couple donaldYdisney are saved in the persistent store. The virtual machine will follow all links in order to be sure that all needed objects are saved, so they can be restored later.

Para garantizar que la información que se lee es la guardada por el programa anterior, se utilizará otro objeto (mucho más pequeño) que se encargue, símplemente, de recuperarla.
In order to guarantee that the information retrieved is just the one stored in the persistent store another smaller object will be created for simple restoring.

object VerPruebaPersistente : ConsoleApplication
         method + doIt()
               __this.prepare()
               System.console.write( "Recuperando info persistente:\n" )
               System.console.lf()
               System.console.write( psRoot.Disney.donaldYdaisy )
               System.console.lf()

               return
         endMethod
endObject

La salida de este objeto, una vez ejecutado, es:
The output of this object, once executed, follows:

$ zvm VerPruebaPersistente
Recuperando info persistente:
Pareja formada por: Donald: donald@disney.com, y Daisy: daisy@disney.com
Dependientes: Jorgito, Jaimito, Juanito, Pluto, Goofy.


Algunas interioridades

(Internals)

Inicialmente, en el directorio de instalación de Zero, la máquina virtual (zvm) y la librería estándar deben existir juntos. Cuando la máquina virtual es lanzada la primera vez con soporte de persistencia (es decir, sin el modificador --nops), se crea un directorio bajo el directorio de instalación llamado ZeroPS. En ese directorio se encontrará el contenedor root.zbj y el directorio Root, que aglutinará bajo él a todos los demás contenedores (directa o indirectamente), ya que es el contenedor raiz. La lbrería estándar estará guardada bajo este contenedor raiz, como InstStdLib.zbj, de manera que cuando la máquina virtual, zvm, es llamada con --nops ...
Initially, in the installation directory of Zero, the virtual machine (zvm program) and the standard library (IntStdLib.zbj) must be found together. When the VM is triggered for the first time with persistence support (i.e., without the --nops switch), the VM creates a directory called ZeroPS under the installation directory. Under this directory, the root one also appears, which is representing the root container (apart from root.zbj), the root container . The standard library is found saved under this root directory, as IntStdLib.zbj. When the VM is executed with the --nops switch,

$ ./zvm --nops Version

entonces se usa la librería estándar en el directorio de instalación, mientras que la encontrada en el almacenamiento persistente es utilizada con soporte de persistencia:
then the standard library in the installation directory is used, while the one present in the PS is used when triggered with persistence support:

$ ./zvm Version

Si bien, el objeto Version.zbj distribuido con el sistema no hace uso del almacenamiento persistente (aparte, claro está, de IntStdLib).
Though the Version.zbj object distributed with the system doesn't make use of the PS (apart from the IntStdLib, of course).

La estructura completa del almacenamiento persistente es una asociación entre contenedores y directorios (ahora sí, directorios del sistema de ficheros). Si un contenedor no tiene subcontenedores, entonces no tendrá un directorio asociado o estará vacío. En caso contrario, el directorio existe, contiene los .zbj de sus contenedores (y sus respectivos directorios asociados), y tiene el mismo nombre que el contenedor (sin la extensión .zbj).
The whole structure of the persistent store is a mapping between containers and directories (of the file system). If a container doesn't have children containers then it won't have a subdirectory or it will be empty. If it has, then the subdirectory won't be empty. Otherwise, it will have the same name the container has, containing its subcontainers files (*.zbj) and their associated directories.

Es posible crear un objeto con cualquier de los lenguajes disponibles que generen Zero bytecode, o con el [macro]ensamblador Zero mismo, y colocar adcuadamente el fichero zbj generado en la estructura de directorios. Por ejemplo, si un objeto llamado Areas es compilado dentro de un archivo llamado Math, (que debería convertirse en Math.zbj), será considerado como el contenedor Math con el objeto Areas en su interior.
It is possible to create an object with a programming language generating zero bytecode, or with the zero [macro]assembler itself and place it (the .zbj file) adequately in the directory structure. For example, if an object called Areas is compiled using a file name Math, (which should become Math.zbj), then it will be considered as the Math container with the Areas object inside it.

OBJ Areas
  MTH + areaOfSquare x
    SET x
    MSG __acc multiplyBy __acc
    ASG __rr
    RET
  ENM
ENO

Por ejemplo, podría ser emplazado dentro del contenedor raiz, Root.
For instance, it could be placed under the root directory,

$ ./za Math
$ cd ZeroPS
$ cd Root
$ mv ../../Math.zbj .

Así podría ser accedido (usando Prowl o macroensamblador) mediante la sentencia:
so it could be accessed through (using the Prowl programming language, or the macroassembler), by a sentence such as:

System.console.write( psRoot.Math.Areas.areaOfSquare( 7 ) );

O mediante (utilizando el ensamblador):
or through (using plain assembler):

INT 7
MSG psRoot.Math.Areas areaOfSquare __acc
MSG System.console write __acc

Mostrando 49, como se esperaba.
Showing 49 as result, as expected.


J. Baltasar García Perez-Schofield  jbgarcia@uvigo.es