This article uses the replication information given in the manual to give an example on how to set up a simple replicating system based on an existing single server application. In this example use case the specific goal of the replicating is to improve performance by duplicating the application (+ federation) on different hosts.
This article only applies to
The first step is to prepare the databases for replication. We create a temporary segment in each database, so that temporary results can be created in the replica-databases. This can be done in the adminclient, by connecting to a database and:
// Creating a temporary segment in Java code
session.getDatabase().createTemporaryDataSegment("tempSegmentName", null, 0);
session.getDatabase().setTemporaryDataSegment("tempSegmentName");
Next, the actual replica is made, assuming the master server is running a page server accessible from
other hosts, you can run the following command on the replica host (assuming
XHCreateReplica -debug -federation xhive://masterhost:1235 -replicaid newOrExistingReplicaId
-replicabootstrappath /path/to/new/replicadata/XhiveDatabase.bootstrap SuperUserPasswordXhiveFederationIf.registerReplicator(...)
and XhiveFederationIf.replicateFully(...) API calls).
This will register the replica in the master federation, and copy the complete federation over
to the replica host. You can now connect to the federation copy on the replica host, although it
is not wise to do so directly (since it should only be accessed as a replica). If something would
happen to your replica for whatever reason, you can always remove the files on the replica host
and issue this command again.
On the master host, you can access the federation in the normal way, as long as you make sure it acts as a page server to the replicating host. So assuming that for performance you access the database files directly the driver initialization code in your application would be:
XhiveDriverIf driver = XhiveDriverFactory.getDriver("/path/to/XhiveDatabase.bootstrap");
driver.init(numCachePages);
driver.startListenerThread(new ServerSocket(1235));
The driver configuration code on the replica host depends on the application. If you only
want to run read-only transactions on your replica federation only an extra call to
XhiveDriverIf.configureReplicator(...) is needed. However, for our example we
want the replica host to act as a full copy of the application, including allowing
for read-write transactions. Since
In code, this means you have to create two driver objects, one that acts on the replica and one that connects to the master-server directly:
// On replica-host, use two drivers
XhiveDriverIf masterDriver = XhiveDriverFactory.getDriver("xhive://masterhost:1235");
masterDriver.init(numCachePages / 2);
XhiveDriverIf replicaDriver = XhiveDriverFactory.getDriver("/path/to/replicadir/XhiveDatabase.bootstrap");
driver.configureReplicator("xhive://masterhost:1235", "previouslySetupId");
replicaDriver.init(numCachePages / 2);
In your session pooling code, you decide which driver to get the session from based on whether
it is a readonly transaction or not. For performance, it is advisable to have your session pool code
(and the code that uses the session pool) already make a distinction between readonly and readwrite
transactions (using XhiveSessionIf.setReadOnlyMode(...)) for concurrency performance. Once
you have that, this could be the getSession code:
synchronized XhiveSessionIf getSession(boolean readOnlyTransaction) {
if (readOnlyTransaction) {
return waitForUpdates(replicaDriver.createSession());
} else {
return masterDriver.createSession();
}
}waitForUpdates will be explained shortly, the createSession call
should be replaced by code that pools the sessions. Since there are two drivers you also need to
set up two collections of sessions.
With the setup above you will be able to perform both readonly and update transactions, with
the readonly transactions having improved performance since they use the replica. However,
XhiveSessionIf.TimeStamp currentWaitTimeStamp = null;
synchronized returnSession(XhiveSessionIf session) {
// Regular session pool code
....
if (session.getDriver().equals(masterDriver)) {
currentWaitTimeStamp = session.getUpdateTimeStamp();
}
}getSession call a routine that waits for the updates to be available
on the replica before continuing:
XhiveSessionIf waitForUpdates(XhiveSessionIf session) {
if (currentWaitTimeStamp != null) {
session.waitForTimeStamp(currentWaitTimeStamp);
currentWaitTimeStamp = null;
}
return session;
}XhiveSessionIf.waitForTimeStamp(...) should complete immediately or quickly).