Commits

Anonymous committed 7e3890f Merge

integrate rebar build and embedded node changes

Comments (0)

Files changed (530)

 ^client_lib/java/javadoc/*
 test\.log
 ^test/.*
-^data/.*
+^data/.*
+.*/.eunit/.*
+^rel/riak/.*
+^dev/.*

Emakefile

-% -*- mode: erlang -*-
-{["src/gen_server2.erl", "src/*"], 
- [{i, "include"},
-  {outdir, "ebin"},
-  debug_info]
-}.
-ERL          ?= erl
-EBIN_DIRS    := $(wildcard deps/*/ebin)
-APP          := riak
+.PHONY: rel
 
-all:  webmachine erl 
+all: compile
 
-erl: ebin/$(APP).app
-	@$(ERL) -pa ebin -pa $(EBIN_DIRS) -noinput +B \
-	  -eval 'case make:all() of up_to_date -> halt(0); error -> halt(1) end.'
+compile:
+	./rebar compile
 
-webmachine:
-	@(cd deps/webmachine;$(MAKE))
+clean:
+	./rebar clean
 
+distclean: clean devclean relclean
+
+test: 
+	./rebar eunit
+
+##
+## Release targets
+##
+rel:
+	./rebar compile generate 
+
+relclean:
+	rm -rf rel/riak
+
+##
+## Developer targets
+##
+
+devrel: dev1 dev2 dev3
+
+dev: 
+	mkdir dev
+	cp -R rel/overlay rel/reltool.config dev
+	./rebar compile && cd dev && ../rebar generate
+
+dev1 dev2 dev3: dev
+	cp -Rn dev/riak dev/$@
+	$(foreach app,$(wildcard apps/*), rm -rf dev/$@/lib/$(shell basename $(app))* && ln -sf $(abspath $(app)) dev/$@/lib;)
+	perl -pi -e 's/name riak/name $@/g' dev/$@/etc/vm.args
+	perl -pi -e 's/riak_web_port, \d+/riak_web_port, 809$(subst dev,,$@)/g' \
+                    dev/$@/etc/app.config
+
+devclean: clean
+	rm -rf dev
+
+##
+## Doc targets
+##
 docs:
-	@erl -noshell -run edoc_run application '$(APP)' '"."' '[]'
-	@cp -r doc/* www/edoc
-	@cp README www/
-	@cp LICENSE www/
-	@cp TODO www/
+	@erl -noshell -run edoc_run application riak '"apps/riak"' '[]' 
+	@cp -R apps/riak/doc doc/riak
 
 reldocs: docs
+	@mkdir -p www/java_client_api
 	@cd client_lib/java && make javadoc && \
-		cp -r javadoc/* ../../www/java_client_api
+            cp -R javadoc/* ../../www/java_client_api
 
 
-clean:
-	@echo "removing:"
-	@rm -fv ebin/*.beam ebin/*.app
+dialyzer: compile
+	@dialyzer -Wno_return -c apps/riak/ebin
 
-ebin/$(APP).app: src/$(APP).app.src
-	@echo "generating ebin/riak.app"
-	@bash scripts/make_appfile.sh >ebin/riak.app	
 
-dialyzer: erl 
-	@dialyzer -Wno_return -c ebin/ | tee priv/log/dialyzer.log
-
-test: erl
-	scripts/run_tests.escript ebin | tee test.log
-
-Welcome to Riak.
+                                Welcome to Riak.
+                                ================
 
-Riak is a distributed, decentralized data storage system.
 
-Below, you will find the "quick start" directions for setting up and
-using Riak.  For more information, browse the following files:
 
- README:  this file
- TODO:    a list of improvements planned for Riak
- LICENSE: the license under which Riak is released
- *.sh:    various startup scripts
- riak_demo.escript:  demo for a base level of Riak functionality
- doc/
-   basic-setup.txt:  slightly more detail on setting up Riak
-   basic-client.txt: slightly more detail on using Riak
-   architecture.txt: details about the underlying design of Riak,
-                     and how this affects applications using it
-   index.html:       the root of the edoc output of 'make docs'
- src/
-   *.erl:            the source for Riak (it's friendly)
- config/
-   *.erlenv:         example configuration files
 
+Table of Contents
+=================
+1 Overview 
+2 Quick Start 
+    2.1 Building Riak 
+    2.2 Starting Riak 
+    2.3 Connecting a client to Riak 
+3 Server Management 
+    3.1 Configuration 
+    3.2 Server Control 
+        3.2.1 bin/riak 
+        3.2.2 bin/riak-admin 
 
-Quick Start
----
 
-This section assumes that you have copy of the Riak source tree at
-$RIAK.  You should have created this by cloning a repo or expanding
-a tarball from somewhere.
+1 Overview 
+~~~~~~~~~~~
+  Riak is a distributed, decentralized data storage system. 
+  
+  Below, you will find the "quick start" directions for setting up and
+  using Riak.  For more information, browse the following files:
+  
+  * README:  this file
+  * TODO:    a list of improvements planned for Riak
+  * LICENSE: the license under which Riak is released
+  * apps/    the source tree for Riak and all its dependencies
+  * doc/
+    - basic-setup.txt:  slightly more detail on setting up Riak
+    - basic-client.txt: slightly more detail on using Riak
+    - architecture.txt: details about the underlying design of Riak
+    - index.html:       the root of the edoc output of 'make docs'
 
-The quick start goes like this:
 
-1. Build Riak
-2. Start the Riak server
-3. Connect a client and store/fetch data
+2 Quick Start 
+~~~~~~~~~~~~~~
 
+  This section assumes that you have copy of the Riak source tree. To get
+  started, you need to:
+  1. Build Riak
+  2. Start the Riak server
+  3. Connect a client and store/fetch data
 
-1. Build Riak
--
-Assuming you have a working Erlang (R13 or later) installation,
-building Riak should be as simple as:
+2.1 Building Riak 
+==================
 
-$ cd $RIAK
-$ make
+   Assuming you have a working Erlang (R13B03 or later) installation,
+   building Riak should be as simple as:
 
+   $ cd $RIAK
+   $ make all rel
 
-2. Start the Riak server - Assuming no errors were generated in the
-build step, $RIAK/config/riak-demo.erlenv and replace all instances of
-$RIAK with the directory in which $RIAK is installed.  For example,
-change:
+2.2 Starting Riak 
+==================
 
-{riak_heart_command, "(cd $RIAK; ./start-restart.sh $RIAK/config/riak-demo.erlenv)"}.
+   Once you have successfully built Riak, you can start the server with the
+   following commands:
 
-to:
+   $ cd $RIAK/rel/riak
+   $ bin/riak start
 
-{riak_heart_command, "(cd /usr/local/riak; ./start-restart.sh /usr/local/riak/config/riak-demo.erlenv)"}.
+   Now, verify that the server started up cleanly and is working:
 
-Then start riak:
+   $ bin/riak-admin test
 
-$ cd $RIAK
-$ ./start-fresh.sh config/riak-demo.erlenv
+   Note that the $RIAK/rel/riak directory is a complete, self-contained instance
+   of Riak and Erlang. It is strongly suggested that you move this directory
+   outside the source tree if you plan to run a production instance.
 
-The server should start, then background itself, leaving you at a
-command prompt.
+2.3 Connecting a client to Riak 
+================================
 
-At this point, you can use riak_demo.escript to ensure that Riak is
-functioning:
+   Now that you have a functional server, let's try storing some data in
+   it. First, start up a erlang node using our embedded version of erlang:
 
-$ ./riak_demo.escript config/riak-demo.erlenv
-Attempting to connect to 127.0.0.1:9000 with cookie riak_demo_cookie...
-Connected successfully
-Looking for pre-existing object at {riak_demo, "demo"}...
-  No pre-existing object found, creating new
-Storing object with new value...
-  Written successfully
-Fetching object at {riak_demo, "demo"}...
-  Fetched successfully
-  Object contained correct value
-SUCCESS
+   $ erts-<vsn>/bin/erl -name riaktest -setcookie riak
+   
+   Eshell V5.7.4  (abort with ^G)
+   (riaktest@example.com)1>
 
-If riak_demo prints no "Error: ..." messages, and instead prints
-"SUCCESS", then Riak is working.
+   Now construct the node name of Riak server and make sure we can talk to it:
 
+   (riaktest@example.com)4> RiakNode = riak_util:str_to_node(riak).
 
-3. Connect a client
--
-Assuming no errors were generated during the server start step, a
-simple client interaction will look like:
-(remember, $RIAK should be set to the local path to your Riak installation)
+   (riaktest@example.com)2> net_adm:ping(RiakNode).
+   pong
+   (riaktest@example.com)2>
+   
+   We are now ready to start the Riak client:
 
-$ erl -name riaktest@127.0.0.1 -pa $RIAK/ebin -setcookie riak_demo_cookie
+   (riaktest@example.com)2> {ok, C} = riak:client_connect(RiakNode).
+   {ok,{riak_client,'riak@example.com',4,136,81,151}}
 
-(riaktest@127.0.0.1)1> %% connect to Riak
-(riaktest@127.0.0.1)1> {ok, C} = riak:client_connect('riakdemo@127.0.0.1').
-{ok,{riak_client,'riakdemo@127.0.0.1',
-                 "20090722191020-riaktest@127.0.0.1-riakdemo@127.0.0.1-266664"}}
+   Let's create a shopping list for bread at /groceries/mine:
 
-riaktest@127.0.0.1)2> %% Create a shopping list for bread at /groceries/mine
-riaktest@127.0.0.1)2> O0 = riak_object:new(<<"groceries">>, <<"mine">>, ["bread"]).
-{r_object,<<"groceries">>,<<"mine">>,
+   (riaktest@example.com)6> O0 = riak_object:new("groceries", "mine", ["bread"]).
+   O0 = riak_object:new("groceries", "mine", ["bread"]).
+   {r_object,"groceries","mine",
           [{r_content,{dict,0,16,16,8,80,48,
                             {[],[],[],[],[],[],[],[],[],[],[],[],[],[],...},
                             {{[],[],[],[],[],[],[],[],[],[],[],[],...}}},
                       ["bread"]}],
           [],
-          {dict,0,16,16,8,80,48,
+          {dict,1,16,16,8,80,48,
                 {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],...},
                 {{[],[],[],[],[],[],[],[],[],[],[],[],[],...}}},
           undefined}
 
-(riaktest@127.0.0.1)3> %% store the list
-(riaktest@127.0.0.1)3> C:put(O0, 1).
-ok
+    (riaktest@example.com)3> C:put(01, 1).
+    
+    Now, read the list back from the Riak server and extract the value
 
-(riaktest@127.0.0.1)4> %% retrieve the list
-(riaktest@127.0.0.1)4> {ok, O1} = C:get(<<"groceries">>, <<"mine">>, 1).
-{ok,{r_object,<<"groceries">>,<<"mine">>,
+    (riaktest@example.com)4> {ok, O1} = C:get("groceries", "mine", 1).
+    {ok,{r_object,"groceries","mine",
               [{r_content,{dict,2,16,16,8,80,48,
                                 {[],[],[],[],[],[],[],[],[],[],[],[],...},
                                 {{[],[],[],[],[],[],
-                                  [["X-Riak-Last-Modified",87|...]],
+                                  ["X-Riak-Last-Modified",87|...],
                                   [],[],[],...}}},
                           ["bread"]}],
-              [{"20090722191020-riaktest@127.0.0.1-riakdemo@127.0.0.1-266664",
+              [{"20090722191020-riaktest@example.com-riakdemo@example.com-266664",
                 {1,63415509105}}],
               {dict,0,16,16,8,80,48,
                     {[],[],[],[],[],[],[],[],[],[],[],[],[],...},
                     {{[],[],[],[],[],[],[],[],[],[],[],...}}},
               undefined}}
 
-(riaktest@127.0.0.1)5> %% extract the value
-(riaktest@127.0.0.1)5> V = riak_object:get_value(O1).
-["bread"]
+     (riaktest@example.com)5> %% extract the value
+     (riaktest@example.com)5> V = riak_object:get_value(O1).
+     ["bread"]
 
-(riaktest@127.0.0.1)6> %% add milk to the list
-(riaktest@127.0.0.1)6> O2 = riak_object:update_value(O1, ["milk"|V]).
-{r_object,<<"groceries">>,<<"mine">>,
+     Add milk to our list of groceries and write the new value to Riak:
+
+     (riaktest@example.com)6> %% add milk to the list
+     (riaktest@example.com)6> O2 = riak_object:update_value(O1, ["milk" | V]).
+     {r_object,"groceries","mine",
           [{r_content,{dict,2,16,16,8,80,48,
                             {[],[],[],[],[],[],[],[],[],[],[],[],[],[],...},
                             {{[],[],[],[],[],[],
-                              [["X-Riak-Last-Modified",87,101,100|...]],
+                              ["X-Riak-Last-Modified",87,101,100|...],
                               [],[],[],[],[],...}}},
                       ["bread"]}],
-          [{"20090722191020-riaktest@127.0.0.1-riakdemo@127.0.0.1-266664",
+          [{"20090722191020-riaktest@example.com-riakdemo@example.com-266664",
             {1,63415509105}}],
           {dict,0,16,16,8,80,48,
                 {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],...},
                 {{[],[],[],[],[],[],[],[],[],[],[],[],[],...}}},
           ["milk","bread"]}
 
-(riaktest@127.0.0.1)7> %% store the new list
-(riaktest@127.0.0.1)7> C:put(O2, 1).
-ok
+     (riaktest@example.com)7> %% store the new list
+     (riaktest@example.com)7> C:put(O2, 1).
+     ok
 
+     Finally, see what other keys are available in groceries bucket:
 
-(riaktest@127.0.0.1)8> %% find out what else is in the groceries bucket
-(riaktest@127.0.0.1)8> C:list_keys(<<"groceries">>).
-{ok,[<<"mine">>]}
+     (riaktest@example.com)8> C:list_keys("groceries").
+     {ok,["mine"]}
+
+
+
+     ["X-Riak-Last-Modified",87|...]: sec-2.3
+     ["X-Riak-Last-Modified",87,101,100|...]: sec-2.3
+
+3 Server Management 
+~~~~~~~~~~~~~~~~~~~~
+
+3.1 Configuration 
+==================
+   Configuration for the Riak server is stored in $RIAK/rel/riak/etc
+   directory. There are two files:
+   - vm.args 
+     This file contains the arguments that are passed to the Erlang VM
+     in which Riak runs. The default settings in this file shouldn't need to be
+     changed for most environments.
+
+   - app.config 
+     This file contains the configuration for the Erlang applications
+     that run on the Riak server.
+
+3.2 Server Control 
+===================
+
+3.2.1 bin/riak 
+---------------
+    This script is the primary interface for starting and stopping the Riak
+    server.
+
+    To start a daemonized (background) instance of Riak:
+
+    $ bin/riak start 
+
+    Once a server is running in the background you can attach to the Erlang
+    console via:
+
+    $ bin/riak attach
+
+    Alternatively, if you want to run a foreground instance of Riak, start it
+    with:
+
+    $ bin/riak console
+
+    Stopping a foreground or background instance of Riak can be done from a
+    shell prompt via:
+
+    $ bin/riak stop 
+
+    Or if you are attached/on the Erlang console:
+
+    (riak@example.com)1> q().
+
+    You can determine if the server is running by:
+
+    $ bin/riak ping
+
+3.2.2 bin/riak-admin 
+---------------------
+    This script provides access to general administration of the Riak server. 
+
+    To join a new Riak node to an existing cluster:
+
+    $ bin/riak start # If a local server is not already running
+    $ bin/riak-admin join <node in cluster>
+
+    (Note that you must have a local node already running for this to work)
+    
+    To verify that the local Riak node is able to read/write data:
+
+    $ bin/riak-admin test
+
+    
+    
+     
+#+OPTIONS: author:nil timestamp:nil
+
+Welcome to Riak.
+
+* Overview
+  Riak is a distributed, decentralized data storage system. 
+  
+  Below, you will find the "quick start" directions for setting up and
+  using Riak.  For more information, browse the following files:
+  
+  * README:  this file
+  * TODO:    a list of improvements planned for Riak
+  * LICENSE: the license under which Riak is released
+  * apps/    the source tree for Riak and all its dependencies
+  * doc/
+    - basic-setup.txt:  slightly more detail on setting up Riak
+    - basic-client.txt: slightly more detail on using Riak
+    - architecture.txt: details about the underlying design of Riak
+    - index.html:       the root of the edoc output of 'make docs'
+
+
+* Quick Start
+
+  This section assumes that you have copy of the Riak source tree. To get
+  started, you need to:
+  1. Build Riak
+  2. Start the Riak server
+  3. Connect a client and store/fetch data
+
+** Building Riak
+
+   Assuming you have a working Erlang (R13B03 or later) installation,
+   building Riak should be as simple as:
+
+   $ cd $RIAK
+   $ make all rel
+
+** Starting Riak
+
+   Once you have successfully built Riak, you can start the server with the
+   following commands:
+
+   $ cd $RIAK/rel/riak
+   $ bin/riak start
+
+   Now, verify that the server started up cleanly and is working:
+
+   $ bin/riak-admin test
+
+   Note that the $RIAK/rel/riak directory is a complete, self-contained instance
+   of Riak and Erlang. It is strongly suggested that you move this directory
+   outside the source tree if you plan to run a production instance.
+
+** Connecting a client to Riak
+
+   Now that you have a functional server, let's try storing some data in
+   it. First, start up a erlang node using our embedded version of erlang:
+
+   $ erts-<vsn>/bin/erl -name riaktest -setcookie riak
+   
+   Eshell V5.7.4  (abort with ^G)
+   (riaktest@example.com)1>
+
+   Now construct the node name of Riak server and make sure we can talk to it:
+
+   (riaktest@example.com)4> RiakNode = riak_util:str_to_node(riak).
+
+   (riaktest@example.com)2> net_adm:ping(RiakNode).
+   pong
+   (riaktest@example.com)2>
+   
+   We are now ready to start the Riak client:
+
+   (riaktest@example.com)2> {ok, C} = riak:client_connect(RiakNode).
+   {ok,{riak_client,'riak@example.com',<<4,136,81,151>>}}
+
+   Let's create a shopping list for bread at /groceries/mine:
+
+   (riaktest@example.com)6> O0 = riak_object:new(<<"groceries">>, <<"mine">>, ["bread"]).
+   O0 = riak_object:new(<<"groceries">>, <<"mine">>, ["bread"]).
+   {r_object,<<"groceries">>,<<"mine">>,
+          [{r_content,{dict,0,16,16,8,80,48,
+                            {[],[],[],[],[],[],[],[],[],[],[],[],[],[],...},
+                            {{[],[],[],[],[],[],[],[],[],[],[],[],...}}},
+                      ["bread"]}],
+          [],
+          {dict,1,16,16,8,80,48,
+                {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],...},
+                {{[],[],[],[],[],[],[],[],[],[],[],[],[],...}}},
+          undefined}
+
+    (riaktest@example.com)3> C:put(01, 1).
+    
+    Now, read the list back from the Riak server and extract the value
+
+    (riaktest@example.com)4> {ok, O1} = C:get(<<"groceries">>, <<"mine">>, 1).
+    {ok,{r_object,<<"groceries">>,<<"mine">>,
+              [{r_content,{dict,2,16,16,8,80,48,
+                                {[],[],[],[],[],[],[],[],[],[],[],[],...},
+                                {{[],[],[],[],[],[],
+                                  [["X-Riak-Last-Modified",87|...]],
+                                  [],[],[],...}}},
+                          ["bread"]}],
+              [{"20090722191020-riaktest@example.com-riakdemo@example.com-266664",
+                {1,63415509105}}],
+              {dict,0,16,16,8,80,48,
+                    {[],[],[],[],[],[],[],[],[],[],[],[],[],...},
+                    {{[],[],[],[],[],[],[],[],[],[],[],...}}},
+              undefined}}
+
+     (riaktest@example.com)5> %% extract the value
+     (riaktest@example.com)5> V = riak_object:get_value(O1).
+     ["bread"]
+
+     Add milk to our list of groceries and write the new value to Riak:
+
+     (riaktest@example.com)6> %% add milk to the list
+     (riaktest@example.com)6> O2 = riak_object:update_value(O1, ["milk" | V]).
+     {r_object,<<"groceries">>,<<"mine">>,
+          [{r_content,{dict,2,16,16,8,80,48,
+                            {[],[],[],[],[],[],[],[],[],[],[],[],[],[],...},
+                            {{[],[],[],[],[],[],
+                              [["X-Riak-Last-Modified",87,101,100|...]],
+                              [],[],[],[],[],...}}},
+                      ["bread"]}],
+          [{"20090722191020-riaktest@example.com-riakdemo@example.com-266664",
+            {1,63415509105}}],
+          {dict,0,16,16,8,80,48,
+                {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],...},
+                {{[],[],[],[],[],[],[],[],[],[],[],[],[],...}}},
+          ["milk","bread"]}
+
+     (riaktest@example.com)7> %% store the new list
+     (riaktest@example.com)7> C:put(O2, 1).
+     ok
+
+     Finally, see what other keys are available in groceries bucket:
+
+     (riaktest@example.com)8> C:list_keys(<<"groceries">>).
+     {ok,[<<"mine">>]}
+
+
+* Server Management
+
+** Configuration
+   Configuration for the Riak server is stored in $RIAK/rel/riak/etc
+   directory. There are two files:
+   - vm.args 
+     This file contains the arguments that are passed to the Erlang VM
+     in which Riak runs. The default settings in this file shouldn't need to be
+     changed for most environments.
+
+   - app.config 
+     This file contains the configuration for the Erlang applications
+     that run on the Riak server.
+
+** Server Control
+*** bin/riak
+    This script is the primary interface for starting and stopping the Riak
+    server.
+
+    To start a daemonized (background) instance of Riak:
+
+    $ bin/riak start 
+
+    Once a server is running in the background you can attach to the Erlang
+    console via:
+
+    $ bin/riak attach
+
+    Alternatively, if you want to run a foreground instance of Riak, start it
+    with:
+
+    $ bin/riak console
+
+    Stopping a foreground or background instance of Riak can be done from a
+    shell prompt via:
+
+    $ bin/riak stop 
+
+    Or if you are attached/on the Erlang console:
+
+    (riak@example.com)1> q().
+
+    You can determine if the server is running by:
+
+    $ bin/riak ping
+
+*** bin/riak-admin
+    This script provides access to general administration of the Riak server. 
+
+    To join a new Riak node to an existing cluster:
+
+    $ bin/riak start # If a local server is not already running
+    $ bin/riak-admin join <node in cluster>
+
+    (Note that you must have a local node already running for this to work)
+    
+    To verify that the local Riak node is able to read/write data:
+
+    $ bin/riak-admin test
+
+    
+    
+     

TODO

-a sampling of improvements on the way:
- - more storage backends
- - repeatable benchmarking suite
- - OTP bootable release
- - nicer shutdown mechanism
- - better cleanup of node storage after handoff
- - move bucket properties out of gossiped ring state
-    (allowing unlimited buckets)
- - improved efficiency of vnode handoff and bootstrapping
- - more explicit UTF-8 support and testing
- - making nodes that have finished exiting a cluster more obvious
- - better timeout management on individual nodes of map-phases
- - revisit hibernate when more monitoring abilities are available
- - document why vnode start is a spawn and monitor instead of ... ?
- - remember why riak_vnode_master:vnode_del is a call instead of a cast
- - riak_mapreduce: provide a version of standard map funs that handles siblings
-   (with reconcile)
--  better mapreduce docs
--  good documents for riak_object and reconciliation
--  better riak_object tests
--  better detection of disconnected eventers
-
+                    Notes on Riak Source Tree Restructuring
+                    =======================================
+
+
+
+
+Table of Contents
+=================
+1 Overview 
+2 Summary of changes 
+    2.1 Building 
+    2.2 Server scripts 
+        2.2.1 riak_demo.escript 
+        2.2.2 start-backup/restore/logger.sh 
+    2.3 Configuration 
+        2.3.1 riak-env.sh 
+
+
+1 Overview 
+~~~~~~~~~~~
+  The Riak source tree has undergone a major restructuring as part of a
+  transition to a new build tool -- rebar. This tool enforces OTP compliant
+  directory structures for the riak application and its dependencies and
+  provides an easy-to-use wrapper around the new reltool system available in
+  Erlang R1303+. Using reltool makes it possible to construct a standalone
+  server instance that can be used on machines without Erlang installed. This
+  transition has also enabled us to introduce a standardized script for
+  starting/stopping and other server management tasks.
+
+
+2 Summary of changes 
+~~~~~~~~~~~~~~~~~~~~~
+
+2.1 Building 
+=============
+   The source code can still be compiled using a single invocation of make at
+   the top-level $RIAK directory:
+
+   $ make
+
+   However, if you want a runnable, redistributable server you need to make sure
+   the "rel" target gets built:
+
+   $ make rel
+
+   This will place a full server install in the $RIAK/rel/riak directory. You
+   can safely copy this riak directory to any other machine with the SAME
+   operating system and architecture and run riak.  See the README for more
+   information about how to start/stop the server.
+
+   As an alternative to the "rel" target, if you are doing active development on
+   the Riak source code you may want to try the "devrel" target. This will
+   generate three runnable nodes in $RIAK/dev and symlink them in such a way
+   that recompiles of the Riak source code (i.e. simple invocation of "make") is
+   automatically available to those nodes. These three nodes, (dev1, dev2, dev2)
+   are NOT suitable for redistribution. They simply make it easy to quickly test
+   changes to the Riak source code in a development environment.
+
+2.2 Server scripts 
+===================
+   start-*.sh and debug-*.sh have all been replaced with the bin/riak and
+   bin/riak-admin scripts that are generated as part of the "rel" or "devrel"
+   targets.
+
+2.2.1 riak_demo.escript 
+------------------------
+    The functionality of this script is now available via:
+
+    $ bin/riak-admin test
+
+
+2.2.2 start-backup/restore/logger.sh 
+-------------------------------------
+    The functionality of these scripts is now available via the bin/riak-admin
+    script.
+
+2.3 Configuration 
+==================
+   The config/ directory has been removed; you can now find default
+   configuration in $RIAK/rel/overlay/etc directory -- the app.config and
+   vm.args files are copied from that location when running the "rel" or
+   "devrel" targets. If you already have run the release targets you can just
+   edit the files in the $RIAK/rel/riak/etc or $RIAK/dev/dev*/etc directories
+   respectively.
+
+2.3.1 riak-env.sh 
+------------------
+    This file has been replaced with vm.args. 
+
+#+OPTIONS: author:nil timestamp:nil
+
+Notes on Riak Source Tree Restructuring
+
+* Overview
+  The Riak source tree has undergone a major restructuring as part of a
+  transition to a new build tool -- rebar. This tool enforces OTP compliant
+  directory structures for the riak application and its dependencies and
+  provides an easy-to-use wrapper around the new reltool system available in
+  Erlang R1303+. Using reltool makes it possible to construct a standalone
+  server instance that can be used on machines without Erlang installed. This
+  transition has also enabled us to introduce a standardized script for
+  starting/stopping and other server management tasks.
+
+
+* Summary of changes
+
+** Building
+   The source code can still be compiled using a single invocation of make at
+   the top-level $RIAK directory:
+
+   $ make
+
+   However, if you want a runnable, redistributable server you need to make sure
+   the "rel" target gets built:
+
+   $ make rel
+
+   This will place a full server install in the $RIAK/rel/riak directory. You
+   can safely copy this riak directory to any other machine with the SAME
+   operating system and architecture and run riak.  See the README for more
+   information about how to start/stop the server.
+
+   As an alternative to the "rel" target, if you are doing active development on
+   the Riak source code you may want to try the "devrel" target. This will
+   generate three runnable nodes in $RIAK/dev and symlink them in such a way
+   that recompiles of the Riak source code (i.e. simple invocation of "make") is
+   automatically available to those nodes. These three nodes, (dev1, dev2, dev2)
+   are NOT suitable for redistribution. They simply make it easy to quickly test
+   changes to the Riak source code in a development environment.
+
+** Server scripts
+   start-*.sh and debug-*.sh have all been replaced with the bin/riak and
+   bin/riak-admin scripts that are generated as part of the "rel" or "devrel"
+   targets.
+
+*** riak_demo.escript 
+    The functionality of this script is now available via:
+
+    $ bin/riak-admin test
+
+
+*** start-backup/restore/logger.sh
+    The functionality of these scripts is now available via the bin/riak-admin
+    script.
+
+** Configuration
+   The config/ directory has been removed; you can now find default
+   configuration in $RIAK/rel/overlay/etc directory -- the app.config and
+   vm.args files are copied from that location when running the "rel" or
+   "devrel" targets. If you already have run the release targets you can just
+   edit the files in the $RIAK/rel/riak/etc or $RIAK/dev/dev*/etc directories
+   respectively.
+
+*** riak-env.sh
+    This file has been replaced with vm.args. 
+

apps/mochiweb/LICENSE

+This is the MIT license.
+
+Copyright (c) 2007 Mochi Media, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

apps/mochiweb/Makefile

+all:
+	(cd src;$(MAKE) all)
+
+edoc:
+	(cd src;$(MAKE) edoc)
+
+test:
+	(cd src;$(MAKE) test)
+
+clean:
+	(cd src;$(MAKE) clean)

apps/mochiweb/README

+MochiWeb is an Erlang library for building lightweight HTTP servers.

apps/mochiweb/ebin/.hg_empty_dir

Empty file added.

apps/mochiweb/ebin/mochiweb.app

+{application, mochiweb,
+ [{description, "MochiMedia Web Server"},
+  {vsn, "0.01"},
+  {modules, [
+        mochihex,
+        mochijson,
+        mochijson2,
+        mochinum,
+        mochiweb,
+        mochiweb_app,
+        mochiweb_charref,
+        mochiweb_cookies,
+        mochiweb_echo,
+        mochiweb_headers,
+        mochiweb_html,
+        mochiweb_http,
+        mochiweb_multipart,
+        mochiweb_request,
+        mochiweb_response,
+        mochiweb_skel,
+        mochiweb_socket_server,
+        mochiweb_sup,
+        mochiweb_util,
+        reloader,
+        mochifmt,
+        mochifmt_std,
+        mochifmt_records
+	    ]},
+  {registered, []},
+  {mod, {mochiweb_app, []}},
+  {env, []},
+  {applications, [kernel, stdlib]}]}.

apps/mochiweb/priv/skel/Makefile

+all:
+	(cd src;$(MAKE))
+
+clean:
+	(cd src;$(MAKE) clean)

apps/mochiweb/priv/skel/priv/www/index.html

+<html>
+<head>
+<title>It Worked</title>
+</head>
+<body>
+MochiWeb running.
+</body>
+</html>

apps/mochiweb/priv/skel/src/Makefile

+include ../support/include.mk
+
+all: $(EBIN_FILES)
+
+debug:
+	$(MAKE) DEBUG=-DDEBUG
+
+clean:
+	rm -rf $(EBIN_FILES)

apps/mochiweb/priv/skel/src/skel.app

+{application, skel,
+ [{description, "skel"},
+  {vsn, "0.01"},
+  {modules, [
+    skel,
+    skel_app,
+    skel_sup,
+    skel_web,
+    skel_deps
+  ]},
+  {registered, []},
+  {mod, {skel_app, []}},
+  {env, []},
+  {applications, [kernel, stdlib, crypto]}]}.

apps/mochiweb/priv/skel/src/skel.erl

+%% @author author <author@example.com>
+%% @copyright YYYY author.
+
+%% @doc TEMPLATE.
+
+-module(skel).
+-author('author <author@example.com>').
+-export([start/0, stop/0]).
+
+ensure_started(App) ->
+    case application:start(App) of
+        ok ->
+            ok;
+        {error, {already_started, App}} ->
+            ok
+    end.
+        
+%% @spec start() -> ok
+%% @doc Start the skel server.
+start() ->
+    skel_deps:ensure(),
+    ensure_started(crypto),
+    application:start(skel).
+
+%% @spec stop() -> ok
+%% @doc Stop the skel server.
+stop() ->
+    Res = application:stop(skel),
+    application:stop(crypto),
+    Res.

apps/mochiweb/priv/skel/src/skel.hrl

+

apps/mochiweb/priv/skel/src/skel_app.erl

+%% @author author <author@example.com>
+%% @copyright YYYY author.
+
+%% @doc Callbacks for the skel application.
+
+-module(skel_app).
+-author('author <author@example.com>').
+
+-behaviour(application).
+-export([start/2,stop/1]).
+
+
+%% @spec start(_Type, _StartArgs) -> ServerRet
+%% @doc application start callback for skel.
+start(_Type, _StartArgs) ->
+    skel_deps:ensure(),
+    skel_sup:start_link().
+
+%% @spec stop(_State) -> ServerRet
+%% @doc application stop callback for skel.
+stop(_State) ->
+    ok.

apps/mochiweb/priv/skel/src/skel_deps.erl

+%% @author author <author@example.com>
+%% @copyright YYYY author.
+
+%% @doc Ensure that the relatively-installed dependencies are on the code
+%%      loading path, and locate resources relative
+%%      to this application's path.
+
+-module(skel_deps).
+-author('author <author@example.com>').
+
+-export([ensure/0, ensure/1]).
+-export([get_base_dir/0, get_base_dir/1]).
+-export([local_path/1, local_path/2]).
+-export([deps_on_path/0, new_siblings/1]).
+
+%% @spec deps_on_path() -> [ProjNameAndVers]
+%% @doc List of project dependencies on the path.
+deps_on_path() ->
+    F = fun (X, Acc) ->
+                ProjDir = filename:dirname(X),
+                case {filename:basename(X),
+                      filename:basename(filename:dirname(ProjDir))} of
+                    {"ebin", "deps"} ->
+                        [filename:basename(ProjDir) | Acc];
+                    _ ->
+                        Acc
+                end
+        end,
+    ordsets:from_list(lists:foldl(F, [], code:get_path())).
+    
+%% @spec new_siblings(Module) -> [Dir]
+%% @doc Find new siblings paths relative to Module that aren't already on the
+%%      code path.
+new_siblings(Module) ->
+    Existing = deps_on_path(),
+    SiblingEbin = filelib:wildcard(local_path(["deps", "*", "ebin"], Module)),
+    Siblings = [filename:dirname(X) || X <- SiblingEbin,
+                           ordsets:is_element(
+                             filename:basename(filename:dirname(X)),
+                             Existing) =:= false],
+    lists:filter(fun filelib:is_dir/1, 
+                 lists:append([[filename:join([X, "ebin"]),
+                                filename:join([X, "include"])] ||
+                                  X <- Siblings])).
+        
+
+%% @spec ensure(Module) -> ok
+%% @doc Ensure that all ebin and include paths for dependencies
+%%      of the application for Module are on the code path.
+ensure(Module) ->
+    code:add_paths(new_siblings(Module)),
+    code:clash(),
+    ok.
+
+%% @spec ensure() -> ok
+%% @doc Ensure that the ebin and include paths for dependencies of
+%%      this application are on the code path. Equivalent to
+%%      ensure(?Module).
+ensure() ->
+    ensure(?MODULE).
+
+%% @spec get_base_dir(Module) -> string()
+%% @doc Return the application directory for Module. It assumes Module is in
+%%      a standard OTP layout application in the ebin or src directory.
+get_base_dir(Module) ->
+    {file, Here} = code:is_loaded(Module),
+    filename:dirname(filename:dirname(Here)).
+
+%% @spec get_base_dir() -> string()
+%% @doc Return the application directory for this application. Equivalent to
+%%      get_base_dir(?MODULE).
+get_base_dir() ->
+    get_base_dir(?MODULE).
+
+%% @spec local_path([string()], Module) -> string()
+%% @doc Return an application-relative directory from Module's application.
+local_path(Components, Module) ->
+    filename:join([get_base_dir(Module) | Components]).
+
+%% @spec local_path(Components) -> string()
+%% @doc Return an application-relative directory for this application.
+%%      Equivalent to local_path(Components, ?MODULE).
+local_path(Components) ->
+    local_path(Components, ?MODULE).

apps/mochiweb/priv/skel/src/skel_sup.erl

+%% @author author <author@example.com>
+%% @copyright YYYY author.
+
+%% @doc Supervisor for the skel application.
+
+-module(skel_sup).
+-author('author <author@example.com>').
+
+-behaviour(supervisor).
+
+%% External exports
+-export([start_link/0, upgrade/0]).
+
+%% supervisor callbacks
+-export([init/1]).
+
+%% @spec start_link() -> ServerRet
+%% @doc API for starting the supervisor.
+start_link() ->
+    supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+%% @spec upgrade() -> ok
+%% @doc Add processes if necessary.
+upgrade() ->
+    {ok, {_, Specs}} = init([]),
+
+    Old = sets:from_list(
+            [Name || {Name, _, _, _} <- supervisor:which_children(?MODULE)]),
+    New = sets:from_list([Name || {Name, _, _, _, _, _} <- Specs]),
+    Kill = sets:subtract(Old, New),
+
+    sets:fold(fun (Id, ok) ->
+                      supervisor:terminate_child(?MODULE, Id),
+                      supervisor:delete_child(?MODULE, Id),
+                      ok
+              end, ok, Kill),
+
+    [supervisor:start_child(?MODULE, Spec) || Spec <- Specs],
+    ok.
+
+%% @spec init([]) -> SupervisorTree
+%% @doc supervisor callback.
+init([]) ->
+    Ip = case os:getenv("MOCHIWEB_IP") of false -> "0.0.0.0"; Any -> Any end,   
+    WebConfig = [
+         {ip, Ip},
+                 {port, 8000},
+                 {docroot, skel_deps:local_path(["priv", "www"])}],
+    Web = {skel_web,
+           {skel_web, start, [WebConfig]},
+           permanent, 5000, worker, dynamic},
+
+    Processes = [Web],
+    {ok, {{one_for_one, 10, 10}, Processes}}.

apps/mochiweb/priv/skel/src/skel_web.erl

+%% @author author <author@example.com>
+%% @copyright YYYY author.
+
+%% @doc Web server for skel.
+
+-module(skel_web).
+-author('author <author@example.com>').
+
+-export([start/1, stop/0, loop/2]).
+
+%% External API
+
+start(Options) ->
+    {DocRoot, Options1} = get_option(docroot, Options),
+    Loop = fun (Req) ->
+                   ?MODULE:loop(Req, DocRoot)
+           end,
+    mochiweb_http:start([{name, ?MODULE}, {loop, Loop} | Options1]).
+
+stop() ->
+    mochiweb_http:stop(?MODULE).
+
+loop(Req, DocRoot) ->
+    "/" ++ Path = Req:get(path),
+    case Req:get(method) of
+        Method when Method =:= 'GET'; Method =:= 'HEAD' ->
+            case Path of
+                _ ->
+                    Req:serve_file(Path, DocRoot)
+            end;
+        'POST' ->
+            case Path of
+                _ ->
+                    Req:not_found()
+            end;
+        _ ->
+            Req:respond({501, [], []})
+    end.
+
+%% Internal API
+
+get_option(Option, Options) ->
+    {proplists:get_value(Option, Options), proplists:delete(Option, Options)}.

apps/mochiweb/priv/skel/start-dev.sh

+#!/bin/sh
+cd `dirname $0`
+exec erl -pa $PWD/ebin $PWD/deps/*/ebin -boot start_sasl -s reloader -s skel

apps/mochiweb/priv/skel/start.sh

+#!/bin/sh
+cd `dirname $0`
+exec erl -pa $PWD/ebin $PWD/deps/*/ebin -boot start_sasl -s skel

apps/mochiweb/priv/skel/support/include.mk

+## -*- makefile -*-
+
+######################################################################
+## Erlang
+
+ERL := erl
+ERLC := $(ERL)c
+
+INCLUDE_DIRS := ../include $(wildcard ../deps/*/include)
+EBIN_DIRS := $(wildcard ../deps/*/ebin)
+ERLC_FLAGS := -W $(INCLUDE_DIRS:../%=-I ../%) $(EBIN_DIRS:%=-pa %)
+
+ifndef no_debug_info
+  ERLC_FLAGS += +debug_info
+endif
+
+ifdef debug
+  ERLC_FLAGS += -Ddebug
+endif
+
+EBIN_DIR := ../ebin
+DOC_DIR  := ../doc
+EMULATOR := beam
+
+ERL_SOURCES := $(wildcard *.erl)
+ERL_HEADERS := $(wildcard *.hrl) $(wildcard ../include/*.hrl)
+ERL_OBJECTS := $(ERL_SOURCES:%.erl=$(EBIN_DIR)/%.$(EMULATOR))
+ERL_DOCUMENTS := $(ERL_SOURCES:%.erl=$(DOC_DIR)/%.html)
+ERL_OBJECTS_LOCAL := $(ERL_SOURCES:%.erl=./%.$(EMULATOR))
+APP_FILES := $(wildcard *.app)
+EBIN_FILES = $(ERL_OBJECTS) $(ERL_DOCUMENTS) $(APP_FILES:%.app=../ebin/%.app)
+EBIN_FILES_NO_DOCS = $(ERL_OBJECTS) $(APP_FILES:%.app=../ebin/%.app)
+MODULES = $(ERL_SOURCES:%.erl=%)
+
+../ebin/%.app: %.app
+	cp $< $@
+
+$(EBIN_DIR)/%.$(EMULATOR): %.erl
+	$(ERLC) $(ERLC_FLAGS) -o $(EBIN_DIR) $<
+
+./%.$(EMULATOR): %.erl
+	$(ERLC) $(ERLC_FLAGS) -o . $<
+
+$(DOC_DIR)/%.html: %.erl
+	$(ERL) -noshell -run edoc file $< -run init stop
+	mv *.html $(DOC_DIR)

apps/mochiweb/scripts/new_mochiweb.erl

+#!/usr/bin/env escript
+%% -*- mode: erlang -*-
+-export([main/1]).
+
+%% External API
+
+main([Name]) ->
+    main([Name, "."]);
+main([Name, Dest]) ->
+    ensure(),
+    DestDir = filename:absname(Dest),
+    ok = mochiweb_skel:skelcopy(DestDir, Name);
+main(_) ->
+    usage().
+
+%% Internal API
+
+ensure() ->
+    code:add_patha(filename:join(filename:dirname(escript:script_name()),
+                                 "../ebin")).
+
+usage() ->
+    io:format("usage: ~s name [destdir]~n",
+              [filename:basename(escript:script_name())]),
+    halt(1).
+
+

apps/mochiweb/src/Makefile

+include ../support/include.mk
+
+APPLICATION=mochiweb
+DOC_OPTS={dir,\"../doc\"}
+
+all: $(EBIN_FILES)
+
+debug:
+	$(MAKE) DEBUG=-DDEBUG
+
+clean:
+	rm -rf $(EBIN_FILES)
+
+edoc:
+	$(ERL) -noshell -pa ../ebin \
+		-eval "edoc:application($(APPLICATION), \".\", [$(DOC_OPTS)])" \
+		-s init stop
+
+test: all
+	$(ERL) -noshell -pa ../ebin -s $(APPLICATION) test -s init stop

apps/mochiweb/src/mochifmt.erl

+%% @author Bob Ippolito <bob@mochimedia.com>
+%% @copyright 2008 Mochi Media, Inc.
+
+%% @doc String Formatting for Erlang, inspired by Python 2.6
+%%      (<a href="http://www.python.org/dev/peps/pep-3101/">PEP 3101</a>).
+%%
+-module(mochifmt).
+-author('bob@mochimedia.com').
+-export([format/2, format_field/2, convert_field/2, get_value/2, get_field/2]).
+-export([tokenize/1, format/3, get_field/3, format_field/3]).
+-export([bformat/2, bformat/3]).
+-export([f/2, f/3]).
+-export([test/0]).
+
+-record(conversion, {length, precision, ctype, align, fill_char, sign}).
+
+%% @spec tokenize(S::string()) -> tokens()
+%% @doc Tokenize a format string into mochifmt's internal format.
+tokenize(S) ->
+    {?MODULE, tokenize(S, "", [])}.
+
+%% @spec convert_field(Arg, Conversion::conversion()) -> term()
+%% @doc Process Arg according to the given explicit conversion specifier.
+convert_field(Arg, "") ->
+    Arg;
+convert_field(Arg, "r") ->
+    repr(Arg);
+convert_field(Arg, "s") ->
+    str(Arg).
+
+%% @spec get_value(Key::string(), Args::args()) -> term()
+%% @doc Get the Key from Args. If Args is a tuple then convert Key to
+%%      an integer and get element(1 + Key, Args). If Args is a list and Key
+%%      can be parsed as an integer then use lists:nth(1 + Key, Args),
+%%      otherwise try and look for Key in Args as a proplist, converting
+%%      Key to an atom or binary if necessary.
+get_value(Key, Args) when is_tuple(Args) ->
+    element(1 + list_to_integer(Key), Args);
+get_value(Key, Args) when is_list(Args) ->
+    try lists:nth(1 + list_to_integer(Key), Args)
+    catch error:_ ->
+            {_K, V} = proplist_lookup(Key, Args),
+            V
+    end.
+
+%% @spec get_field(Key::string(), Args) -> term()
+%% @doc Consecutively call get_value/2 on parts of Key delimited by ".",
+%%      replacing Args with the result of the previous get_value. This
+%%      is used to implement formats such as {0.0}.
+get_field(Key, Args) ->
+    get_field(Key, Args, ?MODULE).
+
+%% @spec get_field(Key::string(), Args, Module) -> term()
+%% @doc Consecutively call Module:get_value/2 on parts of Key delimited by ".",
+%%      replacing Args with the result of the previous get_value. This
+%%      is used to implement formats such as {0.0}.
+get_field(Key, Args, Module) ->
+    {Name, Next} = lists:splitwith(fun (C) -> C =/= $. end, Key),
+    Res = try Module:get_value(Name, Args)
+          catch error:undef -> get_value(Name, Args) end,
+    case Next of
+        "" ->
+            Res;
+        "." ++ S1 ->
+            get_field(S1, Res, Module)
+    end.
+
+%% @spec format(Format::string(), Args) -> iolist()
+%% @doc Format Args with Format.
+format(Format, Args) ->
+    format(Format, Args, ?MODULE).
+
+%% @spec format(Format::string(), Args, Module) -> iolist()
+%% @doc Format Args with Format using Module.
+format({?MODULE, Parts}, Args, Module) ->
+    format2(Parts, Args, Module, []);
+format(S, Args, Module) ->
+    format(tokenize(S), Args, Module).
+
+%% @spec format_field(Arg, Format) -> iolist()
+%% @doc Format Arg with Format.
+format_field(Arg, Format) ->
+    format_field(Arg, Format, ?MODULE).
+
+%% @spec format_field(Arg, Format, _Module) -> iolist()
+%% @doc Format Arg with Format.
+format_field(Arg, Format, _Module) ->
+    F = default_ctype(Arg, parse_std_conversion(Format)),
+    fix_padding(fix_sign(convert2(Arg, F), F), F).
+
+%% @spec f(Format::string(), Args) -> string()
+%% @doc Format Args with Format and return a string().
+f(Format, Args) ->
+    f(Format, Args, ?MODULE).
+
+%% @spec f(Format::string(), Args, Module) -> string()
+%% @doc Format Args with Format using Module and return a string().
+f(Format, Args, Module) ->
+    case lists:member(${, Format) of
+        true ->
+            binary_to_list(bformat(Format, Args, Module));
+        false ->
+            Format
+    end.
+
+%% @spec bformat(Format::string(), Args) -> binary()