Tuesday, November 20, 2012

Android: Trusting SSL certificates

We use a self-signed SSL certificate for the test version of our backend web service. Since our certificate isn't signed by a CA that Android trusts by default, we need to add our server's public certificate to our Android app's trusted store.

These same instructions apply to trusting a custom CA, except you'd get the public certificate directly from the CA instead of from a server.
Required tools:
1. Grab the public certificate from the server you want to trust. Replace ${MY_SERVER} with your server's address.
echo | openssl s_client -connect ${MY_SERVER}:443 2>&1 | \
 sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > mycert.pem
For example, here's the PEM-encoded public certificate from google.com:
-----BEGIN CERTIFICATE-----
MIIDITCCAoqgAwIBAgIQL9+89q6RUm0PmqPfQDQ+mjANBgkqhkiG9w0BAQUFADBM
MQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkg
THRkLjEWMBQGA1UEAxMNVGhhd3RlIFNHQyBDQTAeFw0wOTEyMTgwMDAwMDBaFw0x
MTEyMTgyMzU5NTlaMGgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlh
MRYwFAYDVQQHFA1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKFApHb29nbGUgSW5jMRcw
FQYDVQQDFA53d3cuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
gYEA6PmGD5D6htffvXImttdEAoN4c9kCKO+IRTn7EOh8rqk41XXGOOsKFQebg+jN
gtXj9xVoRaELGYW84u+E593y17iYwqG7tcFR39SDAqc9BkJb4SLD3muFXxzW2k6L
05vuuWciKh0R73mkszeK9P4Y/bz5RiNQl/Os/CRGK1w7t0UCAwEAAaOB5zCB5DAM
BgNVHRMBAf8EAjAAMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwudGhhd3Rl
LmNvbS9UaGF3dGVTR0NDQS5jcmwwKAYDVR0lBCEwHwYIKwYBBQUHAwEGCCsGAQUF
BwMCBglghkgBhvhCBAEwcgYIKwYBBQUHAQEEZjBkMCIGCCsGAQUFBzABhhZodHRw
Oi8vb2NzcC50aGF3dGUuY29tMD4GCCsGAQUFBzAChjJodHRwOi8vd3d3LnRoYXd0
ZS5jb20vcmVwb3NpdG9yeS9UaGF3dGVfU0dDX0NBLmNydDANBgkqhkiG9w0BAQUF
AAOBgQCfQ89bxFApsb/isJr/aiEdLRLDLE5a+RLizrmCUi3nHX4adpaQedEkUjh5
u2ONgJd8IyAPkU0Wueru9G2Jysa9zCRo1kNbzipYvzwY4OA8Ys+WAi0oR1A04Se6
z5nRUP8pJcA2NhUzUnC+MY+f6H/nEQyNv4SgQhqAibAxWEEHXw==
-----END CERTIFICATE-----
2. Android has built-in support for the Bouncy Castle keystore format (BKS). Put Bouncy Castle's jar in your classpath, and create a keystore containing only your trusted key.
export CLASSPATH=bcprov-jdk16-145.jar
CERTSTORE=res/raw/mystore.bks
if [ -a $CERTSTORE ]; then
    rm $CERTSTORE || exit 1
fi
keytool \
      -import \
      -v \
      -trustcacerts \
      -alias 0 \
      -file <(openssl x509 -in mycert.pem) \
      -keystore $CERTSTORE \
      -storetype BKS \
      -provider org.bouncycastle.jce.provider.BouncyCastleProvider \
      -providerpath /usr/share/java/bcprov.jar \
      -storepass ez24get
3. Create a custom Apache HttpClient that uses your custom store for HTTPS connections.
import android.content.Context;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.SingleClientConnManager;

import java.io.InputStream;
import java.security.KeyStore;

public class MyHttpClient extends DefaultHttpClient {

  final Context context;

  public MyHttpClient(Context context) {
    this.context = context;
  }

  @Override protected ClientConnectionManager createClientConnectionManager() {
    SchemeRegistry registry = new SchemeRegistry();
    registry.register(
        new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
    registry.register(new Scheme("https", newSslSocketFactory(), 443));
    return new SingleClientConnManager(getParams(), registry);
  }

  private SSLSocketFactory newSslSocketFactory() {
    try {
      KeyStore trusted = KeyStore.getInstance("BKS");
      InputStream in = context.getResources().openRawResource(R.raw.mystore);
      try {
        trusted.load(in, "ez24get".toCharArray());
      } finally {
        in.close();
      }
      return new SSLSocketFactory(trusted);
    } catch (Exception e) {
      throw new AssertionError(e);
    }
  }
}

Originally Posted in  crazybob blog 

Wednesday, November 14, 2012

Using Hadoop And PHP

Using Hadoop And PHP

php-icon

Getting Started

So first things first.  If you haven’t used Hadoop before you’ll first need to download a Hadoop release and make sure you have Java and PHP installed.  To download Hadoop head over to:
http://hadoop.apache.org/common/releases.html
Click on download a release and choose a mirror.  I suggest choosing the most recent stable release.  Once you’ve downloaded Hadoop, unzip it.
user@computer:$ tar xpf hadoop-0.20.2.tar.gz
I like to create a symlink to the hadoop-<release> directory to make things easier to manage.
user@computer:$ link -s hadoop-0.20.2 hadoop
Now you should have everything you need to start creating a Hadoop PHP job.

Creating The Job

For this example I’m going to create a simple Map/Reduce job for Hadoop.  Let’s start by understanding what we want to happen.
  1. We want to read from an input system – this is our mapper
  2. We want to do something with what we’ve mapped – this is our reducer
At the root of your development directory, let’s create another directory called script.  This is where we’ll store our PHP mapper and reducer files.
user@computer:$ ls

.
..
hadoop-0.20.2
hadoop-0.20.2.tar.gz
hadoop
user@computer:$ mkdir script
Now let’s being creating our mapper script in PHP.  Go ahead and create a PHP file called mapper.php under the script directory.
user@computer:$ touch script/mapper.php
Now let’s look at the basic structure of a PHP mapper.

#!/usr/bin/php
<?php
//this can be anything from reading input from files, to retrieving database content, soap calls, etc.
//for this example I'm going to create a simple php associative array.
$a = array(
'first_name' => 'Hello',
'last_name' => 'World'
);
//it's important to note that anything you send to STDOUT will be written to the output specified by the mapper.
//it's also important to note, do not forget to end all output to STDOUT with a PHP_EOL, this will save you a lot of pain.
echo serialize($a), PHP_EOL;
?>
So this example is extremely simple.  Create a simple associative array and serialize it.  Now onto the reducer.  Create a PHP file in the script directory called reducer.php.
user@computer:$ touch script/reducer.php
Now let’s take a look at the layout of a reducer.

#!/usr/bin/php
 
<?php
 
//Remember when I said anything put out through STDOUT in our mapper would go to the reducer.
//Well, now we read from the STDIN to get the result of our mapper.
//iterate all lines of output from our mapper
while (($line = fgets(STDIN)) !== false) {
    //remove leading and trailing whitespace, just in case  
    $line = trim($line);
    //now recreate the array we serialized in our mapper
    $a = unserialize($line);
    //Now, we do whatever we need to with the data.  Write it out again so another process can pick it up,
    //send it to the database, soap call, whatever.  In this example, just change it a little and
    //write it back out.
    $a['middle_name'] = 'Jason';
    //do not forget the PHP_EOL
    echo serialize($a), PHP_EOL;
}//end while
?>
So now we have a very simple mapper and reducer ready to go.

Execution

So now let’s run it and see what happens.  But first, a little prep work.  We need to specify the input directory that will be used when the job runs.
user@computer:$ mkdir input
user@computer:$ touch input/conf
Ok, that was difficult.  We have an input directory and we’ve created an empty conf file.  The empty conf file is just something that the mapper will use to get started.  For now, don’t worry about it.  Now let’s run this bad boy.  Make sure you have your JAVA_HOME set, this is usually in the /usr directory.  You can set this by running #export JAVA_HOME=/usr.
user@computer:$ hadoop/bin/hadoop jar hadoop/contrib/streaming/hadoop-0.20.2-streaming.jar -mapper script/mapper.php -reducer script/reducer.php -input input/* -output output
So here’s what the command does.  The first part executes the hadoop execute script.  The “jar” argument tells hadoop to use a jar, in this case it tells it to use “hadoop/contrib/streaming/hadoop-0.20.2-streaming.jar”.  Next we pass the mapper and reducer arguments to the job and specify input and output directories.  If we wanted to, we could pass configuration information to the mapper, or files, etc.  We would just use the same line read structure that we used in the reducer to get the information.  That’s what would go in the input directory if we needed it to.  But for this example, we’ll just pass nothing.  Next the output directory will contain the output of our reducer.  In this case if everything works out correct, it will contain the PHP serialized form of our modified $a array.  If all goes well you should see something like this:
user@computer:$ hadoop/bin/hadoop jar hadoop/contrib/streaming/hadoop-0.20.2-streaming.jar -mapper script/mapper.php -reducer script/reducer.php -input input/* -output output

10/12/10 12:53:56 INFO jvm.JvmMetrics: Initializing JVM Metrics with processName=JobTracker, sessionId=
10/12/10 12:53:56 WARN mapred.JobClient: No job jar file set.  User classes may not be found. See JobConf(Class) or JobConf#setJar(String).
10/12/10 12:53:56 INFO mapred.FileInputFormat: Total input paths to process : 1
10/12/10 12:53:56 INFO streaming.StreamJob: getLocalDirs(): [/tmp/hadoop-root/mapred/local]
10/12/10 12:53:56 INFO streaming.StreamJob: Running job: job_local_0001
10/12/10 12:53:56 INFO streaming.StreamJob: Job running in-process (local Hadoop)
10/12/10 12:53:56 INFO mapred.FileInputFormat: Total input paths to process : 1
10/12/10 12:53:56 INFO mapred.MapTask: numReduceTasks: 1
10/12/10 12:53:56 INFO mapred.MapTask: io.sort.mb = 100
10/12/10 12:53:57 INFO mapred.MapTask: data buffer = 79691776/99614720
10/12/10 12:53:57 INFO mapred.MapTask: record buffer = 262144/327680
10/12/10 12:53:57 INFO streaming.PipeMapRed: PipeMapRed exec [/root/./script/mapper.php]
10/12/10 12:53:57 INFO streaming.PipeMapRed: MRErrorThread done
10/12/10 12:53:57 INFO streaming.PipeMapRed: Records R/W=0/1
10/12/10 12:53:57 INFO streaming.PipeMapRed: MROutputThread done
10/12/10 12:53:57 INFO streaming.PipeMapRed: mapRedFinished
10/12/10 12:53:57 INFO mapred.MapTask: Starting flush of map output
10/12/10 12:53:57 INFO mapred.MapTask: Finished spill 0
10/12/10 12:53:57 INFO mapred.TaskRunner: Task:attempt_local_0001_m_000000_0 is done. And is in the process of commiting
10/12/10 12:53:57 INFO mapred.LocalJobRunner: Records R/W=0/1
10/12/10 12:53:57 INFO mapred.TaskRunner: Task 'attempt_local_0001_m_000000_0' done.
10/12/10 12:53:57 INFO mapred.LocalJobRunner:
10/12/10 12:53:57 INFO mapred.Merger: Merging 1 sorted segments
10/12/10 12:53:57 INFO mapred.Merger: Down to the last merge-pass, with 1 segments left of total size: 70 bytes
10/12/10 12:53:57 INFO mapred.LocalJobRunner:
10/12/10 12:53:57 INFO streaming.PipeMapRed: PipeMapRed exec [/root/./script/reducer.php]
10/12/10 12:53:57 INFO streaming.PipeMapRed: R/W/S=1/0/0 in:NA [rec/s] out:NA [rec/s]
10/12/10 12:53:57 INFO streaming.PipeMapRed: Records R/W=1/1
10/12/10 12:53:57 INFO streaming.PipeMapRed: MROutputThread done
10/12/10 12:53:57 INFO streaming.PipeMapRed: MRErrorThread done
10/12/10 12:53:57 INFO streaming.PipeMapRed: mapRedFinished
10/12/10 12:53:57 INFO mapred.TaskRunner: Task:attempt_local_0001_r_000000_0 is done. And is in the process of commiting
10/12/10 12:53:57 INFO mapred.LocalJobRunner:
10/12/10 12:53:57 INFO mapred.TaskRunner: Task attempt_local_0001_r_000000_0 is allowed to commit now
10/12/10 12:53:57 INFO mapred.FileOutputCommitter: Saved output of task 'attempt_local_0001_r_000000_0' to file:/root/output
10/12/10 12:53:57 INFO mapred.LocalJobRunner: Records R/W=1/1 > reduce
10/12/10 12:53:57 INFO mapred.TaskRunner: Task 'attempt_local_0001_r_000000_0' done.
10/12/10 12:53:57 INFO streaming.StreamJob:  map 100%  reduce 100%
10/12/10 12:53:57 INFO streaming.StreamJob: Job complete: job_local_0001
10/12/10 12:53:57 INFO streaming.StreamJob: Output: output
If you get errors where it’s complaining about the output directory, just remove the output directory and try again.

Result

Once you’ve got something similar to the above and no errors, we can check out the result.
user@computer:$ cat output/*

a:3:{s:10:"first_name";s:5:"Hello";s:9:"last_name";s:5:"World";s:11:"middle_name";s:5:"Jason";}
There we go, a serialized form of our modified PHP array $a.  That’s all there is to it.  Now, go forth and Hadoop.

Sunday, November 4, 2012

Downloadable books


Chris J  started a page of links to various books available for download in PDF format. The page contains direct links to the books, without going through a data-harvesting site, as is so often posted here.


http://cfajohnson.com/computers/pdflinks.shtml

"Self-Service Linux®: Mastering the Art of Problem Determination - Free 456 Page eBook"

Get the book directly, without going through a data-harvesting site:http://www.informit.com/content/images/013147751X/downloads/013147751X_book.pdf

Tuesday, June 19, 2012

HOWTO Set KeepAlive in Apache HTTPd

To set keep=alive parameters in Apache2  Httpd, you need to pay attention to 3 directives:

KeepAlive


KeepAliveTimeout


MaxKeepAliveRequests


KeepAlive Directive


Description:Enables HTTP persistent connections
Syntax:KeepAlive On|Off
Default:KeepAlive On
Context:server config, virtual host
Status:Core
Module:core

The Keep-Alive extension to HTTP/1.0 and the persistent connection feature of HTTP/1.1 provide long-lived HTTP sessions which allow multiple requests to be sent over the same TCP connection. In some cases this has been shown to result in an almost 50% speedup in latency times for HTML documents with many images. To enable Keep-Alive connections, set KeepAlive On.

For HTTP/1.0 clients, Keep-Alive connections will only be used if they are specifically requested by a client. In addition, a Keep-Alive connection with an HTTP/1.0 client can only be used when the length of the content is known in advance. This implies that dynamic content such as CGI output, SSI pages, and server-generated directory listings will generally not use Keep-Alive connections to HTTP/1.0 clients. For HTTP/1.1 clients, persistent connections are the default unless otherwise specified. If the client requests it, chunked encoding will be used in order to send content of unknown length over persistent connections.

When a client uses a Keep-Alive connection it will be counted as a single "request" for the MaxRequestsPerChild directive, regardless of how many requests are sent using the connection.

KeepAliveTimeout Directive


Description:Amount of time the server will wait for subsequent requests on a persistent connection
Syntax:KeepAliveTimeout seconds
Default:KeepAliveTimeout 5
Context:server config, virtual host
Status:Core
Module:core

The number of seconds Apache will wait for a subsequent request before closing the connection. Once a request has been received, the timeout value specified by the Timeout directive applies.
Setting KeepAliveTimeout to a high value may cause performance problems in heavily loaded servers. The higher the timeout, the more server processes will be kept occupied waiting on connections with idle clients.
In a name-based virtual host context, the value of the first defined virtual host (the default host) in a set of NameVirtualHost will be used. The other values will be ignored.

MaxKeepAliveRequests Directive


Description:Number of requests allowed on a persistent connection
Syntax:MaxKeepAliveRequests number
Default:MaxKeepAliveRequests 100
Context:server config, virtual host
Status:Core
Module:core

The MaxKeepAliveRequests directive limits the number of requests allowed per connection whenKeepAlive is on. If it is set to 0, unlimited requests will be allowed. We recommend that this setting be kept to a high value for maximum server performance.
For example:
MaxKeepAliveRequests 500

Sunday, June 17, 2012

How to Install Apache CouchDB on CentOS 6 (from Source and EPEL)

CouchDB is an Apache project.

Just like the name suggest it is a database. CouchDB is a NoSQL database. NoSQL databases doesn’t have any schema, tables, etc, that you’ll typically see in a traditional databases like Oracle or MySQL. The data in CouchDB are stored as JSON document, which you can access from a web browser using HTTP.

This article explains how to install CouchDB on RHEL based systems. For example, CentOS, Red Hat, Oracle Enterprise Linux, etc.

There are two methods to install CouchDB. You can install it from EPEL repository, or install from CouchDB source code.

Method 1: Install from EPEL

First, enable EPEL repository as we explained earlier.


Verify that the couchdb is available for yum install.

# yum info couchdb
Name        : couchdb
Arch        : x86_64
Version     : 1.0.3
Release     : 2.el6
Size        : 1.7 M
Repo        : epel
Summary     : A document database server, accessible via a RESTful JSON API


Install couchdb. Depending on your system, this might install lot of dependent packages. On my system, it installed 36 packages in total.


# yum install couchdb

Modify the local.ini file and add a line for bind_address and give the ip-address the system where couchdb is installed.

# vi /etc/couchdb/local.ini
[httpd]
;port = 5984
;bind_address = 127.0.0.1
bind_address = 192.168.101.38


Start the couchdb services

# service couchdb start
Starting couchdb:                [  OK  ]

# service couchdb status
couchdb (pid  29915) is running...

Verify that the couchdb works by going to the URL: http://{your-ip-address}:5984 , it should display a web-page that has the following message.

{“couchdb”:”Welcome”,”version”:”1.0.3″}
Go to: http://{your-ip-address}:5984/_utils/ from where you can create and manage the couchdb database.

Method 2: Install from CouchDB Source Code

If you like to install it yourself from the source code, first you should satisfy all the dependencies.
Install the following standard packages from the CentOS repository.

# yum info gcc libtool xulrunner-devel libicu-devel openssl-devel

Install Erlang

Download the latest version of Erland from here. Or, you can use the wget as shown below to directly download it.

cd /usr/src
wget http://www.erlang.org/download/otp_src_R15B01.tar.gz
tar xvfz otp_src_R15B01.tar.gz

We’ll be installing couchdb and all its dependencies under /opt/couchdb directory. So, while installing erlang, give the prefix as /opt/couchdb/erlang as shown below.

cd otp_src_R15B01
./configure --prefix=/opt/couchdb/erlang --without-termcap --without-javac --enable-smp-support --disable-hipe
make
make install


Install Curl

Download the latest version of Curl from here. Or, you can use the wget as shown below to directly download it.

cd /usr/src
wget http://curl.haxx.se/download/curl-7.26.0.tar.gz
tar xvfz curl-7.25.0.tar.gz

Just like Erlang, we’ll be installing Curl also under /opt/couchdb directory. So, while installing curl, give the prefix as /opt/couchdb/curl as shown below.

cd curl-7.25.0
./configure --prefix=/opt/couchdb/curl
make
make install


SpiderMonkey JS Engine

Download the latest version of SpiderMonkey JS from here. Or, you can use the wget as shown below to directly download it.

cd /usr/src
wget http://ftp.mozilla.org/pub/mozilla.org/js/js185-1.0.0.tar.gz
tar xvfz js185-1.0.0.tar.gz

Please note that you have to cd to “js/src” subdirectory under js-1.8.5 to do the ./configure and make as shown below to install spidermonkey js engine.

cd js-1.8.5/js/src
./configure
make
make install


You’ll see the libmozjs185.so.1.0.0 and libmozjs185-1.0.a installed under /usr/local/lib

# ls -ltr /usr/local/lib
-rwxr-xr-x. 1 root root 3671764 May 30 09:39 libmozjs185.so.1.0.0
-rwxr-xr-x. 1 root root 5523616 May 30 09:39 libmozjs185-1.0.a
lrwxrwxrwx. 1 root root      35 May 30 09:40 libmozjs185.so.1.0 -> /usr/local/lib/libmozjs185.so.1.0.0
lrwxrwxrwx. 1 root root      33 May 30 09:40 libmozjs185.so -> /usr/local/lib/libmozjs185.so.1.0

Note: If spidermonkey JS library is not installed, you’ll get the following error mesage while trying to do the ./configure mentioned in the next step.

checking for JS_NewObject in -lmozjs185... no

configure: error: Could not find the js library.

Is the Mozilla SpiderMonkey library installed?

Install CouchDB

Download the latest version of Couchdb from here. Or, you can use the wget as shown below to directly download it.

cd /usr/src
wget http://apache.mirrors.pair.com/couchdb/releases/1.2.0/apache-couchdb-1.2.0.tar.gz
tar xvfz apache-couchdb-1.2.0.tar.gz

While installing couchdb, you should set ERL, ERLC, CURL_CONFIG environment variables as shown below. These are required during the ./config of couchdb.

Just like the prereqs, we’ll be installing couchdb under /opt/couchdb directory. So, give the prefix as /opt/couchdb/couchdb as shown below.

cd apache-couchdb-1.2.0
export ERL=/opt/couchdb/erlang/bin/erl
export ERLC=/opt/couchdb/erlang/bin/erlc
export CURL_CONFIG=/opt/couchdb/curl/bin/curl-config
export LDFLAGS=-L/opt/couchdb/curl/lib
./configure --prefix=/opt/couchdb/couchdb --with-erlang=/opt/couchdb/erlang/lib/erlang/usr/include/ --enable-js-trunk
make
make install

Note: You’ll use the –enable-js-trunk only if you’ve installed the latest version (anything newer than js185-1.0.0) of the SpiderMonkey JS engine. I recommend that you use –enable-js-trunk option.

If you are not using the latest version of spidermonekey JS engine, you may want to use the flags –with-js-include and –with-js-lib and point it to the appropriate location as shown below.

./configure --prefix=/opt/couchdb/couchdb --with-erlang=/opt/couchdb/erlang/lib/erlang/usr/include/ --with-js-include=/usr/include/xulrunner-2/ --with-js-lib=/usr/lib64/xulrunner-devel-2/lib/
Note: If you’ve installed the latest version of spidermonkey js, and if you are not using –enable-js-trunk, you’ll get the following error message during “make” of couchdb:

cc1: warnings being treated as errors
In file included from couch_js/main.c:20:
couch_js/sm170.c: In function req_status:
couch_js/sm170.c:105: error: implicit declaration of function INT_FITS_IN_JSVAL
couch_js/sm170.c: In function evalcx:
couch_js/sm170.c:138: error: implicit declaration of function JS_GetStringChars
couch_js/sm170.c:138: error: assignment makes pointer from integer without a cast
couch_js/sm170.c: In function seal:
couch_js/sm170.c:220: error: implicit declaration of function JS_SealObject
couch_js/sm170.c: At top level:
couch_js/sm170.c:236: error: initialization from incompatible pointer type

Setup CouchDB Startup Services

Create a couchdb user that is required by the couchdb startup program.

# adduser couchdb

Change the ownership of the var directory, where couchdb will write logs and some other information.

# chown -R couchdb /opt/couchdb/couchdb/var/

Create a link under /etc/init.d for couchdb service

# ln -s /opt/couchdb/couchdb/etc/rc.d/couchdb /etc/init.d/couchdb

Finally start the couchdb service.

# service couchdb start
Starting database server couchdb

Verify that the couchdb works by going to the URL: http://{your-ip-address}:5984 , it should display a web-page that has the following message.

{“couchdb”:”Welcome”,”version”:”1.0.3″}

Go to: http://{your-ip-address}:5984/_utils/ from where you can create and manage the coucbdb database.












search

Google
 

.NET Channel

google ADS

Database Channel

White papers from tech republic

ASP.NET Channel

Google Pack