com.microsoft.azure.eventhubs.impl.FaultTolerantObject Maven / Gradle / Ivy
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package com.microsoft.azure.eventhubs.impl;
import java.io.IOException;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
public class FaultTolerantObject {
private final Operation openTask;
private final Operation closeTask;
private final Queue> openCallbacks;
private final Queue> closeCallbacks;
private T innerObject;
private boolean creatingNewInnerObject;
private boolean closingInnerObject;
public FaultTolerantObject(
final Operation openAsync,
final Operation closeAsync) {
this.openTask = openAsync;
this.closeTask = closeAsync;
this.openCallbacks = new ConcurrentLinkedQueue<>();
this.closeCallbacks = new ConcurrentLinkedQueue<>();
}
// should be invoked from reactor thread
T unsafeGetIfOpened() {
if (innerObject != null && innerObject.getState() == IOObject.IOObjectState.OPENED) {
return innerObject;
}
return null;
}
public void runOnOpenedObject(
final ReactorDispatcher dispatcher,
final OperationResult openCallback) {
try {
dispatcher.invoke(new DispatchHandler() {
@Override
public void onEvent() {
if (!creatingNewInnerObject
&& (innerObject == null || innerObject.getState() == IOObject.IOObjectState.CLOSED
|| innerObject.getState() == IOObject.IOObjectState.CLOSING)) {
creatingNewInnerObject = true;
try {
openCallbacks.offer(openCallback);
openTask.run(new OperationResult() {
@Override
public void onComplete(T result) {
innerObject = result;
for (OperationResult callback : openCallbacks) {
callback.onComplete(result);
}
openCallbacks.clear();
}
@Override
public void onError(Exception error) {
for (OperationResult callback : openCallbacks) {
callback.onError(error);
}
openCallbacks.clear();
}
});
} finally {
creatingNewInnerObject = false;
}
} else if (innerObject != null && innerObject.getState() == IOObject.IOObjectState.OPENED) {
openCallback.onComplete(innerObject);
} else {
openCallbacks.offer(openCallback);
}
}
});
} catch (IOException ioException) {
openCallback.onError(ioException);
}
}
public void close(
final ReactorDispatcher dispatcher,
final OperationResult closeCallback) {
try {
dispatcher.invoke(new DispatchHandler() {
@Override
public void onEvent() {
if (innerObject == null || innerObject.getState() == IOObject.IOObjectState.CLOSED) {
closeCallback.onComplete(null);
} else if (!closingInnerObject && (innerObject.getState() == IOObject.IOObjectState.OPENED || innerObject.getState() == IOObject.IOObjectState.OPENING)) {
closingInnerObject = true;
closeCallbacks.offer(closeCallback);
closeTask.run(new OperationResult() {
@Override
public void onComplete(Void result) {
closingInnerObject = false;
for (OperationResult callback : closeCallbacks) {
callback.onComplete(result);
}
closeCallbacks.clear();
}
@Override
public void onError(Exception error) {
closingInnerObject = false;
for (OperationResult callback : closeCallbacks) {
callback.onError(error);
}
closeCallbacks.clear();
}
});
} else {
closeCallbacks.offer(closeCallback);
}
}
});
} catch (IOException ioException) {
closeCallback.onError(ioException);
}
}
}