diff options
| -rw-r--r-- | .hgignore | 1 | ||||
| -rw-r--r-- | Makefile | 21 | ||||
| -rw-r--r-- | docs/rabbitmqctl.1.pod | 4 | ||||
| -rw-r--r-- | generate_deps | 52 | ||||
| -rw-r--r-- | src/rabbit.erl | 46 | ||||
| -rw-r--r-- | src/rabbit_amqqueue.erl | 5 | ||||
| -rw-r--r-- | src/rabbit_amqqueue_process.erl | 7 | ||||
| -rw-r--r-- | src/rabbit_exchange.erl | 5 | ||||
| -rw-r--r-- | src/rabbit_networking.erl | 12 | ||||
| -rw-r--r-- | src/rabbit_reader.erl | 5 | ||||
| -rw-r--r-- | src/rabbit_tests.erl | 20 | ||||
| -rw-r--r-- | src/vm_memory_monitor.erl | 36 |
12 files changed, 144 insertions, 70 deletions
@@ -4,6 +4,7 @@ syntax: glob *.swp *.patch erl_crash.dump +deps.mk syntax: regexp ^cover/ @@ -6,12 +6,14 @@ RABBITMQ_SERVER_START_ARGS ?= RABBITMQ_MNESIA_DIR ?= $(TMPDIR)/rabbitmq-$(RABBITMQ_NODENAME)-mnesia RABBITMQ_LOG_BASE ?= $(TMPDIR) +DEPS_FILE=deps.mk SOURCE_DIR=src EBIN_DIR=ebin INCLUDE_DIR=include -SOURCES=$(wildcard $(SOURCE_DIR)/*.erl) -BEAM_TARGETS=$(EBIN_DIR)/rabbit_framing.beam $(patsubst $(SOURCE_DIR)/%.erl, $(EBIN_DIR)/%.beam, $(SOURCES)) -TARGETS=$(EBIN_DIR)/rabbit.app $(BEAM_TARGETS) +INCLUDES=$(wildcard $(INCLUDE_DIR)/*.hrl) $(INCLUDE_DIR)/rabbit_framing.hrl +SOURCES=$(wildcard $(SOURCE_DIR)/*.erl) $(SOURCE_DIR)/rabbit_framing.erl +BEAM_TARGETS=$(patsubst $(SOURCE_DIR)/%.erl, $(EBIN_DIR)/%.beam, $(SOURCES)) +TARGETS=$(EBIN_DIR)/rabbit.app $(INCLUDE_DIR)/rabbit_framing.hrl $(BEAM_TARGETS) WEB_URL=http://stage.rabbitmq.com/ MANPAGES=$(patsubst %.pod, %.gz, $(wildcard docs/*.[0-9].pod)) @@ -58,13 +60,13 @@ ERL_EBIN=erl -noinput -pa $(EBIN_DIR) all: $(TARGETS) +$(DEPS_FILE): $(SOURCES) $(INCLUDES) + escript generate_deps $(INCLUDE_DIR) $(SOURCE_DIR) \$$\(EBIN_DIR\) $@ + $(EBIN_DIR)/rabbit.app: $(EBIN_DIR)/rabbit_app.in $(BEAM_TARGETS) generate_app escript generate_app $(EBIN_DIR) $@ < $< -$(EBIN_DIR)/gen_server2.beam: $(SOURCE_DIR)/gen_server2.erl - erlc $(ERLC_OPTS) $< - -$(EBIN_DIR)/%.beam: $(SOURCE_DIR)/%.erl $(INCLUDE_DIR)/rabbit_framing.hrl $(INCLUDE_DIR)/rabbit.hrl $(EBIN_DIR)/gen_server2.beam +$(EBIN_DIR)/%.beam: $(SOURCE_DIR)/%.erl erlc $(ERLC_OPTS) -pa $(EBIN_DIR) $< # ERLC_EMULATOR="erl -smp" erlc $(ERLC_OPTS) -pa $(EBIN_DIR) $< @@ -100,6 +102,7 @@ clean: rm -f $(INCLUDE_DIR)/rabbit_framing.hrl $(SOURCE_DIR)/rabbit_framing.erl codegen.pyc rm -f docs/*.[0-9].gz rm -f $(RABBIT_PLT) + rm -f $(DEPS_FILE) cleandb: rm -rf $(RABBITMQ_MNESIA_DIR)/* @@ -170,7 +173,7 @@ srcdist: distclean sed -i.save 's/%%VSN%%/$(VERSION)/' $(TARGET_SRC_DIR)/ebin/rabbit_app.in && rm -f $(TARGET_SRC_DIR)/ebin/rabbit_app.in.save cp -r $(AMQP_CODEGEN_DIR)/* $(TARGET_SRC_DIR)/codegen/ - cp codegen.py Makefile generate_app calculate-relative $(TARGET_SRC_DIR) + cp codegen.py Makefile generate_app generate_deps calculate-relative $(TARGET_SRC_DIR) cp -r scripts $(TARGET_SRC_DIR) cp -r docs $(TARGET_SRC_DIR) @@ -220,3 +223,5 @@ install: all docs_all install_dirs install_dirs: mkdir -p $(SBIN_DIR) mkdir -p $(TARGET_DIR)/sbin + +-include $(DEPS_FILE) diff --git a/docs/rabbitmqctl.1.pod b/docs/rabbitmqctl.1.pod index 5255be28a0..47c4d16860 100644 --- a/docs/rabbitmqctl.1.pod +++ b/docs/rabbitmqctl.1.pod @@ -284,7 +284,7 @@ separated by tab characters. =item list_connections [I<connectioninfoitem> ...] -List queue information by virtual host. Each line printed describes an +List current AMQP connections. Each line printed describes a connection, with the requested I<connectioninfoitem> values separated by tab characters. If no I<connectioninfoitem>s are specified then I<user>, I<peer_address>, I<peer_port> and I<state> are assumed. @@ -295,7 +295,7 @@ I<user>, I<peer_address>, I<peer_port> and I<state> are assumed. =over -=item node +=item pid id of the Erlang process associated with the connection diff --git a/generate_deps b/generate_deps new file mode 100644 index 0000000000..916006d101 --- /dev/null +++ b/generate_deps @@ -0,0 +1,52 @@ +#!/usr/bin/env escript +%% -*- erlang -*- +-mode(compile). + +main([IncludeDir, ErlDir, EbinDir, TargetFile]) -> + ErlDirContents = filelib:wildcard("*.erl", ErlDir), + ErlFiles = [filename:join(ErlDir, FileName) || FileName <- ErlDirContents], + Modules = sets:from_list( + [list_to_atom(filename:basename(FileName, ".erl")) || + FileName <- ErlDirContents]), + Headers = sets:from_list( + [filename:join(IncludeDir, FileName) || + FileName <- filelib:wildcard("*.hrl", IncludeDir)]), + Deps = lists:foldl( + fun (Path, Deps1) -> + dict:store(Path, detect_deps(IncludeDir, EbinDir, + Modules, Headers, Path), + Deps1) + end, dict:new(), ErlFiles), + {ok, Hdl} = file:open(TargetFile, [write, delayed_write]), + dict:fold( + fun (_Path, [], ok) -> + ok; + (Path, Dep, ok) -> + Module = filename:basename(Path, ".erl"), + ok = file:write(Hdl, [EbinDir, "/", Module, ".beam:"]), + ok = sets:fold(fun (E, ok) -> file:write(Hdl, [" ", E]) end, + ok, Dep), + file:write(Hdl, [" ", ErlDir, "/", Module, ".erl\n"]) + end, ok, Deps), + ok = file:write(Hdl, [TargetFile, ": ", escript:script_name(), "\n"]), + ok = file:sync(Hdl), + ok = file:close(Hdl). + +detect_deps(IncludeDir, EbinDir, Modules, Headers, Path) -> + {ok, Forms} = epp:parse_file(Path, [IncludeDir], [{use_specs, true}]), + lists:foldl( + fun ({attribute, _LineNumber, behaviour, Behaviour}, Deps) -> + case sets:is_element(Behaviour, Modules) of + true -> sets:add_element( + [EbinDir, "/", atom_to_list(Behaviour), ".beam"], + Deps); + false -> Deps + end; + ({attribute, _LineNumber, file, {FileName, _LineNumber1}}, Deps) -> + case sets:is_element(FileName, Headers) of + true -> sets:add_element(FileName, Deps); + false -> Deps + end; + (_Form, Deps) -> + Deps + end, sets:new(), Forms). diff --git a/src/rabbit.erl b/src/rabbit.erl index 76cd82a95b..bdb3a5d04a 100644 --- a/src/rabbit.erl +++ b/src/rabbit.erl @@ -51,17 +51,17 @@ -rabbit_boot_step({database, [{mfa, {rabbit_mnesia, init, []}}, - {pre, kernel_ready}]}). + {enables, kernel_ready}]}). -rabbit_boot_step({rabbit_log, [{description, "logging server"}, {mfa, {rabbit_sup, start_child, [rabbit_log]}}, - {pre, kernel_ready}]}). + {enables, kernel_ready}]}). -rabbit_boot_step({rabbit_hooks, [{description, "internal event notification system"}, {mfa, {rabbit_hooks, start, []}}, - {pre, kernel_ready}]}). + {enables, kernel_ready}]}). -rabbit_boot_step({kernel_ready, [{description, "kernel ready"}]}). @@ -69,27 +69,27 @@ -rabbit_boot_step({rabbit_alarm, [{description, "alarm handler"}, {mfa, {rabbit_alarm, start, []}}, - {post, kernel_ready}, - {pre, core_initialized}]}). + {requires, kernel_ready}, + {enables, core_initialized}]}). -rabbit_boot_step({rabbit_amqqueue_sup, [{description, "queue supervisor"}, {mfa, {rabbit_amqqueue, start, []}}, - {post, kernel_ready}, - {pre, core_initialized}]}). + {requires, kernel_ready}, + {enables, core_initialized}]}). -rabbit_boot_step({rabbit_router, [{description, "cluster router"}, {mfa, {rabbit_sup, start_child, [rabbit_router]}}, - {post, kernel_ready}, - {pre, core_initialized}]}). + {requires, kernel_ready}, + {enables, core_initialized}]}). -rabbit_boot_step({rabbit_node_monitor, [{description, "node monitor"}, {mfa, {rabbit_sup, start_child, [rabbit_node_monitor]}}, - {post, kernel_ready}, - {post, rabbit_amqqueue_sup}, - {pre, core_initialized}]}). + {requires, kernel_ready}, + {requires, rabbit_amqqueue_sup}, + {enables, core_initialized}]}). -rabbit_boot_step({core_initialized, [{description, "core initialized"}]}). @@ -97,27 +97,27 @@ -rabbit_boot_step({empty_db_check, [{description, "empty DB check"}, {mfa, {?MODULE, maybe_insert_default_data, []}}, - {post, core_initialized}]}). + {requires, core_initialized}]}). -rabbit_boot_step({exchange_recovery, [{description, "exchange recovery"}, {mfa, {rabbit_exchange, recover, []}}, - {post, empty_db_check}]}). + {requires, empty_db_check}]}). -rabbit_boot_step({queue_recovery, [{description, "queue recovery"}, {mfa, {rabbit_amqqueue, recover, []}}, - {post, exchange_recovery}]}). + {requires, exchange_recovery}]}). -rabbit_boot_step({persister, [{mfa, {rabbit_sup, start_child, [rabbit_persister]}}, - {post, queue_recovery}]}). + {requires, queue_recovery}]}). -rabbit_boot_step({guid_generator, [{description, "guid generator"}, {mfa, {rabbit_sup, start_child, [rabbit_guid]}}, - {post, persister}, - {pre, routing_ready}]}). + {requires, persister}, + {enables, routing_ready}]}). -rabbit_boot_step({routing_ready, [{description, "message delivery logic ready"}]}). @@ -125,12 +125,12 @@ -rabbit_boot_step({log_relay, [{description, "error log relay"}, {mfa, {rabbit_error_logger, boot, []}}, - {post, routing_ready}]}). + {requires, routing_ready}]}). -rabbit_boot_step({networking, [{mfa, {rabbit_networking, boot, []}}, - {post, log_relay}, - {pre, networking_listening}]}). + {requires, log_relay}, + {enables, networking_listening}]}). -rabbit_boot_step({networking_listening, [{description, "network listeners available"}]}). @@ -286,9 +286,9 @@ sort_boot_steps(UnsortedSteps) -> %% Add edges, detecting cycles and missing vertices. lists:foreach(fun ({StepName, Attributes}) -> [add_boot_step_dep(G, StepName, PrecedingStepName) - || {post, PrecedingStepName} <- Attributes], + || {requires, PrecedingStepName} <- Attributes], [add_boot_step_dep(G, SucceedingStepName, StepName) - || {pre, SucceedingStepName} <- Attributes] + || {enables, SucceedingStepName} <- Attributes] end, UnsortedSteps), %% Use topological sort to find a consistent ordering (if there is diff --git a/src/rabbit_amqqueue.erl b/src/rabbit_amqqueue.erl index 9e8e5d6cdb..db7461b09f 100644 --- a/src/rabbit_amqqueue.erl +++ b/src/rabbit_amqqueue.erl @@ -36,7 +36,7 @@ -export([pseudo_queue/2]). -export([lookup/1, with/2, with_or_die/2, stat/1, stat_all/0, deliver/2, redeliver/2, requeue/3, ack/4]). --export([list/1, info/1, info/2, info_all/1, info_all/2]). +-export([list/1, info_keys/0, info/1, info/2, info_all/1, info_all/2]). -export([claim_queue/2]). -export([basic_get/3, basic_consume/8, basic_cancel/4]). -export([notify_sent/2, unblock/2]). @@ -69,6 +69,7 @@ -spec(with/2 :: (queue_name(), qfun(A)) -> A | not_found()). -spec(with_or_die/2 :: (queue_name(), qfun(A)) -> A). -spec(list/1 :: (vhost()) -> [amqqueue()]). +-spec(info_keys/0 :: () -> [info_key()]). -spec(info/1 :: (amqqueue()) -> [info()]). -spec(info/2 :: (amqqueue(), [info_key()]) -> [info()]). -spec(info_all/1 :: (vhost()) -> [[info()]]). @@ -222,6 +223,8 @@ list(VHostPath) -> rabbit_queue, #amqqueue{name = rabbit_misc:r(VHostPath, queue), _ = '_'}). +info_keys() -> rabbit_amqqueue_process:info_keys(). + map(VHostPath, F) -> rabbit_misc:filter_exit_map(F, list(VHostPath)). info(#amqqueue{ pid = QPid }) -> diff --git a/src/rabbit_amqqueue_process.erl b/src/rabbit_amqqueue_process.erl index a3b0814cfa..06e68a1b16 100644 --- a/src/rabbit_amqqueue_process.erl +++ b/src/rabbit_amqqueue_process.erl @@ -39,7 +39,7 @@ -define(HIBERNATE_AFTER_MIN, 1000). -define(DESIRED_HIBERNATE, 10000). --export([start_link/1]). +-export([start_link/1, info_keys/0]). -export([init/1, terminate/2, code_change/3, handle_call/3, handle_cast/2, handle_info/2]). @@ -88,9 +88,10 @@ %%---------------------------------------------------------------------------- -start_link(Q) -> - gen_server2:start_link(?MODULE, Q, []). +start_link(Q) -> gen_server2:start_link(?MODULE, Q, []). +info_keys() -> ?INFO_KEYS. + %%---------------------------------------------------------------------------- init(Q) -> diff --git a/src/rabbit_exchange.erl b/src/rabbit_exchange.erl index c72ff7f9f7..33bfe89399 100644 --- a/src/rabbit_exchange.erl +++ b/src/rabbit_exchange.erl @@ -35,7 +35,7 @@ -include("rabbit_framing.hrl"). -export([recover/0, declare/5, lookup/1, lookup_or_die/1, - list/1, info/1, info/2, info_all/1, info_all/2, + list/1, info_keys/0, info/1, info/2, info_all/1, info_all/2, publish/2]). -export([add_binding/4, delete_binding/4, list_bindings/1]). -export([delete/2]). @@ -68,6 +68,7 @@ -spec(lookup/1 :: (exchange_name()) -> {'ok', exchange()} | not_found()). -spec(lookup_or_die/1 :: (exchange_name()) -> exchange()). -spec(list/1 :: (vhost()) -> [exchange()]). +-spec(info_keys/0 :: () -> [info_key()]). -spec(info/1 :: (exchange()) -> [info()]). -spec(info/2 :: (exchange(), [info_key()]) -> [info()]). -spec(info_all/1 :: (vhost()) -> [[info()]]). @@ -165,6 +166,8 @@ list(VHostPath) -> rabbit_exchange, #exchange{name = rabbit_misc:r(VHostPath, exchange), _ = '_'}). +info_keys() -> ?INFO_KEYS. + map(VHostPath, F) -> %% TODO: there is scope for optimisation here, e.g. using a %% cursor, parallelising the function invocation diff --git a/src/rabbit_networking.erl b/src/rabbit_networking.erl index 84be7918e9..06e2b40e47 100644 --- a/src/rabbit_networking.erl +++ b/src/rabbit_networking.erl @@ -32,10 +32,11 @@ -module(rabbit_networking). -export([boot/0, start/0, start_tcp_listener/2, start_ssl_listener/3, - stop_tcp_listener/2, on_node_down/1, active_listeners/0, - node_listeners/1, connections/0, connection_info/1, - connection_info/2, connection_info_all/0, - connection_info_all/1]). + stop_tcp_listener/2, on_node_down/1, active_listeners/0, + node_listeners/1, connections/0, connection_info_keys/0, + connection_info/1, connection_info/2, + connection_info_all/0, connection_info_all/1]). + %%used by TCP-based transports, e.g. STOMP adapter -export([check_tcp_listener_address/3]). @@ -70,6 +71,7 @@ -spec(active_listeners/0 :: () -> [listener()]). -spec(node_listeners/1 :: (erlang_node()) -> [listener()]). -spec(connections/0 :: () -> [connection()]). +-spec(connection_info_keys/0 :: () -> [info_key()]). -spec(connection_info/1 :: (connection()) -> [info()]). -spec(connection_info/2 :: (connection(), [info_key()]) -> [info()]). -spec(connection_info_all/0 :: () -> [[info()]]). @@ -214,6 +216,8 @@ connections() -> [Pid || {_, Pid, _, _} <- supervisor:which_children( rabbit_tcp_client_sup)]. +connection_info_keys() -> rabbit_reader:info_keys(). + connection_info(Pid) -> rabbit_reader:info(Pid). connection_info(Pid, Items) -> rabbit_reader:info(Pid, Items). diff --git a/src/rabbit_reader.erl b/src/rabbit_reader.erl index 503e2fb4ae..f5bdb98593 100644 --- a/src/rabbit_reader.erl +++ b/src/rabbit_reader.erl @@ -33,7 +33,7 @@ -include("rabbit_framing.hrl"). -include("rabbit.hrl"). --export([start_link/0, info/1, info/2]). +-export([start_link/0, info_keys/0, info/1, info/2]). -export([system_continue/3, system_terminate/4, system_code_change/4]). @@ -129,6 +129,7 @@ -ifdef(use_specs). +-spec(info_keys/0 :: () -> [info_key()]). -spec(info/1 :: (pid()) -> [info()]). -spec(info/2 :: (pid(), [info_key()]) -> [info()]). @@ -155,6 +156,8 @@ system_terminate(Reason, _Parent, _Deb, _State) -> system_code_change(Misc, _Module, _OldVsn, _Extra) -> {ok, Misc}. +info_keys() -> ?INFO_KEYS. + info(Pid) -> gen_server:call(Pid, info, infinity). diff --git a/src/rabbit_tests.erl b/src/rabbit_tests.erl index 66bdd4cdc7..833ccc2638 100644 --- a/src/rabbit_tests.erl +++ b/src/rabbit_tests.erl @@ -695,18 +695,10 @@ test_server_status() -> false, false, []), %% list queues - ok = info_action( - list_queues, - [name, durable, auto_delete, arguments, pid, - messages_ready, messages_unacknowledged, messages_uncommitted, - messages, acks_uncommitted, consumers, transactions, memory], - true), + ok = info_action(list_queues, rabbit_amqqueue:info_keys(), true), %% list exchanges - ok = info_action( - list_exchanges, - [name, type, durable, auto_delete, arguments], - true), + ok = info_action(list_exchanges, rabbit_exchange:info_keys(), true), %% list bindings ok = control_action(list_bindings, []), @@ -721,12 +713,8 @@ test_server_status() -> {ok, C} = gen_tcp:connect(H, P, []), timer:sleep(100), - ok = info_action( - list_connections, - [pid, address, port, peer_address, peer_port, state, - channels, user, vhost, timeout, frame_max, - recv_oct, recv_cnt, send_oct, send_cnt, send_pend], - false), + ok = info_action(list_connections, + rabbit_networking:connection_info_keys(), false), ok = gen_tcp:close(C), passed. diff --git a/src/vm_memory_monitor.erl b/src/vm_memory_monitor.erl index 91788caae8..02bd04991e 100644 --- a/src/vm_memory_monitor.erl +++ b/src/vm_memory_monitor.erl @@ -37,8 +37,6 @@ %% %% This module tries to warn Rabbit before such situations occur, so %% that it has a higher chance to avoid running out of memory. -%% -%% This code depends on Erlang os_mon application. -module(vm_memory_monitor). @@ -78,6 +76,7 @@ ('ignore' | {'error', any()} | {'ok', pid()})). -spec(update/0 :: () -> 'ok'). -spec(get_total_memory/0 :: () -> (non_neg_integer() | 'unknown')). +-spec(get_vm_limit/0 :: () -> (non_neg_integer() | 'unknown')). -spec(get_memory_limit/0 :: () -> (non_neg_integer() | 'undefined')). -spec(get_check_interval/0 :: () -> non_neg_integer()). -spec(set_check_interval/1 :: (non_neg_integer()) -> 'ok'). @@ -97,6 +96,9 @@ update() -> get_total_memory() -> get_total_memory(os:type()). +get_vm_limit() -> + get_vm_limit(os:type()). + get_check_interval() -> gen_server:call(?MODULE, get_check_interval, infinity). @@ -208,17 +210,26 @@ start_timer(Timeout) -> {ok, TRef} = timer:apply_interval(Timeout, ?MODULE, update, []), TRef. +%% According to http://msdn.microsoft.com/en-us/library/aa366778(VS.85).aspx +%% Windows has 2GB and 8TB of address space for 32 and 64 bit accordingly. +get_vm_limit({win32,_OSname}) -> + case erlang:system_info(wordsize) of + 4 -> 2*1024*1024*1024; %% 2 GB for 32 bits 2^31 + 8 -> 8*1024*1024*1024*1024 %% 8 TB for 64 bits 2^42 + end; + %% On a 32-bit machine, if you're using more than 2 gigs of RAM you're %% in big trouble anyway. -get_vm_limit() -> +get_vm_limit(_OsType) -> case erlang:system_info(wordsize) of - 4 -> 4294967296; %% 4 GB for 32 bits 2^32 - 8 -> 281474976710656 %% 256 TB for 64 bits 2^48 + 4 -> 4*1024*1024*1024; %% 4 GB for 32 bits 2^32 + 8 -> 256*1024*1024*1024*1024 %% 256 TB for 64 bits 2^48 %%http://en.wikipedia.org/wiki/X86-64#Virtual_address_space_details end. get_mem_limit(MemFraction, TotalMemory) -> - lists:min([trunc(TotalMemory * MemFraction), get_vm_limit()]). + AvMem = lists:min([TotalMemory, get_vm_limit()]), + trunc(AvMem * MemFraction). %%---------------------------------------------------------------------------- %% Internal Helpers @@ -250,11 +261,14 @@ get_total_memory({unix,freebsd}) -> PageCount * PageSize; get_total_memory({win32,_OSname}) -> - [Result|_] = os_mon_sysinfo:get_mem_info(), - {ok, [_MemLoad, TotPhys, _AvailPhys, - _TotPage, _AvailPage, _TotV, _AvailV], _RestStr} = - io_lib:fread("~d~d~d~d~d~d~d", Result), - TotPhys; + %% Due to the Erlang print format bug, on Windows boxes the memory size is + %% broken. For example Windows 7 64 bit with 4Gigs of RAM we get negative + %% memory size: + %% > os_mon_sysinfo:get_mem_info(). + %% ["76 -1658880 1016913920 -1 -1021628416 2147352576 2134794240\n"] + %% Due to this bug, we don't actually know anything. Even if the number is + %% postive we can't be sure if it's correct. + unknown; get_total_memory({unix, linux}) -> File = read_proc_file("/proc/meminfo"), |
