HBASE-4347 Remove duplicated code from Put, Delete, Get, Scan, MultiPut

git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1167569 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Michael Stack 2011-09-10 17:57:19 +00:00
parent 743d846b9e
commit 699e15b7a1
8 changed files with 373 additions and 627 deletions

View File

@ -472,6 +472,8 @@ Release 0.91.0 - Unreleased
HBASE-4342 Update Thrift to 0.7.0 (Moaz Reyad)
HBASE-4260 Expose a command to manually trigger an HLog roll
(ramkrishna.s.vasudevan)
HBASE-4347 Remove duplicated code from Put, Delete, Get, Scan, MultiPut
(Lars Hofhansl)
TASKS
HBASE-3559 Move report of split to master OFF the heartbeat channel

View File

@ -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, <tt>null</tt> otherwise
*/
public byte[] getAttribute(String name);
/**
* Gets all attributes
* @return unmodifiable map of all attributes
*/
public Map<String, byte[]> getAttributesMap();
}

View File

@ -24,20 +24,13 @@ import org.apache.hadoop.hbase.HConstants;
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 @@ import java.util.UUID;
* 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<Row> {
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<byte [], List<KeyValue>> familyMap =
new TreeMap<byte [], List<KeyValue>>(Bytes.BYTES_COMPARATOR);
// a opaque blob that can be passed into a Delete.
private Map<String, byte[]> attributes;
/** Constructor for Writable. DO NOT USE */
public Delete() {
this((byte [])null);
@ -136,18 +118,6 @@ public class Delete extends Operation
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.
* <p>
@ -245,47 +215,6 @@ public class Delete extends Operation
return this;
}
/**
* Method for retrieving the delete's familyMap
* @return familyMap
*/
public Map<byte [], List<KeyValue>> 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.
*
@ -295,115 +224,12 @@ public class Delete extends Operation
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<String, byte[]>();
}
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, <tt>null</tt> 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<String, byte[]> 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<String, Object> getFingerprint() {
Map<String, Object> map = new HashMap<String, Object>();
List<String> families = new ArrayList<String>();
// ideally, we would also include table information, but that information
// is not stored in each Operation instance.
map.put("families", families);
for (Map.Entry<byte [], List<KeyValue>> 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<String, Object> toMap(int maxCols) {
// we start with the fingerprint map and build on top of it.
Map<String, Object> map = getFingerprint();
// replace the fingerprint's simple list of families with a
// map from column families to lists of qualifiers and kv details
Map<String, List<Map<String, Object>>> columns =
new HashMap<String, List<Map<String, Object>>>();
map.put("families", columns);
map.put("row", Bytes.toStringBinary(this.row));
Map<String, Object> 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<byte [], List<KeyValue>> entry : this.familyMap.entrySet()) {
// map from this family to details for each kv affected within the family
List<Map<String, Object>> qualifierDetails =
new ArrayList<Map<String, Object>>();
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<String, Object> 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 @@ public class Delete extends Operation
this.familyMap.put(family, list);
}
if (version > 1) {
int numAttributes = in.readInt();
if (numAttributes > 0) {
this.attributes = new HashMap<String, byte[]>();
for(int i=0; i<numAttributes; i++) {
String name = WritableUtils.readString(in);
byte[] value = Bytes.readByteArray(in);
this.attributes.put(name, value);
}
}
readAttributes(in);
}
}
@ -460,15 +278,7 @@ public class Delete extends Operation
kv.write(out);
}
}
if (this.attributes == null) {
out.writeInt(0);
} else {
out.writeInt(this.attributes.size());
for (Map.Entry<String, byte[]> attr : this.attributes.entrySet()) {
WritableUtils.writeString(out, attr.getKey());
Bytes.writeByteArray(out, attr.getValue());
}
}
writeAttributes(out);
}
/**
@ -498,42 +308,4 @@ public class Delete extends Operation
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));
}
}

View File

@ -26,13 +26,11 @@ import org.apache.hadoop.hbase.io.TimeRange;
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 @@ import java.util.TreeSet;
* <p>
* To add a filter, execute {@link #setFilter(Filter) setFilter}.
*/
public class Get extends Operation
public class Get extends OperationWithAttributes
implements Writable, Row, Comparable<Row> {
private static final byte GET_VERSION = (byte)2;
@ -77,7 +75,6 @@ public class Get extends Operation
private TimeRange tr = new TimeRange();
private Map<byte [], NavigableSet<byte []>> familyMap =
new TreeMap<byte [], NavigableSet<byte []>>(Bytes.BYTES_COMPARATOR);
private Map<String, byte[]> attributes;
/** Constructor for Writable. DO NOT USE */
public Get() {}
@ -306,54 +303,6 @@ public class Get extends Operation
return this.familyMap;
}
/**
* 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<String, byte[]>();
}
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, <tt>null</tt> 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<String, byte[]> 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,
@ -462,15 +411,7 @@ public class Get extends Operation
}
this.familyMap.put(family, set);
}
int numAttributes = in.readInt();
if (numAttributes > 0) {
this.attributes = new HashMap<String, byte[]>();
for(int i=0; i<numAttributes; i++) {
String name = WritableUtils.readString(in);
byte[] value = Bytes.readByteArray(in);
this.attributes.put(name, value);
}
}
readAttributes(in);
}
public void write(final DataOutput out)
@ -503,15 +444,7 @@ public class Get extends Operation
}
}
}
if (this.attributes == null) {
out.writeInt(0);
} else {
out.writeInt(this.attributes.size());
for (Map.Entry<String, byte[]> attr : this.attributes.entrySet()) {
WritableUtils.writeString(out, attr.getKey());
Bytes.writeByteArray(out, attr.getValue());
}
}
writeAttributes(out);
}
@SuppressWarnings("unchecked")

View File

@ -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<byte [], List<KeyValue>> familyMap =
new TreeMap<byte [], List<KeyValue>>(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<String, Object> getFingerprint() {
Map<String, Object> map = new HashMap<String, Object>();
List<String> families = new ArrayList<String>();
// ideally, we would also include table information, but that information
// is not stored in each Operation instance.
map.put("families", families);
for (Map.Entry<byte [], List<KeyValue>> 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<String, Object> toMap(int maxCols) {
// we start with the fingerprint map and build on top of it.
Map<String, Object> map = getFingerprint();
// replace the fingerprint's simple list of families with a
// map from column families to lists of qualifiers and kv details
Map<String, List<Map<String, Object>>> columns =
new HashMap<String, List<Map<String, Object>>>();
map.put("families", columns);
map.put("row", Bytes.toStringBinary(this.row));
int colCount = 0;
// iterate through all column families affected
for (Map.Entry<byte [], List<KeyValue>> entry : this.familyMap.entrySet()) {
// map from this family to details for each kv affected within the family
List<Map<String, Object>> qualifierDetails =
new ArrayList<Map<String, Object>>();
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<String, Object> 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<byte [], List<KeyValue>> 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));
}
}

View File

@ -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<String, byte[]> attributes;
public void setAttribute(String name, byte[] value) {
if (attributes == null && value == null) {
return;
}
if (attributes == null) {
attributes = new HashMap<String, byte[]>();
}
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<String, byte[]> 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<String, byte[]> 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<String, byte[]> 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<String, byte[]>();
for(int i=0; i<numAttributes; i++) {
String name = WritableUtils.readString(in);
byte[] value = Bytes.readByteArray(in);
this.attributes.put(name, value);
}
}
}
}

View File

@ -26,22 +26,15 @@ import org.apache.hadoop.hbase.io.HeapSize;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.ClassSize;
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.Arrays;
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 Put operations for a single row.
@ -50,21 +43,10 @@ import java.util.UUID;
* 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<Row> {
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<byte [], List<KeyValue>> familyMap =
new TreeMap<byte [], List<KeyValue>>(Bytes.BYTES_COMPARATOR);
// a opaque blob that can be passed into a Put.
private Map<String, byte[]> attributes;
private static final long OVERHEAD = ClassSize.align(
ClassSize.OBJECT + 2 * ClassSize.REFERENCE +
2 * Bytes.SIZEOF_LONG + Bytes.SIZEOF_BOOLEAN +
@ -111,7 +93,7 @@ public class Put extends Operation
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 @@ public class Put extends Operation
* @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<byte [], List<KeyValue>>(Bytes.BYTES_COMPARATOR);
for(Map.Entry<byte [], List<KeyValue>> entry :
@ -140,7 +122,7 @@ public class Put extends Operation
* @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 @@ public class Put extends Operation
* 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 @@ public class Put extends Operation
* 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);
}
/**
@ -336,53 +318,6 @@ public class Put extends Operation
return list;
}
/**
* Method for retrieving the put's familyMap
* @return familyMap
*/
public Map<byte [], List<KeyValue>> 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
*/
@ -401,138 +336,6 @@ public class Put extends Operation
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<String, byte[]>();
}
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, <tt>null</tt> 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<String, byte[]> 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<String, Object> getFingerprint() {
Map<String, Object> map = new HashMap<String, Object>();
List<String> families = new ArrayList<String>();
// ideally, we would also include table information, but that information
// is not stored in each Operation instance.
map.put("families", families);
for (Map.Entry<byte [], List<KeyValue>> 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<String, Object> toMap(int maxCols) {
// we start with the fingerprint map and build on top of it.
Map<String, Object> map = getFingerprint();
// replace the fingerprint's simple list of families with a
// map from column families to lists of qualifiers and kv details
Map<String, List<Map<String, Object>>> columns =
new HashMap<String, List<Map<String, Object>>>();
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<byte [], List<KeyValue>> entry : this.familyMap.entrySet()) {
// map from this family to details for each kv affected within the family
List<Map<String, Object>> qualifierDetails =
new ArrayList<Map<String, Object>>();
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<String, Object> 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 @@ public class Put extends Operation
heapsize += kv.heapSize();
}
}
if (attributes != null) {
heapsize += ClassSize.align(this.attributes.size() * ClassSize.MAP_ENTRY);
for(Map.Entry<String, byte[]> 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 @@ public class Put extends Operation
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 @@ public class Put extends Operation
this.familyMap.put(family, keys);
}
if (version > 1) {
int numAttributes = in.readInt();
if (numAttributes > 0) {
this.attributes = new HashMap<String, byte[]>();
for(int i=0; i<numAttributes; i++) {
String name = WritableUtils.readString(in);
byte[] value = Bytes.readByteArray(in);
this.attributes.put(name, value);
}
}
readAttributes(in);
}
}
@ -614,7 +404,7 @@ public class Put extends Operation
throws IOException {
out.writeByte(PUT_VERSION);
Bytes.writeByteArray(out, this.row);
out.writeLong(this.timestamp);
out.writeLong(this.ts);
out.writeLong(this.lockId);
out.writeBoolean(this.writeToWAL);
out.writeInt(familyMap.size());
@ -632,15 +422,7 @@ public class Put extends Operation
out.write(kv.getBuffer(), kv.getOffset(), kv.getLength());
}
}
if (this.attributes == null) {
out.writeInt(0);
} else {
out.writeInt(this.attributes.size());
for (Map.Entry<String, byte[]> attr : this.attributes.entrySet()) {
WritableUtils.writeString(out, attr.getKey());
Bytes.writeByteArray(out, attr.getValue());
}
}
writeAttributes(out);
}
/**
@ -657,26 +439,4 @@ public class Put extends Operation
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));
}
}

View File

@ -29,13 +29,11 @@ import org.apache.hadoop.hbase.io.TimeRange;
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 @@ import java.util.TreeSet;
* 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<String, byte[]> attributes;
/*
* -1 means no caching
@ -446,55 +443,6 @@ public class Scan extends Operation implements Writable {
return cacheBlocks;
}
/**
* 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<String, byte[]>();
}
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, <tt>null</tt> 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<String, byte[]> 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,
@ -616,15 +564,7 @@ public class Scan extends Operation implements Writable {
}
if (version > 1) {
int numAttributes = in.readInt();
if (numAttributes > 0) {
this.attributes = new HashMap<String, byte[]>();
for(int i=0; i<numAttributes; i++) {
String name = WritableUtils.readString(in);
byte[] value = Bytes.readByteArray(in);
this.attributes.put(name, value);
}
}
readAttributes(in);
}
}
@ -658,16 +598,7 @@ public class Scan extends Operation implements Writable {
out.writeInt(0);
}
}
if (this.attributes == null) {
out.writeInt(0);
} else {
out.writeInt(this.attributes.size());
for (Map.Entry<String, byte[]> attr : this.attributes.entrySet()) {
WritableUtils.writeString(out, attr.getKey());
Bytes.writeByteArray(out, attr.getValue());
}
}
writeAttributes(out);
}
/**