package org.apache.solr.handler.batch;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.solr.common.params.SolrParams;
public class BatchHandlerRequestQueue {
private Map<String, BatchHandlerRequestData>tbdQueue = Collections.synchronizedMap(new LinkedHashMap<String, BatchHandlerRequestData>());
private Map<String, BatchHandlerRequestData>failedQueue = Collections.synchronizedMap(new LinkedHashMap<String, BatchHandlerRequestData>());
private Integer queuedIn = 0;
private Integer queuedOut = 0;
private Map<String, Integer> jobs = Collections.synchronizedMap(new LinkedHashMap<String, Integer>());
private Map<String, String> failedJobs = Collections.synchronizedMap(new LinkedHashMap<String, String>());
private volatile boolean stopped;
public BatchHandlerRequestData getNext() {
for (Entry e: tbdQueue.entrySet()) {
return tbdQueue.get(e.getKey());
}
return null;
}
public BatchHandlerRequestData pop() {
for (Entry e: tbdQueue.entrySet()) {
queuedOut++;
return tbdQueue.remove(e.getKey());
}
return null;
}
public void registerFailedBatch(BatchProvider provider, BatchHandlerRequestData data) {
String jobid = data.getReqParams().get("jobid");
if (!failedQueue.containsKey(data.url)) {
BatchHandlerRequestData rd = new BatchHandlerRequestData(provider, data.getReqParams());
rd.setMsg(data.getMsg());
failedQueue.put(rd.url, rd);
failedJobs.put(jobid, rd.url);
}
jobs.put(jobid, -jobs.get(jobid));
}
public void registerNewBatch(BatchProvider handler, SolrParams params) {
String jobid = params.get("jobid");
if (isJobidFailed(jobid)) {
throw new SolrException(ErrorCode.BAD_REQUEST, "A job with jobid=" + jobid + " is marked as failed, I denounce obedience");
}
BatchHandlerRequestData rd = new BatchHandlerRequestData(handler, params);
if (!tbdQueue.containsKey(rd.url)) {
queuedIn++;
tbdQueue.put(rd.url, rd);
increaseJobCounter(jobid);
}
}
public void registerFinishedBatch(BatchHandlerRequestData data) {
String jobid = data.getReqParams().get("jobid");
decreaseJobCounter(jobid);
assert jobs.get(jobid) >= 0; // should never happen
}
public boolean hasMore() {
return tbdQueue.size() > 0 && stopped==false;
}
public void stop() {
stopped = true;
}
public void start() {
stopped = false;
}
public void reset() {
tbdQueue.clear();
failedQueue.clear();
queuedIn = 0;
queuedOut = 0;
}
public void reInsert(BatchHandlerRequestData rd) {
if (!tbdQueue.containsKey(rd.url)) {
queuedIn++;
tbdQueue.put(rd.url, rd);
}
}
public boolean isStopped() {
return stopped;
}
public boolean isJobidRegistered(String jobid) {
return jobs.containsKey(jobid);
}
public boolean isJobidFinished(String jobid) {
return jobs.containsKey(jobid) && jobs.get(jobid) == 0;
}
public boolean isJobidFailed(String jobid) {
return jobs.containsKey(jobid) && jobs.get(jobid) < 0;
}
public boolean isJobidRunning(String jobid) {
return jobs.containsKey(jobid) && jobs.get(jobid) > 0;
}
private void increaseJobCounter(String jobid) {
jobs.put(jobid, jobs.get(jobid)!=null ? jobs.get(jobid)+1 : 1);
}
public void decreaseJobCounter(String jobid) {
jobs.put(jobid, jobs.get(jobid)-1);
}
public int getTbdQueueSize() {
return tbdQueue.size();
}
public int getFailedQueueSize() {
return failedQueue.size();
}
public int getTotalQueueSize() {
return queuedIn;
}
public int getTotalFinishedSize() {
return queuedOut;
}
public List<String> getQueueDetails(int howMany, int type) {
ArrayList<String> out = new ArrayList<String>();
Map<String, BatchHandlerRequestData> queue = tbdQueue;
if (type == 0) {
queue = failedQueue;
}
int i = 0;
for (BatchHandlerRequestData d: queue.values()) {
out.add(d.toString());
i++;
if (i >= howMany) {
break;
}
}
return out;
}
public Object getErrorMessage(String jobid) {
if (!failedJobs.containsKey(jobid)) {
return "No message for jobid: " + jobid;
}
return failedQueue.get(failedJobs.get(jobid)).getMsg();
}
}