|
import org.apache.accumulo.core.client.Accumulo; |
|
import org.apache.accumulo.core.client.AccumuloClient; |
|
import org.apache.accumulo.core.client.admin.CompactionConfig; |
|
import org.apache.hadoop.io.Text; |
|
import org.slf4j.Logger; |
|
import org.slf4j.LoggerFactory; |
|
|
|
import java.util.Random; |
|
import java.util.SortedSet; |
|
import java.util.TreeSet; |
|
|
|
public class ModifyTable { |
|
|
|
private static final Logger log = LoggerFactory.getLogger(ModifyTable.class); |
|
|
|
public static void main(String[] args) throws Exception { |
|
try(var client = Accumulo.newClient().from(args[0]).build()){ |
|
run(client); |
|
} |
|
} |
|
|
|
public static void run(AccumuloClient client) throws Exception { |
|
Random rand = new Random(); |
|
|
|
while(true){ |
|
var p = rand.nextDouble(); |
|
|
|
if(p < .05){ |
|
switchTableState(client); |
|
} else if (p < .3666) { |
|
splitTable(client, rand); |
|
} else if(p < .6833){ |
|
mergeTable(client, rand); |
|
} else { |
|
compactTable(client); |
|
} |
|
|
|
Thread.sleep(5000); |
|
} |
|
} |
|
|
|
private static void compactTable(AccumuloClient client) throws Exception { |
|
boolean takeOffline = false; |
|
|
|
if(!client.tableOperations().isOnline("testscan")){ |
|
client.tableOperations().online("testscan",true); |
|
takeOffline=true; |
|
} |
|
|
|
client.tableOperations().compact("testscan", new CompactionConfig().setWait(true)); |
|
|
|
log.info("Compacted table"); |
|
|
|
if(takeOffline){ |
|
client.tableOperations().offline("testscan",true); |
|
} |
|
} |
|
|
|
private static void mergeTable(AccumuloClient client, Random rand) throws Exception { |
|
|
|
|
|
var splits = new TreeSet<>(client.tableOperations().listSplits("testscan")); |
|
|
|
if(splits.isEmpty()) { |
|
log.info("Table has not splits, so not merging"); |
|
return; |
|
} |
|
|
|
boolean takeOffline = false; |
|
|
|
if(!client.tableOperations().isOnline("testscan")){ |
|
client.tableOperations().online("testscan",true); |
|
takeOffline=true; |
|
} |
|
|
|
int d = rand.nextInt(4)+1; |
|
|
|
//remove a random subset of splits |
|
splits.removeIf(split -> split.hashCode() % d == 0); |
|
|
|
if(splits.size() <= 1) { |
|
client.tableOperations().merge("testscan",null,null); |
|
log.info("Merged entire table"); |
|
} else { |
|
var begin = splits.first(); |
|
var end = splits.last(); |
|
|
|
client.tableOperations().merge("testscan",begin,end); |
|
|
|
log.info("Merged {} to {}",begin,end); |
|
} |
|
|
|
|
|
if(takeOffline){ |
|
client.tableOperations().offline("testscan",true); |
|
} |
|
} |
|
|
|
private static void splitTable(AccumuloClient client, Random rand) throws Exception { |
|
boolean takeOffline = false; |
|
if(!client.tableOperations().isOnline("testscan")){ |
|
client.tableOperations().online("testscan",true); |
|
takeOffline=true; |
|
} |
|
|
|
int numToAdd = rand.nextInt(5)+1; |
|
|
|
SortedSet<Text> splits = new TreeSet<>(); |
|
|
|
for(int i = 0; i<numToAdd;i++){ |
|
splits.add(new Text(String.format("%09d",rand.nextInt(1000000)))); |
|
} |
|
|
|
client.tableOperations().addSplits("testscan", splits); |
|
log.info("Added splits : {}",splits); |
|
|
|
if(takeOffline){ |
|
client.tableOperations().offline("testscan",true); |
|
} |
|
} |
|
|
|
private static void switchTableState(AccumuloClient client) throws Exception { |
|
if(client.tableOperations().isOnline("testscan")){ |
|
client.tableOperations().offline("testscan",true); |
|
log.info("Took table offline"); |
|
}else{ |
|
client.tableOperations().online("testscan",true); |
|
log.info("Brought table online"); |
|
} |
|
} |
|
} |
@DomGarguilo I think this test would be useful to add to accumulo testing, but I was not sure how to add it. It kinda close to random walk test, but has more strict requirements (run only two processes w/ each program in a process) that would not be supported out of the box by random walk.
Maybe it would be useful as its own top level test, I had not thought of that. I was trying to think of how to jam it in as a random walk test.
If we move forward with making more table operations like split, merge, compact support offline tables, then this would be a handy test to stress that functionality. We could probably come up with new random walk test to stress those new features also.