Package org.apache.accumulo.core.metadata

Source Code of org.apache.accumulo.core.metadata.MetadataLocationObtainer

/*
* 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.accumulo.core.metadata;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;

import org.apache.accumulo.core.Constants;
import org.apache.accumulo.core.client.AccumuloException;
import org.apache.accumulo.core.client.AccumuloSecurityException;
import org.apache.accumulo.core.client.Instance;
import org.apache.accumulo.core.client.impl.AccumuloServerException;
import org.apache.accumulo.core.client.impl.ScannerOptions;
import org.apache.accumulo.core.client.impl.ServerConfigurationUtil;
import org.apache.accumulo.core.client.impl.TabletLocator;
import org.apache.accumulo.core.client.impl.TabletLocator.TabletLocation;
import org.apache.accumulo.core.client.impl.TabletLocator.TabletLocations;
import org.apache.accumulo.core.client.impl.TabletLocatorImpl.TabletLocationObtainer;
import org.apache.accumulo.core.client.impl.TabletServerBatchReaderIterator;
import org.apache.accumulo.core.client.impl.TabletServerBatchReaderIterator.ResultReceiver;
import org.apache.accumulo.core.client.impl.ThriftScanner;
import org.apache.accumulo.core.data.Column;
import org.apache.accumulo.core.data.Key;
import org.apache.accumulo.core.data.KeyExtent;
import org.apache.accumulo.core.data.PartialKey;
import org.apache.accumulo.core.data.Range;
import org.apache.accumulo.core.data.Value;
import org.apache.accumulo.core.data.thrift.IterInfo;
import org.apache.accumulo.core.iterators.user.WholeRowIterator;
import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection;
import org.apache.accumulo.core.security.Authorizations;
import org.apache.accumulo.core.security.Credentials;
import org.apache.accumulo.core.tabletserver.thrift.NotServingTabletException;
import org.apache.accumulo.core.util.OpTimer;
import org.apache.accumulo.core.util.TextUtil;
import org.apache.hadoop.io.Text;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;

public class MetadataLocationObtainer implements TabletLocationObtainer {
  private static final Logger log = Logger.getLogger(MetadataLocationObtainer.class);
  private SortedSet<Column> locCols;
  private ArrayList<Column> columns;
  private Instance instance;
 
  public MetadataLocationObtainer(Instance instance) {
   
    this.instance = instance;
   
    locCols = new TreeSet<Column>();
    locCols.add(new Column(TextUtil.getBytes(TabletsSection.CurrentLocationColumnFamily.NAME), null, null));
    locCols.add(TabletsSection.TabletColumnFamily.PREV_ROW_COLUMN.toColumn());
    columns = new ArrayList<Column>(locCols);
  }
 
  @Override
  public TabletLocations lookupTablet(Credentials credentials, TabletLocation src, Text row, Text stopRow, TabletLocator parent)
      throws AccumuloSecurityException, AccumuloException {
   
    try {
      OpTimer opTimer = null;
      if (log.isTraceEnabled())
        opTimer = new OpTimer(log, Level.TRACE).start("Looking up in " + src.tablet_extent.getTableId() + " row=" + TextUtil.truncate(row) + "  extent="
            + src.tablet_extent + " tserver=" + src.tablet_location);
     
      Range range = new Range(row, true, stopRow, true);
     
      TreeMap<Key,Value> encodedResults = new TreeMap<Key,Value>();
      TreeMap<Key,Value> results = new TreeMap<Key,Value>();
     
      // Use the whole row iterator so that a partial mutations is not read. The code that extracts locations for tablets does a sanity check to ensure there is
      // only one location. Reading a partial mutation could make it appear there are multiple locations when there are not.
      List<IterInfo> serverSideIteratorList = new ArrayList<IterInfo>();
      serverSideIteratorList.add(new IterInfo(10000, WholeRowIterator.class.getName(), "WRI"));
      Map<String,Map<String,String>> serverSideIteratorOptions = Collections.emptyMap();
     
      boolean more = ThriftScanner.getBatchFromServer(instance, credentials, range, src.tablet_extent, src.tablet_location, encodedResults, locCols,
          serverSideIteratorList, serverSideIteratorOptions, Constants.SCAN_BATCH_SIZE, Authorizations.EMPTY, false, ServerConfigurationUtil.getConfiguration(instance));
     
      decodeRows(encodedResults, results);
     
      if (more && results.size() == 1) {
        range = new Range(results.lastKey().followingKey(PartialKey.ROW_COLFAM_COLQUAL_COLVIS_TIME), true, new Key(stopRow).followingKey(PartialKey.ROW), false);
        encodedResults.clear();
        more = ThriftScanner.getBatchFromServer(instance, credentials, range, src.tablet_extent, src.tablet_location, encodedResults, locCols,
            serverSideIteratorList, serverSideIteratorOptions, Constants.SCAN_BATCH_SIZE, Authorizations.EMPTY, false, ServerConfigurationUtil.getConfiguration(instance));
       
        decodeRows(encodedResults, results);
      }
     
      if (opTimer != null)
        opTimer.stop("Got " + results.size() + " results  from " + src.tablet_extent + " in %DURATION%");
     
      //if (log.isTraceEnabled()) log.trace("results "+results);
     
      return MetadataLocationObtainer.getMetadataLocationEntries(results);
     
    } catch (AccumuloServerException ase) {
      if (log.isTraceEnabled())
        log.trace(src.tablet_extent.getTableId() + " lookup failed, " + src.tablet_location + " server side exception");
      throw ase;
    } catch (NotServingTabletException e) {
      if (log.isTraceEnabled())
        log.trace(src.tablet_extent.getTableId() + " lookup failed, " + src.tablet_location + " not serving " + src.tablet_extent);
      parent.invalidateCache(src.tablet_extent);
    } catch (AccumuloException e) {
      if (log.isTraceEnabled())
        log.trace(src.tablet_extent.getTableId() + " lookup failed", e);
      parent.invalidateCache(src.tablet_location);
    }
   
    return null;
  }
 
  private void decodeRows(TreeMap<Key,Value> encodedResults, TreeMap<Key,Value> results) throws AccumuloException {
    for (Entry<Key,Value> entry : encodedResults.entrySet()) {
      try {
        results.putAll(WholeRowIterator.decodeRow(entry.getKey(), entry.getValue()));
      } catch (IOException e) {
        throw new AccumuloException(e);
      }
    }
  }
 
  @Override
  public List<TabletLocation> lookupTablets(Credentials credentials, String tserver, Map<KeyExtent,List<Range>> tabletsRanges, TabletLocator parent)
      throws AccumuloSecurityException, AccumuloException {
   
    final TreeMap<Key,Value> results = new TreeMap<Key,Value>();

    ResultReceiver rr = new ResultReceiver() {
     
      @Override
      public void receive(List<Entry<Key,Value>> entries) {
        for (Entry<Key,Value> entry : entries) {
          try {
            results.putAll(WholeRowIterator.decodeRow(entry.getKey(), entry.getValue()));
          } catch (IOException e) {
            throw new RuntimeException(e);
          }
        }
      }
    };
   
    ScannerOptions opts = new ScannerOptions() {
      ScannerOptions setOpts() {
        this.fetchedColumns = locCols;
        this.serverSideIteratorList = new ArrayList<IterInfo>();
        // see comment in lookupTablet about why iterator is used
        this.serverSideIteratorList.add(new IterInfo(10000, WholeRowIterator.class.getName(), "WRI"));
        return this;
      }
    }.setOpts();
   
    Map<KeyExtent,List<Range>> unscanned = new HashMap<KeyExtent,List<Range>>();
    Map<KeyExtent,List<Range>> failures = new HashMap<KeyExtent,List<Range>>();
    try {
      TabletServerBatchReaderIterator.doLookup(instance, credentials, tserver, tabletsRanges, failures, unscanned, rr, columns, opts, Authorizations.EMPTY,
          ServerConfigurationUtil.getConfiguration(instance));
      if (failures.size() > 0) {
        // invalidate extents in parents cache
        if (log.isTraceEnabled())
          log.trace("lookupTablets failed for " + failures.size() + " extents");
        parent.invalidateCache(failures.keySet());
      }
    } catch (IOException e) {
      log.trace("lookupTablets failed server=" + tserver, e);
      parent.invalidateCache(tserver);
    } catch (AccumuloServerException e) {
      log.trace("lookupTablets failed server=" + tserver, e);
      throw e;
    }
   
    return MetadataLocationObtainer.getMetadataLocationEntries(results).getLocations();
  }
 
  public static TabletLocations getMetadataLocationEntries(SortedMap<Key,Value> entries) {
    Key key;
    Value val;
    Text location = null;
    Text session = null;
    Value prevRow = null;
    KeyExtent ke;
   
    List<TabletLocation> results = new ArrayList<TabletLocation>();
    ArrayList<KeyExtent> locationless = new ArrayList<KeyExtent>();
   
    Text lastRowFromKey = new Text();
   
    // text obj below is meant to be reused in loop for efficiency
    Text colf = new Text();
    Text colq = new Text();
   
    for (Entry<Key,Value> entry : entries.entrySet()) {
      key = entry.getKey();
      val = entry.getValue();
     
      if (key.compareRow(lastRowFromKey) != 0) {
        prevRow = null;
        location = null;
        session = null;
        key.getRow(lastRowFromKey);
      }
     
      colf = key.getColumnFamily(colf);
      colq = key.getColumnQualifier(colq);
     
      // interpret the row id as a key extent
      if (colf.equals(TabletsSection.CurrentLocationColumnFamily.NAME) || colf.equals(TabletsSection.FutureLocationColumnFamily.NAME)) {
        if (location != null) {
          throw new IllegalStateException("Tablet has multiple locations : " + lastRowFromKey);
        }
        location = new Text(val.toString());
        session = new Text(colq);
      } else if (TabletsSection.TabletColumnFamily.PREV_ROW_COLUMN.equals(colf, colq)) {
        prevRow = new Value(val);
      }
     
      if (prevRow != null) {
        ke = new KeyExtent(key.getRow(), prevRow);
        if (location != null)
          results.add(new TabletLocation(ke, location.toString(), session.toString()));
        else
          locationless.add(ke);
       
        location = null;
        prevRow = null;
      }
    }
   
    return new TabletLocations(results, locationless);
  }
}
TOP

Related Classes of org.apache.accumulo.core.metadata.MetadataLocationObtainer

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.