From 739c21d38ff9b1295adfd77a95ea0b66ae9feda2 Mon Sep 17 00:00:00 2001 From: Alex Newman Date: Wed, 18 Apr 2012 11:18:51 -0700 Subject: [PATCH 1/2] HBASE-2600. Conflicts: src/main/java/org/apache/hadoop/hbase/client/HTable.java --- .../hbase/security/access/AccessController.java | 8 - .../java/org/apache/hadoop/hbase/HConstants.java | 14 +- .../java/org/apache/hadoop/hbase/HRegionInfo.java | 452 +-- .../java/org/apache/hadoop/hbase/HServerLoad.java | 22 - .../org/apache/hadoop/hbase/HTableDescriptor.java | 68 +- .../java/org/apache/hadoop/hbase/KeyValue.java | 6 +- .../apache/hadoop/hbase/catalog/MetaMigratev2.java | 324 +++ .../apache/hadoop/hbase/catalog/MetaReader.java | 31 +- .../org/apache/hadoop/hbase/client/HBaseAdmin.java | 4 +- .../hadoop/hbase/client/HConnectionManager.java | 128 +- .../org/apache/hadoop/hbase/client/HTable.java | 21 - .../hadoop/hbase/client/HTableInterface.java | 17 - .../org/apache/hadoop/hbase/client/HTablePool.java | 5 - .../apache/hadoop/hbase/client/MetaScanner.java | 52 +- .../hbase/coprocessor/BaseRegionObserver.java | 12 - .../hadoop/hbase/coprocessor/CoprocessorHost.java | 5 - .../hadoop/hbase/coprocessor/RegionObserver.java | 34 - .../apache/hadoop/hbase/ipc/HRegionInterface.java | 14 - .../org/apache/hadoop/hbase/master/HMaster.java | 32 +- .../master/handler/ServerShutdownHandler.java | 2 +- .../hadoop/hbase/migration/HRegionInfo090x2.java | 763 ++++++ .../regionserver/GetClosestRowBeforeTracker.java | 242 -- .../apache/hadoop/hbase/regionserver/HRegion.java | 57 +- .../hadoop/hbase/regionserver/HRegionServer.java | 16 - .../apache/hadoop/hbase/regionserver/MemStore.java | 105 - .../hbase/regionserver/RegionCoprocessorHost.java | 54 - .../apache/hadoop/hbase/regionserver/Store.java | 126 - .../hbase/rest/StorageClusterStatusResource.java | 6 +- .../hadoop/hbase/rest/client/RemoteHTable.java | 4 - .../rest/model/StorageClusterStatusModel.java | 177 +- .../hadoop/hbase/rest/model/TableRegionModel.java | 29 +- .../generated/StorageClusterStatusMessage.java | 422 +-- .../hadoop/hbase/thrift/ThriftServerRunner.java | 63 +- .../hbase/thrift/generated/AlreadyExists.java | 10 +- .../hbase/thrift/generated/BatchMutation.java | 19 +- .../hbase/thrift/generated/ColumnDescriptor.java | 50 +- .../hadoop/hbase/thrift/generated/Hbase.java | 2887 ++++++++++---------- .../hadoop/hbase/thrift/generated/IOError.java | 10 +- .../hbase/thrift/generated/IllegalArgument.java | 10 +- .../hadoop/hbase/thrift/generated/Mutation.java | 25 +- .../hadoop/hbase/thrift/generated/TCell.java | 15 +- .../hadoop/hbase/thrift/generated/TRegionInfo.java | 40 +- .../hadoop/hbase/thrift/generated/TRowResult.java | 19 +- .../hadoop/hbase/thrift/generated/TScan.java | 39 +- .../java/org/apache/hadoop/hbase/util/FSUtils.java | 2 +- .../org/apache/hadoop/hbase/util/RetryCounter.java | 5 +- .../org/apache/hadoop/hbase/util/Writables.java | 12 + .../hbase/zookeeper/RecoverableZooKeeper.java | 174 +- .../org/apache/hadoop/hbase/rest/XMLSchema.xsd | 7 - .../protobuf/StorageClusterStatusMessage.proto | 7 - .../org/apache/hadoop/hbase/thrift/Hbase.thrift | 16 - src/test/data/generate-hbase-2600-root-in-tmp.sh | 14 + src/test/data/hbase-2600-root.dir.tgz | Bin 0 -> 260764 bytes .../java/org/apache/hadoop/hbase/TestKeyValue.java | 10 +- .../hadoop/hbase/catalog/TestMetaUpdate.java | 371 +++ .../hadoop/hbase/client/TestFromClientSide.java | 50 - .../hbase/client/TestMetaMigrationRemovingHTD.java | 363 --- .../hbase/coprocessor/SimpleRegionObserver.java | 28 - .../hadoop/hbase/master/MockRegionServer.java | 7 - .../hadoop/hbase/migration/TestMigration.java | 78 + .../hbase/migration/TestMigrationFrom090To092.java | 62 - .../regionserver/TestGetClosestAtOrBefore.java | 348 --- .../hadoop/hbase/regionserver/TestHRegionInfo.java | 22 +- .../hadoop/hbase/regionserver/TestMinVersions.java | 42 - .../hadoop/hbase/rest/TestStatusResource.java | 17 +- .../rest/model/TestStorageClusterStatusModel.java | 40 +- .../hbase/rest/model/TestTableRegionModel.java | 28 +- 67 files changed, 3941 insertions(+), 4201 deletions(-) create mode 100644 src/main/java/org/apache/hadoop/hbase/catalog/MetaMigratev2.java create mode 100644 src/main/java/org/apache/hadoop/hbase/migration/HRegionInfo090x2.java delete mode 100644 src/main/java/org/apache/hadoop/hbase/regionserver/GetClosestRowBeforeTracker.java create mode 100644 src/test/data/generate-hbase-2600-root-in-tmp.sh create mode 100644 src/test/data/hbase-2600-root.dir.tgz create mode 100644 src/test/java/org/apache/hadoop/hbase/catalog/TestMetaUpdate.java delete mode 100644 src/test/java/org/apache/hadoop/hbase/client/TestMetaMigrationRemovingHTD.java create mode 100644 src/test/java/org/apache/hadoop/hbase/migration/TestMigration.java delete mode 100644 src/test/java/org/apache/hadoop/hbase/migration/TestMigrationFrom090To092.java delete mode 100644 src/test/java/org/apache/hadoop/hbase/regionserver/TestGetClosestAtOrBefore.java diff --git security/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java security/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java index b4fa398..55eb44f 100644 --- security/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java +++ security/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java @@ -673,14 +673,6 @@ public class AccessController extends BaseRegionObserver } @Override - public void preGetClosestRowBefore(final ObserverContext c, - final byte [] row, final byte [] family, final Result result) - throws IOException { - requirePermission(TablePermission.Action.READ, c.getEnvironment(), - (family != null ? Lists.newArrayList(family) : null)); - } - - @Override public void preGet(final ObserverContext c, final Get get, final List result) throws IOException { /* diff --git src/main/java/org/apache/hadoop/hbase/HConstants.java src/main/java/org/apache/hadoop/hbase/HConstants.java index a9d80a0..7164f50 100644 --- src/main/java/org/apache/hadoop/hbase/HConstants.java +++ src/main/java/org/apache/hadoop/hbase/HConstants.java @@ -48,7 +48,10 @@ public final class HConstants { /** long constant for zero */ public static final Long ZERO_L = Long.valueOf(0L); + public static final String NINES = "99999999999999"; + + @Deprecated public static final String ZEROES = "00000000000000"; // For migration @@ -62,9 +65,11 @@ public final class HConstants { * Version 5 changes versions in catalog table regions. * Version 6 enables blockcaching on catalog tables. * Version 7 introduces hfile -- hbase 0.19 to 0.20.. + * version 8 changed the metaFormat */ // public static final String FILE_SYSTEM_VERSION = "6"; - public static final String FILE_SYSTEM_VERSION = "7"; + public static final String FILE_SYSTEM_VERSION = "8"; + public static final int FILE_SYSTEM_VERSION_INT = Integer.parseInt(FILE_SYSTEM_VERSION); // Configuration parameters @@ -281,7 +286,7 @@ public final class HConstants { // Always store the location of the root table's HRegion. // This HRegion is never split. - // region name = table + startkey + regionid. This is the row key. + // region name = table + endkey + regionid. This is the row key. // each row in the root and meta tables describes exactly 1 region // Do we ever need to know all the information that we are storing? @@ -304,9 +309,6 @@ public final class HConstants { /** The META table's name. */ public static final byte [] META_TABLE_NAME = Bytes.toBytes(".META."); - /** delimiter used between portions of a region name */ - public static final int META_ROW_DELIMITER = ','; - /** The catalog family as a string*/ public static final String CATALOG_FAMILY_STR = "info"; @@ -347,6 +349,8 @@ public final class HConstants { * meta is up-to-date. */ public static final short META_VERSION = 0; + public static final short META_VERSION2 = 1; + // Other constants diff --git src/main/java/org/apache/hadoop/hbase/HRegionInfo.java src/main/java/org/apache/hadoop/hbase/HRegionInfo.java index 8d83ff3..561460c 100644 --- src/main/java/org/apache/hadoop/hbase/HRegionInfo.java +++ src/main/java/org/apache/hadoop/hbase/HRegionInfo.java @@ -23,6 +23,7 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.EOFException; import java.io.IOException; +import java.nio.ByteBuffer; import java.util.Arrays; import org.apache.commons.logging.Log; @@ -33,7 +34,10 @@ import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.hbase.KeyValue.KVComparator; + + import org.apache.hadoop.hbase.migration.HRegionInfo090x; +import org.apache.hadoop.hbase.migration.HRegionInfo090x2; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.FSTableDescriptors; import org.apache.hadoop.hbase.util.JenkinsHash; @@ -52,7 +56,8 @@ public class HRegionInfo extends VersionedWritable implements WritableComparable { // VERSION == 0 when HRegionInfo had an HTableDescriptor inside it. public static final byte VERSION_PRE_092 = 0; - public static final byte VERSION = 1; + public static final byte VERSION = 2; + private static final Log LOG = LogFactory.getLog(HRegionInfo.class); /** @@ -61,13 +66,15 @@ implements WritableComparable { * in the filesystem. * * New region name format: - * <tablename>,,<startkey>,<regionIdTimestamp>.<encodedName>. + * <tablename><is_end_of_table_marker>,,<endkey>,<regionIdTimestamp>.<encodedName>. * where, + * <end_of_table_marker> HRegionInfo.NOT_END_OF_TABLE + * || HRegionInfo.END_OF_TABLE * <encodedName> is a hex version of the MD5 hash of - * <tablename>,<startkey>,<regionIdTimestamp> + * <tablename>,&<startkey>,<regionIdTimestamp> * * The old region name format: - * <tablename>,<startkey>,<regionIdTimestamp> + * <tablename>,<is_end_of_table_marker><endkey>,<regionIdTimestamp> * For region names in the old format, the encoded name is a 32-bit * JenkinsHash integer value (in its decimal notation, string form). *

@@ -83,6 +90,14 @@ implements WritableComparable { */ private static final int ENC_SEPARATOR = '.'; public static final int MD5_HEX_LENGTH = 32; + // It should say, the tablename encoded in the region ends with !, + // but the last region's tablename ends with " + public static final int NOT_END_OF_TABLE = 33; // The ascii for ! + + // This must come after NOT_END_OF_TABLE to work + public static final int END_OF_TABLE = NOT_END_OF_TABLE + 1; + public static final String ROOT_REGION_ENCODING = "1756551925"; + public static final String META_REGION_ENCODING = "845716343"; /** * Does region name contain its encoded name? @@ -108,7 +123,7 @@ implements WritableComparable { String encodedName; if (hasEncodedName(regionName)) { // region is in new format: - // ,,/encodedName/ + // ,,/encodedName/ encodedName = Bytes.toString(regionName, regionName.length - MD5_HEX_LENGTH - 1, MD5_HEX_LENGTH); @@ -125,15 +140,19 @@ implements WritableComparable { /** * Use logging. * @param encodedRegionName The encoded regionname. - * @return -ROOT- if passed 70236052 or - * .META. if passed 1028785192 else returns + * @return -ROOT- if passed + * HRegionInfo.ROOT_REGION_ENCODING or + * .META. if passed + * HRegionInfo.META_REGION_ENCODING else returns * encodedRegionName */ public static String prettyPrint(final String encodedRegionName) { - if (encodedRegionName.equals("70236052")) { + if (encodedRegionName.equals(ROOT_REGION_ENCODING)) { return encodedRegionName + "/-ROOT-"; - } else if (encodedRegionName.equals("1028785192")) { - return encodedRegionName + "/.META."; + } else { + if (encodedRegionName.equals(META_REGION_ENCODING)) { + return encodedRegionName + "/.META."; + } } return encodedRegionName; } @@ -143,11 +162,12 @@ implements WritableComparable { /** HRegionInfo for root region */ public static final HRegionInfo ROOT_REGIONINFO = - new HRegionInfo(0L, Bytes.toBytes("-ROOT-")); + new HRegionInfo(0L, HConstants.ROOT_TABLE_NAME); /** HRegionInfo for first meta region */ - public static final HRegionInfo FIRST_META_REGIONINFO = - new HRegionInfo(1L, Bytes.toBytes(".META.")); + public static final HRegionInfo + FIRST_META_REGIONINFO = + new HRegionInfo(1L, HConstants.META_TABLE_NAME); private byte [] endKey = HConstants.EMPTY_BYTE_ARRAY; // This flag is in the parent of a split while the parent is still referenced @@ -217,6 +237,32 @@ implements WritableComparable { this.tableName = other.getTableDesc().getName(); } + + /** + * Used only for migration + * @param other HRegionInfoForMigration + */ + public HRegionInfo(HRegionInfo090x2 other) { + super(); + this.endKey = other.getEndKey(); + this.offLine = other.isOffline(); + this.regionId = other.getRegionId(); + this.split = other.isSplit(); + this.startKey = other.getStartKey(); + this.hashCode = other.hashCode(); + this.encodedName = other.getEncodedName(); + this.tableName = other.getTableName(); + if (Arrays.equals(this.tableName, HConstants.META_TABLE_NAME) || + Arrays.equals(this.tableName, HConstants.ROOT_TABLE_NAME)) { + this.regionName = createRegionName(tableName, startKey, endKey, regionId, false); + } else { + this.regionName = createRegionName(tableName, startKey, endKey, regionId, true); + } + this.regionNameStr = Bytes.toStringBinary(this.regionName); + + } + + public HRegionInfo(final byte[] tableName) { this(tableName, null, null); } @@ -276,7 +322,11 @@ implements WritableComparable { this.offLine = false; this.regionId = regionid; - this.regionName = createRegionName(this.tableName, startKey, regionId, true); + this.regionName = createRegionName(this.tableName, + startKey, + endKey, + regionId, + true); this.regionNameStr = Bytes.toStringBinary(this.regionName); this.split = split; @@ -287,7 +337,19 @@ implements WritableComparable { setHashCode(); } - /** + private byte[] createRegionName(byte[] tableName, + byte[] startKey, + byte[] endKey, + long regionId, + boolean newFormat) { + return createRegionName(tableName, + startKey, + endKey, + Long.toString(regionId), + newFormat); + } + + /** * Costruct a copy of another HRegionInfo * * @param other @@ -307,33 +369,28 @@ implements WritableComparable { } - /** - * Make a region name of passed parameters. - * @param tableName - * @param startKey Can be null - * @param regionid Region id (Usually timestamp from when region was created). - * @param newFormat should we create the region name in the new format - * (such that it contains its encoded name?). - * @return Region name made of passed tableName, startKey and id - */ - public static byte [] createRegionName(final byte [] tableName, - final byte [] startKey, final long regionid, boolean newFormat) { - return createRegionName(tableName, startKey, Long.toString(regionid), newFormat); - } - - /** - * Make a region name of passed parameters. - * @param tableName - * @param startKey Can be null - * @param id Region id (Usually timestamp from when region was created). - * @param newFormat should we create the region name in the new format - * (such that it contains its encoded name?). - * @return Region name made of passed tableName, startKey and id - */ - public static byte [] createRegionName(final byte [] tableName, - final byte [] startKey, final String id, boolean newFormat) { - return createRegionName(tableName, startKey, Bytes.toBytes(id), newFormat); - } + /** + * Make a region name of passed parameters. + * + * + * @param tableName + * @param endKey Can be null + * @param regionid Region id (Usually timestamp from when region was + * created). + * @param newFormat should we create the region name in the new format + * (such that it contains its encoded name?). + * @return Region name made of passed tableName, endKey and id + */ + public static byte[] createRegionName(final byte[] tableName, + final byte[] endKey, + final long regionid, + boolean newFormat) { + return createRegionName(tableName, + null, + endKey, + Long.toString(regionid), + newFormat); + } /** * Make a region name of passed parameters. @@ -344,48 +401,114 @@ implements WritableComparable { * (such that it contains its encoded name?). * @return Region name made of passed tableName, startKey and id */ - public static byte [] createRegionName(final byte [] tableName, - final byte [] startKey, final byte [] id, boolean newFormat) { - byte [] b = new byte [tableName.length + 2 + id.length + - (startKey == null? 0: startKey.length) + - (newFormat ? (MD5_HEX_LENGTH + 2) : 0)]; - - int offset = tableName.length; - System.arraycopy(tableName, 0, b, 0, offset); - b[offset++] = DELIMITER; - if (startKey != null && startKey.length > 0) { - System.arraycopy(startKey, 0, b, offset, startKey.length); - offset += startKey.length; + public static byte [] createRegionName(final byte[] tableName, + final byte[] startKey, + final byte[] endKey, + final String id, + boolean newFormat) { + return createRegionName(tableName, + startKey, + endKey, + Bytes.toBytes(id), + newFormat); + } + /** + * Make a region name of passed parameters. + * + * @param tableName + * @param startKey Can be null + * @param endKey Can be null + * @param id Region id (Usually timestamp from when region was + * created). + * @param newFormat should we create the region name in the new format + * (such that it contains its encoded name?). + * @return Region name made of passed tableName, endKey and id + */ + + public static byte[] createRegionName(final byte[] tableName, + final byte[] startKey, + final byte[] endKey, + final byte[] id, + boolean newFormat) { + // Allocate room for the tablename along with the end of table + // marker and the delimiter. + int allocation = tableName.length + 2; + + // If the endKey is null just allocate space for the delimiter, else + // allocate enough for the key and a delimiter + allocation += endKey == null ? 1 : endKey.length + 1; + allocation += id == null ? 0 : id.length; + + ByteBuffer byteArrayDataOutput = ByteBuffer.allocate(allocation); + byteArrayDataOutput.put(tableName); + + if (endKey == null || endKey.length <= 0) { + byteArrayDataOutput.put((byte) END_OF_TABLE); + byteArrayDataOutput.put((byte)DELIMITER); + } else { + byteArrayDataOutput.put((byte) NOT_END_OF_TABLE); + byteArrayDataOutput.put((byte)DELIMITER); + byteArrayDataOutput.put(endKey); + } + byteArrayDataOutput.put((byte)DELIMITER); + + if (id != null && id.length > 0) { + byteArrayDataOutput.put(id); + } + + // Add the encoding bit to the regionname if it is a new style region. + if (newFormat) { + return addEncoding(byteArrayDataOutput.array(), + tableName, + startKey, + id); + } else { + // Old style regions have no encoding so just return. + return byteArrayDataOutput.array(); + } } - b[offset++] = DELIMITER; - System.arraycopy(id, 0, b, offset, id.length); - offset += id.length; - - if (newFormat) { - // - // Encoded name should be built into the region name. - // - // Use the region name thus far (namely, ,,) - // to compute a MD5 hash to be used as the encoded name, and append - // it to the byte buffer. - // - String md5Hash = MD5Hash.getMD5AsHex(b, 0, offset); - byte [] md5HashBytes = Bytes.toBytes(md5Hash); - - if (md5HashBytes.length != MD5_HEX_LENGTH) { - LOG.error("MD5-hash length mismatch: Expected=" + MD5_HEX_LENGTH + - "; Got=" + md5HashBytes.length); - } - // now append the bytes '..' to the end - b[offset++] = ENC_SEPARATOR; - System.arraycopy(md5HashBytes, 0, b, offset, MD5_HEX_LENGTH); - offset += MD5_HEX_LENGTH; - b[offset++] = ENC_SEPARATOR; + /** + * Encoded name should be built into the region name. + * As not to change encodings between the pre-HBASE-2600 + * versions and the post versions + * We want to use the startkey as opposed to the endkey + * here so as not to change encodings. + * @param regionName The regionName without an encoding + * @param tableName The table name. + * @param startKey The startKey. + * @param id The region id + * @return The region with the encoding glued on. + */ + private static byte[] addEncoding(final byte[] regionName, + final byte[] tableName, + final byte[] startKey, + final byte[] id) { + + + byte [] oldRegionKey = Bytes.add(tableName, new byte[] {DELIMITER}); + if (startKey != null) { + oldRegionKey = Bytes.add(oldRegionKey, startKey, new byte[] {DELIMITER}); + } else { + oldRegionKey = Bytes.add(oldRegionKey, + HConstants.EMPTY_BYTE_ARRAY, + new byte[] {DELIMITER}); + } + oldRegionKey = Bytes.add(oldRegionKey, id); + + final byte[] md5HashBytes = MD5Hash.getMD5AsHex(oldRegionKey).getBytes(); + + if (md5HashBytes.length != MD5_HEX_LENGTH) { + LOG.error("MD5-hash length mismatch: Expected=" + MD5_HEX_LENGTH + + "; Got=" + md5HashBytes.length); + } + + byte[] encoding = Bytes.add(new byte[]{ENC_SEPARATOR}, + md5HashBytes, + new byte[]{ENC_SEPARATOR}); + return Bytes.add(regionName, encoding); } - - return b; - } + /** * Gets the table name from the specified region name. @@ -396,7 +519,8 @@ implements WritableComparable { int offset = -1; for (int i = 0; i < regionName.length; i++) { if (regionName[i] == DELIMITER) { - offset = i; + // We are off by one because we need to remove the end of region marker + offset = i - 1; break; } } @@ -405,47 +529,49 @@ implements WritableComparable { return tableName; } - /** - * Separate elements of a regionName. - * @param regionName - * @return Array of byte[] containing tableName, startKey and id - * @throws IOException - */ - public static byte [][] parseRegionName(final byte [] regionName) - throws IOException { - int offset = -1; - for (int i = 0; i < regionName.length; i++) { - if (regionName[i] == DELIMITER) { - offset = i; - break; - } - } - if(offset == -1) throw new IOException("Invalid regionName format"); - byte [] tableName = new byte[offset]; - System.arraycopy(regionName, 0, tableName, 0, offset); - offset = -1; - for (int i = regionName.length - 1; i > 0; i--) { - if(regionName[i] == DELIMITER) { - offset = i; - break; - } - } - if(offset == -1) throw new IOException("Invalid regionName format"); - byte [] startKey = HConstants.EMPTY_BYTE_ARRAY; - if(offset != tableName.length + 1) { - startKey = new byte[offset - tableName.length - 1]; - System.arraycopy(regionName, tableName.length + 1, startKey, 0, - offset - tableName.length - 1); + /** + * Separate elements of a regionName. + * + * @param regionName + * @return Array of byte[] containing the tablename, endKey and id + * @throws IOException + */ + public static byte[][] parseRegionName(final byte[] regionName) + throws IOException { + int offset = -1; + + for (int i = 0; i < regionName.length; i++) { + if (regionName[i] == DELIMITER) { + offset = i - 1; + break; + } + } + if (offset == -1) throw new IOException("Invalid regionName format"); + byte[] tableName = new byte[offset]; + System.arraycopy(regionName, 0, tableName, 0, offset); + offset = -1; + for (int i = regionName.length - 1; i > 0; i--) { + if (regionName[i] == DELIMITER) { + offset = i; + break; + } + } + if (offset == -1) throw new IOException("Invalid regionName format"); + byte[] endKey = HConstants.EMPTY_BYTE_ARRAY; + if (offset != tableName.length + 1) { + endKey = new byte[offset - tableName.length - 1]; + System.arraycopy(regionName, tableName.length + 1, endKey, 0, + offset - tableName.length - 1); + } + byte[] id = new byte[regionName.length - offset - 1]; + System.arraycopy(regionName, offset + 1, id, 0, + regionName.length - offset - 1); + byte[][] elements = new byte[3][]; + elements[0] = tableName; + elements[1] = endKey; + elements[2] = id; + return elements; } - byte [] id = new byte[regionName.length - offset - 1]; - System.arraycopy(regionName, offset + 1, id, 0, - regionName.length - offset - 1); - byte [][] elements = new byte[3][]; - elements[0] = tableName; - elements[1] = startKey; - elements[2] = id; - return elements; - } /** @return the regionId */ public long getRegionId(){ @@ -723,36 +849,58 @@ implements WritableComparable { // because freaks out if its not the current classes' version. This method // can deserialize version 0 and version 1 of HRI. byte version = in.readByte(); - if (version == 0) { - // This is the old HRI that carried an HTD. Migrate it. The below - // was copied from the old 0.90 HRI readFields. - this.endKey = Bytes.readByteArray(in); - this.offLine = in.readBoolean(); - this.regionId = in.readLong(); - this.regionName = Bytes.readByteArray(in); - this.regionNameStr = Bytes.toStringBinary(this.regionName); - this.split = in.readBoolean(); - this.startKey = Bytes.readByteArray(in); - try { - HTableDescriptor htd = new HTableDescriptor(); - htd.readFields(in); - this.tableName = htd.getName(); - } catch(EOFException eofe) { - throw new IOException("HTD not found in input buffer", eofe); - } - this.hashCode = in.readInt(); - } else if (getVersion() == version) { - this.endKey = Bytes.readByteArray(in); - this.offLine = in.readBoolean(); - this.regionId = in.readLong(); - this.regionName = Bytes.readByteArray(in); - this.regionNameStr = Bytes.toStringBinary(this.regionName); - this.split = in.readBoolean(); - this.startKey = Bytes.readByteArray(in); - this.tableName = Bytes.readByteArray(in); - this.hashCode = in.readInt(); - } else { - throw new IOException("Non-migratable/unknown version=" + getVersion()); + switch (version) { + case HRegionInfo.VERSION: + this.endKey = Bytes.readByteArray(in); + this.offLine = in.readBoolean(); + this.regionId = in.readLong(); + this.regionName = Bytes.readByteArray(in); + this.split = in.readBoolean(); + this.startKey = Bytes.readByteArray(in); + this.tableName = Bytes.readByteArray(in); + this.hashCode = in.readInt(); + this.regionNameStr = Bytes.toStringBinary(this.regionName); + break; + case HRegionInfo090x2.VERSION: + this.endKey = Bytes.readByteArray(in); + this.offLine = in.readBoolean(); + this.regionId = in.readLong(); + this.regionName = Bytes.readByteArray(in); + this.split = in.readBoolean(); + this.startKey = Bytes.readByteArray(in); + this.tableName = Bytes.readByteArray(in); + this.hashCode = in.readInt(); + if (Arrays.equals(this.tableName, HConstants.META_TABLE_NAME) || + Arrays.equals(this.tableName, HConstants.ROOT_TABLE_NAME)) { + this.regionName = createRegionName(tableName, startKey, endKey, regionId, false); + } else { + this.regionName = createRegionName(tableName, startKey, endKey, regionId, true); + } + this.regionNameStr = Bytes.toStringBinary(this.regionName); + break; + case VERSION_PRE_092: + // This is the old HRI that carried an HTD. Migrate it. The below + // was copied from the old 0.90 HRI readFields. + this.endKey = Bytes.readByteArray(in); + this.offLine = in.readBoolean(); + this.regionId = in.readLong(); + this.regionName = Bytes.readByteArray(in); + this.split = in.readBoolean(); + this.startKey = Bytes.readByteArray(in); + try { + HTableDescriptor htd = new HTableDescriptor(); + htd.readFields(in); + this.tableName = htd.getName(); + } catch (EOFException eofe) { + throw new IOException("HTD not found in input buffer", eofe); + } + this.hashCode = in.readInt(); + this.regionNameStr = Bytes.toStringBinary(this.regionName); + break; + default: + String errMsg = "Non-migratable/unknown version=" + version; + errMsg += " .It should be= " + getVersion(); + throw new IOException(errMsg); } } diff --git src/main/java/org/apache/hadoop/hbase/HServerLoad.java src/main/java/org/apache/hadoop/hbase/HServerLoad.java index 701aca6..5c94fa3 100644 --- src/main/java/org/apache/hadoop/hbase/HServerLoad.java +++ src/main/java/org/apache/hadoop/hbase/HServerLoad.java @@ -274,30 +274,8 @@ implements WritableComparable { public long getWriteRequestsCount() { return writeRequestsCount; } - - /** - * @return The current total size of root-level indexes for the region, in KB. - */ - public int getRootIndexSizeKB() { - return rootIndexSizeKB; - } - - /** - * @return The total size of all index blocks, not just the root level, in KB. - */ - public int getTotalStaticIndexSizeKB() { - return totalStaticIndexSizeKB; - } /** - * @return The total size of all Bloom filter blocks, not just loaded into the - * block cache, in KB. - */ - public int getTotalStaticBloomSizeKB() { - return totalStaticBloomSizeKB; - } - - /** * @return the total number of kvs in current compaction */ public long getTotalCompactingKVs() { diff --git src/main/java/org/apache/hadoop/hbase/HTableDescriptor.java src/main/java/org/apache/hadoop/hbase/HTableDescriptor.java index af89e3e..d783b38 100644 --- src/main/java/org/apache/hadoop/hbase/HTableDescriptor.java +++ src/main/java/org/apache/hadoop/hbase/HTableDescriptor.java @@ -37,8 +37,6 @@ import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceStability; import org.apache.hadoop.fs.Path; import org.apache.hadoop.hbase.io.ImmutableBytesWritable; -import org.apache.hadoop.hbase.io.hfile.Compression; -import org.apache.hadoop.hbase.regionserver.StoreFile; import org.apache.hadoop.hbase.security.User; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.io.WritableComparable; @@ -283,13 +281,65 @@ public class HTableDescriptor implements WritableComparable { } } - /* - * Set meta flags on this table. - * IS_ROOT_KEY is set if its a -ROOT- table - * IS_META_KEY is set either if its a -ROOT- or a .META. table - * Called by constructors. - * @param name - */ + /** + * This gives you a stop row for scanning for a particular region in meta. + * It's important that we don't scan past the end of the regions for a + * particular table. + * + * @param tableName The tablename in meta in which we want + * to provide a stopRow for scanning for. + * @return The stopRow to prevent scanning past the last region in meta for + * a table. + */ + + public static byte[] getStopRow(final byte[] tableName) { + final int allocation = tableName.length + 3; + byte[] b = new byte[allocation]; + int offset = tableName.length; + System.arraycopy(tableName, 0, b, 0, offset); + + b[offset++] = (byte) (HRegionInfo.END_OF_TABLE + 1); + b[offset++] = HRegionInfo.DELIMITER; + b[offset++] = HRegionInfo.DELIMITER; + return b; + } + + /** + * Get the first possible region that could match a particular + * tablename and searchrow. + * + * @param tableName The tableName in which we are searching for the matching + * region. + * @param searchRow The row in which we are searching for the matching region + * @return The first possible matching region. + */ + public static byte[] getStartRow(final byte[] tableName, + final byte[] searchRow) { + + if (searchRow == null || searchRow.length == 0) { + final int allocation = tableName.length + 3; + byte[] startRow = new byte[allocation]; + System.arraycopy(tableName, 0, startRow, 0, tableName.length); + startRow[tableName.length] = HRegionInfo.NOT_END_OF_TABLE - 1; + startRow[tableName.length + 1] = HRegionInfo.DELIMITER; + startRow[tableName.length + 2] = HRegionInfo.DELIMITER; + return startRow; + } + + return HRegionInfo.createRegionName(tableName, + null, + searchRow, + HConstants.NINES, + false); + } + + /* + * Set meta flags on this table. + * IS_ROOT_KEY is set if its a -ROOT- table + * IS_META_KEY is set either if its a -ROOT- or a .META. table + * Called by constructors. + * @param name + */ private void setMetaFlags(final byte [] name) { setRootRegion(Bytes.equals(name, HConstants.ROOT_TABLE_NAME)); setMetaRegion(isRootRegion() || diff --git src/main/java/org/apache/hadoop/hbase/KeyValue.java src/main/java/org/apache/hadoop/hbase/KeyValue.java index 9ae9e02..577587d 100644 --- src/main/java/org/apache/hadoop/hbase/KeyValue.java +++ src/main/java/org/apache/hadoop/hbase/KeyValue.java @@ -1917,10 +1917,10 @@ public class KeyValue implements Writable, HeapSize { public static class RootKeyComparator extends MetaKeyComparator { public int compareRows(byte [] left, int loffset, int llength, byte [] right, int roffset, int rlength) { - // Rows look like this: .META.,ROW_FROM_META,RID - // LOG.info("ROOT " + Bytes.toString(left, loffset, llength) + + // rows look like this: .META.!,ROW_FROM_META,RID + // LOG.info("ROOT " + Bytes.toString(left, loffset, llength) + // "---" + Bytes.toString(right, roffset, rlength)); - final int metalength = 7; // '.META.' length + final int metalength = 8; // '.META.' length int lmetaOffsetPlusDelimiter = loffset + metalength; int leftFarDelimiter = getDelimiterInReverse(left, lmetaOffsetPlusDelimiter, diff --git src/main/java/org/apache/hadoop/hbase/catalog/MetaMigratev2.java src/main/java/org/apache/hadoop/hbase/catalog/MetaMigratev2.java new file mode 100644 index 0000000..409671c --- /dev/null +++ src/main/java/org/apache/hadoop/hbase/catalog/MetaMigratev2.java @@ -0,0 +1,324 @@ +/** + * 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.hadoop.hbase.catalog; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.hbase.HConstants; +import org.apache.hadoop.hbase.HRegionInfo; +import org.apache.hadoop.hbase.catalog.MetaReader.Visitor; +import org.apache.hadoop.hbase.client.*; +import org.apache.hadoop.hbase.master.AssignmentManager; +import org.apache.hadoop.hbase.master.MasterFileSystem; +import org.apache.hadoop.hbase.master.MasterServices; +import org.apache.hadoop.hbase.migration.HRegionInfo090x2; +import org.apache.hadoop.hbase.util.Bytes; +import org.apache.hadoop.hbase.util.FSUtils; +import org.apache.hadoop.hbase.util.Writables; +import org.apache.zookeeper.KeeperException; + +import java.io.IOException; +import java.util.*; + +public class MetaMigratev2 { + + private static final Log LOG = LogFactory.getLog(MetaMigratev2.class); + private MasterFileSystem masterFileSystem; + private FileSystem fs; + private MasterServices masterServices; + + /** + * A class to check and update the version of Root and Meta + * + * @param hMaster The HMaster's master service + */ + public MetaMigratev2(MasterServices hMaster) { + masterServices = hMaster; + masterFileSystem = masterServices.getMasterFileSystem(); + fs = masterFileSystem.getFileSystem(); + } + + /** + * Meta visitor that migrates the info:regioninfo as it visits. + */ + class MigratingMetaVisitor implements Visitor { + private final MasterServices services; + final List htds = new ArrayList(); + + MigratingMetaVisitor(final MasterServices services) { + this.services = services; + } + + @Override + public boolean visit(Result r) throws IOException { + if (r == null || r.isEmpty()) return true; + // Check info:regioninfo, info:splitA, and info:splitB. Make sure all + // have migrated HRegionInfos... that there are no leftover 090 version + // HRegionInfos. + byte[] hriBytes = getBytes(r, HConstants.REGIONINFO_QUALIFIER); + // Presumes that an edit updating all three cells either succeeds or + // doesn't -- that we don't have case of info:regioninfo migrated but not + // info:splitA. + if (isMigrated(hriBytes)) return true; + // OK. Need to migrate this row in meta. + HRegionInfo090x2 hri090 = getHRegionInfo090x2(hriBytes); + Delete d = new Delete(hri090.getRegionName()); + + // This will 'migrate' the hregioninfo from 090 version to 092. + HRegionInfo hri = new HRegionInfo(hri090); + LOG.error("Migrating from hri090:" + hri090 + "=> to hri:" + hri); + + // Now make a put to write back to meta. + Put p = new Put(hri.getRegionName()); + p.add(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER, + Writables.getBytes(hri)); + + // Now check info:splitA and info:splitB if present. Migrate these too. + checkSplit(r, p, HConstants.SPLITA_QUALIFIER); + checkSplit(r, p, HConstants.SPLITB_QUALIFIER); + + MetaEditor.putToMetaTable(this.services.getCatalogTracker(), p); + MetaEditor.deleteMetaTable(this.services.getCatalogTracker(), d); + + htds.add(hri); + return true; + } + } + + void checkSplit(final Result r, final Put p, final byte[] which) + throws IOException { + //XXX do I need to remove splits, we need a test for this + byte[] hriSplitBytes = getBytes(r, which); + if (!isMigrated(hriSplitBytes)) { + // This will convert the HRI from 092v1 to 092v2 HRI. + // If we can't migrate the children throw an IOException. + HRegionInfo090x2 hri902 = Writables.getHRegionInfo90x2(hriSplitBytes); + // This will 'migrate' the hregioninfo from 090x2 version to 092. + HRegionInfo hri = new HRegionInfo(hri902); + + p.add(HConstants.CATALOG_FAMILY, which, Writables.getBytes(hri)); + } + } + + /** + * Get the version of roottable + * + * @return the version of the root table + * @throws IOException if we can't recover the hbase version. + */ + public int getVersion() throws IOException { + Path rootDir = masterFileSystem.getRootDir(); + return Integer.parseInt(FSUtils.getVersion(fs, rootDir)); + } + + /** + * Update legacy META rows + * + * @return List of table descriptors. + * @throws IOException In case we can't metaScan + */ + List updateMeta() throws IOException { + MigratingMetaVisitor v = new MigratingMetaVisitor(masterServices); + MetaReader.fullScan(masterServices.getCatalogTracker(), v); + + AssignmentManager assignmentManager = masterServices.getAssignmentManager(); + assignmentManager.setRegionsToReopen(v.htds); + return v.htds; + } + + boolean isRootOnline() throws IOException, InterruptedException { + Configuration configuration = masterServices.getConfiguration(); + int defaultTimeout = 1000; + long timeout = configuration.getLong("hbase.catalog.verification.timeout", + defaultTimeout); + CatalogTracker catalogTracker = masterServices.getCatalogTracker(); + return catalogTracker.verifyRootRegionLocation(timeout); + } + + boolean isMetaOnline() throws IOException, InterruptedException { + Configuration configuration = masterServices.getConfiguration(); + int defaultTimeout = 1000; + long timeout = configuration.getLong("hbase.catalog.verification.timeout", + defaultTimeout); + CatalogTracker catalogTracker = masterServices.getCatalogTracker(); + return catalogTracker.verifyMetaRegionLocation(timeout); + } + + void onlineRoot() throws KeeperException, InterruptedException, IOException { + if (isRootOnline()) { + LOG.error("Root is already online"); + return; + } + AssignmentManager assignmentManager = masterServices.getAssignmentManager(); + + Path metaName = new Path(masterFileSystem.getRootDir(), + new Path(Bytes.toString(HConstants.ROOT_TABLE_NAME))); + + Path oldRootRegion = new Path(metaName, "70236052"); + Path newRootRegion = new Path(metaName, HRegionInfo.ROOT_REGION_ENCODING); + + // We are recreating the new region + if (fs.exists(newRootRegion)) { + fs.delete(newRootRegion, true); + } + + //We can't support split meta regions + if (fs.exists(oldRootRegion)) { + fs.delete(oldRootRegion , true); + } + + assignmentManager.assignRoot(); + + //This guarantees that the transition has completed + assignmentManager.waitForAssignment(HRegionInfo.ROOT_REGIONINFO); + } + + + /** + * Update the ROOT with new HRI. (HRI with no HTD) + * + * @return List of table descriptors + * @throws IOException In case we can't metaScan + */ + List updateRoot() throws IOException { + HRegionInfo hri = HRegionInfo.FIRST_META_REGIONINFO; + HTable rootTable = new HTable(masterServices.getConfiguration(), + HConstants.ROOT_TABLE_NAME); + Result result = rootTable.get(new Get(hri.getRegionName())); + ArrayList retVal = new ArrayList(); + + // Make sure the preexisting root doesn't exist and we aren't overriding. + if (result.isEmpty()) { + // Now make a put to write back to meta. + Put p = new Put(hri.getRegionName()); + p.add(HConstants.CATALOG_FAMILY, + HConstants.REGIONINFO_QUALIFIER, + Writables.getBytes(hri)); + MetaEditor.putToRootTable(masterServices.getCatalogTracker(), p); + retVal.add(hri); + } + return retVal; + } + + + /** + * @param r Result to dig in. + * @param qualifier Qualifier to look at in the passed r. + * @return Bytes for an HRegionInfo or null if no bytes or empty bytes found. + */ + byte[] getBytes(final Result r, final byte[] qualifier) { + byte[] hriBytes = r.getValue(HConstants.CATALOG_FAMILY, qualifier); + if (hriBytes == null || hriBytes.length <= 0) return null; + return hriBytes; + } + + boolean isMigrated(final byte[] hriBytes) { + if (hriBytes == null || hriBytes.length <= 0) return true; + // Else, what version this HRegionInfo instance is at. The first byte + // is the version byte in a serialized HRegionInfo. If its same as our + // current HRI, then nothing to do. + + byte version = hriBytes[0]; + if (version == HRegionInfo.VERSION) { + return true; + } else if (version == HRegionInfo090x2.VERSION || version == 0 ) { + return false; + } + // Unknown version. Return true that its 'migrated' but log warning. + // Should 'never' happen. + assert false : "Unexpected version; bytes=" + Bytes.toStringBinary(hriBytes); + return true; + } + + /** + * Update and Online the new root region with information from the old one. + * + * @return Migrated htds + * @throws IOException Changes to the filesystem can trigger. + * @throws InterruptedException Changes to the zookeeper can trigger. + * @throws KeeperException Changes to the zookeeper can trigger. + */ + public List updateAndOnlineRoot() + throws IOException, InterruptedException, KeeperException { + + onlineRoot(); + return updateRoot(); + } + + /** + * Update and Online the new meta region with information from the old one. + * Also if we complete here we can set the hbase file system version. + * + * @return Migrated htds + * @throws IOException Changes to the filesystem can trigger. + * @throws InterruptedException Changes to the zookeeper can trigger. + * @throws KeeperException Changes to the zookeeper can trigger. + */ + public List updateAndOnlineMeta() + throws KeeperException, IOException, InterruptedException { + onlineMeta(); + List htds = updateMeta(); + FSUtils.setVersion(fs, + masterFileSystem.getRootDir(), + HConstants.FILE_SYSTEM_VERSION_INT, + 10); + + return htds; + } + + private void onlineMeta() throws KeeperException, IOException, InterruptedException { + + if (isMetaOnline()) { + LOG.error("Meta is already online"); + return; + } + + Path metaName = new Path(masterFileSystem.getRootDir(), + new Path(Bytes.toString(HConstants.META_TABLE_NAME))); + Path oldMetaRegion = new Path(metaName, "1028785192"); + Path newMetaRegion = new Path(metaName, HRegionInfo.META_REGION_ENCODING); + + if (fs.exists(newMetaRegion)) { + fs.delete(newMetaRegion, true); + } + + fs.rename(oldMetaRegion, newMetaRegion); + this.masterServices.getAssignmentManager().assignMeta(); + } + + /** + * Get HRegionInfoForMigration serialized from bytes. + * + * @param bytes serialized bytes + * @return An instance of a 090 HRI or null if we failed deserialize + */ + HRegionInfo090x2 getHRegionInfo090x2(final byte[] bytes) { + if (bytes == null || bytes.length == 0) return null; + HRegionInfo090x2 hri = null; + try { + hri = (HRegionInfo090x2) Writables.getWritable(bytes, new HRegionInfo090x2()); + } catch (IOException ioe) { + LOG.warn("Failed deserialize as a 090 HRegionInfo); bytes=" + + Bytes.toStringBinary(bytes), ioe); + } + return hri; + } +} diff --git src/main/java/org/apache/hadoop/hbase/catalog/MetaReader.java src/main/java/org/apache/hadoop/hbase/catalog/MetaReader.java index 238740a..1184a40 100644 --- src/main/java/org/apache/hadoop/hbase/catalog/MetaReader.java +++ src/main/java/org/apache/hadoop/hbase/catalog/MetaReader.java @@ -387,7 +387,9 @@ public class MetaReader { this.results.add(this.current); } }; - fullScan(catalogTracker, visitor, getTableStartRowForMeta(tableNameBytes)); + byte[] startRow = HTableDescriptor.getStartRow(tableName.getBytes(), + HConstants.EMPTY_BYTE_ARRAY); + fullScan(catalogTracker, visitor, startRow); // If visitor has results >= 1 then table exists. return visitor.getResults().size() >= 1; } @@ -446,18 +448,7 @@ public class MetaReader { return Bytes.equals(tableName, current.getTableName()); } - /** - * @param tableName - * @return Place to start Scan in .META. when passed a - * tableName; returns <tableName&rt; <,&rt; <,&rt; - */ - static byte [] getTableStartRowForMeta(final byte [] tableName) { - byte [] startRow = new byte[tableName.length + 2]; - System.arraycopy(tableName, 0, startRow, 0, tableName.length); - startRow[startRow.length - 2] = HRegionInfo.DELIMITER; - startRow[startRow.length - 1] = HRegionInfo.DELIMITER; - return startRow; - } + /** * This method creates a Scan object that will only scan catalog rows that @@ -471,12 +462,12 @@ public class MetaReader { public static Scan getScanForTableName(byte[] tableName) { String strName = Bytes.toString(tableName); // Start key is just the table name with delimiters - byte[] startKey = Bytes.toBytes(strName + ",,"); + byte[] startKey = HTableDescriptor.getStartRow(tableName, + HConstants.EMPTY_BYTE_ARRAY); // Stop key appends the smallest possible char to the table name - byte[] stopKey = Bytes.toBytes(strName + " ,,"); + byte[] stopKey = HTableDescriptor.getStopRow(tableName); - Scan scan = new Scan(startKey); - scan.setStopRow(stopKey); + Scan scan = new Scan(startKey, stopKey); return scan; } @@ -541,8 +532,10 @@ public class MetaReader { this.results.add(this.current); } }; - fullScan(catalogTracker, visitor, getTableStartRowForMeta(tableName), - Bytes.equals(tableName, HConstants.META_TABLE_NAME)); + byte[] startRow = HTableDescriptor.getStartRow(tableName, + HConstants.EMPTY_BYTE_ARRAY); + boolean isMeta = Bytes.equals(tableName, HConstants.META_TABLE_NAME); + fullScan(catalogTracker, visitor, startRow, isMeta); return visitor.getResults(); } diff --git src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java index ee16e72..b804fee 100644 --- src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java +++ src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java @@ -1592,8 +1592,8 @@ public class HBaseAdmin implements Abortable, Closeable { private HRegionLocation getFirstMetaServerForTable(final byte [] tableName) throws IOException { - return connection.locateRegion(HConstants.META_TABLE_NAME, - HRegionInfo.createRegionName(tableName, null, HConstants.NINES, false)); + byte[] metaRowKey = HTableDescriptor.getStartRow(tableName, null); + return connection.locateRegion(HConstants.META_TABLE_NAME, metaRowKey); } /** diff --git src/main/java/org/apache/hadoop/hbase/client/HConnectionManager.java src/main/java/org/apache/hadoop/hbase/client/HConnectionManager.java index 820e2a9..187e21a 100644 --- src/main/java/org/apache/hadoop/hbase/client/HConnectionManager.java +++ src/main/java/org/apache/hadoop/hbase/client/HConnectionManager.java @@ -953,8 +953,12 @@ public class HConnectionManager { zkw.close(); } } else if (Bytes.equals(tableName, HConstants.META_TABLE_NAME)) { - return locateRegionInMeta(HConstants.ROOT_TABLE_NAME, tableName, row, - useCache, metaRegionLock); + //HARD CODED TO POINT TO THE FIRST META TABLE + return locateRegionInMeta(HConstants.ROOT_TABLE_NAME, + HConstants.META_TABLE_NAME, + HConstants.EMPTY_BYTE_ARRAY, + useCache, + metaRegionLock); } else { // Region not in the cache - have to go to the meta RS return locateRegionInMeta(HConstants.META_TABLE_NAME, tableName, row, @@ -1022,9 +1026,51 @@ public class HConnectionManager { } } + + private HRegionInfo resultToHRegionInfo(final Result result, + byte[] tableName, + byte[] parentTable) + throws IOException { + + if (result == null) { + throw new TableNotFoundException(Bytes.toString(tableName)); + } + + byte[] value = result.getValue(HConstants.CATALOG_FAMILY, + HConstants.REGIONINFO_QUALIFIER); + + if (value == null || value.length == 0) { + throw new IOException("HRegionInfo was null or empty in " + + Bytes.toString(parentTable) + + ", row=" + + result); + } + + HRegionInfo regionInfo = Writables.getHRegionInfo(value); + + // possible we got a region of a different table... + + if (!Bytes.equals(regionInfo.getTableName(), tableName)) { + String errorMsg = "Table '" + Bytes.toString(tableName) + "' was not found, got: "; + if (regionInfo != null) { + errorMsg += Bytes.toString(regionInfo.getTableName()) + "."; + } + throw new TableNotFoundException(errorMsg); + } + + return regionInfo; + } + private boolean finishedScanningForRegion(HRegionInfo regionInfo) { + if (regionInfo == null || regionInfo.isOffline() || regionInfo.isSplit()) { + return false; + } + return true; + } + /* * Search one of the meta tables (-ROOT- or .META.) for the HRegionLocation - * info that contains the table and row we're seeking. + * info that contains the table and row we're seeking. If the row is null or 0 length + * then return a key which scans to the first meta key for the table. */ private HRegionLocation locateRegionInMeta(final byte [] parentTable, final byte [] tableName, final byte [] row, boolean useCache, @@ -1040,17 +1086,13 @@ public class HConnectionManager { } } - // build the key of the meta region we should be looking for. - // the extra 9's on the end are necessary to allow "exact" matches - // without knowing the precise region names. - byte [] metaKey = HRegionInfo.createRegionName(tableName, row, - HConstants.NINES, false); + final byte [] metaKey = HTableDescriptor.getStartRow(tableName, row); for (int tries = 0; true; tries++) { if (tries >= numRetries) { throw new NoServerForRegionException("Unable to find region for " + Bytes.toStringBinary(row) + " after " + numRetries + " tries."); } - + Result regionInfoRow = null; HRegionLocation metaLocation = null; try { // locate the root or meta region @@ -1060,10 +1102,11 @@ public class HConnectionManager { HRegionInterface server = getHRegionConnection(metaLocation.getHostname(), metaLocation.getPort()); - Result regionInfoRow = null; // This block guards against two threads trying to load the meta // region at the same time. The first will load the meta region and // the second will use the value that the first one found. + + HRegionInfo regionInfo = null; synchronized (regionLockObject) { // If the parent table is META, we may want to pre-fetch some // region info into the global region cache for this table. @@ -1085,29 +1128,42 @@ public class HConnectionManager { deleteCachedLocation(tableName, row); } - // Query the root or meta region for the location of the meta region - regionInfoRow = server.getClosestRowBefore( - metaLocation.getRegionInfo().getRegionName(), metaKey, - HConstants.CATALOG_FAMILY); - } - if (regionInfoRow == null) { - throw new TableNotFoundException(Bytes.toString(tableName)); - } - byte [] value = regionInfoRow.getValue(HConstants.CATALOG_FAMILY, - HConstants.REGIONINFO_QUALIFIER); - if (value == null || value.length == 0) { - throw new IOException("HRegionInfo was null or empty in " + - Bytes.toString(parentTable) + ", row=" + regionInfoRow); - } - // convert the row result into the HRegionLocation we need! - HRegionInfo regionInfo = (HRegionInfo) Writables.getWritable( - value, new HRegionInfo()); - // possible we got a region of a different table... - if (!Bytes.equals(regionInfo.getTableName(), tableName)) { - throw new TableNotFoundException( - "Table '" + Bytes.toString(tableName) + "' was not found, got: " + - Bytes.toString(regionInfo.getTableName()) + "."); + + byte[] stopRow = HTableDescriptor.getStopRow(tableName); + Scan scan = new Scan(metaKey).addFamily(HConstants.CATALOG_FAMILY); + byte[] regionName = metaLocation.getRegionInfo().getRegionName(); + long scannerId = server.openScanner(regionName, scan); + + Result result; + do { + result = server.next(scannerId); + if (result != null ){ + regionInfoRow = result; + regionInfo = resultToHRegionInfo(regionInfoRow, + tableName, + parentTable); + if (! regionInfo.isOffline()) { + break; + } + } + } while (result != null); + + // We haven't cleared the meta entry out of the table yet + if (result == null) { + throw new TableNotFoundException("Table '" + Bytes.toString(tableName) + + " we searched for the StartKey: " + Bytes.toString(metaKey) + + " startKey lastChar's int value: " + (int) metaKey[metaKey.length -3] + + " with the stopKey: " + Bytes.toString(stopRow) + + " stopRow lastChar's int value: " + (int) stopRow[stopRow.length -3] + + " with parentTable:" + Bytes.toString(parentTable)); + } + } + if (regionInfo == null) { + throw new TableNotFoundException("Table '" + + Bytes.toString(tableName) + "' was not found, got: " + + Bytes.toString(regionInfo.getTableName()) + "."); } + if (regionInfo.isSplit()) { throw new RegionOfflineException("the only available region for" + " the required row is a split parent," + @@ -1120,11 +1176,11 @@ public class HConnectionManager { regionInfo.getRegionNameAsString()); } - value = regionInfoRow.getValue(HConstants.CATALOG_FAMILY, - HConstants.SERVER_QUALIFIER); String hostAndPort = ""; - if (value != null) { - hostAndPort = Bytes.toString(value); + if (regionInfoRow.getValue(HConstants.CATALOG_FAMILY, + HConstants.SERVER_QUALIFIER) != null) { + hostAndPort = Bytes.toString(regionInfoRow.getValue(HConstants.CATALOG_FAMILY, + HConstants.SERVER_QUALIFIER)); } if (hostAndPort.equals("")) { throw new NoServerForRegionException("No server address listed " + diff --git src/main/java/org/apache/hadoop/hbase/client/HTable.java src/main/java/org/apache/hadoop/hbase/client/HTable.java index 2c87d50..d7ff800 100644 --- src/main/java/org/apache/hadoop/hbase/client/HTable.java +++ src/main/java/org/apache/hadoop/hbase/client/HTable.java @@ -654,27 +654,6 @@ public class HTable implements HTableInterface { return allRegions; } - /** - * {@inheritDoc} - */ - @Override - public Result getRowOrBefore(final byte[] row, final byte[] family) - throws IOException { - return new ServerCallable(connection, tableName, row, operationTimeout) { - public Result call() throws IOException { - try { - GetRequest request = RequestConverter.buildGetRequest( - location.getRegionInfo().getRegionName(), row, family, true); - GetResponse response = server.get(null, request); - if (!response.hasResult()) return null; - return ProtobufUtil.toResult(response.getResult()); - } catch (ServiceException se) { - throw ProtobufUtil.getRemoteException(se); - } - } - }.withRetries(); - } - /** * {@inheritDoc} */ diff --git src/main/java/org/apache/hadoop/hbase/client/HTableInterface.java src/main/java/org/apache/hadoop/hbase/client/HTableInterface.java index 6dbcf33..2067a0d 100644 --- src/main/java/org/apache/hadoop/hbase/client/HTableInterface.java +++ src/main/java/org/apache/hadoop/hbase/client/HTableInterface.java @@ -134,23 +134,6 @@ public interface HTableInterface extends Closeable { Result[] get(List gets) throws IOException; /** - * Return the row that matches row exactly, - * or the one that immediately precedes it. - * - * @param row A row key. - * @param family Column family to include in the {@link Result}. - * @throws IOException if a remote or network exception occurs. - * @since 0.20.0 - * - * @deprecated As of version 0.92 this method is deprecated without - * replacement. - * getRowOrBefore is used internally to find entries in .META. and makes - * various assumptions about the table (which are true for .META. but not - * in general) to be efficient. - */ - Result getRowOrBefore(byte[] row, byte[] family) throws IOException; - - /** * Returns a scanner on the current table as specified by the {@link Scan} * object. * Note that the passed {@link Scan}'s start row and caching properties diff --git src/main/java/org/apache/hadoop/hbase/client/HTablePool.java src/main/java/org/apache/hadoop/hbase/client/HTablePool.java index a2f1578..135538f 100755 --- src/main/java/org/apache/hadoop/hbase/client/HTablePool.java +++ src/main/java/org/apache/hadoop/hbase/client/HTablePool.java @@ -376,11 +376,6 @@ public class HTablePool implements Closeable { } @Override - public Result getRowOrBefore(byte[] row, byte[] family) throws IOException { - return table.getRowOrBefore(row, family); - } - - @Override public ResultScanner getScanner(Scan scan) throws IOException { return table.getScanner(scan); } diff --git src/main/java/org/apache/hadoop/hbase/client/MetaScanner.java src/main/java/org/apache/hadoop/hbase/client/MetaScanner.java index f404999..032f90c 100644 --- src/main/java/org/apache/hadoop/hbase/client/MetaScanner.java +++ src/main/java/org/apache/hadoop/hbase/client/MetaScanner.java @@ -33,8 +33,8 @@ import org.apache.hadoop.classification.InterfaceStability; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.HRegionInfo; +import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.ServerName; -import org.apache.hadoop.hbase.TableNotFoundException; import org.apache.hadoop.hbase.client.HConnectionManager.HConnectable; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.Writables; @@ -143,44 +143,15 @@ public class MetaScanner { // if row is not null, we want to use the startKey of the row's region as // the startRow for the meta scan. byte[] startRow; - if (row != null) { - // Scan starting at a particular row in a particular table - assert tableName != null; - byte[] searchRow = - HRegionInfo.createRegionName(tableName, row, HConstants.NINES, - false); - HTable metaTable = null; - try { - metaTable = new HTable(configuration, HConstants.META_TABLE_NAME); - Result startRowResult = metaTable.getRowOrBefore(searchRow, - HConstants.CATALOG_FAMILY); - if (startRowResult == null) { - throw new TableNotFoundException("Cannot find row in .META. for table: " - + Bytes.toString(tableName) + ", row=" + Bytes.toStringBinary(searchRow)); - } - byte[] value = startRowResult.getValue(HConstants.CATALOG_FAMILY, - HConstants.REGIONINFO_QUALIFIER); - if (value == null || value.length == 0) { - throw new IOException("HRegionInfo was null or empty in Meta for " + - Bytes.toString(tableName) + ", row=" + Bytes.toStringBinary(searchRow)); - } - HRegionInfo regionInfo = Writables.getHRegionInfo(value); - - byte[] rowBefore = regionInfo.getStartKey(); - startRow = HRegionInfo.createRegionName(tableName, rowBefore, - HConstants.ZEROES, false); - } finally { - if (metaTable != null) { - metaTable.close(); - } - } - } else if (tableName == null || tableName.length == 0) { + byte[] stopRow; + + if (tableName == null || tableName.length == 0) { // Full META scan startRow = HConstants.EMPTY_START_ROW; + stopRow = null; } else { - // Scan META for an entire table - startRow = HRegionInfo.createRegionName( - tableName, HConstants.EMPTY_START_ROW, HConstants.ZEROES, false); + startRow = HTableDescriptor.getStartRow(tableName, row); + stopRow = HTableDescriptor.getStopRow(tableName); } // Scan over each meta region @@ -188,8 +159,15 @@ public class MetaScanner { int rows = Math.min(rowLimit, configuration.getInt( HConstants.HBASE_META_SCANNER_CACHING, HConstants.DEFAULT_HBASE_META_SCANNER_CACHING)); + do { - final Scan scan = new Scan(startRow).addFamily(HConstants.CATALOG_FAMILY); + Scan scan; + if (stopRow != null) { // Support full meta scans + scan = new Scan(startRow, stopRow).addFamily(HConstants.CATALOG_FAMILY); + } else { + scan = new Scan(startRow).addFamily(HConstants.CATALOG_FAMILY); + } + if (LOG.isDebugEnabled()) { LOG.debug("Scanning " + Bytes.toString(metaTableName) + " starting at row=" + Bytes.toStringBinary(startRow) + " for max=" + diff --git src/main/java/org/apache/hadoop/hbase/coprocessor/BaseRegionObserver.java src/main/java/org/apache/hadoop/hbase/coprocessor/BaseRegionObserver.java index 197eb71..dc141a7 100644 --- src/main/java/org/apache/hadoop/hbase/coprocessor/BaseRegionObserver.java +++ src/main/java/org/apache/hadoop/hbase/coprocessor/BaseRegionObserver.java @@ -105,18 +105,6 @@ public abstract class BaseRegionObserver implements RegionObserver { final Store store, final StoreFile resultFile) { } @Override - public void preGetClosestRowBefore(final ObserverContext e, - final byte [] row, final byte [] family, final Result result) - throws IOException { - } - - @Override - public void postGetClosestRowBefore(final ObserverContext e, - final byte [] row, final byte [] family, final Result result) - throws IOException { - } - - @Override public void preGet(final ObserverContext e, final Get get, final List results) throws IOException { } diff --git src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorHost.java src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorHost.java index 4f07d5a..e2a0d49 100644 --- src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorHost.java +++ src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorHost.java @@ -388,11 +388,6 @@ public abstract class CoprocessorHost { } } - public Result getRowOrBefore(byte[] row, byte[] family) - throws IOException { - return table.getRowOrBefore(row, family); - } - public Result get(Get get) throws IOException { return table.get(get); } diff --git src/main/java/org/apache/hadoop/hbase/coprocessor/RegionObserver.java src/main/java/org/apache/hadoop/hbase/coprocessor/RegionObserver.java index 30c61ca..5b4f42d 100644 --- src/main/java/org/apache/hadoop/hbase/coprocessor/RegionObserver.java +++ src/main/java/org/apache/hadoop/hbase/coprocessor/RegionObserver.java @@ -166,40 +166,6 @@ public interface RegionObserver extends Coprocessor { boolean abortRequested); /** - * Called before a client makes a GetClosestRowBefore request. - *

- * Call CoprocessorEnvironment#bypass to skip default actions - *

- * Call CoprocessorEnvironment#complete to skip any subsequent chained - * coprocessors - * @param c the environment provided by the region server - * @param row the row - * @param family the family - * @param result The result to return to the client if default processing - * is bypassed. Can be modified. Will not be used if default processing - * is not bypassed. - * @throws IOException if an error occurred on the coprocessor - */ - void preGetClosestRowBefore(final ObserverContext c, - final byte [] row, final byte [] family, final Result result) - throws IOException; - - /** - * Called after a client makes a GetClosestRowBefore request. - *

- * Call CoprocessorEnvironment#complete to skip any subsequent chained - * coprocessors - * @param c the environment provided by the region server - * @param row the row - * @param family the desired family - * @param result the result to return to the client, modify as necessary - * @throws IOException if an error occurred on the coprocessor - */ - void postGetClosestRowBefore(final ObserverContext c, - final byte [] row, final byte [] family, final Result result) - throws IOException; - - /** * Called before the client performs a Get *

* Call CoprocessorEnvironment#bypass to skip default actions diff --git src/main/java/org/apache/hadoop/hbase/ipc/HRegionInterface.java src/main/java/org/apache/hadoop/hbase/ipc/HRegionInterface.java index 757f98e..d501c1a 100644 --- src/main/java/org/apache/hadoop/hbase/ipc/HRegionInterface.java +++ src/main/java/org/apache/hadoop/hbase/ipc/HRegionInterface.java @@ -135,20 +135,6 @@ public interface HRegionInterface extends VersionedProtocol, Stoppable, Abortabl throws IllegalArgumentException; /** - * Return all the data for the row that matches row exactly, - * or the one that immediately preceeds it. - * - * @param regionName region name - * @param row row key - * @param family Column family to look for row in. - * @return map of values - * @throws IOException e - */ - public Result getClosestRowBefore(final byte [] regionName, - final byte [] row, final byte [] family) - throws IOException; - - /** * Perform Get operation. * @param regionName name of region to get from * @param get Get operation diff --git src/main/java/org/apache/hadoop/hbase/master/HMaster.java src/main/java/org/apache/hadoop/hbase/master/HMaster.java index 10bbfcd..6e66beb 100644 --- src/main/java/org/apache/hadoop/hbase/master/HMaster.java +++ src/main/java/org/apache/hadoop/hbase/master/HMaster.java @@ -65,6 +65,7 @@ import org.apache.hadoop.hbase.TableNotFoundException; import org.apache.hadoop.hbase.UnknownRegionException; import org.apache.hadoop.hbase.ZooKeeperConnectionException; import org.apache.hadoop.hbase.catalog.CatalogTracker; +import org.apache.hadoop.hbase.catalog.MetaMigratev2; import org.apache.hadoop.hbase.catalog.MetaReader; import org.apache.hadoop.hbase.client.HConnectionManager; import org.apache.hadoop.hbase.client.MetaScanner; @@ -573,17 +574,32 @@ Server { status.setStatus("Splitting logs after master startup"); splitLogAfterStartup(this.fileSystemManager, onlineServers); - // Make sure root and meta assigned before proceeding. - if (!assignRootAndMeta(status)) return; serverShutdownHandlerEnabled = true; this.serverManager.expireDeadNotExpiredServers(); - // Update meta with new HRI if required. i.e migrate all HRI with HTD to - // HRI with out HTD in meta and update the status in ROOT. This must happen - // before we assign all user regions or else the assignment will fail. - // TODO: Remove this when we do 0.94. - org.apache.hadoop.hbase.catalog.MetaMigrationRemovingHTD. - updateMetaWithNewHRI(this); + MetaMigratev2 metaMigratev2 = new MetaMigratev2(this); + int version = metaMigratev2.getVersion(); + // TODO: Remove this when we do 1.0 + if (version < HConstants.FILE_SYSTEM_VERSION_INT ){ + boolean rit = this.assignmentManager. + processRegionInTransitionAndBlockUntilAssigned( + HRegionInfo.ROOT_REGIONINFO); + + // Make sure root and meta assigned before proceeding. + metaMigratev2.updateAndOnlineRoot(); + + rit = this.assignmentManager. + processRegionInTransitionAndBlockUntilAssigned( + HRegionInfo.FIRST_META_REGIONINFO); + + metaMigratev2.updateAndOnlineMeta(); + + // Update meta with new HRI if required. i.e migrate all HRI with HTD to + // HRI with out HTD in meta and update the status in ROOT. This must happen + // before we assign all user regions or else the assignment will fail. + + } + assignRootAndMeta(status); // Fixup assignment manager status status.setStatus("Starting assignment manager"); diff --git src/main/java/org/apache/hadoop/hbase/master/handler/ServerShutdownHandler.java src/main/java/org/apache/hadoop/hbase/master/handler/ServerShutdownHandler.java index 2ec6677..040ab38 100644 --- src/main/java/org/apache/hadoop/hbase/master/handler/ServerShutdownHandler.java +++ src/main/java/org/apache/hadoop/hbase/master/handler/ServerShutdownHandler.java @@ -463,7 +463,7 @@ public class ServerShutdownHandler extends EventHandler { return false; } // If our start rows do not compare, move on. - if (!Bytes.equals(daughter.getStartKey(), hri.getStartKey())) { + if (!Bytes.equals(daughter.getEndKey(), hri.getEndKey())) { return false; } // Else, table name and start rows compare. It means that the daughter diff --git src/main/java/org/apache/hadoop/hbase/migration/HRegionInfo090x2.java src/main/java/org/apache/hadoop/hbase/migration/HRegionInfo090x2.java new file mode 100644 index 0000000..7e70acb --- /dev/null +++ src/main/java/org/apache/hadoop/hbase/migration/HRegionInfo090x2.java @@ -0,0 +1,763 @@ +/** + * Copyright 2007 The Apache Software Foundation + * + * 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.hadoop.hbase.migration; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.hbase.*; +import org.apache.hadoop.hbase.KeyValue.KVComparator; +import org.apache.hadoop.hbase.util.Bytes; +import org.apache.hadoop.hbase.util.FSTableDescriptors; +import org.apache.hadoop.hbase.util.JenkinsHash; +import org.apache.hadoop.hbase.util.MD5Hash; +import org.apache.hadoop.io.VersionedWritable; +import org.apache.hadoop.io.WritableComparable; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.EOFException; +import java.io.IOException; +import java.util.Arrays; + +/** + * This contains the newest old HRegionInfo class. It's used for migration. + * Migration happens via the writables interface. + */ +public class HRegionInfo090x2 extends VersionedWritable + implements WritableComparable { + // VERSION == 0 when HRegionInfo had an HTableDescriptor inside it. + public static final byte VERSION_PRE_092 = 0; + public static final byte VERSION = 1; + private static final Log LOG = LogFactory.getLog(HRegionInfo090x2.class); + + /** + * The new format for a region name contains its encodedName at the end. + * The encoded name also serves as the directory name for the region + * in the filesystem. + * + * New region name format: + * <tablename>,,<startkey>,<regionIdTimestamp>.<encodedName>. + * where, + * <encodedName> is a hex version of the MD5 hash of + * <tablename>,<startkey>,<regionIdTimestamp> + * + * The old region name format: + * <tablename>,<startkey>,<regionIdTimestamp> + * For region names in the old format, the encoded name is a 32-bit + * JenkinsHash integer value (in its decimal notation, string form). + *

+ * **NOTE** + * + * ROOT, the first META region, and regions created by an older + * version of HBase (0.20 or prior) will continue to use the + * old region name format. + */ + + /** Separator used to demarcate the encodedName in a region name + * in the new format. See description on new format above. + */ + private static final int ENC_SEPARATOR = '.'; + public static final int MD5_HEX_LENGTH = 32; + + /** + * Does region name contain its encoded name? + * @param regionName region name + * @return boolean indicating if this a new format region + * name which contains its encoded name. + */ + private static boolean hasEncodedName(final byte[] regionName) { + // check if region name ends in ENC_SEPARATOR + if ((regionName.length >= 1) + && (regionName[regionName.length - 1] == ENC_SEPARATOR)) { + // region name is new format. it contains the encoded name. + return true; + } + return false; + } + + /** + * @param regionName + * @return the encodedName + */ + public static String encodeRegionName(final byte [] regionName) { + String encodedName; + if (hasEncodedName(regionName)) { + // region is in new format: + // ,,/encodedName/ + encodedName = Bytes.toString(regionName, + regionName.length - MD5_HEX_LENGTH - 1, + MD5_HEX_LENGTH); + } else { + // old format region name. ROOT and first META region also + // use this format.EncodedName is the JenkinsHash value. + int hashVal = Math.abs(JenkinsHash.getInstance().hash(regionName, + regionName.length, 0)); + encodedName = String.valueOf(hashVal); + } + return encodedName; + } + + /** + * Use logging. + * @param encodedRegionName The encoded regionname. + * @return -ROOT- if passed 70236052 or + * .META. if passed 1028785192 else returns + * encodedRegionName + */ + public static String prettyPrint(final String encodedRegionName) { + if (encodedRegionName.equals("70236052")) { + return encodedRegionName + "/-ROOT-"; + } else if (encodedRegionName.equals("1028785192")) { + return encodedRegionName + "/.META."; + } + return encodedRegionName; + } + + /** delimiter used between portions of a region name */ + public static final int DELIMITER = ','; + + /** HRegionInfo for root region */ + public static final HRegionInfo090x2 ROOT_REGIONINFO = + new HRegionInfo090x2(0L, Bytes.toBytes("-ROOT-")); + + /** HRegionInfo for first meta region */ + public static final HRegionInfo090x2 FIRST_META_REGIONINFO = + new HRegionInfo090x2(1L, Bytes.toBytes(".META.")); + + private byte [] endKey = HConstants.EMPTY_BYTE_ARRAY; + // This flag is in the parent of a split while the parent is still referenced + // by daughter regions. We USED to set this flag when we disabled a table + // but now table state is kept up in zookeeper as of 0.90.0 HBase. + private boolean offLine = false; + private long regionId = -1; + private transient byte [] regionName = HConstants.EMPTY_BYTE_ARRAY; + private String regionNameStr = ""; + private boolean split = false; + private byte [] startKey = HConstants.EMPTY_BYTE_ARRAY; + private int hashCode = -1; + //TODO: Move NO_HASH to HStoreFile which is really the only place it is used. + public static final String NO_HASH = null; + private volatile String encodedName = NO_HASH; + private byte [] encodedNameAsBytes = null; + + // Current TableName + private byte[] tableName = null; + + private void setHashCode() { + int result = Arrays.hashCode(this.regionName); + result ^= this.regionId; + result ^= Arrays.hashCode(this.startKey); + result ^= Arrays.hashCode(this.endKey); + result ^= Boolean.valueOf(this.offLine).hashCode(); + result ^= Arrays.hashCode(this.tableName); + this.hashCode = result; + } + + + /** + * Private constructor used constructing HRegionInfo for the catalog root and + * first meta regions + */ + private HRegionInfo090x2(long regionId, byte[] tableName) { + super(); + this.regionId = regionId; + this.tableName = tableName.clone(); + // Note: Root & First Meta regions names are still in old format + this.regionName = createRegionName(tableName, null, + regionId, false); + this.regionNameStr = Bytes.toStringBinary(this.regionName); + setHashCode(); + } + + /** Default constructor - creates empty object */ + public HRegionInfo090x2() { + super(); + } + + public HRegionInfo090x2(final byte[] tableName) { + this(tableName, null, null); + } + + /** + * Construct HRegionInfo with explicit parameters + * + * @param tableName the table name + * @param startKey first key in region + * @param endKey end of key range + * @throws IllegalArgumentException + */ + public HRegionInfo090x2(final byte[] tableName, final byte[] startKey, + final byte[] endKey) + throws IllegalArgumentException { + this(tableName, startKey, endKey, false); + } + + + /** + * Construct HRegionInfo with explicit parameters + * + * @param tableName the table descriptor + * @param startKey first key in region + * @param endKey end of key range + * @param split true if this region has split and we have daughter regions + * regions that may or may not hold references to this region. + * @throws IllegalArgumentException + */ + public HRegionInfo090x2(final byte[] tableName, final byte[] startKey, + final byte[] endKey, final boolean split) + throws IllegalArgumentException { + this(tableName, startKey, endKey, split, System.currentTimeMillis()); + } + + + /** + * Construct HRegionInfo with explicit parameters + * + * @param tableName the table descriptor + * @param startKey first key in region + * @param endKey end of key range + * @param split true if this region has split and we have daughter regions + * regions that may or may not hold references to this region. + * @param regionid Region id to use. + * @throws IllegalArgumentException + */ + public HRegionInfo090x2(final byte[] tableName, final byte[] startKey, + final byte[] endKey, final boolean split, final long regionid) + throws IllegalArgumentException { + + super(); + if (tableName == null) { + throw new IllegalArgumentException("tableName cannot be null"); + } + this.tableName = tableName.clone(); + this.offLine = false; + this.regionId = regionid; + + this.regionName = createRegionName(this.tableName, startKey, regionId, true); + + this.regionNameStr = Bytes.toStringBinary(this.regionName); + this.split = split; + this.endKey = endKey == null? HConstants.EMPTY_END_ROW: endKey.clone(); + this.startKey = startKey == null? + HConstants.EMPTY_START_ROW: startKey.clone(); + this.tableName = tableName.clone(); + setHashCode(); + } + + /** + * Costruct a copy of another HRegionInfo + * + * @param other + */ + public HRegionInfo090x2(HRegionInfo090x2 other) { + super(); + this.endKey = other.getEndKey(); + this.offLine = other.isOffline(); + this.regionId = other.getRegionId(); + this.regionName = other.getRegionName(); + this.regionNameStr = Bytes.toStringBinary(this.regionName); + this.split = other.isSplit(); + this.startKey = other.getStartKey(); + this.hashCode = other.hashCode(); + this.encodedName = other.getEncodedName(); + this.tableName = other.tableName; + } + + + /** + * Make a region name of passed parameters. + * @param tableName + * @param startKey Can be null + * @param regionid Region id (Usually timestamp from when region was created). + * @param newFormat should we create the region name in the new format + * (such that it contains its encoded name?). + * @return Region name made of passed tableName, startKey and id + */ + public static byte [] createRegionName(final byte [] tableName, + final byte [] startKey, final long regionid, boolean newFormat) { + return createRegionName(tableName, startKey, Long.toString(regionid), newFormat); + } + + /** + * Make a region name of passed parameters. + * @param tableName + * @param startKey Can be null + * @param id Region id (Usually timestamp from when region was created). + * @param newFormat should we create the region name in the new format + * (such that it contains its encoded name?). + * @return Region name made of passed tableName, startKey and id + */ + public static byte [] createRegionName(final byte [] tableName, + final byte [] startKey, final String id, boolean newFormat) { + return createRegionName(tableName, startKey, Bytes.toBytes(id), newFormat); + } + + /** + * Make a region name of passed parameters. + * @param tableName + * @param startKey Can be null + * @param id Region id (Usually timestamp from when region was created). + * @param newFormat should we create the region name in the new format + * (such that it contains its encoded name?). + * @return Region name made of passed tableName, startKey and id + */ + public static byte [] createRegionName(final byte [] tableName, + final byte [] startKey, final byte [] id, boolean newFormat) { + byte [] b = new byte [tableName.length + 2 + id.length + + (startKey == null? 0: startKey.length) + + (newFormat ? (MD5_HEX_LENGTH + 2) : 0)]; + + int offset = tableName.length; + System.arraycopy(tableName, 0, b, 0, offset); + b[offset++] = DELIMITER; + if (startKey != null && startKey.length > 0) { + System.arraycopy(startKey, 0, b, offset, startKey.length); + offset += startKey.length; + } + b[offset++] = DELIMITER; + System.arraycopy(id, 0, b, offset, id.length); + offset += id.length; + + if (newFormat) { + // + // Encoded name should be built into the region name. + // + // Use the region name thus far (namely, ,,) + // to compute a MD5 hash to be used as the encoded name, and append + // it to the byte buffer. + // + String md5Hash = MD5Hash.getMD5AsHex(b, 0, offset); + byte [] md5HashBytes = Bytes.toBytes(md5Hash); + + if (md5HashBytes.length != MD5_HEX_LENGTH) { + LOG.error("MD5-hash length mismatch: Expected=" + MD5_HEX_LENGTH + + "; Got=" + md5HashBytes.length); + } + + // now append the bytes '..' to the end + b[offset++] = ENC_SEPARATOR; + System.arraycopy(md5HashBytes, 0, b, offset, MD5_HEX_LENGTH); + offset += MD5_HEX_LENGTH; + b[offset++] = ENC_SEPARATOR; + } + + return b; + } + + /** + * Gets the table name from the specified region name. + * @param regionName + * @return Table name. + */ + public static byte [] getTableName(byte [] regionName) { + int offset = -1; + for (int i = 0; i < regionName.length; i++) { + if (regionName[i] == DELIMITER) { + offset = i; + break; + } + } + byte [] tableName = new byte[offset]; + System.arraycopy(regionName, 0, tableName, 0, offset); + return tableName; + } + + /** + * Separate elements of a regionName. + * @param regionName + * @return Array of byte[] containing tableName, startKey and id + * @throws IOException + */ + public static byte [][] parseRegionName(final byte [] regionName) + throws IOException { + int offset = -1; + for (int i = 0; i < regionName.length; i++) { + if (regionName[i] == DELIMITER) { + offset = i; + break; + } + } + if(offset == -1) throw new IOException("Invalid regionName format"); + byte [] tableName = new byte[offset]; + System.arraycopy(regionName, 0, tableName, 0, offset); + offset = -1; + for (int i = regionName.length - 1; i > 0; i--) { + if(regionName[i] == DELIMITER) { + offset = i; + break; + } + } + if(offset == -1) throw new IOException("Invalid regionName format"); + byte [] startKey = HConstants.EMPTY_BYTE_ARRAY; + if(offset != tableName.length + 1) { + startKey = new byte[offset - tableName.length - 1]; + System.arraycopy(regionName, tableName.length + 1, startKey, 0, + offset - tableName.length - 1); + } + byte [] id = new byte[regionName.length - offset - 1]; + System.arraycopy(regionName, offset + 1, id, 0, + regionName.length - offset - 1); + byte [][] elements = new byte[3][]; + elements[0] = tableName; + elements[1] = startKey; + elements[2] = id; + return elements; + } + + /** @return the regionId */ + public long getRegionId(){ + return regionId; + } + + /** + * @return the regionName as an array of bytes. + * @see #getRegionNameAsString() + */ + public byte [] getRegionName(){ + return regionName; + } + + /** + * @return Region name as a String for use in logging, etc. + */ + public String getRegionNameAsString() { + if (hasEncodedName(this.regionName)) { + // new format region names already have their encoded name. + return this.regionNameStr; + } + + // old format. regionNameStr doesn't have the region name. + // + // + return this.regionNameStr + "." + this.getEncodedName(); + } + + /** @return the encoded region name */ + public synchronized String getEncodedName() { + if (this.encodedName == NO_HASH) { + this.encodedName = encodeRegionName(this.regionName); + } + return this.encodedName; + } + + public synchronized byte [] getEncodedNameAsBytes() { + if (this.encodedNameAsBytes == null) { + this.encodedNameAsBytes = Bytes.toBytes(getEncodedName()); + } + return this.encodedNameAsBytes; + } + + /** @return the startKey */ + public byte [] getStartKey(){ + return startKey; + } + + /** @return the endKey */ + public byte [] getEndKey(){ + return endKey; + } + + /** + * Get current table name of the region + * @return byte array of table name + */ + public byte[] getTableName() { + if (tableName == null || tableName.length == 0) { + tableName = getTableName(getRegionName()); + } + return tableName; + } + + /** + * Get current table name as string + * @return string representation of current table + */ + public String getTableNameAsString() { + return Bytes.toString(tableName); + } + + /** + * Returns true if the given inclusive range of rows is fully contained + * by this region. For example, if the region is foo,a,g and this is + * passed ["b","c"] or ["a","c"] it will return true, but if this is passed + * ["b","z"] it will return false. + * @throws IllegalArgumentException if the range passed is invalid (ie end < start) + */ + public boolean containsRange(byte[] rangeStartKey, byte[] rangeEndKey) { + if (Bytes.compareTo(rangeStartKey, rangeEndKey) > 0) { + throw new IllegalArgumentException( + "Invalid range: " + Bytes.toStringBinary(rangeStartKey) + + " > " + Bytes.toStringBinary(rangeEndKey)); + } + + boolean firstKeyInRange = Bytes.compareTo(rangeStartKey, startKey) >= 0; + boolean lastKeyInRange = + Bytes.compareTo(rangeEndKey, endKey) < 0 || + Bytes.equals(endKey, HConstants.EMPTY_BYTE_ARRAY); + return firstKeyInRange && lastKeyInRange; + } + + /** + * Return true if the given row falls in this region. + */ + public boolean containsRow(byte[] row) { + return Bytes.compareTo(row, startKey) >= 0 && + (Bytes.compareTo(row, endKey) < 0 || + Bytes.equals(endKey, HConstants.EMPTY_BYTE_ARRAY)); + } + + /** + * @return the tableDesc + * @deprecated Do not use; expensive call + * use HRegionInfo.getTableNameAsString() in place of + * HRegionInfo.getTableDesc().getNameAsString() + */ + @Deprecated + public HTableDescriptor getTableDesc() { + Configuration c = HBaseConfiguration.create(); + FileSystem fs; + try { + fs = FileSystem.get(c); + } catch (IOException e) { + throw new RuntimeException(e); + } + FSTableDescriptors fstd = + new FSTableDescriptors(fs, new Path(c.get(HConstants.HBASE_DIR))); + try { + return fstd.get(this.tableName); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * @param newDesc new table descriptor to use + * @deprecated Do not use; expensive call + */ + @Deprecated + public void setTableDesc(HTableDescriptor newDesc) { + Configuration c = HBaseConfiguration.create(); + FileSystem fs; + try { + fs = FileSystem.get(c); + } catch (IOException e) { + throw new RuntimeException(e); + } + FSTableDescriptors fstd = + new FSTableDescriptors(fs, new Path(c.get(HConstants.HBASE_DIR))); + try { + fstd.add(newDesc); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** @return true if this is the root region */ + public boolean isRootRegion() { + return Bytes.equals(tableName, HRegionInfo090x2.ROOT_REGIONINFO.getTableName()); + } + + /** @return true if this region is from a table that is a meta table, + * either .META. or -ROOT- + */ + public boolean isMetaTable() { + return isRootRegion() || isMetaRegion(); + } + + /** @return true if this region is a meta region */ + public boolean isMetaRegion() { + return Bytes.equals(tableName, HRegionInfo090x2.FIRST_META_REGIONINFO.getTableName()); + } + + /** + * @return True if has been split and has daughters. + */ + public boolean isSplit() { + return this.split; + } + + /** + * @param split set split status + */ + public void setSplit(boolean split) { + this.split = split; + } + + /** + * @return True if this region is offline. + */ + public boolean isOffline() { + return this.offLine; + } + + /** + * The parent of a region split is offline while split daughters hold + * references to the parent. Offlined regions are closed. + * @param offLine Set online/offline status. + */ + public void setOffline(boolean offLine) { + this.offLine = offLine; + } + + + /** + * @return True if this is a split parent region. + */ + public boolean isSplitParent() { + if (!isSplit()) return false; + if (!isOffline()) { + LOG.warn("Region is split but NOT offline: " + getRegionNameAsString()); + } + return true; + } + + /** + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return "{" + HConstants.NAME + " => '" + + this.regionNameStr + + "', STARTKEY => '" + + Bytes.toStringBinary(this.startKey) + "', ENDKEY => '" + + Bytes.toStringBinary(this.endKey) + + "', ENCODED => " + getEncodedName() + "," + + (isOffline()? " OFFLINE => true,": "") + + (isSplit()? " SPLIT => true,": "") + "}"; + } + + /** + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null) { + return false; + } + if (!(o instanceof HRegionInfo090x2)) { + return false; + } + return this.compareTo((HRegionInfo090x2)o) == 0; + } + + /** + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + return this.hashCode; + } + + /** @return the object version number */ + @Override + public byte getVersion() { + return VERSION; + } + + // + // Writable + // + + @Override + public void write(DataOutput out) throws IOException { + super.write(out); + Bytes.writeByteArray(out, endKey); + out.writeBoolean(offLine); + out.writeLong(regionId); + Bytes.writeByteArray(out, regionName); + out.writeBoolean(split); + Bytes.writeByteArray(out, startKey); + Bytes.writeByteArray(out, tableName); + out.writeInt(hashCode); + } + + @Override + public void readFields(DataInput in) throws IOException { + // Read the single version byte. We don't ask the super class do it + // because freaks out if its not the current classes' version. This method + // can deserialize version 0 and version 1 of HRI. + byte version = in.readByte(); + this.endKey = Bytes.readByteArray(in); + this.offLine = in.readBoolean(); + this.regionId = in.readLong(); + this.regionName = Bytes.readByteArray(in); + this.regionNameStr = Bytes.toStringBinary(this.regionName); + this.split = in.readBoolean(); + this.startKey = Bytes.readByteArray(in); + this.tableName = Bytes.readByteArray(in); + this.hashCode = in.readInt(); + } + + // + // Comparable + // + + public int compareTo(HRegionInfo090x2 o) { + if (o == null) { + return 1; + } + + // Are regions of same table? + int result = Bytes.compareTo(this.tableName, o.tableName); + if (result != 0) { + return result; + } + + // Compare start keys. + result = Bytes.compareTo(this.startKey, o.startKey); + if (result != 0) { + return result; + } + + // Compare end keys. + result = Bytes.compareTo(this.endKey, o.endKey); + + if (result != 0) { + if (this.getStartKey().length != 0 + && this.getEndKey().length == 0) { + return 1; // this is last region + } + if (o.getStartKey().length != 0 + && o.getEndKey().length == 0) { + return -1; // o is the last region + } + return result; + } + if (this.offLine == o.offLine) + return 0; + if (this.offLine == true) return -1; + + return 1; + } + + /** + * @return Comparator to use comparing {@link KeyValue}s. + */ + public KVComparator getComparator() { + return isRootRegion()? KeyValue.ROOT_COMPARATOR: isMetaRegion()? + KeyValue.META_COMPARATOR: KeyValue.COMPARATOR; + } +} diff --git src/main/java/org/apache/hadoop/hbase/regionserver/GetClosestRowBeforeTracker.java src/main/java/org/apache/hadoop/hbase/regionserver/GetClosestRowBeforeTracker.java deleted file mode 100644 index 8174cf5..0000000 --- src/main/java/org/apache/hadoop/hbase/regionserver/GetClosestRowBeforeTracker.java +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright 2009 The Apache Software Foundation - * - * 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.hadoop.hbase.regionserver; - -import java.util.NavigableMap; -import java.util.NavigableSet; -import java.util.TreeMap; -import java.util.TreeSet; - -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.hbase.HRegionInfo; -import org.apache.hadoop.hbase.KeyValue; -import org.apache.hadoop.hbase.KeyValue.KVComparator; -import org.apache.hadoop.hbase.util.Bytes; - -/** - * State and utility processing {@link HRegion#getClosestRowBefore(byte[], byte[])}. - * Like {@link ScanDeleteTracker} and {@link ScanDeleteTracker} but does not - * implement the {@link DeleteTracker} interface since state spans rows (There - * is no update nor reset method). - */ -@InterfaceAudience.Private -class GetClosestRowBeforeTracker { - private final KeyValue targetkey; - // Any cell w/ a ts older than this is expired. - private final long oldestts; - private KeyValue candidate = null; - private final KVComparator kvcomparator; - // Flag for whether we're doing getclosest on a metaregion. - private final boolean metaregion; - // Offset and length into targetkey demarking table name (if in a metaregion). - private final int rowoffset; - private final int tablenamePlusDelimiterLength; - - // Deletes keyed by row. Comparator compares on row portion of KeyValue only. - private final NavigableMap> deletes; - - /** - * @param c - * @param kv Presume first on row: i.e. empty column, maximum timestamp and - * a type of Type.Maximum - * @param ttl Time to live in ms for this Store - * @param metaregion True if this is .META. or -ROOT- region. - */ - GetClosestRowBeforeTracker(final KVComparator c, final KeyValue kv, - final long ttl, final boolean metaregion) { - super(); - this.metaregion = metaregion; - this.targetkey = kv; - // If we are in a metaregion, then our table name is the prefix on the - // targetkey. - this.rowoffset = kv.getRowOffset(); - int l = -1; - if (metaregion) { - l = KeyValue.getDelimiter(kv.getBuffer(), rowoffset, kv.getRowLength(), - HRegionInfo.DELIMITER) - this.rowoffset; - } - this.tablenamePlusDelimiterLength = metaregion? l + 1: -1; - this.oldestts = System.currentTimeMillis() - ttl; - this.kvcomparator = c; - KeyValue.RowComparator rc = new KeyValue.RowComparator(this.kvcomparator); - this.deletes = new TreeMap>(rc); - } - - /** - * @param kv - * @return True if this kv is expired. - */ - boolean isExpired(final KeyValue kv) { - return Store.isExpired(kv, this.oldestts); - } - - /* - * Add the specified KeyValue to the list of deletes. - * @param kv - */ - private void addDelete(final KeyValue kv) { - NavigableSet rowdeletes = this.deletes.get(kv); - if (rowdeletes == null) { - rowdeletes = new TreeSet(this.kvcomparator); - this.deletes.put(kv, rowdeletes); - } - rowdeletes.add(kv); - } - - /* - * @param kv Adds candidate if nearer the target than previous candidate. - * @return True if updated candidate. - */ - private boolean addCandidate(final KeyValue kv) { - if (!isDeleted(kv) && isBetterCandidate(kv)) { - this.candidate = kv; - return true; - } - return false; - } - - boolean isBetterCandidate(final KeyValue contender) { - return this.candidate == null || - (this.kvcomparator.compareRows(this.candidate, contender) < 0 && - this.kvcomparator.compareRows(contender, this.targetkey) <= 0); - } - - /* - * Check if specified KeyValue buffer has been deleted by a previously - * seen delete. - * @param kv - * @return true is the specified KeyValue is deleted, false if not - */ - private boolean isDeleted(final KeyValue kv) { - if (this.deletes.isEmpty()) return false; - NavigableSet rowdeletes = this.deletes.get(kv); - if (rowdeletes == null || rowdeletes.isEmpty()) return false; - return isDeleted(kv, rowdeletes); - } - - /** - * Check if the specified KeyValue buffer has been deleted by a previously - * seen delete. - * @param kv - * @param ds - * @return True is the specified KeyValue is deleted, false if not - */ - public boolean isDeleted(final KeyValue kv, final NavigableSet ds) { - if (deletes == null || deletes.isEmpty()) return false; - for (KeyValue d: ds) { - long kvts = kv.getTimestamp(); - long dts = d.getTimestamp(); - if (d.isDeleteFamily()) { - if (kvts <= dts) return true; - continue; - } - // Check column - int ret = Bytes.compareTo(kv.getBuffer(), kv.getQualifierOffset(), - kv.getQualifierLength(), - d.getBuffer(), d.getQualifierOffset(), d.getQualifierLength()); - if (ret <= -1) { - // This delete is for an earlier column. - continue; - } else if (ret >= 1) { - // Beyond this kv. - break; - } - // Check Timestamp - if (kvts > dts) return false; - - // Check Type - switch (KeyValue.Type.codeToType(d.getType())) { - case Delete: return kvts == dts; - case DeleteColumn: return true; - default: continue; - } - } - return false; - } - - /* - * Handle keys whose values hold deletes. - * Add to the set of deletes and then if the candidate keys contain any that - * might match, then check for a match and remove it. Implies candidates - * is made with a Comparator that ignores key type. - * @param kv - * @return True if we removed k from candidates. - */ - boolean handleDeletes(final KeyValue kv) { - addDelete(kv); - boolean deleted = false; - if (!hasCandidate()) return deleted; - if (isDeleted(this.candidate)) { - this.candidate = null; - deleted = true; - } - return deleted; - } - - /** - * Do right thing with passed key, add to deletes or add to candidates. - * @param kv - * @return True if we added a candidate - */ - boolean handle(final KeyValue kv) { - if (kv.isDelete()) { - handleDeletes(kv); - return false; - } - return addCandidate(kv); - } - - /** - * @return True if has candidate - */ - public boolean hasCandidate() { - return this.candidate != null; - } - - /** - * @return Best candidate or null. - */ - public KeyValue getCandidate() { - return this.candidate; - } - - public KeyValue getTargetKey() { - return this.targetkey; - } - - /** - * @param kv Current kv - * @param First on row kv. - * @param state - * @return True if we went too far, past the target key. - */ - boolean isTooFar(final KeyValue kv, final KeyValue firstOnRow) { - return this.kvcomparator.compareRows(kv, firstOnRow) > 0; - } - - boolean isTargetTable(final KeyValue kv) { - if (!metaregion) return true; - // Compare start of keys row. Compare including delimiter. Saves having - // to calculate where tablename ends in the candidate kv. - return Bytes.compareTo(this.targetkey.getBuffer(), this.rowoffset, - this.tablenamePlusDelimiterLength, - kv.getBuffer(), kv.getRowOffset(), this.tablenamePlusDelimiterLength) == 0; - } -} \ No newline at end of file diff --git src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java index 7ab3e61..19c9eab 100644 --- src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java +++ src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java @@ -1533,62 +1533,6 @@ public class HRegion implements HeapSize { // , Writable{ // get() methods for client use. ////////////////////////////////////////////////////////////////////////////// /** - * Return all the data for the row that matches row exactly, - * or the one that immediately preceeds it, at or immediately before - * ts. - * - * @param row row key - * @return map of values - * @throws IOException - */ - Result getClosestRowBefore(final byte [] row) - throws IOException{ - return getClosestRowBefore(row, HConstants.CATALOG_FAMILY); - } - - /** - * Return all the data for the row that matches row exactly, - * or the one that immediately preceeds it, at or immediately before - * ts. - * - * @param row row key - * @param family column family to find on - * @return map of values - * @throws IOException read exceptions - */ - public Result getClosestRowBefore(final byte [] row, final byte [] family) - throws IOException { - if (coprocessorHost != null) { - Result result = new Result(); - if (coprocessorHost.preGetClosestRowBefore(row, family, result)) { - return result; - } - } - // look across all the HStores for this region and determine what the - // closest key is across all column families, since the data may be sparse - checkRow(row, "getClosestRowBefore"); - startRegionOperation(); - this.readRequestsCount.increment(); - try { - Store store = getStore(family); - // get the closest key. (HStore.getRowKeyAtOrBefore can return null) - KeyValue key = store.getRowKeyAtOrBefore(row); - Result result = null; - if (key != null) { - Get get = new Get(key.getRow()); - get.addFamily(family); - result = get(get, null); - } - if (coprocessorHost != null) { - coprocessorHost.postGetClosestRowBefore(row, family, result); - } - return result; - } finally { - closeRegionOperation(); - } - } - - /** * Return an iterator that scans over the HRegion, returning the indicated * columns and rows specified by the {@link Scan}. *

@@ -3143,6 +3087,7 @@ public class HRegion implements HeapSize { // , Writable{ byte[] familyName = p.getFirst(); String path = p.getSecond(); + Store store = getStore(familyName); if (store == null) { IOException ioe = new DoNotRetryIOException( diff --git src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java index 61a5988..5a9a3b0 100644 --- src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java +++ src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java @@ -1783,22 +1783,6 @@ public class HRegionServer extends RegionServer return getRegion(regionName).getRegionInfo(); } - public Result getClosestRowBefore(final byte[] regionName, final byte[] row, - final byte[] family) throws IOException { - checkOpen(); - requestCount.incrementAndGet(); - try { - // locate the region we're operating on - HRegion region = getRegion(regionName); - // ask the region for all the data - - Result r = region.getClosestRowBefore(row, family); - return r; - } catch (Throwable t) { - throw convertThrowableToIOE(cleanup(t)); - } - } - /** {@inheritDoc} */ public Result get(byte[] regionName, Get get) throws IOException { checkOpen(); diff --git src/main/java/org/apache/hadoop/hbase/regionserver/MemStore.java src/main/java/org/apache/hadoop/hbase/regionserver/MemStore.java index 0592f40..08c346a 100644 --- src/main/java/org/apache/hadoop/hbase/regionserver/MemStore.java +++ src/main/java/org/apache/hadoop/hbase/regionserver/MemStore.java @@ -354,88 +354,6 @@ public class MemStore implements HeapSize { } /** - * @param state column/delete tracking state - */ - void getRowKeyAtOrBefore(final GetClosestRowBeforeTracker state) { - this.lock.readLock().lock(); - try { - getRowKeyAtOrBefore(kvset, state); - getRowKeyAtOrBefore(snapshot, state); - } finally { - this.lock.readLock().unlock(); - } - } - - /* - * @param set - * @param state Accumulates deletes and candidates. - */ - private void getRowKeyAtOrBefore(final NavigableSet set, - final GetClosestRowBeforeTracker state) { - if (set.isEmpty()) { - return; - } - if (!walkForwardInSingleRow(set, state.getTargetKey(), state)) { - // Found nothing in row. Try backing up. - getRowKeyBefore(set, state); - } - } - - /* - * Walk forward in a row from firstOnRow. Presumption is that - * we have been passed the first possible key on a row. As we walk forward - * we accumulate deletes until we hit a candidate on the row at which point - * we return. - * @param set - * @param firstOnRow First possible key on this row. - * @param state - * @return True if we found a candidate walking this row. - */ - private boolean walkForwardInSingleRow(final SortedSet set, - final KeyValue firstOnRow, final GetClosestRowBeforeTracker state) { - boolean foundCandidate = false; - SortedSet tail = set.tailSet(firstOnRow); - if (tail.isEmpty()) return foundCandidate; - for (Iterator i = tail.iterator(); i.hasNext();) { - KeyValue kv = i.next(); - // Did we go beyond the target row? If so break. - if (state.isTooFar(kv, firstOnRow)) break; - if (state.isExpired(kv)) { - i.remove(); - continue; - } - // If we added something, this row is a contender. break. - if (state.handle(kv)) { - foundCandidate = true; - break; - } - } - return foundCandidate; - } - - /* - * Walk backwards through the passed set a row at a time until we run out of - * set or until we get a candidate. - * @param set - * @param state - */ - private void getRowKeyBefore(NavigableSet set, - final GetClosestRowBeforeTracker state) { - KeyValue firstOnRow = state.getTargetKey(); - for (Member p = memberOfPreviousRow(set, state, firstOnRow); - p != null; p = memberOfPreviousRow(p.set, state, firstOnRow)) { - // Make sure we don't fall out of our table. - if (!state.isTargetTable(p.kv)) break; - // Stop looking if we've exited the better candidate range. - if (!state.isBetterCandidate(p.kv)) break; - // Make into firstOnRow - firstOnRow = new KeyValue(p.kv.getRow(), HConstants.LATEST_TIMESTAMP); - // If we find something, break; - if (walkForwardInSingleRow(p.set, firstOnRow, state)) break; - } - } - - /** * Given the specs of a column, update it, first by inserting a new record, * then removing the old one. Since there is only 1 KeyValue involved, the memstoreTS * will be set to 0, thus ensuring that they instantly appear to anyone. The underlying @@ -610,29 +528,6 @@ public class MemStore implements HeapSize { } } - /* - * @param set Set to walk back in. Pass a first in row or we'll return - * same row (loop). - * @param state Utility and context. - * @param firstOnRow First item on the row after the one we want to find a - * member in. - * @return Null or member of row previous to firstOnRow - */ - private Member memberOfPreviousRow(NavigableSet set, - final GetClosestRowBeforeTracker state, final KeyValue firstOnRow) { - NavigableSet head = set.headSet(firstOnRow, false); - if (head.isEmpty()) return null; - for (Iterator i = head.descendingIterator(); i.hasNext();) { - KeyValue found = i.next(); - if (state.isExpired(found)) { - i.remove(); - continue; - } - return new Member(head, found); - } - return null; - } - /** * @return scanner on memstore and snapshot in this order. */ diff --git src/main/java/org/apache/hadoop/hbase/regionserver/RegionCoprocessorHost.java src/main/java/org/apache/hadoop/hbase/regionserver/RegionCoprocessorHost.java index a3850e5..34143a4 100644 --- src/main/java/org/apache/hadoop/hbase/regionserver/RegionCoprocessorHost.java +++ src/main/java/org/apache/hadoop/hbase/regionserver/RegionCoprocessorHost.java @@ -484,60 +484,6 @@ public class RegionCoprocessorHost // RegionObserver support /** - * @param row the row key - * @param family the family - * @param result the result set from the region - * @return true if default processing should be bypassed - * @exception IOException Exception - */ - public boolean preGetClosestRowBefore(final byte[] row, final byte[] family, - final Result result) throws IOException { - boolean bypass = false; - ObserverContext ctx = null; - for (RegionEnvironment env: coprocessors) { - if (env.getInstance() instanceof RegionObserver) { - ctx = ObserverContext.createAndPrepare(env, ctx); - try { - ((RegionObserver)env.getInstance()).preGetClosestRowBefore(ctx, row, - family, result); - } catch (Throwable e) { - handleCoprocessorThrowable(env, e); - } - bypass |= ctx.shouldBypass(); - if (ctx.shouldComplete()) { - break; - } - } - } - return bypass; - } - - /** - * @param row the row key - * @param family the family - * @param result the result set from the region - * @exception IOException Exception - */ - public void postGetClosestRowBefore(final byte[] row, final byte[] family, - final Result result) throws IOException { - ObserverContext ctx = null; - for (RegionEnvironment env: coprocessors) { - if (env.getInstance() instanceof RegionObserver) { - ctx = ObserverContext.createAndPrepare(env, ctx); - try { - ((RegionObserver)env.getInstance()).postGetClosestRowBefore(ctx, row, - family, result); - } catch (Throwable e) { - handleCoprocessorThrowable(env, e); - } - if (ctx.shouldComplete()) { - break; - } - } - } - } - - /** * @param get the Get request * @return true if default processing should be bypassed * @exception IOException Exception diff --git src/main/java/org/apache/hadoop/hbase/regionserver/Store.java src/main/java/org/apache/hadoop/hbase/regionserver/Store.java index bf1618e..c9f8f2a 100644 --- src/main/java/org/apache/hadoop/hbase/regionserver/Store.java +++ src/main/java/org/apache/hadoop/hbase/regionserver/Store.java @@ -1628,99 +1628,6 @@ public class Store extends SchemaConfigured implements HeapSize { return key.getTimestamp() < oldestTimestamp; } - /** - * Find the key that matches row exactly, or the one that immediately - * precedes it. WARNING: Only use this method on a table where writes occur - * with strictly increasing timestamps. This method assumes this pattern of - * writes in order to make it reasonably performant. Also our search is - * dependent on the axiom that deletes are for cells that are in the container - * that follows whether a memstore snapshot or a storefile, not for the - * current container: i.e. we'll see deletes before we come across cells we - * are to delete. Presumption is that the memstore#kvset is processed before - * memstore#snapshot and so on. - * @param row The row key of the targeted row. - * @return Found keyvalue or null if none found. - * @throws IOException - */ - KeyValue getRowKeyAtOrBefore(final byte[] row) throws IOException { - // If minVersions is set, we will not ignore expired KVs. - // As we're only looking for the latest matches, that should be OK. - // With minVersions > 0 we guarantee that any KV that has any version - // at all (expired or not) has at least one version that will not expire. - // Note that this method used to take a KeyValue as arguments. KeyValue - // can be back-dated, a row key cannot. - long ttlToUse = scanInfo.getMinVersions() > 0 ? Long.MAX_VALUE : this.ttl; - - KeyValue kv = new KeyValue(row, HConstants.LATEST_TIMESTAMP); - - GetClosestRowBeforeTracker state = new GetClosestRowBeforeTracker( - this.comparator, kv, ttlToUse, this.region.getRegionInfo().isMetaRegion()); - this.lock.readLock().lock(); - try { - // First go to the memstore. Pick up deletes and candidates. - this.memstore.getRowKeyAtOrBefore(state); - // Check if match, if we got a candidate on the asked for 'kv' row. - // Process each store file. Run through from newest to oldest. - for (StoreFile sf : Lists.reverse(storefiles)) { - // Update the candidate keys from the current map file - rowAtOrBeforeFromStoreFile(sf, state); - } - return state.getCandidate(); - } finally { - this.lock.readLock().unlock(); - } - } - - /* - * Check an individual MapFile for the row at or before a given row. - * @param f - * @param state - * @throws IOException - */ - private void rowAtOrBeforeFromStoreFile(final StoreFile f, - final GetClosestRowBeforeTracker state) - throws IOException { - StoreFile.Reader r = f.getReader(); - if (r == null) { - LOG.warn("StoreFile " + f + " has a null Reader"); - return; - } - // TODO: Cache these keys rather than make each time? - byte [] fk = r.getFirstKey(); - KeyValue firstKV = KeyValue.createKeyValueFromKey(fk, 0, fk.length); - byte [] lk = r.getLastKey(); - KeyValue lastKV = KeyValue.createKeyValueFromKey(lk, 0, lk.length); - KeyValue firstOnRow = state.getTargetKey(); - if (this.comparator.compareRows(lastKV, firstOnRow) < 0) { - // If last key in file is not of the target table, no candidates in this - // file. Return. - if (!state.isTargetTable(lastKV)) return; - // If the row we're looking for is past the end of file, set search key to - // last key. TODO: Cache last and first key rather than make each time. - firstOnRow = new KeyValue(lastKV.getRow(), HConstants.LATEST_TIMESTAMP); - } - // Get a scanner that caches blocks and that uses pread. - HFileScanner scanner = r.getHFileReader().getScanner(true, true, false); - // Seek scanner. If can't seek it, return. - if (!seekToScanner(scanner, firstOnRow, firstKV)) return; - // If we found candidate on firstOnRow, just return. THIS WILL NEVER HAPPEN! - // Unlikely that there'll be an instance of actual first row in table. - if (walkForwardInSingleRow(scanner, firstOnRow, state)) return; - // If here, need to start backing up. - while (scanner.seekBefore(firstOnRow.getBuffer(), firstOnRow.getKeyOffset(), - firstOnRow.getKeyLength())) { - KeyValue kv = scanner.getKeyValue(); - if (!state.isTargetTable(kv)) break; - if (!state.isBetterCandidate(kv)) break; - // Make new first on row. - firstOnRow = new KeyValue(kv.getRow(), HConstants.LATEST_TIMESTAMP); - // Seek scanner. If can't seek it, break. - if (!seekToScanner(scanner, firstOnRow, firstKV)) break; - // If we find something, break; - if (walkForwardInSingleRow(scanner, firstOnRow, state)) break; - } - } - /* * Seek the file scanner to firstOnRow or first entry in file. * @param scanner @@ -1741,39 +1648,6 @@ public class Store extends SchemaConfigured implements HeapSize { return result >= 0; } - /* - * When we come in here, we are probably at the kv just before we break into - * the row that firstOnRow is on. Usually need to increment one time to get - * on to the row we are interested in. - * @param scanner - * @param firstOnRow - * @param state - * @return True we found a candidate. - * @throws IOException - */ - private boolean walkForwardInSingleRow(final HFileScanner scanner, - final KeyValue firstOnRow, - final GetClosestRowBeforeTracker state) - throws IOException { - boolean foundCandidate = false; - do { - KeyValue kv = scanner.getKeyValue(); - // If we are not in the row, skip. - if (this.comparator.compareRows(kv, firstOnRow) < 0) continue; - // Did we go beyond the target row? If so break. - if (state.isTooFar(kv, firstOnRow)) break; - if (state.isExpired(kv)) { - continue; - } - // If we added something, this row is a contender. break. - if (state.handle(kv)) { - foundCandidate = true; - break; - } - } while(scanner.next()); - return foundCandidate; - } - public boolean canSplit() { this.lock.readLock().lock(); try { diff --git src/main/java/org/apache/hadoop/hbase/rest/StorageClusterStatusResource.java src/main/java/org/apache/hadoop/hbase/rest/StorageClusterStatusResource.java index 59a791d..67f2c2d 100644 --- src/main/java/org/apache/hadoop/hbase/rest/StorageClusterStatusResource.java +++ src/main/java/org/apache/hadoop/hbase/rest/StorageClusterStatusResource.java @@ -87,11 +87,7 @@ public class StorageClusterStatusResource extends ResourceBase { for (HServerLoad.RegionLoad region: load.getRegionsLoad().values()) { node.addRegion(region.getName(), region.getStores(), region.getStorefiles(), region.getStorefileSizeMB(), - region.getMemStoreSizeMB(), region.getStorefileIndexSizeMB(), - region.getReadRequestsCount(), region.getWriteRequestsCount(), - region.getRootIndexSizeKB(), region.getTotalStaticIndexSizeKB(), - region.getTotalStaticBloomSizeKB(), region.getTotalCompactingKVs(), - region.getCurrentCompactedKVs()); + region.getMemStoreSizeMB(), region.getStorefileIndexSizeMB()); } } for (ServerName name: status.getDeadServerNames()) { diff --git src/main/java/org/apache/hadoop/hbase/rest/client/RemoteHTable.java src/main/java/org/apache/hadoop/hbase/rest/client/RemoteHTable.java index ccfe878..3e95f8e 100644 --- src/main/java/org/apache/hadoop/hbase/rest/client/RemoteHTable.java +++ src/main/java/org/apache/hadoop/hbase/rest/client/RemoteHTable.java @@ -575,10 +575,6 @@ public class RemoteHTable implements HTableInterface { return true; } - public Result getRowOrBefore(byte[] row, byte[] family) throws IOException { - throw new IOException("getRowOrBefore not supported"); - } - public RowLock lockRow(byte[] row) throws IOException { throw new IOException("lockRow not implemented"); } diff --git src/main/java/org/apache/hadoop/hbase/rest/model/StorageClusterStatusModel.java src/main/java/org/apache/hadoop/hbase/rest/model/StorageClusterStatusModel.java index 5072221..2ce6133 100644 --- src/main/java/org/apache/hadoop/hbase/rest/model/StorageClusterStatusModel.java +++ src/main/java/org/apache/hadoop/hbase/rest/model/StorageClusterStatusModel.java @@ -83,13 +83,6 @@ import com.google.protobuf.ByteString; * <attribute name="storefileSizeMB" type="int"></attribute> * <attribute name="memstoreSizeMB" type="int"></attribute> * <attribute name="storefileIndexSizeMB" type="int"></attribute> - * <attribute name="readRequestsCount" type="int"></attribute> - * <attribute name="writeRequestsCount" type="int"></attribute> - * <attribute name="rootIndexSizeKB" type="int"></attribute> - * <attribute name="totalStaticIndexSizeKB" type="int"></attribute> - * <attribute name="totalStaticBloomSizeKB" type="int"></attribute> - * <attribute name="totalCompactingKVs" type="int"></attribute> - * <attribute name="currentCompactedKVs" type="int"></attribute> * </complexType> * */ @@ -114,13 +107,6 @@ public class StorageClusterStatusModel private int storefileSizeMB; private int memstoreSizeMB; private int storefileIndexSizeMB; - private long readRequestsCount; - private long writeRequestsCount; - private int rootIndexSizeKB; - private int totalStaticIndexSizeKB; - private int totalStaticBloomSizeKB; - private long totalCompactingKVs; - private long currentCompactedKVs; /** * Default constructor @@ -145,23 +131,13 @@ public class StorageClusterStatusModel * @param storefileIndexSizeMB total size of store file indexes, in MB */ public Region(byte[] name, int stores, int storefiles, - int storefileSizeMB, int memstoreSizeMB, int storefileIndexSizeMB, - long readRequestsCount, long writeRequestsCount, int rootIndexSizeKB, - int totalStaticIndexSizeKB, int totalStaticBloomSizeKB, - long totalCompactingKVs, long currentCompactedKVs) { + int storefileSizeMB, int memstoreSizeMB, int storefileIndexSizeMB) { this.name = name; this.stores = stores; this.storefiles = storefiles; this.storefileSizeMB = storefileSizeMB; this.memstoreSizeMB = memstoreSizeMB; this.storefileIndexSizeMB = storefileIndexSizeMB; - this.readRequestsCount = readRequestsCount; - this.writeRequestsCount = writeRequestsCount; - this.rootIndexSizeKB = rootIndexSizeKB; - this.totalStaticIndexSizeKB = totalStaticIndexSizeKB; - this.totalStaticBloomSizeKB = totalStaticBloomSizeKB; - this.totalCompactingKVs = totalCompactingKVs; - this.currentCompactedKVs = currentCompactedKVs; } /** @@ -211,118 +187,8 @@ public class StorageClusterStatusModel public int getStorefileIndexSizeMB() { return storefileIndexSizeMB; } - - /** - * @return the current total read requests made to region - */ - @XmlAttribute - public long getReadRequestsCount() { - return readRequestsCount; - } - - /** - * @return the current total write requests made to region - */ - @XmlAttribute - public long getWriteRequestsCount() { - return writeRequestsCount; - } - - /** - * @return The current total size of root-level indexes for the region, in KB. - */ - @XmlAttribute - public int getRootIndexSizeKB() { - return rootIndexSizeKB; - } - - /** - * @return The total size of static index, in KB - */ - @XmlAttribute - public int getTotalStaticIndexSizeKB() { - return totalStaticIndexSizeKB; - } - - /** - * @return The total size of static bloom, in KB - */ - @XmlAttribute - public int getTotalStaticBloomSizeKB() { - return totalStaticBloomSizeKB; - } - - /** - * @return The total number of compacting key-values - */ - @XmlAttribute - public long getTotalCompactingKVs() { - return totalCompactingKVs; - } /** - * @return The number of current compacted key-values - */ - @XmlAttribute - public long getCurrentCompactedKVs() { - return currentCompactedKVs; - } - - /** - * @param readRequestsCount The current total read requests made to region - */ - public void setReadRequestsCount(long readRequestsCount) { - this.readRequestsCount = readRequestsCount; - } - - /** - * @param rootIndexSizeKB The current total size of root-level indexes - * for the region, in KB - */ - public void setRootIndexSizeKB(int rootIndexSizeKB) { - this.rootIndexSizeKB = rootIndexSizeKB; - } - - /** - * @param writeRequestsCount The current total write requests made to region - */ - public void setWriteRequestsCount(long writeRequestsCount) { - this.writeRequestsCount = writeRequestsCount; - } - - /** - * @param currentCompactedKVs The completed count of key values - * in currently running compaction - */ - public void setCurrentCompactedKVs(long currentCompactedKVs) { - this.currentCompactedKVs = currentCompactedKVs; - } - - /** - * @param totalCompactingKVs The total compacting key values - * in currently running compaction - */ - public void setTotalCompactingKVs(long totalCompactingKVs) { - this.totalCompactingKVs = totalCompactingKVs; - } - - /** - * @param totalStaticBloomSizeKB The total size of all Bloom filter blocks, - * not just loaded into the block cache, in KB. - */ - public void setTotalStaticBloomSizeKB(int totalStaticBloomSizeKB) { - this.totalStaticBloomSizeKB = totalStaticBloomSizeKB; - } - - /** - * @param totalStaticIndexSizeKB The total size of all index blocks, - * not just the root level, in KB. - */ - public void setTotalStaticIndexSizeKB(int totalStaticIndexSizeKB) { - this.totalStaticIndexSizeKB = totalStaticIndexSizeKB; - } - - /** * @param name the region name */ public void setName(byte[] name) { @@ -377,14 +243,9 @@ public class StorageClusterStatusModel * @param name the region name */ public void addRegion(byte[] name, int stores, int storefiles, - int storefileSizeMB, int memstoreSizeMB, int storefileIndexSizeMB, - long readRequestsCount, long writeRequestsCount, int rootIndexSizeKB, - int totalStaticIndexSizeKB, int totalStaticBloomSizeKB, - long totalCompactingKVs, long currentCompactedKVs) { + int storefileSizeMB, int memstoreSizeMB, int storefileIndexSizeMB) { regions.add(new Region(name, stores, storefiles, storefileSizeMB, - memstoreSizeMB, storefileIndexSizeMB, readRequestsCount, - writeRequestsCount, rootIndexSizeKB, totalStaticIndexSizeKB, - totalStaticBloomSizeKB, totalCompactingKVs, currentCompactedKVs)); + memstoreSizeMB, storefileIndexSizeMB)); } /** @@ -671,20 +532,6 @@ public class StorageClusterStatusModel sb.append(region.memstoreSizeMB); sb.append("\n storefileIndexSizeMB="); sb.append(region.storefileIndexSizeMB); - sb.append("\n readRequestsCount="); - sb.append(region.readRequestsCount); - sb.append("\n writeRequestsCount="); - sb.append(region.writeRequestsCount); - sb.append("\n rootIndexSizeKB="); - sb.append(region.rootIndexSizeKB); - sb.append("\n totalStaticIndexSizeKB="); - sb.append(region.totalStaticIndexSizeKB); - sb.append("\n totalStaticBloomSizeKB="); - sb.append(region.totalStaticBloomSizeKB); - sb.append("\n totalCompactingKVs="); - sb.append(region.totalCompactingKVs); - sb.append("\n currentCompactedKVs="); - sb.append(region.currentCompactedKVs); sb.append('\n'); } sb.append('\n'); @@ -702,7 +549,7 @@ public class StorageClusterStatusModel } return sb.toString(); } - + @Override public byte[] createProtobufOutput() { StorageClusterStatus.Builder builder = StorageClusterStatus.newBuilder(); @@ -726,13 +573,6 @@ public class StorageClusterStatusModel regionBuilder.setStorefileSizeMB(region.storefileSizeMB); regionBuilder.setMemstoreSizeMB(region.memstoreSizeMB); regionBuilder.setStorefileIndexSizeMB(region.storefileIndexSizeMB); - regionBuilder.setReadRequestsCount(region.readRequestsCount); - regionBuilder.setWriteRequestsCount(region.writeRequestsCount); - regionBuilder.setRootIndexSizeKB(region.rootIndexSizeKB); - regionBuilder.setTotalStaticIndexSizeKB(region.totalStaticIndexSizeKB); - regionBuilder.setTotalStaticBloomSizeKB(region.totalStaticBloomSizeKB); - regionBuilder.setTotalCompactingKVs(region.totalCompactingKVs); - regionBuilder.setCurrentCompactedKVs(region.currentCompactedKVs); nodeBuilder.addRegions(regionBuilder); } builder.addLiveNodes(nodeBuilder); @@ -771,14 +611,7 @@ public class StorageClusterStatusModel region.getStorefiles(), region.getStorefileSizeMB(), region.getMemstoreSizeMB(), - region.getStorefileIndexSizeMB(), - region.getReadRequestsCount(), - region.getWriteRequestsCount(), - region.getRootIndexSizeKB(), - region.getTotalStaticIndexSizeKB(), - region.getTotalStaticBloomSizeKB(), - region.getTotalCompactingKVs(), - region.getCurrentCompactedKVs()); + region.getStorefileIndexSizeMB()); } } for (String node: builder.getDeadNodesList()) { diff --git src/main/java/org/apache/hadoop/hbase/rest/model/TableRegionModel.java src/main/java/org/apache/hadoop/hbase/rest/model/TableRegionModel.java index 3535595..9e16272 100644 --- src/main/java/org/apache/hadoop/hbase/rest/model/TableRegionModel.java +++ src/main/java/org/apache/hadoop/hbase/rest/model/TableRegionModel.java @@ -97,9 +97,11 @@ public class TableRegionModel implements Serializable { public String getName() { byte [] tableNameAsBytes = Bytes.toBytes(this.table); byte [] nameAsBytes = HRegionInfo.createRegionName(tableNameAsBytes, - this.startKey, this.id, - !HTableDescriptor.isMetaTable(tableNameAsBytes)); - return Bytes.toString(nameAsBytes); + this.startKey, + this.endKey, + Long.toString(this.id).getBytes(), + !HTableDescriptor.isMetaTable(tableNameAsBytes)); + return Bytes.toStringBinary(nameAsBytes); } /** @@ -111,6 +113,14 @@ public class TableRegionModel implements Serializable { } /** + * @return the table name + */ + @XmlAttribute + public String getTable() { + return table; + } + + /** * @return the start key */ @XmlAttribute @@ -135,15 +145,10 @@ public class TableRegionModel implements Serializable { } /** - * @param name region printable name + * @param table the table name */ - public void setName(String name) { - String split[] = name.split(","); - this.table = split[0]; - this.startKey = Bytes.toBytes(split[1]); - String tail = split[2]; - split = tail.split("\\."); - id = Long.valueOf(split[0]); + public void setTable(String table) { + this.table = table; } /** @@ -187,6 +192,8 @@ public class TableRegionModel implements Serializable { sb.append(Bytes.toString(startKey)); sb.append("'\n endKey='"); sb.append(Bytes.toString(endKey)); + sb.append("'\n table='"); + sb.append(table); if (location != null) { sb.append("'\n location='"); sb.append(location); diff --git src/main/java/org/apache/hadoop/hbase/rest/protobuf/generated/StorageClusterStatusMessage.java src/main/java/org/apache/hadoop/hbase/rest/protobuf/generated/StorageClusterStatusMessage.java index a6023b9..b20d6d4 100644 --- src/main/java/org/apache/hadoop/hbase/rest/protobuf/generated/StorageClusterStatusMessage.java +++ src/main/java/org/apache/hadoop/hbase/rest/protobuf/generated/StorageClusterStatusMessage.java @@ -92,34 +92,6 @@ public final class StorageClusterStatusMessage { // optional int32 storefileIndexSizeMB = 6; boolean hasStorefileIndexSizeMB(); int getStorefileIndexSizeMB(); - - // optional int64 readRequestsCount = 7; - boolean hasReadRequestsCount(); - long getReadRequestsCount(); - - // optional int64 writeRequestsCount = 8; - boolean hasWriteRequestsCount(); - long getWriteRequestsCount(); - - // optional int32 rootIndexSizeKB = 9; - boolean hasRootIndexSizeKB(); - int getRootIndexSizeKB(); - - // optional int32 totalStaticIndexSizeKB = 10; - boolean hasTotalStaticIndexSizeKB(); - int getTotalStaticIndexSizeKB(); - - // optional int32 totalStaticBloomSizeKB = 11; - boolean hasTotalStaticBloomSizeKB(); - int getTotalStaticBloomSizeKB(); - - // optional int64 totalCompactingKVs = 12; - boolean hasTotalCompactingKVs(); - long getTotalCompactingKVs(); - - // optional int64 currentCompactedKVs = 13; - boolean hasCurrentCompactedKVs(); - long getCurrentCompactedKVs(); } public static final class Region extends com.google.protobuf.GeneratedMessage @@ -210,76 +182,6 @@ public final class StorageClusterStatusMessage { return storefileIndexSizeMB_; } - // optional int64 readRequestsCount = 7; - public static final int READREQUESTSCOUNT_FIELD_NUMBER = 7; - private long readRequestsCount_; - public boolean hasReadRequestsCount() { - return ((bitField0_ & 0x00000040) == 0x00000040); - } - public long getReadRequestsCount() { - return readRequestsCount_; - } - - // optional int64 writeRequestsCount = 8; - public static final int WRITEREQUESTSCOUNT_FIELD_NUMBER = 8; - private long writeRequestsCount_; - public boolean hasWriteRequestsCount() { - return ((bitField0_ & 0x00000080) == 0x00000080); - } - public long getWriteRequestsCount() { - return writeRequestsCount_; - } - - // optional int32 rootIndexSizeKB = 9; - public static final int ROOTINDEXSIZEKB_FIELD_NUMBER = 9; - private int rootIndexSizeKB_; - public boolean hasRootIndexSizeKB() { - return ((bitField0_ & 0x00000100) == 0x00000100); - } - public int getRootIndexSizeKB() { - return rootIndexSizeKB_; - } - - // optional int32 totalStaticIndexSizeKB = 10; - public static final int TOTALSTATICINDEXSIZEKB_FIELD_NUMBER = 10; - private int totalStaticIndexSizeKB_; - public boolean hasTotalStaticIndexSizeKB() { - return ((bitField0_ & 0x00000200) == 0x00000200); - } - public int getTotalStaticIndexSizeKB() { - return totalStaticIndexSizeKB_; - } - - // optional int32 totalStaticBloomSizeKB = 11; - public static final int TOTALSTATICBLOOMSIZEKB_FIELD_NUMBER = 11; - private int totalStaticBloomSizeKB_; - public boolean hasTotalStaticBloomSizeKB() { - return ((bitField0_ & 0x00000400) == 0x00000400); - } - public int getTotalStaticBloomSizeKB() { - return totalStaticBloomSizeKB_; - } - - // optional int64 totalCompactingKVs = 12; - public static final int TOTALCOMPACTINGKVS_FIELD_NUMBER = 12; - private long totalCompactingKVs_; - public boolean hasTotalCompactingKVs() { - return ((bitField0_ & 0x00000800) == 0x00000800); - } - public long getTotalCompactingKVs() { - return totalCompactingKVs_; - } - - // optional int64 currentCompactedKVs = 13; - public static final int CURRENTCOMPACTEDKVS_FIELD_NUMBER = 13; - private long currentCompactedKVs_; - public boolean hasCurrentCompactedKVs() { - return ((bitField0_ & 0x00001000) == 0x00001000); - } - public long getCurrentCompactedKVs() { - return currentCompactedKVs_; - } - private void initFields() { name_ = com.google.protobuf.ByteString.EMPTY; stores_ = 0; @@ -287,13 +189,6 @@ public final class StorageClusterStatusMessage { storefileSizeMB_ = 0; memstoreSizeMB_ = 0; storefileIndexSizeMB_ = 0; - readRequestsCount_ = 0L; - writeRequestsCount_ = 0L; - rootIndexSizeKB_ = 0; - totalStaticIndexSizeKB_ = 0; - totalStaticBloomSizeKB_ = 0; - totalCompactingKVs_ = 0L; - currentCompactedKVs_ = 0L; } private byte memoizedIsInitialized = -1; public final boolean isInitialized() { @@ -329,27 +224,6 @@ public final class StorageClusterStatusMessage { if (((bitField0_ & 0x00000020) == 0x00000020)) { output.writeInt32(6, storefileIndexSizeMB_); } - if (((bitField0_ & 0x00000040) == 0x00000040)) { - output.writeInt64(7, readRequestsCount_); - } - if (((bitField0_ & 0x00000080) == 0x00000080)) { - output.writeInt64(8, writeRequestsCount_); - } - if (((bitField0_ & 0x00000100) == 0x00000100)) { - output.writeInt32(9, rootIndexSizeKB_); - } - if (((bitField0_ & 0x00000200) == 0x00000200)) { - output.writeInt32(10, totalStaticIndexSizeKB_); - } - if (((bitField0_ & 0x00000400) == 0x00000400)) { - output.writeInt32(11, totalStaticBloomSizeKB_); - } - if (((bitField0_ & 0x00000800) == 0x00000800)) { - output.writeInt64(12, totalCompactingKVs_); - } - if (((bitField0_ & 0x00001000) == 0x00001000)) { - output.writeInt64(13, currentCompactedKVs_); - } getUnknownFields().writeTo(output); } @@ -383,34 +257,6 @@ public final class StorageClusterStatusMessage { size += com.google.protobuf.CodedOutputStream .computeInt32Size(6, storefileIndexSizeMB_); } - if (((bitField0_ & 0x00000040) == 0x00000040)) { - size += com.google.protobuf.CodedOutputStream - .computeInt64Size(7, readRequestsCount_); - } - if (((bitField0_ & 0x00000080) == 0x00000080)) { - size += com.google.protobuf.CodedOutputStream - .computeInt64Size(8, writeRequestsCount_); - } - if (((bitField0_ & 0x00000100) == 0x00000100)) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(9, rootIndexSizeKB_); - } - if (((bitField0_ & 0x00000200) == 0x00000200)) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(10, totalStaticIndexSizeKB_); - } - if (((bitField0_ & 0x00000400) == 0x00000400)) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(11, totalStaticBloomSizeKB_); - } - if (((bitField0_ & 0x00000800) == 0x00000800)) { - size += com.google.protobuf.CodedOutputStream - .computeInt64Size(12, totalCompactingKVs_); - } - if (((bitField0_ & 0x00001000) == 0x00001000)) { - size += com.google.protobuf.CodedOutputStream - .computeInt64Size(13, currentCompactedKVs_); - } size += getUnknownFields().getSerializedSize(); memoizedSerializedSize = size; return size; @@ -547,20 +393,6 @@ public final class StorageClusterStatusMessage { bitField0_ = (bitField0_ & ~0x00000010); storefileIndexSizeMB_ = 0; bitField0_ = (bitField0_ & ~0x00000020); - readRequestsCount_ = 0L; - bitField0_ = (bitField0_ & ~0x00000040); - writeRequestsCount_ = 0L; - bitField0_ = (bitField0_ & ~0x00000080); - rootIndexSizeKB_ = 0; - bitField0_ = (bitField0_ & ~0x00000100); - totalStaticIndexSizeKB_ = 0; - bitField0_ = (bitField0_ & ~0x00000200); - totalStaticBloomSizeKB_ = 0; - bitField0_ = (bitField0_ & ~0x00000400); - totalCompactingKVs_ = 0L; - bitField0_ = (bitField0_ & ~0x00000800); - currentCompactedKVs_ = 0L; - bitField0_ = (bitField0_ & ~0x00001000); return this; } @@ -623,34 +455,6 @@ public final class StorageClusterStatusMessage { to_bitField0_ |= 0x00000020; } result.storefileIndexSizeMB_ = storefileIndexSizeMB_; - if (((from_bitField0_ & 0x00000040) == 0x00000040)) { - to_bitField0_ |= 0x00000040; - } - result.readRequestsCount_ = readRequestsCount_; - if (((from_bitField0_ & 0x00000080) == 0x00000080)) { - to_bitField0_ |= 0x00000080; - } - result.writeRequestsCount_ = writeRequestsCount_; - if (((from_bitField0_ & 0x00000100) == 0x00000100)) { - to_bitField0_ |= 0x00000100; - } - result.rootIndexSizeKB_ = rootIndexSizeKB_; - if (((from_bitField0_ & 0x00000200) == 0x00000200)) { - to_bitField0_ |= 0x00000200; - } - result.totalStaticIndexSizeKB_ = totalStaticIndexSizeKB_; - if (((from_bitField0_ & 0x00000400) == 0x00000400)) { - to_bitField0_ |= 0x00000400; - } - result.totalStaticBloomSizeKB_ = totalStaticBloomSizeKB_; - if (((from_bitField0_ & 0x00000800) == 0x00000800)) { - to_bitField0_ |= 0x00000800; - } - result.totalCompactingKVs_ = totalCompactingKVs_; - if (((from_bitField0_ & 0x00001000) == 0x00001000)) { - to_bitField0_ |= 0x00001000; - } - result.currentCompactedKVs_ = currentCompactedKVs_; result.bitField0_ = to_bitField0_; onBuilt(); return result; @@ -685,27 +489,6 @@ public final class StorageClusterStatusMessage { if (other.hasStorefileIndexSizeMB()) { setStorefileIndexSizeMB(other.getStorefileIndexSizeMB()); } - if (other.hasReadRequestsCount()) { - setReadRequestsCount(other.getReadRequestsCount()); - } - if (other.hasWriteRequestsCount()) { - setWriteRequestsCount(other.getWriteRequestsCount()); - } - if (other.hasRootIndexSizeKB()) { - setRootIndexSizeKB(other.getRootIndexSizeKB()); - } - if (other.hasTotalStaticIndexSizeKB()) { - setTotalStaticIndexSizeKB(other.getTotalStaticIndexSizeKB()); - } - if (other.hasTotalStaticBloomSizeKB()) { - setTotalStaticBloomSizeKB(other.getTotalStaticBloomSizeKB()); - } - if (other.hasTotalCompactingKVs()) { - setTotalCompactingKVs(other.getTotalCompactingKVs()); - } - if (other.hasCurrentCompactedKVs()) { - setCurrentCompactedKVs(other.getCurrentCompactedKVs()); - } this.mergeUnknownFields(other.getUnknownFields()); return this; } @@ -771,41 +554,6 @@ public final class StorageClusterStatusMessage { storefileIndexSizeMB_ = input.readInt32(); break; } - case 56: { - bitField0_ |= 0x00000040; - readRequestsCount_ = input.readInt64(); - break; - } - case 64: { - bitField0_ |= 0x00000080; - writeRequestsCount_ = input.readInt64(); - break; - } - case 72: { - bitField0_ |= 0x00000100; - rootIndexSizeKB_ = input.readInt32(); - break; - } - case 80: { - bitField0_ |= 0x00000200; - totalStaticIndexSizeKB_ = input.readInt32(); - break; - } - case 88: { - bitField0_ |= 0x00000400; - totalStaticBloomSizeKB_ = input.readInt32(); - break; - } - case 96: { - bitField0_ |= 0x00000800; - totalCompactingKVs_ = input.readInt64(); - break; - } - case 104: { - bitField0_ |= 0x00001000; - currentCompactedKVs_ = input.readInt64(); - break; - } } } } @@ -941,153 +689,6 @@ public final class StorageClusterStatusMessage { return this; } - // optional int64 readRequestsCount = 7; - private long readRequestsCount_ ; - public boolean hasReadRequestsCount() { - return ((bitField0_ & 0x00000040) == 0x00000040); - } - public long getReadRequestsCount() { - return readRequestsCount_; - } - public Builder setReadRequestsCount(long value) { - bitField0_ |= 0x00000040; - readRequestsCount_ = value; - onChanged(); - return this; - } - public Builder clearReadRequestsCount() { - bitField0_ = (bitField0_ & ~0x00000040); - readRequestsCount_ = 0L; - onChanged(); - return this; - } - - // optional int64 writeRequestsCount = 8; - private long writeRequestsCount_ ; - public boolean hasWriteRequestsCount() { - return ((bitField0_ & 0x00000080) == 0x00000080); - } - public long getWriteRequestsCount() { - return writeRequestsCount_; - } - public Builder setWriteRequestsCount(long value) { - bitField0_ |= 0x00000080; - writeRequestsCount_ = value; - onChanged(); - return this; - } - public Builder clearWriteRequestsCount() { - bitField0_ = (bitField0_ & ~0x00000080); - writeRequestsCount_ = 0L; - onChanged(); - return this; - } - - // optional int32 rootIndexSizeKB = 9; - private int rootIndexSizeKB_ ; - public boolean hasRootIndexSizeKB() { - return ((bitField0_ & 0x00000100) == 0x00000100); - } - public int getRootIndexSizeKB() { - return rootIndexSizeKB_; - } - public Builder setRootIndexSizeKB(int value) { - bitField0_ |= 0x00000100; - rootIndexSizeKB_ = value; - onChanged(); - return this; - } - public Builder clearRootIndexSizeKB() { - bitField0_ = (bitField0_ & ~0x00000100); - rootIndexSizeKB_ = 0; - onChanged(); - return this; - } - - // optional int32 totalStaticIndexSizeKB = 10; - private int totalStaticIndexSizeKB_ ; - public boolean hasTotalStaticIndexSizeKB() { - return ((bitField0_ & 0x00000200) == 0x00000200); - } - public int getTotalStaticIndexSizeKB() { - return totalStaticIndexSizeKB_; - } - public Builder setTotalStaticIndexSizeKB(int value) { - bitField0_ |= 0x00000200; - totalStaticIndexSizeKB_ = value; - onChanged(); - return this; - } - public Builder clearTotalStaticIndexSizeKB() { - bitField0_ = (bitField0_ & ~0x00000200); - totalStaticIndexSizeKB_ = 0; - onChanged(); - return this; - } - - // optional int32 totalStaticBloomSizeKB = 11; - private int totalStaticBloomSizeKB_ ; - public boolean hasTotalStaticBloomSizeKB() { - return ((bitField0_ & 0x00000400) == 0x00000400); - } - public int getTotalStaticBloomSizeKB() { - return totalStaticBloomSizeKB_; - } - public Builder setTotalStaticBloomSizeKB(int value) { - bitField0_ |= 0x00000400; - totalStaticBloomSizeKB_ = value; - onChanged(); - return this; - } - public Builder clearTotalStaticBloomSizeKB() { - bitField0_ = (bitField0_ & ~0x00000400); - totalStaticBloomSizeKB_ = 0; - onChanged(); - return this; - } - - // optional int64 totalCompactingKVs = 12; - private long totalCompactingKVs_ ; - public boolean hasTotalCompactingKVs() { - return ((bitField0_ & 0x00000800) == 0x00000800); - } - public long getTotalCompactingKVs() { - return totalCompactingKVs_; - } - public Builder setTotalCompactingKVs(long value) { - bitField0_ |= 0x00000800; - totalCompactingKVs_ = value; - onChanged(); - return this; - } - public Builder clearTotalCompactingKVs() { - bitField0_ = (bitField0_ & ~0x00000800); - totalCompactingKVs_ = 0L; - onChanged(); - return this; - } - - // optional int64 currentCompactedKVs = 13; - private long currentCompactedKVs_ ; - public boolean hasCurrentCompactedKVs() { - return ((bitField0_ & 0x00001000) == 0x00001000); - } - public long getCurrentCompactedKVs() { - return currentCompactedKVs_; - } - public Builder setCurrentCompactedKVs(long value) { - bitField0_ |= 0x00001000; - currentCompactedKVs_ = value; - onChanged(); - return this; - } - public Builder clearCurrentCompactedKVs() { - bitField0_ = (bitField0_ & ~0x00001000); - currentCompactedKVs_ = 0L; - onChanged(); - return this; - } - // @@protoc_insertion_point(builder_scope:org.apache.hadoop.hbase.rest.protobuf.generated.StorageClusterStatus.Region) } @@ -2811,25 +2412,20 @@ public final class StorageClusterStatusMessage { java.lang.String[] descriptorData = { "\n!StorageClusterStatusMessage.proto\022/org" + ".apache.hadoop.hbase.rest.protobuf.gener" + - "ated\"\333\005\n\024StorageClusterStatus\022]\n\tliveNod" + + "ated\"\222\004\n\024StorageClusterStatus\022]\n\tliveNod" + "es\030\001 \003(\0132J.org.apache.hadoop.hbase.rest." + "protobuf.generated.StorageClusterStatus." + "Node\022\021\n\tdeadNodes\030\002 \003(\t\022\017\n\007regions\030\003 \001(\005" + "\022\020\n\010requests\030\004 \001(\005\022\023\n\013averageLoad\030\005 \001(\001\032" + - "\322\002\n\006Region\022\014\n\004name\030\001 \002(\014\022\016\n\006stores\030\002 \001(\005" + + "\211\001\n\006Region\022\014\n\004name\030\001 \002(\014\022\016\n\006stores\030\002 \001(\005" + "\022\022\n\nstorefiles\030\003 \001(\005\022\027\n\017storefileSizeMB\030" + "\004 \001(\005\022\026\n\016memstoreSizeMB\030\005 \001(\005\022\034\n\024storefi", - "leIndexSizeMB\030\006 \001(\005\022\031\n\021readRequestsCount" + - "\030\007 \001(\003\022\032\n\022writeRequestsCount\030\010 \001(\003\022\027\n\017ro" + - "otIndexSizeKB\030\t \001(\005\022\036\n\026totalStaticIndexS" + - "izeKB\030\n \001(\005\022\036\n\026totalStaticBloomSizeKB\030\013 " + - "\001(\005\022\032\n\022totalCompactingKVs\030\014 \001(\003\022\033\n\023curre" + - "ntCompactedKVs\030\r \001(\003\032\303\001\n\004Node\022\014\n\004name\030\001 " + - "\002(\t\022\021\n\tstartCode\030\002 \001(\003\022\020\n\010requests\030\003 \001(\005" + - "\022\022\n\nheapSizeMB\030\004 \001(\005\022\025\n\rmaxHeapSizeMB\030\005 " + - "\001(\005\022]\n\007regions\030\006 \003(\0132L.org.apache.hadoop" + - ".hbase.rest.protobuf.generated.StorageCl", - "usterStatus.Region" + "leIndexSizeMB\030\006 \001(\005\032\303\001\n\004Node\022\014\n\004name\030\001 \002" + + "(\t\022\021\n\tstartCode\030\002 \001(\003\022\020\n\010requests\030\003 \001(\005\022" + + "\022\n\nheapSizeMB\030\004 \001(\005\022\025\n\rmaxHeapSizeMB\030\005 \001" + + "(\005\022]\n\007regions\030\006 \003(\0132L.org.apache.hadoop." + + "hbase.rest.protobuf.generated.StorageClu" + + "sterStatus.Region" }; com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { @@ -2849,7 +2445,7 @@ public final class StorageClusterStatusMessage { internal_static_org_apache_hadoop_hbase_rest_protobuf_generated_StorageClusterStatus_Region_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_org_apache_hadoop_hbase_rest_protobuf_generated_StorageClusterStatus_Region_descriptor, - new java.lang.String[] { "Name", "Stores", "Storefiles", "StorefileSizeMB", "MemstoreSizeMB", "StorefileIndexSizeMB", "ReadRequestsCount", "WriteRequestsCount", "RootIndexSizeKB", "TotalStaticIndexSizeKB", "TotalStaticBloomSizeKB", "TotalCompactingKVs", "CurrentCompactedKVs", }, + new java.lang.String[] { "Name", "Stores", "Storefiles", "StorefileSizeMB", "MemstoreSizeMB", "StorefileIndexSizeMB", }, org.apache.hadoop.hbase.rest.protobuf.generated.StorageClusterStatusMessage.StorageClusterStatus.Region.class, org.apache.hadoop.hbase.rest.protobuf.generated.StorageClusterStatusMessage.StorageClusterStatus.Region.Builder.class); internal_static_org_apache_hadoop_hbase_rest_protobuf_generated_StorageClusterStatus_Node_descriptor = diff --git src/main/java/org/apache/hadoop/hbase/thrift/ThriftServerRunner.java src/main/java/org/apache/hadoop/hbase/thrift/ThriftServerRunner.java index 99b1392..0fd3903 100644 --- src/main/java/org/apache/hadoop/hbase/thrift/ThriftServerRunner.java +++ src/main/java/org/apache/hadoop/hbase/thrift/ThriftServerRunner.java @@ -66,6 +66,7 @@ import org.apache.hadoop.hbase.filter.Filter; import org.apache.hadoop.hbase.filter.ParseFilter; import org.apache.hadoop.hbase.filter.PrefixFilter; import org.apache.hadoop.hbase.filter.WhileMatchFilter; +import org.apache.hadoop.hbase.migration.HRegionInfo090x; import org.apache.hadoop.hbase.security.User; import org.apache.hadoop.hbase.thrift.CallQueue.Call; import org.apache.hadoop.hbase.thrift.generated.AlreadyExists; @@ -1330,62 +1331,16 @@ public class ThriftServerRunner implements Runnable { } } - @Override - public List getRowOrBefore(ByteBuffer tableName, ByteBuffer row, - ByteBuffer family) throws IOError { - try { - HTable table = getTable(getBytes(tableName)); - Result result = table.getRowOrBefore(getBytes(row), getBytes(family)); - return ThriftUtilities.cellFromHBase(result.raw()); - } catch (IOException e) { - LOG.warn(e.getMessage(), e); - throw new IOError(e.getMessage()); - } - } - + /*** + * Given a row in the meta table return its regioninfo + * XXX Handle splits properly + * @param searchRow The region in meta + * @return The regioninfo associated with that region + * @throws IOError We will IOError if the region can not be found in meta. + */ @Override public TRegionInfo getRegionInfo(ByteBuffer searchRow) throws IOError { - try { - HTable table = getTable(HConstants.META_TABLE_NAME); - byte[] row = getBytes(searchRow); - Result startRowResult = table.getRowOrBefore( - row, HConstants.CATALOG_FAMILY); - - if (startRowResult == null) { - throw new IOException("Cannot find row in .META., row=" - + Bytes.toStringBinary(row)); - } - - // find region start and end keys - byte[] value = startRowResult.getValue(HConstants.CATALOG_FAMILY, - HConstants.REGIONINFO_QUALIFIER); - if (value == null || value.length == 0) { - throw new IOException("HRegionInfo REGIONINFO was null or " + - " empty in Meta for row=" - + Bytes.toStringBinary(row)); - } - HRegionInfo regionInfo = Writables.getHRegionInfo(value); - TRegionInfo region = new TRegionInfo(); - region.setStartKey(regionInfo.getStartKey()); - region.setEndKey(regionInfo.getEndKey()); - region.id = regionInfo.getRegionId(); - region.setName(regionInfo.getRegionName()); - region.version = regionInfo.getVersion(); - - // find region assignment to server - value = startRowResult.getValue(HConstants.CATALOG_FAMILY, - HConstants.SERVER_QUALIFIER); - if (value != null && value.length > 0) { - String hostAndPort = Bytes.toString(value); - region.setServerName(Bytes.toBytes( - Addressing.parseHostname(hostAndPort))); - region.port = Addressing.parsePort(hostAndPort); - } - return region; - } catch (IOException e) { - LOG.warn(e.getMessage(), e); - throw new IOError(e.getMessage()); - } + return null; } private void initMetrics(ThriftMetrics metrics) { diff --git src/main/java/org/apache/hadoop/hbase/thrift/generated/AlreadyExists.java src/main/java/org/apache/hadoop/hbase/thrift/generated/AlreadyExists.java index a5b81f5..abeac63 100644 --- src/main/java/org/apache/hadoop/hbase/thrift/generated/AlreadyExists.java +++ src/main/java/org/apache/hadoop/hbase/thrift/generated/AlreadyExists.java @@ -6,6 +6,7 @@ */ package org.apache.hadoop.hbase.thrift.generated; +import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.thrift.scheme.IScheme; import org.apache.thrift.scheme.SchemeFactory; import org.apache.thrift.scheme.StandardScheme; @@ -226,7 +227,14 @@ public class AlreadyExists extends Exception implements org.apache.thrift.TBase< @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_message = true && (isSetMessage()); + builder.append(present_message); + if (present_message) + builder.append(message); + + return builder.toHashCode(); } public int compareTo(AlreadyExists other) { diff --git src/main/java/org/apache/hadoop/hbase/thrift/generated/BatchMutation.java src/main/java/org/apache/hadoop/hbase/thrift/generated/BatchMutation.java index d5df940..d535baf 100644 --- src/main/java/org/apache/hadoop/hbase/thrift/generated/BatchMutation.java +++ src/main/java/org/apache/hadoop/hbase/thrift/generated/BatchMutation.java @@ -6,6 +6,7 @@ */ package org.apache.hadoop.hbase.thrift.generated; +import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.thrift.scheme.IScheme; import org.apache.thrift.scheme.SchemeFactory; import org.apache.thrift.scheme.StandardScheme; @@ -314,7 +315,19 @@ public class BatchMutation implements org.apache.thrift.TBase(_list0.size); for (int _i1 = 0; _i1 < _list0.size; ++_i1) { - Mutation _elem2; // optional + Mutation _elem2; // required _elem2 = new Mutation(); _elem2.read(iprot); struct.mutations.add(_elem2); @@ -534,7 +547,7 @@ public class BatchMutation implements org.apache.thrift.TBase(_list5.size); for (int _i6 = 0; _i6 < _list5.size; ++_i6) { - Mutation _elem7; // optional + Mutation _elem7; // required _elem7 = new Mutation(); _elem7.read(iprot); struct.mutations.add(_elem7); diff --git src/main/java/org/apache/hadoop/hbase/thrift/generated/ColumnDescriptor.java src/main/java/org/apache/hadoop/hbase/thrift/generated/ColumnDescriptor.java index 4ce85e7..047de4a 100644 --- src/main/java/org/apache/hadoop/hbase/thrift/generated/ColumnDescriptor.java +++ src/main/java/org/apache/hadoop/hbase/thrift/generated/ColumnDescriptor.java @@ -6,6 +6,7 @@ */ package org.apache.hadoop.hbase.thrift.generated; +import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.thrift.scheme.IScheme; import org.apache.thrift.scheme.SchemeFactory; import org.apache.thrift.scheme.StandardScheme; @@ -730,7 +731,54 @@ public class ColumnDescriptor implements org.apache.thrift.TBase mutations, Map attributes) throws IOError, IllegalArgument, org.apache.thrift.TException; @@ -319,7 +320,7 @@ public class Hbase { * * @param timestamp timestamp * - * @param attributes Put attributes + * @param attributes Mutation attributes */ public void mutateRowTs(ByteBuffer tableName, ByteBuffer row, List mutations, long timestamp, Map attributes) throws IOError, IllegalArgument, org.apache.thrift.TException; @@ -333,7 +334,7 @@ public class Hbase { * * @param rowBatches list of row batches * - * @param attributes Put attributes + * @param attributes Mutation attributes */ public void mutateRows(ByteBuffer tableName, List rowBatches, Map attributes) throws IOError, IllegalArgument, org.apache.thrift.TException; @@ -349,7 +350,7 @@ public class Hbase { * * @param timestamp timestamp * - * @param attributes Put attributes + * @param attributes Mutation attributes */ public void mutateRowsTs(ByteBuffer tableName, List rowBatches, long timestamp, Map attributes) throws IOError, IllegalArgument, org.apache.thrift.TException; @@ -582,19 +583,6 @@ public class Hbase { public void scannerClose(int id) throws IOError, IllegalArgument, org.apache.thrift.TException; /** - * Get the row just before the specified one. - * - * @return value for specified row/column - * - * @param tableName name of table - * - * @param row row key - * - * @param family column name - */ - public List getRowOrBefore(ByteBuffer tableName, ByteBuffer row, ByteBuffer family) throws IOError, org.apache.thrift.TException; - - /** * Get the regininfo for the specified row. It scans * the metatable to find region's start and end keys. * @@ -686,8 +674,6 @@ public class Hbase { public void scannerClose(int id, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException; - public void getRowOrBefore(ByteBuffer tableName, ByteBuffer row, ByteBuffer family, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException; - public void getRegionInfo(ByteBuffer row, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException; } @@ -1796,34 +1782,6 @@ public class Hbase { return; } - public List getRowOrBefore(ByteBuffer tableName, ByteBuffer row, ByteBuffer family) throws IOError, org.apache.thrift.TException - { - send_getRowOrBefore(tableName, row, family); - return recv_getRowOrBefore(); - } - - public void send_getRowOrBefore(ByteBuffer tableName, ByteBuffer row, ByteBuffer family) throws org.apache.thrift.TException - { - getRowOrBefore_args args = new getRowOrBefore_args(); - args.setTableName(tableName); - args.setRow(row); - args.setFamily(family); - sendBase("getRowOrBefore", args); - } - - public List recv_getRowOrBefore() throws IOError, org.apache.thrift.TException - { - getRowOrBefore_result result = new getRowOrBefore_result(); - receiveBase(result, "getRowOrBefore"); - if (result.isSetSuccess()) { - return result.success; - } - if (result.io != null) { - throw result.io; - } - throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getRowOrBefore failed: unknown result"); - } - public TRegionInfo getRegionInfo(ByteBuffer row) throws IOError, org.apache.thrift.TException { send_getRegionInfo(row); @@ -3371,44 +3329,6 @@ public class Hbase { } } - public void getRowOrBefore(ByteBuffer tableName, ByteBuffer row, ByteBuffer family, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException { - checkReady(); - getRowOrBefore_call method_call = new getRowOrBefore_call(tableName, row, family, resultHandler, this, ___protocolFactory, ___transport); - this.___currentMethod = method_call; - ___manager.call(method_call); - } - - public static class getRowOrBefore_call extends org.apache.thrift.async.TAsyncMethodCall { - private ByteBuffer tableName; - private ByteBuffer row; - private ByteBuffer family; - public getRowOrBefore_call(ByteBuffer tableName, ByteBuffer row, ByteBuffer family, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException { - super(client, protocolFactory, transport, resultHandler, false); - this.tableName = tableName; - this.row = row; - this.family = family; - } - - public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException { - prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getRowOrBefore", org.apache.thrift.protocol.TMessageType.CALL, 0)); - getRowOrBefore_args args = new getRowOrBefore_args(); - args.setTableName(tableName); - args.setRow(row); - args.setFamily(family); - args.write(prot); - prot.writeMessageEnd(); - } - - public List getResult() throws IOError, org.apache.thrift.TException { - if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) { - throw new IllegalStateException("Method call not finished!"); - } - org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array()); - org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport); - return (new Client(prot)).recv_getRowOrBefore(); - } - } - public void getRegionInfo(ByteBuffer row, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException { checkReady(); getRegionInfo_call method_call = new getRegionInfo_call(row, resultHandler, this, ___protocolFactory, ___transport); @@ -3493,7 +3413,6 @@ public class Hbase { processMap.put("scannerGet", new scannerGet()); processMap.put("scannerGetList", new scannerGetList()); processMap.put("scannerClose", new scannerClose()); - processMap.put("getRowOrBefore", new getRowOrBefore()); processMap.put("getRegionInfo", new getRegionInfo()); return processMap; } @@ -4306,26 +4225,6 @@ public class Hbase { } } - private static class getRowOrBefore extends org.apache.thrift.ProcessFunction { - public getRowOrBefore() { - super("getRowOrBefore"); - } - - protected getRowOrBefore_args getEmptyArgsInstance() { - return new getRowOrBefore_args(); - } - - protected getRowOrBefore_result getResult(I iface, getRowOrBefore_args args) throws org.apache.thrift.TException { - getRowOrBefore_result result = new getRowOrBefore_result(); - try { - result.success = iface.getRowOrBefore(args.tableName, args.row, args.family); - } catch (IOError io) { - result.io = io; - } - return result; - } - } - private static class getRegionInfo extends org.apache.thrift.ProcessFunction { public getRegionInfo() { super("getRegionInfo"); @@ -4565,7 +4464,14 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableName = true && (isSetTableName()); + builder.append(present_tableName); + if (present_tableName) + builder.append(tableName); + + return builder.toHashCode(); } public int compareTo(enableTable_args other) { @@ -4918,7 +4824,14 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + return builder.toHashCode(); } public int compareTo(enableTable_result other) { @@ -5295,7 +5208,14 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableName = true && (isSetTableName()); + builder.append(present_tableName); + if (present_tableName) + builder.append(tableName); + + return builder.toHashCode(); } public int compareTo(disableTable_args other) { @@ -5648,7 +5568,14 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + return builder.toHashCode(); } public int compareTo(disableTable_result other) { @@ -6025,7 +5952,14 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableName = true && (isSetTableName()); + builder.append(present_tableName); + if (present_tableName) + builder.append(tableName); + + return builder.toHashCode(); } public int compareTo(isTableEnabled_args other) { @@ -6440,7 +6374,19 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_success = true; + builder.append(present_success); + if (present_success) + builder.append(success); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + return builder.toHashCode(); } public int compareTo(isTableEnabled_result other) { @@ -6520,6 +6466,8 @@ public class Hbase { private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException { try { + // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor. + __isset_bit_vector = new BitSet(1); 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); @@ -6840,7 +6788,14 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableNameOrRegionName = true && (isSetTableNameOrRegionName()); + builder.append(present_tableNameOrRegionName); + if (present_tableNameOrRegionName) + builder.append(tableNameOrRegionName); + + return builder.toHashCode(); } public int compareTo(compact_args other) { @@ -7193,7 +7148,14 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + return builder.toHashCode(); } public int compareTo(compact_result other) { @@ -7558,7 +7520,14 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableNameOrRegionName = true && (isSetTableNameOrRegionName()); + builder.append(present_tableNameOrRegionName); + if (present_tableNameOrRegionName) + builder.append(tableNameOrRegionName); + + return builder.toHashCode(); } public int compareTo(majorCompact_args other) { @@ -7911,7 +7880,14 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + return builder.toHashCode(); } public int compareTo(majorCompact_result other) { @@ -8201,7 +8177,9 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + return builder.toHashCode(); } public int compareTo(getTableNames_args other) { @@ -8590,7 +8568,19 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_success = true && (isSetSuccess()); + builder.append(present_success); + if (present_success) + builder.append(success); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + return builder.toHashCode(); } public int compareTo(getTableNames_result other) { @@ -8705,7 +8695,7 @@ public class Hbase { struct.success = new ArrayList(_list26.size); for (int _i27 = 0; _i27 < _list26.size; ++_i27) { - ByteBuffer _elem28; // optional + ByteBuffer _elem28; // required _elem28 = iprot.readBinary(); struct.success.add(_elem28); } @@ -8806,7 +8796,7 @@ public class Hbase { struct.success = new ArrayList(_list31.size); for (int _i32 = 0; _i32 < _list31.size; ++_i32) { - ByteBuffer _elem33; // optional + ByteBuffer _elem33; // required _elem33 = iprot.readBinary(); struct.success.add(_elem33); } @@ -9040,7 +9030,14 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableName = true && (isSetTableName()); + builder.append(present_tableName); + if (present_tableName) + builder.append(tableName); + + return builder.toHashCode(); } public int compareTo(getColumnDescriptors_args other) { @@ -9477,7 +9474,19 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_success = true && (isSetSuccess()); + builder.append(present_success); + if (present_success) + builder.append(success); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + return builder.toHashCode(); } public int compareTo(getColumnDescriptors_result other) { @@ -9593,7 +9602,7 @@ public class Hbase { for (int _i35 = 0; _i35 < _map34.size; ++_i35) { ByteBuffer _key36; // required - ColumnDescriptor _val37; // required + ColumnDescriptor _val37; // optional _key36 = iprot.readBinary(); _val37 = new ColumnDescriptor(); _val37.read(iprot); @@ -9699,7 +9708,7 @@ public class Hbase { for (int _i41 = 0; _i41 < _map40.size; ++_i41) { ByteBuffer _key42; // required - ColumnDescriptor _val43; // required + ColumnDescriptor _val43; // optional _key42 = iprot.readBinary(); _val43 = new ColumnDescriptor(); _val43.read(iprot); @@ -9935,7 +9944,14 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableName = true && (isSetTableName()); + builder.append(present_tableName); + if (present_tableName) + builder.append(tableName); + + return builder.toHashCode(); } public int compareTo(getTableRegions_args other) { @@ -10367,7 +10383,19 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_success = true && (isSetSuccess()); + builder.append(present_success); + if (present_success) + builder.append(success); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + return builder.toHashCode(); } public int compareTo(getTableRegions_result other) { @@ -10482,7 +10510,7 @@ public class Hbase { struct.success = new ArrayList(_list44.size); for (int _i45 = 0; _i45 < _list44.size; ++_i45) { - TRegionInfo _elem46; // optional + TRegionInfo _elem46; // required _elem46 = new TRegionInfo(); _elem46.read(iprot); struct.success.add(_elem46); @@ -10584,7 +10612,7 @@ public class Hbase { struct.success = new ArrayList(_list49.size); for (int _i50 = 0; _i50 < _list49.size; ++_i50) { - TRegionInfo _elem51; // optional + TRegionInfo _elem51; // required _elem51 = new TRegionInfo(); _elem51.read(iprot); struct.success.add(_elem51); @@ -10910,7 +10938,19 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableName = true && (isSetTableName()); + builder.append(present_tableName); + if (present_tableName) + builder.append(tableName); + + boolean present_columnFamilies = true && (isSetColumnFamilies()); + builder.append(present_columnFamilies); + if (present_columnFamilies) + builder.append(columnFamilies); + + return builder.toHashCode(); } public int compareTo(createTable_args other) { @@ -11033,7 +11073,7 @@ public class Hbase { struct.columnFamilies = new ArrayList(_list52.size); for (int _i53 = 0; _i53 < _list52.size; ++_i53) { - ColumnDescriptor _elem54; // optional + ColumnDescriptor _elem54; // required _elem54 = new ColumnDescriptor(); _elem54.read(iprot); struct.columnFamilies.add(_elem54); @@ -11130,7 +11170,7 @@ public class Hbase { struct.columnFamilies = new ArrayList(_list57.size); for (int _i58 = 0; _i58 < _list57.size; ++_i58) { - ColumnDescriptor _elem59; // optional + ColumnDescriptor _elem59; // required _elem59 = new ColumnDescriptor(); _elem59.read(iprot); struct.columnFamilies.add(_elem59); @@ -11456,7 +11496,24 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + boolean present_ia = true && (isSetIa()); + builder.append(present_ia); + if (present_ia) + builder.append(ia); + + boolean present_exist = true && (isSetExist()); + builder.append(present_exist); + if (present_exist) + builder.append(exist); + + return builder.toHashCode(); } public int compareTo(createTable_result other) { @@ -11919,7 +11976,14 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableName = true && (isSetTableName()); + builder.append(present_tableName); + if (present_tableName) + builder.append(tableName); + + return builder.toHashCode(); } public int compareTo(deleteTable_args other) { @@ -12272,7 +12336,14 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + return builder.toHashCode(); } public int compareTo(deleteTable_result other) { @@ -12907,7 +12978,29 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableName = true && (isSetTableName()); + builder.append(present_tableName); + if (present_tableName) + builder.append(tableName); + + boolean present_row = true && (isSetRow()); + builder.append(present_row); + if (present_row) + builder.append(row); + + boolean present_column = true && (isSetColumn()); + builder.append(present_column); + if (present_column) + builder.append(column); + + boolean present_attributes = true && (isSetAttributes()); + builder.append(present_attributes); + if (present_attributes) + builder.append(attributes); + + return builder.toHashCode(); } public int compareTo(get_args other) { @@ -13083,7 +13176,7 @@ public class Hbase { for (int _i61 = 0; _i61 < _map60.size; ++_i61) { ByteBuffer _key62; // required - ByteBuffer _val63; // required + ByteBuffer _val63; // optional _key62 = iprot.readBinary(); _val63 = iprot.readBinary(); struct.attributes.put(_key62, _val63); @@ -13213,7 +13306,7 @@ public class Hbase { for (int _i67 = 0; _i67 < _map66.size; ++_i67) { ByteBuffer _key68; // required - ByteBuffer _val69; // required + ByteBuffer _val69; // optional _key68 = iprot.readBinary(); _val69 = iprot.readBinary(); struct.attributes.put(_key68, _val69); @@ -13500,7 +13593,19 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_success = true && (isSetSuccess()); + builder.append(present_success); + if (present_success) + builder.append(success); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + return builder.toHashCode(); } public int compareTo(get_result other) { @@ -13615,7 +13720,7 @@ public class Hbase { struct.success = new ArrayList(_list70.size); for (int _i71 = 0; _i71 < _list70.size; ++_i71) { - TCell _elem72; // optional + TCell _elem72; // required _elem72 = new TCell(); _elem72.read(iprot); struct.success.add(_elem72); @@ -13717,7 +13822,7 @@ public class Hbase { struct.success = new ArrayList(_list75.size); for (int _i76 = 0; _i76 < _list75.size; ++_i76) { - TCell _elem77; // optional + TCell _elem77; // required _elem77 = new TCell(); _elem77.read(iprot); struct.success.add(_elem77); @@ -14284,7 +14389,34 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableName = true && (isSetTableName()); + builder.append(present_tableName); + if (present_tableName) + builder.append(tableName); + + boolean present_row = true && (isSetRow()); + builder.append(present_row); + if (present_row) + builder.append(row); + + boolean present_column = true && (isSetColumn()); + builder.append(present_column); + if (present_column) + builder.append(column); + + boolean present_numVersions = true; + builder.append(present_numVersions); + if (present_numVersions) + builder.append(numVersions); + + boolean present_attributes = true && (isSetAttributes()); + builder.append(present_attributes); + if (present_attributes) + builder.append(attributes); + + return builder.toHashCode(); } public int compareTo(getVer_args other) { @@ -14484,7 +14616,7 @@ public class Hbase { for (int _i79 = 0; _i79 < _map78.size; ++_i79) { ByteBuffer _key80; // required - ByteBuffer _val81; // required + ByteBuffer _val81; // optional _key80 = iprot.readBinary(); _val81 = iprot.readBinary(); struct.attributes.put(_key80, _val81); @@ -14627,7 +14759,7 @@ public class Hbase { for (int _i85 = 0; _i85 < _map84.size; ++_i85) { ByteBuffer _key86; // required - ByteBuffer _val87; // required + ByteBuffer _val87; // optional _key86 = iprot.readBinary(); _val87 = iprot.readBinary(); struct.attributes.put(_key86, _val87); @@ -14914,7 +15046,19 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_success = true && (isSetSuccess()); + builder.append(present_success); + if (present_success) + builder.append(success); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + return builder.toHashCode(); } public int compareTo(getVer_result other) { @@ -15029,7 +15173,7 @@ public class Hbase { struct.success = new ArrayList(_list88.size); for (int _i89 = 0; _i89 < _list88.size; ++_i89) { - TCell _elem90; // optional + TCell _elem90; // required _elem90 = new TCell(); _elem90.read(iprot); struct.success.add(_elem90); @@ -15131,7 +15275,7 @@ public class Hbase { struct.success = new ArrayList(_list93.size); for (int _i94 = 0; _i94 < _list93.size; ++_i94) { - TCell _elem95; // optional + TCell _elem95; // required _elem95 = new TCell(); _elem95.read(iprot); struct.success.add(_elem95); @@ -15769,7 +15913,39 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableName = true && (isSetTableName()); + builder.append(present_tableName); + if (present_tableName) + builder.append(tableName); + + boolean present_row = true && (isSetRow()); + builder.append(present_row); + if (present_row) + builder.append(row); + + boolean present_column = true && (isSetColumn()); + builder.append(present_column); + if (present_column) + builder.append(column); + + boolean present_timestamp = true; + builder.append(present_timestamp); + if (present_timestamp) + builder.append(timestamp); + + boolean present_numVersions = true; + builder.append(present_numVersions); + if (present_numVersions) + builder.append(numVersions); + + boolean present_attributes = true && (isSetAttributes()); + builder.append(present_attributes); + if (present_attributes) + builder.append(attributes); + + return builder.toHashCode(); } public int compareTo(getVerTs_args other) { @@ -15989,7 +16165,7 @@ public class Hbase { for (int _i97 = 0; _i97 < _map96.size; ++_i97) { ByteBuffer _key98; // required - ByteBuffer _val99; // required + ByteBuffer _val99; // optional _key98 = iprot.readBinary(); _val99 = iprot.readBinary(); struct.attributes.put(_key98, _val99); @@ -16145,7 +16321,7 @@ public class Hbase { for (int _i103 = 0; _i103 < _map102.size; ++_i103) { ByteBuffer _key104; // required - ByteBuffer _val105; // required + ByteBuffer _val105; // optional _key104 = iprot.readBinary(); _val105 = iprot.readBinary(); struct.attributes.put(_key104, _val105); @@ -16432,7 +16608,19 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_success = true && (isSetSuccess()); + builder.append(present_success); + if (present_success) + builder.append(success); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + return builder.toHashCode(); } public int compareTo(getVerTs_result other) { @@ -16547,7 +16735,7 @@ public class Hbase { struct.success = new ArrayList(_list106.size); for (int _i107 = 0; _i107 < _list106.size; ++_i107) { - TCell _elem108; // optional + TCell _elem108; // required _elem108 = new TCell(); _elem108.read(iprot); struct.success.add(_elem108); @@ -16649,7 +16837,7 @@ public class Hbase { struct.success = new ArrayList(_list111.size); for (int _i112 = 0; _i112 < _list111.size; ++_i112) { - TCell _elem113; // optional + TCell _elem113; // required _elem113 = new TCell(); _elem113.read(iprot); struct.success.add(_elem113); @@ -17061,7 +17249,24 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableName = true && (isSetTableName()); + builder.append(present_tableName); + if (present_tableName) + builder.append(tableName); + + boolean present_row = true && (isSetRow()); + builder.append(present_row); + if (present_row) + builder.append(row); + + boolean present_attributes = true && (isSetAttributes()); + builder.append(present_attributes); + if (present_attributes) + builder.append(attributes); + + return builder.toHashCode(); } public int compareTo(getRow_args other) { @@ -17211,7 +17416,7 @@ public class Hbase { for (int _i115 = 0; _i115 < _map114.size; ++_i115) { ByteBuffer _key116; // required - ByteBuffer _val117; // required + ByteBuffer _val117; // optional _key116 = iprot.readBinary(); _val117 = iprot.readBinary(); struct.attributes.put(_key116, _val117); @@ -17326,7 +17531,7 @@ public class Hbase { for (int _i121 = 0; _i121 < _map120.size; ++_i121) { ByteBuffer _key122; // required - ByteBuffer _val123; // required + ByteBuffer _val123; // optional _key122 = iprot.readBinary(); _val123 = iprot.readBinary(); struct.attributes.put(_key122, _val123); @@ -17613,7 +17818,19 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_success = true && (isSetSuccess()); + builder.append(present_success); + if (present_success) + builder.append(success); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + return builder.toHashCode(); } public int compareTo(getRow_result other) { @@ -17728,7 +17945,7 @@ public class Hbase { struct.success = new ArrayList(_list124.size); for (int _i125 = 0; _i125 < _list124.size; ++_i125) { - TRowResult _elem126; // optional + TRowResult _elem126; // required _elem126 = new TRowResult(); _elem126.read(iprot); struct.success.add(_elem126); @@ -17830,7 +18047,7 @@ public class Hbase { struct.success = new ArrayList(_list129.size); for (int _i130 = 0; _i130 < _list129.size; ++_i130) { - TRowResult _elem131; // optional + TRowResult _elem131; // required _elem131 = new TRowResult(); _elem131.read(iprot); struct.success.add(_elem131); @@ -18333,7 +18550,29 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableName = true && (isSetTableName()); + builder.append(present_tableName); + if (present_tableName) + builder.append(tableName); + + boolean present_row = true && (isSetRow()); + builder.append(present_row); + if (present_row) + builder.append(row); + + boolean present_columns = true && (isSetColumns()); + builder.append(present_columns); + if (present_columns) + builder.append(columns); + + boolean present_attributes = true && (isSetAttributes()); + builder.append(present_attributes); + if (present_attributes) + builder.append(attributes); + + return builder.toHashCode(); } public int compareTo(getRowWithColumns_args other) { @@ -18500,7 +18739,7 @@ public class Hbase { struct.columns = new ArrayList(_list132.size); for (int _i133 = 0; _i133 < _list132.size; ++_i133) { - ByteBuffer _elem134; // optional + ByteBuffer _elem134; // required _elem134 = iprot.readBinary(); struct.columns.add(_elem134); } @@ -18519,7 +18758,7 @@ public class Hbase { for (int _i136 = 0; _i136 < _map135.size; ++_i136) { ByteBuffer _key137; // required - ByteBuffer _val138; // required + ByteBuffer _val138; // optional _key137 = iprot.readBinary(); _val138 = iprot.readBinary(); struct.attributes.put(_key137, _val138); @@ -18657,7 +18896,7 @@ public class Hbase { struct.columns = new ArrayList(_list143.size); for (int _i144 = 0; _i144 < _list143.size; ++_i144) { - ByteBuffer _elem145; // optional + ByteBuffer _elem145; // required _elem145 = iprot.readBinary(); struct.columns.add(_elem145); } @@ -18671,7 +18910,7 @@ public class Hbase { for (int _i147 = 0; _i147 < _map146.size; ++_i147) { ByteBuffer _key148; // required - ByteBuffer _val149; // required + ByteBuffer _val149; // optional _key148 = iprot.readBinary(); _val149 = iprot.readBinary(); struct.attributes.put(_key148, _val149); @@ -18958,7 +19197,19 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_success = true && (isSetSuccess()); + builder.append(present_success); + if (present_success) + builder.append(success); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + return builder.toHashCode(); } public int compareTo(getRowWithColumns_result other) { @@ -19073,7 +19324,7 @@ public class Hbase { struct.success = new ArrayList(_list150.size); for (int _i151 = 0; _i151 < _list150.size; ++_i151) { - TRowResult _elem152; // optional + TRowResult _elem152; // required _elem152 = new TRowResult(); _elem152.read(iprot); struct.success.add(_elem152); @@ -19175,7 +19426,7 @@ public class Hbase { struct.success = new ArrayList(_list155.size); for (int _i156 = 0; _i156 < _list155.size; ++_i156) { - TRowResult _elem157; // optional + TRowResult _elem157; // required _elem157 = new TRowResult(); _elem157.read(iprot); struct.success.add(_elem157); @@ -19661,7 +19912,29 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableName = true && (isSetTableName()); + builder.append(present_tableName); + if (present_tableName) + builder.append(tableName); + + boolean present_row = true && (isSetRow()); + builder.append(present_row); + if (present_row) + builder.append(row); + + boolean present_timestamp = true; + builder.append(present_timestamp); + if (present_timestamp) + builder.append(timestamp); + + boolean present_attributes = true && (isSetAttributes()); + builder.append(present_attributes); + if (present_attributes) + builder.append(attributes); + + return builder.toHashCode(); } public int compareTo(getRowTs_args other) { @@ -19835,7 +20108,7 @@ public class Hbase { for (int _i159 = 0; _i159 < _map158.size; ++_i159) { ByteBuffer _key160; // required - ByteBuffer _val161; // required + ByteBuffer _val161; // optional _key160 = iprot.readBinary(); _val161 = iprot.readBinary(); struct.attributes.put(_key160, _val161); @@ -19963,7 +20236,7 @@ public class Hbase { for (int _i165 = 0; _i165 < _map164.size; ++_i165) { ByteBuffer _key166; // required - ByteBuffer _val167; // required + ByteBuffer _val167; // optional _key166 = iprot.readBinary(); _val167 = iprot.readBinary(); struct.attributes.put(_key166, _val167); @@ -20250,7 +20523,19 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_success = true && (isSetSuccess()); + builder.append(present_success); + if (present_success) + builder.append(success); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + return builder.toHashCode(); } public int compareTo(getRowTs_result other) { @@ -20365,7 +20650,7 @@ public class Hbase { struct.success = new ArrayList(_list168.size); for (int _i169 = 0; _i169 < _list168.size; ++_i169) { - TRowResult _elem170; // optional + TRowResult _elem170; // required _elem170 = new TRowResult(); _elem170.read(iprot); struct.success.add(_elem170); @@ -20467,7 +20752,7 @@ public class Hbase { struct.success = new ArrayList(_list173.size); for (int _i174 = 0; _i174 < _list173.size; ++_i174) { - TRowResult _elem175; // optional + TRowResult _elem175; // required _elem175 = new TRowResult(); _elem175.read(iprot); struct.success.add(_elem175); @@ -21032,7 +21317,34 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableName = true && (isSetTableName()); + builder.append(present_tableName); + if (present_tableName) + builder.append(tableName); + + boolean present_row = true && (isSetRow()); + builder.append(present_row); + if (present_row) + builder.append(row); + + boolean present_columns = true && (isSetColumns()); + builder.append(present_columns); + if (present_columns) + builder.append(columns); + + boolean present_timestamp = true; + builder.append(present_timestamp); + if (present_timestamp) + builder.append(timestamp); + + boolean present_attributes = true && (isSetAttributes()); + builder.append(present_attributes); + if (present_attributes) + builder.append(attributes); + + return builder.toHashCode(); } public int compareTo(getRowWithColumnsTs_args other) { @@ -21215,7 +21527,7 @@ public class Hbase { struct.columns = new ArrayList(_list176.size); for (int _i177 = 0; _i177 < _list176.size; ++_i177) { - ByteBuffer _elem178; // optional + ByteBuffer _elem178; // required _elem178 = iprot.readBinary(); struct.columns.add(_elem178); } @@ -21242,7 +21554,7 @@ public class Hbase { for (int _i180 = 0; _i180 < _map179.size; ++_i180) { ByteBuffer _key181; // required - ByteBuffer _val182; // required + ByteBuffer _val182; // optional _key181 = iprot.readBinary(); _val182 = iprot.readBinary(); struct.attributes.put(_key181, _val182); @@ -21389,7 +21701,7 @@ public class Hbase { struct.columns = new ArrayList(_list187.size); for (int _i188 = 0; _i188 < _list187.size; ++_i188) { - ByteBuffer _elem189; // optional + ByteBuffer _elem189; // required _elem189 = iprot.readBinary(); struct.columns.add(_elem189); } @@ -21407,7 +21719,7 @@ public class Hbase { for (int _i191 = 0; _i191 < _map190.size; ++_i191) { ByteBuffer _key192; // required - ByteBuffer _val193; // required + ByteBuffer _val193; // optional _key192 = iprot.readBinary(); _val193 = iprot.readBinary(); struct.attributes.put(_key192, _val193); @@ -21694,7 +22006,19 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_success = true && (isSetSuccess()); + builder.append(present_success); + if (present_success) + builder.append(success); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + return builder.toHashCode(); } public int compareTo(getRowWithColumnsTs_result other) { @@ -21809,7 +22133,7 @@ public class Hbase { struct.success = new ArrayList(_list194.size); for (int _i195 = 0; _i195 < _list194.size; ++_i195) { - TRowResult _elem196; // optional + TRowResult _elem196; // required _elem196 = new TRowResult(); _elem196.read(iprot); struct.success.add(_elem196); @@ -21911,7 +22235,7 @@ public class Hbase { struct.success = new ArrayList(_list199.size); for (int _i200 = 0; _i200 < _list199.size; ++_i200) { - TRowResult _elem201; // optional + TRowResult _elem201; // required _elem201 = new TRowResult(); _elem201.read(iprot); struct.success.add(_elem201); @@ -22333,7 +22657,24 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableName = true && (isSetTableName()); + builder.append(present_tableName); + if (present_tableName) + builder.append(tableName); + + boolean present_rows = true && (isSetRows()); + builder.append(present_rows); + if (present_rows) + builder.append(rows); + + boolean present_attributes = true && (isSetAttributes()); + builder.append(present_attributes); + if (present_attributes) + builder.append(attributes); + + return builder.toHashCode(); } public int compareTo(getRows_args other) { @@ -22474,7 +22815,7 @@ public class Hbase { struct.rows = new ArrayList(_list202.size); for (int _i203 = 0; _i203 < _list202.size; ++_i203) { - ByteBuffer _elem204; // optional + ByteBuffer _elem204; // required _elem204 = iprot.readBinary(); struct.rows.add(_elem204); } @@ -22493,7 +22834,7 @@ public class Hbase { for (int _i206 = 0; _i206 < _map205.size; ++_i206) { ByteBuffer _key207; // required - ByteBuffer _val208; // required + ByteBuffer _val208; // optional _key207 = iprot.readBinary(); _val208 = iprot.readBinary(); struct.attributes.put(_key207, _val208); @@ -22616,7 +22957,7 @@ public class Hbase { struct.rows = new ArrayList(_list213.size); for (int _i214 = 0; _i214 < _list213.size; ++_i214) { - ByteBuffer _elem215; // optional + ByteBuffer _elem215; // required _elem215 = iprot.readBinary(); struct.rows.add(_elem215); } @@ -22630,7 +22971,7 @@ public class Hbase { for (int _i217 = 0; _i217 < _map216.size; ++_i217) { ByteBuffer _key218; // required - ByteBuffer _val219; // required + ByteBuffer _val219; // optional _key218 = iprot.readBinary(); _val219 = iprot.readBinary(); struct.attributes.put(_key218, _val219); @@ -22917,7 +23258,19 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_success = true && (isSetSuccess()); + builder.append(present_success); + if (present_success) + builder.append(success); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + return builder.toHashCode(); } public int compareTo(getRows_result other) { @@ -23032,7 +23385,7 @@ public class Hbase { struct.success = new ArrayList(_list220.size); for (int _i221 = 0; _i221 < _list220.size; ++_i221) { - TRowResult _elem222; // optional + TRowResult _elem222; // required _elem222 = new TRowResult(); _elem222.read(iprot); struct.success.add(_elem222); @@ -23134,7 +23487,7 @@ public class Hbase { struct.success = new ArrayList(_list225.size); for (int _i226 = 0; _i226 < _list225.size; ++_i226) { - TRowResult _elem227; // optional + TRowResult _elem227; // required _elem227 = new TRowResult(); _elem227.read(iprot); struct.success.add(_elem227); @@ -23647,7 +24000,29 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableName = true && (isSetTableName()); + builder.append(present_tableName); + if (present_tableName) + builder.append(tableName); + + boolean present_rows = true && (isSetRows()); + builder.append(present_rows); + if (present_rows) + builder.append(rows); + + boolean present_columns = true && (isSetColumns()); + builder.append(present_columns); + if (present_columns) + builder.append(columns); + + boolean present_attributes = true && (isSetAttributes()); + builder.append(present_attributes); + if (present_attributes) + builder.append(attributes); + + return builder.toHashCode(); } public int compareTo(getRowsWithColumns_args other) { @@ -23806,7 +24181,7 @@ public class Hbase { struct.rows = new ArrayList(_list228.size); for (int _i229 = 0; _i229 < _list228.size; ++_i229) { - ByteBuffer _elem230; // optional + ByteBuffer _elem230; // required _elem230 = iprot.readBinary(); struct.rows.add(_elem230); } @@ -23824,7 +24199,7 @@ public class Hbase { struct.columns = new ArrayList(_list231.size); for (int _i232 = 0; _i232 < _list231.size; ++_i232) { - ByteBuffer _elem233; // optional + ByteBuffer _elem233; // required _elem233 = iprot.readBinary(); struct.columns.add(_elem233); } @@ -23843,7 +24218,7 @@ public class Hbase { for (int _i235 = 0; _i235 < _map234.size; ++_i235) { ByteBuffer _key236; // required - ByteBuffer _val237; // required + ByteBuffer _val237; // optional _key236 = iprot.readBinary(); _val237 = iprot.readBinary(); struct.attributes.put(_key236, _val237); @@ -23990,7 +24365,7 @@ public class Hbase { struct.rows = new ArrayList(_list244.size); for (int _i245 = 0; _i245 < _list244.size; ++_i245) { - ByteBuffer _elem246; // optional + ByteBuffer _elem246; // required _elem246 = iprot.readBinary(); struct.rows.add(_elem246); } @@ -24003,7 +24378,7 @@ public class Hbase { struct.columns = new ArrayList(_list247.size); for (int _i248 = 0; _i248 < _list247.size; ++_i248) { - ByteBuffer _elem249; // optional + ByteBuffer _elem249; // required _elem249 = iprot.readBinary(); struct.columns.add(_elem249); } @@ -24017,7 +24392,7 @@ public class Hbase { for (int _i251 = 0; _i251 < _map250.size; ++_i251) { ByteBuffer _key252; // required - ByteBuffer _val253; // required + ByteBuffer _val253; // optional _key252 = iprot.readBinary(); _val253 = iprot.readBinary(); struct.attributes.put(_key252, _val253); @@ -24304,7 +24679,19 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_success = true && (isSetSuccess()); + builder.append(present_success); + if (present_success) + builder.append(success); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + return builder.toHashCode(); } public int compareTo(getRowsWithColumns_result other) { @@ -24419,7 +24806,7 @@ public class Hbase { struct.success = new ArrayList(_list254.size); for (int _i255 = 0; _i255 < _list254.size; ++_i255) { - TRowResult _elem256; // optional + TRowResult _elem256; // required _elem256 = new TRowResult(); _elem256.read(iprot); struct.success.add(_elem256); @@ -24521,7 +24908,7 @@ public class Hbase { struct.success = new ArrayList(_list259.size); for (int _i260 = 0; _i260 < _list259.size; ++_i260) { - TRowResult _elem261; // optional + TRowResult _elem261; // required _elem261 = new TRowResult(); _elem261.read(iprot); struct.success.add(_elem261); @@ -25017,7 +25404,29 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableName = true && (isSetTableName()); + builder.append(present_tableName); + if (present_tableName) + builder.append(tableName); + + boolean present_rows = true && (isSetRows()); + builder.append(present_rows); + if (present_rows) + builder.append(rows); + + boolean present_timestamp = true; + builder.append(present_timestamp); + if (present_timestamp) + builder.append(timestamp); + + boolean present_attributes = true && (isSetAttributes()); + builder.append(present_attributes); + if (present_attributes) + builder.append(attributes); + + return builder.toHashCode(); } public int compareTo(getRowsTs_args other) { @@ -25174,7 +25583,7 @@ public class Hbase { struct.rows = new ArrayList(_list262.size); for (int _i263 = 0; _i263 < _list262.size; ++_i263) { - ByteBuffer _elem264; // optional + ByteBuffer _elem264; // required _elem264 = iprot.readBinary(); struct.rows.add(_elem264); } @@ -25201,7 +25610,7 @@ public class Hbase { for (int _i266 = 0; _i266 < _map265.size; ++_i266) { ByteBuffer _key267; // required - ByteBuffer _val268; // required + ByteBuffer _val268; // optional _key267 = iprot.readBinary(); _val268 = iprot.readBinary(); struct.attributes.put(_key267, _val268); @@ -25333,7 +25742,7 @@ public class Hbase { struct.rows = new ArrayList(_list273.size); for (int _i274 = 0; _i274 < _list273.size; ++_i274) { - ByteBuffer _elem275; // optional + ByteBuffer _elem275; // required _elem275 = iprot.readBinary(); struct.rows.add(_elem275); } @@ -25351,7 +25760,7 @@ public class Hbase { for (int _i277 = 0; _i277 < _map276.size; ++_i277) { ByteBuffer _key278; // required - ByteBuffer _val279; // required + ByteBuffer _val279; // optional _key278 = iprot.readBinary(); _val279 = iprot.readBinary(); struct.attributes.put(_key278, _val279); @@ -25638,7 +26047,19 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_success = true && (isSetSuccess()); + builder.append(present_success); + if (present_success) + builder.append(success); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + return builder.toHashCode(); } public int compareTo(getRowsTs_result other) { @@ -25753,7 +26174,7 @@ public class Hbase { struct.success = new ArrayList(_list280.size); for (int _i281 = 0; _i281 < _list280.size; ++_i281) { - TRowResult _elem282; // optional + TRowResult _elem282; // required _elem282 = new TRowResult(); _elem282.read(iprot); struct.success.add(_elem282); @@ -25855,7 +26276,7 @@ public class Hbase { struct.success = new ArrayList(_list285.size); for (int _i286 = 0; _i286 < _list285.size; ++_i286) { - TRowResult _elem287; // optional + TRowResult _elem287; // required _elem287 = new TRowResult(); _elem287.read(iprot); struct.success.add(_elem287); @@ -26430,7 +26851,34 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableName = true && (isSetTableName()); + builder.append(present_tableName); + if (present_tableName) + builder.append(tableName); + + boolean present_rows = true && (isSetRows()); + builder.append(present_rows); + if (present_rows) + builder.append(rows); + + boolean present_columns = true && (isSetColumns()); + builder.append(present_columns); + if (present_columns) + builder.append(columns); + + boolean present_timestamp = true; + builder.append(present_timestamp); + if (present_timestamp) + builder.append(timestamp); + + boolean present_attributes = true && (isSetAttributes()); + builder.append(present_attributes); + if (present_attributes) + builder.append(attributes); + + return builder.toHashCode(); } public int compareTo(getRowsWithColumnsTs_args other) { @@ -26605,7 +27053,7 @@ public class Hbase { struct.rows = new ArrayList(_list288.size); for (int _i289 = 0; _i289 < _list288.size; ++_i289) { - ByteBuffer _elem290; // optional + ByteBuffer _elem290; // required _elem290 = iprot.readBinary(); struct.rows.add(_elem290); } @@ -26623,7 +27071,7 @@ public class Hbase { struct.columns = new ArrayList(_list291.size); for (int _i292 = 0; _i292 < _list291.size; ++_i292) { - ByteBuffer _elem293; // optional + ByteBuffer _elem293; // required _elem293 = iprot.readBinary(); struct.columns.add(_elem293); } @@ -26650,7 +27098,7 @@ public class Hbase { for (int _i295 = 0; _i295 < _map294.size; ++_i295) { ByteBuffer _key296; // required - ByteBuffer _val297; // required + ByteBuffer _val297; // optional _key296 = iprot.readBinary(); _val297 = iprot.readBinary(); struct.attributes.put(_key296, _val297); @@ -26806,7 +27254,7 @@ public class Hbase { struct.rows = new ArrayList(_list304.size); for (int _i305 = 0; _i305 < _list304.size; ++_i305) { - ByteBuffer _elem306; // optional + ByteBuffer _elem306; // required _elem306 = iprot.readBinary(); struct.rows.add(_elem306); } @@ -26819,7 +27267,7 @@ public class Hbase { struct.columns = new ArrayList(_list307.size); for (int _i308 = 0; _i308 < _list307.size; ++_i308) { - ByteBuffer _elem309; // optional + ByteBuffer _elem309; // required _elem309 = iprot.readBinary(); struct.columns.add(_elem309); } @@ -26837,7 +27285,7 @@ public class Hbase { for (int _i311 = 0; _i311 < _map310.size; ++_i311) { ByteBuffer _key312; // required - ByteBuffer _val313; // required + ByteBuffer _val313; // optional _key312 = iprot.readBinary(); _val313 = iprot.readBinary(); struct.attributes.put(_key312, _val313); @@ -27124,7 +27572,19 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_success = true && (isSetSuccess()); + builder.append(present_success); + if (present_success) + builder.append(success); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + return builder.toHashCode(); } public int compareTo(getRowsWithColumnsTs_result other) { @@ -27239,7 +27699,7 @@ public class Hbase { struct.success = new ArrayList(_list314.size); for (int _i315 = 0; _i315 < _list314.size; ++_i315) { - TRowResult _elem316; // optional + TRowResult _elem316; // required _elem316 = new TRowResult(); _elem316.read(iprot); struct.success.add(_elem316); @@ -27341,7 +27801,7 @@ public class Hbase { struct.success = new ArrayList(_list319.size); for (int _i320 = 0; _i320 < _list319.size; ++_i320) { - TRowResult _elem321; // optional + TRowResult _elem321; // required _elem321 = new TRowResult(); _elem321.read(iprot); struct.success.add(_elem321); @@ -27386,7 +27846,7 @@ public class Hbase { */ public List mutations; // required /** - * Put attributes + * Mutation attributes */ public Map attributes; // required @@ -27405,7 +27865,7 @@ public class Hbase { */ MUTATIONS((short)3, "mutations"), /** - * Put attributes + * Mutation attributes */ ATTRIBUTES((short)4, "attributes"); @@ -27687,14 +28147,14 @@ public class Hbase { } /** - * Put attributes + * Mutation attributes */ public Map getAttributes() { return this.attributes; } /** - * Put attributes + * Mutation attributes */ public mutateRow_args setAttributes(Map attributes) { this.attributes = attributes; @@ -27844,7 +28304,29 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableName = true && (isSetTableName()); + builder.append(present_tableName); + if (present_tableName) + builder.append(tableName); + + boolean present_row = true && (isSetRow()); + builder.append(present_row); + if (present_row) + builder.append(row); + + boolean present_mutations = true && (isSetMutations()); + builder.append(present_mutations); + if (present_mutations) + builder.append(mutations); + + boolean present_attributes = true && (isSetAttributes()); + builder.append(present_attributes); + if (present_attributes) + builder.append(attributes); + + return builder.toHashCode(); } public int compareTo(mutateRow_args other) { @@ -28011,7 +28493,7 @@ public class Hbase { struct.mutations = new ArrayList(_list322.size); for (int _i323 = 0; _i323 < _list322.size; ++_i323) { - Mutation _elem324; // optional + Mutation _elem324; // required _elem324 = new Mutation(); _elem324.read(iprot); struct.mutations.add(_elem324); @@ -28031,7 +28513,7 @@ public class Hbase { for (int _i326 = 0; _i326 < _map325.size; ++_i326) { ByteBuffer _key327; // required - ByteBuffer _val328; // required + ByteBuffer _val328; // optional _key327 = iprot.readBinary(); _val328 = iprot.readBinary(); struct.attributes.put(_key327, _val328); @@ -28169,7 +28651,7 @@ public class Hbase { struct.mutations = new ArrayList(_list333.size); for (int _i334 = 0; _i334 < _list333.size; ++_i334) { - Mutation _elem335; // optional + Mutation _elem335; // required _elem335 = new Mutation(); _elem335.read(iprot); struct.mutations.add(_elem335); @@ -28184,7 +28666,7 @@ public class Hbase { for (int _i337 = 0; _i337 < _map336.size; ++_i337) { ByteBuffer _key338; // required - ByteBuffer _val339; // required + ByteBuffer _val339; // optional _key338 = iprot.readBinary(); _val339 = iprot.readBinary(); struct.attributes.put(_key338, _val339); @@ -28451,7 +28933,19 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + boolean present_ia = true && (isSetIa()); + builder.append(present_ia); + if (present_ia) + builder.append(ia); + + return builder.toHashCode(); } public int compareTo(mutateRow_result other) { @@ -28686,7 +29180,7 @@ public class Hbase { */ public long timestamp; // required /** - * Put attributes + * Mutation attributes */ public Map attributes; // required @@ -28709,7 +29203,7 @@ public class Hbase { */ TIMESTAMP((short)4, "timestamp"), /** - * Put attributes + * Mutation attributes */ ATTRIBUTES((short)5, "attributes"); @@ -29034,14 +29528,14 @@ public class Hbase { } /** - * Put attributes + * Mutation attributes */ public Map getAttributes() { return this.attributes; } /** - * Put attributes + * Mutation attributes */ public mutateRowTs_args setAttributes(Map attributes) { this.attributes = attributes; @@ -29213,7 +29707,34 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableName = true && (isSetTableName()); + builder.append(present_tableName); + if (present_tableName) + builder.append(tableName); + + boolean present_row = true && (isSetRow()); + builder.append(present_row); + if (present_row) + builder.append(row); + + boolean present_mutations = true && (isSetMutations()); + builder.append(present_mutations); + if (present_mutations) + builder.append(mutations); + + boolean present_timestamp = true; + builder.append(present_timestamp); + if (present_timestamp) + builder.append(timestamp); + + boolean present_attributes = true && (isSetAttributes()); + builder.append(present_attributes); + if (present_attributes) + builder.append(attributes); + + return builder.toHashCode(); } public int compareTo(mutateRowTs_args other) { @@ -29396,7 +29917,7 @@ public class Hbase { struct.mutations = new ArrayList(_list340.size); for (int _i341 = 0; _i341 < _list340.size; ++_i341) { - Mutation _elem342; // optional + Mutation _elem342; // required _elem342 = new Mutation(); _elem342.read(iprot); struct.mutations.add(_elem342); @@ -29424,7 +29945,7 @@ public class Hbase { for (int _i344 = 0; _i344 < _map343.size; ++_i344) { ByteBuffer _key345; // required - ByteBuffer _val346; // required + ByteBuffer _val346; // optional _key345 = iprot.readBinary(); _val346 = iprot.readBinary(); struct.attributes.put(_key345, _val346); @@ -29571,7 +30092,7 @@ public class Hbase { struct.mutations = new ArrayList(_list351.size); for (int _i352 = 0; _i352 < _list351.size; ++_i352) { - Mutation _elem353; // optional + Mutation _elem353; // required _elem353 = new Mutation(); _elem353.read(iprot); struct.mutations.add(_elem353); @@ -29590,7 +30111,7 @@ public class Hbase { for (int _i355 = 0; _i355 < _map354.size; ++_i355) { ByteBuffer _key356; // required - ByteBuffer _val357; // required + ByteBuffer _val357; // optional _key356 = iprot.readBinary(); _val357 = iprot.readBinary(); struct.attributes.put(_key356, _val357); @@ -29857,7 +30378,19 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + boolean present_ia = true && (isSetIa()); + builder.append(present_ia); + if (present_ia) + builder.append(ia); + + return builder.toHashCode(); } public int compareTo(mutateRowTs_result other) { @@ -30082,7 +30615,7 @@ public class Hbase { */ public List rowBatches; // required /** - * Put attributes + * Mutation attributes */ public Map attributes; // required @@ -30097,7 +30630,7 @@ public class Hbase { */ ROW_BATCHES((short)2, "rowBatches"), /** - * Put attributes + * Mutation attributes */ ATTRIBUTES((short)3, "attributes"); @@ -30329,14 +30862,14 @@ public class Hbase { } /** - * Put attributes + * Mutation attributes */ public Map getAttributes() { return this.attributes; } /** - * Put attributes + * Mutation attributes */ public mutateRows_args setAttributes(Map attributes) { this.attributes = attributes; @@ -30464,7 +30997,24 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableName = true && (isSetTableName()); + builder.append(present_tableName); + if (present_tableName) + builder.append(tableName); + + boolean present_rowBatches = true && (isSetRowBatches()); + builder.append(present_rowBatches); + if (present_rowBatches) + builder.append(rowBatches); + + boolean present_attributes = true && (isSetAttributes()); + builder.append(present_attributes); + if (present_attributes) + builder.append(attributes); + + return builder.toHashCode(); } public int compareTo(mutateRows_args other) { @@ -30605,7 +31155,7 @@ public class Hbase { struct.rowBatches = new ArrayList(_list358.size); for (int _i359 = 0; _i359 < _list358.size; ++_i359) { - BatchMutation _elem360; // optional + BatchMutation _elem360; // required _elem360 = new BatchMutation(); _elem360.read(iprot); struct.rowBatches.add(_elem360); @@ -30625,7 +31175,7 @@ public class Hbase { for (int _i362 = 0; _i362 < _map361.size; ++_i362) { ByteBuffer _key363; // required - ByteBuffer _val364; // required + ByteBuffer _val364; // optional _key363 = iprot.readBinary(); _val364 = iprot.readBinary(); struct.attributes.put(_key363, _val364); @@ -30748,7 +31298,7 @@ public class Hbase { struct.rowBatches = new ArrayList(_list369.size); for (int _i370 = 0; _i370 < _list369.size; ++_i370) { - BatchMutation _elem371; // optional + BatchMutation _elem371; // required _elem371 = new BatchMutation(); _elem371.read(iprot); struct.rowBatches.add(_elem371); @@ -30763,7 +31313,7 @@ public class Hbase { for (int _i373 = 0; _i373 < _map372.size; ++_i373) { ByteBuffer _key374; // required - ByteBuffer _val375; // required + ByteBuffer _val375; // optional _key374 = iprot.readBinary(); _val375 = iprot.readBinary(); struct.attributes.put(_key374, _val375); @@ -31030,7 +31580,19 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + boolean present_ia = true && (isSetIa()); + builder.append(present_ia); + if (present_ia) + builder.append(ia); + + return builder.toHashCode(); } public int compareTo(mutateRows_result other) { @@ -31260,7 +31822,7 @@ public class Hbase { */ public long timestamp; // required /** - * Put attributes + * Mutation attributes */ public Map attributes; // required @@ -31279,7 +31841,7 @@ public class Hbase { */ TIMESTAMP((short)3, "timestamp"), /** - * Put attributes + * Mutation attributes */ ATTRIBUTES((short)4, "attributes"); @@ -31554,14 +32116,14 @@ public class Hbase { } /** - * Put attributes + * Mutation attributes */ public Map getAttributes() { return this.attributes; } /** - * Put attributes + * Mutation attributes */ public mutateRowsTs_args setAttributes(Map attributes) { this.attributes = attributes; @@ -31711,7 +32273,29 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableName = true && (isSetTableName()); + builder.append(present_tableName); + if (present_tableName) + builder.append(tableName); + + boolean present_rowBatches = true && (isSetRowBatches()); + builder.append(present_rowBatches); + if (present_rowBatches) + builder.append(rowBatches); + + boolean present_timestamp = true; + builder.append(present_timestamp); + if (present_timestamp) + builder.append(timestamp); + + boolean present_attributes = true && (isSetAttributes()); + builder.append(present_attributes); + if (present_attributes) + builder.append(attributes); + + return builder.toHashCode(); } public int compareTo(mutateRowsTs_args other) { @@ -31866,7 +32450,7 @@ public class Hbase { struct.rowBatches = new ArrayList(_list376.size); for (int _i377 = 0; _i377 < _list376.size; ++_i377) { - BatchMutation _elem378; // optional + BatchMutation _elem378; // required _elem378 = new BatchMutation(); _elem378.read(iprot); struct.rowBatches.add(_elem378); @@ -31894,7 +32478,7 @@ public class Hbase { for (int _i380 = 0; _i380 < _map379.size; ++_i380) { ByteBuffer _key381; // required - ByteBuffer _val382; // required + ByteBuffer _val382; // optional _key381 = iprot.readBinary(); _val382 = iprot.readBinary(); struct.attributes.put(_key381, _val382); @@ -32026,7 +32610,7 @@ public class Hbase { struct.rowBatches = new ArrayList(_list387.size); for (int _i388 = 0; _i388 < _list387.size; ++_i388) { - BatchMutation _elem389; // optional + BatchMutation _elem389; // required _elem389 = new BatchMutation(); _elem389.read(iprot); struct.rowBatches.add(_elem389); @@ -32045,7 +32629,7 @@ public class Hbase { for (int _i391 = 0; _i391 < _map390.size; ++_i391) { ByteBuffer _key392; // required - ByteBuffer _val393; // required + ByteBuffer _val393; // optional _key392 = iprot.readBinary(); _val393 = iprot.readBinary(); struct.attributes.put(_key392, _val393); @@ -32312,7 +32896,19 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + boolean present_ia = true && (isSetIa()); + builder.append(present_ia); + if (present_ia) + builder.append(ia); + + return builder.toHashCode(); } public int compareTo(mutateRowsTs_result other) { @@ -32968,7 +33564,29 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableName = true && (isSetTableName()); + builder.append(present_tableName); + if (present_tableName) + builder.append(tableName); + + boolean present_row = true && (isSetRow()); + builder.append(present_row); + if (present_row) + builder.append(row); + + boolean present_column = true && (isSetColumn()); + builder.append(present_column); + if (present_column) + builder.append(column); + + boolean present_value = true; + builder.append(present_value); + if (present_value) + builder.append(value); + + return builder.toHashCode(); } public int compareTo(atomicIncrement_args other) { @@ -33561,7 +34179,24 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_success = true; + builder.append(present_success); + if (present_success) + builder.append(success); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + boolean present_ia = true && (isSetIa()); + builder.append(present_ia); + if (present_ia) + builder.append(ia); + + return builder.toHashCode(); } public int compareTo(atomicIncrement_result other) { @@ -33659,6 +34294,8 @@ public class Hbase { private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException { try { + // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor. + __isset_bit_vector = new BitSet(1); 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); @@ -34274,7 +34911,29 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableName = true && (isSetTableName()); + builder.append(present_tableName); + if (present_tableName) + builder.append(tableName); + + boolean present_row = true && (isSetRow()); + builder.append(present_row); + if (present_row) + builder.append(row); + + boolean present_column = true && (isSetColumn()); + builder.append(present_column); + if (present_column) + builder.append(column); + + boolean present_attributes = true && (isSetAttributes()); + builder.append(present_attributes); + if (present_attributes) + builder.append(attributes); + + return builder.toHashCode(); } public int compareTo(deleteAll_args other) { @@ -34450,7 +35109,7 @@ public class Hbase { for (int _i395 = 0; _i395 < _map394.size; ++_i395) { ByteBuffer _key396; // required - ByteBuffer _val397; // required + ByteBuffer _val397; // optional _key396 = iprot.readBinary(); _val397 = iprot.readBinary(); struct.attributes.put(_key396, _val397); @@ -34580,7 +35239,7 @@ public class Hbase { for (int _i401 = 0; _i401 < _map400.size; ++_i401) { ByteBuffer _key402; // required - ByteBuffer _val403; // required + ByteBuffer _val403; // optional _key402 = iprot.readBinary(); _val403 = iprot.readBinary(); struct.attributes.put(_key402, _val403); @@ -34788,7 +35447,14 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + return builder.toHashCode(); } public int compareTo(deleteAll_result other) { @@ -35497,7 +36163,34 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableName = true && (isSetTableName()); + builder.append(present_tableName); + if (present_tableName) + builder.append(tableName); + + boolean present_row = true && (isSetRow()); + builder.append(present_row); + if (present_row) + builder.append(row); + + boolean present_column = true && (isSetColumn()); + builder.append(present_column); + if (present_column) + builder.append(column); + + boolean present_timestamp = true; + builder.append(present_timestamp); + if (present_timestamp) + builder.append(timestamp); + + boolean present_attributes = true && (isSetAttributes()); + builder.append(present_attributes); + if (present_attributes) + builder.append(attributes); + + return builder.toHashCode(); } public int compareTo(deleteAllTs_args other) { @@ -35697,7 +36390,7 @@ public class Hbase { for (int _i405 = 0; _i405 < _map404.size; ++_i405) { ByteBuffer _key406; // required - ByteBuffer _val407; // required + ByteBuffer _val407; // optional _key406 = iprot.readBinary(); _val407 = iprot.readBinary(); struct.attributes.put(_key406, _val407); @@ -35840,7 +36533,7 @@ public class Hbase { for (int _i411 = 0; _i411 < _map410.size; ++_i411) { ByteBuffer _key412; // required - ByteBuffer _val413; // required + ByteBuffer _val413; // optional _key412 = iprot.readBinary(); _val413 = iprot.readBinary(); struct.attributes.put(_key412, _val413); @@ -36048,7 +36741,14 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + return builder.toHashCode(); } public int compareTo(deleteAllTs_result other) { @@ -36602,7 +37302,24 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableName = true && (isSetTableName()); + builder.append(present_tableName); + if (present_tableName) + builder.append(tableName); + + boolean present_row = true && (isSetRow()); + builder.append(present_row); + if (present_row) + builder.append(row); + + boolean present_attributes = true && (isSetAttributes()); + builder.append(present_attributes); + if (present_attributes) + builder.append(attributes); + + return builder.toHashCode(); } public int compareTo(deleteAllRow_args other) { @@ -36752,7 +37469,7 @@ public class Hbase { for (int _i415 = 0; _i415 < _map414.size; ++_i415) { ByteBuffer _key416; // required - ByteBuffer _val417; // required + ByteBuffer _val417; // optional _key416 = iprot.readBinary(); _val417 = iprot.readBinary(); struct.attributes.put(_key416, _val417); @@ -36867,7 +37584,7 @@ public class Hbase { for (int _i421 = 0; _i421 < _map420.size; ++_i421) { ByteBuffer _key422; // required - ByteBuffer _val423; // required + ByteBuffer _val423; // optional _key422 = iprot.readBinary(); _val423 = iprot.readBinary(); struct.attributes.put(_key422, _val423); @@ -37075,7 +37792,14 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + return builder.toHashCode(); } public int compareTo(deleteAllRow_result other) { @@ -37703,7 +38427,29 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableName = true && (isSetTableName()); + builder.append(present_tableName); + if (present_tableName) + builder.append(tableName); + + boolean present_row = true && (isSetRow()); + builder.append(present_row); + if (present_row) + builder.append(row); + + boolean present_timestamp = true; + builder.append(present_timestamp); + if (present_timestamp) + builder.append(timestamp); + + boolean present_attributes = true && (isSetAttributes()); + builder.append(present_attributes); + if (present_attributes) + builder.append(attributes); + + return builder.toHashCode(); } public int compareTo(deleteAllRowTs_args other) { @@ -37877,7 +38623,7 @@ public class Hbase { for (int _i425 = 0; _i425 < _map424.size; ++_i425) { ByteBuffer _key426; // required - ByteBuffer _val427; // required + ByteBuffer _val427; // optional _key426 = iprot.readBinary(); _val427 = iprot.readBinary(); struct.attributes.put(_key426, _val427); @@ -38005,7 +38751,7 @@ public class Hbase { for (int _i431 = 0; _i431 < _map430.size; ++_i431) { ByteBuffer _key432; // required - ByteBuffer _val433; // required + ByteBuffer _val433; // optional _key432 = iprot.readBinary(); _val433 = iprot.readBinary(); struct.attributes.put(_key432, _val433); @@ -38213,7 +38959,14 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + return builder.toHashCode(); } public int compareTo(deleteAllRowTs_result other) { @@ -38757,7 +39510,24 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableName = true && (isSetTableName()); + builder.append(present_tableName); + if (present_tableName) + builder.append(tableName); + + boolean present_scan = true && (isSetScan()); + builder.append(present_scan); + if (present_scan) + builder.append(scan); + + boolean present_attributes = true && (isSetAttributes()); + builder.append(present_attributes); + if (present_attributes) + builder.append(attributes); + + return builder.toHashCode(); } public int compareTo(scannerOpenWithScan_args other) { @@ -38908,7 +39678,7 @@ public class Hbase { for (int _i435 = 0; _i435 < _map434.size; ++_i435) { ByteBuffer _key436; // required - ByteBuffer _val437; // required + ByteBuffer _val437; // optional _key436 = iprot.readBinary(); _val437 = iprot.readBinary(); struct.attributes.put(_key436, _val437); @@ -39024,7 +39794,7 @@ public class Hbase { for (int _i441 = 0; _i441 < _map440.size; ++_i441) { ByteBuffer _key442; // required - ByteBuffer _val443; // required + ByteBuffer _val443; // optional _key442 = iprot.readBinary(); _val443 = iprot.readBinary(); struct.attributes.put(_key442, _val443); @@ -39294,7 +40064,19 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_success = true; + builder.append(present_success); + if (present_success) + builder.append(success); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + return builder.toHashCode(); } public int compareTo(scannerOpenWithScan_result other) { @@ -39374,6 +40156,8 @@ public class Hbase { private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException { try { + // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor. + __isset_bit_vector = new BitSet(1); 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); @@ -39986,7 +40770,29 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableName = true && (isSetTableName()); + builder.append(present_tableName); + if (present_tableName) + builder.append(tableName); + + boolean present_startRow = true && (isSetStartRow()); + builder.append(present_startRow); + if (present_startRow) + builder.append(startRow); + + boolean present_columns = true && (isSetColumns()); + builder.append(present_columns); + if (present_columns) + builder.append(columns); + + boolean present_attributes = true && (isSetAttributes()); + builder.append(present_attributes); + if (present_attributes) + builder.append(attributes); + + return builder.toHashCode(); } public int compareTo(scannerOpen_args other) { @@ -40153,7 +40959,7 @@ public class Hbase { struct.columns = new ArrayList(_list444.size); for (int _i445 = 0; _i445 < _list444.size; ++_i445) { - ByteBuffer _elem446; // optional + ByteBuffer _elem446; // required _elem446 = iprot.readBinary(); struct.columns.add(_elem446); } @@ -40172,7 +40978,7 @@ public class Hbase { for (int _i448 = 0; _i448 < _map447.size; ++_i448) { ByteBuffer _key449; // required - ByteBuffer _val450; // required + ByteBuffer _val450; // optional _key449 = iprot.readBinary(); _val450 = iprot.readBinary(); struct.attributes.put(_key449, _val450); @@ -40310,7 +41116,7 @@ public class Hbase { struct.columns = new ArrayList(_list455.size); for (int _i456 = 0; _i456 < _list455.size; ++_i456) { - ByteBuffer _elem457; // optional + ByteBuffer _elem457; // required _elem457 = iprot.readBinary(); struct.columns.add(_elem457); } @@ -40324,7 +41130,7 @@ public class Hbase { for (int _i459 = 0; _i459 < _map458.size; ++_i459) { ByteBuffer _key460; // required - ByteBuffer _val461; // required + ByteBuffer _val461; // optional _key460 = iprot.readBinary(); _val461 = iprot.readBinary(); struct.attributes.put(_key460, _val461); @@ -40594,7 +41400,19 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_success = true; + builder.append(present_success); + if (present_success) + builder.append(success); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + return builder.toHashCode(); } public int compareTo(scannerOpen_result other) { @@ -40674,6 +41492,8 @@ public class Hbase { private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException { try { + // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor. + __isset_bit_vector = new BitSet(1); 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); @@ -41371,7 +42191,34 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableName = true && (isSetTableName()); + builder.append(present_tableName); + if (present_tableName) + builder.append(tableName); + + boolean present_startRow = true && (isSetStartRow()); + builder.append(present_startRow); + if (present_startRow) + builder.append(startRow); + + boolean present_stopRow = true && (isSetStopRow()); + builder.append(present_stopRow); + if (present_stopRow) + builder.append(stopRow); + + boolean present_columns = true && (isSetColumns()); + builder.append(present_columns); + if (present_columns) + builder.append(columns); + + boolean present_attributes = true && (isSetAttributes()); + builder.append(present_attributes); + if (present_attributes) + builder.append(attributes); + + return builder.toHashCode(); } public int compareTo(scannerOpenWithStop_args other) { @@ -41564,7 +42411,7 @@ public class Hbase { struct.columns = new ArrayList(_list462.size); for (int _i463 = 0; _i463 < _list462.size; ++_i463) { - ByteBuffer _elem464; // optional + ByteBuffer _elem464; // required _elem464 = iprot.readBinary(); struct.columns.add(_elem464); } @@ -41583,7 +42430,7 @@ public class Hbase { for (int _i466 = 0; _i466 < _map465.size; ++_i466) { ByteBuffer _key467; // required - ByteBuffer _val468; // required + ByteBuffer _val468; // optional _key467 = iprot.readBinary(); _val468 = iprot.readBinary(); struct.attributes.put(_key467, _val468); @@ -41736,7 +42583,7 @@ public class Hbase { struct.columns = new ArrayList(_list473.size); for (int _i474 = 0; _i474 < _list473.size; ++_i474) { - ByteBuffer _elem475; // optional + ByteBuffer _elem475; // required _elem475 = iprot.readBinary(); struct.columns.add(_elem475); } @@ -41750,7 +42597,7 @@ public class Hbase { for (int _i477 = 0; _i477 < _map476.size; ++_i477) { ByteBuffer _key478; // required - ByteBuffer _val479; // required + ByteBuffer _val479; // optional _key478 = iprot.readBinary(); _val479 = iprot.readBinary(); struct.attributes.put(_key478, _val479); @@ -42020,7 +42867,19 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_success = true; + builder.append(present_success); + if (present_success) + builder.append(success); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + return builder.toHashCode(); } public int compareTo(scannerOpenWithStop_result other) { @@ -42100,6 +42959,8 @@ public class Hbase { private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException { try { + // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor. + __isset_bit_vector = new BitSet(1); 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); @@ -42700,7 +43561,29 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableName = true && (isSetTableName()); + builder.append(present_tableName); + if (present_tableName) + builder.append(tableName); + + boolean present_startAndPrefix = true && (isSetStartAndPrefix()); + builder.append(present_startAndPrefix); + if (present_startAndPrefix) + builder.append(startAndPrefix); + + boolean present_columns = true && (isSetColumns()); + builder.append(present_columns); + if (present_columns) + builder.append(columns); + + boolean present_attributes = true && (isSetAttributes()); + builder.append(present_attributes); + if (present_attributes) + builder.append(attributes); + + return builder.toHashCode(); } public int compareTo(scannerOpenWithPrefix_args other) { @@ -42867,7 +43750,7 @@ public class Hbase { struct.columns = new ArrayList(_list480.size); for (int _i481 = 0; _i481 < _list480.size; ++_i481) { - ByteBuffer _elem482; // optional + ByteBuffer _elem482; // required _elem482 = iprot.readBinary(); struct.columns.add(_elem482); } @@ -42886,7 +43769,7 @@ public class Hbase { for (int _i484 = 0; _i484 < _map483.size; ++_i484) { ByteBuffer _key485; // required - ByteBuffer _val486; // required + ByteBuffer _val486; // optional _key485 = iprot.readBinary(); _val486 = iprot.readBinary(); struct.attributes.put(_key485, _val486); @@ -43024,7 +43907,7 @@ public class Hbase { struct.columns = new ArrayList(_list491.size); for (int _i492 = 0; _i492 < _list491.size; ++_i492) { - ByteBuffer _elem493; // optional + ByteBuffer _elem493; // required _elem493 = iprot.readBinary(); struct.columns.add(_elem493); } @@ -43038,7 +43921,7 @@ public class Hbase { for (int _i495 = 0; _i495 < _map494.size; ++_i495) { ByteBuffer _key496; // required - ByteBuffer _val497; // required + ByteBuffer _val497; // optional _key496 = iprot.readBinary(); _val497 = iprot.readBinary(); struct.attributes.put(_key496, _val497); @@ -43308,7 +44191,19 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_success = true; + builder.append(present_success); + if (present_success) + builder.append(success); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + return builder.toHashCode(); } public int compareTo(scannerOpenWithPrefix_result other) { @@ -43388,6 +44283,8 @@ public class Hbase { private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException { try { + // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor. + __isset_bit_vector = new BitSet(1); 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); @@ -44074,7 +44971,34 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableName = true && (isSetTableName()); + builder.append(present_tableName); + if (present_tableName) + builder.append(tableName); + + boolean present_startRow = true && (isSetStartRow()); + builder.append(present_startRow); + if (present_startRow) + builder.append(startRow); + + boolean present_columns = true && (isSetColumns()); + builder.append(present_columns); + if (present_columns) + builder.append(columns); + + boolean present_timestamp = true; + builder.append(present_timestamp); + if (present_timestamp) + builder.append(timestamp); + + boolean present_attributes = true && (isSetAttributes()); + builder.append(present_attributes); + if (present_attributes) + builder.append(attributes); + + return builder.toHashCode(); } public int compareTo(scannerOpenTs_args other) { @@ -44255,7 +45179,7 @@ public class Hbase { struct.columns = new ArrayList(_list498.size); for (int _i499 = 0; _i499 < _list498.size; ++_i499) { - ByteBuffer _elem500; // optional + ByteBuffer _elem500; // required _elem500 = iprot.readBinary(); struct.columns.add(_elem500); } @@ -44282,7 +45206,7 @@ public class Hbase { for (int _i502 = 0; _i502 < _map501.size; ++_i502) { ByteBuffer _key503; // required - ByteBuffer _val504; // required + ByteBuffer _val504; // optional _key503 = iprot.readBinary(); _val504 = iprot.readBinary(); struct.attributes.put(_key503, _val504); @@ -44429,7 +45353,7 @@ public class Hbase { struct.columns = new ArrayList(_list509.size); for (int _i510 = 0; _i510 < _list509.size; ++_i510) { - ByteBuffer _elem511; // optional + ByteBuffer _elem511; // required _elem511 = iprot.readBinary(); struct.columns.add(_elem511); } @@ -44447,7 +45371,7 @@ public class Hbase { for (int _i513 = 0; _i513 < _map512.size; ++_i513) { ByteBuffer _key514; // required - ByteBuffer _val515; // required + ByteBuffer _val515; // optional _key514 = iprot.readBinary(); _val515 = iprot.readBinary(); struct.attributes.put(_key514, _val515); @@ -44717,7 +45641,19 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_success = true; + builder.append(present_success); + if (present_success) + builder.append(success); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + return builder.toHashCode(); } public int compareTo(scannerOpenTs_result other) { @@ -44797,6 +45733,8 @@ public class Hbase { private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException { try { + // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor. + __isset_bit_vector = new BitSet(1); 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); @@ -45568,7 +46506,39 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_tableName = true && (isSetTableName()); + builder.append(present_tableName); + if (present_tableName) + builder.append(tableName); + + boolean present_startRow = true && (isSetStartRow()); + builder.append(present_startRow); + if (present_startRow) + builder.append(startRow); + + boolean present_stopRow = true && (isSetStopRow()); + builder.append(present_stopRow); + if (present_stopRow) + builder.append(stopRow); + + boolean present_columns = true && (isSetColumns()); + builder.append(present_columns); + if (present_columns) + builder.append(columns); + + boolean present_timestamp = true; + builder.append(present_timestamp); + if (present_timestamp) + builder.append(timestamp); + + boolean present_attributes = true && (isSetAttributes()); + builder.append(present_attributes); + if (present_attributes) + builder.append(attributes); + + return builder.toHashCode(); } public int compareTo(scannerOpenWithStopTs_args other) { @@ -45775,7 +46745,7 @@ public class Hbase { struct.columns = new ArrayList(_list516.size); for (int _i517 = 0; _i517 < _list516.size; ++_i517) { - ByteBuffer _elem518; // optional + ByteBuffer _elem518; // required _elem518 = iprot.readBinary(); struct.columns.add(_elem518); } @@ -45802,7 +46772,7 @@ public class Hbase { for (int _i520 = 0; _i520 < _map519.size; ++_i520) { ByteBuffer _key521; // required - ByteBuffer _val522; // required + ByteBuffer _val522; // optional _key521 = iprot.readBinary(); _val522 = iprot.readBinary(); struct.attributes.put(_key521, _val522); @@ -45964,7 +46934,7 @@ public class Hbase { struct.columns = new ArrayList(_list527.size); for (int _i528 = 0; _i528 < _list527.size; ++_i528) { - ByteBuffer _elem529; // optional + ByteBuffer _elem529; // required _elem529 = iprot.readBinary(); struct.columns.add(_elem529); } @@ -45982,7 +46952,7 @@ public class Hbase { for (int _i531 = 0; _i531 < _map530.size; ++_i531) { ByteBuffer _key532; // required - ByteBuffer _val533; // required + ByteBuffer _val533; // optional _key532 = iprot.readBinary(); _val533 = iprot.readBinary(); struct.attributes.put(_key532, _val533); @@ -46252,7 +47222,19 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_success = true; + builder.append(present_success); + if (present_success) + builder.append(success); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + return builder.toHashCode(); } public int compareTo(scannerOpenWithStopTs_result other) { @@ -46332,6 +47314,8 @@ public class Hbase { private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException { try { + // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor. + __isset_bit_vector = new BitSet(1); 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); @@ -46657,7 +47641,14 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_id = true; + builder.append(present_id); + if (present_id) + builder.append(id); + + return builder.toHashCode(); } public int compareTo(scannerGet_args other) { @@ -47144,7 +48135,24 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_success = true && (isSetSuccess()); + builder.append(present_success); + if (present_success) + builder.append(success); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + boolean present_ia = true && (isSetIa()); + builder.append(present_ia); + if (present_ia) + builder.append(ia); + + return builder.toHashCode(); } public int compareTo(scannerGet_result other) { @@ -47277,7 +48285,7 @@ public class Hbase { struct.success = new ArrayList(_list534.size); for (int _i535 = 0; _i535 < _list534.size; ++_i535) { - TRowResult _elem536; // optional + TRowResult _elem536; // required _elem536 = new TRowResult(); _elem536.read(iprot); struct.success.add(_elem536); @@ -47399,7 +48407,7 @@ public class Hbase { struct.success = new ArrayList(_list539.size); for (int _i540 = 0; _i540 < _list539.size; ++_i540) { - TRowResult _elem541; // optional + TRowResult _elem541; // required _elem541 = new TRowResult(); _elem541.read(iprot); struct.success.add(_elem541); @@ -47703,7 +48711,19 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_id = true; + builder.append(present_id); + if (present_id) + builder.append(id); + + boolean present_nbRows = true; + builder.append(present_nbRows); + if (present_nbRows) + builder.append(nbRows); + + return builder.toHashCode(); } public int compareTo(scannerGetList_args other) { @@ -48223,7 +49243,24 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_success = true && (isSetSuccess()); + builder.append(present_success); + if (present_success) + builder.append(success); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + boolean present_ia = true && (isSetIa()); + builder.append(present_ia); + if (present_ia) + builder.append(ia); + + return builder.toHashCode(); } public int compareTo(scannerGetList_result other) { @@ -48356,7 +49393,7 @@ public class Hbase { struct.success = new ArrayList(_list542.size); for (int _i543 = 0; _i543 < _list542.size; ++_i543) { - TRowResult _elem544; // optional + TRowResult _elem544; // required _elem544 = new TRowResult(); _elem544.read(iprot); struct.success.add(_elem544); @@ -48478,7 +49515,7 @@ public class Hbase { struct.success = new ArrayList(_list547.size); for (int _i548 = 0; _i548 < _list547.size; ++_i548) { - TRowResult _elem549; // optional + TRowResult _elem549; // required _elem549 = new TRowResult(); _elem549.read(iprot); struct.success.add(_elem549); @@ -48711,7 +49748,14 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_id = true; + builder.append(present_id); + if (present_id) + builder.append(id); + + return builder.toHashCode(); } public int compareTo(scannerClose_args other) { @@ -49119,7 +50163,19 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + boolean present_ia = true && (isSetIa()); + builder.append(present_ia); + if (present_ia) + builder.append(ia); + + return builder.toHashCode(); } public int compareTo(scannerClose_result other) { @@ -49322,46 +50378,28 @@ public class Hbase { } - public static class getRowOrBefore_args implements org.apache.thrift.TBase, java.io.Serializable, Cloneable { - private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getRowOrBefore_args"); + public static class getRegionInfo_args implements org.apache.thrift.TBase, java.io.Serializable, Cloneable { + private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getRegionInfo_args"); - private static final org.apache.thrift.protocol.TField TABLE_NAME_FIELD_DESC = new org.apache.thrift.protocol.TField("tableName", org.apache.thrift.protocol.TType.STRING, (short)1); - private static final org.apache.thrift.protocol.TField ROW_FIELD_DESC = new org.apache.thrift.protocol.TField("row", org.apache.thrift.protocol.TType.STRING, (short)2); - private static final org.apache.thrift.protocol.TField FAMILY_FIELD_DESC = new org.apache.thrift.protocol.TField("family", org.apache.thrift.protocol.TType.STRING, (short)3); + private static final org.apache.thrift.protocol.TField ROW_FIELD_DESC = new org.apache.thrift.protocol.TField("row", org.apache.thrift.protocol.TType.STRING, (short)1); private static final Map, SchemeFactory> schemes = new HashMap, SchemeFactory>(); static { - schemes.put(StandardScheme.class, new getRowOrBefore_argsStandardSchemeFactory()); - schemes.put(TupleScheme.class, new getRowOrBefore_argsTupleSchemeFactory()); + schemes.put(StandardScheme.class, new getRegionInfo_argsStandardSchemeFactory()); + schemes.put(TupleScheme.class, new getRegionInfo_argsTupleSchemeFactory()); } /** - * name of table - */ - public ByteBuffer tableName; // required - /** * row key */ public ByteBuffer row; // required - /** - * column name - */ - public ByteBuffer family; // 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 { /** - * name of table - */ - TABLE_NAME((short)1, "tableName"), - /** * row key */ - ROW((short)2, "row"), - /** - * column name - */ - FAMILY((short)3, "family"); + ROW((short)1, "row"); private static final Map byName = new HashMap(); @@ -49376,12 +50414,8 @@ public class Hbase { */ public static _Fields findByThriftId(int fieldId) { switch(fieldId) { - case 1: // TABLE_NAME - return TABLE_NAME; - case 2: // ROW + case 1: // ROW return ROW; - case 3: // FAMILY - return FAMILY; default: return null; } @@ -49425,94 +50459,38 @@ public class Hbase { public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap; static { Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class); - tmpMap.put(_Fields.TABLE_NAME, new org.apache.thrift.meta_data.FieldMetaData("tableName", org.apache.thrift.TFieldRequirementType.DEFAULT, - new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING , "Text"))); tmpMap.put(_Fields.ROW, new org.apache.thrift.meta_data.FieldMetaData("row", org.apache.thrift.TFieldRequirementType.DEFAULT, new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING , "Text"))); - tmpMap.put(_Fields.FAMILY, new org.apache.thrift.meta_data.FieldMetaData("family", org.apache.thrift.TFieldRequirementType.DEFAULT, - new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING , "Text"))); metaDataMap = Collections.unmodifiableMap(tmpMap); - org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getRowOrBefore_args.class, metaDataMap); + org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getRegionInfo_args.class, metaDataMap); } - public getRowOrBefore_args() { + public getRegionInfo_args() { } - public getRowOrBefore_args( - ByteBuffer tableName, - ByteBuffer row, - ByteBuffer family) + public getRegionInfo_args( + ByteBuffer row) { this(); - this.tableName = tableName; this.row = row; - this.family = family; } /** * Performs a deep copy on other. */ - public getRowOrBefore_args(getRowOrBefore_args other) { - if (other.isSetTableName()) { - this.tableName = other.tableName; - } + public getRegionInfo_args(getRegionInfo_args other) { if (other.isSetRow()) { this.row = other.row; } - if (other.isSetFamily()) { - this.family = other.family; - } } - public getRowOrBefore_args deepCopy() { - return new getRowOrBefore_args(this); + public getRegionInfo_args deepCopy() { + return new getRegionInfo_args(this); } @Override public void clear() { - this.tableName = null; this.row = null; - this.family = null; - } - - /** - * name of table - */ - public byte[] getTableName() { - setTableName(org.apache.thrift.TBaseHelper.rightSize(tableName)); - return tableName == null ? null : tableName.array(); - } - - public ByteBuffer bufferForTableName() { - return tableName; - } - - /** - * name of table - */ - public getRowOrBefore_args setTableName(byte[] tableName) { - setTableName(tableName == null ? (ByteBuffer)null : ByteBuffer.wrap(tableName)); - return this; - } - - public getRowOrBefore_args setTableName(ByteBuffer tableName) { - this.tableName = tableName; - return this; - } - - public void unsetTableName() { - this.tableName = null; - } - - /** Returns true if field tableName is set (has been assigned a value) and false otherwise */ - public boolean isSetTableName() { - return this.tableName != null; - } - - public void setTableNameIsSet(boolean value) { - if (!value) { - this.tableName = null; - } } /** @@ -49530,12 +50508,12 @@ public class Hbase { /** * row key */ - public getRowOrBefore_args setRow(byte[] row) { + public getRegionInfo_args setRow(byte[] row) { setRow(row == null ? (ByteBuffer)null : ByteBuffer.wrap(row)); return this; } - public getRowOrBefore_args setRow(ByteBuffer row) { + public getRegionInfo_args setRow(ByteBuffer row) { this.row = row; return this; } @@ -49555,56 +50533,8 @@ public class Hbase { } } - /** - * column name - */ - public byte[] getFamily() { - setFamily(org.apache.thrift.TBaseHelper.rightSize(family)); - return family == null ? null : family.array(); - } - - public ByteBuffer bufferForFamily() { - return family; - } - - /** - * column name - */ - public getRowOrBefore_args setFamily(byte[] family) { - setFamily(family == null ? (ByteBuffer)null : ByteBuffer.wrap(family)); - return this; - } - - public getRowOrBefore_args setFamily(ByteBuffer family) { - this.family = family; - return this; - } - - public void unsetFamily() { - this.family = null; - } - - /** Returns true if field family is set (has been assigned a value) and false otherwise */ - public boolean isSetFamily() { - return this.family != null; - } - - public void setFamilyIsSet(boolean value) { - if (!value) { - this.family = null; - } - } - public void setFieldValue(_Fields field, Object value) { switch (field) { - case TABLE_NAME: - if (value == null) { - unsetTableName(); - } else { - setTableName((ByteBuffer)value); - } - break; - case ROW: if (value == null) { unsetRow(); @@ -49613,28 +50543,14 @@ public class Hbase { } break; - case FAMILY: - if (value == null) { - unsetFamily(); - } else { - setFamily((ByteBuffer)value); - } - break; - } } public Object getFieldValue(_Fields field) { switch (field) { - case TABLE_NAME: - return getTableName(); - case ROW: return getRow(); - case FAMILY: - return getFamily(); - } throw new IllegalStateException(); } @@ -49646,12 +50562,8 @@ public class Hbase { } switch (field) { - case TABLE_NAME: - return isSetTableName(); case ROW: return isSetRow(); - case FAMILY: - return isSetFamily(); } throw new IllegalStateException(); } @@ -49660,24 +50572,15 @@ public class Hbase { public boolean equals(Object that) { if (that == null) return false; - if (that instanceof getRowOrBefore_args) - return this.equals((getRowOrBefore_args)that); + if (that instanceof getRegionInfo_args) + return this.equals((getRegionInfo_args)that); return false; } - public boolean equals(getRowOrBefore_args that) { + public boolean equals(getRegionInfo_args that) { if (that == null) return false; - boolean this_present_tableName = true && this.isSetTableName(); - boolean that_present_tableName = true && that.isSetTableName(); - if (this_present_tableName || that_present_tableName) { - if (!(this_present_tableName && that_present_tableName)) - return false; - if (!this.tableName.equals(that.tableName)) - return false; - } - boolean this_present_row = true && this.isSetRow(); boolean that_present_row = true && that.isSetRow(); if (this_present_row || that_present_row) { @@ -49687,41 +50590,29 @@ public class Hbase { return false; } - boolean this_present_family = true && this.isSetFamily(); - boolean that_present_family = true && that.isSetFamily(); - if (this_present_family || that_present_family) { - if (!(this_present_family && that_present_family)) - return false; - if (!this.family.equals(that.family)) - return false; - } - return true; } @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_row = true && (isSetRow()); + builder.append(present_row); + if (present_row) + builder.append(row); + + return builder.toHashCode(); } - public int compareTo(getRowOrBefore_args other) { + public int compareTo(getRegionInfo_args other) { if (!getClass().equals(other.getClass())) { return getClass().getName().compareTo(other.getClass().getName()); } int lastComparison = 0; - getRowOrBefore_args typedOther = (getRowOrBefore_args)other; + getRegionInfo_args typedOther = (getRegionInfo_args)other; - lastComparison = Boolean.valueOf(isSetTableName()).compareTo(typedOther.isSetTableName()); - if (lastComparison != 0) { - return lastComparison; - } - if (isSetTableName()) { - lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.tableName, typedOther.tableName); - if (lastComparison != 0) { - return lastComparison; - } - } lastComparison = Boolean.valueOf(isSetRow()).compareTo(typedOther.isSetRow()); if (lastComparison != 0) { return lastComparison; @@ -49732,16 +50623,6 @@ public class Hbase { return lastComparison; } } - lastComparison = Boolean.valueOf(isSetFamily()).compareTo(typedOther.isSetFamily()); - if (lastComparison != 0) { - return lastComparison; - } - if (isSetFamily()) { - lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.family, typedOther.family); - if (lastComparison != 0) { - return lastComparison; - } - } return 0; } @@ -49759,953 +50640,7 @@ public class Hbase { @Override public String toString() { - StringBuilder sb = new StringBuilder("getRowOrBefore_args("); - boolean first = true; - - sb.append("tableName:"); - if (this.tableName == null) { - sb.append("null"); - } else { - sb.append(this.tableName); - } - first = false; - if (!first) sb.append(", "); - sb.append("row:"); - if (this.row == null) { - sb.append("null"); - } else { - sb.append(this.row); - } - first = false; - if (!first) sb.append(", "); - sb.append("family:"); - if (this.family == null) { - sb.append("null"); - } else { - sb.append(this.family); - } - first = false; - sb.append(")"); - return sb.toString(); - } - - public void validate() throws org.apache.thrift.TException { - // check for required fields - } - - 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, 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 getRowOrBefore_argsStandardSchemeFactory implements SchemeFactory { - public getRowOrBefore_argsStandardScheme getScheme() { - return new getRowOrBefore_argsStandardScheme(); - } - } - - private static class getRowOrBefore_argsStandardScheme extends StandardScheme { - - public void read(org.apache.thrift.protocol.TProtocol iprot, getRowOrBefore_args 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_NAME - if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { - struct.tableName = iprot.readBinary(); - struct.setTableNameIsSet(true); - } else { - org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); - } - break; - case 2: // ROW - if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { - struct.row = iprot.readBinary(); - struct.setRowIsSet(true); - } else { - org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); - } - break; - case 3: // FAMILY - if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { - struct.family = iprot.readBinary(); - struct.setFamilyIsSet(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, getRowOrBefore_args struct) throws org.apache.thrift.TException { - struct.validate(); - - oprot.writeStructBegin(STRUCT_DESC); - if (struct.tableName != null) { - oprot.writeFieldBegin(TABLE_NAME_FIELD_DESC); - oprot.writeBinary(struct.tableName); - oprot.writeFieldEnd(); - } - if (struct.row != null) { - oprot.writeFieldBegin(ROW_FIELD_DESC); - oprot.writeBinary(struct.row); - oprot.writeFieldEnd(); - } - if (struct.family != null) { - oprot.writeFieldBegin(FAMILY_FIELD_DESC); - oprot.writeBinary(struct.family); - oprot.writeFieldEnd(); - } - oprot.writeFieldStop(); - oprot.writeStructEnd(); - } - - } - - private static class getRowOrBefore_argsTupleSchemeFactory implements SchemeFactory { - public getRowOrBefore_argsTupleScheme getScheme() { - return new getRowOrBefore_argsTupleScheme(); - } - } - - private static class getRowOrBefore_argsTupleScheme extends TupleScheme { - - @Override - public void write(org.apache.thrift.protocol.TProtocol prot, getRowOrBefore_args struct) throws org.apache.thrift.TException { - TTupleProtocol oprot = (TTupleProtocol) prot; - BitSet optionals = new BitSet(); - if (struct.isSetTableName()) { - optionals.set(0); - } - if (struct.isSetRow()) { - optionals.set(1); - } - if (struct.isSetFamily()) { - optionals.set(2); - } - oprot.writeBitSet(optionals, 3); - if (struct.isSetTableName()) { - oprot.writeBinary(struct.tableName); - } - if (struct.isSetRow()) { - oprot.writeBinary(struct.row); - } - if (struct.isSetFamily()) { - oprot.writeBinary(struct.family); - } - } - - @Override - public void read(org.apache.thrift.protocol.TProtocol prot, getRowOrBefore_args struct) throws org.apache.thrift.TException { - TTupleProtocol iprot = (TTupleProtocol) prot; - BitSet incoming = iprot.readBitSet(3); - if (incoming.get(0)) { - struct.tableName = iprot.readBinary(); - struct.setTableNameIsSet(true); - } - if (incoming.get(1)) { - struct.row = iprot.readBinary(); - struct.setRowIsSet(true); - } - if (incoming.get(2)) { - struct.family = iprot.readBinary(); - struct.setFamilyIsSet(true); - } - } - } - - } - - public static class getRowOrBefore_result implements org.apache.thrift.TBase, java.io.Serializable, Cloneable { - private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getRowOrBefore_result"); - - private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.LIST, (short)0); - private static final org.apache.thrift.protocol.TField IO_FIELD_DESC = new org.apache.thrift.protocol.TField("io", org.apache.thrift.protocol.TType.STRUCT, (short)1); - - private static final Map, SchemeFactory> schemes = new HashMap, SchemeFactory>(); - static { - schemes.put(StandardScheme.class, new getRowOrBefore_resultStandardSchemeFactory()); - schemes.put(TupleScheme.class, new getRowOrBefore_resultTupleSchemeFactory()); - } - - public List success; // required - public IOError io; // 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 { - SUCCESS((short)0, "success"), - IO((short)1, "io"); - - private static final Map byName = new HashMap(); - - static { - for (_Fields field : 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 0: // SUCCESS - return SUCCESS; - case 1: // IO - return IO; - 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 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(String name) { - return byName.get(name); - } - - private final short _thriftId; - private final String _fieldName; - - _Fields(short thriftId, String fieldName) { - _thriftId = thriftId; - _fieldName = fieldName; - } - - public short getThriftFieldId() { - return _thriftId; - } - - public String getFieldName() { - return _fieldName; - } - } - - // isset id assignments - public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap; - static { - Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class); - tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", 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, TCell.class)))); - tmpMap.put(_Fields.IO, new org.apache.thrift.meta_data.FieldMetaData("io", org.apache.thrift.TFieldRequirementType.DEFAULT, - new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT))); - metaDataMap = Collections.unmodifiableMap(tmpMap); - org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getRowOrBefore_result.class, metaDataMap); - } - - public getRowOrBefore_result() { - } - - public getRowOrBefore_result( - List success, - IOError io) - { - this(); - this.success = success; - this.io = io; - } - - /** - * Performs a deep copy on other. - */ - public getRowOrBefore_result(getRowOrBefore_result other) { - if (other.isSetSuccess()) { - List __this__success = new ArrayList(); - for (TCell other_element : other.success) { - __this__success.add(new TCell(other_element)); - } - this.success = __this__success; - } - if (other.isSetIo()) { - this.io = new IOError(other.io); - } - } - - public getRowOrBefore_result deepCopy() { - return new getRowOrBefore_result(this); - } - - @Override - public void clear() { - this.success = null; - this.io = null; - } - - public int getSuccessSize() { - return (this.success == null) ? 0 : this.success.size(); - } - - public java.util.Iterator getSuccessIterator() { - return (this.success == null) ? null : this.success.iterator(); - } - - public void addToSuccess(TCell elem) { - if (this.success == null) { - this.success = new ArrayList(); - } - this.success.add(elem); - } - - public List getSuccess() { - return this.success; - } - - public getRowOrBefore_result setSuccess(List success) { - this.success = success; - return this; - } - - public void unsetSuccess() { - this.success = null; - } - - /** Returns true if field success is set (has been assigned a value) and false otherwise */ - public boolean isSetSuccess() { - return this.success != null; - } - - public void setSuccessIsSet(boolean value) { - if (!value) { - this.success = null; - } - } - - public IOError getIo() { - return this.io; - } - - public getRowOrBefore_result setIo(IOError io) { - this.io = io; - return this; - } - - public void unsetIo() { - this.io = null; - } - - /** Returns true if field io is set (has been assigned a value) and false otherwise */ - public boolean isSetIo() { - return this.io != null; - } - - public void setIoIsSet(boolean value) { - if (!value) { - this.io = null; - } - } - - public void setFieldValue(_Fields field, Object value) { - switch (field) { - case SUCCESS: - if (value == null) { - unsetSuccess(); - } else { - setSuccess((List)value); - } - break; - - case IO: - if (value == null) { - unsetIo(); - } else { - setIo((IOError)value); - } - break; - - } - } - - public Object getFieldValue(_Fields field) { - switch (field) { - case SUCCESS: - return getSuccess(); - - case IO: - return getIo(); - - } - throw new 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 IllegalArgumentException(); - } - - switch (field) { - case SUCCESS: - return isSetSuccess(); - case IO: - return isSetIo(); - } - throw new IllegalStateException(); - } - - @Override - public boolean equals(Object that) { - if (that == null) - return false; - if (that instanceof getRowOrBefore_result) - return this.equals((getRowOrBefore_result)that); - return false; - } - - public boolean equals(getRowOrBefore_result that) { - if (that == null) - return false; - - boolean this_present_success = true && this.isSetSuccess(); - boolean that_present_success = true && that.isSetSuccess(); - if (this_present_success || that_present_success) { - if (!(this_present_success && that_present_success)) - return false; - if (!this.success.equals(that.success)) - return false; - } - - boolean this_present_io = true && this.isSetIo(); - boolean that_present_io = true && that.isSetIo(); - if (this_present_io || that_present_io) { - if (!(this_present_io && that_present_io)) - return false; - if (!this.io.equals(that.io)) - return false; - } - - return true; - } - - @Override - public int hashCode() { - return 0; - } - - public int compareTo(getRowOrBefore_result other) { - if (!getClass().equals(other.getClass())) { - return getClass().getName().compareTo(other.getClass().getName()); - } - - int lastComparison = 0; - getRowOrBefore_result typedOther = (getRowOrBefore_result)other; - - lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(typedOther.isSetSuccess()); - if (lastComparison != 0) { - return lastComparison; - } - if (isSetSuccess()) { - lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, typedOther.success); - if (lastComparison != 0) { - return lastComparison; - } - } - lastComparison = Boolean.valueOf(isSetIo()).compareTo(typedOther.isSetIo()); - if (lastComparison != 0) { - return lastComparison; - } - if (isSetIo()) { - lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.io, typedOther.io); - 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 { - schemes.get(iprot.getScheme()).getScheme().read(iprot, this); - } - - public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException { - schemes.get(oprot.getScheme()).getScheme().write(oprot, this); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder("getRowOrBefore_result("); - boolean first = true; - - sb.append("success:"); - if (this.success == null) { - sb.append("null"); - } else { - sb.append(this.success); - } - first = false; - if (!first) sb.append(", "); - sb.append("io:"); - if (this.io == null) { - sb.append("null"); - } else { - sb.append(this.io); - } - first = false; - sb.append(")"); - return sb.toString(); - } - - public void validate() throws org.apache.thrift.TException { - // check for required fields - } - - 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, 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 getRowOrBefore_resultStandardSchemeFactory implements SchemeFactory { - public getRowOrBefore_resultStandardScheme getScheme() { - return new getRowOrBefore_resultStandardScheme(); - } - } - - private static class getRowOrBefore_resultStandardScheme extends StandardScheme { - - public void read(org.apache.thrift.protocol.TProtocol iprot, getRowOrBefore_result 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 0: // SUCCESS - if (schemeField.type == org.apache.thrift.protocol.TType.LIST) { - { - org.apache.thrift.protocol.TList _list550 = iprot.readListBegin(); - struct.success = new ArrayList(_list550.size); - for (int _i551 = 0; _i551 < _list550.size; ++_i551) - { - TCell _elem552; // optional - _elem552 = new TCell(); - _elem552.read(iprot); - struct.success.add(_elem552); - } - iprot.readListEnd(); - } - struct.setSuccessIsSet(true); - } else { - org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); - } - break; - case 1: // IO - if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) { - struct.io = new IOError(); - struct.io.read(iprot); - struct.setIoIsSet(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, getRowOrBefore_result struct) throws org.apache.thrift.TException { - struct.validate(); - - oprot.writeStructBegin(STRUCT_DESC); - if (struct.success != null) { - oprot.writeFieldBegin(SUCCESS_FIELD_DESC); - { - oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, struct.success.size())); - for (TCell _iter553 : struct.success) - { - _iter553.write(oprot); - } - oprot.writeListEnd(); - } - oprot.writeFieldEnd(); - } - if (struct.io != null) { - oprot.writeFieldBegin(IO_FIELD_DESC); - struct.io.write(oprot); - oprot.writeFieldEnd(); - } - oprot.writeFieldStop(); - oprot.writeStructEnd(); - } - - } - - private static class getRowOrBefore_resultTupleSchemeFactory implements SchemeFactory { - public getRowOrBefore_resultTupleScheme getScheme() { - return new getRowOrBefore_resultTupleScheme(); - } - } - - private static class getRowOrBefore_resultTupleScheme extends TupleScheme { - - @Override - public void write(org.apache.thrift.protocol.TProtocol prot, getRowOrBefore_result struct) throws org.apache.thrift.TException { - TTupleProtocol oprot = (TTupleProtocol) prot; - BitSet optionals = new BitSet(); - if (struct.isSetSuccess()) { - optionals.set(0); - } - if (struct.isSetIo()) { - optionals.set(1); - } - oprot.writeBitSet(optionals, 2); - if (struct.isSetSuccess()) { - { - oprot.writeI32(struct.success.size()); - for (TCell _iter554 : struct.success) - { - _iter554.write(oprot); - } - } - } - if (struct.isSetIo()) { - struct.io.write(oprot); - } - } - - @Override - public void read(org.apache.thrift.protocol.TProtocol prot, getRowOrBefore_result struct) throws org.apache.thrift.TException { - TTupleProtocol iprot = (TTupleProtocol) prot; - BitSet incoming = iprot.readBitSet(2); - if (incoming.get(0)) { - { - org.apache.thrift.protocol.TList _list555 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32()); - struct.success = new ArrayList(_list555.size); - for (int _i556 = 0; _i556 < _list555.size; ++_i556) - { - TCell _elem557; // optional - _elem557 = new TCell(); - _elem557.read(iprot); - struct.success.add(_elem557); - } - } - struct.setSuccessIsSet(true); - } - if (incoming.get(1)) { - struct.io = new IOError(); - struct.io.read(iprot); - struct.setIoIsSet(true); - } - } - } - - } - - public static class getRegionInfo_args implements org.apache.thrift.TBase, java.io.Serializable, Cloneable { - private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getRegionInfo_args"); - - private static final org.apache.thrift.protocol.TField ROW_FIELD_DESC = new org.apache.thrift.protocol.TField("row", org.apache.thrift.protocol.TType.STRING, (short)1); - - private static final Map, SchemeFactory> schemes = new HashMap, SchemeFactory>(); - static { - schemes.put(StandardScheme.class, new getRegionInfo_argsStandardSchemeFactory()); - schemes.put(TupleScheme.class, new getRegionInfo_argsTupleSchemeFactory()); - } - - /** - * row key - */ - public ByteBuffer row; // 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 { - /** - * row key - */ - ROW((short)1, "row"); - - private static final Map byName = new HashMap(); - - static { - for (_Fields field : 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: // ROW - return ROW; - 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 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(String name) { - return byName.get(name); - } - - private final short _thriftId; - private final String _fieldName; - - _Fields(short thriftId, String fieldName) { - _thriftId = thriftId; - _fieldName = fieldName; - } - - public short getThriftFieldId() { - return _thriftId; - } - - public String getFieldName() { - return _fieldName; - } - } - - // isset id assignments - public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap; - static { - Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class); - tmpMap.put(_Fields.ROW, new org.apache.thrift.meta_data.FieldMetaData("row", org.apache.thrift.TFieldRequirementType.DEFAULT, - new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING , "Text"))); - metaDataMap = Collections.unmodifiableMap(tmpMap); - org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getRegionInfo_args.class, metaDataMap); - } - - public getRegionInfo_args() { - } - - public getRegionInfo_args( - ByteBuffer row) - { - this(); - this.row = row; - } - - /** - * Performs a deep copy on other. - */ - public getRegionInfo_args(getRegionInfo_args other) { - if (other.isSetRow()) { - this.row = other.row; - } - } - - public getRegionInfo_args deepCopy() { - return new getRegionInfo_args(this); - } - - @Override - public void clear() { - this.row = null; - } - - /** - * row key - */ - public byte[] getRow() { - setRow(org.apache.thrift.TBaseHelper.rightSize(row)); - return row == null ? null : row.array(); - } - - public ByteBuffer bufferForRow() { - return row; - } - - /** - * row key - */ - public getRegionInfo_args setRow(byte[] row) { - setRow(row == null ? (ByteBuffer)null : ByteBuffer.wrap(row)); - return this; - } - - public getRegionInfo_args setRow(ByteBuffer row) { - this.row = row; - return this; - } - - public void unsetRow() { - this.row = null; - } - - /** Returns true if field row is set (has been assigned a value) and false otherwise */ - public boolean isSetRow() { - return this.row != null; - } - - public void setRowIsSet(boolean value) { - if (!value) { - this.row = null; - } - } - - public void setFieldValue(_Fields field, Object value) { - switch (field) { - case ROW: - if (value == null) { - unsetRow(); - } else { - setRow((ByteBuffer)value); - } - break; - - } - } - - public Object getFieldValue(_Fields field) { - switch (field) { - case ROW: - return getRow(); - - } - throw new 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 IllegalArgumentException(); - } - - switch (field) { - case ROW: - return isSetRow(); - } - throw new IllegalStateException(); - } - - @Override - public boolean equals(Object that) { - if (that == null) - return false; - if (that instanceof getRegionInfo_args) - return this.equals((getRegionInfo_args)that); - return false; - } - - public boolean equals(getRegionInfo_args that) { - if (that == null) - return false; - - boolean this_present_row = true && this.isSetRow(); - boolean that_present_row = true && that.isSetRow(); - if (this_present_row || that_present_row) { - if (!(this_present_row && that_present_row)) - return false; - if (!this.row.equals(that.row)) - return false; - } - - return true; - } - - @Override - public int hashCode() { - return 0; - } - - public int compareTo(getRegionInfo_args other) { - if (!getClass().equals(other.getClass())) { - return getClass().getName().compareTo(other.getClass().getName()); - } - - int lastComparison = 0; - getRegionInfo_args typedOther = (getRegionInfo_args)other; - - lastComparison = Boolean.valueOf(isSetRow()).compareTo(typedOther.isSetRow()); - if (lastComparison != 0) { - return lastComparison; - } - if (isSetRow()) { - lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.row, typedOther.row); - 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 { - schemes.get(iprot.getScheme()).getScheme().read(iprot, this); - } - - public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException { - schemes.get(oprot.getScheme()).getScheme().write(oprot, this); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder("getRegionInfo_args("); + StringBuilder sb = new StringBuilder("getRegionInfo_args("); boolean first = true; sb.append("row:"); @@ -51079,7 +51014,19 @@ public class Hbase { @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_success = true && (isSetSuccess()); + builder.append(present_success); + if (present_success) + builder.append(success); + + boolean present_io = true && (isSetIo()); + builder.append(present_io); + if (present_io) + builder.append(io); + + return builder.toHashCode(); } public int compareTo(getRegionInfo_result other) { diff --git src/main/java/org/apache/hadoop/hbase/thrift/generated/IOError.java src/main/java/org/apache/hadoop/hbase/thrift/generated/IOError.java index 11e31e3..08ba49e 100644 --- src/main/java/org/apache/hadoop/hbase/thrift/generated/IOError.java +++ src/main/java/org/apache/hadoop/hbase/thrift/generated/IOError.java @@ -6,6 +6,7 @@ */ package org.apache.hadoop.hbase.thrift.generated; +import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.thrift.scheme.IScheme; import org.apache.thrift.scheme.SchemeFactory; import org.apache.thrift.scheme.StandardScheme; @@ -227,7 +228,14 @@ public class IOError extends Exception implements org.apache.thrift.TBase, jav @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_value = true && (isSetValue()); + builder.append(present_value); + if (present_value) + builder.append(value); + + boolean present_timestamp = true; + builder.append(present_timestamp); + if (present_timestamp) + builder.append(timestamp); + + return builder.toHashCode(); } public int compareTo(TCell other) { diff --git src/main/java/org/apache/hadoop/hbase/thrift/generated/TRegionInfo.java src/main/java/org/apache/hadoop/hbase/thrift/generated/TRegionInfo.java index ed251e8..d23cc70 100644 --- src/main/java/org/apache/hadoop/hbase/thrift/generated/TRegionInfo.java +++ src/main/java/org/apache/hadoop/hbase/thrift/generated/TRegionInfo.java @@ -6,6 +6,7 @@ */ package org.apache.hadoop.hbase.thrift.generated; +import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.thrift.scheme.IScheme; import org.apache.thrift.scheme.SchemeFactory; import org.apache.thrift.scheme.StandardScheme; @@ -622,7 +623,44 @@ public class TRegionInfo implements org.apache.thrift.TBase, jav @Override public int hashCode() { - return 0; + HashCodeBuilder builder = new HashCodeBuilder(); + + boolean present_startRow = true && (isSetStartRow()); + builder.append(present_startRow); + if (present_startRow) + builder.append(startRow); + + boolean present_stopRow = true && (isSetStopRow()); + builder.append(present_stopRow); + if (present_stopRow) + builder.append(stopRow); + + boolean present_timestamp = true && (isSetTimestamp()); + builder.append(present_timestamp); + if (present_timestamp) + builder.append(timestamp); + + boolean present_columns = true && (isSetColumns()); + builder.append(present_columns); + if (present_columns) + builder.append(columns); + + boolean present_caching = true && (isSetCaching()); + builder.append(present_caching); + if (present_caching) + builder.append(caching); + + boolean present_filterString = true && (isSetFilterString()); + builder.append(present_filterString); + if (present_filterString) + builder.append(filterString); + + return builder.toHashCode(); } public int compareTo(TScan other) { @@ -772,7 +805,7 @@ public class TScan implements org.apache.thrift.TBase, jav struct.columns = new ArrayList(_list18.size); for (int _i19 = 0; _i19 < _list18.size; ++_i19) { - ByteBuffer _elem20; // optional + ByteBuffer _elem20; // required _elem20 = iprot.readBinary(); struct.columns.add(_elem20); } @@ -944,7 +977,7 @@ public class TScan implements org.apache.thrift.TBase, jav struct.columns = new ArrayList(_list23.size); for (int _i24 = 0; _i24 < _list23.size; ++_i24) { - ByteBuffer _elem25; // optional + ByteBuffer _elem25; // required _elem25 = iprot.readBinary(); struct.columns.add(_elem25); } diff --git src/main/java/org/apache/hadoop/hbase/util/FSUtils.java src/main/java/org/apache/hadoop/hbase/util/FSUtils.java index b9c47fc..4e34375 100644 --- src/main/java/org/apache/hadoop/hbase/util/FSUtils.java +++ src/main/java/org/apache/hadoop/hbase/util/FSUtils.java @@ -308,7 +308,7 @@ public abstract class FSUtils { FSUtils.setVersion(fs, rootdir, wait, retries); return; } - } else if (version.compareTo(HConstants.FILE_SYSTEM_VERSION) == 0) + } else if (version.compareTo(HConstants.FILE_SYSTEM_VERSION) <= 0) return; // version is deprecated require migration diff --git src/main/java/org/apache/hadoop/hbase/util/RetryCounter.java src/main/java/org/apache/hadoop/hbase/util/RetryCounter.java index dee5301..0d1c5ea 100644 --- src/main/java/org/apache/hadoop/hbase/util/RetryCounter.java +++ src/main/java/org/apache/hadoop/hbase/util/RetryCounter.java @@ -52,7 +52,8 @@ public class RetryCounter { public void sleepUntilNextRetry() throws InterruptedException { int attempts = getAttemptTimes(); long sleepTime = (long) (retryIntervalMillis * Math.pow(2, attempts)); - LOG.info("Sleeping " + sleepTime + "ms before retry #" + attempts + "..."); + LOG.info("The " + attempts + " times to retry after sleeping " + sleepTime + + " ms"); timeUnit.sleep(sleepTime); } @@ -67,4 +68,4 @@ public class RetryCounter { public int getAttemptTimes() { return maxRetries-retriesRemaining+1; } -} +} \ No newline at end of file diff --git src/main/java/org/apache/hadoop/hbase/util/Writables.java src/main/java/org/apache/hadoop/hbase/util/Writables.java index 3d20723..ce9d598 100644 --- src/main/java/org/apache/hadoop/hbase/util/Writables.java +++ src/main/java/org/apache/hadoop/hbase/util/Writables.java @@ -22,6 +22,7 @@ package org.apache.hadoop.hbase.util; import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.hbase.HRegionInfo; import org.apache.hadoop.hbase.migration.HRegionInfo090x; +import org.apache.hadoop.hbase.migration.HRegionInfo090x2; import org.apache.hadoop.io.DataInputBuffer; import org.apache.hadoop.io.Writable; @@ -151,6 +152,17 @@ public class Writables { /** * @param bytes serialized bytes + * @return A HRegionInfo instance built out of passed bytes. + * @throws IOException e + */ + public static HRegionInfo090x2 getHRegionInfo90x2(final byte [] bytes) + throws IOException { + return (HRegionInfo090x2)getWritable(bytes, new HRegionInfo090x2()); + } + + + /** + * @param bytes serialized bytes * @return All the hregioninfos that are in the byte array. Keeps reading * till we hit the end. * @throws IOException e diff --git src/main/java/org/apache/hadoop/hbase/zookeeper/RecoverableZooKeeper.java src/main/java/org/apache/hadoop/hbase/zookeeper/RecoverableZooKeeper.java index 233c3cc..a484d36 100644 --- src/main/java/org/apache/hadoop/hbase/zookeeper/RecoverableZooKeeper.java +++ src/main/java/org/apache/hadoop/hbase/zookeeper/RecoverableZooKeeper.java @@ -77,18 +77,10 @@ public class RecoverableZooKeeper { private int sessionTimeout; private String quorumServers; - // The metadata attached to each piece of data has the - // format: - // 1-byte constant - // 4-byte big-endian integer (length of next field) - // identifier corresponding uniquely to this process - // It is prepended to the data supplied by the user. - + private static final int ID_OFFSET = Bytes.SIZEOF_INT; // the magic number is to be backward compatible private static final byte MAGIC =(byte) 0XFF; - private static final int MAGIC_SIZE = Bytes.SIZEOF_BYTE; - private static final int ID_LENGTH_OFFSET = MAGIC_SIZE; - private static final int ID_LENGTH_SIZE = Bytes.SIZEOF_INT; + private static final int MAGIC_OFFSET = Bytes.SIZEOF_BYTE; public RecoverableZooKeeper(String quorumServers, int sessionTimeout, Watcher watcher, int maxRetries, int retryIntervalMillis) @@ -119,9 +111,12 @@ public class RecoverableZooKeeper { } /** - * delete is an idempotent operation. Retry before throwing exception. - * This function will not throw NoNodeException if the path does not - * exist. + * delete is an idempotent operation. Retry before throw out exception. + * This function will not throw out NoNodeException if the path is not existed + * @param path + * @param version + * @throws InterruptedException + * @throws KeeperException */ public void delete(String path, int version) throws InterruptedException, KeeperException { @@ -146,7 +141,12 @@ public class RecoverableZooKeeper { case CONNECTIONLOSS: case SESSIONEXPIRED: case OPERATIONTIMEOUT: - retryOrThrow(retryCounter, e, "delete"); + LOG.warn("Possibly transient ZooKeeper exception: " + e); + if (!retryCounter.shouldRetry()) { + LOG.error("ZooKeeper delete failed after " + + retryCounter.getMaxRetries() + " retries"); + throw e; + } break; default: @@ -160,8 +160,12 @@ public class RecoverableZooKeeper { } /** - * exists is an idempotent operation. Retry before throwing exception + * exists is an idempotent operation. Retry before throw out exception + * @param path + * @param watcher * @return A Stat instance + * @throws KeeperException + * @throws InterruptedException */ public Stat exists(String path, Watcher watcher) throws KeeperException, InterruptedException { @@ -174,7 +178,12 @@ public class RecoverableZooKeeper { case CONNECTIONLOSS: case SESSIONEXPIRED: case OPERATIONTIMEOUT: - retryOrThrow(retryCounter, e, "exists"); + LOG.warn("Possibly transient ZooKeeper exception: " + e); + if (!retryCounter.shouldRetry()) { + LOG.error("ZooKeeper exists failed after " + + retryCounter.getMaxRetries() + " retries"); + throw e; + } break; default: @@ -187,8 +196,12 @@ public class RecoverableZooKeeper { } /** - * exists is an idempotent operation. Retry before throwing exception + * exists is an idempotent operation. Retry before throw out exception + * @param path + * @param watch * @return A Stat instance + * @throws KeeperException + * @throws InterruptedException */ public Stat exists(String path, boolean watch) throws KeeperException, InterruptedException { @@ -201,7 +214,12 @@ public class RecoverableZooKeeper { case CONNECTIONLOSS: case SESSIONEXPIRED: case OPERATIONTIMEOUT: - retryOrThrow(retryCounter, e, "exists"); + LOG.warn("Possibly transient ZooKeeper exception: " + e); + if (!retryCounter.shouldRetry()) { + LOG.error("ZooKeeper exists failed after " + + retryCounter.getMaxRetries() + " retries"); + throw e; + } break; default: @@ -213,19 +231,13 @@ public class RecoverableZooKeeper { } } - private void retryOrThrow(RetryCounter retryCounter, KeeperException e, - String opName) throws KeeperException { - LOG.warn("Possibly transient ZooKeeper exception: " + e); - if (!retryCounter.shouldRetry()) { - LOG.error("ZooKeeper " + opName + " failed after " - + retryCounter.getMaxRetries() + " retries"); - throw e; - } - } - /** - * getChildren is an idempotent operation. Retry before throwing exception + * getChildren is an idempotent operation. Retry before throw out exception + * @param path + * @param watcher * @return List of children znodes + * @throws KeeperException + * @throws InterruptedException */ public List getChildren(String path, Watcher watcher) throws KeeperException, InterruptedException { @@ -238,7 +250,12 @@ public class RecoverableZooKeeper { case CONNECTIONLOSS: case SESSIONEXPIRED: case OPERATIONTIMEOUT: - retryOrThrow(retryCounter, e, "getChildren"); + LOG.warn("Possibly transient ZooKeeper exception: " + e); + if (!retryCounter.shouldRetry()) { + LOG.error("ZooKeeper getChildren failed after " + + retryCounter.getMaxRetries() + " retries"); + throw e; + } break; default: @@ -251,8 +268,12 @@ public class RecoverableZooKeeper { } /** - * getChildren is an idempotent operation. Retry before throwing exception + * getChildren is an idempotent operation. Retry before throw out exception + * @param path + * @param watch * @return List of children znodes + * @throws KeeperException + * @throws InterruptedException */ public List getChildren(String path, boolean watch) throws KeeperException, InterruptedException { @@ -265,7 +286,12 @@ public class RecoverableZooKeeper { case CONNECTIONLOSS: case SESSIONEXPIRED: case OPERATIONTIMEOUT: - retryOrThrow(retryCounter, e, "getChildren"); + LOG.warn("Possibly transient ZooKeeper exception: " + e); + if (!retryCounter.shouldRetry()) { + LOG.error("ZooKeeper getChildren failed after " + + retryCounter.getMaxRetries() + " retries"); + throw e; + } break; default: @@ -278,8 +304,13 @@ public class RecoverableZooKeeper { } /** - * getData is an idempotent operation. Retry before throwing exception + * getData is an idempotent operation. Retry before throw out exception + * @param path + * @param watcher + * @param stat * @return Data + * @throws KeeperException + * @throws InterruptedException */ public byte[] getData(String path, Watcher watcher, Stat stat) throws KeeperException, InterruptedException { @@ -293,7 +324,12 @@ public class RecoverableZooKeeper { case CONNECTIONLOSS: case SESSIONEXPIRED: case OPERATIONTIMEOUT: - retryOrThrow(retryCounter, e, "getData"); + LOG.warn("Possibly transient ZooKeeper exception: " + e); + if (!retryCounter.shouldRetry()) { + LOG.error("ZooKeeper getData failed after " + + retryCounter.getMaxRetries() + " retries"); + throw e; + } break; default: @@ -306,8 +342,13 @@ public class RecoverableZooKeeper { } /** - * getData is an idemnpotent operation. Retry before throwing exception + * getData is an idemnpotent operation. Retry before throw out exception + * @param path + * @param watch + * @param stat * @return Data + * @throws KeeperException + * @throws InterruptedException */ public byte[] getData(String path, boolean watch, Stat stat) throws KeeperException, InterruptedException { @@ -321,7 +362,12 @@ public class RecoverableZooKeeper { case CONNECTIONLOSS: case SESSIONEXPIRED: case OPERATIONTIMEOUT: - retryOrThrow(retryCounter, e, "getData"); + LOG.warn("Possibly transient ZooKeeper exception: " + e); + if (!retryCounter.shouldRetry()) { + LOG.error("ZooKeeper getData failed after " + + retryCounter.getMaxRetries() + " retries"); + throw e; + } break; default: @@ -337,7 +383,12 @@ public class RecoverableZooKeeper { * setData is NOT an idempotent operation. Retry may cause BadVersion Exception * Adding an identifier field into the data to check whether * badversion is caused by the result of previous correctly setData + * @param path + * @param data + * @param version * @return Stat instance + * @throws KeeperException + * @throws InterruptedException */ public Stat setData(String path, byte[] data, int version) throws KeeperException, InterruptedException { @@ -351,28 +402,33 @@ public class RecoverableZooKeeper { case CONNECTIONLOSS: case SESSIONEXPIRED: case OPERATIONTIMEOUT: - retryOrThrow(retryCounter, e, "setData"); + LOG.warn("Possibly transient ZooKeeper exception: " + e); + if (!retryCounter.shouldRetry()) { + LOG.error("ZooKeeper setData failed after " + + retryCounter.getMaxRetries() + " retries"); + throw e; + } break; case BADVERSION: // try to verify whether the previous setData success or not try{ Stat stat = new Stat(); byte[] revData = zk.getData(path, false, stat); - int idLength = Bytes.toInt(revData, ID_LENGTH_SIZE); - int dataLength = revData.length-ID_LENGTH_SIZE-idLength; - int dataOffset = ID_LENGTH_SIZE+idLength; + int idLength = Bytes.toInt(revData, ID_OFFSET); + int dataLength = revData.length-ID_OFFSET-idLength; + int dataOffset = ID_OFFSET+idLength; - if(Bytes.compareTo(revData, ID_LENGTH_SIZE, id.length, + if(Bytes.compareTo(revData, ID_OFFSET, id.length, revData, dataOffset, dataLength) == 0) { // the bad version is caused by previous successful setData return stat; } } catch(KeeperException keeperException){ - // the ZK is not reliable at this moment. just throwing exception + // the ZK is not reliable at this moment. just throw out exception throw keeperException; } - // throw other exceptions and verified bad version exceptions + // throw out other exceptions and verified bad version exceptions default: throw e; } @@ -385,8 +441,8 @@ public class RecoverableZooKeeper { /** *

* NONSEQUENTIAL create is idempotent operation. - * Retry before throwing exceptions. - * But this function will not throw the NodeExist exception back to the + * Retry before throw out exceptions. + * But this function will not throw out the NodeExist exception back to the * application. *

*

@@ -395,7 +451,13 @@ public class RecoverableZooKeeper { * or not. *

* + * @param path + * @param data + * @param acl + * @param createMode * @return Path + * @throws KeeperException + * @throws InterruptedException */ public String create(String path, byte[] data, List acl, CreateMode createMode) @@ -448,7 +510,12 @@ public class RecoverableZooKeeper { case CONNECTIONLOSS: case SESSIONEXPIRED: case OPERATIONTIMEOUT: - retryOrThrow(retryCounter, e, "create"); + LOG.warn("Possibly transient ZooKeeper exception: " + e); + if (!retryCounter.shouldRetry()) { + LOG.error("ZooKeeper create failed after " + + retryCounter.getMaxRetries() + " retries"); + throw e; + } break; default: @@ -483,7 +550,12 @@ public class RecoverableZooKeeper { case CONNECTIONLOSS: case SESSIONEXPIRED: case OPERATIONTIMEOUT: - retryOrThrow(retryCounter, e, "create"); + LOG.warn("Possibly transient ZooKeeper exception: " + e); + if (!retryCounter.shouldRetry()) { + LOG.error("ZooKeeper create failed after " + + retryCounter.getMaxRetries() + " retries"); + throw e; + } break; default: @@ -524,9 +596,9 @@ public class RecoverableZooKeeper { return data; } - int idLength = Bytes.toInt(data, ID_LENGTH_OFFSET); - int dataLength = data.length-MAGIC_SIZE-ID_LENGTH_SIZE-idLength; - int dataOffset = MAGIC_SIZE+ID_LENGTH_SIZE+idLength; + int idLength = Bytes.toInt(data, MAGIC_OFFSET); + int dataLength = data.length-MAGIC_OFFSET-ID_OFFSET-idLength; + int dataOffset = MAGIC_OFFSET+ID_OFFSET+idLength; byte[] newData = new byte[dataLength]; System.arraycopy(data, dataOffset, newData, 0, dataLength); @@ -540,7 +612,7 @@ public class RecoverableZooKeeper { return data; } - byte[] newData = new byte[MAGIC_SIZE+ID_LENGTH_SIZE+id.length+data.length]; + byte[] newData = new byte[MAGIC_OFFSET+ID_OFFSET+id.length+data.length]; int pos = 0; pos = Bytes.putByte(newData, pos, MAGIC); pos = Bytes.putInt(newData, pos, id.length); diff --git src/main/resources/org/apache/hadoop/hbase/rest/XMLSchema.xsd src/main/resources/org/apache/hadoop/hbase/rest/XMLSchema.xsd index c2df60d..de4fff1 100644 --- src/main/resources/org/apache/hadoop/hbase/rest/XMLSchema.xsd +++ src/main/resources/org/apache/hadoop/hbase/rest/XMLSchema.xsd @@ -166,13 +166,6 @@ - - - - - - - diff --git src/main/resources/org/apache/hadoop/hbase/rest/protobuf/StorageClusterStatusMessage.proto src/main/resources/org/apache/hadoop/hbase/rest/protobuf/StorageClusterStatusMessage.proto index 46e275d..2b032f7 100644 --- src/main/resources/org/apache/hadoop/hbase/rest/protobuf/StorageClusterStatusMessage.proto +++ src/main/resources/org/apache/hadoop/hbase/rest/protobuf/StorageClusterStatusMessage.proto @@ -26,13 +26,6 @@ message StorageClusterStatus { optional int32 storefileSizeMB = 4; optional int32 memstoreSizeMB = 5; optional int32 storefileIndexSizeMB = 6; - optional int64 readRequestsCount = 7; - optional int64 writeRequestsCount = 8; - optional int32 rootIndexSizeKB = 9; - optional int32 totalStaticIndexSizeKB = 10; - optional int32 totalStaticBloomSizeKB = 11; - optional int64 totalCompactingKVs = 12; - optional int64 currentCompactedKVs = 13; } message Node { required string name = 1; // name:port diff --git src/main/resources/org/apache/hadoop/hbase/thrift/Hbase.thrift src/main/resources/org/apache/hadoop/hbase/thrift/Hbase.thrift index f698a6c..c4c783d 100644 --- src/main/resources/org/apache/hadoop/hbase/thrift/Hbase.thrift +++ src/main/resources/org/apache/hadoop/hbase/thrift/Hbase.thrift @@ -858,22 +858,6 @@ service Hbase { ) throws (1:IOError io, 2:IllegalArgument ia) /** - * Get the row just before the specified one. - * - * @return value for specified row/column - */ - list getRowOrBefore( - /** name of table */ - 1:Text tableName, - - /** row key */ - 2:Text row, - - /** column name */ - 3:Text family - ) throws (1:IOError io) - - /** * Get the regininfo for the specified row. It scans * the metatable to find region's start and end keys. * diff --git src/test/data/generate-hbase-2600-root-in-tmp.sh src/test/data/generate-hbase-2600-root-in-tmp.sh new file mode 100644 index 0000000..f886e12 --- /dev/null +++ src/test/data/generate-hbase-2600-root-in-tmp.sh @@ -0,0 +1,14 @@ +#!/bin/sh +set -ev +echo "create 't1','c1'" +NUM_PUTS=1000 +NUM_SPLITS=5 +FOO="dfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsd dfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsd dfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsd dfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsd dfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsd dfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsd dfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsd dfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsddfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsd dfjsgkljsdfklgjklsdjgkldjsfgjsdfklgjklsd" +for i in `seq 1 $NUM_PUTS` + do echo "put 't1','r${i}','c1','${FOO}'" +done +for i in `seq 1 $NUM_SPLITS` + do echo "split 't1'" + echo "list" + echo scan "'.META.'" +done diff --git src/test/data/hbase-2600-root.dir.tgz src/test/data/hbase-2600-root.dir.tgz new file mode 100644 index 0000000000000000000000000000000000000000..f606141ebd1544ed17b8ca71a34eab91f5823994 GIT binary patch literal 260764 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

Ag>_r2IgBRD0p&N*hr!INY_Q5 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

=hxaR%@`Gx?q)*cN#*{am*!I@tg>irGS%>s9 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

v@(=i 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 dqZHj_FrM2|>yex{ztq737(^$1 htds = metaMigratev2.updateAndOnlineRoot(); + assertEquals(0, htds.size()); + + htds = metaMigratev2.updateAndOnlineMeta(); + assertEquals(2, htds.size()); + + String versionStr = FSUtils.getVersion(masterFileSystem.getFileSystem(), + masterFileSystem.getRootDir()); + assertEquals(HConstants.FILE_SYSTEM_VERSION, versionStr); + + MetaReader.fullScanMetaAndPrint(master.getCatalogTracker()); + } + + + /** + * @param c + * @param htd + * @param family + * @param numRegions + * @return + * @throws IOException + * @deprecated Just for testing migration of meta from 0.90 to 0.92... will be + * removed thereafter + */ + public int createMultiRegionsWithLegacyHRI(final Configuration c, + final HTableDescriptor htd, + final byte[] family, + int numRegions) + throws IOException { + if (numRegions < 3) throw new IOException("Must create at least 3 regions"); + byte[] startKey = Bytes.toBytes("aaaaa"); + byte[] endKey = Bytes.toBytes("zzzzz"); + byte[][] splitKeys = Bytes.split(startKey, endKey, numRegions - 3); + byte[][] regionStartKeys = new byte[splitKeys.length + 1][]; + for (int i = 0; i < splitKeys.length; i++) { + regionStartKeys[i + 1] = splitKeys[i]; + } + regionStartKeys[0] = HConstants.EMPTY_BYTE_ARRAY; + return createMultiRegionsWithLegacyHRI(c, htd, family, regionStartKeys); + } + + /** + * @param c + * @param htd + * @param columnFamily + * @param startKeys + * @return + * @throws IOException + * @deprecated Just for testing migration of meta from 0.92 to 0.92v2... + * will be removed thereafter + */ + public int createMultiRegionsWithLegacyHRI(final Configuration c, + final HTableDescriptor htd, + final byte[] columnFamily, + byte[][] startKeys) + throws IOException { + Arrays.sort(startKeys, Bytes.BYTES_COMPARATOR); + HTable meta = new HTable(c, HConstants.META_TABLE_NAME); + if (!htd.hasFamily(columnFamily)) { + HColumnDescriptor hcd = new HColumnDescriptor(columnFamily); + htd.addFamily(hcd); + } + List newRegions + = new ArrayList(startKeys.length); + int count = 0; + for (int i = 0; i < startKeys.length; i++) { + int j = (i + 1) % startKeys.length; + HRegionInfo090x2 hri = new HRegionInfo090x2(htd.getName(), + startKeys[i], startKeys[j]); + Put put = new Put(hri.getRegionName()); + put.setWriteToWAL(false); + put.add(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER, + Writables.getBytes(hri)); + meta.put(put); + LOG.info("createMultiRegions: PUT inserted " + hri.toString()); + + newRegions.add(hri); + count++; + } + meta.close(); + return count; + } + + int createMultiRegionsWithNewHRI(final Configuration c, + final HTableDescriptor htd, + final byte[] family, + int numRegions) throws IOException { + if (numRegions < 3) throw new IOException("Must create at least 3 regions"); + byte[] startKey = Bytes.toBytes("aaaaa"); + byte[] endKey = Bytes.toBytes("zzzzz"); + byte[][] splitKeys = Bytes.split(startKey, endKey, numRegions - 3); + byte[][] regionStartKeys = new byte[splitKeys.length + 1][]; + for (int i = 0; i < splitKeys.length; i++) { + regionStartKeys[i + 1] = splitKeys[i]; + } + regionStartKeys[0] = HConstants.EMPTY_BYTE_ARRAY; + return createMultiRegionsWithNewHRI(c, htd, family, regionStartKeys); + } + + int createMultiRegionsWithNewHRI(final Configuration c, final HTableDescriptor htd, + final byte[] columnFamily, byte[][] endKeys) + throws IOException { + Arrays.sort(endKeys, Bytes.BYTES_COMPARATOR); + HTable meta = new HTable(c, HConstants.META_TABLE_NAME); + if (!htd.hasFamily(columnFamily)) { + HColumnDescriptor hcd = new HColumnDescriptor(columnFamily); + htd.addFamily(hcd); + } + List newRegions + = new ArrayList(endKeys.length); + int count = 0; + for (int i = 0; i < endKeys.length; i++) { + int j = (i + 1) % endKeys.length; + HRegionInfo hri = new HRegionInfo(htd.getName(), + endKeys[i], endKeys[j]); + Put put = new Put(hri.getRegionName()); + put.setWriteToWAL(false); + put.add(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER, + Writables.getBytes(hri)); + meta.put(put); + LOG.info("createMultiRegions: PUT inserted " + hri.toString()); + + newRegions.add(hri); + count++; + } + meta.close(); + return count; + } + + @org.junit.Rule + public org.apache.hadoop.hbase.ResourceCheckerJUnitRule cu = + new org.apache.hadoop.hbase.ResourceCheckerJUnitRule(); +} \ No newline at end of file diff --git src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide.java src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide.java index 2dadc7c..f573f53 100644 --- src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide.java +++ src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide.java @@ -4038,56 +4038,6 @@ public class TestFromClientSide { } } - @Test - public void testGetClosestRowBefore() throws IOException { - final byte [] tableAname = Bytes.toBytes("testGetClosestRowBefore"); - final byte [] row = Bytes.toBytes("row"); - - - byte[] firstRow = Bytes.toBytes("ro"); - byte[] beforeFirstRow = Bytes.toBytes("rn"); - byte[] beforeSecondRow = Bytes.toBytes("rov"); - - HTable table = TEST_UTIL.createTable(tableAname, - new byte [][] {HConstants.CATALOG_FAMILY, Bytes.toBytes("info2")}); - Put put = new Put(firstRow); - Put put2 = new Put(row); - byte[] zero = new byte[]{0}; - byte[] one = new byte[]{1}; - - put.add(HConstants.CATALOG_FAMILY, null, zero); - put2.add(HConstants.CATALOG_FAMILY, null, one); - - table.put(put); - table.put(put2); - - Result result = null; - - // Test before first that null is returned - result = table.getRowOrBefore(beforeFirstRow, HConstants.CATALOG_FAMILY); - assertTrue(result == null); - - // Test at first that first is returned - result = table.getRowOrBefore(firstRow, HConstants.CATALOG_FAMILY); - assertTrue(result.containsColumn(HConstants.CATALOG_FAMILY, null)); - assertTrue(Bytes.equals(result.getValue(HConstants.CATALOG_FAMILY, null), zero)); - - // Test in between first and second that first is returned - result = table.getRowOrBefore(beforeSecondRow, HConstants.CATALOG_FAMILY); - assertTrue(result.containsColumn(HConstants.CATALOG_FAMILY, null)); - assertTrue(Bytes.equals(result.getValue(HConstants.CATALOG_FAMILY, null), zero)); - - // Test at second make sure second is returned - result = table.getRowOrBefore(row, HConstants.CATALOG_FAMILY); - assertTrue(result.containsColumn(HConstants.CATALOG_FAMILY, null)); - assertTrue(Bytes.equals(result.getValue(HConstants.CATALOG_FAMILY, null), one)); - - // Test after second, make sure second is returned - result = table.getRowOrBefore(Bytes.add(row,one), HConstants.CATALOG_FAMILY); - assertTrue(result.containsColumn(HConstants.CATALOG_FAMILY, null)); - assertTrue(Bytes.equals(result.getValue(HConstants.CATALOG_FAMILY, null), one)); - } - /** * For HBASE-2156 * @throws Exception diff --git src/test/java/org/apache/hadoop/hbase/client/TestMetaMigrationRemovingHTD.java src/test/java/org/apache/hadoop/hbase/client/TestMetaMigrationRemovingHTD.java deleted file mode 100644 index d1c15af..0000000 --- src/test/java/org/apache/hadoop/hbase/client/TestMetaMigrationRemovingHTD.java +++ /dev/null @@ -1,363 +0,0 @@ -/** - * Copyright 2010 The Apache Software Foundation - * - * 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.hadoop.hbase.client; - -import static org.junit.Assert.*; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Set; - -import junit.framework.Assert; -import junit.framework.AssertionFailedError; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.FileSystem; -import org.apache.hadoop.fs.FileUtil; -import org.apache.hadoop.fs.FsShell; -import org.apache.hadoop.fs.Path; -import org.apache.hadoop.hbase.*; -import org.apache.hadoop.hbase.catalog.CatalogTracker; -import org.apache.hadoop.hbase.catalog.MetaMigrationRemovingHTD; -import org.apache.hadoop.hbase.catalog.MetaReader; -import org.apache.hadoop.hbase.migration.HRegionInfo090x; -import org.apache.hadoop.hbase.util.Bytes; -import org.apache.hadoop.hbase.util.Writables; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.experimental.categories.Category; - -/** - * Test migration that removes HTableDescriptor from HRegionInfo moving the - * meta version from no version to {@link MetaReader#META_VERSION}. - */ -@Category(MediumTests.class) -public class TestMetaMigrationRemovingHTD { - static final Log LOG = LogFactory.getLog(TestMetaMigrationRemovingHTD.class); - private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(); - private final static String TESTTABLE = "TestTable"; - private final static int ROWCOUNT = 100; - - @BeforeClass - public static void setUpBeforeClass() throws Exception { - // Start up our mini cluster on top of an 0.90 root.dir that has data from - // a 0.90 hbase run -- it has a table with 100 rows in it -- and see if - // we can migrate from 0.90. - TEST_UTIL.startMiniZKCluster(); - TEST_UTIL.startMiniDFSCluster(1); - Path testdir = TEST_UTIL.getDataTestDir("TestMetaMigrationRemovingHTD"); - // Untar our test dir. - File untar = untar(new File(testdir.toString())); - // Now copy the untar up into hdfs so when we start hbase, we'll run from it. - Configuration conf = TEST_UTIL.getConfiguration(); - FsShell shell = new FsShell(conf); - FileSystem fs = FileSystem.get(conf); - // find where hbase will root itself, so we can copy filesystem there - Path hbaseRootDir = TEST_UTIL.getDefaultRootDirPath(); - doFsCommand(shell, - new String [] {"-put", untar.toURI().toString(), hbaseRootDir.toString()}); - // See whats in minihdfs. - doFsCommand(shell, new String [] {"-lsr", "/"}); - TEST_UTIL.startMiniHBaseCluster(1, 1); - // Assert we are running against the copied-up filesystem. The copied-up - // rootdir should have had a table named 'TestTable' in it. Assert it - // present. - HTable t = new HTable(TEST_UTIL.getConfiguration(), TESTTABLE); - ResultScanner scanner = t.getScanner(new Scan()); - int count = 0; - while (scanner.next() != null) { - count++; - } - // Assert that we find all 100 rows that are in the data we loaded. If - // so then we must have migrated it from 0.90 to 0.92. - Assert.assertEquals(ROWCOUNT, count); - scanner.close(); - t.close(); - } - - private static File untar(final File testdir) throws IOException { - // Find the src data under src/test/data - final String datafile = "hbase-4388-root.dir"; - String srcTarFile = - System.getProperty("project.build.testSourceDirectory", "src/test") + - File.separator + "data" + File.separator + datafile + ".tgz"; - File homedir = new File(testdir.toString()); - File tgtUntarDir = new File(homedir, datafile); - if (tgtUntarDir.exists()) { - if (!FileUtil.fullyDelete(tgtUntarDir)) { - throw new IOException("Failed delete of " + tgtUntarDir.toString()); - } - } - LOG.info("Untarring " + srcTarFile + " into " + homedir.toString()); - FileUtil.unTar(new File(srcTarFile), homedir); - Assert.assertTrue(tgtUntarDir.exists()); - return tgtUntarDir; - } - - private static void doFsCommand(final FsShell shell, final String [] args) - throws Exception { - // Run the 'put' command. - int errcode = shell.run(args); - if (errcode != 0) throw new IOException("Failed put; errcode=" + errcode); - } - - /** - * @throws java.lang.Exception - */ - @AfterClass - public static void tearDownAfterClass() throws Exception { - TEST_UTIL.shutdownMiniCluster(); - } - - @Test - public void testMetaUpdatedFlagInROOT() throws Exception { - boolean metaUpdated = MetaMigrationRemovingHTD. - isMetaHRIUpdated(TEST_UTIL.getMiniHBaseCluster().getMaster()); - assertEquals(true, metaUpdated); - } - - @Test - public void testMetaMigration() throws Exception { - LOG.info("Starting testMetaWithLegacyHRI"); - final byte [] FAMILY = Bytes.toBytes("family"); - HTableDescriptor htd = new HTableDescriptor("testMetaMigration"); - HColumnDescriptor hcd = new HColumnDescriptor(FAMILY); - htd.addFamily(hcd); - Configuration conf = TEST_UTIL.getConfiguration(); - createMultiRegionsWithLegacyHRI(conf, htd, FAMILY, - new byte[][]{ - HConstants.EMPTY_START_ROW, - Bytes.toBytes("region_a"), - Bytes.toBytes("region_b")}); - CatalogTracker ct = - TEST_UTIL.getMiniHBaseCluster().getMaster().getCatalogTracker(); - // Erase the current version of root meta for this test. - undoVersionInMeta(); - MetaReader.fullScanMetaAndPrint(ct); - LOG.info("Meta Print completed.testUpdatesOnMetaWithLegacyHRI"); - - Set htds = - MetaMigrationRemovingHTD.updateMetaWithNewRegionInfo( - TEST_UTIL.getHBaseCluster().getMaster()); - MetaReader.fullScanMetaAndPrint(ct); - // Should be one entry only and it should be for the table we just added. - assertEquals(1, htds.size()); - assertTrue(htds.contains(htd)); - // Assert that the flag in ROOT is updated to reflect the correct status - boolean metaUpdated = - MetaMigrationRemovingHTD.isMetaHRIUpdated( - TEST_UTIL.getMiniHBaseCluster().getMaster()); - assertEquals(true, metaUpdated); - } - - /** - * This test assumes a master crash/failure during the meta migration process - * and attempts to continue the meta migration process when a new master takes over. - * When a master dies during the meta migration we will have some rows of - * META.CatalogFamily updated with new HRI, (i.e HRI with out HTD) and some - * still hanging with legacy HRI. (i.e HRI with HTD). When the backup master/ or - * fresh start of master attempts the migration it will encouter some rows of META - * already updated with new HRI and some still legacy. This test will simulate this - * scenario and validates that the migration process can safely skip the updated - * rows and migrate any pending rows at startup. - * @throws Exception - */ - @Test - public void testMasterCrashDuringMetaMigration() throws Exception { - final byte[] FAMILY = Bytes.toBytes("family"); - HTableDescriptor htd = new HTableDescriptor("testMasterCrashDuringMetaMigration"); - HColumnDescriptor hcd = new HColumnDescriptor(FAMILY); - htd.addFamily(hcd); - Configuration conf = TEST_UTIL.getConfiguration(); - // Create 10 New regions. - createMultiRegionsWithNewHRI(conf, htd, FAMILY, 10); - // Create 10 Legacy regions. - createMultiRegionsWithLegacyHRI(conf, htd, FAMILY, 10); - CatalogTracker ct = - TEST_UTIL.getMiniHBaseCluster().getMaster().getCatalogTracker(); - // Erase the current version of root meta for this test. - undoVersionInMeta(); - MetaMigrationRemovingHTD.updateRootWithMetaMigrationStatus(ct); - //MetaReader.fullScanMetaAndPrint(ct); - LOG.info("Meta Print completed.testUpdatesOnMetaWithLegacyHRI"); - - Set htds = - MetaMigrationRemovingHTD.updateMetaWithNewRegionInfo( - TEST_UTIL.getHBaseCluster().getMaster()); - assertEquals(1, htds.size()); - assertTrue(htds.contains(htd)); - // Assert that the flag in ROOT is updated to reflect the correct status - boolean metaUpdated = MetaMigrationRemovingHTD. - isMetaHRIUpdated(TEST_UTIL.getMiniHBaseCluster().getMaster()); - assertEquals(true, metaUpdated); - LOG.info("END testMetaWithLegacyHRI"); - } - - private void undoVersionInMeta() throws IOException { - Delete d = new Delete(HRegionInfo.ROOT_REGIONINFO.getRegionName()); - // Erase the current version of root meta for this test. - d.deleteColumn(HConstants.CATALOG_FAMILY, HConstants.META_VERSION_QUALIFIER); - HTable rootTable = - new HTable(TEST_UTIL.getConfiguration(), HConstants.ROOT_TABLE_NAME); - try { - rootTable.delete(d); - } finally { - rootTable.close(); - } - } - - public static void assertEquals(int expected, int actual) { - if (expected != actual) { - throw new AssertionFailedError("expected:<" + - expected + "> but was:<" + - actual + ">"); - } - } - - public static void assertEquals(boolean expected, boolean actual) { - if (expected != actual) { - throw new AssertionFailedError("expected:<" + - expected + "> but was:<" + - actual + ">"); - } - } - - - /** - * @param c - * @param htd - * @param family - * @param numRegions - * @return - * @throws IOException - * @deprecated Just for testing migration of meta from 0.90 to 0.92... will be - * removed thereafter - */ - public int createMultiRegionsWithLegacyHRI(final Configuration c, - final HTableDescriptor htd, final byte [] family, int numRegions) - throws IOException { - if (numRegions < 3) throw new IOException("Must create at least 3 regions"); - byte [] startKey = Bytes.toBytes("aaaaa"); - byte [] endKey = Bytes.toBytes("zzzzz"); - byte [][] splitKeys = Bytes.split(startKey, endKey, numRegions - 3); - byte [][] regionStartKeys = new byte[splitKeys.length+1][]; - for (int i=0;i newRegions - = new ArrayList(startKeys.length); - int count = 0; - for (int i = 0; i < startKeys.length; i++) { - int j = (i + 1) % startKeys.length; - HRegionInfo090x hri = new HRegionInfo090x(htd, - startKeys[i], startKeys[j]); - Put put = new Put(hri.getRegionName()); - put.setWriteToWAL(false); - put.add(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER, - Writables.getBytes(hri)); - meta.put(put); - LOG.info("createMultiRegions: PUT inserted " + hri.toString()); - - newRegions.add(hri); - count++; - } - meta.close(); - return count; - } - - int createMultiRegionsWithNewHRI(final Configuration c, - final HTableDescriptor htd, final byte [] family, int numRegions) - throws IOException { - if (numRegions < 3) throw new IOException("Must create at least 3 regions"); - byte [] startKey = Bytes.toBytes("aaaaa"); - byte [] endKey = Bytes.toBytes("zzzzz"); - byte [][] splitKeys = Bytes.split(startKey, endKey, numRegions - 3); - byte [][] regionStartKeys = new byte[splitKeys.length+1][]; - for (int i=0;i newRegions - = new ArrayList(startKeys.length); - int count = 0; - for (int i = 0; i < startKeys.length; i++) { - int j = (i + 1) % startKeys.length; - HRegionInfo hri = new HRegionInfo(htd.getName(), - startKeys[i], startKeys[j]); - Put put = new Put(hri.getRegionName()); - put.setWriteToWAL(false); - put.add(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER, - Writables.getBytes(hri)); - meta.put(put); - LOG.info("createMultiRegions: PUT inserted " + hri.toString()); - - newRegions.add(hri); - count++; - } - meta.close(); - return count; - } - - @org.junit.Rule - public org.apache.hadoop.hbase.ResourceCheckerJUnitRule cu = - new org.apache.hadoop.hbase.ResourceCheckerJUnitRule(); -} - diff --git src/test/java/org/apache/hadoop/hbase/coprocessor/SimpleRegionObserver.java src/test/java/org/apache/hadoop/hbase/coprocessor/SimpleRegionObserver.java index dacb936..a2f5dfc 100644 --- src/test/java/org/apache/hadoop/hbase/coprocessor/SimpleRegionObserver.java +++ src/test/java/org/apache/hadoop/hbase/coprocessor/SimpleRegionObserver.java @@ -73,8 +73,6 @@ public class SimpleRegionObserver extends BaseRegionObserver { boolean hadPostPut = false; boolean hadPreDeleted = false; boolean hadPostDeleted = false; - boolean hadPreGetClosestRowBefore = false; - boolean hadPostGetClosestRowBefore = false; boolean hadPreIncrement = false; boolean hadPostIncrement = false; boolean hadPreWALRestored = false; @@ -345,32 +343,6 @@ public class SimpleRegionObserver extends BaseRegionObserver { } @Override - public void preGetClosestRowBefore(final ObserverContext c, - final byte[] row, final byte[] family, final Result result) - throws IOException { - RegionCoprocessorEnvironment e = c.getEnvironment(); - assertNotNull(e); - assertNotNull(e.getRegion()); - assertNotNull(row); - assertNotNull(result); - if (beforeDelete) { - hadPreGetClosestRowBefore = true; - } - } - - @Override - public void postGetClosestRowBefore(final ObserverContext c, - final byte[] row, final byte[] family, final Result result) - throws IOException { - RegionCoprocessorEnvironment e = c.getEnvironment(); - assertNotNull(e); - assertNotNull(e.getRegion()); - assertNotNull(row); - assertNotNull(result); - hadPostGetClosestRowBefore = true; - } - - @Override public Result preIncrement(final ObserverContext c, final Increment increment) throws IOException { hadPreIncrement = true; diff --git src/test/java/org/apache/hadoop/hbase/master/MockRegionServer.java src/test/java/org/apache/hadoop/hbase/master/MockRegionServer.java index a59e152..61dd5cf 100644 --- src/test/java/org/apache/hadoop/hbase/master/MockRegionServer.java +++ src/test/java/org/apache/hadoop/hbase/master/MockRegionServer.java @@ -257,13 +257,6 @@ class MockRegionServer implements HRegionInterface, ClientProtocol, RegionServer } @Override - public Result getClosestRowBefore(byte[] regionName, byte[] row, - byte[] family) throws IOException { - // TODO Auto-generated method stub - return null; - } - - @Override public Result get(byte[] regionName, Get get) throws IOException { // TODO Auto-generated method stub return null; diff --git src/test/java/org/apache/hadoop/hbase/migration/TestMigration.java src/test/java/org/apache/hadoop/hbase/migration/TestMigration.java new file mode 100644 index 0000000..e637c31 --- /dev/null +++ src/test/java/org/apache/hadoop/hbase/migration/TestMigration.java @@ -0,0 +1,78 @@ +/** + * 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.hadoop.hbase.migration; + + +import java.io.IOException; + +import junit.framework.Assert; + +import org.apache.hadoop.hbase.*; +import org.apache.hadoop.hbase.util.Bytes; +import org.apache.hadoop.hbase.catalog.MetaMigrationRemovingHTD; +import org.apache.hadoop.hbase.util.Writables; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +@Category(LargeTests.class) +public class TestMigration { + @Test + public void testMigrateHRegionInfoFromVersion0toVersion2() + throws IOException { + HTableDescriptor htd = + getHTableDescriptor("testMigrateHRegionInfoFromVersion0toVersion2"); + HRegionInfo090x ninety = + new HRegionInfo090x(htd, HConstants.EMPTY_START_ROW, HConstants.EMPTY_END_ROW); + byte [] bytes = Writables.getBytes(ninety); + // Now deserialize into an HRegionInfo + HRegionInfo hri = Writables.getHRegionInfo(bytes); + Assert.assertEquals(hri.getTableNameAsString(), + ninety.getTableDesc().getNameAsString()); + Assert.assertEquals(HRegionInfo.VERSION, hri.getVersion()); + } + + @Test + public void testMigrateHRegionInfoFromVersion1toVersion2() + throws IOException { + String tableName = "testMigrateHRegionInfoFromVersion1toVersion2"; + byte[] tableNameB = Bytes.toBytes(tableName); + + HRegionInfo090x2 ninety = + new HRegionInfo090x2(tableNameB, + HConstants.EMPTY_START_ROW, + HConstants.EMPTY_END_ROW); + byte [] bytes = Writables.getBytes(ninety); + // Now deserialize into an HRegionInfo + HRegionInfo hri = Writables.getHRegionInfo(bytes); + Assert.assertEquals(hri.getTableNameAsString(), + Bytes.toString(ninety.getTableName())); + Assert.assertEquals(HRegionInfo.VERSION, hri.getVersion()); + } + + + private HTableDescriptor getHTableDescriptor(final String name) { + HTableDescriptor htd = new HTableDescriptor(name); + htd.addFamily(new HColumnDescriptor("family")); + return htd; + } + + @org.junit.Rule + public org.apache.hadoop.hbase.ResourceCheckerJUnitRule cu = + new org.apache.hadoop.hbase.ResourceCheckerJUnitRule(); +} + diff --git src/test/java/org/apache/hadoop/hbase/migration/TestMigrationFrom090To092.java src/test/java/org/apache/hadoop/hbase/migration/TestMigrationFrom090To092.java deleted file mode 100644 index c3651ac..0000000 --- src/test/java/org/apache/hadoop/hbase/migration/TestMigrationFrom090To092.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * 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.hadoop.hbase.migration; - - -import java.io.IOException; - -import junit.framework.Assert; - -import org.apache.hadoop.hbase.*; -import org.apache.hadoop.hbase.catalog.MetaMigrationRemovingHTD; -import org.apache.hadoop.hbase.util.Writables; -import org.junit.Test; -import org.junit.experimental.categories.Category; - -/** - * Migration tests that do not need spin up of a cluster. - * @deprecated Remove after we release 0.92 - */ -@Category(SmallTests.class) -public class TestMigrationFrom090To092 { - @Test - public void testMigrateHRegionInfoFromVersion0toVersion1() - throws IOException { - HTableDescriptor htd = - getHTableDescriptor("testMigrateHRegionInfoFromVersion0toVersion1"); - HRegionInfo090x ninety = - new HRegionInfo090x(htd, HConstants.EMPTY_START_ROW, HConstants.EMPTY_END_ROW); - byte [] bytes = Writables.getBytes(ninety); - // Now deserialize into an HRegionInfo - HRegionInfo hri = Writables.getHRegionInfo(bytes); - Assert.assertEquals(hri.getTableNameAsString(), - ninety.getTableDesc().getNameAsString()); - Assert.assertEquals(HRegionInfo.VERSION, hri.getVersion()); - } - - private HTableDescriptor getHTableDescriptor(final String name) { - HTableDescriptor htd = new HTableDescriptor(name); - htd.addFamily(new HColumnDescriptor("family")); - return htd; - } - - @org.junit.Rule - public org.apache.hadoop.hbase.ResourceCheckerJUnitRule cu = - new org.apache.hadoop.hbase.ResourceCheckerJUnitRule(); -} - diff --git src/test/java/org/apache/hadoop/hbase/regionserver/TestGetClosestAtOrBefore.java src/test/java/org/apache/hadoop/hbase/regionserver/TestGetClosestAtOrBefore.java deleted file mode 100644 index 5f97167..0000000 --- src/test/java/org/apache/hadoop/hbase/regionserver/TestGetClosestAtOrBefore.java +++ /dev/null @@ -1,348 +0,0 @@ -/** - * Copyright 2009 The Apache Software Foundation - * - * 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.hadoop.hbase.regionserver; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.fs.FileSystem; -import org.apache.hadoop.fs.Path; -import org.apache.hadoop.hbase.*; -import org.apache.hadoop.hbase.client.Delete; -import org.apache.hadoop.hbase.client.Put; -import org.apache.hadoop.hbase.client.Result; -import org.apache.hadoop.hbase.client.Scan; -import org.apache.hadoop.hbase.util.Bytes; -import org.apache.hadoop.hbase.util.Writables; -import org.apache.hadoop.hdfs.MiniDFSCluster; -import org.junit.experimental.categories.Category; - -/** - * {@link TestGet} is a medley of tests of get all done up as a single test. - * This class - */ -@Category(SmallTests.class) -public class TestGetClosestAtOrBefore extends HBaseTestCase { - private static final Log LOG = LogFactory.getLog(TestGetClosestAtOrBefore.class); - - private static final byte[] T00 = Bytes.toBytes("000"); - private static final byte[] T10 = Bytes.toBytes("010"); - private static final byte[] T11 = Bytes.toBytes("011"); - private static final byte[] T12 = Bytes.toBytes("012"); - private static final byte[] T20 = Bytes.toBytes("020"); - private static final byte[] T30 = Bytes.toBytes("030"); - private static final byte[] T31 = Bytes.toBytes("031"); - private static final byte[] T35 = Bytes.toBytes("035"); - private static final byte[] T40 = Bytes.toBytes("040"); - - - - public void testUsingMetaAndBinary() throws IOException { - FileSystem filesystem = FileSystem.get(conf); - Path rootdir = testDir; - // Up flush size else we bind up when we use default catalog flush of 16k. - HTableDescriptor.META_TABLEDESC.setMemStoreFlushSize(64 * 1024 * 1024); - - HRegion mr = HRegion.createHRegion(HRegionInfo.FIRST_META_REGIONINFO, - rootdir, this.conf, HTableDescriptor.META_TABLEDESC); - try { - // Write rows for three tables 'A', 'B', and 'C'. - for (char c = 'A'; c < 'D'; c++) { - HTableDescriptor htd = new HTableDescriptor("" + c); - final int last = 128; - final int interval = 2; - for (int i = 0; i <= last; i += interval) { - HRegionInfo hri = new HRegionInfo(htd.getName(), - i == 0? HConstants.EMPTY_BYTE_ARRAY: Bytes.toBytes((byte)i), - i == last? HConstants.EMPTY_BYTE_ARRAY: Bytes.toBytes((byte)i + interval)); - Put put = new Put(hri.getRegionName()); - put.setWriteToWAL(false); - put.add(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER, - Writables.getBytes(hri)); - mr.put(put, false); - } - } - InternalScanner s = mr.getScanner(new Scan()); - try { - List keys = new ArrayList(); - while(s.next(keys)) { - LOG.info(keys); - keys.clear(); - } - } finally { - s.close(); - } - findRow(mr, 'C', 44, 44); - findRow(mr, 'C', 45, 44); - findRow(mr, 'C', 46, 46); - findRow(mr, 'C', 43, 42); - mr.flushcache(); - findRow(mr, 'C', 44, 44); - findRow(mr, 'C', 45, 44); - findRow(mr, 'C', 46, 46); - findRow(mr, 'C', 43, 42); - // Now delete 'C' and make sure I don't get entries from 'B'. - byte [] firstRowInC = HRegionInfo.createRegionName(Bytes.toBytes("" + 'C'), - HConstants.EMPTY_BYTE_ARRAY, HConstants.ZEROES, false); - Scan scan = new Scan(firstRowInC); - s = mr.getScanner(scan); - try { - List keys = new ArrayList(); - while (s.next(keys)) { - mr.delete(new Delete(keys.get(0).getRow()), null, false); - keys.clear(); - } - } finally { - s.close(); - } - // Assert we get null back (pass -1). - findRow(mr, 'C', 44, -1); - findRow(mr, 'C', 45, -1); - findRow(mr, 'C', 46, -1); - findRow(mr, 'C', 43, -1); - mr.flushcache(); - findRow(mr, 'C', 44, -1); - findRow(mr, 'C', 45, -1); - findRow(mr, 'C', 46, -1); - findRow(mr, 'C', 43, -1); - } finally { - if (mr != null) { - try { - mr.close(); - } catch (Exception e) { - e.printStackTrace(); - } - mr.getLog().closeAndDelete(); - } - } - } - - /* - * @param mr - * @param table - * @param rowToFind - * @param answer Pass -1 if we're not to find anything. - * @return Row found. - * @throws IOException - */ - private byte [] findRow(final HRegion mr, final char table, - final int rowToFind, final int answer) - throws IOException { - byte [] tableb = Bytes.toBytes("" + table); - // Find the row. - byte [] tofindBytes = Bytes.toBytes((short)rowToFind); - byte [] metaKey = HRegionInfo.createRegionName(tableb, tofindBytes, - HConstants.NINES, false); - LOG.info("find=" + new String(metaKey)); - Result r = mr.getClosestRowBefore(metaKey); - if (answer == -1) { - assertNull(r); - return null; - } - assertTrue(Bytes.compareTo(Bytes.toBytes((short)answer), - extractRowFromMetaRow(r.getRow())) == 0); - return r.getRow(); - } - - private byte [] extractRowFromMetaRow(final byte [] b) { - int firstDelimiter = KeyValue.getDelimiter(b, 0, b.length, - HRegionInfo.DELIMITER); - int lastDelimiter = KeyValue.getDelimiterInReverse(b, 0, b.length, - HRegionInfo.DELIMITER); - int length = lastDelimiter - firstDelimiter - 1; - byte [] row = new byte[length]; - System.arraycopy(b, firstDelimiter + 1, row, 0, length); - return row; - } - - /** - * Test file of multiple deletes and with deletes as final key. - * @see HBASE-751 - */ - public void testGetClosestRowBefore3() throws IOException{ - HRegion region = null; - byte [] c0 = COLUMNS[0]; - byte [] c1 = COLUMNS[1]; - try { - HTableDescriptor htd = createTableDescriptor(getName()); - region = createNewHRegion(htd, null, null); - - Put p = new Put(T00); - p.add(c0, c0, T00); - region.put(p); - - p = new Put(T10); - p.add(c0, c0, T10); - region.put(p); - - p = new Put(T20); - p.add(c0, c0, T20); - region.put(p); - - Result r = region.getClosestRowBefore(T20, c0); - assertTrue(Bytes.equals(T20, r.getRow())); - - Delete d = new Delete(T20); - d.deleteColumn(c0, c0); - region.delete(d, null, false); - - r = region.getClosestRowBefore(T20, c0); - assertTrue(Bytes.equals(T10, r.getRow())); - - p = new Put(T30); - p.add(c0, c0, T30); - region.put(p); - - r = region.getClosestRowBefore(T30, c0); - assertTrue(Bytes.equals(T30, r.getRow())); - - d = new Delete(T30); - d.deleteColumn(c0, c0); - region.delete(d, null, false); - - r = region.getClosestRowBefore(T30, c0); - assertTrue(Bytes.equals(T10, r.getRow())); - r = region.getClosestRowBefore(T31, c0); - assertTrue(Bytes.equals(T10, r.getRow())); - - region.flushcache(); - - // try finding "010" after flush - r = region.getClosestRowBefore(T30, c0); - assertTrue(Bytes.equals(T10, r.getRow())); - r = region.getClosestRowBefore(T31, c0); - assertTrue(Bytes.equals(T10, r.getRow())); - - // Put into a different column family. Should make it so I still get t10 - p = new Put(T20); - p.add(c1, c1, T20); - region.put(p); - - r = region.getClosestRowBefore(T30, c0); - assertTrue(Bytes.equals(T10, r.getRow())); - r = region.getClosestRowBefore(T31, c0); - assertTrue(Bytes.equals(T10, r.getRow())); - - region.flushcache(); - - r = region.getClosestRowBefore(T30, c0); - assertTrue(Bytes.equals(T10, r.getRow())); - r = region.getClosestRowBefore(T31, c0); - assertTrue(Bytes.equals(T10, r.getRow())); - - // Now try combo of memcache and mapfiles. Delete the t20 COLUMS[1] - // in memory; make sure we get back t10 again. - d = new Delete(T20); - d.deleteColumn(c1, c1); - region.delete(d, null, false); - r = region.getClosestRowBefore(T30, c0); - assertTrue(Bytes.equals(T10, r.getRow())); - - // Ask for a value off the end of the file. Should return t10. - r = region.getClosestRowBefore(T31, c0); - assertTrue(Bytes.equals(T10, r.getRow())); - region.flushcache(); - r = region.getClosestRowBefore(T31, c0); - assertTrue(Bytes.equals(T10, r.getRow())); - - // Ok. Let the candidate come out of hfile but have delete of - // the candidate be in memory. - p = new Put(T11); - p.add(c0, c0, T11); - region.put(p); - d = new Delete(T10); - d.deleteColumn(c1, c1); - r = region.getClosestRowBefore(T12, c0); - assertTrue(Bytes.equals(T11, r.getRow())); - } finally { - if (region != null) { - try { - region.close(); - } catch (Exception e) { - e.printStackTrace(); - } - region.getLog().closeAndDelete(); - } - } - } - - /** For HBASE-694 */ - public void testGetClosestRowBefore2() throws IOException{ - HRegion region = null; - byte [] c0 = COLUMNS[0]; - try { - HTableDescriptor htd = createTableDescriptor(getName()); - region = createNewHRegion(htd, null, null); - - Put p = new Put(T10); - p.add(c0, c0, T10); - region.put(p); - - p = new Put(T30); - p.add(c0, c0, T30); - region.put(p); - - p = new Put(T40); - p.add(c0, c0, T40); - region.put(p); - - // try finding "035" - Result r = region.getClosestRowBefore(T35, c0); - assertTrue(Bytes.equals(T30, r.getRow())); - - region.flushcache(); - - // try finding "035" - r = region.getClosestRowBefore(T35, c0); - assertTrue(Bytes.equals(T30, r.getRow())); - - p = new Put(T20); - p.add(c0, c0, T20); - region.put(p); - - // try finding "035" - r = region.getClosestRowBefore(T35, c0); - assertTrue(Bytes.equals(T30, r.getRow())); - - region.flushcache(); - - // try finding "035" - r = region.getClosestRowBefore(T35, c0); - assertTrue(Bytes.equals(T30, r.getRow())); - } finally { - if (region != null) { - try { - region.close(); - } catch (Exception e) { - e.printStackTrace(); - } - region.getLog().closeAndDelete(); - } - } - } - - @org.junit.Rule - public org.apache.hadoop.hbase.ResourceCheckerJUnitRule cu = - new org.apache.hadoop.hbase.ResourceCheckerJUnitRule(); -} - diff --git src/test/java/org/apache/hadoop/hbase/regionserver/TestHRegionInfo.java src/test/java/org/apache/hadoop/hbase/regionserver/TestHRegionInfo.java index 6dfba41..575962f 100644 --- src/test/java/org/apache/hadoop/hbase/regionserver/TestHRegionInfo.java +++ src/test/java/org/apache/hadoop/hbase/regionserver/TestHRegionInfo.java @@ -30,8 +30,6 @@ import java.io.IOException; import org.apache.hadoop.hbase.*; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.FSTableDescriptors; -import org.apache.hadoop.hbase.util.FSUtils; -import org.apache.hadoop.hbase.util.MD5Hash; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -43,22 +41,24 @@ public class TestHRegionInfo { final byte [] tn = Bytes.toBytes(tableName); String startKey = "startkey"; final byte [] sk = Bytes.toBytes(startKey); - String id = "id"; + String endKey = "endkey"; + final byte [] ek = Bytes.toBytes(endKey); + + String id = "id"; // old format region name - byte [] name = HRegionInfo.createRegionName(tn, sk, id, false); + byte [] name = HRegionInfo.createRegionName(tn, sk, ek, id, false); String nameStr = Bytes.toString(name); - assertEquals(tableName + "," + startKey + "," + id, nameStr); + assertEquals(tableName + "!," + endKey + "," + id, nameStr); - // new format region name. - String md5HashInHex = MD5Hash.getMD5AsHex(name); + // This should not change as it changes the location on HDFS. + String md5HashInHex = "e3365833b0bc503b5c0f4e8441da5897"; assertEquals(HRegionInfo.MD5_HEX_LENGTH, md5HashInHex.length()); - name = HRegionInfo.createRegionName(tn, sk, id, true); + name = HRegionInfo.createRegionName(tn, sk, ek, id, true); nameStr = Bytes.toString(name); - assertEquals(tableName + "," + startKey + "," - + id + "." + md5HashInHex + ".", - nameStr); + assertEquals(tableName + "!," + endKey + "," + id + "." + md5HashInHex + + ".", nameStr); } @Test diff --git src/test/java/org/apache/hadoop/hbase/regionserver/TestMinVersions.java src/test/java/org/apache/hadoop/hbase/regionserver/TestMinVersions.java index 33c78ab..fa1f37d 100644 --- src/test/java/org/apache/hadoop/hbase/regionserver/TestMinVersions.java +++ src/test/java/org/apache/hadoop/hbase/regionserver/TestMinVersions.java @@ -47,48 +47,6 @@ public class TestMinVersions extends HBaseTestCase { private final byte[] c0 = COLUMNS[0]; /** - * Verify behavior of getClosestBefore(...) - */ - public void testGetClosestBefore() throws Exception { - HTableDescriptor htd = createTableDescriptor(getName(), 1, 1000, 1, false); - HRegion region = createNewHRegion(htd, null, null); - - // 2s in the past - long ts = EnvironmentEdgeManager.currentTimeMillis() - 2000; - - Put p = new Put(T1, ts); - p.add(c0, c0, T1); - region.put(p); - - p = new Put(T1, ts+1); - p.add(c0, c0, T4); - region.put(p); - - p = new Put(T3, ts); - p.add(c0, c0, T3); - region.put(p); - - // now make sure that getClosestBefore(...) get can - // rows that would be expired without minVersion. - // also make sure it gets the latest version - Result r = region.getClosestRowBefore(T1, c0); - checkResult(r, c0, T4); - - r = region.getClosestRowBefore(T2, c0); - checkResult(r, c0, T4); - - // now flush/compact - region.flushcache(); - region.compactStores(true); - - r = region.getClosestRowBefore(T1, c0); - checkResult(r, c0, T4); - - r = region.getClosestRowBefore(T2, c0); - checkResult(r, c0, T4); - } - - /** * Test mixed memstore and storefile scanning * with minimum versions. */ diff --git src/test/java/org/apache/hadoop/hbase/rest/TestStatusResource.java src/test/java/org/apache/hadoop/hbase/rest/TestStatusResource.java index cffdcb6..108c9a1 100644 --- src/test/java/org/apache/hadoop/hbase/rest/TestStatusResource.java +++ src/test/java/org/apache/hadoop/hbase/rest/TestStatusResource.java @@ -27,6 +27,8 @@ import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import org.apache.hadoop.hbase.HBaseTestingUtility; +import org.apache.hadoop.hbase.HConstants; +import org.apache.hadoop.hbase.HRegionInfo; import org.apache.hadoop.hbase.MediumTests; import org.apache.hadoop.hbase.rest.client.Client; import org.apache.hadoop.hbase.rest.client.Cluster; @@ -42,8 +44,19 @@ import org.junit.experimental.categories.Category; @Category(MediumTests.class) public class TestStatusResource { - private static final byte[] ROOT_REGION_NAME = Bytes.toBytes("-ROOT-,,0"); - private static final byte[] META_REGION_NAME = Bytes.toBytes(".META.,,1"); + + private static final byte[] ROOT_REGION_NAME = HRegionInfo.createRegionName(HConstants.ROOT_TABLE_NAME, + HConstants.EMPTY_BYTE_ARRAY, + HConstants.EMPTY_BYTE_ARRAY, + "0".getBytes(), + false); + + private static final byte[] META_REGION_NAME = HRegionInfo.createRegionName(HConstants.META_TABLE_NAME, + HConstants.EMPTY_BYTE_ARRAY, + HConstants.EMPTY_BYTE_ARRAY, + "1".getBytes(), + false); + private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(); private static final HBaseRESTTestingUtility REST_TEST_UTIL = diff --git src/test/java/org/apache/hadoop/hbase/rest/model/TestStorageClusterStatusModel.java src/test/java/org/apache/hadoop/hbase/rest/model/TestStorageClusterStatusModel.java index c44f720..32e91d9 100644 --- src/test/java/org/apache/hadoop/hbase/rest/model/TestStorageClusterStatusModel.java +++ src/test/java/org/apache/hadoop/hbase/rest/model/TestStorageClusterStatusModel.java @@ -45,25 +45,19 @@ public class TestStorageClusterStatusModel extends TestCase { " name=\"test1\" maxHeapSizeMB=\"1024\" heapSizeMB=\"128\">" + "" + + " memstoreSizeMB=\"0\"/>" + "" + ""+ + " memstoreSizeMB=\"0\"/>"+ ""; - private static final String AS_PB = - "CjsKBXRlc3QxEOO6i+eeJBgAIIABKIAIMiMKCS1ST09ULSwsMBABGAEgACgAMAA4AUACSAFQAVgB" + - "YAFoAQpHCgV0ZXN0MhD+krHwniQYACCABCiACDIvChUuTUVUQS4sLDEyNDYwMDAwNDM3MjQQARgB" + - "IAAoADAAOAFAAkgBUAFYAWABaAEYAiAAKQAAAAAAAPA/"; - + private static final String AS_PB = +"Ci0KBXRlc3QxEOO6i+eeJBgAIIABKIAIMhUKCS1ST09ULSwsMBABGAEgACgAMAAKOQoFdGVzdDIQ"+ +"/pKx8J4kGAAggAQogAgyIQoVLk1FVEEuLCwxMjQ2MDAwMDQzNzI0EAEYASAAKAAwABgCIAApAAAA"+ +"AAAA8D8="; + private JAXBContext context; public TestStorageClusterStatusModel() throws JAXBException { @@ -77,10 +71,9 @@ public class TestStorageClusterStatusModel extends TestCase { model.setRequests(0); model.setAverageLoad(1.0); model.addLiveNode("test1", 1245219839331L, 128, 1024) - .addRegion(Bytes.toBytes("-ROOT-,,0"), 1, 1, 0, 0, 0, 1, 2, 1, 1, 1, 1, 1); + .addRegion(Bytes.toBytes("-ROOT-,,0"), 1, 1, 0, 0, 0); model.addLiveNode("test2", 1245239331198L, 512, 1024) - .addRegion(Bytes.toBytes(".META.,,1246000043724"),1, 1, 0, 0, 0, - 1, 2, 1, 1, 1, 1, 1); + .addRegion(Bytes.toBytes(".META.,,1246000043724"),1, 1, 0, 0, 0); return model; } @@ -126,13 +119,6 @@ public class TestStorageClusterStatusModel extends TestCase { assertEquals(region.getStorefileSizeMB(), 0); assertEquals(region.getMemstoreSizeMB(), 0); assertEquals(region.getStorefileIndexSizeMB(), 0); - assertEquals(region.getReadRequestsCount(), 1); - assertEquals(region.getWriteRequestsCount(), 2); - assertEquals(region.getRootIndexSizeKB(), 1); - assertEquals(region.getTotalStaticIndexSizeKB(), 1); - assertEquals(region.getTotalStaticBloomSizeKB(), 1); - assertEquals(region.getTotalCompactingKVs(), 1); - assertEquals(region.getCurrentCompactedKVs(), 1); assertFalse(regions.hasNext()); node = nodes.next(); assertEquals(node.getName(), "test2"); @@ -147,14 +133,6 @@ public class TestStorageClusterStatusModel extends TestCase { assertEquals(region.getStorefileSizeMB(), 0); assertEquals(region.getMemstoreSizeMB(), 0); assertEquals(region.getStorefileIndexSizeMB(), 0); - assertEquals(region.getReadRequestsCount(), 1); - assertEquals(region.getWriteRequestsCount(), 2); - assertEquals(region.getRootIndexSizeKB(), 1); - assertEquals(region.getTotalStaticIndexSizeKB(), 1); - assertEquals(region.getTotalStaticBloomSizeKB(), 1); - assertEquals(region.getTotalCompactingKVs(), 1); - assertEquals(region.getCurrentCompactedKVs(), 1); - assertFalse(regions.hasNext()); assertFalse(nodes.hasNext()); } diff --git src/test/java/org/apache/hadoop/hbase/rest/model/TestTableRegionModel.java src/test/java/org/apache/hadoop/hbase/rest/model/TestTableRegionModel.java index b6f0ab5..754c04b 100644 --- src/test/java/org/apache/hadoop/hbase/rest/model/TestTableRegionModel.java +++ src/test/java/org/apache/hadoop/hbase/rest/model/TestTableRegionModel.java @@ -45,7 +45,8 @@ public class TestTableRegionModel extends TestCase { " endKey=\"enp5eng=\"" + " startKey=\"YWJyYWNhZGJyYQ==\"" + " id=\"8731042424\"" + - " name=\"testtable,abracadbra,8731042424\"/>"; + " table=\"testtable\"" + + " name=\"testtable,zzyzx,8731042424\"/>"; private JAXBContext context; @@ -55,9 +56,7 @@ public class TestTableRegionModel extends TestCase { } private TableRegionModel buildTestModel() { - TableRegionModel model = - new TableRegionModel(TABLE, ID, START_KEY, END_KEY, LOCATION); - return model; + return new TableRegionModel(TABLE, ID, START_KEY, END_KEY, LOCATION); } @SuppressWarnings("unused") @@ -77,9 +76,12 @@ public class TestTableRegionModel extends TestCase { assertTrue(Bytes.equals(model.getEndKey(), END_KEY)); assertEquals(model.getId(), ID); assertEquals(model.getLocation(), LOCATION); - assertEquals(model.getName(), - TABLE + "," + Bytes.toString(START_KEY) + "," + Long.toString(ID) + - ".ad9860f031282c46ed431d7af8f94aca."); + byte[] regionInfo = HRegionInfo.createRegionName(TABLE.getBytes(), + START_KEY, + END_KEY, + Long.toString(ID).getBytes(), + true); + assertEquals(model.getName(), Bytes.toStringBinary(regionInfo)); } public void testBuildModel() throws Exception { @@ -90,17 +92,13 @@ public class TestTableRegionModel extends TestCase { TableRegionModel model = buildTestModel(); String modelName = model.getName(); HRegionInfo hri = new HRegionInfo(Bytes.toBytes(TABLE), - START_KEY, END_KEY, false, ID); + START_KEY, + END_KEY, + false, + ID); assertEquals(modelName, hri.getRegionNameAsString()); } - public void testSetName() { - TableRegionModel model = buildTestModel(); - String name = model.getName(); - model.setName(name); - assertEquals(name, model.getName()); - } - public void testFromXML() throws Exception { checkModel(fromXML(AS_XML)); } -- 1.7.9.4