Просмотр исходного кода

Compatibility with OTP 21.1 (#84)

* Erlang/OTP version 21 deprecated erlang:get_stacktrace/0. Now we use a macros for either catch C:E:T or get_stacktrace depending on OTP version.
* Erlang/OTP 20.0 has an error in binary pattern matching optimization, so 20.0 doesn't work.
* add erlang 21.1 in travis test matrix
* add ssl options
* start error_logger explicitly for erlang 21 in test suite
18年梦醒 6 лет назад
Родитель
Сommit
ef71b8fa24
5 измененных файлов с 44 добавлено и 12 удалено
  1. 1 0
      .travis.yml
  2. 9 0
      include/exception.hrl
  3. 10 8
      src/mysql.erl
  4. 17 3
      test/error_logger_acc.erl
  5. 7 1
      test/ssl_tests.erl

+ 1 - 0
.travis.yml

@@ -14,6 +14,7 @@ before_script:
   - mysql -uroot -e "grant all privileges on otptestssl.* to otptestssl@localhost identified by 'otptestssl' require ssl"
 script: 'make tests'
 otp_release:
+  - 21.1
   - 20.0
   - 19.0
   - 18.3

+ 9 - 0
include/exception.hrl

@@ -0,0 +1,9 @@
+-ifdef(OTP_RELEASE). %% this implies 21 or higher
+-define(EXCEPTION(Class, Reason, Stacktrace), Class:Reason:Stacktrace).
+-define(EXCEPTION(Class, Reason, Stacktrace, N), Class:Reason:Stacktrace when N >= 1).
+-define(GET_STACK(Stacktrace), Stacktrace).
+-else.
+-define(EXCEPTION(Class, Reason, _), Class:Reason).
+-define(EXCEPTION(Class, Reason, _, N), Class:Reason when N >= 1).
+-define(GET_STACK(_), erlang:get_stacktrace()).
+-endif.

+ 10 - 8
src/mysql.erl

@@ -25,6 +25,8 @@
 %% gen_server is locally registered.
 -module(mysql).
 
+-include("exception.hrl").
+
 -export([start_link/1, query/2, query/3, query/4, execute/3, execute/4,
          prepare/2, prepare/3, unprepare/2,
          warning_count/1, affected_rows/1, autocommit/1, insert_id/1,
@@ -392,28 +394,28 @@ execute_transaction(Conn, Fun, Args, Retries) ->
     catch
         %% We are at the top level, try to restart the transaction if there are
         %% retries left
-        throw:{implicit_rollback, 1, _} when Retries =:= infinity ->
+        ?EXCEPTION(throw, {implicit_rollback, 1, _}, _Stacktrace) when Retries =:= infinity ->
             execute_transaction(Conn, Fun, Args, infinity);
-        throw:{implicit_rollback, 1, _} when Retries > 0 ->
+        ?EXCEPTION(throw, {implicit_rollback, 1, _}, _Stacktrace) when Retries > 0 ->
             execute_transaction(Conn, Fun, Args, Retries - 1);
-        throw:{implicit_rollback, N, Reason} when N > 1 ->
+        ?EXCEPTION(throw, {implicit_rollback, N, Reason}, Stacktrace, N) ->
             erlang:raise(throw, {implicit_rollback, N - 1, Reason},
-                         erlang:get_stacktrace());
-        error:{implicit_commit, _Query} = E ->
+                         ?GET_STACK(Stacktrace));
+        ?EXCEPTION(error, {implicit_commit, _Query} = E, Stacktrace) ->
             %% The called did something like ALTER TABLE which resulted in an
             %% implicit commit. The server has already committed. We need to
             %% jump out of N levels of transactions.
             %%
             %% Returning 'atomic' or 'aborted' would both be wrong. Raise an
             %% exception is the best we can do.
-            erlang:raise(error, E, erlang:get_stacktrace());
-        Class:Reason ->
+            erlang:raise(error, E, ?GET_STACK(Stacktrace));
+        ?EXCEPTION(Class, Reason, Stacktrace) ->
             %% We must be able to rollback. Otherwise let's crash.
             ok = gen_server:call(Conn, rollback),
             %% These forms for throw, error and exit mirror Mnesia's behaviour.
             Aborted = case Class of
                 throw -> {throw, Reason};
-                error -> {Reason, erlang:get_stacktrace()};
+                error -> {Reason, ?GET_STACK(Stacktrace)};
                 exit  -> Reason
             end,
             {aborted, Aborted}

+ 17 - 3
test/error_logger_acc.erl

@@ -4,6 +4,8 @@
 %% returned along with the return value of the fun.
 -module(error_logger_acc).
 
+-include("exception.hrl").
+
 %% Public API
 -export([capture/1]).
 
@@ -22,6 +24,9 @@
        AccumulatedErrors :: [{error|warning_msg|info_msg, string()} |
                              {error_report|warning_report|info_report, term()}].
 capture(Fun) when is_function(Fun, 0) ->
+
+    start_error_logger(),
+
     OldHandlers = gen_event:which_handlers(error_logger),
     error_logger:add_report_handler(?MODULE),
     lists:foreach(fun error_logger:delete_report_handler/1, OldHandlers),
@@ -30,11 +35,10 @@ capture(Fun) when is_function(Fun, 0) ->
             lists:foreach(fun error_logger:add_report_handler/1, OldHandlers),
             {ok, Result, error_logger:delete_report_handler(?MODULE)}
     catch
-        Class:Error ->
-            Trace = erlang:get_stacktrace(),
+        ?EXCEPTION(Class, Error, Stacktrace) ->
             lists:foreach(fun error_logger:add_report_handler/1, OldHandlers),
             AccumulatedErrors = error_logger:delete_report_handler(?MODULE),
-            {Class, Error, Trace, AccumulatedErrors}
+            {Class, Error, ?GET_STACK(Stacktrace), AccumulatedErrors}
     end.
 
 %% --- gen_event callbacks ---
@@ -70,6 +74,16 @@ terminate(_Arg, _State) ->
 code_change(_OldVsn, State, _Extra) ->
     {ok, State}.
 
+%% error logger is no longer started since erlang 21, start it explicitly
+-ifdef(OTP_RELEASE).
+start_error_logger() ->
+    error_logger:start(),
+    logger:add_handler(error_logger,error_logger,#{level=>info,filter_default=>log}).
+-else.
+start_error_logger() ->
+    ok.
+-endif.
+
 -ifdef(TEST).
 -include_lib("eunit/include/eunit.hrl").
 

+ 7 - 1
test/ssl_tests.erl

@@ -24,10 +24,16 @@
 -define(ssl_user,     "otptestssl").
 -define(ssl_password, "otptestssl").
 -define(cacertfile,   "test/ssl/ca.pem").
+-define(certfile,     "test/ssl/server-cert.pem").
+-define(keyfile,      "test/ssl/server-key.pem").
 
 successful_ssl_connect_test() ->
     [ application:start(App) || App <- [crypto, asn1, public_key, ssl] ],
-    common_basic_check([{ssl, [{cacertfile, ?cacertfile}]},
+    common_basic_check([{ssl, [
+                        {server_name_indication, disable}, 
+                        {cacertfile, ?cacertfile}]},
+                        {certfile, ?certfile},
+                        {keyfile, ?keyfile},
                         {user, ?ssl_user}, {password, ?ssl_password}]),
     common_conn_close(),
     ok.