package org.codelibs.elasticsearch.taste.worker;
import java.util.List;
import java.util.NoSuchElementException;
import org.codelibs.elasticsearch.taste.common.LongPrimitiveIterator;
import org.codelibs.elasticsearch.taste.common.MemoryUtil;
import org.codelibs.elasticsearch.taste.recommender.ItemBasedRecommender;
import org.codelibs.elasticsearch.taste.recommender.RecommendedItem;
import org.codelibs.elasticsearch.taste.writer.ItemWriter;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.Loggers;
public class SimilarItemsWorker implements Runnable {
private static final ESLogger logger = Loggers
.getLogger(SimilarItemsWorker.class);
protected int number;
protected ItemBasedRecommender recommender;
protected LongPrimitiveIterator itemIDs;
protected int numOfMostSimilarItems;
protected ItemWriter writer;
private boolean running;
public SimilarItemsWorker(final int number,
final ItemBasedRecommender recommender,
final LongPrimitiveIterator itemIDs,
final int numOfMostSimilarItems, final ItemWriter writer) {
this.number = number;
this.recommender = recommender;
this.itemIDs = itemIDs;
this.numOfMostSimilarItems = numOfMostSimilarItems;
this.writer = writer;
}
@Override
public void run() {
int count = 0;
final long startTime = System.currentTimeMillis();
logger.info("Worker {} is started.", number);
long itemID;
running = true;
while ((itemID = nextId(itemIDs)) != -1 && running) {
if (Thread.currentThread().isInterrupted()) {
break;
}
try {
long time = System.nanoTime();
final List<RecommendedItem> recommendedItems = recommender
.mostSimilarItems(itemID, numOfMostSimilarItems);
writer.write(itemID, recommendedItems);
time = (System.nanoTime() - time) / 1000000;
if (logger.isDebugEnabled()) {
logger.debug("Item {} => Time: {} ms, Result: {}", itemID,
time, recommendedItems);
if (count % 100 == 0) {
MemoryUtil.logMemoryStatistics();
}
} else {
logger.info("Item {} => Time: {} ms, Result: {} items",
itemID, time, recommendedItems.size());
if (count % 1000 == 0) {
MemoryUtil.logMemoryStatistics();
}
}
} catch (final Exception e) {
if (!Thread.currentThread().isInterrupted()) {
logger.error("Item {} could not be processed.", e, itemID);
} else {
break;
}
}
count++;
}
logger.info("Worker {} processed {} items at {} ms. ", number, count,
System.currentTimeMillis() - startTime);
}
private long nextId(final LongPrimitiveIterator itemIDs) {
synchronized (itemIDs) {
try {
return itemIDs.nextLong();
} catch (final NoSuchElementException e) {
return -1;
}
}
}
public void stop() {
running = false;
}
}