Index: src/main/java/org/apache/hadoop/hbase/client/Mutation.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/client/Mutation.java (revision 0) +++ src/main/java/org/apache/hadoop/hbase/client/Mutation.java (revision 0) @@ -0,0 +1,195 @@ +/* + * Copyright 2011 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 java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.UUID; + +import org.apache.hadoop.hbase.HConstants; +import org.apache.hadoop.hbase.KeyValue; +import org.apache.hadoop.hbase.util.Bytes; + +public abstract class Mutation extends OperationWithAttributes { + protected byte [] row = null; + protected long ts = HConstants.LATEST_TIMESTAMP; + protected long lockId = -1L; + protected boolean writeToWAL = true; + protected Map> familyMap = + new TreeMap>(Bytes.BYTES_COMPARATOR); + + /** + * Compile the column family (i.e. schema) information + * into a Map. Useful for parsing and aggregation by debugging, + * logging, and administration tools. + * @return Map + */ + @Override + public Map getFingerprint() { + Map map = new HashMap(); + List families = new ArrayList(); + // ideally, we would also include table information, but that information + // is not stored in each Operation instance. + map.put("families", families); + for (Map.Entry> entry : this.familyMap.entrySet()) { + families.add(Bytes.toStringBinary(entry.getKey())); + } + return map; + } + + /** + * Compile the details beyond the scope of getFingerprint (row, columns, + * timestamps, etc.) into a Map along with the fingerprinted information. + * Useful for debugging, logging, and administration tools. + * @param maxCols a limit on the number of columns output prior to truncation + * @return Map + */ + @Override + public Map toMap(int maxCols) { + // we start with the fingerprint map and build on top of it. + Map map = getFingerprint(); + // replace the fingerprint's simple list of families with a + // map from column families to lists of qualifiers and kv details + Map>> columns = + new HashMap>>(); + map.put("families", columns); + map.put("row", Bytes.toStringBinary(this.row)); + int colCount = 0; + // iterate through all column families affected + for (Map.Entry> entry : this.familyMap.entrySet()) { + // map from this family to details for each kv affected within the family + List> qualifierDetails = + new ArrayList>(); + columns.put(Bytes.toStringBinary(entry.getKey()), qualifierDetails); + colCount += entry.getValue().size(); + if (maxCols <= 0) { + continue; + } + // add details for each kv + for (KeyValue kv : entry.getValue()) { + if (--maxCols <= 0 ) { + continue; + } + Map kvMap = kv.toStringMap(); + // row and family information are already available in the bigger map + kvMap.remove("row"); + kvMap.remove("family"); + qualifierDetails.add(kvMap); + } + } + map.put("totalColumns", colCount); + return map; + } + + /** + * @return true if edits should be applied to WAL, false if not + */ + public boolean getWriteToWAL() { + return this.writeToWAL; + } + + /** + * Set whether this Delete should be written to the WAL or not. + * Not writing the WAL means you may lose edits on server crash. + * @param write true if edits should be written to WAL, false if not + */ + public void setWriteToWAL(boolean write) { + this.writeToWAL = write; + } + + /** + * Method for retrieving the put's familyMap + * @return familyMap + */ + public Map> getFamilyMap() { + return this.familyMap; + } + + /** + * Method to check if the familyMap is empty + * @return true if empty, false otherwise + */ + public boolean isEmpty() { + return familyMap.isEmpty(); + } + + /** + * Method for retrieving the delete's row + * @return row + */ + public byte [] getRow() { + return this.row; + } + + public int compareTo(final Row d) { + return Bytes.compareTo(this.getRow(), d.getRow()); + } + + /** + * Method for retrieving the delete's RowLock + * @return RowLock + */ + public RowLock getRowLock() { + return new RowLock(this.row, this.lockId); + } + + /** + * Method for retrieving the delete's lock ID. + * + * @return The lock ID. + */ + public long getLockId() { + return this.lockId; + } + + /** + * Method for retrieving the timestamp + * @return timestamp + */ + public long getTimeStamp() { + return this.ts; + } + + /** + * Set the replication custer id. + * @param clusterId + */ + public void setClusterId(UUID clusterId) { + byte[] val = new byte[2*Bytes.SIZEOF_LONG]; + Bytes.putLong(val, 0, clusterId.getMostSignificantBits()); + Bytes.putLong(val, Bytes.SIZEOF_LONG, clusterId.getLeastSignificantBits()); + setAttribute(HConstants.CLUSTER_ID_ATTR, val); + } + + /** + * @return The replication cluster id. + */ + public UUID getClusterId() { + byte[] attr = getAttribute(HConstants.CLUSTER_ID_ATTR); + if (attr == null) { + return HConstants.DEFAULT_CLUSTER_ID; + } + return new UUID(Bytes.toLong(attr,0), Bytes.toLong(attr, Bytes.SIZEOF_LONG)); + } +} Index: src/main/java/org/apache/hadoop/hbase/client/Delete.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/client/Delete.java (revision 1167301) +++ src/main/java/org/apache/hadoop/hbase/client/Delete.java (working copy) @@ -24,20 +24,13 @@ import org.apache.hadoop.hbase.KeyValue; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.io.Writable; -import org.apache.hadoop.io.WritableUtils; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; -import java.util.TreeMap; -import java.util.TreeSet; -import java.util.UUID; /** * Used to perform Delete operations on a single row. @@ -71,21 +64,10 @@ * deleteFamily -- then you need to use the method overrides that take a * timestamp. The constructor timestamp is not referenced. */ -public class Delete extends Operation +public class Delete extends Mutation implements Writable, Row, Comparable { private static final byte DELETE_VERSION = (byte)3; - private byte [] row = null; - // This ts is only used when doing a deleteRow. Anything less, - private long ts; - private long lockId = -1L; - private boolean writeToWAL = true; - private final Map> familyMap = - new TreeMap>(Bytes.BYTES_COMPARATOR); - - // a opaque blob that can be passed into a Delete. - private Map attributes; - /** Constructor for Writable. DO NOT USE */ public Delete() { this((byte [])null); @@ -136,19 +118,7 @@ this.writeToWAL = d.writeToWAL; } - public int compareTo(final Row d) { - return Bytes.compareTo(this.getRow(), d.getRow()); - } - /** - * Method to check if the familyMap is empty - * @return true if empty, false otherwise - */ - public boolean isEmpty() { - return familyMap.isEmpty(); - } - - /** * Delete all versions of all columns of the specified family. *

* Overrides previous calls to deleteColumn and deleteColumns for the @@ -246,47 +216,6 @@ } /** - * Method for retrieving the delete's familyMap - * @return familyMap - */ - public Map> getFamilyMap() { - return this.familyMap; - } - - /** - * Method for retrieving the delete's row - * @return row - */ - public byte [] getRow() { - return this.row; - } - - /** - * Method for retrieving the delete's RowLock - * @return RowLock - */ - public RowLock getRowLock() { - return new RowLock(this.row, this.lockId); - } - - /** - * Method for retrieving the delete's lock ID. - * - * @return The lock ID. - */ - public long getLockId() { - return this.lockId; - } - - /** - * Method for retrieving the delete's timestamp - * @return timestamp - */ - public long getTimeStamp() { - return this.ts; - } - - /** * Set the timestamp of the delete. * * @param timestamp @@ -295,115 +224,12 @@ this.ts = timestamp; } - /** - * Sets arbitrary delete's attribute. - * In case value = null attribute is removed from the attributes map. - * @param name attribute name - * @param value attribute value - */ - public void setAttribute(String name, byte[] value) { - if (attributes == null && value == null) { - return; - } - - if (attributes == null) { - attributes = new HashMap(); - } - - if (value == null) { - attributes.remove(name); - if (attributes.isEmpty()) { - this.attributes = null; - } - } else { - attributes.put(name, value); - } - } - - /** - * Gets put's attribute - * @param name attribute name - * @return attribute value if attribute is set, null otherwise - */ - public byte[] getAttribute(String name) { - if (attributes == null) { - return null; - } - return attributes.get(name); - } - - /** - * Gets all scan's attributes - * @return unmodifiable map of all attributes - */ - public Map getAttributesMap() { - if (attributes == null) { - return Collections.emptyMap(); - } - return Collections.unmodifiableMap(attributes); - } - - /** - * Compile the column family (i.e. schema) information - * into a Map. Useful for parsing and aggregation by debugging, - * logging, and administration tools. - * @return Map - */ @Override - public Map getFingerprint() { - Map map = new HashMap(); - List families = new ArrayList(); - // ideally, we would also include table information, but that information - // is not stored in each Operation instance. - map.put("families", families); - for (Map.Entry> entry : this.familyMap.entrySet()) { - families.add(Bytes.toStringBinary(entry.getKey())); - } - return map; - } - - /** - * Compile the details beyond the scope of getFingerprint (row, columns, - * timestamps, etc.) into a Map along with the fingerprinted information. - * Useful for debugging, logging, and administration tools. - * @param maxCols a limit on the number of columns output prior to truncation - * @return Map - */ - @Override public Map toMap(int maxCols) { // we start with the fingerprint map and build on top of it. - Map map = getFingerprint(); - // replace the fingerprint's simple list of families with a - // map from column families to lists of qualifiers and kv details - Map>> columns = - new HashMap>>(); - map.put("families", columns); - map.put("row", Bytes.toStringBinary(this.row)); + Map map = super.toMap(maxCols); + // why is put not doing this? map.put("ts", this.ts); - int colCount = 0; - // iterate through all column families affected by this Delete - for (Map.Entry> entry : this.familyMap.entrySet()) { - // map from this family to details for each kv affected within the family - List> qualifierDetails = - new ArrayList>(); - columns.put(Bytes.toStringBinary(entry.getKey()), qualifierDetails); - colCount += entry.getValue().size(); - if (maxCols <= 0) { - continue; - } - // add details for each kv - for (KeyValue kv : entry.getValue()) { - if (--maxCols <= 0 ) { - continue; - } - Map kvMap = kv.toStringMap(); - // row and family information are already available in the bigger map - kvMap.remove("row"); - kvMap.remove("family"); - qualifierDetails.add(kvMap); - } - } - map.put("totalColumns", colCount); return map; } @@ -433,15 +259,7 @@ this.familyMap.put(family, list); } if (version > 1) { - int numAttributes = in.readInt(); - if (numAttributes > 0) { - this.attributes = new HashMap(); - for(int i=0; i attr : this.attributes.entrySet()) { - WritableUtils.writeString(out, attr.getKey()); - Bytes.writeByteArray(out, attr.getValue()); - } - } + writeAttributes(out); } /** @@ -498,42 +308,4 @@ this.deleteColumn(parts[0], parts[1], HConstants.LATEST_TIMESTAMP); return this; } - - /** - * @return true if edits should be applied to WAL, false if not - */ - public boolean getWriteToWAL() { - return this.writeToWAL; - } - - /** - * Set whether this Delete should be written to the WAL or not. - * Not writing the WAL means you may lose edits on server crash. - * @param write true if edits should be written to WAL, false if not - */ - public void setWriteToWAL(boolean write) { - this.writeToWAL = write; - } - - /** - * Set the replication custer id. - * @param clusterId - */ - public void setClusterId(UUID clusterId) { - byte[] val = new byte[2*Bytes.SIZEOF_LONG]; - Bytes.putLong(val, 0, clusterId.getMostSignificantBits()); - Bytes.putLong(val, Bytes.SIZEOF_LONG, clusterId.getLeastSignificantBits()); - setAttribute(HConstants.CLUSTER_ID_ATTR, val); - } - - /** - * @return The replication cluster id. - */ - public UUID getClusterId() { - byte[] attr = getAttribute(HConstants.CLUSTER_ID_ATTR); - if (attr == null) { - return HConstants.DEFAULT_CLUSTER_ID; - } - return new UUID(Bytes.toLong(attr,0), Bytes.toLong(attr, Bytes.SIZEOF_LONG)); - } } Index: src/main/java/org/apache/hadoop/hbase/client/OperationWithAttributes.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/client/OperationWithAttributes.java (revision 0) +++ src/main/java/org/apache/hadoop/hbase/client/OperationWithAttributes.java (revision 0) @@ -0,0 +1,107 @@ +/* + * Copyright 2011 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 java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.apache.hadoop.hbase.util.Bytes; +import org.apache.hadoop.hbase.util.ClassSize; +import org.apache.hadoop.io.WritableUtils; + +public abstract class OperationWithAttributes extends Operation implements Attributes { + // a opaque blob of attributes + private Map attributes; + + public void setAttribute(String name, byte[] value) { + if (attributes == null && value == null) { + return; + } + + if (attributes == null) { + attributes = new HashMap(); + } + + if (value == null) { + attributes.remove(name); + if (attributes.isEmpty()) { + this.attributes = null; + } + } else { + attributes.put(name, value); + } + } + + public byte[] getAttribute(String name) { + if (attributes == null) { + return null; + } + + return attributes.get(name); + } + + public Map getAttributesMap() { + if (attributes == null) { + return Collections.emptyMap(); + } + return Collections.unmodifiableMap(attributes); + } + + protected long getAttributeSize() { + long size = 0; + if (attributes != null) { + size += ClassSize.align(this.attributes.size() * ClassSize.MAP_ENTRY); + for(Map.Entry entry : this.attributes.entrySet()) { + size += ClassSize.align(ClassSize.STRING + entry.getKey().length()); + size += ClassSize.align(ClassSize.ARRAY + entry.getValue().length); + } + } + return size; + } + + protected void writeAttributes(final DataOutput out) throws IOException { + if (this.attributes == null) { + out.writeInt(0); + } else { + out.writeInt(this.attributes.size()); + for (Map.Entry attr : this.attributes.entrySet()) { + WritableUtils.writeString(out, attr.getKey()); + Bytes.writeByteArray(out, attr.getValue()); + } + } + } + + protected void readAttributes(final DataInput in) throws IOException { + int numAttributes = in.readInt(); + if (numAttributes > 0) { + this.attributes = new HashMap(); + for(int i=0; i @@ -50,21 +43,10 @@ * for each column to be inserted, execute {@link #add(byte[], byte[], byte[]) add} or * {@link #add(byte[], byte[], long, byte[]) add} if setting the timestamp. */ -public class Put extends Operation +public class Put extends Mutation implements HeapSize, Writable, Row, Comparable { private static final byte PUT_VERSION = (byte)2; - private byte [] row = null; - private long timestamp = HConstants.LATEST_TIMESTAMP; - private long lockId = -1L; - private boolean writeToWAL = true; - - private Map> familyMap = - new TreeMap>(Bytes.BYTES_COMPARATOR); - - // a opaque blob that can be passed into a Put. - private Map attributes; - private static final long OVERHEAD = ClassSize.align( ClassSize.OBJECT + 2 * ClassSize.REFERENCE + 2 * Bytes.SIZEOF_LONG + Bytes.SIZEOF_BOOLEAN + @@ -111,7 +93,7 @@ throw new IllegalArgumentException("Row key is invalid"); } this.row = Arrays.copyOf(row, row.length); - this.timestamp = ts; + this.ts = ts; if(rowLock != null) { this.lockId = rowLock.getLockId(); } @@ -122,7 +104,7 @@ * @param putToCopy put to copy */ public Put(Put putToCopy) { - this(putToCopy.getRow(), putToCopy.timestamp, putToCopy.getRowLock()); + this(putToCopy.getRow(), putToCopy.ts, putToCopy.getRowLock()); this.familyMap = new TreeMap>(Bytes.BYTES_COMPARATOR); for(Map.Entry> entry : @@ -140,7 +122,7 @@ * @return this */ public Put add(byte [] family, byte [] qualifier, byte [] value) { - return add(family, qualifier, this.timestamp, value); + return add(family, qualifier, this.ts, value); } /** @@ -207,7 +189,7 @@ * existing KeyValue object in the family map. */ public boolean has(byte [] family, byte [] qualifier) { - return has(family, qualifier, this.timestamp, new byte[0], true, true); + return has(family, qualifier, this.ts, new byte[0], true, true); } /** @@ -237,7 +219,7 @@ * existing KeyValue object in the family map. */ public boolean has(byte [] family, byte [] qualifier, byte [] value) { - return has(family, qualifier, this.timestamp, value, true, false); + return has(family, qualifier, this.ts, value, true, false); } /** @@ -337,53 +319,6 @@ } /** - * Method for retrieving the put's familyMap - * @return familyMap - */ - public Map> getFamilyMap() { - return this.familyMap; - } - - /** - * Method for retrieving the put's row - * @return row - */ - public byte [] getRow() { - return this.row; - } - - /** - * Method for retrieving the put's RowLock - * @return RowLock - */ - public RowLock getRowLock() { - return new RowLock(this.row, this.lockId); - } - - /** - * Method for retrieving the put's lockId - * @return lockId - */ - public long getLockId() { - return this.lockId; - } - - /** - * Method to check if the familyMap is empty - * @return true if empty, false otherwise - */ - public boolean isEmpty() { - return familyMap.isEmpty(); - } - - /** - * @return Timestamp - */ - public long getTimeStamp() { - return this.timestamp; - } - - /** * @return the number of different families included in this put */ public int numFamilies() { @@ -401,138 +336,6 @@ return size; } - /** - * @return true if edits should be applied to WAL, false if not - */ - public boolean getWriteToWAL() { - return this.writeToWAL; - } - - /** - * Set whether this Put should be written to the WAL or not. - * Not writing the WAL means you may lose edits on server crash. - * @param write true if edits should be written to WAL, false if not - */ - public void setWriteToWAL(boolean write) { - this.writeToWAL = write; - } - - /** - * Sets arbitrary put's attribute. - * In case value = null attribute is removed from the attributes map. - * @param name attribute name - * @param value attribute value - */ - public void setAttribute(String name, byte[] value) { - if (attributes == null && value == null) { - return; - } - - if (attributes == null) { - attributes = new HashMap(); - } - - if (value == null) { - attributes.remove(name); - if (attributes.isEmpty()) { - this.attributes = null; - } - } else { - attributes.put(name, value); - } - } - - /** - * Gets put's attribute - * @param name attribute name - * @return attribute value if attribute is set, null otherwise - */ - public byte[] getAttribute(String name) { - if (attributes == null) { - return null; - } - - return attributes.get(name); - } - - /** - * Gets all scan's attributes - * @return unmodifiable map of all attributes - */ - public Map getAttributesMap() { - if (attributes == null) { - return Collections.emptyMap(); - } - return Collections.unmodifiableMap(attributes); - } - - /** - * Compile the column family (i.e. schema) information - * into a Map. Useful for parsing and aggregation by debugging, - * logging, and administration tools. - * @return Map - */ - @Override - public Map getFingerprint() { - Map map = new HashMap(); - List families = new ArrayList(); - // ideally, we would also include table information, but that information - // is not stored in each Operation instance. - map.put("families", families); - for (Map.Entry> entry : this.familyMap.entrySet()) { - families.add(Bytes.toStringBinary(entry.getKey())); - } - return map; - } - - /** - * Compile the details beyond the scope of getFingerprint (row, columns, - * timestamps, etc.) into a Map along with the fingerprinted information. - * Useful for debugging, logging, and administration tools. - * @param maxCols a limit on the number of columns output prior to truncation - * @return Map - */ - @Override - public Map toMap(int maxCols) { - // we start with the fingerprint map and build on top of it. - Map map = getFingerprint(); - // replace the fingerprint's simple list of families with a - // map from column families to lists of qualifiers and kv details - Map>> columns = - new HashMap>>(); - map.put("families", columns); - map.put("row", Bytes.toStringBinary(this.row)); - int colCount = 0; - // iterate through all column families affected by this Put - for (Map.Entry> entry : this.familyMap.entrySet()) { - // map from this family to details for each kv affected within the family - List> qualifierDetails = - new ArrayList>(); - columns.put(Bytes.toStringBinary(entry.getKey()), qualifierDetails); - colCount += entry.getValue().size(); - if (maxCols <= 0) { - continue; - } - // add details for each kv - for (KeyValue kv : entry.getValue()) { - if (--maxCols <= 0 ) { - continue; - } - Map kvMap = kv.toStringMap(); - // row and family information are already available in the bigger map - kvMap.remove("row"); - kvMap.remove("family"); - qualifierDetails.add(kvMap); - } - } - map.put("totalColumns", colCount); - return map; - } - - public int compareTo(Row p) { - return Bytes.compareTo(this.getRow(), p.getRow()); - } - //HeapSize public long heapSize() { long heapsize = OVERHEAD; @@ -559,13 +362,8 @@ heapsize += kv.heapSize(); } } - if (attributes != null) { - heapsize += ClassSize.align(this.attributes.size() * ClassSize.MAP_ENTRY); - for(Map.Entry entry : this.attributes.entrySet()) { - heapsize += ClassSize.align(ClassSize.STRING + entry.getKey().length()); - heapsize += ClassSize.align(ClassSize.ARRAY + entry.getValue().length); - } - } + heapsize += getAttributeSize(); + return ClassSize.align((int)heapsize); } @@ -577,7 +375,7 @@ throw new IOException("version not supported"); } this.row = Bytes.readByteArray(in); - this.timestamp = in.readLong(); + this.ts = in.readLong(); this.lockId = in.readLong(); this.writeToWAL = in.readBoolean(); int numFamilies = in.readInt(); @@ -598,15 +396,7 @@ this.familyMap.put(family, keys); } if (version > 1) { - int numAttributes = in.readInt(); - if (numAttributes > 0) { - this.attributes = new HashMap(); - for(int i=0; i attr : this.attributes.entrySet()) { - WritableUtils.writeString(out, attr.getKey()); - Bytes.writeByteArray(out, attr.getValue()); - } - } + writeAttributes(out); } /** @@ -657,26 +439,4 @@ byte [][] parts = KeyValue.parseColumn(column); return add(parts[0], parts[1], ts, value); } - - /** - * Set the replication custer id. - * @param clusterId - */ - public void setClusterId(UUID clusterId) { - byte[] val = new byte[2*Bytes.SIZEOF_LONG]; - Bytes.putLong(val, 0, clusterId.getMostSignificantBits()); - Bytes.putLong(val, Bytes.SIZEOF_LONG, clusterId.getLeastSignificantBits()); - setAttribute(HConstants.CLUSTER_ID_ATTR, val); - } - - /** - * @return The replication cluster id. - */ - public UUID getClusterId() { - byte[] attr = getAttribute(HConstants.CLUSTER_ID_ATTR); - if (attr == null) { - return HConstants.DEFAULT_CLUSTER_ID; - } - return new UUID(Bytes.toLong(attr,0), Bytes.toLong(attr, Bytes.SIZEOF_LONG)); - } } Index: src/main/java/org/apache/hadoop/hbase/client/Get.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/client/Get.java (revision 1167301) +++ src/main/java/org/apache/hadoop/hbase/client/Get.java (working copy) @@ -26,13 +26,11 @@ import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.io.Writable; import org.apache.hadoop.io.WritableFactories; -import org.apache.hadoop.io.WritableUtils; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -65,7 +63,7 @@ *

* To add a filter, execute {@link #setFilter(Filter) setFilter}. */ -public class Get extends Operation +public class Get extends OperationWithAttributes implements Writable, Row, Comparable { private static final byte GET_VERSION = (byte)2; @@ -77,7 +75,6 @@ private TimeRange tr = new TimeRange(); private Map> familyMap = new TreeMap>(Bytes.BYTES_COMPARATOR); - private Map attributes; /** Constructor for Writable. DO NOT USE */ public Get() {} @@ -307,54 +304,6 @@ } /** - * Sets arbitrary get's attribute. - * In case value = null attribute is removed from the attributes map. - * @param name attribute name - * @param value attribute value - */ - public void setAttribute(String name, byte[] value) { - if (attributes == null && value == null) { - return; - } - - if (attributes == null) { - attributes = new HashMap(); - } - - if (value == null) { - attributes.remove(name); - if (attributes.isEmpty()) { - this.attributes = null; - } - } else { - attributes.put(name, value); - } - } - - /** - * Gets get's attribute - * @param name attribute name - * @return attribute value if attribute is set, null otherwise - */ - public byte[] getAttribute(String name) { - if (attributes == null) { - return null; - } - return attributes.get(name); - } - - /** - * Gets all scan's attributes - * @return unmodifiable map of all attributes - */ - public Map getAttributesMap() { - if (attributes == null) { - return Collections.emptyMap(); - } - return Collections.unmodifiableMap(attributes); - } - - /** * Compile the table and column family (i.e. schema) information * into a String. Useful for parsing and aggregation by debugging, * logging, and administration tools. @@ -462,15 +411,7 @@ } this.familyMap.put(family, set); } - int numAttributes = in.readInt(); - if (numAttributes > 0) { - this.attributes = new HashMap(); - for(int i=0; i attr : this.attributes.entrySet()) { - WritableUtils.writeString(out, attr.getKey()); - Bytes.writeByteArray(out, attr.getValue()); - } - } + writeAttributes(out); } @SuppressWarnings("unchecked") Index: src/main/java/org/apache/hadoop/hbase/client/Attributes.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/client/Attributes.java (revision 0) +++ src/main/java/org/apache/hadoop/hbase/client/Attributes.java (revision 0) @@ -0,0 +1,46 @@ +/* + * Copyright 2011 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 java.util.Map; + +public interface Attributes { + /** + * Sets an attribute. + * In case value = null attribute is removed from the attributes map. + * @param name attribute name + * @param value attribute value + */ + public void setAttribute(String name, byte[] value); + + /** + * Gets an attribute + * @param name attribute name + * @return attribute value if attribute is set, null otherwise + */ + public byte[] getAttribute(String name); + + /** + * Gets all attributes + * @return unmodifiable map of all attributes + */ + public Map getAttributesMap(); +} Index: src/main/java/org/apache/hadoop/hbase/client/Scan.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/client/Scan.java (revision 1167301) +++ src/main/java/org/apache/hadoop/hbase/client/Scan.java (working copy) @@ -29,13 +29,11 @@ import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.io.Writable; import org.apache.hadoop.io.WritableFactories; -import org.apache.hadoop.io.WritableUtils; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -83,13 +81,12 @@ * Expert: To explicitly disable server-side block caching for this scan, * execute {@link #setCacheBlocks(boolean)}. */ -public class Scan extends Operation implements Writable { +public class Scan extends OperationWithAttributes implements Writable { private static final byte SCAN_VERSION = (byte)2; private byte [] startRow = HConstants.EMPTY_START_ROW; private byte [] stopRow = HConstants.EMPTY_END_ROW; private int maxVersions = 1; private int batch = -1; - private Map attributes; /* * -1 means no caching @@ -447,55 +444,6 @@ } /** - * Sets arbitrary scan's attribute. - * In case value = null attribute is removed from the attributes map. - * @param name attribute name - * @param value attribute value - */ - public void setAttribute(String name, byte[] value) { - if (attributes == null && value == null) { - return; - } - - if (attributes == null) { - attributes = new HashMap(); - } - - if (value == null) { - attributes.remove(name); - if (attributes.isEmpty()) { - this.attributes = null; - } - } else { - attributes.put(name, value); - } - } - - /** - * Gets scan's attribute - * @param name attribute name - * @return attribute value if attribute is set, null otherwise - */ - public byte[] getAttribute(String name) { - if (attributes == null) { - return null; - } - - return attributes.get(name); - } - - /** - * Gets all scan's attributes - * @return unmodifiable map of all attributes - */ - public Map getAttributesMap() { - if (attributes == null) { - return Collections.emptyMap(); - } - return Collections.unmodifiableMap(attributes); - } - - /** * Compile the table and column family (i.e. schema) information * into a String. Useful for parsing and aggregation by debugging, * logging, and administration tools. @@ -616,15 +564,7 @@ } if (version > 1) { - int numAttributes = in.readInt(); - if (numAttributes > 0) { - this.attributes = new HashMap(); - for(int i=0; i attr : this.attributes.entrySet()) { - WritableUtils.writeString(out, attr.getKey()); - Bytes.writeByteArray(out, attr.getValue()); - } - } + writeAttributes(out); } /**