Package com.senseidb.indexing.activity

Source Code of com.senseidb.indexing.activity.BoboIndexTracker

/**
* This software is licensed to you under the Apache License, Version 2.0 (the
* "Apache License").
*
* LinkedIn's contributions are made under the Apache License. If you contribute
* to the Software, the contributions will be deemed to have been made under the
* Apache License, unless you expressly indicate otherwise. Please do not make any
* contributions that would be inconsistent with the Apache License.
*
* You may obtain a copy of the Apache License at http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, this software
* distributed under the Apache License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the Apache
* License for the specific language governing permissions and limitations for the
* software governed under the Apache License.
*
* © 2012 LinkedIn Corp. All Rights Reserved.
*/
package com.senseidb.indexing.activity;

import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;

import org.apache.log4j.Logger;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.store.RAMDirectory;

import proj.zoie.api.DocIDMapper;
import proj.zoie.api.IndexReaderFactory;
import proj.zoie.api.ZoieIndexReader;
import proj.zoie.api.ZoieSegmentReader;

import com.browseengine.bobo.api.BoboIndexReader;
import com.senseidb.search.node.SenseiCore;
import com.senseidb.search.node.SenseiIndexReaderDecorator.BoboListener;
import com.senseidb.search.plugin.PluggableSearchEngineManager;
import com.yammer.metrics.Metrics;
import com.yammer.metrics.core.Counter;
import com.yammer.metrics.core.MetricName;

public class BoboIndexTracker implements BoboListener {
  private final static Logger logger = Logger.getLogger(PluggableSearchEngineManager.class);
  private Object dummyValue = new Object();
  private Map<BoboIndexReader, Object> readers = new WeakHashMap<BoboIndexReader, Object>();
  private static Counter recoveredIndexInBoboFacetDataCache;
  private static Counter facetMappingMismatch;
  private static Counter numberOfCachedReaders;
  private static Counter numberOfDeletedReaders;
  private static Counter numberOfCreatedReaders;

  private  SenseiCore senseiCore;
  static {
    recoveredIndexInBoboFacetDataCache = Metrics.newCounter(new MetricName(CompositeActivityManager.class,
        "recoveredIndexInBoboFacetDataCache"));
    facetMappingMismatch = Metrics.newCounter(new MetricName(BoboIndexTracker.class, "facetMappingMismatch"));
    numberOfCachedReaders = Metrics.newCounter(new MetricName(BoboIndexTracker.class, "numberOfCachedReaders"));
    numberOfDeletedReaders = Metrics.newCounter(new MetricName(BoboIndexTracker.class, "numberOfDeletedReaders"));
    numberOfCreatedReaders = Metrics.newCounter(new MetricName(BoboIndexTracker.class, "numberOfCreatedReaders"));
  }

  public synchronized void updateExistingBoboIndexes(long uid, int index, Set<String> facets) {
    boolean deletedSegments = false;
    for (int partition : senseiCore.getPartitions()) {
      IndexReaderFactory<ZoieIndexReader<BoboIndexReader>> indexReaderFactory = senseiCore.getIndexReaderFactory(partition);
      List<ZoieIndexReader<BoboIndexReader>> indexReaders = null;
      try {
        indexReaders = indexReaderFactory.getIndexReaders();
        List<BoboIndexReader> boboReaders = ZoieSegmentReader.extractDecoratedReaders(indexReaders);
        for (BoboIndexReader boboIndexReader : boboReaders) {
          ZoieSegmentReader<BoboIndexReader> zoieSegmentReader = (ZoieSegmentReader<BoboIndexReader>) boboIndexReader.getInnerReader();  
          if (!isSegmentOnDisk(zoieSegmentReader)) {
            continue;
          }
          if (readers.remove(boboIndexReader) != null) {
            numberOfDeletedReaders.inc();
            deletedSegments = true;
          }        
          recoverReaderIfNeeded(uid, index, facets, boboIndexReader);
        }
      } catch (IOException ex) {
        logger.error(ex.getMessage(), ex);
      } finally {
        if (indexReaders != null) {
          indexReaderFactory.returnIndexReaders(indexReaders);
        }
      }
    
    }
    if (deletedSegments) {
      numberOfCachedReaders.clear();
      numberOfCachedReaders.inc(readers.size());
    }
    for (BoboIndexReader boboSegmentReader : readers.keySet()) {
      if (boboSegmentReader != null) {
        recoverReaderIfNeeded(uid, index, facets, boboSegmentReader);
      }
    }
  }

  private final  void recoverReaderIfNeeded(long uid, int index, Set<String> facets, BoboIndexReader boboIndexReader) {
    ZoieSegmentReader<BoboIndexReader> zoieSegmentReader = (ZoieSegmentReader<BoboIndexReader>) boboIndexReader.getInnerReader();
    if (zoieSegmentReader == null) return;
    DocIDMapper mapper = zoieSegmentReader.getDocIDMaper();
    if (mapper == null) return;
    int docId = mapper.getDocID(uid);
    if (docId < 0) {
      return ;
    }
    BoboIndexReader decoratedReader = (BoboIndexReader) zoieSegmentReader.getDecoratedReader();
    for (String facet : facets) {
      Object facetData = decoratedReader.getFacetData(facet);
      if (!(facetData instanceof int[])) {
        logger.warn("The facet " + facet + " should have a facet data of type int[] but not " + facetData.getClass().toString());
        continue;
      }
      int[] indexes = (int[]) facetData;
      if (indexes.length <= docId) {
        logger.warn(String.format(
            "The facet [%s] is supposed to contain the uid [%s] as the docid [%s], but its index array is only [%s] long", facet, uid,
            docId, indexes.length));
        facetMappingMismatch.inc();
        continue;
      }
      if (indexes[docId] > -1 && indexes[docId] != index) {
        logger.warn(String.format(
            "The facet [%s] is supposed to contain the uid [%s] as the docid [%s], with docId index [%s] but it contains index [%s]",
            facet, uid, docId, index, indexes[docId]));
        facetMappingMismatch.inc();
        continue;
      }
      if (indexes[docId] == -1) {
        indexes[docId] = index;
        recoveredIndexInBoboFacetDataCache.inc();
      }
    }
    return;
  }

  protected boolean isSegmentOnDiskAndBig(ZoieSegmentReader zoieSegmentReader) {
    return isSegmentOnDisk(zoieSegmentReader) && zoieSegmentReader.getUIDArray().length > 2000;
  }

  protected boolean isSegmentOnDisk(ZoieSegmentReader zoieSegmentReader) {
    return zoieSegmentReader.directory() != null && !(zoieSegmentReader.directory() instanceof RAMDirectory);
  }

  @Override
  public void indexCreated(BoboIndexReader boboIndexReader) {
    ZoieSegmentReader<BoboIndexReader> zoieSegmentReader = (ZoieSegmentReader<BoboIndexReader>) boboIndexReader.getInnerReader();
    if (isSegmentOnDiskAndBig(zoieSegmentReader)) {
      synchronized (this) {
        if (readers.containsKey(boboIndexReader)) {
          return;
        }
        readers.put(boboIndexReader, dummyValue);
        numberOfCachedReaders.clear();
        numberOfCachedReaders.inc(readers.size());
        numberOfCreatedReaders.inc();
      }
    }
  }

  @Override
  public void indexDeleted(IndexReader boboIndexReader) {
  }
  public SenseiCore getSenseiCore() {
    return senseiCore;
  }
  public void setSenseiCore(SenseiCore senseiCore) {
    this.senseiCore = senseiCore;
  }
}
TOP

Related Classes of com.senseidb.indexing.activity.BoboIndexTracker

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.