gusucode.com > bigdata 工具箱 matlab源码程序 > bigdata/+matlab/+bigdata/BigDataException.m

    %BigDataException Capture error information from errors thrown in user code inside a Big-Data language construct.
%
%   BigDataException methods:
%      throw         - Issue exception and terminate function
%      rethrow       - Reissue existing exception and terminate function
%      throwAsCaller - Issue exception as if from calling function
%      addCause      - Record additional causes of exception
%      getReport     - Get error message for exception
%      last          - Return last uncaught exception
%
%   BigDataException properties:
%      identifier  - Character string that uniquely identifies the error
%      message     - Formatted error message that is displayed
%      cause       - Cell array of MExceptions that caused the error
%      stack       - Structure containing stack trace information
%
%   See also try, catch, MException

% Copyright 2015-2016 The MathWorks, Inc.

classdef BigDataException < MException & matlab.mixin.CustomDisplay
    
    properties (SetAccess = immutable, GetAccess = private)
        % The functional stack of the call that submitted the deferred
        % operation.
        SubmissionStack;
        
        % The functional stack inside the function handle that has been
        % called by the execution environment.
        CalleeStack;
    end
    
    properties (Access = private)
        % The number of frames to ignore from the execution functional
        % stack.
        NumIgnoredFrames = 0;
    end
    
    methods (Static, Hidden)
        % Helper function that obtains the current functional stack to
        % attach to a lazily evaluated function handle.
        %
        % Syntax:
        %   BigDataException.hGetStack(numIgnoredFrames) returns the
        %   current functional stack ignoring the first numIgnoredFrames
        %   entries of the stack.
        %
        function stack = hGetStack(numIgnoredFrames)
            import matlab.bigdata.internal.InternalStackFrame;
            import matlab.bigdata.BigDataException;
            if nargin < 1
                numIgnoredFrames = 0;
            end
            
            if ~BigDataException.showFullStack() && InternalStackFrame.hasInternalStackFrames()
                stack = InternalStackFrame.userStack();
                
                if numIgnoredFrames > 2
                    % If numIgnoredFrames is 2 or less, we can optimize
                    % away this second call to dbstack because the user
                    % stack will be at most dbstack(2).
                    thisStack = dbstack('-completenames', numIgnoredFrames + 1);
                    if numel(thisStack) < numel(stack)
                        stack = thisStack;
                    end
                end
            else
                stack = dbstack('-completenames', numIgnoredFrames + 1);
            end
            
            if ~BigDataException.showFullStack()
                % Filter out all user frames except for the stack frame
                % that calls into tall code.
                % This is to make gather errors more readable.
                toolboxPath = fullfile(matlabroot, 'toolbox');
                for ii = 1:numel(stack)
                    if ~strncmp(stack(ii).file, toolboxPath, numel(toolboxPath))
                        stack(ii + 2 : end) = [];
                        break;
                    end
                end
            end
        end
        
        % Helper function that attaches a submission functional stack to an
        % MException.
        %
        % Syntax:
        %   BigDataException.hAttachSubmissionStack(err, submissionStack)
        %   Prepends the attached submission stack to the error.
        %
        function err = hAttachSubmissionStack(err, submissionStack)
            import matlab.bigdata.BigDataException;
            if ~isa(err, 'matlab.bigdata.BigDataException')
                err = BigDataException(submissionStack, err);
            end
        end
        
        % Helper function that throws a given MATLAB MException but with
        % the stack of submission prepended to the error. This should be
        % used to stitch the stack of a line of code with an error that
        % occurred in deferred execution.
        %
        % The resulting stack will be:
        %
        % Error in tallMethod
        % Error in userMethodThatCalledTallFrame1
        % Error in gather
        % Error in userMethodThatCalledGatherFrame1
        % Error in userMethodThatCalledGatherFrame2
        % ...
        % Error in userMethodThatCalledGatherFrameN
        %
        % Syntax:
        %   BigDataException.hThrowAsCallerWithSubmissionStack(err) throws the
        %   given error as the caller, preserving any submit stack that has
        %   already be prepended to the error. Specifically, This will keep
        %   the submission stack but truncate the execution stack to the
        %   frame of the caller.
        %
        %   BigDataException.hThrowAsCallerWithSubmissionStack(err, submissionStack)
        %   Prepends the attached submission stack to the error and then
        %   proceeds to throw it as the caller. Specifically, this will
        %   truncate the execution stack to the frame of the caller and
        %   then prepend the submission stack.
        %
        %   BigDataException.hThrowAsCallerWithSubmissionStack(err, submissionStack, extraMsg)
        %   appends the string "extraMsg" to the end of the message of "err".
        %
        function hThrowAsCallerWithSubmissionStack(err, submissionStack, extraMsg)
            import matlab.bigdata.BigDataException;
            if nargin < 2
                submissionStack = [];
            end
            if nargin < 3
                extraMsg = '';
            end
            
            if ~isa(err, 'matlab.bigdata.BigDataException')
                err = BigDataException(submissionStack, err, extraMsg);
            else
                err = BigDataException(err.SubmissionStack, err, extraMsg);
            end
            throwWithMarkerFrame(err, 2);
        end
    end
    
    methods (Access = protected)
        % Override of the getStack method that replaces the exception stack
        % with one that has been prepended by a submission stack.
        function stack = getStack(obj)
            import matlab.bigdata.BigDataException;
            stack = getStack@MException(obj);
            
            % Only prepend the stack if 'BigDataException.throwWithMarkerFrame'
            % is still on the stack. This will be the case exactly until
            % throw or throwAsCaller are called.
            if ~isempty(stack) && isequal(stack(1).name, 'BigDataException.throwWithMarkerFrame')
                % Ignore frames that are internal to throwWithMarkerFrame
                stack(1 : min(obj.NumIgnoredFrames, end)) = [];
                
                stack = [obj.SubmissionStack; stack];
                
                if BigDataException.showFullStack()
                    stack = [obj.CalleeStack; stack];
                end
            end
        end
    end
    
    methods (Access = private)
        % Private constructor for static attach and throw methods.
        function obj = BigDataException(submissionStack, err, extraMessage)
            if nargin >= 3 && ~isempty(extraMessage)
                errText = sprintf('%s\n%s', err.message, extraMessage);
            else
                errText = err.message;
            end
            obj = obj@MException(err.identifier, '%s', errText);
            obj.SubmissionStack = submissionStack;
            if isa(err, 'matlab.bigdata.BigDataException')
                obj.CalleeStack = err.CalleeStack;
            else
                obj.CalleeStack = err.stack;
            end
            if ~isempty(err.cause)
                obj = addCause(obj, err.cause{1});
            end
        end
        
        % Private helper method that is intended to throw with the last
        % stack frame being "BigDataException.throwWithMarkerFrame".
        function throwWithMarkerFrame(err, numIgnoredFrames)
            err.NumIgnoredFrames = numIgnoredFrames + 1;
            throw(err);
        end
    end
    
    methods (Static, Hidden)
        % Static state that determines if errors thrown by this class
        % display the full stack or a user-friendly version.
        function out = showFullStack(in)
            persistent value;
            if ~nargin && ~nargout
                value = true;
            elseif isempty(value)
                value = false;
            end
            if nargout
                out = value;
            end
            if nargin
                value = in;
            end
        end
    end
end