From e1e70fdfc30ffb7c69b50e15f0c1fadaa1431deb Mon Sep 17 00:00:00 2001 From: Andrew Kyle Purtell Date: Sat, 20 Mar 2010 01:42:09 +0000 Subject: [PATCH] HBASE-2283 row level atomicity; add missing file WALEdit.java git-svn-id: https://svn.apache.org/repos/asf/hadoop/hbase/trunk@925519 13f79535-47bb-0310-9956-ffa450edef68 --- .../hbase/regionserver/wal/WALEdit.java | 147 ++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 core/src/main/java/org/apache/hadoop/hbase/regionserver/wal/WALEdit.java 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 new file mode 100644 index 00000000000..8d2facd1c8a --- /dev/null +++ b/core/src/main/java/org/apache/hadoop/hbase/regionserver/wal/WALEdit.java @@ -0,0 +1,147 @@ +/** + * 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.wal; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.hadoop.hbase.KeyValue; +import org.apache.hadoop.hbase.util.ClassSize; +import org.apache.hadoop.io.Writable; + +/** + * WALEdit: Used in HBase's transaction log (WAL) to represent + * the collection of edits (KeyValue objects) corresponding to a + * single transaction. The class implements "Writable" interface + * for serializing/deserializing a set of KeyValue items. + * + * Previously, if a transaction contains 3 edits to c1, c2, c3 for a row R, + * the HLog would have three log entries as follows: + * + * : + * : + * : + * + * This presents problems because row level atomicity of transactions + * was not guaranteed. If we crash after few of the above appends make + * it, then recovery will restore a partial transaction. + * + * In the new world, all the edits for a given transaction are written + * out as a single record, for example: + * + * : + * + * where, the WALEdit is serialized as: + * <-1, # of edits, , , ... > + * For example: + * <-1, 3, , , > + * + * The -1 marker is just a special way of being backward compatible with + * an old HLog which would have contained a single . + * + * The deserializer for WALEdit backward compatibly detects if the record + * is an old style KeyValue or the new style WALEdit. + * + */ +public class WALEdit implements Writable { + + private final int VERSION_2 = -1; + + private List kvs = new ArrayList(); + + public WALEdit() { + } + + public void add(KeyValue kv) { + this.kvs.add(kv); + } + + public boolean isEmpty() { + return kvs.isEmpty(); + } + + public int size() { + return kvs.size(); + } + + public List getKeyValues() { + 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(); + + int versionOrLength = in.readInt(); + + if (versionOrLength == VERSION_2) { + // this is new style HLog entry containing multiple KeyValues. + int numEdits = in.readInt(); + for (int idx = 0; idx < numEdits; idx++) { + KeyValue kv = new KeyValue(); + kv.readFields(in); + this.add(kv); + } + } else { + // this is an old style HLog entry. The int that we just + // read is actually the length of a single KeyValye. + KeyValue kv = new KeyValue(); + kv.readFields(versionOrLength, in); + this.add(kv); + } + + } + + public void write(DataOutput out) throws IOException { + out.writeInt(VERSION_2); + out.writeInt(kvs.size()); + for (KeyValue kv : kvs) { + kv.write(out); + } + } + + public long heapSize() { + long size = ClassSize.align(ClassSize.OBJECT + + ClassSize.REFERENCE + + ClassSize.ARRAYLIST); + for (KeyValue kv : kvs) { + size += kv.heapSize(); + } + + return size; + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + + sb.append("[#edits: " + kvs.size() + " = <"); + for (KeyValue kv : kvs) { + sb.append(kv.toString()); + sb.append("; "); + } + sb.append(">]"); + return sb.toString(); + } + +}