diff --git a/core/src/main/java/org/apache/hadoop/hbase/regionserver/wal/WALEdit.java b/core/src/main/java/org/apache/hadoop/hbase/regionserver/wal/WALEdit.java index 8d2facd..62962b7 100644 --- a/core/src/main/java/org/apache/hadoop/hbase/regionserver/wal/WALEdit.java +++ b/core/src/main/java/org/apache/hadoop/hbase/regionserver/wal/WALEdit.java @@ -24,8 +24,11 @@ import java.io.DataOutput; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.TreeMap; import org.apache.hadoop.hbase.KeyValue; +import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.ClassSize; import org.apache.hadoop.io.Writable; @@ -67,7 +70,13 @@ public class WALEdit implements Writable { private final int VERSION_2 = -1; - private List kvs = new ArrayList(); + private final ArrayList kvs = new ArrayList(); + private Map scopes; + + private static final int OVERHEAD = ClassSize.align(ClassSize.OBJECT + + ClassSize.REFERENCE + + ClassSize.ARRAYLIST + + ClassSize.TREEMAP); public WALEdit() { } @@ -88,24 +97,45 @@ public class WALEdit implements Writable { return kvs; } - public void readFields(DataInput in) throws IOException { - - // ignore any old state in case caller is recycling an instance of this object. - kvs = new ArrayList(); + public Map getScopes() { + return scopes; + } - int versionOrLength = in.readInt(); + public void setScopes (Map scopes) { + // We currently process the map outside of WALEdit, + // TODO revisit when replication is part of core + this.scopes = scopes; + } + + public void readFields(DataInput in) throws IOException { + kvs.clear(); + int versionOrLength = in.readInt(); if (versionOrLength == VERSION_2) { // this is new style HLog entry containing multiple KeyValues. int numEdits = in.readInt(); + // Set it to the right size since we know it for (int idx = 0; idx < numEdits; idx++) { KeyValue kv = new KeyValue(); kv.readFields(in); this.add(kv); } + int numFamilies = in.readInt(); + if (numFamilies > 0) { + if (scopes == null) { + scopes = new TreeMap(Bytes.BYTES_COMPARATOR); + } else { + scopes.clear(); + } + for (int i = 0; i < numFamilies; i++) { + byte[] fam = Bytes.readByteArray(in); + int scope = in.readInt(); + scopes.put(fam, scope); + } + } } else { // this is an old style HLog entry. The int that we just - // read is actually the length of a single KeyValye. + // read is actually the length of a single KeyValue. KeyValue kv = new KeyValue(); kv.readFields(versionOrLength, in); this.add(kv); @@ -116,19 +146,34 @@ public class WALEdit implements Writable { public void write(DataOutput out) throws IOException { out.writeInt(VERSION_2); out.writeInt(kvs.size()); + // We interleave the two lists for code simplicity for (KeyValue kv : kvs) { kv.write(out); } + if (scopes == null) { + out.writeInt(0); + } else { + out.writeInt(scopes.size()); + for (byte[] key : scopes.keySet()) { + Bytes.writeByteArray(out, key); + out.writeInt(scopes.get(key)); + } + } + } public long heapSize() { - long size = ClassSize.align(ClassSize.OBJECT + - ClassSize.REFERENCE + - ClassSize.ARRAYLIST); + long size = OVERHEAD; for (KeyValue kv : kvs) { size += kv.heapSize(); } - + if (scopes != null) { + size += ClassSize.align(scopes.size() * ClassSize.MAP_ENTRY); + for (Map.Entry entry : scopes.entrySet()) { + size += ClassSize.align(ClassSize.ARRAY + entry.getKey().length); + size += Bytes.SIZEOF_INT; + } + } return size; }