/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.apache.sling.discovery.impl.setup; import java.util.Properties; import java.util.concurrent.ConcurrentLinkedQueue; import javax.jcr.RepositoryException; import javax.jcr.observation.Event; import javax.jcr.observation.EventIterator; import javax.jcr.observation.EventListener; import org.apache.sling.api.SlingConstants; import org.apache.sling.discovery.base.its.setup.VirtualInstance; import org.apache.sling.discovery.impl.cluster.voting.VotingHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; class VotingEventListener implements EventListener { private final Logger logger = LoggerFactory.getLogger(this.getClass()); /** * */ private final VirtualInstance instance; private final VotingHandler votingHandler; volatile boolean stopped = false; private final String slingId; private ConcurrentLinkedQueue<org.osgi.service.event.Event> q = new ConcurrentLinkedQueue<org.osgi.service.event.Event>(); public VotingEventListener(VirtualInstance instance, final VotingHandler votingHandler, final String slingId) { this.instance = instance; this.votingHandler = votingHandler; this.slingId = slingId; Thread th = new Thread(new Runnable() { @Override public void run() { while(!stopped) { try{ org.osgi.service.event.Event ev = q.poll(); if (ev==null) { Thread.sleep(10); continue; } logger.debug("async.run: delivering event to listener: "+slingId+", stopped: "+stopped+", event: "+ev); votingHandler.handleEvent(ev); } catch(Exception e) { logger.error("async.run: got Exception: "+e, e); } } } }); th.setName("VotingEventListener-"+instance.getDebugName()); th.setDaemon(true); th.start(); } public void stop() { logger.debug("stop: stopping listener for slingId: "+slingId); stopped = true; } public void onEvent(EventIterator events) { if (stopped) { logger.info("onEvent: listener: "+slingId+" getting late events even though stopped: "+events.hasNext()); return; } try { while (!stopped && events.hasNext()) { Event event = events.nextEvent(); Properties properties = new Properties(); String topic; if (event.getType() == Event.NODE_ADDED) { topic = SlingConstants.TOPIC_RESOURCE_ADDED; } else if (event.getType() == Event.NODE_MOVED) { topic = SlingConstants.TOPIC_RESOURCE_CHANGED; } else if (event.getType() == Event.NODE_REMOVED) { topic = SlingConstants.TOPIC_RESOURCE_REMOVED; } else { topic = SlingConstants.TOPIC_RESOURCE_CHANGED; } try { properties.put("path", event.getPath()); org.osgi.service.event.Event osgiEvent = new org.osgi.service.event.Event( topic, properties); logger.debug("onEvent: enqueuing event to listener: "+slingId+", stopped: "+stopped+", event: "+osgiEvent); q.add(osgiEvent); } catch (RepositoryException e) { logger.warn("RepositoryException: " + e, e); } } if (stopped) { logger.info("onEvent: listener stopped: "+slingId+", pending events: "+events.hasNext()); } } catch (Throwable th) { try { this.instance.dumpRepo(); } catch (Exception e) { logger.info("onEvent: could not dump as part of catching a throwable, e="+e+", th="+th); } logger.error( "Throwable occurred in onEvent: " + th, th); } } }