Merge branch 'stable'
Conflicts: src/rabbit_stomp_reader.erl
This commit is contained in:
		
						commit
						fcdd8ef3d5
					
				|  | @ -58,13 +58,13 @@ adapter_name(State) -> | ||||||
|        PeerAddr :: inet:ip_address(). |        PeerAddr :: inet:ip_address(). | ||||||
| 
 | 
 | ||||||
| -type process_frame_result() :: | -type process_frame_result() :: | ||||||
|     {ok, #proc_state{}} | |     {ok, term(), #proc_state{}} | | ||||||
|     {stop, term(), #proc_state{}}. |     {stop, term(), #proc_state{}}. | ||||||
| 
 | 
 | ||||||
| -spec process_frame(#stomp_frame{}, #proc_state{}) -> | -spec process_frame(#stomp_frame{}, #proc_state{}) -> | ||||||
|     process_frame_result(). |     process_frame_result(). | ||||||
| 
 | 
 | ||||||
| -spec flush_and_die(#proc_state{}) -> ok. | -spec flush_and_die(#proc_state{}) -> #proc_state{}. | ||||||
| 
 | 
 | ||||||
| -spec command({Command, Frame}, State) -> process_frame_result() | -spec command({Command, Frame}, State) -> process_frame_result() | ||||||
|     when Command :: string(), |     when Command :: string(), | ||||||
|  | @ -212,7 +212,7 @@ handle_exit(Conn, {shutdown, {connection_closing, | ||||||
|             State = #proc_state{connection = Conn}) -> |             State = #proc_state{connection = Conn}) -> | ||||||
|     amqp_death(Code, Explanation, State); |     amqp_death(Code, Explanation, State); | ||||||
| handle_exit(Conn, Reason, State = #proc_state{connection = Conn}) -> | handle_exit(Conn, Reason, State = #proc_state{connection = Conn}) -> | ||||||
|     send_error("AMQP connection died", "Reason: ~p", [Reason], State), |     _ = send_error("AMQP connection died", "Reason: ~p", [Reason], State), | ||||||
|     {stop, {conn_died, Reason}, State}; |     {stop, {conn_died, Reason}, State}; | ||||||
| 
 | 
 | ||||||
| handle_exit(Ch, {shutdown, {server_initiated_close, Code, Explanation}}, | handle_exit(Ch, {shutdown, {server_initiated_close, Code, Explanation}}, | ||||||
|  | @ -220,7 +220,7 @@ handle_exit(Ch, {shutdown, {server_initiated_close, Code, Explanation}}, | ||||||
|     amqp_death(Code, Explanation, State); |     amqp_death(Code, Explanation, State); | ||||||
| 
 | 
 | ||||||
| handle_exit(Ch, Reason, State = #proc_state{channel = Ch}) -> | handle_exit(Ch, Reason, State = #proc_state{channel = Ch}) -> | ||||||
|     send_error("AMQP channel died", "Reason: ~p", [Reason], State), |     _ = send_error("AMQP channel died", "Reason: ~p", [Reason], State), | ||||||
|     {stop, {channel_died, Reason}, State}; |     {stop, {channel_died, Reason}, State}; | ||||||
| handle_exit(Ch, {shutdown, {server_initiated_close, Code, Explanation}}, | handle_exit(Ch, {shutdown, {server_initiated_close, Code, Explanation}}, | ||||||
|             State = #proc_state{channel = Ch}) -> |             State = #proc_state{channel = Ch}) -> | ||||||
|  | @ -248,7 +248,7 @@ process_request(ProcessFun, SuccessFun, State) -> | ||||||
|           end, |           end, | ||||||
|     case Res of |     case Res of | ||||||
|         {ok, Frame, NewState = #proc_state{connection = Conn}} -> |         {ok, Frame, NewState = #proc_state{connection = Conn}} -> | ||||||
|             case Frame of |             _ = case Frame of | ||||||
|                     none -> ok; |                     none -> ok; | ||||||
|                     _    -> send_frame(Frame, NewState) |                     _    -> send_frame(Frame, NewState) | ||||||
|                 end, |                 end, | ||||||
|  | @ -449,14 +449,14 @@ server_cancel_consumer(ConsumerTag, State = #proc_state{subscriptions = Subs}) - | ||||||
|                      {ok,    {_, Id1}} -> Id1; |                      {ok,    {_, Id1}} -> Id1; | ||||||
|                      {error, {_, Id1}} -> "Unknown[" ++ Id1 ++ "]" |                      {error, {_, Id1}} -> "Unknown[" ++ Id1 ++ "]" | ||||||
|                  end, |                  end, | ||||||
|             send_error_frame("Server cancelled subscription", |             _ = send_error_frame("Server cancelled subscription", | ||||||
|                                  [{?HEADER_SUBSCRIPTION, Id}], |                                  [{?HEADER_SUBSCRIPTION, Id}], | ||||||
|                                  "The server has canceled a subscription.~n" |                                  "The server has canceled a subscription.~n" | ||||||
|                                  "No more messages will be delivered for ~p.~n", |                                  "No more messages will be delivered for ~p.~n", | ||||||
|                                  [Description], |                                  [Description], | ||||||
|                                  State), |                                  State), | ||||||
|             tidy_canceled_subscription(ConsumerTag, Subscription, |             tidy_canceled_subscription(ConsumerTag, Subscription, | ||||||
|                                        #stomp_frame{}, State) |                                        undefined, State) | ||||||
|     end. |     end. | ||||||
| 
 | 
 | ||||||
| cancel_subscription({error, invalid_prefix}, _Frame, State) -> | cancel_subscription({error, invalid_prefix}, _Frame, State) -> | ||||||
|  | @ -495,6 +495,15 @@ cancel_subscription({ok, ConsumerTag, Description}, Frame, | ||||||
|             end |             end | ||||||
|     end. |     end. | ||||||
| 
 | 
 | ||||||
|  | %% Server-initiated cancelations will pass an undefined instead of a | ||||||
|  | %% STOMP frame. In this case we know that the queue was deleted and | ||||||
|  | %% thus we don't have to clean it up. | ||||||
|  | tidy_canceled_subscription(ConsumerTag, _Subscription, | ||||||
|  |                            undefined, State = #proc_state{subscriptions = Subs}) -> | ||||||
|  |     Subs1 = dict:erase(ConsumerTag, Subs), | ||||||
|  |     ok(State#proc_state{subscriptions = Subs1}); | ||||||
|  | 
 | ||||||
|  | %% Client-initiated cancelations will pass an actual frame | ||||||
| tidy_canceled_subscription(ConsumerTag, #subscription{dest_hdr = DestHdr}, | tidy_canceled_subscription(ConsumerTag, #subscription{dest_hdr = DestHdr}, | ||||||
|                            Frame, State = #proc_state{subscriptions = Subs}) -> |                            Frame, State = #proc_state{subscriptions = Subs}) -> | ||||||
|     Subs1 = maps:remove(ConsumerTag, Subs), |     Subs1 = maps:remove(ConsumerTag, Subs), | ||||||
|  | @ -663,8 +672,8 @@ do_subscribe(Destination, DestHdr, Frame, | ||||||
|                 {ok, _} -> |                 {ok, _} -> | ||||||
|                     Message = "Duplicated subscription identifier", |                     Message = "Duplicated subscription identifier", | ||||||
|                     Detail = "A subscription identified by '~s' alredy exists.", |                     Detail = "A subscription identified by '~s' alredy exists.", | ||||||
|                     error(Message, Detail, [ConsumerTag], State), |                     _ = error(Message, Detail, [ConsumerTag], State), | ||||||
|                     send_error(Message, Detail, [ConsumerTag], State), |                     _ = send_error(Message, Detail, [ConsumerTag], State), | ||||||
|                     {stop, normal, close_connection(State)}; |                     {stop, normal, close_connection(State)}; | ||||||
|                 error -> |                 error -> | ||||||
|                     ExchangeAndKey = |                     ExchangeAndKey = | ||||||
|  | @ -1049,7 +1058,7 @@ ensure_heartbeats(Heartbeats) -> | ||||||
|     {SendTimeout, ReceiveTimeout} = |     {SendTimeout, ReceiveTimeout} = | ||||||
|         {millis_to_seconds(CY), millis_to_seconds(CX)}, |         {millis_to_seconds(CY), millis_to_seconds(CX)}, | ||||||
| 
 | 
 | ||||||
|     rabbit_stomp_reader:start_heartbeats(self(), {SendTimeout, ReceiveTimeout}), |     _ = rabbit_stomp_reader:start_heartbeats(self(), {SendTimeout, ReceiveTimeout}), | ||||||
|     {SendTimeout * 1000 , ReceiveTimeout * 1000}. |     {SendTimeout * 1000 , ReceiveTimeout * 1000}. | ||||||
| 
 | 
 | ||||||
| millis_to_seconds(M) when M =< 0   -> 0; | millis_to_seconds(M) when M =< 0   -> 0; | ||||||
|  |  | ||||||
|  | @ -52,7 +52,7 @@ start_link(SupHelperPid, Ref, Sock, Configuration) -> | ||||||
|     %% meaningless synchronous call to the underlying gen_event |     %% meaningless synchronous call to the underlying gen_event | ||||||
|     %% mechanism. When it returns the mailbox is drained, and we |     %% mechanism. When it returns the mailbox is drained, and we | ||||||
|     %% return to our caller to accept more connections. |     %% return to our caller to accept more connections. | ||||||
|     gen_event:which_handlers(error_logger), |     _ = gen_event:which_handlers(error_logger), | ||||||
| 
 | 
 | ||||||
|     {ok, Pid}. |     {ok, Pid}. | ||||||
| 
 | 
 | ||||||
|  | @ -80,7 +80,7 @@ init([SupHelperPid, Ref, Sock, Configuration]) -> | ||||||
|                 [self(), ConnStr]), |                 [self(), ConnStr]), | ||||||
| 
 | 
 | ||||||
|             ParseState = rabbit_stomp_frame:initial_state(), |             ParseState = rabbit_stomp_frame:initial_state(), | ||||||
|             register_resource_alarm(), |             _ = register_resource_alarm(), | ||||||
|             gen_server2:enter_loop(?MODULE, [], |             gen_server2:enter_loop(?MODULE, [], | ||||||
|               rabbit_event:init_stats_timer( |               rabbit_event:init_stats_timer( | ||||||
|                 run_socket(control_throttle( |                 run_socket(control_throttle( | ||||||
|  | @ -275,15 +275,18 @@ run_socket(State = #reader_state{state = blocked}) -> | ||||||
| run_socket(State = #reader_state{recv_outstanding = true}) -> | run_socket(State = #reader_state{recv_outstanding = true}) -> | ||||||
|     State; |     State; | ||||||
| run_socket(State = #reader_state{socket = Sock}) -> | run_socket(State = #reader_state{socket = Sock}) -> | ||||||
|     rabbit_net:async_recv(Sock, 0, infinity), |     _ = rabbit_net:async_recv(Sock, 0, infinity), | ||||||
|     State#reader_state{recv_outstanding = true}. |     State#reader_state{recv_outstanding = true}. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | terminate(Reason, undefined) -> | ||||||
|  |     log_reason(Reason, undefined), | ||||||
|  |     {stop, Reason}; | ||||||
| terminate(Reason, State = #reader_state{ processor_state = ProcState }) -> | terminate(Reason, State = #reader_state{ processor_state = ProcState }) -> | ||||||
|   maybe_emit_stats(State), |   maybe_emit_stats(State), | ||||||
|   log_reason(Reason, State), |   log_reason(Reason, State), | ||||||
|   rabbit_stomp_processor:flush_and_die(ProcState), |   _ = rabbit_stomp_processor:flush_and_die(ProcState), | ||||||
|   ok. |     {stop, Reason}. | ||||||
| 
 | 
 | ||||||
| code_change(_OldVsn, State, _Extra) -> | code_change(_OldVsn, State, _Extra) -> | ||||||
|     {ok, State}. |     {ok, State}. | ||||||
|  | @ -331,12 +334,14 @@ log_reason({shutdown, client_heartbeat_timeout}, | ||||||
| log_reason(normal, #reader_state{ conn_name  = ConnName}) -> | log_reason(normal, #reader_state{ conn_name  = ConnName}) -> | ||||||
|     log(info, "closing STOMP connection ~p (~s)~n", [self(), ConnName]); |     log(info, "closing STOMP connection ~p (~s)~n", [self(), ConnName]); | ||||||
| 
 | 
 | ||||||
|  | log_reason(shutdown, undefined) -> | ||||||
|  |     log(error, "closing STOMP connection that never completed connection handshake (negotiation)~n", []); | ||||||
|  | 
 | ||||||
| log_reason(Reason, #reader_state{ processor_state = ProcState }) -> | log_reason(Reason, #reader_state{ processor_state = ProcState }) -> | ||||||
|     AdapterName = rabbit_stomp_processor:adapter_name(ProcState), |     AdapterName = rabbit_stomp_processor:adapter_name(ProcState), | ||||||
|     rabbit_log:warning("STOMP connection ~s terminated" |     rabbit_log:warning("STOMP connection ~s terminated" | ||||||
|                        " with reason ~p, closing it~n", [AdapterName, Reason]). |                        " with reason ~p, closing it~n", [AdapterName, Reason]). | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| %%---------------------------------------------------------------------------- | %%---------------------------------------------------------------------------- | ||||||
| 
 | 
 | ||||||
| processor_args(Configuration, Sock) -> | processor_args(Configuration, Sock) -> | ||||||
|  | @ -417,8 +422,8 @@ info_internal(SockStat, #reader_state{socket = Sock}) when SockStat =:= recv_oct | ||||||
|                                                            SockStat =:= send_cnt; |                                                            SockStat =:= send_cnt; | ||||||
|                                                            SockStat =:= send_pend -> |                                                            SockStat =:= send_pend -> | ||||||
|     case rabbit_net:getstat(Sock, [SockStat]) of |     case rabbit_net:getstat(Sock, [SockStat]) of | ||||||
|         {ok, [{_, I}]} -> I; |         {ok, [{_, N}]} when is_number(N) -> N; | ||||||
|         {error, _} -> '' |         _ -> 0 | ||||||
|     end; |     end; | ||||||
| info_internal(state, State) -> info_internal(connection_state, State); | info_internal(state, State) -> info_internal(connection_state, State); | ||||||
| info_internal(garbage_collection, _State) -> | info_internal(garbage_collection, _State) -> | ||||||
|  |  | ||||||
|  | @ -383,7 +383,6 @@ subscription_queue_name(Destination, SubscriptionId, Frame) -> | ||||||
| %% ---- Helpers ---- | %% ---- Helpers ---- | ||||||
| 
 | 
 | ||||||
| split([],      _Splitter) -> []; | split([],      _Splitter) -> []; | ||||||
| split(Content, [])        -> Content; |  | ||||||
| split(Content, Splitter)  -> split(Content, [], [], Splitter). | split(Content, Splitter)  -> split(Content, [], [], Splitter). | ||||||
| 
 | 
 | ||||||
| split([], RPart, RParts, _Splitter) -> | split([], RPart, RParts, _Splitter) -> | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue