Showing posts with label raspberry pi. Show all posts
Showing posts with label raspberry pi. 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.




Sunday, 20 September 2015

Installing Couchdb 1.6.1 on a Raspberry Pi Model 2

Couchdb 1.6.1 on a Pi 2

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.

Installing the couch version 1.6.1

This will probably be my shortest post ever.
Last week I installed couchdb version 1.6.1 on my Raspberry Pi Model 2.
I did this for two reasons. One was to have the couch on Pi 2. The second was to see if my own install instructions are still valid for couch 1.6.1 and Pi Model 2. Two readers reported problems, so I was a little worried.

But everything worked well and it was soon time to relax.
I went along the instructions using copy and past, with only two exceptions:
The instructions are still valid. They worked for me and should do so for you.

Have fun.

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...



Sunday, 18 August 2013

Running JBoss AS7 on Raspberry Pi

Running JBoss

Choose a Mode

The JBoss installation on our Pi offers a couple of different configurations out of the box.
The first choice to be taken is whether to start JBoss in standalone or domain mode. 
Doman mode is a special management mode which we might inspect later. For now we will set off in standalone mode. This just means we will have to configure each instance individually. We can still cluster our standalone instances and even go for high availability in standalone mode.

Choose a Configuration

All the scripts for starting JBoss are located in JBOSS_HOME/bin.
JBoss is started in standalone mode by running standalone.sh:
standalone.sh
Without any parameters, standalone.sh will use the configuration defined in standalone.xml, located in JBOSS_HOME/standalone/configuration directory.
You can choose another configuration by specifying it on the command line:
standalone.sh –server-config=standalone-full.xml

My approach is to backup standlone.xml and to edit the original according to my needs. I’m going for standalone.xml to have a small footprint to start with. Additional features can be included later, either by editing standalone.xml or by using the management console or the command line interface CLI.

JBoss and Java

Standalone.sh inspects first JAVA then JAVA_HOME environment variable for a hint, where java is installed. If both variables are not set, JAVA is simply set to java which means the PATH variable determines if and where Java will be found.
And it will be found like this:
  • We find /usr/bin in our classpath (verify by typing $PATH on a Pi console)
  • /usr/bin contains “java”
  • Java is a softlink into alternatives  (/etc/alternatives/java)
  • Following this link, we find: java -> /usr/lib/jvm/java-7-openjdk-armel/jre/bin/java
And that is what we get when we run Java on the Pi.
Everything depends on soft links and the alternatives concept. This makes it very easy to switch to another Java installation in the future.
To make a long story short, leave everything as it is.

Making JBoss available within Your Network

All my Pis have static IP addresses within my private network. This can be configured within your router.
If you want to be able to reach a JBoss instance running on a Pi, you have to configure JBoss’ “Public Interface”.
This configuration is done standalone.xml located in /JBOSS_HOME/standalone/configuration.
Find the interfaces section and edit the public and the management interface like this:
<interfaces>
        <interface name="management">
            <inet-address value="xxx.xxx.xxx.xxx"/>
        </interface>
        <interface name="public">
            <inet-address value="xxx.xxx.xxx.xxx"/>
        </interface>
</interfaces>
Where xxx.xxx.xxx.xxx is the IP you configured in your rooter for this specific Pi.

Save the changes.

Create JBoss Users

In order to access JBoss’ admin console, we need to create a management-realm user.
This is done by running the add-user.sh script located in /JBOSS_HOME/bin directory.
Be sure to select management realm.







For later use, we create an application-realm user.
For now, assign the guest role to this user.







Starting JBoss

Let’s give JBoss a test run.
Switch to /JBOSS_HOME/bin and run standalone.sh in a Pi terminal window:
sh standalone.sh











When JBoss is up, you can access the web-server from any client within your network.
If you assigned a name to your Pi within your router, you can use this name to access the Pi. If not, use the Pi’s IP address.

 From here, you should be able to access the management console. As credentials, enter the admin-user you just created using add-user script.













Stopping JBoss

The best way to stop JBoss is by using the CLI.
Open another terminal session on the Pi and switch to /JBOSS_HOME/bin.
Run
jboss-cli.sh
The CLI starts in “disconnected” mode, so you have to connect.
Type connect xxx.xxx.xxx.xxx (IP address of your Pi)
When connected successfully, enter
:shutdown
JBoss will shut down and you can exit the terminal session.











Summary

Now we have Java and JBoss installed on our Pi(s).
JBoss is now accessible from anywhere within our network.
We created a management-user and an application-user.
We can start and stop JBoss on the Pi and have access to its management console.
In the next post we will develop our first JEE application and deploy it to the Pi.
See you then…

Thursday, 8 August 2013

Setting up the Raspberry Pi installing Debian. Java and JBoss

Setting up the Pi  

Before we can start playing JEE on the Raspberry Pi, a few things need to be set up.
As this is not too interesting, I try to cover it in a hurry. Please leave a note if you want one topic or the other dealt with in more detail.

What this post will cover:

  • Choosing and installing a suitable operating system for your Pi
  • Installing Java on the Pi
  • Installing JBoss on the Pi
  • Setting up the Pi network

Choosing and installing a suitable operating system for your Pi

The first task now is to choose and install a suitable operating system for your Pi.
There are several options available on the download page of the Raspberry Pi Foundation: http://www.raspberrypi.org/downloads
We go for Soft-float Debian “wheezy” for the reasons described on the page:
This image is identical to the Raspbian “wheezy” image, but uses the slower soft-float ABI. It is only intended for use with software such as the Oracle JVM which does not yet support the hard-float ABI used by Raspbian.”
 If we want to run java, what we do, we must stick to an operating system offering a soft-float ABI.
I tried the Java8 preview offered by Oracle here: http://jdk8.java.net/download.html which is supposed to support the hard-float ABI. But sorry, this works only when running Java in client mode. As soon as your software needs server-mode, you are out of the game.
This is also true for the embedded version of the Standard Edition.
Do we need server mode? Yes, because software like JBoss AS7 needs it.
So as of now (at the time of this writing) the soft-float Debian “wheezy” seems like a good idea for starting off:
  • Download soft-float Debian “wheezy” image
  • Bring the image to your sd-card
  • Start the Pi and run through the config-script that will start up on first boot
Hint: The config-script now offers to assign a hostname to your Pi. It is a good idea to make use of this. Later, when you have a couple of console windows open on your desktop machine pointing to different Pis, you will be glad to see meaningful prompts identifying the Pis respectively (of course you can change the hostname of your Pi later, but using the config-script is easier).
Later, when plugging your Pis into your network, you want to add these names to your router’s configuration.

Installing Java JDK on the Pi

The next step is installing Java on your Pis.
Software like the Oracle Java 8 preview would have to be installed manually.
The regular Java versions are maintained in the Debian software repositories and can easily be installed by Debians package manager.
I chose this package and installed it with apt-get.
Open up a console and enter:

sudo apt-get install openjdk-7-jdk

After the dust has settled, you have an openJDK 7 on your Pi.

Installing JBoss AS7 on the Pi

When installing JBoss, a little bit more manual effort is required. Here is what you have to do:

Step 1: Download the package

At the time of this writing, JBoss AS7 was available in version 7.1.1.Final.
You can download this package from the console using wget:

sudo wget http://download.jboss.org/jbossas/7.1/jboss-as\
 -7.1.1.Final/jboss-as-7.1.1.Final.tar.gz

Step 2: Extract the download 

Now that we have the tar-file on the pi we have to extract it into a suitable directory.
/usr/local is a good choice:

sudo tar zxvf jboss-as-7.1.1.Final.tar.gz -C /usr/local

(don't forget the -C option or the necessary directories will not be created)

Step 3: Smoothen the installation directory

JBoss AS7 is now installed in /usr/local/jboss-as-7.1.1.Final
If you find this to be a bit unhandy, change it like this:

sudo mv jboss-as-7.1.1.Final/ jboss7

Step 4: Make pi the owner of the installation

I like my pi user to be the owner of the installation.
You can do this with the Change Owner command:
sudo chown -R pi:pi /usr/local/jboss7/

JBoss AS7 is now installed and ready to run on your Raspberry Pi.
Quite some heavy lifting for a little Pi like that. But we'll see JBoss behaves itself very well.

Network configuration

My setup consists of 3 Raspberry Pis plugged into the local network behind my router.
On the router assigned static IP addresses and logical names to them. The Pis are named “frodo”, “samwise” and “gandalf”. 
Naming your Pis according to your rooter's configuration will help you to stay on top of things later.

Before getting serious with playing JEE on the Pi we'll have to do some minor configurations on JBoss.
But I leave this for the next post.

Wednesday, 7 August 2013

Why this blog?

Why this blog?

This blog was inspired by a very interesting enterprise architecture project I had the pleasure of being part of. Two reasons made this project somehow more interesting than others. The architecture was supposed to cover service integration spanning the cloud, data center hosted services and services running on small and very small devices operated in the field. On top of that a lot of these field devices were manufactured by the customer himself, making them quite propriety.
This translates into distributed enterprise computing in a very heterogeneous environment.
Perfect fit for the by now quite mature JEE technologies?
In the end, only time will tell. But what we’ve seen so far looks really promising.
Anyway, we used a lot of “heavy weight” JEE technologies on very limited devices. And we are still experimenting.
This blog describes some of these efforts.
I choose the Raspberry Pi, or Pi for short, for representing our small field devices because it is easily available and quite cheap. Two or three Pis in a local network and JEE computing suddenly becomes very tangible and a lot of fun (if you have the kind of humor for this).

If you find this to be interesting, keep on reading and let me know what you think.