Medvirkning til arbeidsområdelagring

Det utløses en arbeidsområdelagring når arbeidsbenken avsluttes av brukeren eller eventuelt av plattformen. Plugin-moduler kan delta i lagringsprosessen for arbeidsbenken slik at kritiske plugin-data lagres på disk når øvrige persistente arbeidsområdedata lagres.

Lagringsprosessen for arbeidsområdet kan også brukes til å spore endringer som oppstår mellom aktivering av plugin-modulen.

Implementere en lagringsdeltaker

For å medvirke til arbeidsområdelagring må det legges til en lagringsdeltaker i arbeidsområdet. Dette gjøres vanligvis i oppstartsmetoden for plugin-modulen.  Her leser du også eventuelle tilstander som kan ha blitt lagret sist plugin-modulen ble avsluttet.

La oss se på lagringsprosessen med en enkel plugin-modul.

   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;
      // the plugin instance should read any important state from the file.
         File f = getStateLocation().append(location).toFile();
         readStateFrom(f);
      }

      protected void writeImportantState(File target) {
      }
   }

ISaveParticipant definerer protokollen for en deltaker i arbeidsområdelagringen. Implementerere av dette grensesnittet kan oppgi funksjonalitet for ulike stadier i lagringsprosessen.  La oss se på stadiene og hvordan klassen WorkspaceSaveParticipant implementerer hvert av disse trinnene.

      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();
               // save the plug-in state
               int saveNumber = context.getSaveNumber();
         String saveFileName = "save-" + Integer.toString(saveNumber);
      File f = myPluginInstance.getStateLocation().append(saveFileName).toFile();
               // if we fail to write, an exception is thrown and we do not update the path
               myPluginInstance.writeImportantState(f);
               context.map(new Path("save"), new Path(saveFileName));
               context.needSaveNumber();
      break;
            case ISaveContext.PROJECT_SAVE:
               // get the project related to this save operation
               IProject project = context.getProject();
               // save its information, if necessary
      break;
            case ISaveContext.SNAPSHOT:
               // This operation needs to be really fast because
               // snapshots can be requested frequently by the
               // workspace.
      break;
         }
      }

ISaveContext beskriver informasjon om lagringsoperasjonen.  Det finnes tre ulike lagringsoperasjoner:   FULL_SAVE, SNAPSHOT og PROJECT_SAVE. Lagringsdeltakere må bruke riktig operasjon når de skal behandle den mottatte lagringshendelsestypen. For eksempel kan snapshot-hendelser oppstå relativt ofte og gjør det mulig for plugin-moduler å lagre den kritiske tilstanden. Hvis det tar lang tid å lagre en tilstand som kan behandles på nytt i tilfelle krasj, reduseres ytelsen i plattformen.

Det brukes et lagringsnummer til å opprette datalagringsfiler som navngis ved hjelp av sekvensielle tall (save-1, save-2, osv.) Hver lagringsfil tilordnes til et logisk filnavn (save), som er uavhengig av lagringsnummeret. Plugin-data skrives til den tilsvarende filen og kan hentes senere uten at det er nødvendig å kjenne det spesifikke lagringsnummeret for siste lagring.  Dette har vi beskrevet i  oppstartskoden for plugin-modulen:

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

Etter at vi har lagret dataene og tilordnet filnavnet, kaller vi opp needSaveNumber for å angi at vi aktivt har deltatt i en arbeidsområdelagring og vil tildele et nummer til lagringsaktiviteten. Lagringsnumrene kan brukes til å opprette datafilene ovenfor. 

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

         // delete the old saved state since it is not necessary anymore
         int previousSaveNumber = context.getPreviousSaveNumber();
         String oldFileName = "save-" + Integer.toString(previousSaveNumber);
         File f = myPluginInstance.getStateLocation().append(oldFileName).toFile();
         f.delete();
      }

Her kan vi rydde lagringsinformasjonen fra den forrige lagringsoperasjonen. Vi bruker getPreviousSaveNumber til å hente lagringsnummeret som ble tildelt ved forrige lagring (ikke den vi nettopp fullførte).  Vi bruker dette nummeret til å opprette navnet på filen som vi må slette. Merk at vi ikke trenger å bruke lagringstilstandens logiske filtilordning siden vi allerede har tilordnet det gjeldende lagringsfilnummeret. 

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

         // since the save operation has failed, delete the saved state we have just written
         int saveNumber = context.getSaveNumber();
         String saveFileName = "save-" + Integer.toString(saveNumber);
      File f = myPluginInstance.getStateLocation().append(saveFileName).toFile();
         f.delete();
      }

Her sletter vi tilstanden vi nettopp lagret. Merk at vi bruker det gjeldende lagringsnummeret til å opprette navnet på filen vi nettopp lagret.  Vi trenger ikke å tenke på at vi har tilordnet dette filnavnet til ISaveContext. Plattformen fjerner konteksten hvis en lagringsoperasjon mislykkes.

Hvis en plugin-modulen kaster et unntak i løpet av livssyklusen for en lagring, fjernes den fra den gjeldende lagringsoperasjonen og får ingen av de gjenværende livssyklusmetodene.  Hvis du for eksempel mislykkes med lagringsmetoden, får du ingen melding om rollback eller doneSaving

Bruke tidligere lagret tilstand

Når du legger til en lagringsdeltaker i arbeidsområdet, returneres et ISavedState-objekt som beskriver hva plugin-modulen lagret ved siste lagring (eller null hvis plugin-modulen ikke har lagret noen tilstand). Dette objektet kan brukes for å få tilgang til informasjon fra forrige lagringsfil (ved å bruke lagringsnummeret og filtilordningen) eller behandle endringer som har oppstått mellom aktivering av en plugin-modul.

Få tilgang til lagringsfiler

Hvis det ble brukt en filtilordning til å lagre logiske navngitte filer i henhold til lagringsnummeret, kan den samme tilordningen brukes til å hente data fra sist kjente lagringstilstand.

   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();
      // the plugin instance should read any important state from the file.
      myPluginInstance.readStateFrom(f);
   }

Behandle ressursdeltaer mellom aktiveringer

Husk at det kan oppstå en rekke ressursendringshendelser i arbeidsområdet før plugin-modulen aktiveres. Hvis du vil vite hvilke endringer som har oppstått siden plugin-modulen ble deaktivert sist, finner du dette ved å bruke lagringsmekanismen selv om du ikke trenger å lagre andre data.

Lagringsdeltakeren må be plattformen om å oppbevare en ressursdelta for seg. Dette gjøres som en del av lagringsoperasjonen.

   public void saving(ISaveContext context) throws CoreException {
      // no state to be saved by the plug-in, but request a
      // resource delta to be used on next activation.
      context.needDelta();
   }

Når plugin-modulen startes, gis det tilgang til forrige lagrede tilstand og det opprettes endringshendelser for alle endringer som har oppstått siden siste lagring.

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

Den oppgitte klassen må implementere IResourceChangeListener, slik det er beskrevet i Spore ressursendringer.  Endringer siden forrige lagring rapporteres som en del av ressursendringshendelsen POST_AUTO_BUILD.

Merk:  Merkeendringer rapporteres ikke i endringshendelser som er lagret i en ISavedState. Du må anta at noen eller alle merker er endret siden siste tilstand ble lagret.