자원 변경 일괄처리

작업공간에서 자원을 수정해야 할 경우 다른 플러그인이 동일한 자원에 대해 작업 중일 수 있음을 고려해야 합니다. 자원 API는 작업공간의 변경사항을 계속해서 플러그인에 알리고 여러 플러그인이 동시에 동일한 자원을 수정하지 않도록 하는 강력한 메커니즘을 제공합니다. 가능하면 작업공간에 대한 플러그인의 수정사항은 작업공간 실행 프로그램에서 작업 단위로 일괄처리되어야 합니다. 이러한 실행 프로그램은 변경으로 생성되는 다량의 변경 알림을 줄이는 데 도움이 됩니다. 이 실행 프로그램을 사용하면 다른 플러그인이 작업공간의 동일한 부분을 변경하지 못하게 잠길 수 있도록 수정할 작업공간의 부분을 선언할 수도 있습니다.

IWorkspaceRunnable의 프로토콜은 매우 단순합니다. 작업공간 실행 프로그램은 장기 실행 조작 또는 플랫폼 작업과 유사합니다. 실제 작업은 실행 메소드에서 수행되며, 진행 상태가 제공된 IProgressMonitor로 보고됩니다. 작업공간을 조작하는 코드는 실행 메소드에서 수행됩니다.

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

코드를 실행할 시간이 되면 플러그인은 작업공간이 플러그인을 대신하여 코드를 실행하도록 알립니다. 이 방법으로 작업공간은 필요한 변경 이벤트를 생성하여 두 개의 플러그인이 동시에 동일한 자원을 수정하지 않도록 할 수 있습니다. (사용자의 플러그인이 작업공간을 수정하기 위해 배경 작업 및 동시성 프레임워크를 사용하지 않는경우에도 다른 플러그인은 이를 수행할 수 있습니다.)

스케줄링 규칙 및 잠금

IWorkspace 프로토콜은 작업공간 실행 프로그램을 실행하는 데 사용됩니다. 선호되는 기술은 스케줄링 규칙을 제공하고 자원 변경 이벤트가 브로드캐스트되는 방법을 지정하는 장기 실행 메소드 양식을 사용하는 것입니다.

작업공간 실행 프로그램을 실행할 때 스케줄링 규칙을 지정하면 자원 변경사항이 다른 스레드에서 발생하는 작업공간 변경사항과 충돌하는지 여부를 작업공간이 판별할 수 있습니다. (스케줄링 규칙 및 ISchedulingRule 프로토콜을 다루는 개요는 스케줄링 규칙을 참조하십시오.) 다행히도 IResource 프로토콜에는 ISchedulingRule의 프로토콜이 포함되어 있는데, 이것은 자원이 종종 자원 자체에 대한 스케줄링 규칙으로 사용될 수 있음을 의미합니다.

혼동되십니까? 코드는 이 점을 명확히 하는 데 도움이 됩니다. 플러그인이 특정 프로젝트에서 일련의 자원을 수정할 준비가 되어 있다고 가정해 보십시오. 플러그인은 프로젝트 자체를 변경사항 작성을 위한 스케줄링 규칙으로 사용할 수 있습니다. 다음 스니펫은 앞에서 작성한 작업공간 실행 프로그램을 실행합니다.

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

실행 프로그램은 작업공간으로 전달되고 코드가 조작 중인 프로젝트로 전달됩니다. 이렇게 하여 실행 프로그램의 모든 변경사항이 myProject로 제한됨을 작업공간에 알립니다. 다른 스레드가 myProject를 변경하기 위한 모든 요청은 이 실행 프로그램이 완료될 때까지 블록됩니다. 마찬가지로 이 호출은 일부 다른 스레드가 이미 myProject를 수정 중인 경우 블록됩니다. 실행 프로그램에서 수정할 자원 트리 부분을 지정하면 다른 스레드가 작업공간의 다른 부분을 계속해서 수정할 수 있게 됩니다. 자원 규칙이 실행 프로그램에서 수행 중인 작업과 일치하는지를 확인하는 것이 중요합니다. 스케줄링 규칙의 범위 밖에 있는 자원에 액세스하려고 시도하면 예외가 발생합니다.

실행 메소드에 대한 세 번째 매개변수는 주기적인 모든 자원 변경 이벤트가 이 호출 범위 내에 브로드캐스트되어야 하는지 여부를 지정합니다. IWorkspace.AVOID_UPDATE를 사용하면 실행 프로그램이 실행 중인 동안 모든 자원 변경 이벤트를 억제하여 변경 종료 시점에 하나의 이벤트를 브로드캐스트하도록 플랫폼에 알립니다. 이 호출 중 실행 프로그램에 작성된 다른 모든 실행 프로그램은 상위 일괄처리 조작의 일부로 간주됩니다. 해당 실행 프로그램에서 작성된 자원 변경사항은 상위의 자원 변경 알림에 표시됩니다.

자원 규칙 팩토리

위의 예제에서 실행 프로그램 내부의 코드만 특정 프로젝트의 자원을 수정했음을 가정했습니다. 따라서 실행 프로그램에 스케줄링 규칙을 지정하는 것이 매우 쉽습니다. 실제로는 특정 변경사항으로 영향을 받는 작업공간의 부분을 계산하는 것이 더 어려울 수 있습니다. 예를 들어 한 프로젝트에서 다른 프로젝트로 자원을 이동시키면 두 프로젝트가 모두 영향을 받습니다. IResourceRuleFactory는 특정 종류의 자원 변경사항에 적절한 자원 규칙을 계산하는 데 도움이 됩니다. 작업공간 자체에서 자원 규칙 팩토리를 가져올 수 있습니다.

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

팩토리는 다양한 종류의 조작에 적절한 규칙을 제공할 수 있습니다. 실행 프로그램이 한 위치에서 다른 위치로 자원을 이동하는 경우 다음과 같이 이 조작에 적절한 규칙을 얻을 수 있습니다.

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

사용 가능한 규칙 목록은 IResourceRuleFactory의 javadoc을 참조하십시오. 자원 플러그인은 이 규칙 자체를 사용하여 대부분의 자원 조작을 구현합니다. 이러한 규칙 메소드를 참조하는 코드를 찾아보면 실제로 이 메소드를 사용하는 방법을 시연하는 데 도움이 됩니다.

복수 규칙은 MultiRule을 사용하여 결합할 수 있습니다.

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

규칙 무시

IWorkspace의 단기 실행 메소드 양식도 사용 가능합니다. 이 메소드는 역 호환성을 위해 유지됩니다. 단기 양식에는 규칙 또는 갱신 플래그가 포함되어 있지 않습니다.

workspace.run(myRunnable, null);

위 항목은 실제로 호출과 동일합니다.

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

작업공간 루트를 스케줄링 규칙으로 지정하면 실행 프로그램이 완료될 때까지 전체 작업공간에 잠금이 적용됩니다. 이것은 작업공간 갱신을 수행하는 가장 전형적인 방법이지만 다른 동시성 기반 플러그인에는 별로 적합하지 않습니다.