/* * 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.spelling.suggest; import java.io.IOException; import java.lang.invoke.MethodHandles; import org.apache.lucene.search.spell.Dictionary; import org.apache.lucene.search.suggest.InputIterator; import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.BytesRefIterator; import org.apache.lucene.util.LuceneTestCase; import org.apache.lucene.util.TestUtil; import org.apache.solr.common.params.CommonParams; import org.apache.solr.core.SolrCore; import org.apache.solr.search.SolrIndexSearcher; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Factory for a dictionary with an iterator over bounded-length random strings (with fixed * weight of 1 and null payloads) that only operates when RandomDictionary.enabledSysProp * is set; this will be true from the time a RandomDictionary has been constructed until * its enabledSysProp has been cleared. */ public class RandomTestDictionaryFactory extends DictionaryFactory { public static final String RAND_DICT_MAX_ITEMS = "randDictMaxItems"; private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); private static final long DEFAULT_MAX_ITEMS = 100_000_000; @Override public RandomTestDictionary create(SolrCore core, SolrIndexSearcher searcher) { if(params == null) { // should not happen; implies setParams was not called throw new IllegalStateException("Value of params not set"); } String name = (String)params.get(CommonParams.NAME); if (name == null) { // Shouldn't happen since this is the component name throw new IllegalArgumentException(CommonParams.NAME + " is a mandatory parameter"); } long maxItems = DEFAULT_MAX_ITEMS; Object specifiedMaxItems = params.get(RAND_DICT_MAX_ITEMS); if (specifiedMaxItems != null) { maxItems = Long.parseLong(specifiedMaxItems.toString()); } return new RandomTestDictionary(name, maxItems); } public static class RandomTestDictionary implements Dictionary { private static final String SYS_PROP_PREFIX = RandomTestDictionary.class.getName() + ".enabled."; private final String enabledSysProp; // Clear this property to stop the input iterator private final long maxItems; private long emittedItems = 0L; RandomTestDictionary(String name, long maxItems) { enabledSysProp = getEnabledSysProp(name); this.maxItems = maxItems; synchronized (RandomTestDictionary.class) { if (System.getProperty(enabledSysProp) != null) { throw new RuntimeException("System property '" + enabledSysProp + "' is already in use."); } System.setProperty(enabledSysProp, "true"); } } public static String getEnabledSysProp(String suggesterName) { return SYS_PROP_PREFIX + suggesterName; } @Override public InputIterator getEntryIterator() throws IOException { return new InputIterator.InputIteratorWrapper(new RandomByteRefIterator()); } private class RandomByteRefIterator implements BytesRefIterator { private static final int MAX_LENGTH = 100; @Override public BytesRef next() throws IOException { BytesRef next = null; if (System.getProperty(enabledSysProp) != null) { if (emittedItems < maxItems) { ++emittedItems; next = new BytesRef(TestUtil.randomUnicodeString(LuceneTestCase.random(), MAX_LENGTH)); if (emittedItems % 1000 == 0) { log.info(enabledSysProp + " emitted " + emittedItems + " items."); } } else { log.info(enabledSysProp + " disabled after emitting " + emittedItems + " items."); System.clearProperty(enabledSysProp); // disable once maxItems has been reached emittedItems = 0L; } } else { log.warn(enabledSysProp + " invoked when disabled"); emittedItems = 0L; } return next; } } } }