function didCancel = cancelOrDestroyJob( obj, job, fcnH )
% cancelOrDestroyJob for parallel.cluster.Local
% - obj: the Local scheduler
% - job: the job object
% - fcnH: a function handle to invoke on the "command"
%
% Algorithm:
% didCancel = false
% jobNeedsCancelling = ( pending < job.State < finished )
% if ( ~my job ) && jobNeedsCancelling
%     warn "not my job"
%     return
% end
% foreach ( taskUUIDs in local scheduler )
%     fcnH( command corresponding to taskUUID )
% end
% didCancel = true

% Copyright 2011-2019 The MathWorks, Inc.

import parallel.internal.types.States;
import parallel.cluster.Local;

didCancel               = false;
[correctType, correctClient, jobData] = ...
    Local.getJobSchedDataIfAvailable( job );
jobState                = job.StateEnum; % Fully derive job state
jobNeedsCancelling      = jobState > States.Pending && ...
    jobState < States.Finished;
% NB - guards in CJSJobMethods.cancelOneJob should defend against
% jobNeedsCancelling being false during 'cancel(job)'.

if ~correctClient && jobNeedsCancelling
    warning(message('parallel:cluster:LocalCannotCancelOrDestroyJob'));
    return
end

% Always ensure we clean up the local scheduler commands
try
    if correctType && correctClient
        iCancelOrDestroyCommands( obj.LocalSched, jobData.taskUUIDs, fcnH );
        didCancel = true;
    end
catch E
    warning(message('parallel:cluster:LocalFailedToCancelOrDestroyJob', E.message));
end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Ask the localSched java scheduler for the underlying "commands", and
% cancel/destroy those.
function iCancelOrDestroyCommands( localSched, taskUUIDs, fcnH )
for ii = 1:numel( taskUUIDs )
    fcnH( localSched, taskUUIDs{ii} );
end
end
