use of com.linkedin.r2.SizeLimitExceededException in project rest.li by linkedin.
the class AsyncSharedPoolImpl method get.
@Override
public Cancellable get(Callback<T> callback) {
ArgumentUtil.notNull(callback, "callback");
final TimeTrackingCallback timeTrackingCallback = new TimeTrackingCallback(callback);
final LinkedDeque.Node<Callback<T>> node;
T item = null;
boolean create = false;
while (true) {
final State state;
synchronized (_lock) {
state = _state;
if (state == State.RUNNING) {
item = _item.get();
if (item == null) {
node = _waiters.size() < _maxWaiters ? _waiters.addLastNode(timeTrackingCallback) : null;
if (_isCreateInProgress) {
LOG.debug("{}: item creation is in progress", _name);
} else {
_isCreateInProgress = true;
create = true;
}
break;
}
_checkedOut++;
_statsTracker.sampleMaxCheckedOut();
}
}
if (state != State.RUNNING) {
// Defer execution of the callback until we are out of the synchronized block
timeTrackingCallback.onError(new IllegalStateException(_name + " is " + _state));
return () -> false;
}
// through the item lifecycle before passing back to user callback
if (_lifecycle.validateGet(item)) {
timeTrackingCallback.onSuccess(item);
return () -> false;
}
boolean disposed;
synchronized (_lock) {
// The connection has gone bad so we proceed to destroy it
disposed = doDispose(item);
}
if (disposed) {
doDestroy(item, BAD, () -> {
});
}
}
if (node == null) {
// This is a recoverable exception. User can simply retry the failed get() operation.
timeTrackingCallback.onError(new SizeLimitExceededException("AsyncPool " + _name + " reached maximum waiter size: " + _maxWaiters));
return () -> false;
}
// The pool is currently empty we need to construct a new item
if (create) {
doCreate();
}
return () -> {
synchronized (_lock) {
return _waiters.removeNode(node) != null;
}
};
}
use of com.linkedin.r2.SizeLimitExceededException in project rest.li by linkedin.
the class AsyncPoolImpl method get.
@Override
public Cancellable get(final Callback<T> callback) {
// getter needs to add to wait queue atomically with check for empty pool
// putter needs to add to pool atomically with check for empty wait queue
boolean create = false;
boolean reject = false;
final LinkedDeque.Node<Callback<T>> node;
Callback<T> callbackWithTracking = new TimeTrackingCallback<>(callback);
for (; ; ) {
TimedObject<T> obj = null;
final State state;
synchronized (_lock) {
state = _state;
if (state == State.RUNNING) {
if (_strategy == Strategy.LRU) {
obj = _idle.pollFirst();
} else {
obj = _idle.pollLast();
}
if (obj == null) {
if (_waiters.size() < _maxWaiters) {
if (isWaiterTimeoutEnabled()) {
callbackWithTracking = new WaiterTimeoutCallback(callbackWithTracking);
}
// No objects available and the waiter list is not full; add to waiter list and break out of loop
node = _waiters.addLastNode(callbackWithTracking);
create = shouldCreate();
} else {
reject = true;
node = null;
}
break;
}
}
}
if (state != State.RUNNING) {
// Defer execution of the callback until we are out of the synchronized block
callbackWithTracking.onError(new IllegalStateException(_poolName + " is " + _state));
return () -> false;
}
T rawObj = obj.get();
if (_lifecycle.validateGet(rawObj)) {
trc("dequeued an idle object");
// Valid object; done
synchronized (_lock) {
_checkedOut++;
_statsTracker.sampleMaxCheckedOut();
}
callbackWithTracking.onSuccess(rawObj);
return () -> false;
}
// Invalid object, discard it and keep trying
destroy(rawObj, true);
trc("dequeued and disposed an invalid idle object");
}
if (reject) {
// This is a recoverable exception. User can simply retry the failed get() operation.
callbackWithTracking.onError(new SizeLimitExceededException("AsyncPool " + _poolName + " reached maximum waiter size: " + _maxWaiters));
return () -> false;
}
trc("enqueued a waiter");
if (create) {
create();
}
return new Cancellable() {
@Override
public boolean cancel() {
synchronized (_lock) {
boolean cancelled = _waiters.removeNode(node) != null;
if (cancelled) {
shutdownIfNeeded();
}
return cancelled;
}
}
};
}
Aggregations