Version 2.0.2
Copyright © 2002, 2003, 2004, 2005 French National Institute For Research In Computer Science And Control (INRIA), Emic Networks
Java, and all Java-based trademarks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries.
Table of Contents
C-JDBC is a database cluster middleware that allows any Java™ application (standalone application, servlet or EJB™ container, ...) to transparently access a cluster of databases through JDBC™. You do not have to modify client applications, application servers or database server software. You just have to ensure that all database accesses are performed through C-JDBC.
C-JDBC is a free, open source project of the ObjectWeb Consortium. It is licensed under the GNU Lesser General Public License (LGPL).
In order to use C-JDBC, you will need:
a client application that accesses a database through JDBC,
a JDK™ 1.3 (or greater) compliant Java Virtual Machine™ (JVM)[1],
a database with a JDBC driver (type 1, 2, 3 or 4) or an ODBC driver used with the JDBC-ODBC bridge.
a network supporting TCP/IP communications between your cluster nodes.
![]() | Note |
|---|---|
If your client application uses ODBC, it is possible to use an ODBC-JDBC bridge such as the unixODBC provided by Easysoft. | |
You have a Java application or a Java-based application server that accesses one or several databases. The database tier becomes the bottleneck of your application or it is a single point of failure or both. C-JDBC can help you resolve these problems by providing:
performance scalability by adding database nodes and balacing the load among these nodes.
high availability of the database tier, i.e. C-JDBC tolerates database crashes and offers transparent failover using database replication techniques.
improved performance with fine grain query caching and transparent connection pooling.
SQL traffic logging for performance monitoring and analysis.
support for clusters of heterogenous database engines.
C-JDBC provides a flexible architecture that allows you to achieve scalability, high availability and failover with your database tier. C-JDBC implements the concept of RAIDb: Redundant Array of Inexpensive Databases (see Section 10, “RAIDb Basics”). The database is distributed and replicated among several nodes and C-JDBC load balances the queries between these nodes.
C-JDBC provides a generic JDBC driver to be used by the clients (see Section 4, “C-JDBC Driver”). This driver forwards the SQL requests to the C-JDBC controller (see Section 6, “C-JDBC controller”) that balances them on a cluster of databases (reads are load balanced and writes are broadcasted). C-JDBC can be used with any RDBMS (Relational DataBase Management System) providing a JDBC driver, that is to say almost all existing open source and commercial databases. Figure 1, “C-JDBC principle” gives an overview of the C-JDBC principle.
C-JDBC allows to build any cluster configuration including mixing database engines from different vendors. The main features provided by C-JDBC are performance scalability, fault tolerance and high availability. Additional features such as monitoring, logging, SQL requests caching are provided as well.
The architecture is widely open to allow anyone to plug custom requests schedulers, load balancers, connection managers, caching policies, ...
From a software point of view, C-JDBC is an open-source software licensed under LGPL which means that it is free of charge for any usage (personal or commercial). If you are using commercial RDBMS (such as Oracle, DB2, ...), you will have to buy extra licenses for the nodes where you install replicas of the database. But you can possibly use open-source databases to host replicas of your main database.
You need to buy extra machines if you want more performance and more fault tolerance. C-JDBC has been designed to work with standard off-the-shelf workstations because it primarily targets low cost open-source solutions but it can work as well with large SMP machines. A standard Ethernet network is sufficient to achieve good performance.
You do not have to change anything to your application or your database.
You only have to update the JDBC driver configuration used by your application (usually it is just a configuration file update) and to setup a C-JDBC configuration file (see Section 11, “Virtual database configuration”).
The binary distribution of C-JDBC can be downloaded from C-JDBC's Web site. It mainly contains the JAR files for the C-JDBC driver and controller and also the documentation and other tools such as the C-JDBC administration console.
![]() | Note |
|---|---|
A source distribution of C-JDBC is also available. The whole code base can also be downloaded through an anonymous CVS server[2]. For more information, please refer to C-JDBC Developper's Guide. Most users will only need the binary distribution. | |
The following formats are available (where x.y is the C-JDBC release number):
We strongly advice to use the Java installer package since it automatically configures the scripts to suit your system configuration.
![]() | Note |
|---|---|
All distributions contain the user documentation. | |
The easiest way to install C-JDBC is to use the Java graphical installer. A Java Virtual Machine is of course needed in this case.
Unix users can simply launch the installation program by typing:
bash> java -jar c-jdbc-x.y.bin-installer.jar
Windows users can use the same command or just double-clik on the JAR installation file if your JRE has been properly installed.
If you want to use the other distribution formats (for example if you have not installed a JVM or if you can not launch a graphical application), you have to uncompress the downloaded file in the directory of your choice, and then set the CJDBC_HOME environment variable.
![]() | Note |
|---|---|
If you are using the Java installer, you do not need to set any environment variable since the installer customizes the scripts with the installation path. | |
To set the CJDBC_HOME environment variable, you can proceed as follows:
Unix users can proceed as follows:
bash> mkdir -p /usr/local/c-jdbc
bash> cd /usr/local/c-jdbc
bash> tar xfz /path-to-c-jdbc-bin-dist/c-jdbc-x.y-bin.tar.gz
bash> export CJDBC_HOME=/usr/local/c-jdbc
![]() | Note |
|---|---|
In this example, we assume you install C-JDBC in the /usr/local/c-jdbc directory. | |
You can modify your shell configuration file (.bashrc, .cshrc, ...) to set the environment variable permanently.
Windows users have to use an utility such as WinZip to extract the files from the archive. Then, to set the CJDB_HOME variable, do the following according to your Windows version:
Windows 95 or 98: you must insert the following line in the AUTOEXEC.BAT file:
set CJDBC_HOME="C:\Program Files\C-JDBC"
Windows Me: go to the “Start Menu”, then choose “Programs”, “Accessories”, “System Tools” and “System Information”. A window titled “Microsoft Help and Support” should appear. Select the “Tools” menu, and choose the “System Configuration Utility”. Go to the “Environment” and click on the “New” button. Enter CJDBC_HOME in the “Variable Name” field and "C:\Program Files\C-JDBC" in “Variable Value”. Once you have changed and saved the value, you will be prompted for reboot.
Windows NT: go to the “Start Menu”, then choose “Settings”, “Control Panel” and select “System”. Select the “Environment” tab and click on the “New” button. Enter CJDBC_HOME in the “Variable Name” field and "C:\Program Files\C-JDBC" in “Variable Value”.
Windows 2000: go to the “Start Menu”, then choose “Settings”, “Control Panel” and select “System”. Select the “Advanced” tab and click on the “New” button. Enter CJDBC_HOME in the “Variable Name” field and "C:\Program Files\C-JDBC" in “Variable Value”.
Windows XP: go to the “Start Menu”, then double click on “System”. In the “System Control Panel” select the “Advanced” tab and push the Environment Variables button. Click on the “New” button for “System Variables”. Enter CJDBC_HOME in the “Variable Name” field and "C:\Program Files\C-JDBC" in “Variable Value”.
![]() | Note |
|---|---|
In this example, we assume you install C-JDBC in the C:\Program Files\C-JDBC directory. | |
![]() | Note |
|---|---|
Do not forget the quotes in the CJDBC_HOME environment variable definition else the starting scripts will fail with paths including spaces. | |
Once you have installed the C-JDBC controller, you will find the driver JAR file in the drivers/ directory of the controller installation location.
To install the C-JDBC driver, you just have to add the c-jdbc-driver.jar file to the client application classpath. This driver replaces the database native driver in the client application. The database native driver will be used by the C-JDBC controller to access your database. Therefore, the C-JDBC driver and controller can be seen as a proxy between your application and your database native driver.
Since version 1.0b13, you have access to a RAIDb-1 configuration of HyperSonic SQL databases, just by launching the demo-raidb1.sh or demo-raidb1.bat file from the demo directory in your C-JDBC installation.
This is especially useful if you are new to clustering, or new to C-JDBC. The setup used is as follows:
2 HyperSonic SQL databases are started on two different ports (9001 and 9002)
An extra HyperSonic SQL database is started on port 9003 to be used as the recovery log database
The C-JDBC controller is configured to load automatically a virtual database containing those two HyperSonic SQL backends. The controller startup configuration file is found in CJDBC_HOME/config/controller/controller-raidb1.xml and the virtual database configuration file is CJDBC_HOME/config/virtualdatabase/hsqldb-raidb1.xml.
Once the RAIDb-1 configuration is loaded, you can connect to C-JDBC using Squirrel, a graphical SQL console bundled with C-JDBC. You can start Squirrel by using squirrel.sh or squirrel.bat.
Squirrel shows the C-JDBC driver and HSQL database driver, and links to databases. You can click on them to view the different data. The login to use for C-JDBC is user with an empty password. The login for both HSQL databases is test with an empty password.
The C-JDBC driver is a generic JDBC driver that is designed to replace any database specific JDBC driver that could be used by a client. The client only has to know on which node the C-JDBC controller is running and the name of the database to access. The C-JDBC driver implements most of the JDBC 2.0 interface and some functionalities from JDBC 3.0 such as the support for autogenerated keys.
Users reported successful usage of C-JDBC with the following RDBMS: Oracle®, PostgreSQL, MySQL, Apache Derby, IBM DB2®, Sybase®, SAP DB (MySQL MaxDB), HyperSonic SQL, Firebird, MS SQL Server and InstantDB.
The C-JDBC driver can be loaded as any standard JDBC driver from the client program using:
Class.forName("org.objectweb.cjdbc.driver.Driver");
![]() | Note |
|---|---|
The c-jdbc-driver.jar file must be in the client classpath else the driver will fail to load. | |
The JDBC URL expected for the use with C-JDBC is the following: jdbc:cjdbc://host1:port1,host2:port2/database.
host is the machine name (or IP address) where the C-JDBC controller is running, port is the port the controller is listening for client connections.
At least one host must be specified but a list of comma separated hosts can be specified. If several hosts are given, one is picked up randomly from the list. If the currently selected controller fails, another one is automatically picked up from the list.
The port is optional is the URL and the default port number is 25322 (C-JDBC on the phone!) if it is omitted. Those two examples are equivalent:
DriverManager.getConnection("jdbc:cjdbc://localhost/tpcw");
DriverManager.getConnection("jdbc:cjdbc://localhost:25322/tpcw");
Examples using two controllers for fault tolerance:
DriverManager.getConnection("jdbc:cjdbc://c1.objectweb.org,c2.objectweb.org/tpcw");
DriverManager.getConnection("jdbc:cjdbc://localhost,remote.objectweb.org:2048/tpcw");
DriverManager.getConnection("jdbc:cjdbc://smpnode.com:25322,smpnode.com:1098/tpcw");
The C-JDBC driver accepts additional options to override the default behavior of the driver. The options are appended at the end of the C-JDBC URL after a question mark followed by a list of ampersands separated options. Here is an example:
DriverManager.getConnection("jdbc:cjdbc://host/db?user=me&password=secret")Another option is to use semicolons to delimit the start of options and options themselves. Example:
DriverManager.getConnection("jdbc:cjdbc://host/db;user=me;password=secret")The recognized options are:
booleanTrue: String value to use in PreparedStatement.setBoolean(true), default is '1'.
booleanFalse: String value to use in PreparedStatement.setBoolean(false), default is '0'.
connectionPooling: By default the C-JDBC driver does transparent connection pooling on your behalf meaning that when connection.close() is called, the connection is not physically closed but rather put in a pool for reuse within the next 5 seconds. Set this to false if you do not want the driver to perform transparent connection pooling.
debugLevel: Debug level that can be set to 'debug', 'info' or 'off' to display driver related information on the standard output. Default is off.
driverProcessed: can be set to 'true or 'false', see Proxying mode below.
escapeBackslash: Set this to false if you don't want to escape backslashes when performing escape processing of PreparedStatements, default is true.
escapeSingleQuote: Set this to false if you don't want to escape single quotes (') when performing escape processing of PreparedStatements, default is true
escapeCharacter: Character to prepend and append to the String values when performing escape processing of PreparedStatements, default is a single quote.
user: user login
password: user password
preferredController: defines the strategy to use to choose a preferred controller to connect to.
jdbc:cjdbc://node1,node2,node3/myDB?preferredController=ordered : Always connect to node1, and if not available then try to node2 and finally if none are available try node3.
jdbc:cjdbc://node1,node2,node3/myDB?preferredController=random: Pickup a controller node randomly (default strategy)
jdbc:cjdbc://node1,node2:25343,node3/myDB?preferredController=node2:25343,node3 : Round-robin between node2 and node3, fallback to node1 if none of node2 and node3 is available.
jdbc:cjdbc://node1,node2,node3/myDB?preferredController=roundRobin: Round robin starting with first node in URL.
retryIntervalInMs: once a controller has died, the driver will try to reconnect to this controller every retryIntervalInMs to see if the backend is back online. The default is 5000 (5 seconds).
By default, the C-JDBC driver interprets the PreparedStatement locally and forwards a pre-processed statement. The C-JDBC controller executes directly these statements on the backends as statements without recreating a whole PreparedStatement and re-calling all setXXX() methods on the PreparedStatement. The default setting is the one that consumes the less resources and carries the minimum information over the network.
However, it might happen that this behavior is not desired or that the C-JDBC driver interpretation is unsuitable for some data types or database specific syntax. Therefore, it is possible to make the driver act as a real proxy that will forward all setXXX() calls to the database native driver. This will usually result in slightly lower performance but better portability.
The proxying mode can be enabled for a connection by setting a specific variable named driverProcessed to false (default value if omitted is true). To enable PreparedStatement proxying in C-JDBC use a connection URL like this:
DriverManager.getConnection("jdbc:cjdbc://host/db?driverProcessed=false")
Note: since any optional blob encoding is performed by the driver, blob encoding is disabled by driverProcessed=false. If you ever encoded blobs, you CANNOT switch to driverProcessed=false anymore.
Another way to use the C-JDBC driver is to use its DataSource implementation. Data sources have been introduced in JDBC 2.0 Standard Extension API and are also a part of JDBC 3.0. They use the Java Naming and Directory Interface (JNDI) to break the application dependence on the JDBC driver configuration (i.e., driver class name, machine name, port number, etc.). With a data source, the only thing an application has to know is the name assigned to the DataSource object in the jdbc naming subcontext of the JNDI namespace.
The example below registers a data source object with a JNDI naming service. It is typically used by an application server.
import org.objectweb.cjdbc.driver.DataSource;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
...
private final static String NAME = "jdbc/c-jdbc";
private final static String URL = "jdbc:cjdbc://localhost:25322/mysql";
// Initializing data source
DataSource ds = new DataSource();
ds.setUrl(URL);
// Get initial context
Context ctx;
try {
ctx = new InitialContext();
} catch (javax.naming.NamingException _e) {
... // Naming exception
}
// Bind data source to a JNDI name
try {
ctx.bind(NAME, ds);
} catch (javax.naming.NamingException _e) {
... // Naming exception
}
The org.objectweb.cjdbc.driver.DataSource class implements the javax.sql.DataSource JDBC 3.0 interface. The setUrl line initializes the data source properties (the URL in this case). The data source object is bound to a logical JNDI name by calling ctx.bind(). In the example above, the JNDI name specifies a "jdbc" subcontext and a "c-jdbc" logical name within this subcontext.
Once a data source object is registered to JNDI, it can be used by an application. The example below gets the data source using the JNDI naming service. Such a piece of code is typically a part of an application that uses JDBC.
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.sql.Connection;
import javax.sql.DataSource;
...
private final static String NAME = "jdbc/c-jdbc";
// Lookup for the data source object
try {
Context ctx = new InitialContext();
Object obj = ctx.lookup(NAME);
if (null == obj) {
... // Something wrong: NAME not found
}
ctx.close( );
} catch (javax.naming.NamingException _e) {
... // Naming exception
}
// Get a new JDBC connection
try {
DataSource ds = (DataSource) obj;
Connection conn = ds.getConnection("user", "c-jdbc");
... // Use of the connection retrieved
...
} catch (SQLException _e) {
... // SQL exception
}
The ctx.lookup() line in the example uses the retrieved initial JNDI naming context to do a lookup using the data source logical name. The method returns a reference to a Java object which is then narrowed to a javax.sql.DataSource object. Such an object can be then used to open a new JDBC connection by invoking one of its getConnection() methods. The application code is completely independent of the driver details, such as the Driver class name, URL, etc. (the user name and password used by the connection can be also set by the application server - look at the C-JDBC javadoc documentation for more details). The only information a JDBC application has to know is the logical name of the data source object to use.
![]() | Note |
|---|---|
The URL used for the C-JDBC data source is the same as for the Driver decribed in the previous section. | |
Stored procedures are supported by C-JDBC since version 1.0b6. Note that C-JDBC only support calls in the form {call <procedure-name>[<arg1>,<arg2>, ...]} but does not support {? = call <procedure-name>[<arg1>,<arg2>, ...]}.
A call to a stored procedure is systematically broadcasted to all backends since there is no way to know if the stored procedure will update the database or not. Therefore, the query cache (see Section 11.6.3, “Request Cache”), is completely flushed on every stored procedure call. To prevent cache flushing, the user can force the connection to read-only before calling the stored procedure. But never set a connection to read-only when calling a stored procedure that updates the database. If C-JDBC detects a read-only connection, it will not flush the cache. However, the call will still be broadcasted to all nodes resulting in duplicated jobs on each backend. Here is an example on how to prevent cache flushing when calling a stored procedure that does only read-only:
...
CallableStatement cs = connection.prepareCall("{call myproc(?)}");
cs.setString(1,"parameter1");
// Force no cache flush
connection.setReadOny(true);
// Call the stored procedure without flushing the cache ...
ResultSet rs = cs.executeQuery();
In the case of horizontal scalability, only read-only stored procedures are not broadbasted. All other stored procedures returning an int or a ResultSet are executed by all backends at all controllers.
![]() | Note |
|---|---|
It is not allowed to set a connection to read-only in the middle of a transaction. If you need to set a connection to read-only, you must do so before starting the transaction. | |
Binary large objects can now be stored using the C-JDBC driver since 1.0b10. Data is encoded into hexadecimal to be portable accross database engines.
FIXME: this whole section is outdated and should be re-written. Blob encoding is now configured in controller's DTD and set to "none" by default. It requires driverProcessed=true, which is the default.
![]() | Note |
|---|---|
| |
You should not have to change your code for storing blobs into your database, but previous blobs have to be converted to their hexadecimal form. You can use Octopus to perform this transformation.
Please refer to the following lines of code for storing and retrieving of large objects:
// In the code below:
// The signature of the readBinary method is:
// byte[] readBinary(File file) throws IOException
// it just read a file, and convert its content into an array of bytes
// Store file in database
File fis = new File(storeFile);
query = "insert into ... values(...,?)";
ps1 = con.prepareStatement(query);
if (callBlobMethods)
{
org.objectweb.cjdbc.driver.Blob bob =
new org.objectweb.cjdbc.driver.Blob(readBinary(fis));
ps1.setBlob(1, bob);
}
else
{
ps1.setBytes(1, readBinary(fis));
}
ps1.executeUpdate();
// Read File from database
query = "select * from ... where id=...";
ps1 = con.prepareStatement(query);
ResultSet rs = ps1.executeQuery();
rs.first();
byte[] lisette;
if (callBlobMethods)
{
Blob blisette = rs.getBlob("blobcolumnname");
lisette = blisette.getBytes((long) 1, (int) blisette.length());
}
else
{
lisette = rs.getBytes("blobcolumnname");
}
CLOB is a built-in type that stores a Character Large Object as a column value in a row of a database table. By default drivers implement Clob using an SQL locator (CLOB), which means that a Clob object contains a logical pointer to the SQL CLOB data rather than the data itself. A Clob object is valid for the duration of the transaction in which it was created.
Clobs in C-JDBC are handled like strings. You can refer to the section of code below to make good usage of clobs. This code is part of the C-JDBC test suite.
String clob = "I am a clob";
ps = con.prepareStatement("insert into ... values(...,?)");
ps.setString(1, clob);
ps.executeUpdate();
// Test retrieval
String ret;
ps = con.prepareStatement("Select * from ... where id=...");
rs = ps.executeQuery();
rs.first();
clob = rs.getClob("name");
ret = clob.getSubString((long) 0, (int) clob.length());
In its default mode, when a query is executed on a backend, C-JDBC makes a copy of the backend's native ResultSet into a C-JDBC serializable ResultSet. If the result contains many rows or very large objects, the controller might run out of memory when trying to copy the whole ResultSet.
Since C-JDBC 1.0rc6, it is possible to fetch ResultSets by blocks using the Statement.setFetchSize(int rows) method. In this case, the ResultSet will be copied by block of rows and returned when needed by the client. Note that the current implemtation only allows to fetch forward streamable ResultSet, which basically means that you are only allowed to call ResultSet.next() on a streamable ResultSet.
C-JDBC will try to call setFetchSize() on the backend's driver to let the backend driver also perform the necessary optimizations. However, some driver requires a prior call to setCursorName() in which case you will also have to call setCursorName() on C-JDBC to pass it to the backend's driver.
A typical usage of the ResultSet streaming feature is as follows:
...
Connection con = getCJDBCConnection();
con.setAutocommit(false);
Statement s = con.createStatement();
s.setCursorName("cursor name");
s.setFetchSize(10);
rs = s.executeQuery(sql);
while (rs.next())
{ // Every 10 calls, C-JDBC will transfer a new block of rows
XXX o = rs.getXXX("some column name");
}
...
con.commit();
![]() | Note |
|---|---|
Streamable ResultSets are not cacheable. The result cache automatically detects this kind of ResultSet and does not keep them in the cache. However, as database specific ResultSets are copied into C-JDBC ResultSets, the memory footprint of the fetched blocks will be twice the one obtained without C-JDBC. If you have memory restrictions, you can reduce your fetch size by half to reduce the memory footprint of streamed ResultSets. Streamable ResultSets do not work properly in autocommit mode as the connection used for retrieving the ResultSet is handed back to the pool. The workaround is to always encapsulate the query in a transaction. Note that databases such as PostgreSQL do not support streamable ResultSets in autocommit mode as well. | |
The C-JDBC driver currently does not support the following features:
java.sql.Array and java.sql.Ref types,
Custom type mapping using java.sql.Connection.setTypeMap(java.util.Map map),
XAConnections (look at the XAPool project for XA support with C-JDBC),
CallableStatements with OUT parameters,
Streamable ResultSets do not work in autocommit mode.
If the application you are using C-JDBC with requires a mapper, the best thing to do is to configure the mapping to be that of C-JDBC's underlying databases. For example, if you were using JBoss with PostgreSQL , then using C-JDBC on top of the PostgreSQL backends with JBoss would imply to still use the mapping for PostgreSQL while plugging the application server to C-JDBC (using C-JDBC's driver and C-JDBC's url).
Copy the c-jdbc-driver.jar file to the lib directory of your web application (for example: $TOMCAT_HOME/webapps/mywebapp/WEB-INF/lib).
There are many ways to obtain connections from a Tomcat application. Just ensure that you are using org.objectweb.cjdbc.driver.Driver as the driver class name and that the JDBC URL is a C-JDBC URL (see Section 4.3, “C-JDBC JDBC URL”).
The c-jdbc-driver.jar file must be found in the JOnAS CLASSPATH.
Here is an example of a cjdbc.properties file to store in JONAS 3.x conf directory (use the config directory for JOnAS 2.x):
###################### C-JDBC DataSource configuration example #
datasource.name jdbc_1
datasource.url jdbc:cjdbc://someMachine/someDatabase
datasource.classname org.objectweb.cjdbc.driver.Driver
datasource.username your-username
datasource.password your-password
Copy the c-jdbc-driver.jar file to $JBOSS_DIST/server/default/lib for JBoss 3.x or to $JBOSS_DIST/jboss/lib/ext for JBoss 2.x.
Here is an example of a datasource configuration file to be used with JBoss:
<?xml version="1.0" encoding="UTF-8"?>
<!-- ===================================================================== -->
<!-- -->
<!-- JBoss Server Configuration -->
<!-- -->
<!-- ===================================================================== -->
<!-- ===================================================================== -->
<!-- Datasource config for C-JDBC -->
<!-- ===================================================================== -->
<datasources>
<local-tx-datasource>
<jndi-name>cjdbc-DS</jndi-name>
<connection-url>jdbc:cjdbc://localhost:25322/lscluster</connection-url>
<driver-class>org.objectweb.cjdbc.driver.Driver</driver-class>
<user-name>user</user-name>
<password>tagada</password>
</local-tx-datasource>
</datasources>
Place the c-jdbc-driver.jar file in the classpath of the Weblogic Server.
Here is an example of a connection pool configuration for use with Weblogic:
<JDBCConnectionPool
DriverName="org.objectweb.cjdbc.driver.Driver"
InitialCapacity="1" MaxCapacity="15"
Name="cjdbcPool" Properties="user=username;password=password"
ShrinkingEnabled="true" SupportsLocalTransaction="true"
Targets="wlservername" URL="jdbc:cjdbc://192.168.0.1/vdb"
XAPreparedStatementCacheSize="0"/>
Next, create the required TXDataSources:
<JDBCTxDataSource EnableTwoPhaseCommit="true"
JNDIName="cjdbc-DS" Name="C-JDBC TX Data Source"
PoolName="cjdbcPool" RowPrefetchEnabled="true" Targets="wlservername"/>
C-JDBC just has to be defined as any JDBC driver in Hibernate, leaving the syntax set to the proper database. Here is a configuration example to use Hibernate with a C-JDBC cluster made of Sybase backends:
## C-JDBC
hibernate.dialect net.sf.hibernate.dialect.SybaseDialect
hibernate.connection.driver_class org.objectweb.cjdbc.driver.Driver
hibernate.connection.username user
hibernate.connection.password pass
hibernate.connection.url jdbc:cjdbc://localhost:25322/test
Our Hibernate dialect is as follows:
import net.sf.hibernate.dialect.PostgreSQLDialect;
public class CJDBCPostgreSQLDialect extends PostgreSQLDialect
{
public String getSequenceNextValString(String sequenceName)
{
return "{call nextval('"+sequenceName+"')}";
}
}
We simply extend the default PostgreSQL Dialect and override the getSequenceNextValString() method and tell it to use "{call ..." so that all the sequences in the cluster get incremented.
We then changed our Hibernate conf file to user to our custom dialect instead of net.sf.hibernate.dialect.PostgreSQLDialect.
The C-JDBC controller is made of several components as shown in Figure 2, “C-JDBC controller design overview”. The controller hosts virtual databases. A virtual database gives the illusion of a single database to the user. It exports the same database name and login/password as those used in the client application. Therefore the client application can run unmodified with C-JDBC.
When the client application connects to the database using an URL like jdbc:cjdbc://host:25322/myDB, the C-JDBC driver tries to connect to a C-JDBC controller running on port 25322 on node host. Once the connection is established the login and password are sent with the myDB database name to be checked by the controller.
A virtual database contains the following components:
authentication manager: it matches the virtual database login/password (provided by the application to the C-JDBC driver) with the real login/password to use on each backend. The authentication manager is only involved at connection establishment time.
backup manager: manages a list of generic or database specific Backupers that are in charge of performing database dump and restore operation. Backupers should also take careof transferring dumps from one controller to another.
request manager: it handles the requests coming from a connection with a C-JDBC driver. It is composed of several components:
scheduler: it is responsible for scheduling the requests. Each RAIDb level has its own scheduler.
request caches: these are optional components that can cache query parsing, the result set and result metadata of queries.
load balancer: it balances the load on the underlying backends according to the chosen RAIDb level configuration.
recovery log: it handles checkpoints and allows backends to dynamically recover from a failure or to be dynamically added to a running cluster.
database backend: it represents the real database backend running the RDBMS engine. A connection manager mainly provides connection pooling on top of the database JDBC native driver.
Each virtual database and its components are configured using an XML configuration file that is sent from the administration console to the C-JDBC controller.
![]() | Note |
|---|---|
A research report details RAIDb and C-JDBC implementation. Other documents and presentations about C-JDBC can be found in the documentation section of the web site. | |
The bin directory of the C-JDBC distribution contains the scripts to start the controller. Unix users must start the controller with controller.sh whereas Windows users will use controller.bat.
Since C-JDBC Controller version 1.0b11, the controller start is tuned via a configuration file, called controller.xml, included under the config/controller directory of your C-JDBC installation. A simple configuration file looks like this:
A standard C-JDBC Controller configuration file looks like this:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE C-JDBC-CONTROLLER PUBLIC "-//ObjectWeb//DTD C-JDBC-CONTROLLER 2.0.2//EN" "http://c-jdbc.objectweb.org/dtds/c-jdbc-controller-2.0.2.dtd">
<C-JDBC-CONTROLLER>
<Controller port="25322">
<Report hideSensitiveData="true" generateOnFatal="true"/>
<JmxSettings>
<RmiJmxAdaptor/>
</JmxSettings>
</Controller>
</C-JDBC-CONTROLLER>
You can specify at startup a different file than config/controller/controller.xml. This is useful if you have to startup many identical controllers from the network. You can then use the command controller.sh -f filename on Unix machines or controller.bat -f filename on windows.
For more information you can refer to the controller-configuration.xml example in the example directory of c-jdbc.
Next section describes how to write a controller configuration file.
The controller is entirely configurable via an xml file, by default it is controller.xml located in the config/controller of the C-JDBC installation. This section details how to write such a file.
The root element of the controller configuration is defined as follows
<!ELEMENT Controller (Internationalization?, Report?, JmxSettings?,
VirtualDatabase*, SecuritySettings?)>
<!ATTLIST Controller
port CDATA "25322"
ipAddress CDATA "127.0.0.1"
backlogSize CDATA "10"
>
All sub-elements of Controller are defined in the next sections. Here is a brief overview of each of them:
Internationalization: defines the language setting for C-JDBC console and error messages.
Report: if this option is enabled, C-JDBC can automatically generate a report on fatal errors or shutdown. If you experience any problem with C-JDBC, you can directly send the report on the mailing list to get a quick diagnostic of what happened.
JmxSettings: JMX is the technology used for management and monitoring in C-JDBC. These functionalities can be accessed through HTTP with an internet browser or through the RMI connector used by the C-JDBC console.
VirtualDatabase: Defines a virtual database to load automatically at controller startup given a reference to its configuration file.
SecuritySettings: Allows to filter accesses to a controller based on access lists.
The attributes of a Controller element are defined as follows:
port: the port number on which clients (C-JDBC drivers) will connect. The default port number is 25322.
![]() | Note |
|---|---|
A port number below 1024 will require running the controller with privileged rights (root user under Unix). | |
ipAddress: This can be defined to bind a specific IP address in case of a host with multiple IP addresses. This can be ignored if there is only one IP address available and will be replaced by 127.0.0.1.
backlogSize: the server socket backlog size (number of connections that can wait in the accept queue before the system returns "connection refused" to the client). Default is 10. Tune this value according to your operating system, but the default value should be fine for most settings.
If your machine has multiple network adapters, you can for the C-JDBC Controller to bind a specific IP address like this:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE C-JDBC-CONTROLLER PUBLIC "-//ObjectWeb//DTD C-JDBC-CONTROLLER 2.0.2//EN" "http://c-jdbc.objectweb.org/dtds/c-jdbc-controller-2.0.2.dtd">
<C-JDBC-CONTROLLER>
<Controller port="25322" ipAddress="192.168.0.1">
<JmxSettings enabled="false"/>
</Controller>
</C-JDBC-CONTROLLER>
You can use this element to override the default locale retrieved by java. English is the only language looked at at the moment.
<!ELEMENT Internationalization EMPTY>
<!ATTLIST Internationalization language (en|fr|it|jp) "en">
A report can be define in case you want to get a trace of what happened during the execution of the controller. If this element is included in the controller.xml report is enabled and will output a report, under certain conditions, in a file named c-jdbc.report.
<!ELEMENT Report EMPTY>
<!ATTLIST Report
hideSensitiveData (true|false) "true"
generateOnShutdown (true|false) "true"
generateOnFatal (true|false) "true"
enableFileLogging (true|false) "true"
reportLocation CDATA #IMPLIED
>
hideSensitiveData: will replace passwords with '*****'.
generateOnShutdown: tells the controller to generate a report when it has received a shutdown command.
generateOnFatal: tells the controller to generate a report when it cannot recover from an error.
enableFileLogging: logs all the console output into a file and include this file into the report.
reportLocation: specify the path where to create the report, default is CJDBC_HOME/log directory.
JMX is used to remotely administrate the controller. You can use the bundled C-JDBC console or use your own code to access JMX MBeans via the protocol adaptor. C-JDBC proposes both the RMI and HTTP adaptors of the MX4J JMX server. You can override the default port numbers for each adaptor if they conflict with another application that is already using them (i.e. another C-JDBC controller on the same machine).
<!ELEMENT JmxSettings (HttpJmxAdaptor?, RmiJmxAdaptor?)>
<!ELEMENT HttpJmxAdaptor EMPTY>
<!ATTLIST HttpJmxAdaptor
port CDATA "8090"
>
<!ELEMENT RmiJmxAdaptor (SSL?)>
<!ATTLIST RmiJmxAdaptor
port CDATA "1090"
username CDATA #IMPLIED
password CDATA #IMPLIED
>
<!ELEMENT SSL EMPTY>
<!ATTLIST SSL
keyStore CDATA #REQUIRED
keyStorePassword CDATA #REQUIRED
keyStoreKeyPassword CDATA #IMPLIED
isClientAuthNeeded (true|false) "false"
trustStore CDATA #IMPLIED
trustStorePassword CDATA #IMPLIED
>
Configure ssl for encryption and/or authentication.
keyStore: The file where the keys are stored
keyStorePassword: the password to the keyStore
keyStoreKeyPassword: the password to the key, if none is specified the same password as for the store is used
isClientAuthNeeded: if set to false ssl is used for encryption, the server is only accepting trusted clients (the client certificate has to be in the trusted store)
trustStore: the file where the trusted certificates are stored, if none is specified the same store as for the key is used
trustStorePassword: the password to the trustStore, if none is specified the same password as for the keyStore is used
You have to enable the RMI adaptor if you want to use the C-JDBC console to administrate the controller remotely. To enable the RMI JMX adaptor, use this setting:
<JmxSettings>
<RmiJmxAdaptor/>
</JmxSettings>
This element specifies virtual databases to load at controller startup.
<!ELEMENT VirtualDatabase EMPTY>
<!ATTLIST VirtualDatabase
configFile CDATA #REQUIRED
virtualDatabaseName CDATA #REQUIRED
autoEnableBackends (true | false | force) "true"
checkpointName CDATA ""
>
configFile: The path to the virtual database configuration file. See Section 11, “Virtual database configuration” to learn how to write a virtual database configuration file.
virtualDatabaseName: The name of the virtual database since the configuration file can contain multiple virtual database definitions.
autoEnableBackends: set to true by default to reenable backends from their last known state as stored during last shutdown. If backends where not properly shutdown, nothing will happen. You can specify false to let the backends in disabled state at startup. The force option should only be used if you know exactly what you are doing and override backend status by providing a new checkpoint. Warning! Use this setting carefully as it might break your database consistency if you do not provide a valid checkpoint.Force is considered the same as true if no recovery log has been defined.
checkpointName: the checkpoint name to use with the recovery log to enable backend from a known coherent state. If the checkpoint is omitted, the last known checkpoint is used.
Example:
<VirtualDatabase configFile="/databases/MySQLDb.xml" virtualDatabaseName="rubis" autoEnableBackends="true"/>
This will enable a virtual database named rubis taken from a configuration file named /databases/MySQLDb.xml and will enable all backends of the database from the last known checkpoint.
Security settings define the policy to adopt for some functionalities that may compromise the security of the controller. These settings depends on your environment and can be relaxed if you are running in a secure network. The less security settings you have, the faster the controller will run. A SecuritySettings element is defined as follows:
<!ELEMENT SecuritySettings (Jar?, Shutdown?, Accept?, Block?)>
<!ATTLIST SecuritySettings
defaultConnect (true|false) "true"
>
defaultConnect: is used to allow (true) or refuse (false) connections to the controller. This default setting can be then be tuned with access lists defined in Accept and Block elements (see below).
Additional database drivers can be uploaded dynamically to the controller. As the controller has no way to check if this is a real JDBC driver or some malicious code hidden a JDBC driver interface, you have to be very careful if you enable this option and anybody can connect from anywhere to your controller.
<!ELEMENT Jar EMPTY>
<!ATTLIST Jar
allowAdditionalDriver (true|false) "true"
>
The Shutdown element defines how the controller can be terminated - in order to shutdown the controller properly, we have to use the console. Specify if the controller should consider shutdown command received by one or the other, and if this command can only be received from localhost or not. A default configuration would be:
<Shutdown>
<Client allow="true" onlyLocalhost="true"/>
<Console allow="true" onlyLocalhost="true"/>
</Shutdown>
This prevents unwanted and unauthorized shutdown calls from remote hosts. Only somebody logged locally on the machine can request a shutdown of the controller. Here is the full description for details:
<!ELEMENT Shutdown (Client?,Console?)>
<!ELEMENT Client EMPTY>
<!ATTLIST Client
allow (true|false) "true"
onlyLocalhost (true|false) "true"
>
<!ELEMENT Console EMPTY>
<!ATTLIST Console
allow (true|false) "true"
onlyLocalhost (true|false) "true"
>
You can control who can connect to the controller by setting access lists based on IP addresses to accept or block. defaultConnect is set in SecuritySettings defined above. Default is to accept all connections if no security manager is enabled.
<!ELEMENT Accept (Hostname|IpAddress|IpRange)*>
<!ELEMENT Block (Hostname|IpAddress|IpRange)*>
<!ELEMENT Hostname EMPTY>
<!ATTLIST Hostname
value CDATA #REQUIRED
>
IpAddress value is an IPv4 address (ex:192.168.1.12):
<!ELEMENT IpAddress EMPTY>
<!ATTLIST IpAddress
value CDATA #REQUIRED
>
IpRange value is based on IPv4 addresses and has the following form: 192.168.1.*.
<!ELEMENT IpRange EMPTY>
<!ATTLIST IpRange
value CDATA #REQUIRED
>
Here is a full security configuration example:
<SecuritySettings defaultConnect="false">
<Jar allowAdditionalDriver="true"/>
<Shutdown>
<Client allow="true" onlyLocalhost="true"/>
<Console allow="false"/>
</Shutdown>
<Accept>
<IpRange value="192.168.*.*"/>
</Accept>
</SecuritySettings>
This setting accepts driver connections only from machines having an IP address starting with 192.168, allows loading of additional drivers via the console, refuses shutdown from the console, but allows it from the local machine.
C-JDBC uses the Log4j logging framework. The log4j.properties configuration file is located in the /c-jdbc/config directory of your installation. Here is a brief description of the loggers available in the configuration file:
log4j.logger.org.objectweb.cjdbc.core.controller: Controller related activities mainly for bootstrap and virtual database adding/removal operations.
log4j.logger.org.objectweb.cjdbc.controller.xml.Handler: XML configuration file parsing and handling.
log4j.logger.org.objectweb.cjdbc.controller.VirtualDatabase: Virtual database related operations. A specific log4j.logger.org.objectweb.cjdbc.controller.VirtualDatabase.virtualDatabaseName logger is automatically created for each virtual database. This allows to tune different logging levels for each virtual database.
log4j.logger.org.objectweb.cjdbc.controller.VirtualDatabase.request: Log the incoming requests and transactions in files that can be replayed by the Request Player tool provided with C-JDBC.
log4j.logger.org.objectweb.cjdbc.controller.distributedvirtualdatabase.request : Log distributed request execution when using horizontal scalability (a.k.a. controller replication).
log4j.logger.org.objectweb.cjdbc.controller.backup : Log backup manager and backuper related activities from dump/restore operations.
log4j.logger.org.objectweb.cjdbc.controller.VirtualDatabaseServerThread: The server thread accepts client connections and manages the worker threads.
log4j.logger.org.objectweb.cjdbc.controller.VirtualDatabaseWorkerThread: Each worker thread handle a session with a client C-JDBC driver.
log4j.logger.org.objectweb.cjdbc.controller.RequestManager: Log the request flows between the different Request Manager components (scheduler, cache, load balancer, recovery log).
log4j.logger.org.objectweb.cjdbc.controller.scheduler: Log the request ordering and synchronization performed by the scheduler.
log4j.logger.org.objectweb.cjdbc.controller.cache: SQL Query cache related activities.
log4j.logger.org.objectweb.cjdbc.controller.loadbalancer: Log how requests are balanced on the backends.
log4j.logger.org.objectweb.cjdbc.controller.connection: Connection pooling related information.
log4j.logger.org.objectweb.cjdbc.controller.recoverylog: C-JDBC Recovery Log information.
log4j.logger.org.objectweb.cjdbc.controller.console.jmx: JMX management system logging.
log4j.logger.org.objectweb.tribe.channels: Tribe low level group communication channel.
log4j.logger.org.objectweb.tribe.gms: Tribe Group Membership Service (GMS).
log4j.logger.org.objectweb.tribe.discovery: Tribe Discovery Service (used by GMS).
og4j.logger.org.objectweb.tribe.blocks.multicastadapter: Tribe Multicast Dispatcher building block for application level message handling.
When you want to add a database to your cluster, you do not want to stop the system, replicate the current database state to the new database (that may take a long while) and then restart the system. The Recovery Log helps you in the process of dynamically adding a new backend (or recovering a previously failed backend) without stopping the system.
The Recovery Log records the write operations and transactions that are performed by the C-JDBC controller between checkpoints. A checkpoint is just a logical index in the log that reflect the recovery log state at a given time. As of C-JDBC 2.0, checkpoints are automatically managed by the controller and are generated when needed on behalf of the administrator when a backend is disabled or enter a backup phase. When re-enabling the backend, the Recovery Log replays all write queries and transactions that the backend missed during the time it was offline and it comes back to the enabled state once it is synchronized with the other nodes.
![]() | Note |
|---|---|
Since version 2.0, the backup infrastructure has completely changed and is based on Backupers. We provide a generic Backuper based on Enhydra Octopus to copy, backup and restore content of backends through JDBC. Even if Octopus is supposed to handle most common databases, it might fail for some specific databases or data types. In that case, we strongly recommend to use or implement a database specific Backuper. | |
Your Web site is running with a single database and you want to use C-JDBC with three nodes using full replication (RAIDb-1). You have two new backends ready to be installed. You can start the C-JDBC console and connect to the controller. Start the administration module by connecting to the virtual database. Type: backup <backend name> <dump name> <backuper name> <path to backup directory>. If you want to use Octopus you will use a command line like backup node1 dump1 Octopus /var/backups. During the backup, the update requests are logged in the recovery log, so no update is lost. If the backend was in the enabled state when backup was initiated, it will automatically replay the recovery log to resynchronize itself and return to the enabled state.
To restore the dump on another backend, just type restore <newbackend> <dumpname> and the appropriate backuper (Octopus in our previous example) will be used to restore the dump. After restoring the dump, you can enable the backend at any time so that the recovery log replays all the missing requests since the dump was taken.
Here is the set of commands to use in the C-JDBC console if node1 is your existing backend and you want to dynamically add node2 and node3:
backup node1 initial_dump Octopus /var/backups
restore node2 initial_dump
restore node3 initial_dump
enable node2
enable node3
![]() | Note |
|---|---|
Note that these steps can be automated by scriptin the console. | |
If a node crashes, use the administration console to restore the dump on the node using the restore command. Once the dump is restored, re-enable the backend from the stored checkpoint and the Recovery Log will automatically replay all the write queries to rebuild a consistent database state on the node.
To prevent the recovery log from being too large, you can periodically perform backup operations. This will also lower the recovery time since the part of the log to replay will be smaller. You can delete older dumps and logs if you do not need them anymore.
A checkpoint is a reference used by the recovery log to replay missing requests. If a backend is disabled from the console for maintenance, the controller will automatically create a checkpoint (prior to v2.0, the checkpoint name had to be provided manually through the console). Once the backend is enabled again, the controller retrieves its last known checkpoint from the recovery log and replays all the requests that the disabled backend missed since it was disabled. A checkpoint is nothing more than a reference in time.
As the C-JDBC recovery log can be stored in a database providing a JDBC driver, it is possible to make the recovery log fault tolerant by redirecting it to a C-JDBC controller (even self) that will distribute and replicate the log content on several backends.
The JDBC Recovery Log configuration is detailed in Section 11.6.5, “Recovery Log”.
To prevent the C-JDBC controller from being a single point of failure, C-JDBC provides controller replication also called horizontal scalability. A virtual database can be replicated in several controllers that can be added dynamically at runtime. Controllers use the JGroups group communication middleware to synchronize updates in a distributed way. The JGroups stack configuration is found in config/jgroups.xml and should not be altered unless you specifically know what you are doing. Keep in mind that total order reliable multicast is needed to ensure proper synchonization of the controllers. More information about JGroups can be found on the JGroups web site. Note that JGroups requires proper network settings, here are a few guidelines:
a default route must be defined (check with /sbin/route under Linux) for the network adapter which is bound by JGroups (usually eth0). If such route does not exist, either the group communication initialization will block or controllers will not be able to see each other even on the local host. If you don't have any default entry in your routing table you can use a command like '/sbin/route add default eth0' to define this default route.
issues have been reported with DHCP that can either block (under Windows) or just fail to properly set a default route and leads to the issue reported above. We strongly discourage the use of DHCP, you should use fixed IP addresses instead.
name resolution should be properly set so that the IP address/machine name matching works both ways. Often improper /etc/hosts or DNS configuration leads to group communication initialization problems. In particular, under Linux, the IP address associated to the name returned by the 'hostname' command must not resolve to 127.0.0.1 else controllers will not see each other.
In order for a virtual database to be replicated, you must define a Distribution element in the virtual database configuration file (see Section 11.2.1, “Distribution”). There are several constraints for different controllers to replicate a virtual database:
give the list of all controllers that you plan to use for replication of your virtual database in the C-JDBC driver URL. Even if all controllers are not online at all times, the driver will automatically detect the alive controllers: jdbc:cjdbc://node1,node2,node3,node4/myDB
the virtual database must have the same name and use the same groupName (in the Distribution element).
each controller must have its own set of backends and no backends should be shared between controllers (C-JDBC checks the database URLs, having different backend names is not sufficient).
each controller must have its own recovery log, recovery logs cannot be shared. It is possible for a controller not to have a recovery log but this controller will have no recovery capabilities.
the authentication managers must support the same logins.
schedulers and load balancers must implement the same RAIDb configuration.
database schemas (if defined) must be compatible according to the RAIDb level you are using.
![]() | Note |
|---|---|
As backends cannot be shared between controllers, it is not possible to use a SingleDB load balancer with controller replication. If each controller only has a single database backend attached to it, then you must use a RAIDb-1 configuration since in fact you have 2 replicated backends in the cluster. | |
Several configuration file examples are available in the doc/examples/HorizontalScalability directory of your C-JDBC distribution.
![]() | Note |
|---|---|
You can find more information in the document titled "C-JDBC Horizontal Scalability - A controller replication user guide" available from the C-JDBC web site. | |
The C-JDBC controller in its 2.0.2 release has the following limitations:
GRANT/REVOKE commands will be sent to the database engines but this will not add or remove users from the virtual database authentication manager.
network partition/reconciliation is not supported,
distributed joins are not supported which means that you must ensure that every query can be executed by at least a single backend,
RAIDb-1ec and RAIDb-2ec levels are not supported,
The C-JDBC administration console is now based on JMX technologies. The text mode console is a JMX client based on the standard RMI connector for JMX but you can also use a generic a JMX administration console through HTTP from any web browser to see all the MBeans registered in the cjdbc domain. The graphical console is not fully supported and only the text console is actively maintained.
You can start the graphic interface using the console.sh/.bat script. If your environment does not support graphic interface, it will automatically revert to the text console.

![]() | Note |
|---|---|
This section is under huge rewriting and will be put up to date soon. Please, do come back and check this soon. | |
Here is a list of the JMX remote notifications generated by C-JDBC.
cjdbc.controller.virtualdatabases.removed a virtual database has been removed.
cjdbc.controller.virtualdatabase.added a virtual database has been added to the controller
cjdbc.virtualdatabase.dump.list the list of dump files has been updated
cjdbc.virtualdatabase.backend.added a backend has been added to the virtual database
cjdbc.distributed.controller.added a controller has joined the group
cjdbc.virtualdatabase.backend.disabled a backend has been disabled
cjdbc.virtualdatabase.backend.enabled a backend has been enabled
cjdbc.virtualdatabase.backend.recovering a backend is recovering a dump file
cjdbc.virtualdatabase.backend.recovery.failed Recovery of a dump file failed
cjdbc.virtualdatabase.backend.replaying.failed Recovery log replay failed
cjdbc.virtualdatabase.backend.backingup a backend is backing up
cjdbc.virtualdatabase.backend.enable.write a backend is now write enabled
cjdbc.virtualdatabase.backend.removed a backend has been removed from the virtual database
cjdbc.virtualdatabase.backend.disabling a backend is now in state disabling (finishing pending transactions and pending requests)
cjdbc.virtualdatabase.backend.unknown The backend state has been completely lost. Recovery needed
cjdbc.virtualdatabase.backend.replaying a backend is replaying requests from the recovery log
The bin directory of the C-JDBC distribution contains the scripts to start the console. Unix users must start the console with console.sh -t whereas Windows users have to start console.bat -t.
The console script accepts several options:
-d or --debug: show stack trace when error occurs.
-f or --file: Use a given file as the source of commands instead of reading commands interactively.
-h or --help: displays usage information.
-i or --ip: IP address of the host name where the JMX Server hosting the controller is running (the default is '0.0.0.0').
-p or --port: JMX/RMI port number of (the default is 1090).
-s or --secret: Password for JMX connection.
-u or --username: username for JMX connection.
-v or --version: displays version information.
-t or --text: force the console to start in text mode. By default, it will try to start in graphic mode
For example, console.sh -t -i 192.168.0.1 -p 1234 will connect the console to the controller using the RMI JMX adaptor listening on port 1234 on 192.168.0.1.
The console has an online help that is accessible by typing help at any time.
Here is a quick description of the steps needed to make a controller ready to serve requests:
Start the controller using controller.sh or controller.bat (see Section 6.2, “Starting the Controller”).
Start the console using console.sh -t or console.bat -t (see Section 7.2, “Starting the Administration Console”).
Load a configuration file using load <complete-path>/config.xml. The controller configuration files are described in Section 11, “Virtual database configuration”.
Connect to the virtual database with the administrator login using the admin command (see example below).
Enable all backends using the enableAll command.
Come back to the main menu using the quit command.
Check the configuration using the getInfo command.
Here is an example of a controller configuration and startup:
[emmanuel@gre-home bin]$ console.sh -t
Launching the C-JDBC controller console
Initializing Controller module...
Initializing VirtualDatabase Administration module...
Initializing Monitoring module...
Initializing SQL Console module...
C-JDBC driver (v. 2.0) successfully loaded.
gre-home:1090 >help
Commands available for the Controller module are:
admin <virtualdatabase name>
Administrate a virtual database
connect controller <controller hostname> <jmx port>
Connect to a C-JDBC controller
drop virtualdatabase <virtualdatabase name>
Drop a virtual database from the controller
help
Print this help message
history [<commandIndex>]
Display history of commands for this module
load virtualdatabase config <virtualdatabase xml file>
Send a virtual database XML configuration file to the controller and load it
monitor <virtualdatabase name>
Monitor a virtual database
quit
Quit this console
reload logging configuration
Refresh the trace system by reloading the logging configuration file
save configuration
Save the current configuration of the virtual databases as an XML file
show controller config
Show Controller configuration
show logging config
Show logging configuration and the most recent traces
show virtualdatabases
Show the names of the virtual databases for this controller
shutdown [mode]
Shutdown the controller and all its virtual databases. Mode parameter must be:
1 -- wait for all client connections to be closed, does not work with a connection pool
2 -- mode safe, default value, waits for all current transactions to complete
3 -- mode force, immediate shutdown without consistency: recovery will be needed on restart
sql client <c-jdbc url>
Open a SQL client console for the virtual database specified by the C-JDBC URL
upload driver <driver file>
Upload a driver to the controller
gre-home:1090 > <userinput>show virtualdatabases</userinput>
myDB
gre-home:1090 > <userinput>admin myDB</userinput>
Virtual database Administrator Login > <userinput>admin</userinput>
Virtual database Administrator Password > <userinput>*****</userinput>
Ready to administrate virtual database myDB
myDB(admin) > help
Commands available for the VirtualDatabase Administration module are:
backup <backend name> <dump name> <backuper name> <path> [<tables>]
Backup a backend into a dump file and associate a checkpoint with this dump
delete dump <dump name>
Delete a dump
disable <backend name | *>
Disable the specified backend and automatically set a checkpoint
* means that all backends of this virtual database must be disabled
enable <backend name | *>
Enable the specified backend
* means that all backends of this virtual database must be enabled
expert <on|off>
Switch to expert mode (commands for advanced users are available)
help
Print this help message
history [<commandIndex>]
Display history of commands for this module
quit
Quit this console
restore <backend name> <dump name> [<tables>]
Starts the recovery process of the given backend for a given dump name
show backend <backend name | *>
Show information on backend of this virtual database
* means to show information for all the backends of this virtual database
show backends
Show the names of the backends of this virtual database on the current controller
show backupers
Show the backupers available for backup
show controllers
Show the names of the controllers hosting this virtual database
show dumps
Show all dumps available for database recovery
show virtualdatabase config
Show the XML configuration of the virtual database
transfer dump <dump name> <controller name> [nocopy]
Make a dump available for restore on another controller.
Optional 'nocopy' (default: false) flag specifies not to copy the dump.
myDB(admin) > <userinput>show backend *</userinput>
+--------------------------+-----------------------------------+
| Backend Name | localhost |
| Driver | org.hsqldb.jdbcDriver |
| URL | jdbc:hsqldb:hsql://localhost:9001 |
| Active transactions | 0 |
| Pending Requests | 0 |
| Read Enabled | true |
| Write Enabled | true |
| Is Initialized | true |
| Static Schema | false |
| Connection Managers | 1 |
| Total Active Connections | 5 |
| Total Requests | 0 |
| Total Transactions | 0 |
| Last known checkpoint | <unknown> |
+--------------------------+-----------------------------------+
| Backend Name | localhost2 |
| Driver | org.hsqldb.jdbcDriver |
| URL | jdbc:hsqldb:hsql://localhost:9002 |
| Active transactions | 0 |
| Pending Requests | 0 |
| Read Enabled | true |
| Write Enabled | true |
| Is Initialized | true |
| Static Schema | false |
| Connection Managers | 1 |
| Total Active Connections | 5 |
| Total Requests | 0 |
| Total Transactions | 0 |
| Last known checkpoint | <unknown> |
+--------------------------+-----------------------------------+
The graphical version of the console provides a shell-like history (more precisely a tcsh-like behavior). You can recall a previous command by using the arrow keys (up and down) to browse the history. If you prefix a command by !, the console will browse the history and complete the command with the latest command in the history starting with the command prefix (completion occurs when you press the tab key). In the graphical version, you can also access all the commands of the different module using the right button of the mouse.
![]() | Note |
|---|---|
All the commands issued can also be recalled using the history menu in the contextual menu that appears on a right-button click. | |
Commands available from the console main menu are:
admin <virtualdatabase name>: Administrate a virtual database
connect controller <controller hostname> <jmx port>: connect to a C-JDBC controller
drop virtualdatabase <virtualdatabase name>: Drop a virtual database from the controller
help: Print this help message
history [<commandIndex>]: Display history of commands for this module
load virtualdatabase config <virtualdatabase xml file>: Send a virtual database XML configuration file to the controller and load it
monitor <virtualdatabase name>: Monitor a virtual database
quit: Quit this console
reload logging configuration: Refresh the trace system by reloading the logging configuration file
save configuration: Save the current configuration of the virtual databases as an XML file
show controller config: Show Controller configuration
show logging config: Show logging configuration and the most recent traces
show virtualdatabases: Show the names of the virtual databases for this controller
shutdown [mode]: shutdown the controller and all its virtual databases.
Three shutdown modes are provided. If not specified, the default mode is the shutdown mode immediate.
Shutdown mode wait (mode 1): wait for all client connections to be closed, does not work if the client uses a connection pool with persistent connections.
Shutdown mode safe (mode 2): default value, waits for all current transactions to complete before shutting down. transaction and shutdown.
Shutdown mode force (mode 3): does not wait for transactions completion and kill all connections. Backends are disabled without consistency and a full recovery will be needed on restart.
E.g: shudown 2.
sql client <c-jdbc url>: Open a SQL client console for the virtual database specified by the C-JDBC URL
upload driver <driver file>: Upload a driver to the controller
Once the configuration file has been loaded on the controller, all backends are in the disabled state. You must enable them all or one by one to allow them to execute requests. C-JDBC does not check that database contents are synchronized and you must ensure that all backends are in a coherent state prior to starting the controller. To ensure that backends remain synchronized on startup, you must use checkpoints (see Section 6.5.2, “Understanding checkpoints”).
If you properly shutdown the controller using the wait or safe mode, database backend states are properly recorded and their state is automatically restored when they are enabled.
Standard commands available from the console administrator menu are:
backup <backend name> <dump name> <backuper name> <path> [<tables>]: Backup a backend into a dump file and associate a checkpoint with this dump. Note that the console will ask for a login and password to connect to the backend to backup. This is specific to the Backuper that you are using but this should usually be a valid login/password on the database engine that you are backuping. The login must be granted access on all tables from the controller node.
delete dump <dump name>: Delete a dump
disable <backend name | *> <checkpoint>: Disable the specified backend and store the given checkpoint (* means that all backends of this virtual database must be disabled)
enable <backend name | *>: Enable the specified backend from its last known checkpoint (* means that all backends of this virtual database must be enabled)
expert <on|off>: Switch to expert mode (commands for advanced users are available)
help: Print this help message
history [<commandIndex>]: Display history of commands for this module
quit: Quit this console
restore <backend name> <dump name> [<tables>]: Starts the recovery process of the given backend using the given dump name. Note that the console will ask for a login and password to connect to the backend to restore This is specific to the Backuper that you are using but this should usually be a valid login/password (real login in the C-JDBC terminology) on the database engine that you are restoring. Note that this login must be granted the right to create new databases and tables.
show backend <backend name | *>: Show information on backend of this virtual database (* means to show information for all the backends of this virtual database)
show backends: Show the names of the backends of this virtual database on the current controller
show backupers: Show the backupers available for backup
show controllers: Show the names of the controllers hosting this virtual database
show dumps: Show all du