package com.couchbase.loadgen.client; import java.util.LinkedList; import java.util.List; import com.couchbase.loadgen.Config; import com.couchbase.loadgen.DataStore; import com.couchbase.loadgen.cluster.ClusterManager; import com.couchbase.loadgen.exception.DataStoreException; import com.couchbase.loadgen.exception.UnknownDataStoreException; import com.couchbase.loadgen.memcached.MemcachedFactory; import com.couchbase.loadgen.workloads.Workload; /** * A thread pool is a group of a limited number of threads that are used to * execute tasks. */ public class ClientThreadPool extends ThreadGroup { private static int threadPoolID; private List<PooledThread> threads; private boolean isAlive; private int threadID; private int ops; private int lastTarget; private long st; private long opsdone; public ClientThreadPool(int threadcount, Workload workload, String dbname) { super("ThreadPool-" + (threadPoolID++)); this.threads = new LinkedList<PooledThread>(); if (((Boolean)Config.getConfig().get(Config.DO_TRANSACTIONS)).booleanValue()) { this.ops = ((Integer)Config.getConfig().get(Config.OP_COUNT)).intValue(); } else { this.ops = ((Integer)Config.getConfig().get(Config.RECORD_COUNT)).intValue(); } this.lastTarget = ((Integer)Config.getConfig().get(Config.TARGET)); this.opsdone = 0; this.st = System.currentTimeMillis(); setDaemon(true); isAlive = true; for (int i = 0; i < threadcount; i++) { DataStore db = null; try { if (workload instanceof com.couchbase.loadgen.workloads.MemcachedCoreWorkload) db = MemcachedFactory.newMemcached(dbname); else { System.out.println("Invalid Database/Workload Combination"); System.exit(0); } db.init(); } catch (UnknownDataStoreException e) { System.out.println("Unknown DataStore " + dbname); System.exit(0); } catch (DataStoreException e) { e.printStackTrace(); System.exit(0); } PooledThread thread = new PooledThread(workload, db); threads.add(thread); thread.start(); } } protected synchronized boolean getTask() { int target = ((Integer) Config.getConfig().get(Config.TARGET)).intValue() / ClusterManager.getManager().getClusterSize(); if (target != lastTarget) { lastTarget = target; opsdone = 0; st = System.currentTimeMillis(); } if (target > 0) { while ((System.currentTimeMillis() - st) / 1000 < (((double)opsdone) / target)) { try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } } if (!isAlive) { return false; } else if (ops == -1){ opsdone++; return true; } else if (ops <= opsdone) { return false; } else { opsdone++; return true; } } public synchronized void close() { if (isAlive) { isAlive = false; } } public void join() { // wait for all threads to finish Thread[] threads = new Thread[activeCount()]; int count = enumerate(threads); for (int i = 0; i < count; i++) { try { threads[i].join(); } catch (InterruptedException ex) { } } } /** * A PooledThread is a Thread in a ThreadPool group, designed to run tasks * (Runnables). */ private class PooledThread extends Thread { private Workload workload; private DataStore db; //private BlockingQueue opqueue; public PooledThread(Workload workload, DataStore db) { super(ClientThreadPool.this, "PooledThread-" + (threadID++)); this.workload = workload; this.db = db; } public void run() { while (!isInterrupted() && getTask()) { //System.out.println(getId() + " is doing teansaction"); workload.doOperation(db); } // TODO: Probably shouldn't be here try { db.cleanup(); } catch (DataStoreException e) { e.printStackTrace(); } System.out.println("Client Thread Done"); } } }