/*
* Copyright (C) 2010-2012 The Async HBase Authors. All rights reserved.
* This file is part of Async HBase.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the StumbleUpon nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package org.hbase.async;
import org.jboss.netty.buffer.ChannelBuffer;
/**
* Acquires an explicit row lock.
* <p>
* <strong>Row locks are no longer supported as of HBase 0.96.</strong>
* While they can still be used with earlier HBase versions,
* attempting to use them with HBase 0.95 and up will cause a
* {@link UnsupportedOperationException} to be thrown.
* <p>
* For a description of what row locks are, see {@link RowLock}.
*
* <h1>A note on passing {@code byte} arrays in argument</h1>
* None of the method that receive a {@code byte[]} in argument will copy it.
* For more info, please refer to the documentation of {@link HBaseRpc}.
* <h1>A note on passing {@code String}s in argument</h1>
* All strings are assumed to use the platform's default charset.
*/
public final class RowLockRequest extends HBaseRpc
implements HBaseRpc.HasTable, HBaseRpc.HasKey {
private static final byte[] LOCK_ROW = new byte[] {
'l', 'o', 'c', 'k', 'R', 'o', 'w'
};
/**
* Constructor.
* <strong>These byte arrays will NOT be copied.</strong>
* @param table The table containing the row to lock.
* @param key The key of the row to lock in that table.
*/
public RowLockRequest(final byte[] table, final byte[] key) {
super(table, key);
}
/**
* Constructor.
* @param table The table containing the row to lock.
* @param key The key of the row to lock in that table.
*/
public RowLockRequest(final String table, final String key) {
this(table.getBytes(), key.getBytes());
}
@Override
byte[] method(final byte unused_server_version) {
return LOCK_ROW;
}
@Override
public byte[] table() {
return table;
}
@Override
public byte[] key() {
return key;
}
// ---------------------- //
// Package private stuff. //
// ---------------------- //
private int predictSerializedSize() {
int size = 0;
size += 4; // int: Number of parameters.
size += 1; // byte: Type of the 1st parameter.
size += 3; // vint: region name length (3 bytes => max length = 32768).
size += region.name().length; // The region name.
size += 1; // byte: Type of the 2nd parameter.
size += 3; // vint: row key length (3 bytes => max length = 32768).
size += key.length; // The row key.
return size;
}
/** Serializes this request. */
ChannelBuffer serialize(final byte server_version) {
if (server_version >= RegionClient.SERVER_VERSION_095_OR_ABOVE) {
throw new UnsupportedOperationException("Row locks are not supported with"
+ " this version of HBase ("
+ server_version + ").");
}
final ChannelBuffer buf = newBuffer(server_version,
predictSerializedSize());
buf.writeInt(2); // Number of parameters.
writeHBaseByteArray(buf, region.name());
writeHBaseByteArray(buf, key);
return buf;
}
@Override
Object deserialize(final ChannelBuffer buf, int cell_size) {
throw new AssertionError("Should never be here.");
}
/**
* Package-private RPC used by {@link HBaseClient} to release row locks.
*/
static final class ReleaseRequest extends HBaseRpc {
private static final byte[] UNLOCK_ROW = new byte[] {
'u', 'n', 'l', 'o', 'c', 'k', 'R', 'o', 'w'
};
private final RowLock lock;
/**
* Constructor.
* @param lock The lock we wanna release.
* @param region The region corresponding to {@code lock.region()}.
*/
ReleaseRequest(final RowLock lock, final RegionInfo region) {
super(region.table(),
// This isn't actually the key we locked, but it doesn't matter
// as this information is useless for this RPC, we simply supply
// a key to the parent constructor to make it happy.
region.stopKey());
this.lock = lock;
}
@Override
byte[] method(final byte unused_server_version) {
return UNLOCK_ROW;
}
ChannelBuffer serialize(final byte server_version) {
// num param + type 1 + region length + region + type 2 + long
final ChannelBuffer buf = newBuffer(server_version,
+ 4 + 1 + 3 + region.name().length
+ 1 + 8);
buf.writeInt(2); // Number of parameters.
writeHBaseByteArray(buf, region.name());
writeHBaseLong(buf, lock.id());
return buf;
}
@Override
Object deserialize(final ChannelBuffer buf, final int cell_size) {
throw new AssertionError("Should never be here.");
}
}
}