package net.johnewart.gearman.client;
import net.johnewart.gearman.common.Job;
import net.johnewart.gearman.common.interfaces.GearmanFunction;
import net.johnewart.gearman.common.interfaces.GearmanWorker;
import net.johnewart.gearman.net.Connection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* A multi-threaded network-connected worker pool.
*/
public class NetworkGearmanWorkerPool implements GearmanWorker {
private int threadCount;
private final List<Connection> connectionList;
private final Set<GearmanWorkerThread> threadSet;
private final Set<GearmanWorker> workerSet;
private final AtomicBoolean isActive;
private static Logger LOG = LoggerFactory.getLogger(NetworkGearmanWorkerPool.class);
private NetworkGearmanWorkerPool() {
this.threadCount = 1;
this.connectionList = new LinkedList<>();
this.threadSet = new HashSet<>();
this.workerSet = new HashSet<>();
this.isActive = new AtomicBoolean(true);
}
private void initialize() {
for(int i = 0; i < threadCount; i++) {
NetworkGearmanWorker.Builder workerBuilder = new NetworkGearmanWorker.Builder();
for(Connection c : connectionList) {
workerBuilder.withConnection(new Connection(c));
}
NetworkGearmanWorker worker = workerBuilder.build();
threadSet.add(new GearmanWorkerThread(worker));
workerSet.add(worker);
}
}
@Override
public void doWork() {
int counter = 0;
for(GearmanWorkerThread t : threadSet) {
LOG.debug("Starting worker #" + counter++);
t.start();
}
for(GearmanWorkerThread t : threadSet) {
try {
t.join();
LOG.debug("Thread " + t.getId() + " joined.");
} catch (InterruptedException e) {
LOG.error("Error waiting for worker thread: ", e);
}
}
}
@Override
public void stopWork() {
for(GearmanWorker worker : workerSet) {
worker.stopWork();
}
}
@Override
public void sendData(Job job, byte[] data) throws IOException {
// NOOP -- handled by worker
}
@Override
public void sendStatus(Job job, int numerator, int denominator) throws IOException {
// NOOP -- handled by worker
}
@Override
public void sendWarning(Job job, byte[] warning) throws IOException {
// NOOP -- handled by worker
}
@Override
public void registerCallback(String functionName, GearmanFunction function) {
for(GearmanWorkerThread t : threadSet) {
t.getWorker().registerCallback(functionName, function);
}
}
public static class Builder {
private NetworkGearmanWorkerPool pool;
public Builder() {
this.pool = new NetworkGearmanWorkerPool();
}
public NetworkGearmanWorkerPool build() {
pool.initialize();
return pool;
}
public Builder threads(int value) {
pool.threadCount = value;
return this;
}
public Builder withConnection(Connection c) {
pool.connectionList.add(c);
return this;
}
}
static class GearmanWorkerThread extends Thread {
private NetworkGearmanWorker worker;
public GearmanWorkerThread(NetworkGearmanWorker worker) {
this.worker = worker;
}
public NetworkGearmanWorker getWorker() {
return worker;
}
@Override
public void run() {
worker.doWork();
}
}
}