HBASE-4913 Per-CF compaction Via the Shell (Mubarak and Gregory)

git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1407227 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
gchanan 2012-11-08 19:22:58 +00:00
parent dbddf05a0a
commit 82ebcfd458
10 changed files with 346 additions and 91 deletions

View File

@ -1285,7 +1285,35 @@ public class HBaseAdmin implements Abortable, Closeable {
*/
public void compact(final byte [] tableNameOrRegionName)
throws IOException, InterruptedException {
compact(tableNameOrRegionName, false);
compact(tableNameOrRegionName, null, false);
}
/**
* Compact a column family within a table or region.
* Asynchronous operation.
*
* @param tableOrRegionName table or region to compact
* @param columnFamily column family within a table or region
* @throws IOException if a remote or network exception occurs
* @throws InterruptedException
*/
public void compact(String tableOrRegionName, String columnFamily)
throws IOException, InterruptedException {
compact(Bytes.toBytes(tableOrRegionName), Bytes.toBytes(columnFamily));
}
/**
* Compact a column family within a table or region.
* Asynchronous operation.
*
* @param tableNameOrRegionName table or region to compact
* @param columnFamily column family within a table or region
* @throws IOException if a remote or network exception occurs
* @throws InterruptedException
*/
public void compact(final byte [] tableNameOrRegionName, final byte[] columnFamily)
throws IOException, InterruptedException {
compact(tableNameOrRegionName, columnFamily, false);
}
/**
@ -1311,7 +1339,36 @@ public class HBaseAdmin implements Abortable, Closeable {
*/
public void majorCompact(final byte [] tableNameOrRegionName)
throws IOException, InterruptedException {
compact(tableNameOrRegionName, true);
compact(tableNameOrRegionName, null, true);
}
/**
* Major compact a column family within a table or region.
* Asynchronous operation.
*
* @param tableNameOrRegionName table or region to major compact
* @param columnFamily column family within a table or region
* @throws IOException if a remote or network exception occurs
* @throws InterruptedException
*/
public void majorCompact(final String tableNameOrRegionName,
final String columnFamily) throws IOException, InterruptedException {
majorCompact(Bytes.toBytes(tableNameOrRegionName),
Bytes.toBytes(columnFamily));
}
/**
* Major compact a column family within a table or region.
* Asynchronous operation.
*
* @param tableNameOrRegionName table or region to major compact
* @param columnFamily column family within a table or region
* @throws IOException if a remote or network exception occurs
* @throws InterruptedException
*/
public void majorCompact(final byte [] tableNameOrRegionName,
final byte[] columnFamily) throws IOException, InterruptedException {
compact(tableNameOrRegionName, columnFamily, true);
}
/**
@ -1319,11 +1376,13 @@ public class HBaseAdmin implements Abortable, Closeable {
* Asynchronous operation.
*
* @param tableNameOrRegionName table or region to compact
* @param columnFamily column family within a table or region
* @param major True if we are to do a major compaction.
* @throws IOException if a remote or network exception occurs
* @throws InterruptedException
*/
private void compact(final byte [] tableNameOrRegionName, final boolean major)
private void compact(final byte [] tableNameOrRegionName,
final byte[] columnFamily,final boolean major)
throws IOException, InterruptedException {
CatalogTracker ct = getCatalogTracker();
try {
@ -1333,7 +1392,7 @@ public class HBaseAdmin implements Abortable, Closeable {
if (regionServerPair.getSecond() == null) {
throw new NoServerForRegionException(Bytes.toStringBinary(tableNameOrRegionName));
} else {
compact(regionServerPair.getSecond(), regionServerPair.getFirst(), major);
compact(regionServerPair.getSecond(), regionServerPair.getFirst(), major, columnFamily);
}
} else {
final String tableName = tableNameString(tableNameOrRegionName, ct);
@ -1344,7 +1403,7 @@ public class HBaseAdmin implements Abortable, Closeable {
if (pair.getFirst().isOffline()) continue;
if (pair.getSecond() == null) continue;
try {
compact(pair.getSecond(), pair.getFirst(), major);
compact(pair.getSecond(), pair.getFirst(), major, columnFamily);
} catch (NotServingRegionException e) {
if (LOG.isDebugEnabled()) {
LOG.debug("Trying to" + (major ? " major" : "") + " compact " +
@ -1360,12 +1419,12 @@ public class HBaseAdmin implements Abortable, Closeable {
}
private void compact(final ServerName sn, final HRegionInfo hri,
final boolean major)
final boolean major, final byte [] family)
throws IOException {
AdminProtocol admin =
this.connection.getAdmin(sn.getHostname(), sn.getPort());
CompactRegionRequest request =
RequestConverter.buildCompactRegionRequest(hri.getRegionName(), major);
RequestConverter.buildCompactRegionRequest(hri.getRegionName(), major, family);
try {
admin.compactRegion(null, request);
} catch (ServiceException se) {

View File

@ -740,12 +740,15 @@ public final class RequestConverter {
* @return a CompactRegionRequest
*/
public static CompactRegionRequest buildCompactRegionRequest(
final byte[] regionName, final boolean major) {
final byte[] regionName, final boolean major, final byte [] family) {
CompactRegionRequest.Builder builder = CompactRegionRequest.newBuilder();
RegionSpecifier region = buildRegionSpecifier(
RegionSpecifierType.REGION_NAME, regionName);
builder.setRegion(region);
builder.setMajor(major);
if (family != null) {
builder.setFamily(ByteString.copyFrom(family));
}
return builder.build();
}

View File

@ -7687,6 +7687,10 @@ public final class AdminProtos {
// optional bool major = 2;
boolean hasMajor();
boolean getMajor();
// optional bytes family = 3;
boolean hasFamily();
com.google.protobuf.ByteString getFamily();
}
public static final class CompactRegionRequest extends
com.google.protobuf.GeneratedMessage
@ -7740,9 +7744,20 @@ public final class AdminProtos {
return major_;
}
// optional bytes family = 3;
public static final int FAMILY_FIELD_NUMBER = 3;
private com.google.protobuf.ByteString family_;
public boolean hasFamily() {
return ((bitField0_ & 0x00000004) == 0x00000004);
}
public com.google.protobuf.ByteString getFamily() {
return family_;
}
private void initFields() {
region_ = org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionSpecifier.getDefaultInstance();
major_ = false;
family_ = com.google.protobuf.ByteString.EMPTY;
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
@ -7770,6 +7785,9 @@ public final class AdminProtos {
if (((bitField0_ & 0x00000002) == 0x00000002)) {
output.writeBool(2, major_);
}
if (((bitField0_ & 0x00000004) == 0x00000004)) {
output.writeBytes(3, family_);
}
getUnknownFields().writeTo(output);
}
@ -7787,6 +7805,10 @@ public final class AdminProtos {
size += com.google.protobuf.CodedOutputStream
.computeBoolSize(2, major_);
}
if (((bitField0_ & 0x00000004) == 0x00000004)) {
size += com.google.protobuf.CodedOutputStream
.computeBytesSize(3, family_);
}
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
@ -7820,6 +7842,11 @@ public final class AdminProtos {
result = result && (getMajor()
== other.getMajor());
}
result = result && (hasFamily() == other.hasFamily());
if (hasFamily()) {
result = result && getFamily()
.equals(other.getFamily());
}
result = result &&
getUnknownFields().equals(other.getUnknownFields());
return result;
@ -7837,6 +7864,10 @@ public final class AdminProtos {
hash = (37 * hash) + MAJOR_FIELD_NUMBER;
hash = (53 * hash) + hashBoolean(getMajor());
}
if (hasFamily()) {
hash = (37 * hash) + FAMILY_FIELD_NUMBER;
hash = (53 * hash) + getFamily().hashCode();
}
hash = (29 * hash) + getUnknownFields().hashCode();
return hash;
}
@ -7962,6 +7993,8 @@ public final class AdminProtos {
bitField0_ = (bitField0_ & ~0x00000001);
major_ = false;
bitField0_ = (bitField0_ & ~0x00000002);
family_ = com.google.protobuf.ByteString.EMPTY;
bitField0_ = (bitField0_ & ~0x00000004);
return this;
}
@ -8012,6 +8045,10 @@ public final class AdminProtos {
to_bitField0_ |= 0x00000002;
}
result.major_ = major_;
if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
to_bitField0_ |= 0x00000004;
}
result.family_ = family_;
result.bitField0_ = to_bitField0_;
onBuilt();
return result;
@ -8034,6 +8071,9 @@ public final class AdminProtos {
if (other.hasMajor()) {
setMajor(other.getMajor());
}
if (other.hasFamily()) {
setFamily(other.getFamily());
}
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
@ -8087,6 +8127,11 @@ public final class AdminProtos {
major_ = input.readBool();
break;
}
case 26: {
bitField0_ |= 0x00000004;
family_ = input.readBytes();
break;
}
}
}
}
@ -8204,6 +8249,30 @@ public final class AdminProtos {
return this;
}
// optional bytes family = 3;
private com.google.protobuf.ByteString family_ = com.google.protobuf.ByteString.EMPTY;
public boolean hasFamily() {
return ((bitField0_ & 0x00000004) == 0x00000004);
}
public com.google.protobuf.ByteString getFamily() {
return family_;
}
public Builder setFamily(com.google.protobuf.ByteString value) {
if (value == null) {
throw new NullPointerException();
}
bitField0_ |= 0x00000004;
family_ = value;
onChanged();
return this;
}
public Builder clearFamily() {
bitField0_ = (bitField0_ & ~0x00000004);
family_ = getDefaultInstance().getFamily();
onChanged();
return this;
}
// @@protoc_insertion_point(builder_scope:CompactRegionRequest)
}
@ -16383,51 +16452,52 @@ public final class AdminProtos {
"lastFlushTime\030\001 \002(\004\022\017\n\007flushed\030\002 \001(\010\"J\n\022" +
"SplitRegionRequest\022 \n\006region\030\001 \002(\0132\020.Reg",
"ionSpecifier\022\022\n\nsplitPoint\030\002 \001(\014\"\025\n\023Spli" +
"tRegionResponse\"G\n\024CompactRegionRequest\022" +
"tRegionResponse\"W\n\024CompactRegionRequest\022" +
" \n\006region\030\001 \002(\0132\020.RegionSpecifier\022\r\n\005maj" +
"or\030\002 \001(\010\"\027\n\025CompactRegionResponse\"1\n\004UUI" +
"D\022\024\n\014leastSigBits\030\001 \002(\004\022\023\n\013mostSigBits\030\002" +
" \002(\004\"\270\003\n\010WALEntry\022\035\n\003key\030\001 \002(\0132\020.WALEntr" +
"y.WALKey\022\037\n\004edit\030\002 \002(\0132\021.WALEntry.WALEdi" +
"t\032~\n\006WALKey\022\031\n\021encodedRegionName\030\001 \002(\014\022\021" +
"\n\ttableName\030\002 \002(\014\022\031\n\021logSequenceNumber\030\003" +
" \002(\004\022\021\n\twriteTime\030\004 \002(\004\022\030\n\tclusterId\030\005 \001",
"(\0132\005.UUID\032\353\001\n\007WALEdit\022\025\n\rkeyValueBytes\030\001" +
" \003(\014\0222\n\013familyScope\030\002 \003(\0132\035.WALEntry.WAL" +
"Edit.FamilyScope\032M\n\013FamilyScope\022\016\n\006famil" +
"y\030\001 \002(\014\022.\n\tscopeType\030\002 \002(\0162\033.WALEntry.WA" +
"LEdit.ScopeType\"F\n\tScopeType\022\033\n\027REPLICAT" +
"ION_SCOPE_LOCAL\020\000\022\034\n\030REPLICATION_SCOPE_G" +
"LOBAL\020\001\"4\n\030ReplicateWALEntryRequest\022\030\n\005e" +
"ntry\030\001 \003(\0132\t.WALEntry\"\033\n\031ReplicateWALEnt" +
"ryResponse\"\026\n\024RollWALWriterRequest\".\n\025Ro" +
"llWALWriterResponse\022\025\n\rregionToFlush\030\001 \003",
"(\014\"#\n\021StopServerRequest\022\016\n\006reason\030\001 \002(\t\"" +
"\024\n\022StopServerResponse\"\026\n\024GetServerInfoRe" +
"quest\"@\n\nServerInfo\022\037\n\nserverName\030\001 \002(\0132" +
"\013.ServerName\022\021\n\twebuiPort\030\002 \001(\r\"8\n\025GetSe" +
"rverInfoResponse\022\037\n\nserverInfo\030\001 \002(\0132\013.S" +
"erverInfo2\371\005\n\014AdminService\022>\n\rgetRegionI" +
"nfo\022\025.GetRegionInfoRequest\032\026.GetRegionIn" +
"foResponse\022;\n\014getStoreFile\022\024.GetStoreFil" +
"eRequest\032\025.GetStoreFileResponse\022D\n\017getOn" +
"lineRegion\022\027.GetOnlineRegionRequest\032\030.Ge",
"tOnlineRegionResponse\0225\n\nopenRegion\022\022.Op" +
"enRegionRequest\032\023.OpenRegionResponse\0228\n\013" +
"closeRegion\022\023.CloseRegionRequest\032\024.Close" +
"RegionResponse\0228\n\013flushRegion\022\023.FlushReg" +
"ionRequest\032\024.FlushRegionResponse\0228\n\013spli" +
"tRegion\022\023.SplitRegionRequest\032\024.SplitRegi" +
"onResponse\022>\n\rcompactRegion\022\025.CompactReg" +
"ionRequest\032\026.CompactRegionResponse\022J\n\021re" +
"plicateWALEntry\022\031.ReplicateWALEntryReque" +
"st\032\032.ReplicateWALEntryResponse\022>\n\rrollWA",
"LWriter\022\025.RollWALWriterRequest\032\026.RollWAL" +
"WriterResponse\022>\n\rgetServerInfo\022\025.GetSer" +
"verInfoRequest\032\026.GetServerInfoResponse\0225" +
"\n\nstopServer\022\022.StopServerRequest\032\023.StopS" +
"erverResponseBA\n*org.apache.hadoop.hbase" +
".protobuf.generatedB\013AdminProtosH\001\210\001\001\240\001\001"
"or\030\002 \001(\010\022\016\n\006family\030\003 \001(\014\"\027\n\025CompactRegio" +
"nResponse\"1\n\004UUID\022\024\n\014leastSigBits\030\001 \002(\004\022" +
"\023\n\013mostSigBits\030\002 \002(\004\"\270\003\n\010WALEntry\022\035\n\003key" +
"\030\001 \002(\0132\020.WALEntry.WALKey\022\037\n\004edit\030\002 \002(\0132\021" +
".WALEntry.WALEdit\032~\n\006WALKey\022\031\n\021encodedRe" +
"gionName\030\001 \002(\014\022\021\n\ttableName\030\002 \002(\014\022\031\n\021log" +
"SequenceNumber\030\003 \002(\004\022\021\n\twriteTime\030\004 \002(\004\022",
"\030\n\tclusterId\030\005 \001(\0132\005.UUID\032\353\001\n\007WALEdit\022\025\n" +
"\rkeyValueBytes\030\001 \003(\014\0222\n\013familyScope\030\002 \003(" +
"\0132\035.WALEntry.WALEdit.FamilyScope\032M\n\013Fami" +
"lyScope\022\016\n\006family\030\001 \002(\014\022.\n\tscopeType\030\002 \002" +
"(\0162\033.WALEntry.WALEdit.ScopeType\"F\n\tScope" +
"Type\022\033\n\027REPLICATION_SCOPE_LOCAL\020\000\022\034\n\030REP" +
"LICATION_SCOPE_GLOBAL\020\001\"4\n\030ReplicateWALE" +
"ntryRequest\022\030\n\005entry\030\001 \003(\0132\t.WALEntry\"\033\n" +
"\031ReplicateWALEntryResponse\"\026\n\024RollWALWri" +
"terRequest\".\n\025RollWALWriterResponse\022\025\n\rr",
"egionToFlush\030\001 \003(\014\"#\n\021StopServerRequest\022" +
"\016\n\006reason\030\001 \002(\t\"\024\n\022StopServerResponse\"\026\n" +
"\024GetServerInfoRequest\"@\n\nServerInfo\022\037\n\ns" +
"erverName\030\001 \002(\0132\013.ServerName\022\021\n\twebuiPor" +
"t\030\002 \001(\r\"8\n\025GetServerInfoResponse\022\037\n\nserv" +
"erInfo\030\001 \002(\0132\013.ServerInfo2\371\005\n\014AdminServi" +
"ce\022>\n\rgetRegionInfo\022\025.GetRegionInfoReque" +
"st\032\026.GetRegionInfoResponse\022;\n\014getStoreFi" +
"le\022\024.GetStoreFileRequest\032\025.GetStoreFileR" +
"esponse\022D\n\017getOnlineRegion\022\027.GetOnlineRe",
"gionRequest\032\030.GetOnlineRegionResponse\0225\n" +
"\nopenRegion\022\022.OpenRegionRequest\032\023.OpenRe" +
"gionResponse\0228\n\013closeRegion\022\023.CloseRegio" +
"nRequest\032\024.CloseRegionResponse\0228\n\013flushR" +
"egion\022\023.FlushRegionRequest\032\024.FlushRegion" +
"Response\0228\n\013splitRegion\022\023.SplitRegionReq" +
"uest\032\024.SplitRegionResponse\022>\n\rcompactReg" +
"ion\022\025.CompactRegionRequest\032\026.CompactRegi" +
"onResponse\022J\n\021replicateWALEntry\022\031.Replic" +
"ateWALEntryRequest\032\032.ReplicateWALEntryRe",
"sponse\022>\n\rrollWALWriter\022\025.RollWALWriterR" +
"equest\032\026.RollWALWriterResponse\022>\n\rgetSer" +
"verInfo\022\025.GetServerInfoRequest\032\026.GetServ" +
"erInfoResponse\0225\n\nstopServer\022\022.StopServe" +
"rRequest\032\023.StopServerResponseBA\n*org.apa" +
"che.hadoop.hbase.protobuf.generatedB\013Adm" +
"inProtosH\001\210\001\001\240\001\001"
};
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
@ -16559,7 +16629,7 @@ public final class AdminProtos {
internal_static_CompactRegionRequest_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_CompactRegionRequest_descriptor,
new java.lang.String[] { "Region", "Major", },
new java.lang.String[] { "Region", "Major", "Family", },
org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CompactRegionRequest.class,
org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CompactRegionRequest.Builder.class);
internal_static_CompactRegionResponse_descriptor =

View File

@ -3561,17 +3561,35 @@ public class HRegionServer implements ClientProtocol,
HRegion region = getRegion(request.getRegion());
LOG.info("Compacting " + region.getRegionNameAsString());
boolean major = false;
byte [] family = null;
Store store = null;
if (request.hasFamily()) {
family = request.getFamily().toByteArray();
store = region.getStore(family);
if (store == null) {
throw new ServiceException(new IOException("column family " + Bytes.toString(family) +
" does not exist in region " + new String(region.getRegionNameAsString())));
}
}
if (request.hasMajor()) {
major = request.getMajor();
}
if (major) {
region.triggerMajorCompaction();
if (family != null) {
store.triggerMajorCompaction();
} else {
region.triggerMajorCompaction();
}
}
LOG.trace("User-triggered compaction requested for region " +
region.getRegionNameAsString());
compactSplitThread.requestCompaction(region,
"User-triggered " + (major ? "major " : "") + "compaction",
String log = "User-triggered " + (major ? "major " : "") + "compaction";
if(family != null) {
compactSplitThread.requestCompaction(region, store, log,
Store.PRIORITY_USER);
} else {
compactSplitThread.requestCompaction(region, log,
Store.PRIORITY_USER);
}
return CompactRegionResponse.newBuilder().build();
} catch (IOException ie) {
throw new ServiceException(ie);

View File

@ -135,6 +135,7 @@ message SplitRegionResponse {
message CompactRegionRequest {
required RegionSpecifier region = 1;
optional bool major = 2;
optional bytes family = 3;
}
message CompactRegionResponse {

View File

@ -50,15 +50,27 @@ module Hbase
end
#----------------------------------------------------------------------------------------------
# Requests a table or region compaction
def compact(table_or_region_name)
@admin.compact(table_or_region_name)
# Requests a table or region or column family compaction
def compact(table_or_region_name, *args)
if args.empty?
@admin.compact(table_or_region_name)
elsif args.length == 1
# We are compacting a column family within a region.
column_family = args.first
@admin.compact(table_or_region_name, column_family)
end
end
#----------------------------------------------------------------------------------------------
# Requests a table or region major compaction
def major_compact(table_or_region_name)
@admin.majorCompact(table_or_region_name)
# Requests a table or region or column family major compaction
def major_compact(table_or_region_name, *args)
if args.empty?
@admin.majorCompact(table_or_region_name)
elsif args.length == 1
# We are major compacting a column family within a region or table.
column_family = args.first
@admin.majorCompact(table_or_region_name, column_family)
end
end
#----------------------------------------------------------------------------------------------

View File

@ -22,14 +22,24 @@ module Shell
class Compact < Command
def help
return <<-EOF
Compact all regions in passed table or pass a region row
to compact an individual region
EOF
Compact all regions in passed table or pass a region row
to compact an individual region. You can also compact a single column
family within a region.
Examples:
Compact all regions in a table:
hbase> compact 't1'
Compact an entire region:
hbase> compact 'r1'
Compact only a column family within a region:
hbase> compact 'r1', 'c1'
Compact a column family within a table:
hbase> compact 't1', 'c1'
EOF
end
def command(table_or_region_name)
def command(table_or_region_name, *args)
format_simple_command do
admin.compact(table_or_region_name)
admin.compact(table_or_region_name, *args)
end
end
end

View File

@ -22,14 +22,25 @@ module Shell
class MajorCompact < Command
def help
return <<-EOF
Run major compaction on passed table or pass a region row
to major compact an individual region
EOF
Run major compaction on passed table or pass a region row
to major compact an individual region. To compact a single
column family within a region specify the region name
followed by the column family name.
Examples:
Compact all regions in a table:
hbase> major_compact 't1'
Compact an entire region:
hbase> major_compact 'r1'
Compact a single column family within a region:
hbase> major_compact 'r1', 'c1'
Compact a single column family within a table:
hbase> major_compact 't1', 'c1'
EOF
end
def command(table_or_region_name)
def command(table_or_region_name, *args)
format_simple_command do
admin.major_compact(table_or_region_name)
admin.major_compact(table_or_region_name, *args)
end
end
end

View File

@ -60,12 +60,52 @@ public class TestCompactionState {
@Test(timeout=60000)
public void testMajorCompaction() throws IOException, InterruptedException {
compaction("testMajorCompaction", 8, CompactionState.MAJOR);
compaction("testMajorCompaction", 8, CompactionState.MAJOR, false);
}
@Test(timeout=60000)
public void testMinorCompaction() throws IOException, InterruptedException {
compaction("testMinorCompaction", 15, CompactionState.MINOR);
compaction("testMinorCompaction", 15, CompactionState.MINOR, false);
}
@Test(timeout=60000)
public void testMajorCompactionOnFamily() throws IOException, InterruptedException {
compaction("testMajorCompactionOnFamily", 8, CompactionState.MAJOR, true);
}
@Test(timeout=60000)
public void testMinorCompactionOnFamily() throws IOException, InterruptedException {
compaction("testMinorCompactionOnFamily", 15, CompactionState.MINOR, true);
}
@Test
public void testInvalidColumnFamily() throws IOException, InterruptedException {
byte [] table = Bytes.toBytes("testInvalidColumnFamily");
byte [] family = Bytes.toBytes("family");
byte [] fakecf = Bytes.toBytes("fakecf");
boolean caughtMinorCompact = false;
boolean caughtMajorCompact = false;
HTable ht = null;
try {
ht = TEST_UTIL.createTable(table, family);
HBaseAdmin admin = new HBaseAdmin(TEST_UTIL.getConfiguration());
try {
admin.compact(table, fakecf);
} catch (IOException ioe) {
caughtMinorCompact = true;
}
try {
admin.majorCompact(table, fakecf);
} catch (IOException ioe) {
caughtMajorCompact = true;
}
} finally {
if (ht != null) {
TEST_UTIL.deleteTable(table);
}
assertTrue(caughtMinorCompact);
assertTrue(caughtMajorCompact);
}
}
/**
@ -75,27 +115,40 @@ public class TestCompactionState {
* @param tableName
* @param flushes
* @param expectedState
* @param singleFamily otherwise, run compaction on all cfs
* @throws IOException
* @throws InterruptedException
*/
private void compaction(final String tableName, final int flushes,
final CompactionState expectedState) throws IOException, InterruptedException {
final CompactionState expectedState, boolean singleFamily)
throws IOException, InterruptedException {
// Create a table with regions
byte [] table = Bytes.toBytes(tableName);
byte [] family = Bytes.toBytes("family");
byte [][] families =
{family, Bytes.add(family, Bytes.toBytes("2")), Bytes.add(family, Bytes.toBytes("3"))};
HTable ht = null;
try {
ht = TEST_UTIL.createTable(table, family);
loadData(ht, family, 3000, flushes);
ht = TEST_UTIL.createTable(table, families);
loadData(ht, families, 3000, flushes);
HRegionServer rs = TEST_UTIL.getMiniHBaseCluster().getRegionServer(0);
List<HRegion> regions = rs.getOnlineRegions(table);
int countBefore = countStoreFiles(regions, family);
int countBefore = countStoreFilesInFamilies(regions, families);
int countBeforeSingleFamily = countStoreFilesInFamily(regions, family);
assertTrue(countBefore > 0); // there should be some data files
HBaseAdmin admin = new HBaseAdmin(TEST_UTIL.getConfiguration());
if (expectedState == CompactionState.MINOR) {
admin.compact(tableName);
if (singleFamily) {
admin.compact(table, family);
} else {
admin.compact(table);
}
} else {
admin.majorCompact(table);
if (singleFamily) {
admin.majorCompact(table, family);
} else {
admin.majorCompact(table);
}
}
long curt = System.currentTimeMillis();
long waitTime = 5000;
@ -126,10 +179,22 @@ public class TestCompactionState {
// Now, compaction should be done.
assertEquals(CompactionState.NONE, state);
}
int countAfter = countStoreFiles(regions, family);
int countAfter = countStoreFilesInFamilies(regions, families);
int countAfterSingleFamily = countStoreFilesInFamily(regions, family);
assertTrue(countAfter < countBefore);
if (expectedState == CompactionState.MAJOR) assertTrue(1 == countAfter);
else assertTrue(1 < countAfter);
if (!singleFamily) {
if (expectedState == CompactionState.MAJOR) assertTrue(families.length == countAfter);
else assertTrue(families.length < countAfter);
} else {
int singleFamDiff = countBeforeSingleFamily - countAfterSingleFamily;
// assert only change was to single column family
assertTrue(singleFamDiff == (countBefore - countAfter));
if (expectedState == CompactionState.MAJOR) {
assertTrue(1 == countAfterSingleFamily);
} else {
assertTrue(1 < countAfterSingleFamily);
}
}
} finally {
if (ht != null) {
TEST_UTIL.deleteTable(table);
@ -137,16 +202,20 @@ public class TestCompactionState {
}
}
private static int countStoreFiles(
private static int countStoreFilesInFamily(
List<HRegion> regions, final byte[] family) {
return countStoreFilesInFamilies(regions, new byte[][]{family});
}
private static int countStoreFilesInFamilies(List<HRegion> regions, final byte[][] families) {
int count = 0;
for (HRegion region: regions) {
count += region.getStoreFileList(new byte[][]{family}).size();
count += region.getStoreFileList(families).size();
}
return count;
}
private static void loadData(final HTable ht, final byte[] family,
private static void loadData(final HTable ht, final byte[][] families,
final int rows, final int flushes) throws IOException {
List<Put> puts = new ArrayList<Put>(rows);
byte[] qualifier = Bytes.toBytes("val");
@ -154,7 +223,9 @@ public class TestCompactionState {
for (int k = 0; k < rows; k++) {
byte[] row = Bytes.toBytes(random.nextLong());
Put p = new Put(row);
p.add(family, qualifier, row);
for (int j = 0; j < families.length; ++j) {
p.add(families[ j ], qualifier, row);
}
puts.add(p);
}
ht.put(puts);

View File

@ -169,7 +169,7 @@ public class TestHRegionServerBulkLoad {
location.getHostname(), location.getPort());
CompactRegionRequest request =
RequestConverter.buildCompactRegionRequest(
location.getRegionInfo().getRegionName(), true);
location.getRegionInfo().getRegionName(), true, null);
server.compactRegion(null, request);
numCompactions.incrementAndGet();
return null;