use of org.apache.sling.discovery.commons.providers.DefaultInstanceDescription in project sling by apache.
the class OakClusterViewService method asClusterView.
private LocalClusterView asClusterView(DiscoveryLiteDescriptor descriptor, ResourceResolver resourceResolver) throws Exception {
if (descriptor == null) {
throw new IllegalArgumentException("descriptor must not be null");
}
if (resourceResolver == null) {
throw new IllegalArgumentException("resourceResolver must not be null");
}
logger.trace("asClusterView: start");
String clusterViewId = descriptor.getViewId();
if (clusterViewId == null || clusterViewId.length() == 0) {
logger.trace("asClusterView: no clusterId provided by discovery-lite descriptor - reading from repo.");
clusterViewId = readOrDefineClusterId(resourceResolver);
}
String localClusterSyncTokenId = /*descriptor.getViewId()+"_"+*/
String.valueOf(descriptor.getSeqNum());
if (!descriptor.isFinal()) {
throw new UndefinedClusterViewException(Reason.NO_ESTABLISHED_VIEW, "descriptor is not yet final: " + descriptor);
}
LocalClusterView cluster = new LocalClusterView(clusterViewId, localClusterSyncTokenId);
long me = descriptor.getMyId();
int[] activeIds = descriptor.getActiveIds();
if (activeIds == null || activeIds.length == 0) {
throw new UndefinedClusterViewException(Reason.NO_ESTABLISHED_VIEW, "Descriptor contained no active ids: " + descriptor.getDescriptorStr());
}
// convert int[] to List<Integer>
//TODO: could use Guava's Ints class here..
List<Integer> activeIdsList = new LinkedList<Integer>();
for (Integer integer : activeIds) {
activeIdsList.add(integer);
}
// step 1: sort activeIds by their leaderElectionId
// serves two purposes: pos[0] is then leader
// and the rest are properly sorted within the cluster
final Map<Integer, String> leaderElectionIds = new HashMap<Integer, String>();
for (Integer id : activeIdsList) {
String slingId = idMapService.toSlingId(id, resourceResolver);
if (slingId == null) {
idMapService.clearCache();
throw new UndefinedClusterViewException(Reason.NO_ESTABLISHED_VIEW, "no slingId mapped for clusterNodeId=" + id);
}
String leaderElectionId = getLeaderElectionId(resourceResolver, slingId);
leaderElectionIds.put(id, leaderElectionId);
}
Collections.sort(activeIdsList, new Comparator<Integer>() {
@Override
public int compare(Integer arg0, Integer arg1) {
return leaderElectionIds.get(arg0).compareTo(leaderElectionIds.get(arg1));
}
});
for (int i = 0; i < activeIdsList.size(); i++) {
int id = activeIdsList.get(i);
// thx to sorting above [0] is leader indeed
boolean isLeader = i == 0;
boolean isOwn = id == me;
String slingId = idMapService.toSlingId(id, resourceResolver);
if (slingId == null) {
idMapService.clearCache();
logger.info("asClusterView: cannot resolve oak-clusterNodeId {} to a slingId", id);
throw new Exception("Cannot resolve oak-clusterNodeId " + id + " to a slingId");
}
Map<String, String> properties = readProperties(slingId, resourceResolver);
// create a new instance (adds itself to the cluster in the constructor)
new DefaultInstanceDescription(cluster, isLeader, isOwn, slingId, properties);
}
logger.trace("asClusterView: returning {}", cluster);
InstanceDescription local = cluster.getLocalInstance();
if (local != null) {
return cluster;
} else {
logger.info("getClusterView: the local instance (" + getSlingId() + ") is currently not included in the existing established view! " + "This is normal at startup. At other times is pseudo-network-partitioning is an indicator for repository/network-delays or clocks-out-of-sync (SLING-3432). " + "(increasing the heartbeatTimeout can help as a workaround too) " + "The local instance will stay in TOPOLOGY_CHANGING or pre _INIT mode until a new vote was successful.");
throw new UndefinedClusterViewException(Reason.ISOLATED_FROM_TOPOLOGY, "established view does not include local instance - isolated");
}
}
use of org.apache.sling.discovery.commons.providers.DefaultInstanceDescription in project sling by apache.
the class OakDiscoveryService method activate.
/**
* Activate this service
*/
@Activate
protected void activate(final BundleContext bundleContext) {
logger.debug("OakDiscoveryService activating...");
if (settingsService == null) {
throw new IllegalStateException("settingsService not found");
}
if (oakViewChecker == null) {
throw new IllegalStateException("heartbeatHandler not found");
}
slingId = settingsService.getSlingId();
ClusterSyncService consistencyService;
if (config.getSyncTokenEnabled()) {
//TODO: ConsistencyHistory is implemented a little bit hacky ..
ClusterSyncHistory consistencyHistory = new ClusterSyncHistory();
oakBacklogClusterSyncService.setConsistencyHistory(consistencyHistory);
syncTokenService.setConsistencyHistory(consistencyHistory);
consistencyService = new ClusterSyncServiceChain(oakBacklogClusterSyncService, syncTokenService);
} else {
consistencyService = oakBacklogClusterSyncService;
}
viewStateManager = ViewStateManagerFactory.newViewStateManager(viewStateManagerLock, consistencyService);
if (config.getMinEventDelay() > 0) {
viewStateManager.installMinEventDelayHandler(this, scheduler, config.getMinEventDelay());
}
final String isolatedClusterId = UUID.randomUUID().toString();
{
// create a pre-voting/isolated topologyView which would be used
// until the first voting has finished.
// this way for the single-instance case the clusterId can
// remain the same between a getTopology() that is invoked before
// the first TOPOLOGY_INIT and afterwards
DefaultClusterView isolatedCluster = new DefaultClusterView(isolatedClusterId);
Map<String, String> emptyProperties = new HashMap<String, String>();
DefaultInstanceDescription isolatedInstance = new DefaultInstanceDescription(isolatedCluster, true, true, slingId, emptyProperties);
Collection<InstanceDescription> col = new ArrayList<InstanceDescription>();
col.add(isolatedInstance);
final DefaultTopologyView topology = new DefaultTopologyView();
topology.addInstances(col);
topology.setNotCurrent();
setOldView(topology);
}
setOldView((DefaultTopologyView) getTopology());
getOldView().setNotCurrent();
// make sure the first heartbeat is issued as soon as possible - which
// is right after this service starts. since the two (discoveryservice
// and heartbeatHandler need to know each other, the discoveryservice
// is passed on to the heartbeatHandler in this initialize call).
oakViewChecker.initialize(this);
viewStateManagerLock.lock();
try {
viewStateManager.handleActivated();
doUpdateProperties();
DefaultTopologyView newView = (DefaultTopologyView) getTopology();
if (newView.isCurrent()) {
viewStateManager.handleNewView(newView);
} else {
// SLING-3750: just issue a log.info about the delaying
logger.info("activate: this instance is in isolated mode and must yet finish voting before it can send out TOPOLOGY_INIT.");
}
activated = true;
setOldView(newView);
// bind them to the viewstatemanager too
for (TopologyEventListener listener : pendingListeners) {
viewStateManager.bind(listener);
}
pendingListeners.clear();
viewStateManager.bind(changePropagationListener);
} finally {
if (viewStateManagerLock != null) {
viewStateManagerLock.unlock();
}
}
URL[] topologyConnectorURLs = config.getTopologyConnectorURLs();
if (topologyConnectorURLs != null) {
for (int i = 0; i < topologyConnectorURLs.length; i++) {
final URL aURL = topologyConnectorURLs[i];
if (aURL != null) {
try {
logger.info("activate: registering outgoing topology connector to " + aURL);
connectorRegistry.registerOutgoingConnector(clusterViewService, aURL);
} catch (final Exception e) {
logger.info("activate: could not register url: " + aURL + " due to: " + e, e);
}
}
}
}
logger.debug("OakDiscoveryService activated.");
}
use of org.apache.sling.discovery.commons.providers.DefaultInstanceDescription in project sling by apache.
the class AnnouncementRegistryImplTest method doTestRegisterUnregister.
private void doTestRegisterUnregister(boolean includeFinalExpiryCheck) throws Exception {
try {
registry.registerAnnouncement(null);
fail("should complain");
} catch (IllegalArgumentException iae) {
// ok
}
try {
registry.unregisterAnnouncement(null);
fail("should complain");
} catch (IllegalArgumentException iae) {
// ok
}
try {
registry.unregisterAnnouncement("");
fail("should complain");
} catch (IllegalArgumentException iae) {
// ok
}
try {
new Announcement(null);
fail("should complain");
} catch (IllegalArgumentException iae) {
// ok
}
try {
new Announcement("");
fail("should complain");
} catch (IllegalArgumentException iae) {
// ok
}
Announcement ann = new Announcement(slingId);
assertFalse(ann.isValid());
assertFalse(registry.registerAnnouncement(ann) != -1);
DefaultClusterView localCluster = new DefaultClusterView(UUID.randomUUID().toString());
ann.setLocalCluster(localCluster);
assertFalse(ann.isValid());
assertFalse(registry.registerAnnouncement(ann) != -1);
try {
registry.listInstances(localCluster);
fail("doing getInstances() on an empty cluster should throw an illegalstateexception");
} catch (IllegalStateException ise) {
// ok
}
DefaultInstanceDescription instance = TopologyHelper.createInstanceDescription(ann.getOwnerId(), true, localCluster);
assertEquals(instance.getSlingId(), ann.getOwnerId());
assertTrue(ann.isValid());
assertTrue(registry.registerAnnouncement(ann) != -1);
assertEquals(1, registry.listInstances(localCluster).size());
registry.checkExpiredAnnouncements();
assertEquals(1, registry.listInstances(localCluster).size());
registry.unregisterAnnouncement(ann.getOwnerId());
assertEquals(0, registry.listInstances(localCluster).size());
assertTrue(ann.isValid());
assertTrue(registry.registerAnnouncement(ann) != -1);
assertEquals(1, registry.listInstances(localCluster).size());
if (includeFinalExpiryCheck) {
Thread.sleep(10500);
assertEquals(0, registry.listInstances(localCluster).size());
}
}
use of org.apache.sling.discovery.commons.providers.DefaultInstanceDescription in project sling by apache.
the class DefaultTopologyViewTest method testCompare.
@Test
public void testCompare() throws Exception {
DefaultTopologyView newView = TopologyHelper.createTopologyView(UUID.randomUUID().toString(), UUID.randomUUID().toString());
try {
newView.compareTopology(null);
fail("Should complain about null");
} catch (Exception e) {
// ok
}
DefaultTopologyView oldView = TopologyHelper.cloneTopologyView(newView);
assertNull(newView.compareTopology(oldView));
DefaultInstanceDescription id = TopologyHelper.createInstanceDescription(newView.getClusterViews().iterator().next());
TopologyHelper.addInstanceDescription(newView, id);
assertEquals(Type.TOPOLOGY_CHANGED, newView.compareTopology(oldView));
assertEquals(2, newView.getInstances().size());
// addInstanceDescription now no longer throws an exception if you add
// the same
// instance twice. this provides greater stability
TopologyHelper.addInstanceDescription(newView, id);
assertEquals(2, newView.getInstances().size());
// try{
// TopologyTestHelper.addInstanceDescription(newView, id);
// fail("should not be able to add twice");
// } catch(Exception e) {
// // ok
// }
oldView = TopologyHelper.cloneTopologyView(newView);
assertNull(newView.compareTopology(oldView));
DefaultInstanceDescription instance = (DefaultInstanceDescription) newView.getInstances().iterator().next();
instance.setProperty("a", "b");
assertEquals(Type.PROPERTIES_CHANGED, newView.compareTopology(oldView));
oldView = TopologyHelper.cloneTopologyView(newView);
assertNull(newView.compareTopology(oldView));
instance.setProperty("a", "B");
assertEquals(Type.PROPERTIES_CHANGED, newView.compareTopology(oldView));
oldView = TopologyHelper.cloneTopologyView(newView);
assertNull(newView.compareTopology(oldView));
instance.setProperty("a", "B");
assertNull(newView.compareTopology(oldView));
// now change the properties of the first instance but modify the second instance' cluster
Iterator<InstanceDescription> it = newView.getInstances().iterator();
DefaultInstanceDescription firstInstance = (DefaultInstanceDescription) it.next();
assertNotNull(firstInstance);
DefaultInstanceDescription secondInstance = (DefaultInstanceDescription) it.next();
assertNotNull(secondInstance);
firstInstance.setProperty("c", "d");
DefaultClusterView cluster = new DefaultClusterView(UUID.randomUUID().toString());
PrivateAccessor.setField(secondInstance, "clusterView", null);
cluster.addInstanceDescription(secondInstance);
assertEquals(Type.TOPOLOGY_CHANGED, newView.compareTopology(oldView));
}
use of org.apache.sling.discovery.commons.providers.DefaultInstanceDescription in project sling by apache.
the class DiscoveryServiceImpl method activate.
/**
* Activate this service
*/
@Activate
protected void activate(final BundleContext bundleContext) {
logger.debug("DiscoveryServiceImpl activating...");
if (settingsService == null) {
throw new IllegalStateException("settingsService not found");
}
if (heartbeatHandler == null) {
throw new IllegalStateException("heartbeatHandler not found");
}
slingId = settingsService.getSlingId();
final ClusterSyncService clusterSyncService;
if (!config.useSyncTokenService()) {
logger.info("activate: useSyncTokenService is configured to false. Using pass-through cluster-sync-service.");
clusterSyncService = PASS_THROUGH_CLUSTER_SYNC_SERVICE;
} else if (syncTokenService == null) {
logger.warn("activate: useSyncTokenService is configured to true but there's no SyncTokenService! Using pass-through cluster-sync-service instead.");
clusterSyncService = syncTokenService;
} else {
logger.info("activate: useSyncTokenService is configured to true, using the available SyncTokenService: " + syncTokenService);
clusterSyncService = syncTokenService;
}
viewStateManager = ViewStateManagerFactory.newViewStateManager(viewStateManagerLock, clusterSyncService);
if (config.getMinEventDelay() > 0) {
viewStateManager.installMinEventDelayHandler(this, scheduler, config.getMinEventDelay());
}
final String isolatedClusterId = UUID.randomUUID().toString();
{
// create a pre-voting/isolated topologyView which would be used
// until the first voting has finished.
// this way for the single-instance case the clusterId can
// remain the same between a getTopology() that is invoked before
// the first TOPOLOGY_INIT and afterwards
DefaultClusterView isolatedCluster = new DefaultClusterView(isolatedClusterId);
Map<String, String> emptyProperties = new HashMap<String, String>();
DefaultInstanceDescription isolatedInstance = new DefaultInstanceDescription(isolatedCluster, true, true, slingId, emptyProperties);
Collection<InstanceDescription> col = new ArrayList<InstanceDescription>();
col.add(isolatedInstance);
final DefaultTopologyView topology = new DefaultTopologyView();
topology.addInstances(col);
topology.setNotCurrent();
setOldView(topology);
}
setOldView((DefaultTopologyView) getTopology());
getOldView().setNotCurrent();
// make sure the first heartbeat is issued as soon as possible - which
// is right after this service starts. since the two (discoveryservice
// and heartbeatHandler need to know each other, the discoveryservice
// is passed on to the heartbeatHandler in this initialize call).
heartbeatHandler.initialize(this, isolatedClusterId);
viewStateManagerLock.lock();
try {
viewStateManager.handleActivated();
doUpdateProperties();
DefaultTopologyView newView = (DefaultTopologyView) getTopology();
if (newView.isCurrent()) {
viewStateManager.handleNewView(newView);
} else {
// SLING-3750: just issue a log.info about the delaying
logger.info("activate: this instance is in isolated mode and must yet finish voting before it can send out TOPOLOGY_INIT.");
}
activated = true;
setOldView(newView);
// bind them to the viewstatemanager too
for (TopologyEventListener listener : pendingListeners) {
viewStateManager.bind(listener);
}
pendingListeners.clear();
viewStateManager.bind(changePropagationListener);
} finally {
if (viewStateManagerLock != null) {
viewStateManagerLock.unlock();
}
}
URL[] topologyConnectorURLs = config.getTopologyConnectorURLs();
if (topologyConnectorURLs != null) {
for (int i = 0; i < topologyConnectorURLs.length; i++) {
final URL aURL = topologyConnectorURLs[i];
if (aURL != null) {
try {
logger.info("activate: registering outgoing topology connector to " + aURL);
connectorRegistry.registerOutgoingConnector(clusterViewService, aURL);
} catch (final Exception e) {
logger.info("activate: could not register url: " + aURL + " due to: " + e, e);
}
}
}
}
registerMBean(bundleContext);
logger.debug("DiscoveryServiceImpl activated.");
}
Aggregations