use of org.apache.accumulo.core.tabletserver.thrift.TExternalCompactionJob in project accumulo by apache.
the class CompactionCoordinatorTest method testCoordinatorRestartOneRunningCompaction.
@Test
public void testCoordinatorRestartOneRunningCompaction() throws Exception {
PowerMock.resetAll();
PowerMock.suppress(PowerMock.constructor(AbstractServer.class));
PowerMock.suppress(PowerMock.methods(ThriftUtil.class, "returnClient"));
PowerMock.suppress(PowerMock.methods(DeadCompactionDetector.class, "detectDeadCompactions", "detectDanglingFinalStateMarkers"));
AccumuloConfiguration conf = PowerMock.createNiceMock(AccumuloConfiguration.class);
ServerContext context = PowerMock.createNiceMock(ServerContext.class);
TCredentials creds = PowerMock.createNiceMock(TCredentials.class);
EasyMock.expect(context.rpcCreds()).andReturn(creds);
CompactionFinalizer finalizer = PowerMock.createNiceMock(CompactionFinalizer.class);
LiveTServerSet tservers = PowerMock.createNiceMock(LiveTServerSet.class);
TServerInstance instance = PowerMock.createNiceMock(TServerInstance.class);
HostAndPort tserverAddress = HostAndPort.fromString("localhost:9997");
EasyMock.expect(instance.getHostAndPort()).andReturn(tserverAddress).anyTimes();
EasyMock.expect(tservers.getCurrentServers()).andReturn(Sets.newHashSet(instance)).once();
tservers.startListeningForTabletServerChanges();
PowerMock.mockStatic(ExternalCompactionUtil.class);
List<RunningCompaction> runningCompactions = new ArrayList<>();
ExternalCompactionId eci = ExternalCompactionId.generate(UUID.randomUUID());
TExternalCompactionJob job = PowerMock.createNiceMock(TExternalCompactionJob.class);
EasyMock.expect(job.getExternalCompactionId()).andReturn(eci.toString()).anyTimes();
TKeyExtent extent = new TKeyExtent();
extent.setTable("1".getBytes());
runningCompactions.add(new RunningCompaction(job, tserverAddress.toString(), "queue"));
EasyMock.expect(ExternalCompactionUtil.getCompactionsRunningOnCompactors(context)).andReturn(runningCompactions);
ServerAddress client = PowerMock.createNiceMock(ServerAddress.class);
HostAndPort address = HostAndPort.fromString("localhost:10240");
EasyMock.expect(client.getAddress()).andReturn(address).anyTimes();
EasyMock.expect(instance.getHostPort()).andReturn("localhost:9997").anyTimes();
TabletClientService.Client tsc = PowerMock.createNiceMock(TabletClientService.Client.class);
TCompactionQueueSummary queueSummary = PowerMock.createNiceMock(TCompactionQueueSummary.class);
EasyMock.expect(tsc.getCompactionQueueInfo(EasyMock.anyObject(), EasyMock.anyObject())).andReturn(Collections.singletonList(queueSummary)).anyTimes();
EasyMock.expect(queueSummary.getQueue()).andReturn("R2DQ").anyTimes();
EasyMock.expect(queueSummary.getPriority()).andReturn((short) 1).anyTimes();
AuditedSecurityOperation security = PowerMock.createNiceMock(AuditedSecurityOperation.class);
PowerMock.replayAll();
TestCoordinator coordinator = new TestCoordinator(conf, finalizer, tservers, client, tsc, context, security);
coordinator.resetInternals();
assertEquals(0, coordinator.getQueues().size());
assertEquals(0, coordinator.getIndex().size());
assertEquals(0, coordinator.getRunning().size());
coordinator.run();
assertEquals(1, coordinator.getQueues().size());
QueueAndPriority qp = QueueAndPriority.get("R2DQ".intern(), (short) 1);
Map<Short, TreeSet<TServerInstance>> m = coordinator.getQueues().get("R2DQ".intern());
assertNotNull(m);
assertEquals(1, m.size());
assertTrue(m.containsKey((short) 1));
Set<TServerInstance> t = m.get((short) 1);
assertNotNull(t);
assertEquals(1, t.size());
TServerInstance queuedTsi = t.iterator().next();
assertEquals(instance.getHostPortSession(), queuedTsi.getHostPortSession());
assertEquals(1, coordinator.getIndex().size());
assertTrue(coordinator.getIndex().containsKey(queuedTsi));
Set<QueueAndPriority> i = coordinator.getIndex().get(queuedTsi);
assertEquals(1, i.size());
assertEquals(qp, i.iterator().next());
assertEquals(1, coordinator.getRunning().size());
PowerMock.verifyAll();
coordinator.resetInternals();
coordinator.close();
}
use of org.apache.accumulo.core.tabletserver.thrift.TExternalCompactionJob in project accumulo by apache.
the class CompactionCoordinatorTest method testGetCompactionJobNoJobs.
@Test
public void testGetCompactionJobNoJobs() throws Exception {
PowerMock.resetAll();
PowerMock.suppress(PowerMock.constructor(AbstractServer.class));
AccumuloConfiguration conf = PowerMock.createNiceMock(AccumuloConfiguration.class);
ServerContext context = PowerMock.createNiceMock(ServerContext.class);
TCredentials creds = PowerMock.createNiceMock(TCredentials.class);
CompactionFinalizer finalizer = PowerMock.createNiceMock(CompactionFinalizer.class);
LiveTServerSet tservers = PowerMock.createNiceMock(LiveTServerSet.class);
ServerAddress client = PowerMock.createNiceMock(ServerAddress.class);
HostAndPort address = HostAndPort.fromString("localhost:10240");
EasyMock.expect(client.getAddress()).andReturn(address).anyTimes();
TabletClientService.Client tsc = PowerMock.createNiceMock(TabletClientService.Client.class);
AuditedSecurityOperation security = PowerMock.createNiceMock(AuditedSecurityOperation.class);
EasyMock.expect(security.canPerformSystemActions(creds)).andReturn(true);
PowerMock.replayAll();
TestCoordinator coordinator = new TestCoordinator(conf, finalizer, tservers, client, tsc, context, security);
coordinator.resetInternals();
TExternalCompactionJob job = coordinator.getCompactionJob(TraceUtil.traceInfo(), creds, "R2DQ", "localhost:10240", UUID.randomUUID().toString());
assertNull(job.getExternalCompactionId());
PowerMock.verifyAll();
coordinator.resetInternals();
coordinator.close();
}
use of org.apache.accumulo.core.tabletserver.thrift.TExternalCompactionJob in project accumulo by apache.
the class CompactionCoordinatorTest method testGetCompactionJob.
@Test
public void testGetCompactionJob() throws Exception {
PowerMock.resetAll();
PowerMock.suppress(PowerMock.constructor(AbstractServer.class));
PowerMock.suppress(PowerMock.methods(ThriftUtil.class, "returnClient"));
PowerMock.suppress(PowerMock.methods(DeadCompactionDetector.class, "detectDeadCompactions", "detectDanglingFinalStateMarkers"));
AccumuloConfiguration conf = PowerMock.createNiceMock(AccumuloConfiguration.class);
ServerContext context = PowerMock.createNiceMock(ServerContext.class);
TCredentials creds = PowerMock.createNiceMock(TCredentials.class);
EasyMock.expect(context.rpcCreds()).andReturn(creds).anyTimes();
PowerMock.mockStatic(ExternalCompactionUtil.class);
List<RunningCompaction> runningCompactions = new ArrayList<>();
EasyMock.expect(ExternalCompactionUtil.getCompactionsRunningOnCompactors(context)).andReturn(runningCompactions);
CompactionFinalizer finalizer = PowerMock.createNiceMock(CompactionFinalizer.class);
LiveTServerSet tservers = PowerMock.createNiceMock(LiveTServerSet.class);
TServerInstance instance = PowerMock.createNiceMock(TServerInstance.class);
EasyMock.expect(tservers.getCurrentServers()).andReturn(Collections.singleton(instance)).once();
HostAndPort tserverAddress = HostAndPort.fromString("localhost:9997");
EasyMock.expect(instance.getHostAndPort()).andReturn(tserverAddress).anyTimes();
ServerAddress client = PowerMock.createNiceMock(ServerAddress.class);
HostAndPort address = HostAndPort.fromString("localhost:10240");
EasyMock.expect(client.getAddress()).andReturn(address).anyTimes();
TServerInstance tsi = PowerMock.createNiceMock(TServerInstance.class);
EasyMock.expect(tsi.getHostPort()).andReturn("localhost:9997").anyTimes();
TabletClientService.Client tsc = PowerMock.createNiceMock(TabletClientService.Client.class);
TCompactionQueueSummary queueSummary = PowerMock.createNiceMock(TCompactionQueueSummary.class);
EasyMock.expect(tsc.getCompactionQueueInfo(EasyMock.anyObject(), EasyMock.anyObject())).andReturn(Collections.singletonList(queueSummary)).anyTimes();
EasyMock.expect(queueSummary.getQueue()).andReturn("R2DQ").anyTimes();
EasyMock.expect(queueSummary.getPriority()).andReturn((short) 1).anyTimes();
ExternalCompactionId eci = ExternalCompactionId.generate(UUID.randomUUID());
TExternalCompactionJob job = PowerMock.createNiceMock(TExternalCompactionJob.class);
EasyMock.expect(job.getExternalCompactionId()).andReturn(eci.toString()).anyTimes();
TInfo trace = TraceUtil.traceInfo();
EasyMock.expect(tsc.reserveCompactionJob(trace, creds, "R2DQ", 1, "localhost:10241", eci.toString())).andReturn(job).anyTimes();
AuditedSecurityOperation security = PowerMock.createNiceMock(AuditedSecurityOperation.class);
EasyMock.expect(security.canPerformSystemActions(creds)).andReturn(true);
PowerMock.replayAll();
TestCoordinator coordinator = new TestCoordinator(conf, finalizer, tservers, client, tsc, context, security);
coordinator.resetInternals();
assertEquals(0, coordinator.getQueues().size());
assertEquals(0, coordinator.getIndex().size());
assertEquals(0, coordinator.getRunning().size());
// Use coordinator.run() to populate the internal data structures. This is tested in a different
// test.
coordinator.run();
assertEquals(1, coordinator.getQueues().size());
QueueAndPriority qp = QueueAndPriority.get("R2DQ".intern(), (short) 1);
Map<Short, TreeSet<TServerInstance>> m = coordinator.getQueues().get("R2DQ".intern());
assertNotNull(m);
assertEquals(1, m.size());
assertTrue(m.containsKey((short) 1));
Set<TServerInstance> t = m.get((short) 1);
assertNotNull(t);
assertEquals(1, t.size());
TServerInstance queuedTsi = t.iterator().next();
assertEquals(tsi.getHostPortSession(), queuedTsi.getHostPortSession());
assertEquals(1, coordinator.getIndex().size());
assertTrue(coordinator.getIndex().containsKey(queuedTsi));
Set<QueueAndPriority> i = coordinator.getIndex().get(queuedTsi);
assertEquals(1, i.size());
assertEquals(qp, i.iterator().next());
assertEquals(0, coordinator.getRunning().size());
// Get the next job
TExternalCompactionJob createdJob = coordinator.getCompactionJob(trace, creds, "R2DQ", "localhost:10241", eci.toString());
assertEquals(eci.toString(), createdJob.getExternalCompactionId());
assertEquals(1, coordinator.getQueues().size());
assertEquals(1, coordinator.getIndex().size());
assertEquals(1, coordinator.getRunning().size());
Entry<ExternalCompactionId, RunningCompaction> entry = coordinator.getRunning().entrySet().iterator().next();
assertEquals(eci.toString(), entry.getKey().toString());
assertEquals("localhost:10241", entry.getValue().getCompactorAddress());
assertEquals(eci.toString(), entry.getValue().getJob().getExternalCompactionId());
PowerMock.verifyAll();
coordinator.resetInternals();
coordinator.close();
}
use of org.apache.accumulo.core.tabletserver.thrift.TExternalCompactionJob in project accumulo by apache.
the class Compactor method checkIfCanceled.
protected void checkIfCanceled() {
TExternalCompactionJob job = JOB_HOLDER.getJob();
if (job != null) {
try {
var extent = KeyExtent.fromThrift(job.getExtent());
var ecid = ExternalCompactionId.of(job.getExternalCompactionId());
TabletMetadata tabletMeta = getContext().getAmple().readTablet(extent, ColumnType.ECOMP, ColumnType.PREV_ROW);
if (tabletMeta == null || !tabletMeta.getExternalCompactions().containsKey(ecid)) {
// table was deleted OR tablet was split or merged OR tablet no longer thinks compaction
// is running for some reason
LOG.info("Cancelling compaction {} that no longer has a metadata entry at {}", ecid, extent);
JOB_HOLDER.cancel(job.getExternalCompactionId());
return;
}
if (job.getKind() == TCompactionKind.USER) {
String zTablePath = Constants.ZROOT + "/" + getContext().getInstanceID() + Constants.ZTABLES + "/" + extent.tableId() + Constants.ZTABLE_COMPACT_CANCEL_ID;
byte[] id = getContext().getZooCache().get(zTablePath);
if (id == null) {
// table probably deleted
LOG.info("Cancelling compaction {} for table that no longer exists {}", ecid, extent);
JOB_HOLDER.cancel(job.getExternalCompactionId());
return;
} else {
var cancelId = Long.parseLong(new String(id, UTF_8));
if (cancelId >= job.getUserCompactionId()) {
LOG.info("Cancelling compaction {} because user compaction was canceled", ecid);
JOB_HOLDER.cancel(job.getExternalCompactionId());
return;
}
}
}
} catch (RuntimeException e) {
LOG.warn("Failed to check if compaction {} for {} was canceled.", job.getExternalCompactionId(), KeyExtent.fromThrift(job.getExtent()), e);
}
}
}
use of org.apache.accumulo.core.tabletserver.thrift.TExternalCompactionJob in project accumulo by apache.
the class Compactor method run.
@Override
public void run() {
try {
compactorAddress = startCompactorClientService();
} catch (UnknownHostException e1) {
throw new RuntimeException("Failed to start the compactor client service", e1);
}
final HostAndPort clientAddress = compactorAddress.getAddress();
try {
announceExistence(clientAddress);
} catch (KeeperException | InterruptedException e) {
throw new RuntimeException("Error registering compactor in ZooKeeper", e);
}
try {
MetricsUtil.initializeMetrics(getContext().getConfiguration(), this.applicationName, clientAddress);
} catch (Exception e1) {
LOG.error("Error initializing metrics, metrics will not be emitted.", e1);
}
MetricsUtil.initializeProducers(this);
LOG.info("Compactor started, waiting for work");
try {
final AtomicReference<Throwable> err = new AtomicReference<>();
while (!shutdown) {
currentCompactionId.set(null);
err.set(null);
JOB_HOLDER.reset();
TExternalCompactionJob job;
try {
job = getNextJob(getNextId());
if (!job.isSetExternalCompactionId()) {
LOG.trace("No external compactions in queue {}", this.queueName);
UtilWaitThread.sleep(getWaitTimeBetweenCompactionChecks());
continue;
}
if (!job.getExternalCompactionId().equals(currentCompactionId.get().toString())) {
throw new IllegalStateException("Returned eci " + job.getExternalCompactionId() + " does not match supplied eci " + currentCompactionId.get());
}
} catch (RetriesExceededException e2) {
LOG.warn("Retries exceeded getting next job. Retrying...");
continue;
}
LOG.debug("Received next compaction job: {}", job);
final LongAdder totalInputEntries = new LongAdder();
final LongAdder totalInputBytes = new LongAdder();
final CountDownLatch started = new CountDownLatch(1);
final CountDownLatch stopped = new CountDownLatch(1);
final Thread compactionThread = Threads.createThread("Compaction job for tablet " + job.getExtent().toString(), createCompactionJob(job, totalInputEntries, totalInputBytes, started, stopped, err));
JOB_HOLDER.set(job, compactionThread);
try {
// start the compactionThread
compactionThread.start();
// wait until the compactor is started
started.await();
final long inputEntries = totalInputEntries.sum();
final long waitTime = calculateProgressCheckTime(totalInputBytes.sum());
LOG.debug("Progress checks will occur every {} seconds", waitTime);
String percentComplete = "unknown";
while (!stopped.await(waitTime, TimeUnit.SECONDS)) {
List<CompactionInfo> running = org.apache.accumulo.server.compaction.FileCompactor.getRunningCompactions();
if (!running.isEmpty()) {
// Compaction has started. There should only be one in the list
CompactionInfo info = running.get(0);
if (info != null) {
if (inputEntries > 0) {
percentComplete = Float.toString((info.getEntriesRead() / (float) inputEntries) * 100);
}
String message = String.format("Compaction in progress, read %d of %d input entries ( %s %s ), written %d entries", info.getEntriesRead(), inputEntries, percentComplete, "%", info.getEntriesWritten());
watcher.run();
try {
LOG.debug("Updating coordinator with compaction progress: {}.", message);
TCompactionStatusUpdate update = new TCompactionStatusUpdate(TCompactionState.IN_PROGRESS, message, inputEntries, info.getEntriesRead(), info.getEntriesWritten());
updateCompactionState(job, update);
} catch (RetriesExceededException e) {
LOG.warn("Error updating coordinator with compaction progress, error: {}", e.getMessage());
}
}
} else {
LOG.error("Waiting on compaction thread to finish, but no RUNNING compaction");
}
}
compactionThread.join();
LOG.trace("Compaction thread finished.");
// Run the watcher again to clear out the finished compaction and set the
// stuck count to zero.
watcher.run();
if (err.get() != null) {
// maybe the error occured because the table was deleted or something like that, so
// force a cancel check to possibly reduce noise in the logs
checkIfCanceled();
}
if (compactionThread.isInterrupted() || JOB_HOLDER.isCancelled() || (err.get() != null && err.get().getClass().equals(InterruptedException.class))) {
LOG.warn("Compaction thread was interrupted, sending CANCELLED state");
try {
TCompactionStatusUpdate update = new TCompactionStatusUpdate(TCompactionState.CANCELLED, "Compaction cancelled", -1, -1, -1);
updateCompactionState(job, update);
updateCompactionFailed(job);
} catch (RetriesExceededException e) {
LOG.error("Error updating coordinator with compaction cancellation.", e);
} finally {
currentCompactionId.set(null);
}
} else if (err.get() != null) {
try {
LOG.info("Updating coordinator with compaction failure.");
TCompactionStatusUpdate update = new TCompactionStatusUpdate(TCompactionState.FAILED, "Compaction failed due to: " + err.get().getMessage(), -1, -1, -1);
updateCompactionState(job, update);
updateCompactionFailed(job);
} catch (RetriesExceededException e) {
LOG.error("Error updating coordinator with compaction failure.", e);
} finally {
currentCompactionId.set(null);
}
} else {
try {
LOG.trace("Updating coordinator with compaction completion.");
updateCompactionCompleted(job, JOB_HOLDER.getStats());
} catch (RetriesExceededException e) {
LOG.error("Error updating coordinator with compaction completion, cancelling compaction.", e);
try {
cancel(job.getExternalCompactionId());
} catch (TException e1) {
LOG.error("Error cancelling compaction.", e1);
}
} finally {
currentCompactionId.set(null);
}
}
} catch (RuntimeException e1) {
LOG.error("Compactor thread was interrupted waiting for compaction to start, cancelling job", e1);
try {
cancel(job.getExternalCompactionId());
} catch (TException e2) {
LOG.error("Error cancelling compaction.", e2);
}
} finally {
currentCompactionId.set(null);
// avoid multiple threads updating shared state.
while (compactionThread.isAlive()) {
compactionThread.interrupt();
compactionThread.join(1000);
}
}
}
} catch (Exception e) {
LOG.error("Unhandled error occurred in Compactor", e);
} finally {
// Shutdown local thrift server
LOG.info("Stopping Thrift Servers");
if (compactorAddress.server != null) {
compactorAddress.server.stop();
}
try {
LOG.debug("Closing filesystems");
VolumeManager mgr = getContext().getVolumeManager();
if (null != mgr) {
mgr.close();
}
} catch (IOException e) {
LOG.warn("Failed to close filesystem : {}", e.getMessage(), e);
}
gcLogger.logGCInfo(getConfiguration());
LOG.info("stop requested. exiting ... ");
try {
if (null != compactorLock) {
compactorLock.unlock();
}
} catch (Exception e) {
LOG.warn("Failed to release compactor lock", e);
}
}
}
Aggregations