diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index d01bfe37764..8348ab8a163 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -360,7 +360,6 @@ Optimizations Bug Fixes ---------------------- - * SOLR-1432: Make the new ValueSource.getValues(context,reader) delegate to the original ValueSource.getValues(reader) so custom sources will work. (yonik) @@ -569,6 +568,8 @@ Bug Fixes * SOLR-2219: The init() method of every SolrRequestHandler was being called twice. (ambikeshwar singh and hossman) +* SOLR-2285: duplicate SolrEventListeners no longer created (hossman) + Other Changes ---------------------- diff --git a/solr/src/java/org/apache/solr/core/SolrConfig.java b/solr/src/java/org/apache/solr/core/SolrConfig.java index 6834026645d..27a8d4b724a 100644 --- a/solr/src/java/org/apache/solr/core/SolrConfig.java +++ b/solr/src/java/org/apache/solr/core/SolrConfig.java @@ -198,7 +198,13 @@ public class SolrConfig extends Config { loadPluginInfo(ValueSourceParser.class,"valueSourceParser",true, true); loadPluginInfo(SearchComponent.class,"searchComponent",true, true); loadPluginInfo(QueryConverter.class,"queryConverter",true, true); + + // this is hackish, since it picks up all SolrEventListeners, + // regardless of when/how/why thye are used (or even if they are + // declared outside of the appropriate context) but there's no nice + // way arround that in the PluginInfo framework loadPluginInfo(SolrEventListener.class, "//listener",false, true); + loadPluginInfo(DirectoryFactory.class,"directoryFactory",false, true); loadPluginInfo(IndexDeletionPolicy.class,"mainIndex/deletionPolicy",false, true); loadPluginInfo(IndexReaderFactory.class,"indexReaderFactory",false, true); diff --git a/solr/src/java/org/apache/solr/core/SolrCore.java b/solr/src/java/org/apache/solr/core/SolrCore.java index a8f6c9684f1..559838b4f18 100644 --- a/solr/src/java/org/apache/solr/core/SolrCore.java +++ b/solr/src/java/org/apache/solr/core/SolrCore.java @@ -275,15 +275,19 @@ public final class SolrCore implements SolrInfoMBean { } private void initListeners() { + final Class clazz = SolrEventListener.class; + final String label = "Event Listener"; for (PluginInfo info : solrConfig.getPluginInfos(SolrEventListener.class.getName())) { - SolrEventListener listener = createInitInstance(info, SolrEventListener.class,"Event Listener",null); String event = info.attributes.get("event"); if("firstSearcher".equals(event) ){ - firstSearcherListeners.add(listener); + SolrEventListener obj = createInitInstance(info,clazz,label,null); + firstSearcherListeners.add(obj); + log.info(logid + "Added SolrEventListener for firstSearcher: " + obj); } else if("newSearcher".equals(event) ){ - newSearcherListeners.add(listener); + SolrEventListener obj = createInitInstance(info,clazz,label,null); + newSearcherListeners.add(obj); + log.info(logid + "Added SolrEventListener for newSearcher: " + obj); } - log.info(logid + "Added SolrEventListener: " + listener); } } diff --git a/solr/src/java/org/apache/solr/update/UpdateHandler.java b/solr/src/java/org/apache/solr/update/UpdateHandler.java index 48816b63371..4280b77f37a 100644 --- a/solr/src/java/org/apache/solr/update/UpdateHandler.java +++ b/solr/src/java/org/apache/solr/update/UpdateHandler.java @@ -61,15 +61,18 @@ public abstract class UpdateHandler implements SolrInfoMBean { protected Vector optimizeCallbacks = new Vector(); private void parseEventListeners() { - for (PluginInfo pluginInfo : core.getSolrConfig().getPluginInfos(SolrEventListener.class.getName())) { - String event = pluginInfo.attributes.get("event"); - SolrEventListener listener = core.createInitInstance(pluginInfo,SolrEventListener.class,"Event Listener",null); + final Class clazz = SolrEventListener.class; + final String label = "Event Listener"; + for (PluginInfo info : core.getSolrConfig().getPluginInfos(SolrEventListener.class.getName())) { + String event = info.attributes.get("event"); if ("postCommit".equals(event)) { - commitCallbacks.add(core.createInitInstance(pluginInfo,SolrEventListener.class,"Event Listener",null)); - log.info("added SolrEventListener for postCommit: " + listener); + SolrEventListener obj = core.createInitInstance(info,clazz,label,null); + commitCallbacks.add(obj); + log.info("added SolrEventListener for postCommit: " + obj); } else if ("postOptimize".equals(event)) { - optimizeCallbacks.add(listener); - log.info("added SolrEventListener for postOptimize: " + listener); + SolrEventListener obj = core.createInitInstance(info,clazz,label,null); + optimizeCallbacks.add(obj); + log.info("added SolrEventListener for postOptimize: " + obj); } } } diff --git a/solr/src/test/org/apache/solr/core/MockEventListener.java b/solr/src/test/org/apache/solr/core/MockEventListener.java new file mode 100644 index 00000000000..9fcd20f1941 --- /dev/null +++ b/solr/src/test/org/apache/solr/core/MockEventListener.java @@ -0,0 +1,49 @@ +/** + * 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.solr.core; + +import org.apache.solr.search.SolrIndexSearcher; +import org.apache.solr.common.util.NamedList; + +import java.util.concurrent.atomic.AtomicInteger; + +public class MockEventListener implements SolrEventListener { + + final static AtomicInteger createCounter = new AtomicInteger(0); + + public static final int getCreateCount() { + return createCounter.intValue(); + } + + public MockEventListener() { + createCounter.incrementAndGet(); + } + + public void init(NamedList args) { + /* NOOP */ + } + + public void postCommit() { + /* NOOP */ + } + + public void newSearcher(SolrIndexSearcher newSearcher, + SolrIndexSearcher currentSearcher) { + /* NOOP */ + } + +} diff --git a/solr/src/test/org/apache/solr/core/TestQuerySenderListener.java b/solr/src/test/org/apache/solr/core/TestQuerySenderListener.java index 8dc426ed4ab..2a6659340c3 100644 --- a/solr/src/test/org/apache/solr/core/TestQuerySenderListener.java +++ b/solr/src/test/org/apache/solr/core/TestQuerySenderListener.java @@ -28,18 +28,37 @@ import static org.junit.Assert.*; public class TestQuerySenderListener extends SolrTestCaseJ4 { + // number of instances configured in the solrconfig.xml + private static final int EXPECTED_MOCK_LISTENER_INSTANCES = 4; + + private static int preInitMockListenerCount = 0; + @BeforeClass public static void beforeClass() throws Exception { + // record current value prior to core initialization + // so we can verify the correct number of instances later + // NOTE: this won't work properly if concurrent tests run + // in the same VM + preInitMockListenerCount = MockEventListener.getCreateCount(); + initCore("solrconfig-querysender.xml","schema.xml"); } + public void testListenerCreationCounts() { + SolrCore core = h.getCore(); + + assertEquals("Unexpected number of listeners created", + EXPECTED_MOCK_LISTENER_INSTANCES, + MockEventListener.getCreateCount() - preInitMockListenerCount); + } + @Test public void testRequestHandlerRegistry() { // property values defined in build.xml SolrCore core = h.getCore(); - assertEquals( 1, core.firstSearcherListeners.size() ); - assertEquals( 1, core.newSearcherListeners.size() ); + assertEquals( 2, core.firstSearcherListeners.size() ); + assertEquals( 2, core.newSearcherListeners.size() ); } @Test diff --git a/solr/src/test/test-files/solr/conf/solrconfig-querysender.xml b/solr/src/test/test-files/solr/conf/solrconfig-querysender.xml index d1d66c119fa..a23c7342d26 100644 --- a/solr/src/test/test-files/solr/conf/solrconfig-querysender.xml +++ b/solr/src/test/test-files/solr/conf/solrconfig-querysender.xml @@ -29,6 +29,12 @@ solr.RAMDirectoryFactory is memory based and not persistent. --> + + + + @@ -43,6 +49,9 @@ rocks 0 10 mock + +