/**
* This file is part of General Entity Annotator Benchmark.
*
* General Entity Annotator Benchmark is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* General Entity Annotator Benchmark is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with General Entity Annotator Benchmark. If not, see <http://www.gnu.org/licenses/>.
*/
package org.aksw.gerbil.http;
import java.util.concurrent.Semaphore;
import org.apache.http.client.methods.HttpUriRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.carrotsearch.hppc.ObjectLongOpenHashMap;
public class InterruptingObserver implements Runnable {
private static final Logger LOGGER = LoggerFactory.getLogger(InterruptingObserver.class);
private long maxWaitingTime;
private long checkInterval;
private final ObjectLongOpenHashMap<ObservedHttpRequest> observedRequests = new ObjectLongOpenHashMap<ObservedHttpRequest>();
private final Semaphore observedMappingMutex = new Semaphore(1);
public InterruptingObserver(long maxWaitingTime, long checkInterval) {
this.maxWaitingTime = maxWaitingTime;
this.checkInterval = checkInterval;
}
@Override
public void run() {
while (true) {
checkAnnotators();
try {
Thread.sleep(checkInterval);
} catch (InterruptedException e) {
LOGGER.error("Interrupted while sleeping.");
}
}
}
private void checkAnnotators() {
try {
observedMappingMutex.acquire();
} catch (InterruptedException e) {
LOGGER.error("Interrupted while waiting for mutex. Aborting.");
}
long waitingTime;
long currentTime = System.currentTimeMillis();
ObservedHttpRequest observedRequest;
for (int i = 0; i < observedRequests.allocated.length; ++i) {
if (observedRequests.allocated[i]) {
waitingTime = currentTime - observedRequests.values[i];
if (waitingTime > maxWaitingTime) {
observedRequest = ((ObservedHttpRequest) ((Object[]) observedRequests.keys)[i]);
LOGGER.info("The HTTP request emitter \"{}\" already runs for {} ms. Trying to interrupt it.",
observedRequest.emitter.getName(), waitingTime);
try {
observedRequest.emitter.interrupt(observedRequest.request);
} catch (UnsupportedOperationException e) {
LOGGER.error("Couldn't interrupt request of HTTP request emitter \""
+ observedRequest.emitter.getName() + "\" that is already running for " + waitingTime
+ " ms.");
}
}
}
}
observedMappingMutex.release();
}
public void reportStart(HttpRequestEmitter emitter, HttpUriRequest request) {
ObservedHttpRequest observedRequest = new ObservedHttpRequest(request, emitter);
try {
observedMappingMutex.acquire();
} catch (InterruptedException e) {
LOGGER.error("Interrupted while waiting for mutex. Aborting.");
}
if (observedRequests.containsKey(observedRequest)) {
LOGGER.error("There already is an observed request equal to this new one (" + observedRequest.toString()
+ "). Note that this is a fatal error and the old request will be overwritten.");
}
observedRequests.put(observedRequest, System.currentTimeMillis());
observedMappingMutex.release();
}
public void reportEnd(HttpRequestEmitter emitter, HttpUriRequest request) {
ObservedHttpRequest observedRequest = new ObservedHttpRequest(request, emitter);
try {
observedMappingMutex.acquire();
} catch (InterruptedException e) {
LOGGER.error("Interrupted while waiting for mutex. Aborting.");
}
if (observedRequests.containsKey(observedRequest)) {
observedRequests.remove(observedRequest);
} else {
LOGGER.error("Tried to remove an observed request that is not existing (" + observedRequest.toString()
+ "). This is a fatal error.");
}
observedMappingMutex.release();
}
public long getMaxWaitingTime() {
return maxWaitingTime;
}
public void setMaxWaitingTime(long maxWaitingTime) {
this.maxWaitingTime = maxWaitingTime;
}
public long getCheckInterval() {
return checkInterval;
}
public void setCheckInterval(long checkInterval) {
this.checkInterval = checkInterval;
}
}