use of com.twitter.distributedlog.exceptions.StreamUnavailableException in project distributedlog by twitter.
the class DistributedLogServiceImpl method executeStreamOp.
private void executeStreamOp(final StreamOp op) {
// Must attach this as early as possible--returning before this point will cause us to
// lose the status code.
op.responseHeader().addEventListener(new FutureEventListener<ResponseHeader>() {
@Override
public void onSuccess(ResponseHeader header) {
if (header.getLocation() != null || header.getCode() == StatusCode.FOUND) {
redirects.inc();
}
countStatusCode(header.getCode());
}
@Override
public void onFailure(Throwable cause) {
}
});
try {
// Apply the request limiter
limiter.apply(op);
// Execute per-op pre-exec code
op.preExecute();
} catch (TooManyStreamsException e) {
// Translate to StreamUnavailableException to ensure that the client will redirect
// to a different host. Ideally we would be able to return TooManyStreamsException,
// but the way exception handling works right now we can't control the handling in
// the client because client changes deploy very slowly.
op.fail(new StreamUnavailableException(e.getMessage()));
return;
} catch (Exception e) {
op.fail(e);
return;
}
Stream stream;
try {
stream = getLogWriter(op.streamName());
} catch (RegionUnavailableException rue) {
// redirect the requests to other region
op.fail(new RegionUnavailableException("Region " + serverRegionId + " is unavailable."));
return;
} catch (IOException e) {
op.fail(e);
return;
}
if (null == stream) {
// redirect the requests when stream is unavailable.
op.fail(new ServiceUnavailableException("Server " + clientId + " is closed."));
return;
}
if (op instanceof WriteOpWithPayload) {
WriteOpWithPayload writeOp = (WriteOpWithPayload) op;
windowedBps.add(writeOp.getPayloadSize());
windowedRps.inc();
}
stream.submit(op);
}
use of com.twitter.distributedlog.exceptions.StreamUnavailableException in project distributedlog by twitter.
the class StreamManagerImpl method getOrCreateStream.
@Override
public Stream getOrCreateStream(String streamName) throws IOException {
Stream stream = streams.get(streamName);
if (null == stream) {
closeLock.readLock().lock();
try {
if (closed) {
return null;
}
DynamicDistributedLogConfiguration dynConf = getDynConf(streamName);
int maxCachedPartitions = dynConf.getMaxCachedPartitionsPerProxy();
// get partition from the stream name
Partition partition = partitionConverter.convert(streamName);
// add partition to cached map
if (!cachedPartitions.addPartition(partition, maxCachedPartitions)) {
throw new StreamUnavailableException("Stream " + streamName + " is not allowed to cache more than " + maxCachedPartitions + " partitions");
}
stream = newStream(streamName, dynConf);
Stream oldWriter = streams.putIfAbsent(streamName, stream);
if (null != oldWriter) {
stream = oldWriter;
} else {
numCached.getAndIncrement();
logger.info("Inserted mapping stream name {} -> stream {}", streamName, stream);
stream.initialize();
stream.start();
}
} finally {
closeLock.readLock().unlock();
}
}
return stream;
}
use of com.twitter.distributedlog.exceptions.StreamUnavailableException in project distributedlog by twitter.
the class StreamImpl method closeManagerAndErrorOutPendingRequests.
private void closeManagerAndErrorOutPendingRequests() {
close(manager);
// Failed the pending requests.
Queue<StreamOp> oldPendingOps;
synchronized (this) {
oldPendingOps = pendingOps;
pendingOps = new ArrayDeque<StreamOp>();
}
StreamUnavailableException closingException = new StreamUnavailableException("Stream " + name + " is closed.");
for (StreamOp op : oldPendingOps) {
op.fail(closingException);
pendingOpsCounter.dec();
}
limiter.close();
logger.info("Closed stream {}.", name);
}
use of com.twitter.distributedlog.exceptions.StreamUnavailableException in project distributedlog by twitter.
the class StreamImpl method submit.
/**
* Execute the StreamOp. If reacquire is needed, this may initiate reacquire and queue the op for
* execution once complete.
*
* @param op
* stream operation to execute.
*/
@Override
public void submit(StreamOp op) {
// Let stream acquire thread know a write has been attempted.
writeSinceLastAcquire = true;
try {
limiter.apply(op);
} catch (OverCapacityException ex) {
op.fail(ex);
return;
}
// Timeout stream op if requested.
if (serviceTimeoutMs > 0) {
scheduleTimeout(op);
}
boolean notifyAcquireThread = false;
boolean completeOpNow = false;
boolean success = true;
if (StreamStatus.isUnavailable(status)) {
// Stream is closed, fail the op immediately
op.fail(new StreamUnavailableException("Stream " + name + " is closed."));
return;
}
if (StreamStatus.INITIALIZED == status && writer != null) {
completeOpNow = true;
success = true;
} else {
synchronized (this) {
if (StreamStatus.isUnavailable(status)) {
// complete the write op as {@link #executeOp(op, success)} will handle closed case.
completeOpNow = true;
success = true;
}
if (StreamStatus.INITIALIZED == status) {
completeOpNow = true;
success = true;
} else if (StreamStatus.BACKOFF == status && lastAcquireFailureWatch.elapsed(TimeUnit.MILLISECONDS) < nextAcquireWaitTimeMs) {
completeOpNow = true;
success = false;
} else if (failFastOnStreamNotReady) {
notifyAcquireThread = true;
completeOpNow = false;
success = false;
op.fail(new StreamNotReadyException("Stream " + name + " is not ready; status = " + status));
} else {
// closing & initializing
notifyAcquireThread = true;
pendingOps.add(op);
pendingOpsCounter.inc();
if (1 == pendingOps.size()) {
if (op instanceof HeartbeatOp) {
((HeartbeatOp) op).setWriteControlRecord(true);
}
}
}
}
}
if (notifyAcquireThread && !suspended) {
scheduleTryAcquireOnce(0L);
}
if (completeOpNow) {
executeOp(op, success);
}
}
use of com.twitter.distributedlog.exceptions.StreamUnavailableException in project distributedlog by twitter.
the class TestDistributedLogService method testAcquireStreamsWhenExceedMaxCachedPartitions.
@Test(timeout = 60000)
public void testAcquireStreamsWhenExceedMaxCachedPartitions() throws Exception {
String streamName = testName.getMethodName() + "_0000";
DistributedLogConfiguration confLocal = new DistributedLogConfiguration();
confLocal.addConfiguration(dlConf);
confLocal.setMaxCachedPartitionsPerProxy(1);
ServerConfiguration serverConfLocal = new ServerConfiguration();
serverConfLocal.addConfiguration(serverConf);
serverConfLocal.setStreamPartitionConverterClass(DelimiterStreamPartitionConverter.class);
DistributedLogServiceImpl serviceLocal = createService(serverConfLocal, confLocal);
Stream stream = serviceLocal.getLogWriter(streamName);
// stream is cached
assertNotNull(stream);
assertEquals(1, serviceLocal.getStreamManager().numCached());
// create write ops
WriteOp op0 = createWriteOp(service, streamName, 0L);
stream.submit(op0);
WriteResponse wr0 = Await.result(op0.result());
assertEquals("Op 0 should succeed", StatusCode.SUCCESS, wr0.getHeader().getCode());
assertEquals(1, serviceLocal.getStreamManager().numAcquired());
// should fail to acquire another partition
try {
serviceLocal.getLogWriter(testName.getMethodName() + "_0001");
fail("Should fail to acquire new streams");
} catch (StreamUnavailableException sue) {
// expected
}
assertEquals(1, serviceLocal.getStreamManager().numCached());
assertEquals(1, serviceLocal.getStreamManager().numAcquired());
// should be able to acquire partitions from other streams
String anotherStreamName = testName.getMethodName() + "-another_0001";
Stream anotherStream = serviceLocal.getLogWriter(anotherStreamName);
assertNotNull(anotherStream);
assertEquals(2, serviceLocal.getStreamManager().numCached());
// create write ops
WriteOp op1 = createWriteOp(service, anotherStreamName, 0L);
anotherStream.submit(op1);
WriteResponse wr1 = Await.result(op1.result());
assertEquals("Op 1 should succeed", StatusCode.SUCCESS, wr1.getHeader().getCode());
assertEquals(2, serviceLocal.getStreamManager().numAcquired());
}
Aggregations