Package org.apache.solr.update

Source Code of org.apache.solr.update.CommitTracker

package org.apache.solr.update;

/**
* 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.
*/

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.core.SolrCore;
import org.apache.solr.request.LocalSolrQueryRequest;
import org.apache.solr.request.SolrQueryRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Helper class for tracking autoCommit state.
*
* Note: This is purely an implementation detail of autoCommit and will
* definitely change in the future, so the interface should not be relied-upon
*
* Note: all access must be synchronized.
*/
final class CommitTracker implements Runnable {
  protected final static Logger log = LoggerFactory.getLogger(CommitTracker.class);
 
  // scheduler delay for maxDoc-triggered autocommits
  public final int DOC_COMMIT_DELAY_MS = 1;
 
  // settings, not final so we can change them in testing
  private int docsUpperBound;
  private long timeUpperBound;
 
  private final ScheduledExecutorService scheduler = Executors
      .newScheduledThreadPool(1);
  private ScheduledFuture pending;
 
  // state
  private AtomicLong docsSinceCommit = new AtomicLong(0);
  private AtomicInteger autoCommitCount = new AtomicInteger(0);

  private final SolrCore core;

  private final boolean softCommit;
  private final boolean waitSearcher;

  private String name;
 
  public CommitTracker(String name, SolrCore core, int docsUpperBound, int timeUpperBound, boolean waitSearcher, boolean softCommit) {
    this.core = core;
    this.name = name;
    pending = null;
   
    this.docsUpperBound = docsUpperBound;
    this.timeUpperBound = timeUpperBound;
   
    this.softCommit = softCommit;
    this.waitSearcher = waitSearcher;

    SolrCore.log.info(name + " AutoCommit: " + this);
  }
 
  public synchronized void close() {
    if (pending != null) {
      pending.cancel(true);
      pending = null;
    }
    scheduler.shutdownNow();
  }
 
  /** schedule individual commits */
  public void scheduleCommitWithin(long commitMaxTime) {
    _scheduleCommitWithin(commitMaxTime);
  }

  private void _scheduleCommitWithin(long commitMaxTime) {
    if (commitMaxTime <= 0) return;
    synchronized (this) {
      if (pending != null && pending.getDelay(TimeUnit.MILLISECONDS) <= commitMaxTime) {
        // There is already a pending commit that will happen first, so
        // nothing else to do here.
        // log.info("###returning since getDelay()==" + pending.getDelay(TimeUnit.MILLISECONDS) + " less than " + commitMaxTime);

        return;
      }

      if (pending != null) {
        // we need to schedule a commit to happen sooner than the existing one,
        // so lets try to cancel the existing one first.
        boolean canceled = pending.cancel(false);
        if (!canceled) {
          // It looks like we can't cancel... it must have just started running!
          // this is possible due to thread scheduling delays and a low commitMaxTime.
          // Nothing else to do since we obviously can't schedule our commit *before*
          // the one that just started running (or has just completed).
          // log.info("###returning since cancel failed");
          return;
        }
      }

      // log.info("###scheduling for " + commitMaxTime);

      // schedule our new commit
      pending = scheduler.schedule(this, commitMaxTime, TimeUnit.MILLISECONDS);
    }
  }
 
  /**
   * Indicate that documents have been added
   */
  public void addedDocument(int commitWithin) {
    // maxDocs-triggered autoCommit.  Use == instead of > so we only trigger once on the way up
    if (docsUpperBound > 0) {
      long docs = docsSinceCommit.incrementAndGet();
      if (docs == docsUpperBound + 1) {
        // reset the count here instead of run() so we don't miss other documents being added
        docsSinceCommit.set(0);
        _scheduleCommitWithin(DOC_COMMIT_DELAY_MS);
      }
    }
   
    // maxTime-triggered autoCommit
    long ctime = (commitWithin > 0) ? commitWithin : timeUpperBound;

    if (ctime > 0) {
      _scheduleCommitWithin(ctime);
    }
  }
 
  /** Inform tracker that a commit has occurred */
  public void didCommit() {
  }
 
  /** Inform tracker that a rollback has occurred, cancel any pending commits */
  public void didRollback() {
    synchronized (this) {
      if (pending != null) {
        pending.cancel(false);
        pending = null; // let it start another one
      }
      docsSinceCommit.set(0);
    }
  }
 
  /** This is the worker part for the ScheduledFuture **/
  public void run() {
    synchronized (this) {
      // log.info("###start commit. pending=null");
      pending = null// allow a new commit to be scheduled
    }

    SolrQueryRequest req = new LocalSolrQueryRequest(core,
        new ModifiableSolrParams());
    try {
      CommitUpdateCommand command = new CommitUpdateCommand(false);
      command.waitSearcher = waitSearcher;
      // no need for command.maxOptimizeSegments = 1; since it is not optimizing

      // we increment this *before* calling commit because it was causing a race
      // in the tests (the new searcher was registered and the test proceeded
      // to check the commit count before we had incremented it.)
      autoCommitCount.incrementAndGet();

      core.getUpdateHandler().commit(command);
    } catch (Exception e) {
      SolrException.log(log, "auto commit error...", e);
    } finally {
      // log.info("###done committing");
      req.close();
    }
  }
 
  // to facilitate testing: blocks if called during commit
  public int getCommitCount() {
    return autoCommitCount.get();
  }
 
  @Override
  public String toString() {
    if (timeUpperBound > 0 || docsUpperBound > 0) {
      return (timeUpperBound > 0 ? ("if uncommited for " + timeUpperBound + "ms; ")
          : "")
          + (docsUpperBound > 0 ? ("if " + docsUpperBound + " uncommited docs ")
              : "");
     
    } else {
      return "disabled";
    }
  }

  public long getTimeUpperBound() {
    return timeUpperBound;
  }

  int getDocsUpperBound() {
    return docsUpperBound;
  }

  void setDocsUpperBound(int docsUpperBound) {
    this.docsUpperBound = docsUpperBound;
  }

  void setTimeUpperBound(long timeUpperBound) {
    this.timeUpperBound = timeUpperBound;
  }
}
TOP

Related Classes of org.apache.solr.update.CommitTracker

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.