Showing posts with label raspberry. Show all posts
Showing posts with label raspberry. Show all posts

Monday, 28 September 2015

Couchdb, MVCC and Conflicts while Replicating

Setup

In my last post regarding Multiversion Concurrency Control, we saw what it takes to enter conflicting versions of a document into a single couch instance. You have to be somewhat resourceful.

But the real fun with the couch comes from its distributed nature.
We will see that the rules change a bit when we talk about more than one instance and use replication to synchronize them.

Here's the setup for playing around with MVCC on two couches:

First Pi:

  • hostname: frodo
  • Model: Pi B+ (ARMv6h)
  • OS: Arch Linux ARM
  • Couchdb 1.6.1_4 (taken from Arch Linux ARM Repository)

Second Pi:


Again, everything will be done via curl. Data will not be directly on the command line but always be taken from a file (due to strange behaviour of my curl on Windows).

We assume two users entering data into the their respective Pis. Arwen uses the the couch on her arwen-Pi when Frodo uses his frodo-Pi. Eventually they will exchange their work via replication.

Preparation

Let's start from scratch by creating the database on each Pi respectively:
#
# create the database on arwen
curl -X PUT http://arwen:5984/mvcc
#
# reaponse
{"ok":true}
#
# create the database on frodo
curl -X PUT http://frodo:5984/mvcc
#
# resonse
{"ok":true}
#

...And Go

Arwen inserts her document first:
#
# Arwen inserts her Doc rep_mydoc_u1_1.json
{
  "content": "U1_1"
}
#
curl -H "Content-Type: application/json" -d @rep_mydoc_u1_1.json -X PUT http://arwen:5984/mvcc/mydoc 
#response
{
  "ok":true,
  "id":"mydoc",
  "rev":"1-3557461c60a30b0d156f8b36a1bdcf9f"
}
#

Arwen wants to share her document with Frodo. She submits a Push Replication Request into the _replicator database of her Pi to trigger the replication:
#
# Arwen shares her doc with frodo via replication
# She initiates a push replication from arwen to frodo
# push_a2f_01.json:
{
  "source": "mvcc", 
  "target": "http://frodo:5984/mvcc"
}
#
curl -H "Content-Type: application/json" -d @push_a2f_01.json -X PUT http://arwen:5984/_replicator/a2s01
#
#responsse
{
  "ok":true,
  "id":"a2s01",
  "rev":"1-0088a4a381404b513bf0586d08d6ce80"
}
#
Taking a look into Arwen's couch.log tells us that the replication took place:
#
Document `a2s01` triggered replication `6018cd9109568fed438add0722e9bccb`
starting new replication `6018cd9109568fed438add0722e9bccb` at <0 data-blogger-escaped-.31751.2=""> (`mvcc` -> `http://frodo:5984/mvcc/`)
recording a checkpoint for `mvcc` -> `http://frodo:5984/mvcc/` at source update_seq 1
Replication `6018cd9109568fed438add0722e9bccb` finished (triggered by document `a2s01`)
#

Please note that these Pis do not know about each other. The replication request is the only point of contact. This request requires Arwen to know about a frodo-Pi.

OK, Frodo should have Arwen's document on his Pi now:
#
# Frodo should now have the document too:
curl  http://frodo:5984/mvcc/mydoc
#respopnse
{
  "_id":"mydoc",
  "_rev":"1-3557461c60a30b0d156f8b36a1bdcf9f",
  "content":"U1_1"
}
#

Now Arwen and Frodo both continue to work on their respective copy of the document and eventually save their work:
#
# Arwen edits her document on arwen
# rep_mydoc_u1_2.json:
{
  "_rev": "1-3557461c60a30b0d156f8b36a1bdcf9f",
  "content": "U1_2"
}
#
curl -H "Content-Type: application/json" -d @rep_mydoc_u1_2.json -X PUT http://arwen:5984/mvcc/mydoc
# response
{
  "ok":true,
  "id":"mydoc",
  "rev":"2-2686fb85c0681a3d8c411617f048f94f"
}
#
# Frodo does the same on frodo
# rep_mydoc_u2_2.json:
{
  "_rev":"1-3557461c60a30b0d156f8b36a1bdcf9f",
  "content": "U2_2"
} 
#
curl -H "Content-Type: application/json" -d @rep_mydoc_u2_2.json -X PUT http://frodo:5984/mvcc/mydoc
# response
{
  "ok":true,
  "id":"mydoc",
  "rev":"2-03b64efa2cd6619f46bcbe618fa791f9"
}
#
Each Pi now holds a different version of the document.
Frodo initiates a full sync by triggering first a push replication followed by a pull replication to Arwen. As Frodo now takes the lead, both requests will be submitted into the_replicator DB of his Pi:
# Frodo pushes his stuff to Arwen
# push request push_f2a_01.json:
{
  "source": "mvcc", 
  "target": "http://arwen:5984/mvcc"
}
#
curl -H "Content-Type: application/json" -d @push_f2a_01.json -X PUT http://frodo:5984/_replicator/f2a01
#response
{
  "ok":true,
  "id":"f2a01",
  "rev":"1-d20099b5d5b65eb05271be0204d8100a"
}
#
# Next Frodo pulls from Arwen
# pull request pull_a2f_01.json:
{
  "source": "http://arwen:5984/mvcc", 
  "target": "mvcc"
}
curl -H "Content-Type: application/json" -d @pull_a2f_01.json -X PUT http://frodo:5984/_replicator/a2f01
#response
{
  "ok":true,
  "id":"a2f01",
  "rev":"1-26926753f759498b86ece4e48fdb0e5f"
}
#
What would be our expectation after syncing both Pis?
The same document was edited on different hosts. After the new versions had been submitted, each host then held the old and a new version of the document. Both hosts may claim to hold the current version of the document with equal rights.
After a full sync, we expect this:

  • there is identical data on both hosts
  • each host holds the old version and both "new" versions of the document
So, let's see.
We're going to check by requesting the current version and conflicting versions if any.
Let's check on Arwen first:
#
# there should be a conflict on arwen now... 
curl  http://arwen:5984/mvcc/mydoc?conflicts=true
#response
{
  "_id":"mydoc",
  "_rev":"2-2686fb85c0681a3d8c411617f048f94f",
  "content":"U1_2",
  "_conflicts":["2-03b64efa2cd6619f46bcbe618fa791f9"]
}
#
The current version is the one that Arwen herself submitted.
As expected, there is a conflict.

What is it on Frodo's Pi?
#
# there should be a conflict on frodo too... 
curl  http://frodo:5984/mvcc/mydoc?conflicts=true
#response
{
  "_id":"mydoc",
  "_rev":"2-2686fb85c0681a3d8c411617f048f94f",
  "content":"U1_2",
  "_conflicts":["2-03b64efa2cd6619f46bcbe618fa791f9"]
}
#
On Frodo's Pi we find the same situation. Arwen's document is delivered as current. Frodo's version constitutes the conflict.
The couch keeps its promise to deliver the same "winning" version on both nodes.

Summery

As far as conflicts are concerned, working distributed changes the rules completely.
On a single node, the couch is quite strict avoiding conflicts. You need a bulk update with a special mode switched on to get it done.
Once you decide to work distributed, the priorities change. When replicating between nodes, pushing or pulling your data successfully becomes the main objective. The goal is to save data over a network. As the nodes operate completely independent from one another, conflicts cannot be avoided.

Well, if you need to go for distributed and want your nodes to be independent, this is the price you have to pay. As economics teaches us: there is no such thing as a free lunch. This seems to hold true for the computer scientist's menu too.




Tuesday, 10 February 2015

CouchDB - MVCC and Conflicts

This is a small entry about couchDB's Multi Version Concurrency Control mechanism and what it takes to have conflicting documents end up on the couch.
Though MVCC is well covered by couchDB's documentation, I wanted to see it in action with my own Pies :-)

Setup

I have couchDB installed on two Pies, gandalf and samwise. On gandalf, the couchdb version is 1.6.0 whereas on samwise it is a 1.5.1.

We will first create conflicts on a single node (gandalf) and then on two nodes by means of master-master replication.
Curl will be used to talk to the couches (note: my curl shell on Windows does not like mixing " and ' which is why I have to put all the JSON data I want to send via curl into files).

If you want to replay this on your system, make sure to not only adjust IP addresses or host names but also substitute the revision values (_rev) with the ones you'll receive as response.
All curl commands and there respective responses are genuine. Responses are formatted for better readability.

What is a Conflict?

Before we start, let's agree on what a conflict is:
A conflict is a state where two or more versions of a document branch from a common root version. Only the leafs of conflicting branches are considered to be in conflict with each other.
Let's try to create this on couchdb.

We'll be acting on behalf of two users, first on one and then on two couchdb nodes.

Conflicts on a Single Node

On a single instance of couchdb, it is not possible to create a conflict when performing single document updates. If you want to update a document, you have to supply the latest revision of this document's revision tree. If you do not have this revision, your update will be rejected.

If you want to end up with a conflict, i.e. two revisions branching from a single common revision, you have to use couchdb's bulk update feature. But that's not all it takes. In addition you have to use the bulk update in the special "All-or-Nothing" mode.

Not so easy to to create a conflict on a single instance, but lets see.

We start by creating a database called mvcc on gandalf:
# check if couchdb is running
curl http://gandalf:5984
# response:
{"couchdb":"Welcome",
 "uuid":"360325151b6a3c70595a522b36f52037",
 "version":"1.6.0",
 "vendor":{"name":"The Apache Software Foundation",
 "version":"1.6.0"}
}
#
# create database "mvcc"
curl -X PUT http://gandalf:5984/mvcc
# response:
{"ok":true}

User 1 inserts an initial version of a document into the database. The document is stored in file mydoc_u1_1.json and looks like this:
{
  "content": "U1_1"
} 


curl -H "Content-Type: application/json" -d @mydoc_u1_1.json -X PUT http://gandalf:5984/mvcc/mydoc
# response:
{"ok":true,
 "id":"mydoc",
 "rev":"1-3557461c60a30b0d156f8b36a1bdcf9f"
}


User 2 reads the document and takes down the revision in order to use it for the update he plans.
# User 2 reads the doc...
curl -X GET http://gandalf:5984/mvcc/mydoc
# response:
{"_id":"mydoc",
 "_rev":"1-3557461c60a30b0d156f8b36a1bdcf9f",
 "content":"U1_1"
}


Both users are now holding the same revision of the document and both plan to update the document. User 1 is faster and places his update.
# here is the updated doc (mydoc_u1_2.json)
{
  "_rev":"1-3557461c60a30b0d156f8b36a1bdcf9f",
  "content": "U1_2"
}
#
# ...and the update...
curl -H "Content-Type: application/json" -d @mydoc_u1_2.json -X PUT http://gandalf:5984/mvcc/mydoc
# response:
{"ok":true,
 "id":"mydoc",
 "rev":"2-2686fb85c0681a3d8c411617f048f94f"
}


Done. We hava a second revision of the document. User 2 will now submit his update, but he still holds revision 1. Here is his update.
# here is the document...
{
  "_rev":"1-3557461c60a30b0d156f8b36a1bdcf9f",
  "content": "U2_1"
}
#
# Note that it indeed references the 1 revision of the document
# Now the update itself:
curl -H "Content-Type: application/json" -d @mydoc_u2_1.json -X PUT http://gandalf:5984/mvcc/mydoc
# response: 
{"error":"conflict",
 "reason":"Document update conflict."
}


Here we see the expected result: You are not allowed to update a document if you do not have the latest revision. Another way of saying this is, you can only update the latest revision of a document or slightly different again, you cannot branch the document. At least not in single document update mode.
User 2 may be a bit slow, but he is resourceful. He knows about couchdb's bulk update interface and that this is a way to fork a branch from revision 1. So here is what he does:
 # this is the bulk doc (bulk_u2_1.json): 
{
"docs": [{
  "_id": "mydoc",
  "_rev":"1-3557461c60a30b0d156f8b36a1bdcf9f",
  "content": "U2_1"
}]
}


Granted, this is some sorry bulk file, consisting only of a single document...
# user 2 tries the bulk interface:
curl -H "Content-Type: application/json" -d @bulk_u2_1.json -X POST http://gandalf:5984/mvcc/_bulk_docs
# response: 
[{"id":"mydoc",
  "error":"conflict",
  "reason":"Document update conflict."
}]


Same result as before. Using the bulk interface is not enough. It has to be used with the all-or-nothing option. This is what user 2 tries next.
Now the bulk document contains the all_or_noting property.
# bulk-doc: bulk_u2_2.json
{
"all_or_nothing": true,
"docs": [{
  "_id": "mydoc",
  "_rev":"1-3557461c60a30b0d156f8b36a1bdcf9f",
  "content": "U2_1"
}]
}
#
# ...and now the update:
curl -H "Content-Type: application/json" -d @bulk_u2_2.json -X POST http://gandalf:5984/mvcc/_bulk_docs
# response:
[{"ok":true,
  "id":"mydoc",
  "rev":"2-ba85ce56711c69f7d6200935357d79f9"
}]


Success: this time, the update was accepted. We now have one root-revision and two revisions branching from that root revision:
# the revision tree:
root:     1-3557461c60a30b0d156f8b36a1bdcf9f
branch 1:   2-2686fb85c0681a3d8c411617f048f94f
branch 2:   2-ba85ce56711c69f7d6200935357d79f9


Now that we finally have a conflict, how does couchdb deal with it? Let's simply retrieve the document and see what we get.
# a simple get...
curl  http://gandalf:5984/mvcc/mydoc
# response:
{"_id":"mydoc",
 "_rev":"2-ba85ce56711c69f7d6200935357d79f9",
 "content":"U2_1"
}


Couchdb determines a "winner" and does not let the conflict surface as long as you do not specifically ask for it.
Let's ask for it.
# fetch current document and all conflicting revisions...
curl  http://gandalf:5984/mvcc/mydoc?conflicts=true
# response:
{"_id":"mydoc",
 "_rev":"2-ba85ce56711c69f7d6200935357d79f9",
 "content":"U2_1","_conflicts":["2-2686fb85c0681a3d8c411617f048f94f"]
}


Couchdb presents the revision inserted by user 2 as the winning revision. The version introduced by user 1 appears in the conflicts list.
User 1 may not be aware of the fact that his revision is no longer in favor. He continues to update his branch of the document.
# user 1 updates his branch of the document (mydoc_u1_3.json)
{
  "_rev":"2-2686fb85c0681a3d8c411617f048f94f",
  "content": "U1_3"
}
#
# here is the update:
curl -H "Content-Type: application/json" -d @mydoc_u1_3.json -X PUT http://gandalf:5984/mvcc/mydoc
#response
{"ok":true,
 "id":"mydoc",
 "rev":"3-627f10af94aaf3f31a20c9277c68219a"}


No problem with this update. This means that once a document is branched, each branch can be updated in its own right. In our case the branch user 1 maintains is now one revision longer than the branch maintained by user 2. Let's see what this means in terms of conflicting documents and which branch couchdb now elects to be the winner.
We do a regular GET with the conflicts option enabled.
# GET the winning revision and all conflicting revisions:
curl  http://gandalf:5984/mvcc/mydoc?conflicts=true
# response:
{"_id":"mydoc",
 "_rev":"3-627f10af94aaf3f31a20c9277c68219a",
 "content":"U1_3","_conflicts":["2-ba85ce56711c69f7d6200935357d79f9"]
}


We can conclude two things from the result of this GET. One is that the winning branch has changed. The branch of user 1, which has the highest revision number, is now the winner. Another thing to notice is that the conflict moved up the document tree into its leaves.

Summary

Short summary on "Conflicts on a Single Couchdb Instance":

  • It's not that easy to produce a conflict on a single instance
  • Once you have one, you are free to ignore it, couchdb will always decide on a winning revision
  • In spite of couchdb picking a winner, you are free to follow and work on any branch you please
  • With every change on any branch, the dice are rolled again an a new winner may turn up
That's it for now on working with a single instance. The next entry will deal with two instances (running on two Pies of course :-) and master-master replication between them.



Sunday, 10 August 2014

Installing CouchDB 1.6.0 on the Raspberry Pi

Update 03.11.2015

The Erlang Solutions Repository now contains a new version of Erlang. The major version is now 18. This is too high for the couch in version 1.6.x.
For this reason, please omit the step of including the Erlang Solutions Repository.
Just rely on what you get from the default Raspbina/Debian repos.
I still have to verify this with Wheezy, but for the new Raspbian Jessie image this does the trick.

Also please note that the couch is now available in version 1.6.1.
The instructions below are valid for this version too, as described here.


Building CouchDB 1.6.0 On Your Pi

CouchDB 1.6.0 has been released and of course we want to have it running on our Pis.
I guess my previous blog on installing version 1.5.1 is still valid but couchDB 1.6.0 is now able to run on Erlang 1.17 and that makes for a sight difference during installation.

Preparing the Pi

Nothing new here...
  • I used a brand new 16 GB card.
  • Download the latest Raspbian Wheezy from www.raspberrypi.org/downloads
    At the time of this writing, the image version was 2014-06-20
  • Install the image on your Pi and do the regular raspi-config
    • Extend the partition
    • Set your locales
    • ...
    • Btw, I did not change the default memory split nor did I overclock
  • Re-boot the Pi for the partition extension to take effect
  • update and upgrade your installation
The Pi is now ready.

Add Erlang Solutions' Repository (omit this step, see update 03.11.2015 hint)

Again, we will not add the Cloudant repository for Spidermonkey, but this time add the Erlang Solutions repository in order to install their Erlang package. This will get you an Erlang 1.17 version which is now ok for couchDB 1.6.0.
The following instructions have been taken from Erlang Solutions' download section:
# 
# Add the following line to your /etc/apt/sources.list:
deb http://packages.erlang-solutions.com/debian wheezy contrib

#Next, add the Erlang Solutions public key for apt-secure using following commans:
wget http://packages.erlang-solutions.com/debian/erlang_solutions.asc
sudo apt-key add erlang_solutions.asc

# update repository cache
sudo apt-get update
#  

Install what's needed

Install the following packages:
#   
# Install Compilers
sudo apt-get install erlang-nox
sudo apt-get install erlang-dev
# Spidermonkey JS engine as lib
sudo apt-get install libmozjs185-1.0
# Development headers for spidermonkey lib
sudo apt-get install libmozjs185-dev
# Dev files for libcurl (openSSL)
sudo apt-get install libcurl4-openssl-dev
# Dev files for icu (Unicode and Locales)
sudo apt-get install libicu-dev
#  

Create an account for couchDB

Next we have to create an account for couchDB:
#   
# Create couchDB account
sudo useradd -d /var/lib/couchdb couchdb

sudo mkdir -p /usr/local/{lib,etc}/couchdb /usr/local/var/{lib,log,run}/couchdb /var/lib/couchdb

sudo chown -R couchdb:couchdb /usr/local/{lib,etc}/couchdb /usr/local/var/{lib,log,run}/couchdb

sudo chmod -R g+rw /usr/local/{lib,etc}/couchdb /usr/local/var/{lib,log,run}/couchdb
#   
The next step is downloading the source code and unpacking it:
(find an appropriate mirror near you)
#   
# Download source and unpack
wget http://ftp-stud.hs-esslingen.de/pub/Mirrors/ftp.apache.org/dist/couchdb/source/1.6.0/apache-couchdb-1.6.0.tar.gz
tar xzf apache-couchdb-*.tar.gz
#   
In order to start the "configure" and "make" process, switch into the couchDB directory:
#   
# Change into the couchDB directory
cd apache-couchdb-1.6.0
#   
Now configure the build:
#   
#Configure the build
./configure --prefix=/usr/local --with-js-lib=/usr/lib --with-js-include=/usr/include/js --enable-init
#  
When configure is through, you should see this message:
“You have configured Apache CouchDB, time to relax.
Run 'make && sudo make install' to install.”
This also tells you what the next step will be: running make and make install.
#   
# running make and make install
make && sudo make install
#   
This will take a couple of minutes. But when its done, you have couchDB 1.6.0 compiled on your pi.

Finally create some soft links, make the service start up at boot-time and start couchDB:
#   
# Start couchDB
sudo ln -s /usr/local/etc/init.d/couchdb /etc/init.d/couchdb
sudo /etc/init.d/couchdb start
sudo update-rc.d couchdb defaults
# see if its running...
curl http://127.0.0.1:5984/
#   

As you can see, the couchDB service binds to localhost.
If you want to reach couchDB from another machine, maybe from another Pi :-), change this.
Open local.ini, find the [httpd] section, activate the binding_address and set it to the IP of your Pi:
#   
# make couchDB accessible within your network
sudo vi /usr/local/etc/couchdb/local.ini
#   
Within this file, find the [httpd] section, activate bind_address and set it to 0.0.0.0
It should now look like this:

[httpd]
;port = 5984
bind_address = 0.0.0.0

As a final test, re-boot your Pi and try to reach couchDB Futon:











And that's it. CouchDB 1.6.0 is running on your Pi.

There is one additional step suggested by a kind reader:
#   
# Now including this hint sent by anonymous
# make couchdb user (created above) owner of local ini-file
sudo chown couchdb:couchdb /usr/local/etc/couchdb/local.ini
#   

Credits

The instructions above are based on an installation guide compiled by Dave Cottlehuber on the new couchDB Confluence Wiki. It describes the process of installing couchDB on a Debian system.
The Wiki entry is here.
I slightly adjusted this process to be working for the Pi too and now with the Erlang Solutions repository included, this guide is even closer to the Wiki than the one for version 1.5.1.

Sunday, 11 May 2014

Installing CouchDB on the Raspberry Pi

Installing CouchDB on the Raspberry Pi

Why concern yourself with CouchDB

There are a lot of noSQL databases out there. Most of them are designed to be working distributed across a network and thus are subject to the CAP Theorem, meaning they are positioned somewhere within the triangle of Consistency, Availability and Partition Tolerance.
A beautiful article dealing with the CAP Theorem (and how this theorem is related to the first concert of the Sex Pistols) can be found here.
Personally I tend to associate the CAP Theorem more with Meat Loaf's immortal Two Out Of Three Ain't Bad, because it all comes down to that you can only go for two of the CAP features, but never for all three at once.

The theorem implies that a software developer or architect has to carefully select a database according to the needs of his application.
I came across couchDB while researching for a client insisting on offline capability being a core feature of his application.
If you want a database to solve your offline capability problem, you are looking for one with at least these features:
  • distributed
  • clever replication patterns
  • eventual consistency
 Of course you have to consider a lot more, like availability on different devices, replication protocol, security etc.

Finally you have managed to replicate your data into even the remotest parts of this world, provided that the devices hosting your application are at least online every now and then.

But what about the application itself? How can we keep this up to date in this offline scenario?

Actually this is where couchDB really kicks in.
On top of just being a database, couchDB can serve its own web applications called couchApps. And these Apps are actually stored as documents inside of couchDB. And as such they can be replicated.

Nice feature, this.

Hopefully this will fire up your interest in couchDB and make you curious for all its other features like being schema-less, offering a pure REST-API, employing map-and-reduce queries and last but not least being designed with running on small devices in mind.

Small devices like, for instance, the Raspberry Pi.

How To Get CouchDB On The Pi

To install couchDB on your Pi, you have in fact two basic options:
  • install the binary package from Debian repository (e.g. with apt-get)
  • build from source
At the time of this writing, the latest stable version of couchDB was 1.5.1.
The binary package you will get from the Wheezy repository is 1.2.0-5.
Its quite a way from 1.2... to 1.5...

If version 1.2 is all you need, just do this:
sudo apt-get install couchdb
If you are a bit more ambitious, then read on.

Building CouchDB On Your Pi

The following instructions are based on an installation guide compiled by Dave Cottlehuber on the new couchDB Confluence Wiki. It describes the process of installing couchDB on a Debian system.
The Wiki entry is here.
With just a little modification, this process works for the Pi too.

The basic idea here is, to only build what is necessary, couchDB, and take what you can (Spidermonkey, Erlang and supporting libs) as binaries.

But let's do this step by step.

Preparing the Pi

  • I used a brand new 16 GB card.
  • Download the latest Raspbian Wheezy from www.raspberrypi.org/downloads
    At the time of this writing, the image version was 2014-01-07
  • Install the image on your pi and do the regular raspi-config
    • Extend the partition
    • Set your locales
    • ...
    • I did not change the default memory split
  • Re-boot the pi for the partition extension to take effect
  • update and upgrade your installation
The pi is now ready.

Install all we need

The Wiki suggests to add the Cloudant repository for Spidermonkey and the Erlang Solutions repository for Erlang respectively.
I tried this and encountered some problems on the Pi:
  • The Erlang package you get this way is version 17+
    The configure-process later complained about this version being out of range (I guess its too new)
  • The Cloudant repo lacked support armhf 
On the pi you are better off with what the standard repository offers.
Install the following packages:
# Install lsb-release
sudo apt-get install lsb-release

# Install Compilers
sudo apt-get install erlang-nox
sudo apt-get install erlang-dev

# Install what else is needed
sudo apt-get install libmozjs185-1.0
sudo apt-get install libmozjs185-dev
sudo apt-get install libcurl4-openssl-dev
sudo apt-get install libicu-dev
Next we have to create an account for couchDB:
# Create couchDB account

sudo useradd -d /var/lib/couchdb couchdb

sudo mkdir -p /usr/local/{lib,etc}/couchdb /usr/local/var/{lib,log,run}/couchdb /var/lib/couchdb

sudo chown -R couchdb:couchdb /usr/local/{lib,etc}/couchdb /usr/local/var/{lib,log,run}/couchdb

sudo chmod -R g+rw /usr/local/{lib,etc}/couchdb /usr/local/var/{lib,log,run}/couchdb
The next step is downloading the source code and unpacking it:
(find an appropriate mirror near your location)
# Download source and unpack
wget http://ftp-stud.hs-esslingen.de/pub/Mirrors/ftp.apache.org/dist/couchdb/source/1.5.1/apache-couchdb-1.5.1.tar.gz

tar xzf apache-couchdb-*.tar.gz
In order to start the "configure" and "make" process, switch into the couchDB directory:
# Change into the couchDB directory
cd apache-couchdb-1.5.1
Now configure the build:
#Configure the build
./configure --prefix=/usr/local --with-js-lib=/usr/lib --with-js-include=/usr/include/js --enable-init
When configure is through, you should see this message:
“You have configured Apache CouchDB, time to relax.
Run 'make && sudo make install' to install.”
This also tells you what the next step will be: running make and make install.
# running make and make install
make && sudo make install
This will take a couple of minutes. But when its done, you have couchDB 1.5.1 compiled on your pi.

Finally create some soft links, make the service start up at boot-time and start couchDB:
# Start couchDB
sudo ln -s /usr/local/etc/init.d/couchdb /etc/init.d/couchdb
sudo /etc/init.d/couchdb start
sudo update-rc.d couchdb defaults
# see if its running...
curl http://127.0.0.1:5984/

As you can see, the couchDB service binds to localhost.
If you want to reach couchDB from another machine, maybe from another Pi :-), change this.
On start up, couchDB reads its configuration in file chain that you can see by typing:
# View config file chain
couchdb -c
You should see something like this:





CouchDB first reads default.ini. Afterwards these settings can be enriched or overwritten by the local.ini setting.
Documentation suggests to change local.ini for default.ini might be overwritten by upgrade or re-installation.
Open local.ini, find the [httpd] section, activate the binding_address and set it to the IP of your Pi:
# make couchDB accessible within your network
sudo vi /usr/local/etc/couchdb/local.ini.
As a final test, re-boot your Pi and try to reach couchDB Futon:











And that's it. CouchDB 1.5.1 is running on your Pi.

PS
This blog is call Playing JEE On The Pi, but the next entries will probably be more JavaScript than Java. I hope you don't mind...