AMQP client for Erlang
This code implements a client for AMQP in the Erlang programming

This client offers both a networked version that uses standard
TCP-based AMQP framing and a direct client that uses native Erlang
message passing to a RabbitMQ broker.

The API exposed to the user is common to both clients, so each version
can be used interchangeably without having to modify any client code.

The TCP networked client has been tested with RabbitMQ server 1.4.0,
but should theoretically work with any 0-8 compliant AMQP server.

The direct client is bound to an 0-8 compliant broker using native
Erlang message passing, which in the absence of an alternative Erlang
AMQP implementation means that it only works with RabbitMQ.

It does however provide a level of abstraction above the internal
server API of RabbitMQ, meaning that you can write client code in
Erlang and still remain isolated from any API changes in the
underlying broker.

It also provides a client-orientated API into RabbitMQ, allowing the
user to reuse AMQP knowledge gained by using AMQP clients in other

The advantage of the direct client is that it eliminates the network
overhead as well as the marshaling to and from the AMQP wire format,
so that neither side has to decode or encode any AMQP frames.

In order to compile/run this code you must have the following

- Erlang/OTP, R11B-5 or later,
- The RabbitMQ server, 93cc2ca0ba62 or later
- Eunit, the Erlang unit testing framework - currently the whole build process
  depends on eunit because all of the modules are compiled together.
  A future version of the build process could remove this dependency when you
  only want to compile the core libraries.

Getting Eunit
The test suite uses eunit which is either available bundled with OTP from
release R12B-5 onwards or as a separate download that you will need to build
yourself if you are using an older version of Erlang.

* If you are using R12B-5 or newer:

Just skip to the next section.

* If you are using R12B-4 or older:

Check out eunit from their Subversion repository and build it:

    $ svn co eunit
    $ cd eunit
    $ make

After this has sucessfully been built, you will need to create a symlink to
the eunit directory in your OTP installation directory:

    $ cd $OTP_HOME/lib/erlang/lib
    $ ln -sf PATH_TO_EUNIT eunit

where $OTP_HOME is the location of your Erlang/OTP installation.

Compiling the Erlang client
You will need to get a copy of the server in order to be able to use it's
header files and runtime libraries. A good place to put this is in the sibling
directory to the Erlang client (i.e: ../rabbitmq-server), which is the default
that the Makefile expects. In this case, you can just run make:

    $ make

If the source tree for the server is not in the sibling directory, you will
need to specify the path to this directory:

    $ make BROKER_DIR=/path/to/server

In this case, make sure you specify BROKER_DIR every time you run a make target.

Running the network client, direct client and packaging tests
The direct client has to be run in the same Erlang VM instance as the
RabbitMQ server. In order to use the makefile to run tests, you will need to
shutdown any other running instance of RabbitMQ server that you may have on
your machine. This is because the Makefile test targets boot their own instance
of RabbitMQ with settings depending on the test.
To run these tests, use either of the following targets:

    $ make test_network
    $ make test_direct
    $ make test_common_package

Or to run all tests:

    $ make all_tests

If any test fails, the make command will return a non-zero exit code. The reason
is logged by the server in /tmp/rabbit-sasl.log by default.

The network client test can also be run from a separate Erlang VM instance from
RabbitMQ server. You can *start an instance of the server* and then, in the
rabbitmq-erlang-client folder, type

    rabbitmq-erlang-client $ make compile_tests
    rabbitmq-erlang-client $ make run
    erl -pa ebin ../rabbitmq-server/ebin tests
    Erlang (BEAM) emulator version 5.6.5 [source] [64-bit] [smp:4] \
    [async-threads:0] [hipe] [kernel-poll:false]

    Eshell V5.6.5  (abort with ^G)
    1> network_client_SUITE:test().

To get more examples of the API, look at the functions in the test_util module.

Running the channel flow tests
There are two tests for producer control flow. The first is a unit
test that asserts the reception of the correct chain of commands in
conjunction with a direct manipulation of the high water mark. The
second test does not make any assertion about the behavior of the
server but it does produce output that demonstrates that the client
library is indeed notifying higher level application code that flow
control has been activated or deactivated.

Both tests require that the memory alarms are turned on in the
server. By default they are turned off. To turn them on, set the
memory_alarms flag in the config file.

First of all, in the *rabbitmq-erlang-client directory*, type

    rabbitmq-erlang-client $ make compile_tests

to make sure test modules are compiled.

Because the unit test accesses memsup directly, it needs to use the
direct API and hence needs to run in the same VM as the server. To do
this from the *rabbitmq-erlang-client directory*, type

    rabbitmq-erlang-client $ make run_in_broker
When that has booted, you need to *wait one minute* for the memory
alarms to become active. After that, you can run the following from
the Erlang shell:

    1> direct_client_SUITE:test_channel_flow().

The non-unit test can be run in separate VM, because it uses the
network client driver. Whilst it can be run using the direct client,
it produces log output which makes it difficult to enter in commands
interactively (which you need to do to see the throttling).

After *having booted* an *instance of the server* with alarms handlers
turned on, run the following in the *rabbitmq-erlang-client directory*:

    rabbitmq-erlang-client $ make compile_tests
    rabbitmq-erlang-client $ make run
    Erlang (BEAM) emulator version 5.6.3 [source] [smp:2] \

    Eshell V5.6.3  (abort with ^G)
    1> P = #amqp_params{}.
    2> test_util:channel_flow_sync(amqp_connection:start_network(P)).

After having done this, you should see output similar to this:
    Producer (<0.39.0>) has sent about 0 messages since it started
    Producer (<0.39.0>) has sent about 5000 messages since it started
    Producer (<0.39.0>) has sent about 10000 messages since it started
To throttle the producer, go to the *server shell* and turn the memory
limit to some suitably low value:
    2> memsup:set_sysmem_high_watermark(0.01).
Back in the *client shell*, you should see the following output:
    Producer (<0.39.0>) has sent about 235000 messages since it started
    Producer throttling ON
    Producer (<0.39.0>) is blocked, will go to sleep.....ZZZ
If you now set the high water mark to say 99%, the producer should
wake up again:

    Producer throttling OFF, waking up producer (<0.39.0>)
    Producer (<0.39.0>) has woken up :-)
    Producer (<0.39.0>) has sent about 240000 messages since it started

Make targets
Interesting rabbitmq-erlang-client make targets include

    The default target. Builds the client (does not compile the tests).

    Builds the client.

    Builds the client test modules.

    Builds the client and starts an Erlang shell with both the client and the
    server in the load path.

    Builds the client and starts RabbitMQ server with shell and the client
    included in load path.

    Removes build products and wipes all files produced by any other
    rabbitmq-erlang-client make targets or client errors.

    Analyses the client source code with dialyzer. Uses PLT file from default
    location: ~/.dialyzer_plt. Use

        $ make PLT=/path/to/plt dialyze

    to override this. Add broker to PLT beforehand, otherwise you will a lot
    of 'unknown function' warnings. See add_broker_to_plt make target.

    Same as dialyze, except that this also analyses tests source code.

    Adds broker .beam files to default plt. Use

        $ make PLT=/path/to/plt add_broker_to_plt

    to override default plt location ( ~/.dialyzer_plt ).

    Creates tarball of all the client source code.

    Creates an erlang archive of the client.

    Creates an erlang archive of the server modules required by the erlang

    Clean compiles the client and client tests source code and runs
    network_client_SUITE, direct_client_SUITE and packaging tests. During the
    testing, this make target runs an instance of the broker, so make sure
    there is no other instance of RabbitMQ server running.