content: /**
   * 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.update;
  
  import org.apache.lucene.index.*;
  import org.apache.lucene.util.Version;
  import org.apache.solr.core.SolrConfig;
  import org.apache.solr.core.PluginInfo;
  import org.apache.solr.schema.IndexSchema;
  import org.apache.solr.util.SolrPluginUtils;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  import java.util.List;
  import java.util.Map;
  import java.util.HashMap;
  
  //
  // For performance reasons, we don't want to re-read
  // config params each time an index writer is created.
  // This config object encapsulates IndexWriter config params.
  //
  /**
   * @version $Id: SolrIndexConfig.java 1197159 2011-11-03 14:40:25Z mvg $
   */
  public class SolrIndexConfig {
    public static final Logger log = LoggerFactory.getLogger(SolrIndexConfig.class);
    
    public static final String defaultsName ="indexDefaults";
    final String defaultMergePolicyClassName;
    public static final String DEFAULT_MERGE_SCHEDULER_CLASSNAME = ConcurrentMergeScheduler.class.getName();
    static final SolrIndexConfig defaultDefaults = new SolrIndexConfig();
  
    private SolrIndexConfig() {
      luceneVersion = Version.LUCENE_31;
      useCompoundFile = true;
      maxBufferedDocs = -1;
      maxMergeDocs = -1;
      mergeFactor = -1;
      ramBufferSizeMB = 16;
      maxFieldLength = -1;
      writeLockTimeout = -1;
      lockType = null;
      termIndexInterval = IndexWriterConfig.DEFAULT_TERM_INDEX_INTERVAL;
      mergePolicyInfo = null;
      mergeSchedulerInfo = null;
      defaultMergePolicyClassName = TieredMergePolicy.class.getName();
    }
  
    public final Version luceneVersion;
    
    public final boolean useCompoundFile;
    public final int maxBufferedDocs;
    public final int maxMergeDocs;
    public final int mergeFactor;
  
    public final double ramBufferSizeMB;
  
    public final int maxFieldLength;
    public final int writeLockTimeout;
    public final String lockType;
    public final PluginInfo mergePolicyInfo;
    public final PluginInfo mergeSchedulerInfo;
    public final int termIndexInterval;
    
    public String infoStreamFile = null;
  
    public SolrIndexConfig(SolrConfig solrConfig, String prefix, SolrIndexConfig def)  {
      if (prefix == null)
        prefix = defaultsName;
      if (def == null)
        def = defaultDefaults;
  
      luceneVersion = solrConfig.luceneMatchVersion;
  
      defaultMergePolicyClassName = luceneVersion.onOrAfter(Version.LUCENE_33) ? TieredMergePolicy.class.getName() : LogByteSizeMergePolicy.class.getName();
      useCompoundFile=solrConfig.getBool(prefix+"/useCompoundFile", def.useCompoundFile);
      maxBufferedDocs=solrConfig.getInt(prefix+"/maxBufferedDocs",def.maxBufferedDocs);
      maxMergeDocs=solrConfig.getInt(prefix+"/maxMergeDocs",def.maxMergeDocs);
      mergeFactor=solrConfig.getInt(prefix+"/mergeFactor",def.mergeFactor);
      ramBufferSizeMB = solrConfig.getDouble(prefix+"/ramBufferSizeMB", def.ramBufferSizeMB);
  
      maxFieldLength=solrConfig.getInt(prefix+"/maxFieldLength",def.maxFieldLength);
      writeLockTimeout=solrConfig.getInt(prefix+"/writeLockTimeout", def.writeLockTimeout);
      lockType=solrConfig.get(prefix+"/lockType", def.lockType);
  
      String str =  solrConfig.get(prefix+"/mergeScheduler/text()",null);
      if(str != null && str.trim().length() >0){
        //legacy handling <mergeScheduler>[classname]</mergeScheduler>
        //remove in Solr2.0
        log.warn("deprecated syntax : <mergeScheduler>[classname]</mergeScheduler>");
        Map<String,String> atrs = new HashMap<String, String>();
        atrs.put("class",str.trim());
        mergeSchedulerInfo = new PluginInfo("mergeScheduler",atrs,null,null);
      } else {
        mergeSchedulerInfo = getPluginInfo(prefix + "/mergeScheduler", solrConfig, def.mergeSchedulerInfo);
      }
      str =  solrConfig.get(prefix+"/mergePolicy/text()",null);
      if(str != null && str.trim().length() >0){
        //legacy handling  <mergePolicy>[classname]</mergePolicy>
        //remove in Solr2.0
        log.warn("deprecated syntax : <mergePolicy>[classname]</mergePolicy>");
        Map<String,String> atrs = new HashMap<String, String>();
        atrs.put("class",str.trim());
        mergePolicyInfo = new PluginInfo("mergePolicy",atrs,null,null);
      } else {
        mergePolicyInfo = getPluginInfo(prefix + "/mergePolicy", solrConfig, def.mergePolicyInfo);
      }
      
      Object luceneAutoCommit = solrConfig.get(prefix + "/luceneAutoCommit", null);
      if(luceneAutoCommit != null) {
        log.warn("found deprecated option : luceneAutoCommit no longer has any affect - it is always false");
      }
      
      termIndexInterval = solrConfig.getInt(prefix + "/termIndexInterval", def.termIndexInterval);
      
      boolean infoStreamEnabled = solrConfig.getBool(prefix + "/infoStream", false);
      if(infoStreamEnabled) {
        infoStreamFile= solrConfig.get(prefix + "/infoStream/@file", null);
        log.info("IndexWriter infoStream debug log is enabled: " + infoStreamFile);
      }
    }
  
    private PluginInfo getPluginInfo(String path, SolrConfig solrConfig, PluginInfo def)  {
      List<PluginInfo> l = solrConfig.readPluginInfos(path, false, true);
      return l.isEmpty() ? def : l.get(0);
    }
  
    public IndexWriterConfig toIndexWriterConfig(IndexSchema schema) {
      IndexWriterConfig iwc = new IndexWriterConfig(luceneVersion, schema.getAnalyzer());
      if (maxBufferedDocs != -1)
        iwc.setMaxBufferedDocs(maxBufferedDocs);
  
      if (ramBufferSizeMB != -1)
        iwc.setRAMBufferSizeMB(ramBufferSizeMB);
  
      if (termIndexInterval != -1)
        iwc.setTermIndexInterval(termIndexInterval);
  
      if (writeLockTimeout != -1)
        iwc.setWriteLockTimeout(writeLockTimeout);
  
      iwc.setSimilarity(schema.getSimilarity());
      iwc.setMergePolicy(buildMergePolicy(schema));
      iwc.setMergeScheduler(buildMergeScheduler(schema));
  
      return iwc;
    }
  
    private MergePolicy buildMergePolicy(IndexSchema schema) {
      MergePolicy policy;
      String mpClassName = mergePolicyInfo == null ? defaultMergePolicyClassName : mergePolicyInfo.className;
  
      try {
        policy = (MergePolicy) schema.getResourceLoader().newInstance(mpClassName, null, new Class[]{IndexWriter.class}, new Object[]{this});
      } catch (Exception e) {
        policy = (MergePolicy) schema.getResourceLoader().newInstance(mpClassName);
      }
  
      if (policy instanceof LogMergePolicy) {
        LogMergePolicy logMergePolicy = (LogMergePolicy) policy;
  
        if (maxMergeDocs != -1)
          logMergePolicy.setMaxMergeDocs(maxMergeDocs);
  
        logMergePolicy.setUseCompoundFile(useCompoundFile);
  
        if (mergeFactor != -1)
          logMergePolicy.setMergeFactor(mergeFactor);
      } else if (policy instanceof TieredMergePolicy) {
        TieredMergePolicy tieredMergePolicy = (TieredMergePolicy) policy;
        
        tieredMergePolicy.setUseCompoundFile(useCompoundFile);
        
        if (mergeFactor != -1) {
          tieredMergePolicy.setMaxMergeAtOnce(mergeFactor);
          tieredMergePolicy.setSegmentsPerTier(mergeFactor);
        }
      } else {
        log.warn("Use of compound file format or mergefactor cannot be configured if merge policy is not an instance of LogMergePolicy or TieredMergePolicy. The configured policy's defaults will be used.");
      }
  
      if (mergePolicyInfo != null)
        SolrPluginUtils.invokeSetters(policy, mergePolicyInfo.initArgs);
  
      return policy;
    }
  
    private MergeScheduler buildMergeScheduler(IndexSchema schema) {
      String msClassName = mergeSchedulerInfo == null ? SolrIndexConfig.DEFAULT_MERGE_SCHEDULER_CLASSNAME : mergeSchedulerInfo.className;
      MergeScheduler scheduler = (MergeScheduler) schema.getResourceLoader().newInstance(msClassName);
  
      if (mergeSchedulerInfo != null)
        SolrPluginUtils.invokeSetters(scheduler, mergeSchedulerInfo.initArgs);
  
      return scheduler;
    }
  }
  