All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.modeshape.jcr.bus.ClusteredChangeBus Maven / Gradle / Ivy

There is a newer version: 5.4.1.Final
Show newest version
/*
 * ModeShape (http://www.modeshape.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.modeshape.jcr.bus;

import org.modeshape.common.annotation.ThreadSafe;
import org.modeshape.common.logging.Logger;
import org.modeshape.common.util.CheckArg;
import org.modeshape.jcr.cache.change.ChangeSet;
import org.modeshape.jcr.cache.change.ChangeSetListener;
import org.modeshape.jcr.clustering.ClusteringService;
import org.modeshape.jcr.clustering.MessageConsumer;

/**
 * Implementation of a {@link ChangeBus} which can run in a cluster, via {@link ClusteringService}. This bus wraps around another
 * bus, to which it delegates all "local" processing of events.
 * 

* It is important that the order of the {@link org.modeshape.jcr.cache.change.ChangeSet} instances are maintained across the * cluster, and JGroups will do this for us as long as we push all local changes into the channel and receive all local/remote * changes from the channel. *

* * @author Horia Chiorean */ @ThreadSafe public final class ClusteredChangeBus extends MessageConsumer implements ChangeBus { private static final Logger LOGGER = Logger.getLogger(ClusteredChangeBus.class); /** * The wrapped standalone bus to which standard bus operations are delegated */ private final ChangeBus delegate; /** * The {@link ClusteringService} which handles communication inside the cluster */ private final ClusteringService clusteringService; /** * Creates a new clustered repository bus * * @param delegate the local bus to which changes will be delegated * @param clusteringService the object which will handle sending/receiving information in the cluster. */ public ClusteredChangeBus( ChangeBus delegate, ClusteringService clusteringService ) { super(ChangeSet.class); CheckArg.isNotNull(delegate, "delegate"); CheckArg.isNotNull(clusteringService, "clusteringService"); this.delegate = delegate; this.clusteringService = clusteringService; } @Override public void consume( ChangeSet changes ) { if (hasObservers()) { delegate.notify(changes); logReceivedOperation(changes); } } @Override public synchronized void start() throws Exception { // make sure the clustering service is open if (!clusteringService.isOpen()) { throw new IllegalStateException("The clustering service has not been started"); } // start the delegate delegate.start(); // register with the clustering service clusteringService.addConsumer(this); } @Override public boolean hasObservers() { return delegate.hasObservers(); } @Override public synchronized void shutdown() { delegate.shutdown(); } @Override public void notify( ChangeSet changeSet ) { if (changeSet == null) { return; // do nothing } if (!clusteringService.multipleMembersInCluster()) { // We are in clustered mode, but there is only one participant in the cluster (us). // So short-circuit the cluster and just notify the local observers ... consume(changeSet); return; } // There are multiple participants in the cluster, so send all changes out to JGroups, // letting JGroups do the ordering of messages... logSendOperation(changeSet); clusteringService.sendMessage(changeSet); } protected final void logSendOperation( ChangeSet changeSet ) { if (LOGGER.isTraceEnabled()) { LOGGER.trace("Sending to cluster '{0}' {1} changes on workspace {2} made by {3} from process '{4}' at {5}", clusteringService.clusterName(), changeSet.size(), changeSet.getWorkspaceName(), changeSet.getUserData(), changeSet.getProcessKey(), changeSet.getTimestamp()); } } protected final void logReceivedOperation( ChangeSet changeSet ) { if (LOGGER.isTraceEnabled()) { LOGGER.trace("Received from cluster '{0}' {1} changes on workspace {2} made by {3} from process '{4}' at {5}", clusteringService.clusterName(), changeSet.size(), changeSet.getWorkspaceName(), changeSet.getUserId(), changeSet.getProcessKey(), changeSet.getTimestamp()); } } @Override public boolean register( ChangeSetListener listener ) { return delegate.register(listener); } @Override public boolean registerInThread( ChangeSetListener listener ) { return delegate.registerInThread(listener); } @Override public boolean unregister( ChangeSetListener listener ) { return delegate.unregister(listener); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy