package ninja.ugly.prevail.datamodel;
import com.google.common.base.Optional;
import org.hamcrest.Matchers;
import org.junit.Test;
import org.mockito.Mockito;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import ninja.ugly.prevail.Key;
import ninja.ugly.prevail.KeyValueChunk;
import ninja.ugly.prevail.Value;
import ninja.ugly.prevail.chunk.Chunk;
import ninja.ugly.prevail.chunk.DefaultChunk;
import ninja.ugly.prevail.chunk.QueryResult;
import ninja.ugly.prevail.event.Event;
import ninja.ugly.prevail.event.factory.DeleteEventFactory;
import ninja.ugly.prevail.event.factory.InsertEventFactory;
import ninja.ugly.prevail.event.factory.QueryEventFactory;
import ninja.ugly.prevail.event.factory.UpdateEventFactory;
import ninja.ugly.prevail.exception.DeleteException;
import ninja.ugly.prevail.exception.InsertException;
import ninja.ugly.prevail.exception.QueryException;
import ninja.ugly.prevail.exception.UpdateException;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.any;
import static org.hamcrest.Matchers.everyItem;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.argThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class DataModelTest {
private final DataModel mDataModel = new DataModel();
private final Chunk<Key, Value> mChunk = mock(Chunk.class);
private final Key mKey = mock(Key.class);
private final Value mValue = mock(Value.class);
@Test(expected = NullPointerException.class)
public void testCannotAddNullChunk() {
mDataModel.addChunk("segment", null);
}
@Test
public void testDeleteBySegmentDelegatesToAddedChunkWithSegment() throws DeleteException, TimeoutException, InterruptedException, ExecutionException {
mDataModel.addChunk("segment", mChunk);
mDataModel.delete("segment", mKey).get(1, TimeUnit.SECONDS);
verify(mChunk).delete(argThat(is(mKey)), Mockito.<DeleteEventFactory>anyVararg());
}
@Test
public void testDeleteBySegmentDelegatesToAllChunksAddedWithSegment() throws DeleteException, TimeoutException, InterruptedException, ExecutionException {
final Chunk chunk1 = mock(Chunk.class);
final Chunk chunk2 = mock(Chunk.class);
mDataModel.addChunk("segment", chunk1);
mDataModel.addChunk("segment", chunk2);
mDataModel.delete("segment", mKey).get(1, TimeUnit.SECONDS);
verify(chunk1).delete(argThat(is(mKey)), Mockito.<DeleteEventFactory>anyVararg());
verify(chunk2).delete(argThat(is(mKey)), Mockito.<DeleteEventFactory>anyVararg());
}
@Test
public void testDeleteBySegmentWithSegmentNotAddedToDataModelReturnsEmptyFuture() throws DeleteException, TimeoutException, InterruptedException, ExecutionException {
final List<Integer> integers = mDataModel.delete("some segment not in data model", mKey).get(1, TimeUnit.SECONDS);
assertThat(integers, hasSize(0));
}
@Test
public void testDeleteBySegmentWithEventFactoryDelegatesToAddedChunk() throws DeleteException, TimeoutException, InterruptedException, ExecutionException {
final DeleteEventFactory eventFactory = mock(DeleteEventFactory.class);
when(eventFactory.startEvent(argThat(is(mKey)))).thenReturn(Optional.<Event>absent());
when(eventFactory.endEvent(argThat(is(mKey)), anyInt())).thenReturn(Optional.<Event>absent());
mDataModel.addChunk("segment", mChunk);
mDataModel.delete("segment", mKey, eventFactory).get(1, TimeUnit.SECONDS);
verify(mChunk).delete(argThat(is(mKey)), Mockito.<DeleteEventFactory>anyVararg());
}
@Test
public void testDeleteDelegatesToAddedChunk() throws DeleteException, TimeoutException, InterruptedException, ExecutionException {
mDataModel.addChunk(mChunk);
mDataModel.delete(mKey).get(1, TimeUnit.SECONDS);
verify(mChunk).delete(argThat(is(mKey)), Mockito.<DeleteEventFactory>anyVararg());
}
@Test
public void testDeleteIsExecutedOnBackgroundThread() throws InterruptedException, TimeoutException, DeleteException, ExecutionException {
final Thread testThread = Thread.currentThread();
final Chunk<Key, Value> chunk = new Chunk.EmptyChunk<Key, Value>() {
@Override
public int delete(final Key key, final DeleteEventFactory... eventFactories) throws DeleteException {
assertThat(Thread.currentThread(), is(not(testThread)));
return super.delete(key, eventFactories);
}
};
mDataModel.addChunk(chunk);
mDataModel.delete(mKey).get(1, TimeUnit.SECONDS);
}
@Test
public void testDeleteIsExecutedOnChunkThread() throws InterruptedException, TimeoutException, DeleteException, ExecutionException {
final Thread[] chunkThreadFromFactory = new Thread[1];
final ExecutorService executor = getExecutorAndThread(chunkThreadFromFactory);
final Chunk<Key, Value> chunk = new Chunk.EmptyChunk<Key, Value>() {
@Override
public int delete(final Key key, final DeleteEventFactory... eventFactories) throws DeleteException {
assertThat(Thread.currentThread(), is(chunkThreadFromFactory[0]));
return super.delete(key, eventFactories);
}
};
mDataModel.addChunk(chunk, executor);
mDataModel.delete(mKey).get(1, TimeUnit.SECONDS);
}
@Test
public void testDeleteOnMultipleChunksReturnsResultsInFuture() throws TimeoutException, InterruptedException, ExecutionException, DeleteException {
final KeyValueChunk.Deleter<Key> deleter = mock(KeyValueChunk.Deleter.class);
when(deleter.delete(argThat(is(mKey)), argThat(is(any(DefaultChunk.OnProgressUpdateListener.class))))).thenReturn(1);
mDataModel.addChunk(new KeyValueChunk(null, null, null, deleter));
mDataModel.addChunk(new KeyValueChunk(null, null, null, deleter));
final List<Integer> results = mDataModel.delete(mKey).get(1, TimeUnit.SECONDS);
assertThat(results, hasSize(2));
assertThat(results, everyItem(is(1)));
}
@Test
public void testDeleteOnSingleChunkReturnsResultInFuture() throws TimeoutException, InterruptedException, ExecutionException, DeleteException {
final KeyValueChunk.Deleter<Key> deleter = mock(KeyValueChunk.Deleter.class);
when(deleter.delete(argThat(is(mKey)), argThat(is(any(DefaultChunk.OnProgressUpdateListener.class))))).thenReturn(1);
mDataModel.addChunk(new KeyValueChunk(null, null, null, deleter));
final List<Integer> results = mDataModel.delete(mKey).get(1, TimeUnit.SECONDS);
assertThat(results, hasSize(1));
assertThat(results, everyItem(is(1)));
}
@Test
public void testInsertBySegmentDelegatesToAddedChunkWithSegment() throws InsertException, TimeoutException, InterruptedException, ExecutionException {
mDataModel.addChunk("segment", mChunk);
mDataModel.insert("segment", mValue).get(1, TimeUnit.SECONDS);
verify(mChunk).insert(argThat(is(mValue)), Mockito.<InsertEventFactory>anyVararg());
}
@Test
public void testInsertBySegmentDelegatesToAllChunksAddedWithSegment() throws InsertException, TimeoutException, InterruptedException, ExecutionException {
final Chunk chunk1 = mock(Chunk.class);
final Chunk chunk2 = mock(Chunk.class);
mDataModel.addChunk("segment", chunk1);
mDataModel.addChunk("segment", chunk2);
mDataModel.insert("segment", mValue).get(1, TimeUnit.SECONDS);
verify(chunk1).insert(argThat(is(mValue)), Mockito.<InsertEventFactory>anyVararg());
verify(chunk2).insert(argThat(is(mValue)), Mockito.<InsertEventFactory>anyVararg());
}
@Test
public void testInsertBySegmentWithSegmentNotAddedToDataModelReturnsEmptyFuture() throws InsertException, TimeoutException, InterruptedException, ExecutionException {
final List<Object> keys = mDataModel.insert("some segment not in data model", mValue).get(1, TimeUnit.SECONDS);
assertThat(keys, hasSize(0));
}
@Test
public void testInsertBySegmentWithEventFactoryDelegatesToAddedChunk() throws InsertException, TimeoutException, InterruptedException, ExecutionException {
final InsertEventFactory<Key, Value> eventFactory = mock(InsertEventFactory.class);
when(eventFactory.startEvent(argThat(is(mValue)))).thenReturn(Optional.<Event>absent());
when(eventFactory.endEvent(argThat(any(Key.class)), argThat(is(mValue)))).thenReturn(Optional.<Event>absent());
mDataModel.addChunk("segment", mChunk);
mDataModel.insert("segment", mValue, eventFactory).get(1, TimeUnit.SECONDS);
verify(mChunk).insert(argThat(is(mValue)), Mockito.<InsertEventFactory>anyVararg());
}
@Test
public void testInsertDelegatesToAddedChunk() throws InsertException, TimeoutException, InterruptedException, ExecutionException {
mDataModel.addChunk(mChunk);
mDataModel.insert(mValue).get(1, TimeUnit.SECONDS);
verify(mChunk).insert(argThat(is(mValue)));
}
@Test
public void testInsertIsExecutedOnBackgroundThread() throws InterruptedException, TimeoutException, ExecutionException, InsertException {
final Thread testThread = Thread.currentThread();
final Chunk<Key, Value> chunk = new Chunk.EmptyChunk<Key, Value>() {
@Override
public Key insert(final Value value, final InsertEventFactory... eventFactories) throws InsertException {
assertThat(Thread.currentThread(), is(not(testThread)));
return super.insert(value, eventFactories);
}
};
mDataModel.addChunk(chunk);
mDataModel.insert(mValue).get(1, TimeUnit.SECONDS);
}
@Test
public void testInsertIsExecutedOnChunkThread() throws InterruptedException, TimeoutException, DeleteException, ExecutionException {
final Thread[] chunkThreadFromFactory = new Thread[1];
final ExecutorService executor = getExecutorAndThread(chunkThreadFromFactory);
final Chunk<Key, Value> chunk = new Chunk.EmptyChunk<Key, Value>() {
@Override
public Key insert(final Value value, final InsertEventFactory... eventFactories) throws InsertException {
assertThat(Thread.currentThread(), is(chunkThreadFromFactory[0]));
return super.insert(value, eventFactories);
}
};
mDataModel.addChunk(chunk, executor);
mDataModel.delete(mKey).get(1, TimeUnit.SECONDS);
}
@Test
public void testInsertOnMultipleChunksReturnsKeysInFuture() throws InsertException, TimeoutException, InterruptedException, ExecutionException {
final KeyValueChunk.Inserter<Key, Value> inserter = mock(KeyValueChunk.Inserter.class);
when(inserter.insert(argThat(is(mValue)), argThat(is(any(DefaultChunk.OnProgressUpdateListener.class))))).thenReturn(mKey);
mDataModel.addChunk(new KeyValueChunk<Key, Value>(inserter, null, null, null));
mDataModel.addChunk(new KeyValueChunk<Key, Value>(inserter, null, null, null));
final List<Object> keys = mDataModel.insert(mValue).get(1, TimeUnit.SECONDS);
assertThat(keys, hasSize(2));
assertThat(keys, everyItem(is((Object) mKey)));
}
@Test
public void testInsertOnSingleChunkReturnsKeyInFuture() throws InsertException, TimeoutException, InterruptedException, ExecutionException {
final KeyValueChunk.Inserter<Key, Value> inserter = mock(KeyValueChunk.Inserter.class);
when(inserter.insert(argThat(is(mValue)), argThat(is(any(DefaultChunk.OnProgressUpdateListener.class))))).thenReturn(mKey);
mDataModel.addChunk(new KeyValueChunk<Key, Value>(inserter, null, null, null));
final List<Object> keys = mDataModel.insert(mValue).get(1, TimeUnit.SECONDS);
assertThat(keys, hasSize(1));
assertThat(keys, hasItem(mKey));
}
@Test
public void testQueryBySegmentDelegatesToAddedChunkWithSegment() throws QueryException, InterruptedException, TimeoutException, ExecutionException {
mDataModel.addChunk("segment", mChunk);
mDataModel.query("segment", mKey).get(1, TimeUnit.SECONDS);
verify(mChunk).query(argThat(is(mKey)), Mockito.<QueryEventFactory>anyVararg());
}
@Test
public void testQueryBySegmentDelegatesToAddedFirstAddedChunkWithSegmentWhenMultipleChunksAreAdded() throws QueryException, InterruptedException, TimeoutException, ExecutionException {
mDataModel.addChunk("segment1", mChunk);
mDataModel.addChunk("segment2", mock(Chunk.class));
mDataModel.query("segment1", mKey).get(1, TimeUnit.SECONDS);
verify(mChunk).query(argThat(is(mKey)), Mockito.<QueryEventFactory>anyVararg());
}
@Test
public void testQueryBySegmentDelegatesToAddedSecondAddedChunkWithSegmentWhenMultipleChunksAreAdded() throws QueryException, InterruptedException, TimeoutException, ExecutionException {
mDataModel.addChunk("segment1", mock(Chunk.class));
mDataModel.addChunk("segment2", mChunk);
mDataModel.query("segment2", mKey).get(1, TimeUnit.SECONDS);
verify(mChunk).query(argThat(is(mKey)), Mockito.<QueryEventFactory>anyVararg());
}
@Test
public void testQueryBySegmentDelegatesToAllChunksAddedWithSegment() throws QueryException, InterruptedException, TimeoutException, ExecutionException {
final Chunk chunk1 = mock(Chunk.class);
final Chunk chunk2 = mock(Chunk.class);
mDataModel.addChunk("segment", chunk1);
mDataModel.addChunk("segment", chunk2);
mDataModel.query("segment", mKey).get(1, TimeUnit.SECONDS);
verify(chunk1).query(argThat(is(mKey)), Mockito.<QueryEventFactory>anyVararg());
verify(chunk2).query(argThat(is(mKey)), Mockito.<QueryEventFactory>anyVararg());
}
@Test
public void testQueryBySegmentWithSegmentNotAddedToDataModelReturnsEmptyFuture() throws InterruptedException, TimeoutException, QueryException, ExecutionException {
final List<QueryResult<Object>> queryResults = mDataModel.query("some segment not in data model", mKey).get(1, TimeUnit.SECONDS);
assertThat(queryResults, hasSize(0));
}
@Test
public void testQueryBySegmentWithEventFactoryDelegatesToAddedChunk() throws QueryException, InterruptedException, TimeoutException, ExecutionException {
final QueryEventFactory<Key, Value> eventFactory = mock(QueryEventFactory.class);
when(eventFactory.startEvent(argThat(is(mKey)))).thenReturn(Optional.<Event>absent());
when(eventFactory.endEvent(argThat(is(mKey)), argThat(any(QueryResult.class)))).thenReturn(Optional.<Event>absent());
mDataModel.addChunk("segment", mChunk);
mDataModel.query("segment", mKey, eventFactory).get(1, TimeUnit.SECONDS);
verify(mChunk).query(argThat(is(mKey)), argThat(is(eventFactory)));
}
@Test
public void testQueryDelegatesToAddedChunk() throws QueryException, InterruptedException, TimeoutException, ExecutionException {
mDataModel.addChunk(mChunk);
mDataModel.query(mKey).get(1, TimeUnit.SECONDS);
verify(mChunk).query(argThat(is(mKey)), Mockito.<QueryEventFactory>anyVararg());
}
@Test
public void testQueryIsExecutedOnBackgroundThread() throws InterruptedException, TimeoutException, QueryException, ExecutionException {
final Thread testThread = Thread.currentThread();
final Chunk<Key, Value> chunk = new Chunk.EmptyChunk<Key, Value>() {
@Override
public QueryResult query(final Key key, final QueryEventFactory... eventFactories) throws QueryException {
assertThat(Thread.currentThread(), is(not(testThread)));
return super.query(key, eventFactories);
}
};
mDataModel.addChunk(chunk);
mDataModel.query(mKey).get(1, TimeUnit.SECONDS);
}
@Test
public void testQueryIsExecutedOnChunkThread() throws InterruptedException, TimeoutException, QueryException, ExecutionException {
final Thread[] chunkThreadFromFactory = new Thread[1];
final ExecutorService executor = getExecutorAndThread(chunkThreadFromFactory);
final Chunk<Key, Value> chunk = new Chunk.EmptyChunk<Key, Value>() {
@Override
public QueryResult query(final Key key, final QueryEventFactory... eventFactories) throws QueryException {
assertThat(Thread.currentThread(), is(chunkThreadFromFactory[0]));
return super.query(key, eventFactories);
}
};
mDataModel.addChunk(chunk, executor);
mDataModel.query(mKey).get(1, TimeUnit.SECONDS);
}
@Test
public void testQueryOnMultipleChunksReturnsResultsInFuture() throws TimeoutException, InterruptedException, ExecutionException, QueryException {
final KeyValueChunk.Queryer<Key, Value> queryer = mock(KeyValueChunk.Queryer.class);
when(queryer.query(argThat(is(mKey)), argThat(is(any(DefaultChunk.OnProgressUpdateListener.class))))).thenReturn(new QueryResult.SingletonQueryResult<Value>(mValue));
mDataModel.addChunk(new KeyValueChunk<Key, Value>(null, null, queryer, null));
mDataModel.addChunk(new KeyValueChunk<Key, Value>(null, null, queryer, null));
final List<QueryResult<Object>> results = mDataModel.query(mKey).get(1, TimeUnit.SECONDS);
assertThat(results, hasSize(2));
assertThat(results.get(0).iterator().next(), Matchers.<Object>is(mValue));
assertThat(results.get(1).iterator().next(), Matchers.<Object>is(mValue));
}
@Test
public void testQueryOnSingleChunkReturnsResultInFuture() throws TimeoutException, InterruptedException, ExecutionException, QueryException {
final KeyValueChunk.Queryer<Key, Value> queryer = mock(KeyValueChunk.Queryer.class);
when(queryer.query(argThat(is(mKey)), argThat(is(any(DefaultChunk.OnProgressUpdateListener.class))))).thenReturn(new QueryResult.SingletonQueryResult<Value>(mValue));
mDataModel.addChunk(new KeyValueChunk<Key, Value>(null, null, queryer, null));
final List<QueryResult<Object>> results = mDataModel.query(mKey).get(1, TimeUnit.SECONDS);
assertThat(results, hasSize(1));
assertThat(results.get(0).iterator().next(), Matchers.<Object>is(mValue));
}
@Test
public void testUpdateBySegmentDelegatesToAddedChunkWithSegment() throws UpdateException, TimeoutException, InterruptedException, ExecutionException {
mDataModel.addChunk("segment", mChunk);
mDataModel.update("segment", mKey, mValue).get(1, TimeUnit.SECONDS);
verify(mChunk).update(argThat(is(mKey)), argThat(is(mValue)), Mockito.<UpdateEventFactory>anyVararg());
}
@Test
public void testUpdateBySegmentDelegatesToAllChunksAddedWithSegment() throws UpdateException, TimeoutException, InterruptedException, ExecutionException {
final Chunk chunk1 = mock(Chunk.class);
final Chunk chunk2 = mock(Chunk.class);
mDataModel.addChunk("segment", chunk1);
mDataModel.addChunk("segment", chunk2);
mDataModel.update("segment", mKey, mValue).get(1, TimeUnit.SECONDS);
verify(chunk1).update(argThat(is(mKey)), argThat(is(mValue)), Mockito.<UpdateEventFactory>anyVararg());
verify(chunk2).update(argThat(is(mKey)), argThat(is(mValue)), Mockito.<UpdateEventFactory>anyVararg());
}
@Test
public void testUpdateBySegmentWithSegmentNotAddedToDataModelReturnsEmptyFuture() throws UpdateException, TimeoutException, InterruptedException, ExecutionException {
final List<Integer> integers = mDataModel.update("some segment not in data model", mKey, mValue).get(1, TimeUnit.SECONDS);
assertThat(integers, hasSize(0));
}
@Test
public void testUpdateBySegmentWithEventFactoryDelegatesToAddedChunk() throws UpdateException, TimeoutException, InterruptedException, ExecutionException {
final UpdateEventFactory eventFactory = mock(UpdateEventFactory.class);
when(eventFactory.startEvent(argThat(is(mKey)), argThat(is(mValue)))).thenReturn(Optional.<Event>absent());
when(eventFactory.endEvent(argThat(is(mKey)), argThat(is(mValue)), anyInt())).thenReturn(Optional.<Event>absent());
mDataModel.addChunk("segment", mChunk);
mDataModel.update("segment", mKey, mValue, eventFactory).get(1, TimeUnit.SECONDS);
verify(mChunk).update(argThat(is(mKey)), argThat(is(mValue)), Mockito.<UpdateEventFactory>anyVararg());
}
@Test
public void testUpdateDelegatesToAddedChunk() throws UpdateException, TimeoutException, InterruptedException, ExecutionException {
mDataModel.addChunk(mChunk);
mDataModel.update(mKey, mValue).get(1, TimeUnit.SECONDS);
verify(mChunk).update(argThat(is(mKey)), argThat(is(mValue)), Mockito.<UpdateEventFactory>anyVararg());
}
@Test
public void testUpdateIsExecutedOnBackgroundThread() throws InterruptedException, TimeoutException, UpdateException, ExecutionException {
final Thread testThread = Thread.currentThread();
final Chunk<Key, Value> chunk = new Chunk.EmptyChunk<Key, Value>() {
@Override
public int update(final Key key, final Value value, final UpdateEventFactory... eventFactories) throws UpdateException {
assertThat(Thread.currentThread(), is(not(testThread)));
return super.update(key, value, eventFactories);
}
};
mDataModel.addChunk(chunk);
mDataModel.update(mKey, mValue).get(1, TimeUnit.SECONDS);
}
@Test
public void testUpdateIsExecutedOnChunkThread() throws InterruptedException, TimeoutException, UpdateException, ExecutionException {
final Thread[] chunkThreadFromFactory = new Thread[1];
final ExecutorService executor = getExecutorAndThread(chunkThreadFromFactory);
final Chunk<Key, Value> chunk = new Chunk.EmptyChunk<Key, Value>() {
@Override
public int update(final Key key, final Value value, final UpdateEventFactory... eventFactories) throws UpdateException {
assertThat(Thread.currentThread(), is(chunkThreadFromFactory[0]));
return super.update(key, value, eventFactories);
}
};
mDataModel.addChunk(chunk, executor);
mDataModel.update(mKey, mValue).get(1, TimeUnit.SECONDS);
}
@Test
public void testUpdateOnMultipleChunksReturnsResultsInFuture() throws TimeoutException, InterruptedException, ExecutionException, UpdateException {
final KeyValueChunk.Updater<Key, Value> updater = mock(KeyValueChunk.Updater.class);
when(updater.update(argThat(is(mKey)), argThat(is(mValue)), argThat(is(any(DefaultChunk.OnProgressUpdateListener.class))))).thenReturn(1);
mDataModel.addChunk(new KeyValueChunk<Key, Value>(null, updater, null, null));
mDataModel.addChunk(new KeyValueChunk<Key, Value>(null, updater, null, null));
final List<Integer> results = mDataModel.update(mKey, mValue).get(1, TimeUnit.SECONDS);
assertThat(results, hasSize(2));
assertThat(results, everyItem(is(1)));
}
@Test
public void testUpdateOnSingleChunkReturnsResultInFuture() throws TimeoutException, InterruptedException, ExecutionException, UpdateException {
final KeyValueChunk.Updater<Key, Value> updater = mock(KeyValueChunk.Updater.class);
when(updater.update(argThat(is(mKey)), argThat(is(mValue)), argThat(is(any(DefaultChunk.OnProgressUpdateListener.class))))).thenReturn(1);
mDataModel.addChunk(new KeyValueChunk<Key, Value>(null, updater, null, null));
final List<Integer> results = mDataModel.update(mKey, mValue).get(1, TimeUnit.SECONDS);
assertThat(results, hasSize(1));
assertThat(results, everyItem(is(1)));
}
private ExecutorService getExecutorAndThread(final Thread[] chunkThreadFromFactory) {
return Executors.newSingleThreadExecutor(new ThreadFactory() {
@Override
public Thread newThread(final Runnable r) {
final Thread t = new Thread(r, "Chunk Thread");
chunkThreadFromFactory[0] = t;
return t;
}
});
}
}