Participación del guardado del área de trabajo

El proceso de guardado del área de trabajo se desencadena cuando el usuario, y otras veces la plataforma de manera periódica, cierra el entorno de trabajo.   Los conectores pueden participar en el proceso de guardado del área de trabajo para que los datos críticos del conector se guarden en el disco siempre que se guarden los demás datos persistentes del área de trabajo.

El proceso de guardado del área de trabajo también permite hacer un seguimiento de los cambios que se producen entre las activaciones del conector.

Implementar un participante del guardado

Para participar en el guardado del área de trabajo, debe añadir a ella un participante de la operación de guardar. Esto se suele realizar durante el método de inicio del conector.   Aquí también es donde se lee el estado que podría haber guardado la última vez que se cerró el conector.

Veamos un conector simple que nos hará una demostración del proceso de guardar.

   package com.example.saveparticipant;

   import org.eclipse.core.runtime.*;
   import org.eclipse.core.resources.*;
   import java.io.File;
   import java.util.*;

   public class MyPlugin extends Plugin {
      private static MyPlugin plugin;

      public MyPlugin(IPluginDescriptor descriptor) {
         super(descriptor);
         plugin = this;
      }

      public static MyPlugin getDefault() {
         return plugin;
      }

      protected void readStateFrom(File target) {
      }

      public void startup() throws CoreException {
         super.startup();
   ISaveParticipant saveParticipant = new MyWorkspaceSaveParticipant();
   ISavedState lastState =
            ResourcesPlugin.getWorkspace().addSaveParticipant(this, saveParticipant);
         if (lastState == null)
            return;
         IPath location = lastState.lookup(new Path("save"));
         if (location == null)
            return;
      // La instancia del conector debe leer todo estado importante en el archivo.
         File f = getStateLocation().append(location).toFile();
         readStateFrom(f);
      }

      protected void writeImportantState(File target) {
      }
   }

La interfaz ISaveParticipant define el protocolo de un participante del guardado del área de trabajo. Los implementadores de esta interfaz pueden proporcionar el comportamiento de las diferentes fases del proceso de guardado.  A continuación, se muestra cómo implementa la clase WorkspaceSaveParticipant cada uno de estos pasos.

      public void prepareToSave(ISaveContext context) throws CoreException {
      }
   public void saving(ISaveContext context) throws CoreException {
         switch (context.getKind()) {
            case ISaveContext.FULL_SAVE:
         MyPlugin myPluginInstance = MyPlugin.getDefault();
               // guardar el estado del conector
               int saveNumber = context.getSaveNumber();
         String saveFileName = "save-" + Integer.toString(saveNumber);
      File f = myPluginInstance.getStateLocation().append(saveFileName).toFile();
               // si no se puede escribir, se lanza una excepción y no se actualiza la vía de acceso
               myPluginInstance.writeImportantState(f);
               context.map(new Path("save"), new Path(saveFileName));
               context.needSaveNumber();
      break;
            case ISaveContext.PROJECT_SAVE:
               // obtener el proyecto relacionado con esta operación de guardar
               IProject project = context.getProject();
               // guardar su información, si es necesario
      break;
            case ISaveContext.SNAPSHOT:
               // Esta operación se tiene que realizar verdaderamente deprisa
               // porque puede ser que se soliciten instantáneas frecuentes de parte del
               // área de trabajo.
      break;
         }
      }

ISaveContext describe información relativa a la operación de guardar.  Existen tres tipos de operaciones de guardar:  FULL_SAVE, SNAPSHOT y PROJECT_SAVE.  Los participantes en las operaciones de guardar deben tener cuidado de realizar los procesos adecuados al tipo de evento de guardar que han recibido.  Por ejemplo, pueden producirse con frecuencia eventos de instantánea, que están destinados a permitir que los conectores guarden su estado crítico.  Si se tarda mucho en guardar un estado que pueda volver a calcularse en caso de siniestro, se ralentizará el rendimiento de la plataforma.

Para crear archivos de guardado de datos cuyo nombre contenga números secuenciales, se utiliza un número de guardado (save-1, save-2, etcétera).Cada archivo de guardar se correlaciona con un nombre de archivo lógico (save) que es independiente del número del guardado. Los datos del conector se escriben en el archivo correspondiente y pueden recuperarse más adelante sin que sea necesario conocer el número de guardado específico de la última operación de guardado satisfactoria.   Recuerde que se utilizó esta técnica en el código de inicio del conector: 

IPath location = lastState.lookup(new Path("save"));

Después de haber guardado los datos y correlacionado el nombre del archivo, se llama a needSaveNumber para indicar que se ha participado de manera activa en un guardado del área de trabajo y que se desea asignar un número a la actividad de guardado. Los números de guardado permiten crear archivos de datos, tal como se ha mostrado anteriormente. 

      public void doneSaving(ISaveContext context) {
         MyPlugin myPluginInstance = MyPlugin.getDefault();

         // suprimir el estado guardado antiguo porque ha dejado de necesitarse
         int previousSaveNumber = context.getPreviousSaveNumber();
         String oldFileName = "save-" + Integer.toString(previousSaveNumber);
         File f = myPluginInstance.getStateLocation().append(oldFileName).toFile();
         f.delete();
      }

En este ejemplo se ha borrado la información de guardar de la operación de guardar anterior.  Se ha utilizado getPreviousSaveNumber para obtener el número de guardado asignado a la operación de guardar anterior (no la que acabamos de realizar).  Se ha utilizado este número para construir el nombre del archivo que necesitamos suprimir.  Observe que no se utiliza la correlación de archivo lógico del estado de guardado, puesto que ya se ha correlacionado el número de archivo de guardar actual. 

      public void rollback(ISaveContext context) {
         MyPlugin myPluginInstance = MyPlugin.getDefault();

         // como el guardado ha fallado, suprimir el estado guardado que acabamos de escribir
         int saveNumber = context.getSaveNumber();
         String saveFileName = "save-" + Integer.toString(saveNumber);
      File f = myPluginInstance.getStateLocation().append(saveFileName).toFile();
         f.delete();
      }

En este ejemplo se ha suprimido el estado que acabamos de guardar.  Observe que utilizamos el número de guardado actual para construir el nombre del archivo que acabamos de guardar.  No tenemos que preocuparnos del hecho de haber correlacionado este nombre de archivo con la interfaz ISaveContext. La plataforma descartará el contexto cuando falle una operación de guardado.

Si el conector lanza una excepción en cualquier momento durante el ciclo de vida del guardado, se eliminará de la operación de guardado actual y no obtendrá ninguno de los métodos de ciclo de vida restantes.  Por ejemplo, si se produce una anomalía durante el método saving, no recibirá ningún mensaje rollback ni doneSaving

Utilizar un estado guardado anteriormente

Cuando añade un participante del guardado al área de trabajo, devolverá un objeto ISavedState, que describe lo que el conector guardó durante su última operación de guardado (o null si el conector no guardó anteriormente ningún estado). Este objeto permite acceder a información del archivo de guardado anterior (utilizando el número de guardado y la correlación de archivos) o procesar los cambios que se han producido entre las activaciones de un conector.

Acceder a los archivos de guardado

Si se ha utilizado una correlación de archivos para guardar archivos denominados de manera lógica según el número del guardado, se puede utilizar esta misma correlación para recuperar los datos del último estado de guardado conocido.

   ISaveParticipant saveParticipant = new MyWorkspaceSaveParticipant();
   ISavedState lastState =
      ResourcesPlugin.getWorkspace().addSaveParticipant(myPluginInstance, saveParticipant);

   if (lastState != null) {
      String saveFileName = lastState.lookup(new Path("save")).toString();
      File f = myPluginInstance.getStateLocation().append(saveFileName).toFile();
      // La instancia del conector debe leer todo estado importante en el archivo.
      myPluginInstance.readStateFrom(f);
   }

Procesar deltas de recursos entre activaciones

Recuerde que podría tener lugar cualquier número de eventos de cambio de recurso en el área de trabajo antes de que el conector se active. Si desea saber qué cambios se han producido desde que se desactivó el conector, puede utilizar el mecanismo de guardado para hacerlo, incluso si no necesita guardar ningún otro dato.

El participante del guardado debe pedir que la plataforma mantenga un delta de recursos en su nombre. Esto se lleva a cabo como parte de la operación de guardado.

   public void saving(ISaveContext context) throws CoreException {
      // no hay ningún estado que el conector deba guardar, pero hay que solicitar
      // un delta de recursos que se empleará en la próxima activación.
      context.needDelta();
   }

Durante el inicio del conector, se puede acceder al estado guardado anterior y se crearán eventos de todos los cambios que se han producido desde el último guardado.

   ISaveParticipant saveParticipant = new MyWorkspaceSaveParticipant();
   ISavedState lastState =
      ResourcesPlugin.getWorkspace().addSaveParticipant(myPluginInstance, saveParticipant);
   if (lastState != null) {
      lastState.processResourceChangeEvents(new MyResourceChangeReporter());
   }

La clase proporcionada debe implementar la interfaz IResourceChangeListener, tal como se describe en el tema Hacer un seguimiento de los cambios de recursos.   Los cambios producidos desde el último guardado se notifican como parte del evento de cambio de recurso POST_AUTO_BUILD.

Nota: los cambios de marcador no se incluyen en los eventos de cambios almacenados en una interfaz ISavedState. Debe presuponer que han cambiado algunos o todos los marcadores desde que se guardó el último estado.

Copyright IBM Corporation y otros 2000, 2003.