http://git-wip-us.apache.org/repos/asf/accumulo/blob/94cdcc4d/core/src/main/java/org/apache/accumulo/core/data/thrift/TSummaryRequest.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/data/thrift/TSummaryRequest.java b/core/src/main/java/org/apache/accumulo/core/data/thrift/TSummaryRequest.java new file mode 100644 index 0000000..78c242e --- /dev/null +++ b/core/src/main/java/org/apache/accumulo/core/data/thrift/TSummaryRequest.java @@ -0,0 +1,760 @@ +/* + * 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. + */ +/** + * Autogenerated by Thrift Compiler (0.10.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +package org.apache.accumulo.core.data.thrift; + +@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"}) +@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.10.0)") +public class TSummaryRequest implements org.apache.thrift.TBase<TSummaryRequest, TSummaryRequest._Fields>, java.io.Serializable, Cloneable, Comparable<TSummaryRequest> { + private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("TSummaryRequest"); + + private static final org.apache.thrift.protocol.TField TABLE_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("tableId", org.apache.thrift.protocol.TType.STRING, (short)1); + private static final org.apache.thrift.protocol.TField BOUNDS_FIELD_DESC = new org.apache.thrift.protocol.TField("bounds", org.apache.thrift.protocol.TType.STRUCT, (short)2); + private static final org.apache.thrift.protocol.TField SUMMARIZERS_FIELD_DESC = new org.apache.thrift.protocol.TField("summarizers", org.apache.thrift.protocol.TType.LIST, (short)3); + private static final org.apache.thrift.protocol.TField SUMMARIZER_PATTERN_FIELD_DESC = new org.apache.thrift.protocol.TField("summarizerPattern", org.apache.thrift.protocol.TType.STRING, (short)4); + + private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new TSummaryRequestStandardSchemeFactory(); + private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new TSummaryRequestTupleSchemeFactory(); + + public java.lang.String tableId; // required + public TRowRange bounds; // required + public java.util.List<TSummarizerConfiguration> summarizers; // required + public java.lang.String summarizerPattern; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements org.apache.thrift.TFieldIdEnum { + TABLE_ID((short)1, "tableId"), + BOUNDS((short)2, "bounds"), + SUMMARIZERS((short)3, "summarizers"), + SUMMARIZER_PATTERN((short)4, "summarizerPattern"); + + private static final java.util.Map<java.lang.String, _Fields> byName = new java.util.HashMap<java.lang.String, _Fields>(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // TABLE_ID + return TABLE_ID; + case 2: // BOUNDS + return BOUNDS; + case 3: // SUMMARIZERS + return SUMMARIZERS; + case 4: // SUMMARIZER_PATTERN + return SUMMARIZER_PATTERN; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + public static final java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.TABLE_ID, new org.apache.thrift.meta_data.FieldMetaData("tableId", org.apache.thrift.TFieldRequirementType.DEFAULT, + new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))); + tmpMap.put(_Fields.BOUNDS, new org.apache.thrift.meta_data.FieldMetaData("bounds", org.apache.thrift.TFieldRequirementType.DEFAULT, + new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, TRowRange.class))); + tmpMap.put(_Fields.SUMMARIZERS, new org.apache.thrift.meta_data.FieldMetaData("summarizers", org.apache.thrift.TFieldRequirementType.DEFAULT, + new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, + new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, TSummarizerConfiguration.class)))); + tmpMap.put(_Fields.SUMMARIZER_PATTERN, new org.apache.thrift.meta_data.FieldMetaData("summarizerPattern", org.apache.thrift.TFieldRequirementType.DEFAULT, + new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(TSummaryRequest.class, metaDataMap); + } + + public TSummaryRequest() { + } + + public TSummaryRequest( + java.lang.String tableId, + TRowRange bounds, + java.util.List<TSummarizerConfiguration> summarizers, + java.lang.String summarizerPattern) + { + this(); + this.tableId = tableId; + this.bounds = bounds; + this.summarizers = summarizers; + this.summarizerPattern = summarizerPattern; + } + + /** + * Performs a deep copy on <i>other</i>. + */ + public TSummaryRequest(TSummaryRequest other) { + if (other.isSetTableId()) { + this.tableId = other.tableId; + } + if (other.isSetBounds()) { + this.bounds = new TRowRange(other.bounds); + } + if (other.isSetSummarizers()) { + java.util.List<TSummarizerConfiguration> __this__summarizers = new java.util.ArrayList<TSummarizerConfiguration>(other.summarizers.size()); + for (TSummarizerConfiguration other_element : other.summarizers) { + __this__summarizers.add(new TSummarizerConfiguration(other_element)); + } + this.summarizers = __this__summarizers; + } + if (other.isSetSummarizerPattern()) { + this.summarizerPattern = other.summarizerPattern; + } + } + + public TSummaryRequest deepCopy() { + return new TSummaryRequest(this); + } + + @Override + public void clear() { + this.tableId = null; + this.bounds = null; + this.summarizers = null; + this.summarizerPattern = null; + } + + public java.lang.String getTableId() { + return this.tableId; + } + + public TSummaryRequest setTableId(java.lang.String tableId) { + this.tableId = tableId; + return this; + } + + public void unsetTableId() { + this.tableId = null; + } + + /** Returns true if field tableId is set (has been assigned a value) and false otherwise */ + public boolean isSetTableId() { + return this.tableId != null; + } + + public void setTableIdIsSet(boolean value) { + if (!value) { + this.tableId = null; + } + } + + public TRowRange getBounds() { + return this.bounds; + } + + public TSummaryRequest setBounds(TRowRange bounds) { + this.bounds = bounds; + return this; + } + + public void unsetBounds() { + this.bounds = null; + } + + /** Returns true if field bounds is set (has been assigned a value) and false otherwise */ + public boolean isSetBounds() { + return this.bounds != null; + } + + public void setBoundsIsSet(boolean value) { + if (!value) { + this.bounds = null; + } + } + + public int getSummarizersSize() { + return (this.summarizers == null) ? 0 : this.summarizers.size(); + } + + public java.util.Iterator<TSummarizerConfiguration> getSummarizersIterator() { + return (this.summarizers == null) ? null : this.summarizers.iterator(); + } + + public void addToSummarizers(TSummarizerConfiguration elem) { + if (this.summarizers == null) { + this.summarizers = new java.util.ArrayList<TSummarizerConfiguration>(); + } + this.summarizers.add(elem); + } + + public java.util.List<TSummarizerConfiguration> getSummarizers() { + return this.summarizers; + } + + public TSummaryRequest setSummarizers(java.util.List<TSummarizerConfiguration> summarizers) { + this.summarizers = summarizers; + return this; + } + + public void unsetSummarizers() { + this.summarizers = null; + } + + /** Returns true if field summarizers is set (has been assigned a value) and false otherwise */ + public boolean isSetSummarizers() { + return this.summarizers != null; + } + + public void setSummarizersIsSet(boolean value) { + if (!value) { + this.summarizers = null; + } + } + + public java.lang.String getSummarizerPattern() { + return this.summarizerPattern; + } + + public TSummaryRequest setSummarizerPattern(java.lang.String summarizerPattern) { + this.summarizerPattern = summarizerPattern; + return this; + } + + public void unsetSummarizerPattern() { + this.summarizerPattern = null; + } + + /** Returns true if field summarizerPattern is set (has been assigned a value) and false otherwise */ + public boolean isSetSummarizerPattern() { + return this.summarizerPattern != null; + } + + public void setSummarizerPatternIsSet(boolean value) { + if (!value) { + this.summarizerPattern = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case TABLE_ID: + if (value == null) { + unsetTableId(); + } else { + setTableId((java.lang.String)value); + } + break; + + case BOUNDS: + if (value == null) { + unsetBounds(); + } else { + setBounds((TRowRange)value); + } + break; + + case SUMMARIZERS: + if (value == null) { + unsetSummarizers(); + } else { + setSummarizers((java.util.List<TSummarizerConfiguration>)value); + } + break; + + case SUMMARIZER_PATTERN: + if (value == null) { + unsetSummarizerPattern(); + } else { + setSummarizerPattern((java.lang.String)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case TABLE_ID: + return getTableId(); + + case BOUNDS: + return getBounds(); + + case SUMMARIZERS: + return getSummarizers(); + + case SUMMARIZER_PATTERN: + return getSummarizerPattern(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case TABLE_ID: + return isSetTableId(); + case BOUNDS: + return isSetBounds(); + case SUMMARIZERS: + return isSetSummarizers(); + case SUMMARIZER_PATTERN: + return isSetSummarizerPattern(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof TSummaryRequest) + return this.equals((TSummaryRequest)that); + return false; + } + + public boolean equals(TSummaryRequest that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_tableId = true && this.isSetTableId(); + boolean that_present_tableId = true && that.isSetTableId(); + if (this_present_tableId || that_present_tableId) { + if (!(this_present_tableId && that_present_tableId)) + return false; + if (!this.tableId.equals(that.tableId)) + return false; + } + + boolean this_present_bounds = true && this.isSetBounds(); + boolean that_present_bounds = true && that.isSetBounds(); + if (this_present_bounds || that_present_bounds) { + if (!(this_present_bounds && that_present_bounds)) + return false; + if (!this.bounds.equals(that.bounds)) + return false; + } + + boolean this_present_summarizers = true && this.isSetSummarizers(); + boolean that_present_summarizers = true && that.isSetSummarizers(); + if (this_present_summarizers || that_present_summarizers) { + if (!(this_present_summarizers && that_present_summarizers)) + return false; + if (!this.summarizers.equals(that.summarizers)) + return false; + } + + boolean this_present_summarizerPattern = true && this.isSetSummarizerPattern(); + boolean that_present_summarizerPattern = true && that.isSetSummarizerPattern(); + if (this_present_summarizerPattern || that_present_summarizerPattern) { + if (!(this_present_summarizerPattern && that_present_summarizerPattern)) + return false; + if (!this.summarizerPattern.equals(that.summarizerPattern)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetTableId()) ? 131071 : 524287); + if (isSetTableId()) + hashCode = hashCode * 8191 + tableId.hashCode(); + + hashCode = hashCode * 8191 + ((isSetBounds()) ? 131071 : 524287); + if (isSetBounds()) + hashCode = hashCode * 8191 + bounds.hashCode(); + + hashCode = hashCode * 8191 + ((isSetSummarizers()) ? 131071 : 524287); + if (isSetSummarizers()) + hashCode = hashCode * 8191 + summarizers.hashCode(); + + hashCode = hashCode * 8191 + ((isSetSummarizerPattern()) ? 131071 : 524287); + if (isSetSummarizerPattern()) + hashCode = hashCode * 8191 + summarizerPattern.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(TSummaryRequest other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetTableId()).compareTo(other.isSetTableId()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetTableId()) { + lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.tableId, other.tableId); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetBounds()).compareTo(other.isSetBounds()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetBounds()) { + lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.bounds, other.bounds); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetSummarizers()).compareTo(other.isSetSummarizers()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetSummarizers()) { + lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.summarizers, other.summarizers); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetSummarizerPattern()).compareTo(other.isSetSummarizerPattern()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetSummarizerPattern()) { + lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.summarizerPattern, other.summarizerPattern); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("TSummaryRequest("); + boolean first = true; + + sb.append("tableId:"); + if (this.tableId == null) { + sb.append("null"); + } else { + sb.append(this.tableId); + } + first = false; + if (!first) sb.append(", "); + sb.append("bounds:"); + if (this.bounds == null) { + sb.append("null"); + } else { + sb.append(this.bounds); + } + first = false; + if (!first) sb.append(", "); + sb.append("summarizers:"); + if (this.summarizers == null) { + sb.append("null"); + } else { + sb.append(this.summarizers); + } + first = false; + if (!first) sb.append(", "); + sb.append("summarizerPattern:"); + if (this.summarizerPattern == null) { + sb.append("null"); + } else { + sb.append(this.summarizerPattern); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws org.apache.thrift.TException { + // check for required fields + // check for sub-struct validity + if (bounds != null) { + bounds.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out))); + } catch (org.apache.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in))); + } catch (org.apache.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class TSummaryRequestStandardSchemeFactory implements org.apache.thrift.scheme.SchemeFactory { + public TSummaryRequestStandardScheme getScheme() { + return new TSummaryRequestStandardScheme(); + } + } + + private static class TSummaryRequestStandardScheme extends org.apache.thrift.scheme.StandardScheme<TSummaryRequest> { + + public void read(org.apache.thrift.protocol.TProtocol iprot, TSummaryRequest struct) throws org.apache.thrift.TException { + org.apache.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // TABLE_ID + if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { + struct.tableId = iprot.readString(); + struct.setTableIdIsSet(true); + } else { + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 2: // BOUNDS + if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) { + struct.bounds = new TRowRange(); + struct.bounds.read(iprot); + struct.setBoundsIsSet(true); + } else { + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 3: // SUMMARIZERS + if (schemeField.type == org.apache.thrift.protocol.TType.LIST) { + { + org.apache.thrift.protocol.TList _list122 = iprot.readListBegin(); + struct.summarizers = new java.util.ArrayList<TSummarizerConfiguration>(_list122.size); + TSummarizerConfiguration _elem123; + for (int _i124 = 0; _i124 < _list122.size; ++_i124) + { + _elem123 = new TSummarizerConfiguration(); + _elem123.read(iprot); + struct.summarizers.add(_elem123); + } + iprot.readListEnd(); + } + struct.setSummarizersIsSet(true); + } else { + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 4: // SUMMARIZER_PATTERN + if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { + struct.summarizerPattern = iprot.readString(); + struct.setSummarizerPatternIsSet(true); + } else { + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(org.apache.thrift.protocol.TProtocol oprot, TSummaryRequest struct) throws org.apache.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.tableId != null) { + oprot.writeFieldBegin(TABLE_ID_FIELD_DESC); + oprot.writeString(struct.tableId); + oprot.writeFieldEnd(); + } + if (struct.bounds != null) { + oprot.writeFieldBegin(BOUNDS_FIELD_DESC); + struct.bounds.write(oprot); + oprot.writeFieldEnd(); + } + if (struct.summarizers != null) { + oprot.writeFieldBegin(SUMMARIZERS_FIELD_DESC); + { + oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, struct.summarizers.size())); + for (TSummarizerConfiguration _iter125 : struct.summarizers) + { + _iter125.write(oprot); + } + oprot.writeListEnd(); + } + oprot.writeFieldEnd(); + } + if (struct.summarizerPattern != null) { + oprot.writeFieldBegin(SUMMARIZER_PATTERN_FIELD_DESC); + oprot.writeString(struct.summarizerPattern); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class TSummaryRequestTupleSchemeFactory implements org.apache.thrift.scheme.SchemeFactory { + public TSummaryRequestTupleScheme getScheme() { + return new TSummaryRequestTupleScheme(); + } + } + + private static class TSummaryRequestTupleScheme extends org.apache.thrift.scheme.TupleScheme<TSummaryRequest> { + + @Override + public void write(org.apache.thrift.protocol.TProtocol prot, TSummaryRequest struct) throws org.apache.thrift.TException { + org.apache.thrift.protocol.TTupleProtocol oprot = (org.apache.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetTableId()) { + optionals.set(0); + } + if (struct.isSetBounds()) { + optionals.set(1); + } + if (struct.isSetSummarizers()) { + optionals.set(2); + } + if (struct.isSetSummarizerPattern()) { + optionals.set(3); + } + oprot.writeBitSet(optionals, 4); + if (struct.isSetTableId()) { + oprot.writeString(struct.tableId); + } + if (struct.isSetBounds()) { + struct.bounds.write(oprot); + } + if (struct.isSetSummarizers()) { + { + oprot.writeI32(struct.summarizers.size()); + for (TSummarizerConfiguration _iter126 : struct.summarizers) + { + _iter126.write(oprot); + } + } + } + if (struct.isSetSummarizerPattern()) { + oprot.writeString(struct.summarizerPattern); + } + } + + @Override + public void read(org.apache.thrift.protocol.TProtocol prot, TSummaryRequest struct) throws org.apache.thrift.TException { + org.apache.thrift.protocol.TTupleProtocol iprot = (org.apache.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(4); + if (incoming.get(0)) { + struct.tableId = iprot.readString(); + struct.setTableIdIsSet(true); + } + if (incoming.get(1)) { + struct.bounds = new TRowRange(); + struct.bounds.read(iprot); + struct.setBoundsIsSet(true); + } + if (incoming.get(2)) { + { + org.apache.thrift.protocol.TList _list127 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32()); + struct.summarizers = new java.util.ArrayList<TSummarizerConfiguration>(_list127.size); + TSummarizerConfiguration _elem128; + for (int _i129 = 0; _i129 < _list127.size; ++_i129) + { + _elem128 = new TSummarizerConfiguration(); + _elem128.read(iprot); + struct.summarizers.add(_elem128); + } + } + struct.setSummarizersIsSet(true); + } + if (incoming.get(3)) { + struct.summarizerPattern = iprot.readString(); + struct.setSummarizerPatternIsSet(true); + } + } + } + + private static <S extends org.apache.thrift.scheme.IScheme> S scheme(org.apache.thrift.protocol.TProtocol proto) { + return (org.apache.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } + private static void unusedMethod() {} +} +
http://git-wip-us.apache.org/repos/asf/accumulo/blob/94cdcc4d/core/src/main/java/org/apache/accumulo/core/file/BloomFilterLayer.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/file/BloomFilterLayer.java b/core/src/main/java/org/apache/accumulo/core/file/BloomFilterLayer.java index 6e5728a..4808da3 100644 --- a/core/src/main/java/org/apache/accumulo/core/file/BloomFilterLayer.java +++ b/core/src/main/java/org/apache/accumulo/core/file/BloomFilterLayer.java @@ -97,12 +97,12 @@ public class BloomFilterLayer { private boolean closed = false; private long length = -1; - Writer(FileSKVWriter writer, AccumuloConfiguration acuconf) { + Writer(FileSKVWriter writer, AccumuloConfiguration acuconf, boolean useAccumuloStart) { this.writer = writer; - initBloomFilter(acuconf); + initBloomFilter(acuconf, useAccumuloStart); } - private synchronized void initBloomFilter(AccumuloConfiguration acuconf) { + private synchronized void initBloomFilter(AccumuloConfiguration acuconf, boolean useAccumuloStart) { numKeys = acuconf.getCount(Property.TABLE_BLOOM_SIZE); // vector size should be <code>-kn / (ln(1 - c^(1/k)))</code> bits for @@ -121,7 +121,9 @@ public class BloomFilterLayer { String context = acuconf.get(Property.TABLE_CLASSPATH); String classname = acuconf.get(Property.TABLE_BLOOM_KEY_FUNCTOR); Class<? extends KeyFunctor> clazz; - if (context != null && !context.equals("")) + if (!useAccumuloStart) + clazz = Writer.class.getClassLoader().loadClass(classname).asSubclass(KeyFunctor.class); + else if (context != null && !context.equals("")) clazz = AccumuloVFSClassLoader.getContextManager().loadClass(context, classname, KeyFunctor.class); else clazz = AccumuloVFSClassLoader.loadClass(classname, KeyFunctor.class); http://git-wip-us.apache.org/repos/asf/accumulo/blob/94cdcc4d/core/src/main/java/org/apache/accumulo/core/file/DispatchingFileFactory.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/file/DispatchingFileFactory.java b/core/src/main/java/org/apache/accumulo/core/file/DispatchingFileFactory.java index c7d8248..e36b30f 100644 --- a/core/src/main/java/org/apache/accumulo/core/file/DispatchingFileFactory.java +++ b/core/src/main/java/org/apache/accumulo/core/file/DispatchingFileFactory.java @@ -23,6 +23,7 @@ import org.apache.accumulo.core.conf.Property; import org.apache.accumulo.core.file.map.MapFileOperations; import org.apache.accumulo.core.file.rfile.RFile; import org.apache.accumulo.core.file.rfile.RFileOperations; +import org.apache.accumulo.core.summary.SummaryWriter; import org.apache.hadoop.fs.Path; class DispatchingFileFactory extends FileOperations { @@ -73,10 +74,10 @@ class DispatchingFileFactory extends FileOperations { protected FileSKVWriter openWriter(OpenWriterOperation options) throws IOException { FileSKVWriter writer = findFileFactory(options).openWriter(options); if (options.getTableConfiguration().getBoolean(Property.TABLE_BLOOM_ENABLED)) { - return new BloomFilterLayer.Writer(writer, options.getTableConfiguration()); - } else { - return writer; + writer = new BloomFilterLayer.Writer(writer, options.getTableConfiguration(), options.isAccumuloStartEnabled()); } + + return SummaryWriter.wrap(writer, options.getTableConfiguration(), options.isAccumuloStartEnabled()); } @Override http://git-wip-us.apache.org/repos/asf/accumulo/blob/94cdcc4d/core/src/main/java/org/apache/accumulo/core/file/FileOperations.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/file/FileOperations.java b/core/src/main/java/org/apache/accumulo/core/file/FileOperations.java index 10bb784..67757bc 100644 --- a/core/src/main/java/org/apache/accumulo/core/file/FileOperations.java +++ b/core/src/main/java/org/apache/accumulo/core/file/FileOperations.java @@ -292,6 +292,7 @@ public abstract class FileOperations { NeedsFileOrOuputStream<OpenWriterOperationBuilder> { private String compression; private FSDataOutputStream outputStream; + private boolean enableAccumuloStart = true; @Override public NeedsTableConfiguration<OpenWriterOperationBuilder> forOutputStream(String extenstion, FSDataOutputStream outputStream, Configuration fsConf) { @@ -301,6 +302,16 @@ public abstract class FileOperations { return this; } + public boolean isAccumuloStartEnabled() { + return enableAccumuloStart; + } + + @Override + public OpenWriterOperation setAccumuloStartEnabled(boolean enableAccumuloStart) { + this.enableAccumuloStart = enableAccumuloStart; + return this; + } + @Override public OpenWriterOperation withCompression(String compression) { this.compression = compression; @@ -337,6 +348,13 @@ public abstract class FileOperations { /** Set the compression type. */ public OpenWriterOperationBuilder withCompression(String compression); + /** + * Classes may be instantiated as part of a write operation. For example if BloomFilters, Samplers, or Summarizers are used then classes are loaded. When + * running in a tserver, Accumulo start should be used to load classes. When running in a client process, Accumulo start should not be used. This method + * makes it possible to specify if Accumulo Start should be used to load classes. Calling this method is optional and the default is true. + */ + public OpenWriterOperationBuilder setAccumuloStartEnabled(boolean enableAccumuloStart); + /** Construct the writer. */ public FileSKVWriter build() throws IOException; } http://git-wip-us.apache.org/repos/asf/accumulo/blob/94cdcc4d/core/src/main/java/org/apache/accumulo/core/file/rfile/PrintInfo.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/file/rfile/PrintInfo.java b/core/src/main/java/org/apache/accumulo/core/file/rfile/PrintInfo.java index 00ebb7a..d17528c 100644 --- a/core/src/main/java/org/apache/accumulo/core/file/rfile/PrintInfo.java +++ b/core/src/main/java/org/apache/accumulo/core/file/rfile/PrintInfo.java @@ -30,6 +30,7 @@ import org.apache.accumulo.core.data.Value; import org.apache.accumulo.core.file.FileSKVIterator; import org.apache.accumulo.core.file.blockfile.impl.CachableBlockFile; import org.apache.accumulo.core.file.rfile.RFile.Reader; +import org.apache.accumulo.core.summary.SummaryReader; import org.apache.accumulo.core.util.LocalityGroupUtil; import org.apache.accumulo.start.spi.KeywordExecutable; import org.apache.commons.math3.stat.descriptive.SummaryStatistics; @@ -58,6 +59,8 @@ public class PrintInfo implements KeywordExecutable { boolean histogram = false; @Parameter(names = {"--useSample"}, description = "Use sample data for --dump, --vis, --histogram options") boolean useSample = false; + @Parameter(names = {"--summary"}, description = "Print summary data in file") + boolean printSummary = false; @Parameter(names = {"--keyStats"}, description = "print key length statistics for index and all data") boolean keyStats = false; @Parameter(description = " <file> { <file> ... }") @@ -210,6 +213,10 @@ public class PrintInfo implements KeywordExecutable { } } + if (opts.printSummary) { + SummaryReader.print(iter, System.out); + } + iter.close(); if (opts.vis || opts.hash) { http://git-wip-us.apache.org/repos/asf/accumulo/blob/94cdcc4d/core/src/main/java/org/apache/accumulo/core/file/rfile/RFileOperations.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/file/rfile/RFileOperations.java b/core/src/main/java/org/apache/accumulo/core/file/rfile/RFileOperations.java index 96d31ce..ec721ba 100644 --- a/core/src/main/java/org/apache/accumulo/core/file/rfile/RFileOperations.java +++ b/core/src/main/java/org/apache/accumulo/core/file/rfile/RFileOperations.java @@ -88,7 +88,7 @@ public class RFileOperations extends FileOperations { Sampler sampler = null; if (samplerConfig != null) { - sampler = SamplerFactory.newSampler(samplerConfig, acuconf); + sampler = SamplerFactory.newSampler(samplerConfig, acuconf, options.isAccumuloStartEnabled()); } String compression = options.getCompression(); http://git-wip-us.apache.org/repos/asf/accumulo/blob/94cdcc4d/core/src/main/java/org/apache/accumulo/core/metadata/schema/MetadataScanner.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/metadata/schema/MetadataScanner.java b/core/src/main/java/org/apache/accumulo/core/metadata/schema/MetadataScanner.java new file mode 100644 index 0000000..7e92b64 --- /dev/null +++ b/core/src/main/java/org/apache/accumulo/core/metadata/schema/MetadataScanner.java @@ -0,0 +1,236 @@ +/* + * 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.schema; + +import static org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.TabletColumnFamily.PREV_ROW_COLUMN; + +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; + +import org.apache.accumulo.core.client.AccumuloException; +import org.apache.accumulo.core.client.AccumuloSecurityException; +import org.apache.accumulo.core.client.IsolatedScanner; +import org.apache.accumulo.core.client.Scanner; +import org.apache.accumulo.core.client.TableNotFoundException; +import org.apache.accumulo.core.client.impl.ClientContext; +import org.apache.accumulo.core.data.impl.KeyExtent; +import org.apache.accumulo.core.metadata.MetadataTable; +import org.apache.accumulo.core.metadata.RootTable; +import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.CurrentLocationColumnFamily; +import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.DataFileColumnFamily; +import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.FutureLocationColumnFamily; +import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.LastLocationColumnFamily; +import org.apache.accumulo.core.metadata.schema.TabletMetadata.FetchedColumns; +import org.apache.accumulo.core.security.Authorizations; +import org.apache.accumulo.core.util.ColumnFQ; +import org.apache.hadoop.io.Text; + +import com.google.common.base.Preconditions; + +public class MetadataScanner { + + public static interface SourceOptions { + TableOptions from(Scanner scanner); + + TableOptions from(ClientContext ctx); + } + + public static interface TableOptions { + ColumnOptions overRootTable(); + + ColumnOptions overMetadataTable(); + + ColumnOptions overUserTableId(String tableId); + + ColumnOptions overUserTableId(String tableId, Text startRow, Text endRow); + } + + public static interface ColumnOptions { + public ColumnOptions fetchFiles(); + + public ColumnOptions fetchLocation(); + + public ColumnOptions fetchPrev(); + + public ColumnOptions fetchLast(); + + public Iterable<TabletMetadata> build() throws TableNotFoundException, AccumuloException, AccumuloSecurityException; + } + + private static class TabletMetadataIterator implements Iterator<TabletMetadata> { + + private boolean sawLast = false; + private Iterator<TabletMetadata> iter; + private Text endRow; + + TabletMetadataIterator(Iterator<TabletMetadata> source, Text endRow) { + this.iter = source; + this.endRow = endRow; + } + + @Override + public boolean hasNext() { + return !sawLast && iter.hasNext(); + } + + @Override + public TabletMetadata next() { + if (sawLast) { + throw new NoSuchElementException(); + } + TabletMetadata next = iter.next(); + if (next.getExtent().contains(endRow)) { + sawLast = true; + } + return next; + } + } + + private static class Builder implements SourceOptions, TableOptions, ColumnOptions { + + private List<Text> families = new ArrayList<>(); + private List<ColumnFQ> qualifiers = new ArrayList<>(); + private Scanner scanner; + private ClientContext ctx; + private String table; + private String userTableId; + private EnumSet<FetchedColumns> fetchedCols = EnumSet.noneOf(FetchedColumns.class); + private Text startRow; + private Text endRow; + + @Override + public ColumnOptions fetchFiles() { + fetchedCols.add(FetchedColumns.FILES); + families.add(DataFileColumnFamily.NAME); + return this; + } + + @Override + public ColumnOptions fetchLocation() { + fetchedCols.add(FetchedColumns.LOCATION); + families.add(CurrentLocationColumnFamily.NAME); + families.add(FutureLocationColumnFamily.NAME); + return this; + } + + @Override + public ColumnOptions fetchPrev() { + fetchedCols.add(FetchedColumns.PREV_ROW); + qualifiers.add(PREV_ROW_COLUMN); + return this; + } + + @Override + public ColumnOptions fetchLast() { + fetchedCols.add(FetchedColumns.LAST); + families.add(LastLocationColumnFamily.NAME); + return this; + } + + @Override + public Iterable<TabletMetadata> build() throws TableNotFoundException, AccumuloException, AccumuloSecurityException { + if (ctx != null) { + scanner = new IsolatedScanner(ctx.getConnector().createScanner(table, Authorizations.EMPTY)); + } else if (!(scanner instanceof IsolatedScanner)) { + scanner = new IsolatedScanner(scanner); + } + + if (userTableId != null) { + scanner.setRange(new KeyExtent(userTableId, null, startRow).toMetadataRange()); + } + + for (Text fam : families) { + scanner.fetchColumnFamily(fam); + } + + for (ColumnFQ col : qualifiers) { + col.fetch(scanner); + } + + if (families.size() == 0 && qualifiers.size() == 0) { + fetchedCols = EnumSet.allOf(FetchedColumns.class); + } + + Iterable<TabletMetadata> tmi = TabletMetadata.convert(scanner, fetchedCols); + + if (endRow != null) { + // create an iterable that will stop at the tablet which contains the endRow + return new Iterable<TabletMetadata>() { + @Override + public Iterator<TabletMetadata> iterator() { + return new TabletMetadataIterator(tmi.iterator(), endRow); + } + }; + } else { + return tmi; + } + + } + + @Override + public ColumnOptions overRootTable() { + this.table = RootTable.NAME; + return this; + } + + @Override + public ColumnOptions overMetadataTable() { + this.table = MetadataTable.NAME; + return this; + } + + @Override + public ColumnOptions overUserTableId(String tableId) { + Preconditions.checkArgument(!tableId.equals(RootTable.ID) && !tableId.equals(MetadataTable.ID)); + + this.table = MetadataTable.NAME; + this.userTableId = tableId; + return this; + } + + @Override + public TableOptions from(Scanner scanner) { + this.scanner = scanner; + return this; + } + + @Override + public TableOptions from(ClientContext ctx) { + this.ctx = ctx; + return this; + } + + @Override + public ColumnOptions overUserTableId(String tableId, Text startRow, Text endRow) { + this.table = MetadataTable.NAME; + this.userTableId = tableId; + this.startRow = startRow; + this.endRow = endRow; + return this; + } + + } + + public static SourceOptions builder() { + return new Builder(); + } + +} http://git-wip-us.apache.org/repos/asf/accumulo/blob/94cdcc4d/core/src/main/java/org/apache/accumulo/core/metadata/schema/TabletMetadata.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/metadata/schema/TabletMetadata.java b/core/src/main/java/org/apache/accumulo/core/metadata/schema/TabletMetadata.java new file mode 100644 index 0000000..af5f814 --- /dev/null +++ b/core/src/main/java/org/apache/accumulo/core/metadata/schema/TabletMetadata.java @@ -0,0 +1,182 @@ +/* + * 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.schema; + +import static org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.TabletColumnFamily.PREV_ROW_COLUMN; + +import java.util.EnumSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map.Entry; +import java.util.Objects; + +import org.apache.accumulo.core.client.RowIterator; +import org.apache.accumulo.core.client.Scanner; +import org.apache.accumulo.core.data.ByteSequence; +import org.apache.accumulo.core.data.Key; +import org.apache.accumulo.core.data.Value; +import org.apache.accumulo.core.data.impl.KeyExtent; +import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.CurrentLocationColumnFamily; +import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.DataFileColumnFamily; +import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.FutureLocationColumnFamily; +import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.LastLocationColumnFamily; +import org.apache.hadoop.io.Text; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableList.Builder; +import com.google.common.collect.Iterators; +import com.google.common.net.HostAndPort; + +public class TabletMetadata { + + private String tableId; + private Text prevEndRow; + private Text endRow; + private Location location; + private List<String> files; + private EnumSet<FetchedColumns> fetchedColumns; + private KeyExtent extent; + private Location last; + + public static enum LocationType { + CURRENT, FUTURE, LAST + } + + public static enum FetchedColumns { + LOCATION, PREV_ROW, FILES, LAST + } + + public static class Location { + private final String server; + private final String session; + private final LocationType lt; + + Location(String server, String session, LocationType lt) { + this.server = server; + this.session = session; + this.lt = lt; + } + + public HostAndPort getHostAndPort() { + return HostAndPort.fromString(server); + } + + public String getSession() { + return session; + } + + public LocationType getLocationType() { + return lt; + } + } + + public String getTableId() { + return tableId; + } + + public KeyExtent getExtent() { + if (extent == null) { + extent = new KeyExtent(getTableId(), getEndRow(), getPrevEndRow()); + } + return extent; + } + + public Text getPrevEndRow() { + Preconditions.checkState(fetchedColumns.contains(FetchedColumns.PREV_ROW), "Requested prev row when it was not fetched"); + return prevEndRow; + } + + public Text getEndRow() { + return endRow; + } + + public Location getLocation() { + Preconditions.checkState(fetchedColumns.contains(FetchedColumns.LOCATION), "Requested location when it was not fetched"); + return location; + } + + public Location getLast() { + Preconditions.checkState(fetchedColumns.contains(FetchedColumns.LAST), "Requested last when it was not fetched"); + return last; + } + + public List<String> getFiles() { + Preconditions.checkState(fetchedColumns.contains(FetchedColumns.FILES), "Requested files when it was not fetched"); + return files; + } + + public static TabletMetadata convertRow(Iterator<Entry<Key,Value>> rowIter, EnumSet<FetchedColumns> fetchedColumns) { + Objects.requireNonNull(rowIter); + + TabletMetadata te = new TabletMetadata(); + + Builder<String> filesBuilder = ImmutableList.builder(); + ByteSequence row = null; + + while (rowIter.hasNext()) { + Entry<Key,Value> kv = rowIter.next(); + Key k = kv.getKey(); + Value v = kv.getValue(); + Text fam = k.getColumnFamily(); + + if (row == null) { + row = k.getRowData(); + KeyExtent ke = new KeyExtent(k.getRow(), (Text) null); + te.endRow = ke.getEndRow(); + te.tableId = ke.getTableId(); + } else if (!row.equals(k.getRowData())) { + throw new IllegalArgumentException("Input contains more than one row : " + row + " " + k.getRowData()); + } + + if (PREV_ROW_COLUMN.hasColumns(k)) { + te.prevEndRow = KeyExtent.decodePrevEndRow(v); + } + + if (fam.equals(DataFileColumnFamily.NAME)) { + filesBuilder.add(k.getColumnQualifier().toString()); + } else if (fam.equals(CurrentLocationColumnFamily.NAME)) { + if (te.location != null) { + throw new IllegalArgumentException("Input contains more than one location " + te.location + " " + v); + } + te.location = new Location(v.toString(), k.getColumnQualifierData().toString(), LocationType.CURRENT); + } else if (fam.equals(FutureLocationColumnFamily.NAME)) { + if (te.location != null) { + throw new IllegalArgumentException("Input contains more than one location " + te.location + " " + v); + } + te.location = new Location(v.toString(), k.getColumnQualifierData().toString(), LocationType.FUTURE); + } else if (fam.equals(LastLocationColumnFamily.NAME)) { + te.last = new Location(v.toString(), k.getColumnQualifierData().toString(), LocationType.LAST); + } + } + + te.files = filesBuilder.build(); + te.fetchedColumns = fetchedColumns; + return te; + } + + public static Iterable<TabletMetadata> convert(Scanner input, EnumSet<FetchedColumns> fetchedColumns) { + return new Iterable<TabletMetadata>() { + @Override + public Iterator<TabletMetadata> iterator() { + RowIterator rowIter = new RowIterator(input); + return Iterators.transform(rowIter, ri -> convertRow(ri, fetchedColumns)); + } + }; + } +} http://git-wip-us.apache.org/repos/asf/accumulo/blob/94cdcc4d/core/src/main/java/org/apache/accumulo/core/sample/impl/SamplerConfigurationImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/sample/impl/SamplerConfigurationImpl.java b/core/src/main/java/org/apache/accumulo/core/sample/impl/SamplerConfigurationImpl.java index d3e2fe7..7c622b0 100644 --- a/core/src/main/java/org/apache/accumulo/core/sample/impl/SamplerConfigurationImpl.java +++ b/core/src/main/java/org/apache/accumulo/core/sample/impl/SamplerConfigurationImpl.java @@ -17,8 +17,6 @@ package org.apache.accumulo.core.sample.impl; -import static com.google.common.base.Preconditions.checkArgument; - import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; @@ -171,16 +169,6 @@ public class SamplerConfigurationImpl implements Writable { return className + " " + options; } - public static void checkDisjoint(Map<String,String> props, SamplerConfiguration samplerConfiguration) { - if (props.isEmpty() || samplerConfiguration == null) { - return; - } - - Map<String,String> sampleProps = new SamplerConfigurationImpl(samplerConfiguration).toTablePropertiesMap(); - - checkArgument(Collections.disjoint(props.keySet(), sampleProps.keySet()), "Properties and derived sampler properties are not disjoint"); - } - public static TSamplerConfiguration toThrift(SamplerConfiguration samplerConfig) { if (samplerConfig == null) return null; http://git-wip-us.apache.org/repos/asf/accumulo/blob/94cdcc4d/core/src/main/java/org/apache/accumulo/core/sample/impl/SamplerFactory.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/sample/impl/SamplerFactory.java b/core/src/main/java/org/apache/accumulo/core/sample/impl/SamplerFactory.java index d70f3af..0cf75ae 100644 --- a/core/src/main/java/org/apache/accumulo/core/sample/impl/SamplerFactory.java +++ b/core/src/main/java/org/apache/accumulo/core/sample/impl/SamplerFactory.java @@ -25,11 +25,13 @@ import org.apache.accumulo.core.conf.Property; import org.apache.accumulo.start.classloader.vfs.AccumuloVFSClassLoader; public class SamplerFactory { - public static Sampler newSampler(SamplerConfigurationImpl config, AccumuloConfiguration acuconf) throws IOException { + public static Sampler newSampler(SamplerConfigurationImpl config, AccumuloConfiguration acuconf, boolean useAccumuloStart) throws IOException { String context = acuconf.get(Property.TABLE_CLASSPATH); Class<? extends Sampler> clazz; try { + if (!useAccumuloStart) + clazz = SamplerFactory.class.getClassLoader().loadClass(config.getClassName()).asSubclass(Sampler.class); if (context != null && !context.equals("")) clazz = AccumuloVFSClassLoader.getContextManager().loadClass(context, config.getClassName(), Sampler.class); else @@ -45,4 +47,8 @@ public class SamplerFactory { throw new RuntimeException(e); } } + + public static Sampler newSampler(SamplerConfigurationImpl config, AccumuloConfiguration acuconf) throws IOException { + return newSampler(config, acuconf, true); + } } http://git-wip-us.apache.org/repos/asf/accumulo/blob/94cdcc4d/core/src/main/java/org/apache/accumulo/core/security/TablePermission.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/security/TablePermission.java b/core/src/main/java/org/apache/accumulo/core/security/TablePermission.java index a80be9a..d721ebc 100644 --- a/core/src/main/java/org/apache/accumulo/core/security/TablePermission.java +++ b/core/src/main/java/org/apache/accumulo/core/security/TablePermission.java @@ -33,11 +33,12 @@ public enum TablePermission { BULK_IMPORT((byte) 4), ALTER_TABLE((byte) 5), GRANT((byte) 6), - DROP_TABLE((byte) 7); + DROP_TABLE((byte) 7), + GET_SUMMARIES((byte) 8); final private byte permID; - final private static TablePermission mapping[] = new TablePermission[8]; + final private static TablePermission mapping[] = new TablePermission[9]; static { for (TablePermission perm : TablePermission.values()) mapping[perm.permID] = perm; http://git-wip-us.apache.org/repos/asf/accumulo/blob/94cdcc4d/core/src/main/java/org/apache/accumulo/core/summary/Gatherer.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/summary/Gatherer.java b/core/src/main/java/org/apache/accumulo/core/summary/Gatherer.java new file mode 100644 index 0000000..8389051 --- /dev/null +++ b/core/src/main/java/org/apache/accumulo/core/summary/Gatherer.java @@ -0,0 +1,631 @@ +/* + * 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.summary; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.TreeMap; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Predicate; +import java.util.function.Supplier; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +import org.apache.accumulo.core.client.AccumuloException; +import org.apache.accumulo.core.client.AccumuloSecurityException; +import org.apache.accumulo.core.client.TableNotFoundException; +import org.apache.accumulo.core.client.impl.ClientContext; +import org.apache.accumulo.core.client.impl.ServerClient; +import org.apache.accumulo.core.client.summary.SummarizerConfiguration; +import org.apache.accumulo.core.conf.AccumuloConfiguration; +import org.apache.accumulo.core.data.ByteSequence; +import org.apache.accumulo.core.data.Key; +import org.apache.accumulo.core.data.Range; +import org.apache.accumulo.core.data.impl.KeyExtent; +import org.apache.accumulo.core.data.thrift.TRowRange; +import org.apache.accumulo.core.data.thrift.TSummaries; +import org.apache.accumulo.core.data.thrift.TSummaryRequest; +import org.apache.accumulo.core.file.blockfile.cache.BlockCache; +import org.apache.accumulo.core.metadata.schema.MetadataScanner; +import org.apache.accumulo.core.metadata.schema.TabletMetadata; +import org.apache.accumulo.core.rpc.ThriftUtil; +import org.apache.accumulo.core.tabletserver.thrift.TabletClientService; +import org.apache.accumulo.core.tabletserver.thrift.TabletClientService.Client; +import org.apache.accumulo.core.trace.Tracer; +import org.apache.accumulo.core.trace.thrift.TInfo; +import org.apache.accumulo.core.util.ByteBufferUtil; +import org.apache.accumulo.core.util.CachedConfiguration; +import org.apache.accumulo.core.util.CancelFlagFuture; +import org.apache.accumulo.core.util.CompletableFutureUtil; +import org.apache.accumulo.core.util.TextUtil; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.io.Text; +import org.apache.thrift.TApplicationException; +import org.apache.thrift.TException; +import org.apache.thrift.transport.TTransportException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; +import com.google.common.hash.Hashing; +import com.google.common.net.HostAndPort; + +/** + * This class implements using multiple tservers to gather summaries. + * + * Below is a rough outline of the RPC process. + * + * <ol> + * <li>Clients pick a random tserver and make an RPC to remotely execute {@link #gather(ExecutorService)}. + * <li> {@link #gather(ExecutorService)} will call make RPC calls to multiple tservers to remotely execute {@link #processPartition(ExecutorService, int, int)} + * <li> {@link #processPartition(ExecutorService, int, int)} will make RPC calls to multiple tserver to remotely execute + * <li> {@link #processFiles(FileSystemResolver, Map, BlockCache, BlockCache, ExecutorService)} + * </ol> + */ +public class Gatherer { + + private static final Logger log = LoggerFactory.getLogger(Gatherer.class); + + private ClientContext ctx; + private String tableId; + private SummarizerFactory factory; + private Text startRow = null; + private Text endRow = null; + private Range clipRange; + private Predicate<SummarizerConfiguration> summarySelector; + + private TSummaryRequest request; + + private String summarizerPattern; + + private Set<SummarizerConfiguration> summaries; + + public Gatherer(ClientContext context, TSummaryRequest request, AccumuloConfiguration tableConfig) { + this.ctx = context; + this.tableId = request.tableId; + this.startRow = ByteBufferUtil.toText(request.bounds.startRow); + this.endRow = ByteBufferUtil.toText(request.bounds.endRow); + this.clipRange = new Range(startRow, false, endRow, true); + this.summaries = request.getSummarizers().stream().map(SummarizerConfigurationUtil::fromThrift).collect(Collectors.toSet()); + this.request = request; + + this.summarizerPattern = request.getSummarizerPattern(); + + if (summarizerPattern != null) { + Pattern pattern = Pattern.compile(summarizerPattern); + // The way conf is converted to string below is documented in the API, so consider this when making changes! + summarySelector = conf -> pattern.matcher(conf.getClassName() + " " + new TreeMap<>(conf.getOptions())).matches(); + if (!summaries.isEmpty()) { + summarySelector = summarySelector.or(conf -> summaries.contains(conf)); + } + } else if (!summaries.isEmpty()) { + summarySelector = conf -> summaries.contains(conf); + } else { + summarySelector = conf -> true; + } + + this.factory = new SummarizerFactory(tableConfig); + } + + private TSummaryRequest getRequest() { + return request; + } + + /** + * @param fileSelector + * only returns files that match this predicate + * @return A map of the form : {@code map<tserver location, map<path, list<range>>} . The ranges associated with a file represent the tablets that use the + * file. + */ + private Map<String,Map<String,List<TRowRange>>> getFilesGroupedByLocation(Predicate<String> fileSelector) throws TableNotFoundException, AccumuloException, + AccumuloSecurityException { + + Iterable<TabletMetadata> tmi = MetadataScanner.builder().from(ctx).overUserTableId(tableId, startRow, endRow).fetchFiles().fetchLocation().fetchLast() + .fetchPrev().build(); + + // get a subset of files + Map<String,List<TabletMetadata>> files = new HashMap<>(); + for (TabletMetadata tm : tmi) { + for (String file : tm.getFiles()) { + if (fileSelector.test(file)) { + // TODO push this filtering to server side and possibly use batch scanner + files.computeIfAbsent(file, s -> new ArrayList<>()).add(tm); + } + } + } + + // group by location, then file + + Map<String,Map<String,List<TRowRange>>> locations = new HashMap<>(); + + List<String> tservers = null; + + for (Entry<String,List<TabletMetadata>> entry : files.entrySet()) { + + String location = entry.getValue().stream().filter(tm -> tm.getLocation() != null) // filter tablets w/o a location + .map(tm -> tm.getLocation().getHostAndPort().toString()) // convert to host:port strings + .min(String::compareTo) // find minimum host:port + .orElse(entry.getValue().stream().filter(tm -> tm.getLast() != null) // if no locations, then look at last locations + .map(tm -> tm.getLast().getHostAndPort().toString()) // convert to host:port strings + .min(String::compareTo).orElse(null)); // find minimum last location or return null + + if (location == null) { + if (tservers == null) { + tservers = ctx.getConnector().instanceOperations().getTabletServers(); + Collections.sort(tservers); + } + + // When no location, the approach below will consistently choose the same tserver for the same file (as long as the set of tservers is stable). + int idx = Math.abs(Hashing.murmur3_32().hashString(entry.getKey()).asInt()) % tservers.size(); + location = tservers.get(idx); + } + + List<Range> merged = Range.mergeOverlapping(Lists.transform(entry.getValue(), tm -> tm.getExtent().toDataRange())); // merge contiguous ranges + List<TRowRange> ranges = merged.stream().map(r -> toClippedExtent(r).toThrift()).collect(Collectors.toList()); // clip ranges to queried range + + locations.computeIfAbsent(location, s -> new HashMap<>()).put(entry.getKey(), ranges); + } + + return locations; + } + + private <K,V> Iterable<Map<K,V>> partition(Map<K,V> map, int max) { + + if (map.size() < max) { + return Collections.singletonList(map); + } + + return new Iterable<Map<K,V>>() { + @Override + public Iterator<Map<K,V>> iterator() { + Iterator<Entry<K,V>> esi = map.entrySet().iterator(); + + return new Iterator<Map<K,V>>() { + @Override + public boolean hasNext() { + return esi.hasNext(); + } + + @Override + public Map<K,V> next() { + Map<K,V> workingMap = new HashMap<>(max); + while (esi.hasNext() && workingMap.size() < max) { + Entry<K,V> entry = esi.next(); + workingMap.put(entry.getKey(), entry.getValue()); + } + return workingMap; + } + }; + } + }; + } + + private static class ProcessedFiles { + final SummaryCollection summaries; + final Set<String> failedFiles; + + public ProcessedFiles() { + this.summaries = new SummaryCollection(); + this.failedFiles = new HashSet<>(); + } + + public ProcessedFiles(SummaryCollection summaries, SummarizerFactory factory) { + this(); + this.summaries.merge(summaries, factory); + } + + static ProcessedFiles merge(ProcessedFiles pf1, ProcessedFiles pf2, SummarizerFactory factory) { + ProcessedFiles ret = new ProcessedFiles(); + ret.failedFiles.addAll(pf1.failedFiles); + ret.failedFiles.addAll(pf2.failedFiles); + ret.summaries.merge(pf1.summaries, factory); + ret.summaries.merge(pf2.summaries, factory); + return ret; + } + } + + private class FilesProcessor implements Supplier<ProcessedFiles> { + + HostAndPort location; + Map<String,List<TRowRange>> allFiles; + private TInfo tinfo; + private AtomicBoolean cancelFlag; + + public FilesProcessor(TInfo tinfo, HostAndPort location, Map<String,List<TRowRange>> allFiles, AtomicBoolean cancelFlag) { + this.location = location; + this.allFiles = allFiles; + this.tinfo = tinfo; + this.cancelFlag = cancelFlag; + } + + @Override + public ProcessedFiles get() { + ProcessedFiles pfiles = new ProcessedFiles(); + + Client client = null; + try { + client = ThriftUtil.getTServerClient(location, ctx); + // partition files into smaller chunks so that not too many are sent to a tserver at once + for (Map<String,List<TRowRange>> files : partition(allFiles, 500)) { + if (pfiles.failedFiles.size() > 0) { + // there was a previous failure on this tserver, so just fail the rest of the files + pfiles.failedFiles.addAll(files.keySet()); + continue; + } + + try { + TSummaries tSums = client.startGetSummariesFromFiles(tinfo, ctx.rpcCreds(), getRequest(), files); + while (!tSums.finished && !cancelFlag.get()) { + tSums = client.contiuneGetSummaries(tinfo, tSums.sessionId); + } + + pfiles.summaries.merge(new SummaryCollection(tSums), factory); + } catch (TApplicationException tae) { + throw new RuntimeException(tae); + } catch (TTransportException e) { + pfiles.failedFiles.addAll(files.keySet()); + continue; + } catch (TException e) { + throw new RuntimeException(e); + } + + } + } catch (TTransportException e1) { + pfiles.failedFiles.addAll(allFiles.keySet()); + } finally { + ThriftUtil.returnClient(client); + } + + if (cancelFlag.get()) { + throw new RuntimeException("Operation canceled"); + } + + return pfiles; + } + } + + private class PartitionFuture implements Future<SummaryCollection> { + + private CompletableFuture<ProcessedFiles> future; + private int modulus; + private int remainder; + private ExecutorService execSrv; + private TInfo tinfo; + private AtomicBoolean cancelFlag = new AtomicBoolean(false); + + PartitionFuture(TInfo tinfo, ExecutorService execSrv, int modulus, int remainder) { + this.tinfo = tinfo; + this.execSrv = execSrv; + this.modulus = modulus; + this.remainder = remainder; + } + + private synchronized void initiateProcessing(ProcessedFiles previousWork) { + try { + Predicate<String> fileSelector = file -> Math.abs(Hashing.murmur3_32().hashString(file).asInt()) % modulus == remainder; + if (previousWork != null) { + fileSelector = fileSelector.and(file -> previousWork.failedFiles.contains(file)); + } + Map<String,Map<String,List<TRowRange>>> filesGBL; + filesGBL = getFilesGroupedByLocation(fileSelector); + + List<CompletableFuture<ProcessedFiles>> futures = new ArrayList<>(); + if (previousWork != null) { + futures.add(CompletableFuture.completedFuture(new ProcessedFiles(previousWork.summaries, factory))); + } + + for (Entry<String,Map<String,List<TRowRange>>> entry : filesGBL.entrySet()) { + HostAndPort location = HostAndPort.fromString(entry.getKey()); + Map<String,List<TRowRange>> allFiles = entry.getValue(); + + futures.add(CompletableFuture.supplyAsync(new FilesProcessor(tinfo, location, allFiles, cancelFlag), execSrv)); + } + + future = CompletableFutureUtil.merge(futures, (pf1, pf2) -> ProcessedFiles.merge(pf1, pf2, factory), ProcessedFiles::new); + + // when all processing is done, check for failed files... and if found starting processing again + future.thenRun(() -> updateFuture()); + } catch (Exception e) { + future = CompletableFuture.completedFuture(new ProcessedFiles()); + // force future to have this exception + future.obtrudeException(e); + } + } + + private ProcessedFiles _get() { + try { + return future.get(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException(e); + } catch (ExecutionException e) { + throw new RuntimeException(e); + } + } + + private synchronized CompletableFuture<ProcessedFiles> updateFuture() { + if (future.isDone()) { + if (!future.isCancelled() && !future.isCompletedExceptionally()) { + ProcessedFiles pf = _get(); + if (pf.failedFiles.size() > 0) { + initiateProcessing(pf); + } + } + } + + return future; + } + + synchronized void initiateProcessing() { + Preconditions.checkState(future == null); + initiateProcessing(null); + } + + @Override + public synchronized boolean cancel(boolean mayInterruptIfRunning) { + boolean canceled = future.cancel(mayInterruptIfRunning); + if (canceled) { + cancelFlag.set(true); + } + return canceled; + } + + @Override + public synchronized boolean isCancelled() { + return future.isCancelled(); + } + + @Override + public synchronized boolean isDone() { + updateFuture(); + if (future.isDone()) { + if (future.isCancelled() || future.isCompletedExceptionally()) { + return true; + } + + ProcessedFiles pf = _get(); + if (pf.failedFiles.size() == 0) { + return true; + } else { + updateFuture(); + } + } + + return false; + } + + @Override + public SummaryCollection get() throws InterruptedException, ExecutionException { + CompletableFuture<ProcessedFiles> futureRef = updateFuture(); + ProcessedFiles processedFiles = futureRef.get(); + while (processedFiles.failedFiles.size() > 0) { + futureRef = updateFuture(); + processedFiles = futureRef.get(); + } + return processedFiles.summaries; + } + + @Override + public SummaryCollection get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { + long nanosLeft = unit.toNanos(timeout); + long t1, t2; + CompletableFuture<ProcessedFiles> futureRef = updateFuture(); + t1 = System.nanoTime(); + ProcessedFiles processedFiles = futureRef.get(Long.max(1, nanosLeft), TimeUnit.NANOSECONDS); + t2 = System.nanoTime(); + nanosLeft -= (t2 - t1); + while (processedFiles.failedFiles.size() > 0) { + futureRef = updateFuture(); + t1 = System.nanoTime(); + processedFiles = futureRef.get(Long.max(1, nanosLeft), TimeUnit.NANOSECONDS); + t2 = System.nanoTime(); + nanosLeft -= (t2 - t1); + } + return processedFiles.summaries; + } + + } + + /** + * This methods reads a subset of file paths into memory and groups them by location. Then it request sumaries for files from each location/tablet server. + */ + public Future<SummaryCollection> processPartition(ExecutorService execSrv, int modulus, int remainder) { + PartitionFuture future = new PartitionFuture(Tracer.traceInfo(), execSrv, modulus, remainder); + future.initiateProcessing(); + return future; + } + + public static interface FileSystemResolver { + FileSystem get(Path file); + } + + /** + * This method will read summaries from a set of files. + */ + public Future<SummaryCollection> processFiles(FileSystemResolver volMgr, Map<String,List<TRowRange>> files, BlockCache summaryCache, BlockCache indexCache, + ExecutorService srp) { + List<CompletableFuture<SummaryCollection>> futures = new ArrayList<>(); + for (Entry<String,List<TRowRange>> entry : files.entrySet()) { + futures.add(CompletableFuture.supplyAsync(() -> { + List<RowRange> rrl = Lists.transform(entry.getValue(), RowRange::new); + return getSummaries(volMgr, entry.getKey(), rrl, summaryCache, indexCache); + }, srp)); + } + + return CompletableFutureUtil.merge(futures, (sc1, sc2) -> SummaryCollection.merge(sc1, sc2, factory), SummaryCollection::new); + } + + private int countFiles() throws TableNotFoundException, AccumuloException, AccumuloSecurityException { + // TODO use a batch scanner + iterator to parallelize counting files + Iterable<TabletMetadata> tmi = MetadataScanner.builder().from(ctx).overUserTableId(tableId, startRow, endRow).fetchFiles().fetchPrev().build(); + return (int) StreamSupport.stream(tmi.spliterator(), false).mapToInt(tm -> tm.getFiles().size()).sum(); + } + + private class GatherRequest implements Supplier<SummaryCollection> { + + private int remainder; + private int modulus; + private TInfo tinfo; + private AtomicBoolean cancelFlag; + + GatherRequest(TInfo tinfo, int remainder, int modulus, AtomicBoolean cancelFlag) { + this.remainder = remainder; + this.modulus = modulus; + this.tinfo = tinfo; + this.cancelFlag = cancelFlag; + } + + @Override + public SummaryCollection get() { + TSummaryRequest req = getRequest(); + + TSummaries tSums; + try { + tSums = ServerClient.execute(ctx, new TabletClientService.Client.Factory(), client -> { + TSummaries tsr = client.startGetSummariesForPartition(tinfo, ctx.rpcCreds(), req, modulus, remainder); + while (!tsr.finished && !cancelFlag.get()) { + tsr = client.contiuneGetSummaries(tinfo, tsr.sessionId); + } + return tsr; + }); + } catch (AccumuloException | AccumuloSecurityException e) { + throw new RuntimeException(e); + } + + if (cancelFlag.get()) { + throw new RuntimeException("Operation canceled"); + } + + return new SummaryCollection(tSums); + } + } + + public Future<SummaryCollection> gather(ExecutorService es) { + int numFiles; + try { + numFiles = countFiles(); + } catch (TableNotFoundException | AccumuloException | AccumuloSecurityException e) { + throw new RuntimeException(e); + } + + log.debug("Gathering summaries from {} files", numFiles); + + if (numFiles == 0) { + return CompletableFuture.completedFuture(new SummaryCollection()); + } + + // have each tablet server process ~100K files + int numRequest = Math.max(numFiles / 100_000, 1); + + List<CompletableFuture<SummaryCollection>> futures = new ArrayList<>(); + + AtomicBoolean cancelFlag = new AtomicBoolean(false); + + TInfo tinfo = Tracer.traceInfo(); + for (int i = 0; i < numRequest; i++) { + futures.add(CompletableFuture.supplyAsync(new GatherRequest(tinfo, i, numRequest, cancelFlag), es)); + } + + Future<SummaryCollection> future = CompletableFutureUtil.merge(futures, (sc1, sc2) -> SummaryCollection.merge(sc1, sc2, factory), SummaryCollection::new); + return new CancelFlagFuture<>(future, cancelFlag); + } + + private static Text removeTrailingZeroFromRow(Key k) { + if (k != null) { + Text t = new Text(); + ByteSequence row = k.getRowData(); + Preconditions.checkArgument(row.length() >= 1 && row.byteAt(row.length() - 1) == 0); + t.set(row.getBackingArray(), row.offset(), row.length() - 1); + return t; + } else { + return null; + } + } + + private RowRange toClippedExtent(Range r) { + r = clipRange.clip(r); + + Text startRow = removeTrailingZeroFromRow(r.getStartKey()); + Text endRow = removeTrailingZeroFromRow(r.getEndKey()); + + return new RowRange(startRow, endRow); + } + + public static class RowRange { + private Text startRow; + private Text endRow; + + public RowRange(KeyExtent ke) { + this.startRow = ke.getPrevEndRow(); + this.endRow = ke.getEndRow(); + } + + public RowRange(TRowRange trr) { + this.startRow = ByteBufferUtil.toText(trr.startRow); + this.endRow = ByteBufferUtil.toText(trr.endRow); + } + + public RowRange(Text startRow, Text endRow) { + this.startRow = startRow; + this.endRow = endRow; + } + + public Range toRange() { + return new Range(startRow, false, endRow, true); + } + + public TRowRange toThrift() { + return new TRowRange(TextUtil.getByteBuffer(startRow), TextUtil.getByteBuffer(endRow)); + } + + public Text getStartRow() { + return startRow; + } + + public Text getEndRow() { + return endRow; + } + + public String toString() { + return startRow + " " + endRow; + } + } + + private SummaryCollection getSummaries(FileSystemResolver volMgr, String file, List<RowRange> ranges, BlockCache summaryCache, BlockCache indexCache) { + Path path = new Path(file); + Configuration conf = CachedConfiguration.getInstance(); + return SummaryReader.load(volMgr.get(path), conf, ctx.getConfiguration(), factory, path, summarySelector, summaryCache, indexCache).getSummaries(ranges); + } +} http://git-wip-us.apache.org/repos/asf/accumulo/blob/94cdcc4d/core/src/main/java/org/apache/accumulo/core/summary/SummarizerConfigurationUtil.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/summary/SummarizerConfigurationUtil.java b/core/src/main/java/org/apache/accumulo/core/summary/SummarizerConfigurationUtil.java new file mode 100644 index 0000000..a67b8c2 --- /dev/null +++ b/core/src/main/java/org/apache/accumulo/core/summary/SummarizerConfigurationUtil.java @@ -0,0 +1,128 @@ +/* + * 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.summary; + +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.Set; +import java.util.SortedMap; +import java.util.TreeMap; + +import org.apache.accumulo.core.client.summary.SummarizerConfiguration; +import org.apache.accumulo.core.client.summary.SummarizerConfiguration.Builder; +import org.apache.accumulo.core.conf.AccumuloConfiguration; +import org.apache.accumulo.core.conf.Property; +import org.apache.accumulo.core.data.thrift.TSummarizerConfiguration; + +public class SummarizerConfigurationUtil { + + public static Map<String,String> toTablePropertiesMap(List<SummarizerConfiguration> summarizers) { + if (summarizers.size() == 0) { + return Collections.emptyMap(); + } + + Map<String,String> props = new HashMap<>(); + + for (SummarizerConfiguration sconf : summarizers) { + String cid = sconf.getPropertyId(); + String prefix = Property.TABLE_SUMMARIZER_PREFIX.getKey() + cid; + + if (props.containsKey(prefix)) { + throw new IllegalArgumentException("Duplicate summarizer config id : " + cid); + } + + props.put(prefix, sconf.getClassName()); + Set<Entry<String,String>> es = sconf.getOptions().entrySet(); + StringBuilder sb = new StringBuilder(prefix + ".opt."); + int resetLen = sb.length(); + for (Entry<String,String> entry : es) { + sb.append(entry.getKey()); + props.put(sb.toString(), entry.getValue()); + sb.setLength(resetLen); + } + } + + return props; + } + + public static List<SummarizerConfiguration> getSummarizerConfigs(Iterable<Entry<String,String>> props) { + TreeMap<String,String> filteredMap = new TreeMap<>(); + for (Entry<String,String> entry : props) { + if (entry.getKey().startsWith(Property.TABLE_SUMMARIZER_PREFIX.getKey())) { + filteredMap.put(entry.getKey(), entry.getValue()); + } + } + + return getSummarizerConfigsFiltered(filteredMap); + } + + public static List<SummarizerConfiguration> getSummarizerConfigs(AccumuloConfiguration aconf) { + Map<String,String> sprops = aconf.getAllPropertiesWithPrefix(Property.TABLE_SUMMARIZER_PREFIX); + return getSummarizerConfigsFiltered(new TreeMap<>(sprops)); + } + + private static List<SummarizerConfiguration> getSummarizerConfigsFiltered(SortedMap<String,String> sprops) { + if (sprops.size() == 0) { + return Collections.emptyList(); + } + + SummarizerConfiguration.Builder builder = null; + + List<SummarizerConfiguration> configs = new ArrayList<>(); + + final int preLen = Property.TABLE_SUMMARIZER_PREFIX.getKey().length(); + for (Entry<String,String> entry : sprops.entrySet()) { + String k = entry.getKey().substring(preLen); + + String[] tokens = k.split("\\."); + + String id = tokens[0]; + if (tokens.length == 1) { + if (builder != null) { + configs.add(builder.build()); + } + + builder = SummarizerConfiguration.builder(entry.getValue()).setPropertyId(id); + + } else if (tokens.length == 3 || tokens[1].equals("opt")) { + builder.addOption(tokens[2], entry.getValue()); + } else { + throw new IllegalArgumentException("Unable to parse summarizer property : " + k); + } + } + + configs.add(builder.build()); + + return configs; + } + + public static TSummarizerConfiguration toThrift(SummarizerConfiguration sc) { + return new TSummarizerConfiguration(sc.getClassName(), sc.getOptions(), sc.getPropertyId()); + } + + public static SummarizerConfiguration fromThrift(TSummarizerConfiguration config) { + Builder builder = SummarizerConfiguration.builder(config.getClassname()); + builder.setPropertyId(config.getConfigId()); + builder.addOptions(config.getOptions()); + return builder.build(); + } +} http://git-wip-us.apache.org/repos/asf/accumulo/blob/94cdcc4d/core/src/main/java/org/apache/accumulo/core/summary/SummarizerFactory.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/summary/SummarizerFactory.java b/core/src/main/java/org/apache/accumulo/core/summary/SummarizerFactory.java new file mode 100644 index 0000000..bba41b5 --- /dev/null +++ b/core/src/main/java/org/apache/accumulo/core/summary/SummarizerFactory.java @@ -0,0 +1,63 @@ +/* + * 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.summary; + +import java.io.IOException; + +import org.apache.accumulo.core.client.summary.Summarizer; +import org.apache.accumulo.core.client.summary.SummarizerConfiguration; +import org.apache.accumulo.core.conf.AccumuloConfiguration; +import org.apache.accumulo.core.conf.Property; +import org.apache.accumulo.start.classloader.vfs.AccumuloVFSClassLoader; + +public class SummarizerFactory { + private ClassLoader classloader; + private String context; + + public SummarizerFactory() { + this.classloader = SummarizerFactory.class.getClassLoader(); + } + + public SummarizerFactory(ClassLoader classloader) { + this.classloader = classloader; + } + + public SummarizerFactory(AccumuloConfiguration tableConfig) { + this.context = tableConfig.get(Property.TABLE_CLASSPATH); + } + + private Summarizer newSummarizer(String classname) throws ClassNotFoundException, IOException, InstantiationException, IllegalAccessException { + if (classloader != null) { + return classloader.loadClass(classname).asSubclass(Summarizer.class).newInstance(); + } else { + if (context != null && !context.equals("")) + return AccumuloVFSClassLoader.getContextManager().loadClass(context, classname, Summarizer.class).newInstance(); + else + return AccumuloVFSClassLoader.loadClass(classname, Summarizer.class).newInstance(); + } + } + + public Summarizer getSummarizer(SummarizerConfiguration conf) { + try { + Summarizer summarizer = newSummarizer(conf.getClassName()); + return summarizer; + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | IOException e) { + throw new RuntimeException(e); + } + } +}