[thrift] gut Erlang exception handling
Summary: * move type field to tException from subclasses
* add backtrace to tException
* add oop:is_a
* on exit, wrap exceptions in {thrift_exception, E} ... otherwise can't distinguish e.g. exit:{{tBinProtException, {tException, ...}}, Stack} vs. exit:{tBinProtException, {tException, ...} -- I hate erlang
* all throws/exits to tException:throw which does the wrapping described above
Reviewed By: eletuchy
Test Plan: been using this code on my live server ^_^
Revert: OK
git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@665350 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/erl/src/tException.erl b/lib/erl/src/tException.erl
index 0ec4c94..6dd3084 100644
--- a/lib/erl/src/tException.erl
+++ b/lib/erl/src/tException.erl
@@ -1,31 +1,36 @@
%%% Copyright (c) 2007- Facebook
%%% Distributed under the Thrift Software License
-%%%
+%%%
%%% See accompanying file LICENSE or visit the Thrift site at:
%%% http://developers.facebook.com/thrift/
-module(tException).
-include("oop.hrl").
+-include("thrift.hrl").
-include("tException.hrl").
-behavior(oop).
-export([attr/4, super/0, inspect/1]).
--export([new/1]).
+-export([new/2, add_backtrace_element/2, throw/2, inspect_with_backtrace/2, inspect_with_backtrace/3]).
+
+-export([read/1]).
%%%
%%% define attributes
%%% 'super' is required unless ?MODULE is a base class
%%%
-?DEFINE_ATTR(message).
-
+?DEFINE_ATTR(message);
+?DEFINE_ATTR(type);
+?DEFINE_ATTR(backtrace).
+
%%%
%%% behavior callbacks
%%%
-
+
%%% super() -> SuperModule = atom()
%%% | none
@@ -35,16 +40,54 @@
%%% inspect(This) -> string()
inspect(This) ->
- ?FORMAT_ATTR(message).
+ BT = ?ATTR(backtrace),
+ Depth =
+ if
+ is_list(BT) -> integer_to_list(length(BT));
+ true -> "?"
+ end,
+ ?FORMAT_ATTR(message) ++ ", " ++
+ ?FORMAT_ATTR(type) ++ ", "
+ " backtrace:" ++ Depth.
%%%
%%% class methods
%%%
-new(Message) ->
- #?MODULE{message=Message}.
+new(Type, Message) ->
+ #?MODULE{type=Type, message=Message, backtrace=[]}.
-%%%
-%%% instance methods
-%%%
+add_backtrace_element(E, Info) ->
+ BT = oop:get(E, backtrace),
+ E1 = oop:set(E, backtrace, [Info|BT]),
+ E1.
+throw(Class, Args) ->
+ E = apply(Class, new, Args),
+ exit({thrift_exception, E}).
+
+
+inspect_with_backtrace(E, Where, Info) ->
+ E1 = add_backtrace_element(E, Info),
+ inspect_with_backtrace(E1, Where).
+
+inspect_with_backtrace(E, Where) ->
+ thrift_utils:sformat("** ~s~n** ~s", [Where, oop:inspect(E)]) ++
+ case oop:get(E, backtrace) of
+ [] ->
+ "";
+ BT when is_list(BT) ->
+ thrift_utils:sformat("~n** trace = ~p", [lists:reverse(BT)]);
+ Else ->
+ thrift_utils:sformat("<ERROR BT NOT A LIST = ~p>", [Else])
+ end.
+
+read(E) ->
+ case oop:class(E) of
+ none ->
+ none;
+ Class ->
+ Type = oop:get(E, type),
+ BT = oop:get(E, backtrace),
+ {Class, Type, BT}
+ end.