Advanced Server Integration

 

Author: Eike Stepper

Advanced integrations compose repositories with other repositories, diagnostics, or data-transfer facilities. They remain application integrations, not a substitute for Operator's Guide procedures for production topology, backups, or failover operation.

1 Synchronization and Failover
2 Monitoring and Activity Logs
3 Import and Export
4 Net4j and Other Intentional Extensions

1  Synchronization and Failover

An offline clone or failover participant is assembled from a local IStore, repository properties, and an IRepositorySynchronizer. Create the synchronizer from a remote CDOSessionConfigurationFactory; that factory supplies the remote session configuration, including connector and repository name. Configure retry and recommit policy before activation, create the specialized repository with CDOServerUtil.createOfflineClone(String, IStore, Map, IRepositorySynchronizer) or a failover-participant factory, then register it with the owning container. Repository activation starts synchronization; container deactivation stops the repository and synchronizer. The synchronizer owns the remote session it opens, while the application still owns the container, local store resources, and separately created connector infrastructure.

ISynchronizableRepository is a repository that synchronizes against a master through an IRepositorySynchronizer. It exposes the synchronizer, replicator session, replication progress, and explicit online/offline transition. The last replicated branch ID and commit timestamp describe replication progress; ISynchronizableRepository.hasBeenReplicated() distinguishes a repository that has completed an initial replication from one that has not. These values are progress information, not a promise that the remote repository is currently reachable or that a promotion is safe.

CDOServerUtil.createRepositorySynchronizer(CDOSessionConfigurationFactory) creates the supplied synchronizer from a remote session configuration factory. The synchronizer owns the remote session it opens and exposes retry and recommit controls. Keep the local repository and synchronizer under a clear lifecycle owner so shutdown closes the replication connection with the repository. These APIs expose state and transitions; they do not select a master, detect safe promotion, resolve split-brain, or guarantee automatic high availability. Those decisions and storage durability remain application and operations responsibilities. Progress and state events are useful inputs, but are not an operational failover protocol. CDOServerUtil.createOfflineClone(String, IStore, Map, IRepositorySynchronizer) and the failover-participant factories assemble specialized repository variants, but the application must still choose and coordinate the master, backup, storage, and transition policy. The API does not itself establish an operational failover topology or guarantee promotion safety. Treat source/target selection, retry policy, and lifecycle as application design; production failover and recovery procedures belong to the Operator's Guide.

2  Monitoring and Activity Logs

Repository state, manager containers, lifecycle events, and commit information provide lightweight programmatic diagnostics. RepositoryActivityLog is a lifecycle hook that registers a session-manager listener and a write-access handler while active. The rolling implementation records repository activation, session/view and transaction lifecycle, and commit start/finish events. Deactivating it removes those hooks and closes the rolling log. Keep the log active only while its repository is active, and treat it as diagnostic output rather than an audit trail or retention policy.

WithActivityLog.java      
RepositoryActivityLog log = new RepositoryActivityLog.Rolling("activities", 1000000L, true);
log.setRepository(repository);

try
{
  LifecycleUtil.activate(log);
  applicationWork.run();
}
finally
{
  LifecycleUtil.deactivate(log);
  log.setRepository(null);
}

3  Import and Export

CDOServerExporter and CDOServerImporter are stream-based programmatic transfer boundaries. Choose matching XML or binary implementations. An exporter reads package metadata, branches/revisions, large-object contents, and commit information. It flushes but does not close the caller's output stream, and it temporarily activates a repository only if it was inactive. An importer targets a newly constructed inactive repository: its constructor prepares the target store to drop existing data and activates the target before reading. Never point it at a live repository whose data must be preserved. It consumes but does not own the input stream. The caller closes streams and deactivates the target after import, including when import fails. A failed transfer may leave partial target data; discard that target and retry into a fresh one.

This sequence is useful for controlled migration/interchange. It is not an atomic backup or restore operation. The example uses an application-owned file as the transfer boundary.

TransferRepository.java      
try (OutputStream output = new FileOutputStream(exchangeFile))
{
  new CDOServerExporter.XML(source).exportRepository(output);
}

try
{
  try (InputStream input = new FileInputStream(exchangeFile))
  {
    new CDOServerImporter.XML(emptyTarget).importRepository(input);
  }
}
finally
{
  LifecycleUtil.deactivate(emptyTarget);
}

Backup consistency, scheduling, storage retention, and recovery runbooks remain Operator's Guide concerns.

4  Net4j and Other Intentional Extensions

Use the managed container to integrate supported acceptors, connectors, factories, and monitors with a CDO repository. Do not customize internal signal indications or protocol dispatch. When an extension cannot be expressed through the public API or documented SPI presented in this guide, keep it isolated and verify that it is intentionally supported before relying on it across CDO releases.