Satsvis kjøring av ressursendringer

Når du vil endre ressurser i arbeidsområdet, er det viktig å være klar over at andre plugin-moduler kanskje arbeider med samme ressurs. Programmeringsgrensesnittet for ressursene inneholder kraftige mekanismer som holder plugin-moduler informert om endringer i arbeidsområdet, og sørger for at flere plugin-moduler ikke endrer de samme ressursene samtidig. Der det er mulig bør plugin-modulens endringer i arbeidsområdet kjøres satsvist i arbeidsenheter, i en kjørbar fil i arbeidsområdet. De kjørbare filene bidrar til å redusere mengden endringsmeldinger som genereres av endringene. De gjør det også mulig å deklarere hvilken del av arbeidsområdet som skal endres, slik at andre plugin-moduler kan stenges ute fra å endre samme del av arbeidsområdet.

Protokollen for IWorkspaceRunnable er nokså enkel. En kjørbar fil i arbeidsområdet ser ut som en tidkrevende operasjon eller plattformjobb. Det egentlige arbeidet utføres i en run-metode, der fremdriften rapporteres til den oppgitte IProgressMonitor. Koden som manipulerer arbeidsområdet utføres i run-metoden.

IWorkspaceRunnable myRunnable = 
	new IWorkspaceRunnable() {
		public void run(IProgressMonitor monitor) throws CoreException {
			//do the actual work in here
			...
		}
}

Når koden skal kjøres, forteller plugin-modulen arbeidsområdet at koden skal kjøres. På denne måten kan arbeidsområdet generere nødvendige endringshendelser og sørge for at to plugin-moduler ikke endrer samme ressurs samtidig. (Selv om plugin-modulen ikke bruker bakgrunnsjobber og samtidighetsrammeverket for å endre arbeidsområdet, kan det hende at andre plugin-moduler gjør dette.)

Planleggingsregler og låsing

IWorkspace-protokollen brukes til å kjøre en utførbar fil i arbeidsområdet. Det foretrekkes å bruke den lange varianten av run-metoden, som oppgir en planleggingsregel og angir hvordan ressursendringer kunngjøres.

Ved å angi en planleggingsregel når det kjøres en utførbar fil i arbeidsområdet, kan arbeidsområdet finne ut om ressursendringene er i konflikt med arbeidsområdeendringer som oppstår i andre tråder. (Se under Planleggingsregler hvis du vil se en oversikt over planleggingsregler og ISchedulingRule-protokollen.) Heldigvis inneholder IResource-protokollen en protokoll for ISchedulingRule, som betyr at en ressurs ofte kan brukes som en egen planleggingsregel.

Forvirret? Koden kan bidra til å gjøre dette punktet klarere. Tenk deg at plugin-modulen gjør seg klar til å endre noen ressurser i et bestemt prosjekt. Den kan bruke selve prosjektet som planleggingsregel for å utføre endringene. Følgende snutt kjører den utførbare filen i arbeidsområdet som vi opprettet tidligere:

   IWorkspace workspace = ResourcesPlugin.getWorkspace();
workspace.run(myRunnable, myProject, IWorkspace.AVOID_UPDATE, null);

Den kjørbare filen sendes til arbeidsområdet, etterfulgt av prosjektet som koden manipulerer. Dette angir for arbeidsområdet at alle endringene i den kjørbare filen, begrenses til myProject. Forespørsler fra andre tråder om å endre myProject, blokkeres til den kjørbare filen er ferdig. På samme måte blokkerer dette kallet hvis en annen tråd allerede er i ferd med å endre myProject. Ved å oppgi hvilken del av ressurstreet som skal endres av den kjørbare filen, er det mulig for andre tråder å fortsette å endre andre deler av arbeidsområdet. Det er viktig å være sikker på at ressursregelen samsvarer med det arbeidet som utføres i den kjørbare filen. Når det brukes en planleggingsregel som ikke er null, vil alle forsøk på å få tilgang til ressurser utenfor planleggingsregelsens omfang utløse et unntak.

De er to spesielle planleggingsregler som er viktige å vurdere. For det første: Hvis du bruker en forekomst av IWorkspaceRoot som planleggingsregel, betyr det at tråden blokkerer tilgangen til alle ressurser i treet. Når en tråd inneholder rotregelen, får ingen annen tråd lov til å endre arbeidsområdet. Motsatt innebærer en regel med null at tråden vil blokkere tilgang til ingen ressurser i treet. Selv om en tråd med null-regel er fri til å endre selve arbeidsområdet, kan ikke andre tråder hindres i å utføre endringer. Planleggingsreglene IWorkspaceRoot og null befinner seg i hver sin ende av samtidighetsspekteret. Med IWorkspaceRoot er det ingen samtidighet, og bare en tråd endrer arbeidsområdet om gangen. Med en null-regel er det maksimal samtidighet, og alle tråder kan endre arbeidsområdet samtidig.

Den tredje parameteren for run-metoden angir om periodiske ressursendringshendelser skal kunngjøres under omfanget av dette kallet. Ved å bruke IWorkspace.AVOID_UPDATE angis det overfor plattformen at eventuelle ressursendringer skal holdes tilbake mens de kjørbare hendelsene kjøres, og at en hendelse skal kunngjøres mot slutten av endringene. Under dette kallet vil alle andre kjørbare filer som opprettes i den kjørbare filen, betraktes som en del av den overordnede satsvise operasjonen. Ressursendringer som gjøres i disse kjørbare filene, vises i den overordnede ressursens endringsmelding.

Ressursregel-factory

I eksempelet ovenfor ble det forutsatt at koden i den kjørbare filen bare endret ressurser i et bestemt prosjekt. Dette gjorde det veldig enkelt å angi en planleggingsregel for den kjørbare filen. I praksis kan det være vanskeligere å beregne hvilke deler av arbeidsområdet som ble påvirket av en bestemt endring. For eksempel vil flytting av en ressurs fra et prosjekt til et annet påvirke begge prosjektene. IResourceRuleFactory kan brukes til å beregne en egnet ressursregel for bestemte ressursendringer. Du kan hente en ressursregel-factory fra selve arbeidsområdet:

   IWorkspace workspace = ResourcesPlugin.getWorkspace();
IResourceRuleFactory ruleFactory = workspace.getRuleFactory();

Factory kan oppgi regler som er egnet for mange typer operasjoner. Hvis den kjørbare filen flytter en ressurs fra et sted til et annet, kan den hente en regel som er egnet for denne operasjonen:

ISchedulingRule movingRule = ruleFactory.moveResource(sourceResource, destinationResource);
workspace.run(myRunnable, movingRule, IWorkspace.AVOID_UPDATE, null);

Du finner en liste over tilgjengelige regler i Javadoc for IResourceRuleFactory. Ressursenes plugin-modul bruker disse reglene selv til å implementere de fleste ressursoperasjoner. Ved å se på koden som refererer til disse regelmetodene, ser du hvordan de brukes i praksis.

Flere regler kan kombineres ved hjelp av MultiRule.

ISchedulingRule movingRule = ruleFactory.moveResource(sourceResource, destinationResource);
ISchedulingRule modifyRule = ruleFactory.modifyResource(destinationResource);
workspace.run(myRunnable, MultiRule.combine(movingRule, modifyRule), IWorkspace.AVOID_UPDATE, null);

Ignorere reglene

Den korte varianten av run-metoden i IWorkspace er også tilgjengelig. Den beholdes for tilbakekompatibilitet. Kortvarianten inneholder ikke en regel eller et oppdateringsflagg.

workspace.run(myRunnable, null);

er det samme som å kalle

workspace.run(myRunnable, workspace.getRoot(), IWorkspace.AVOID_UPDATE, null);

Ved å angi arbeidsområdets rot som planleggingsregel, låses hele arbeidsområdet til den kjørbare filen er ferdig. Dette er den mest skånsomme måten å oppdatere arbeidsområdet på, men ikke spesielt gunstig med tanke på samtidighet i andre plugin-moduler.