@SuppressWarnings("unused")
private void asyncSetState(final Collection<INews> news, final State state, final boolean affectEquivalentNews, final boolean force) throws PersistenceException {
if (news.isEmpty())
return;
final NewsEventRunnable eventRunnable = new NewsEventRunnable();;
final Lock setStateLock = new ReentrantLock();
setStateLock.lock();
final Condition condition = setStateLock.newCondition();
fExecutorService.execute(new Runnable() {
public void run() {
Set<INews> changedNews = null;
try {
fWriteLock.lock();
setStateLock.lock();
if (affectEquivalentNews) {
/*
* Give extra 25% size to take into account news that have same guid or
* link.
*/
int capacity = news.size() + (news.size() / 4);
changedNews = new HashSet<INews>(capacity);
for (INews newsItem : news) {
if (newsItem.getId() == null)
throw new IllegalArgumentException("newsItem was never saved to the database"); //$NON-NLS-1$
List<INews> equivalentNews;
if (newsItem.getGuid() != null) {
equivalentNews = getNewsFromGuid(newsItem, true);
if (equivalentNews.isEmpty()) {
throw createIllegalException("No news were found with guid: " + //$NON-NLS-1$
newsItem.getGuid().getValue(), newsItem);
}
} else if (newsItem.getLinkAsText() != null) {
equivalentNews = getNewsFromLink(newsItem, true);
if (equivalentNews.isEmpty()) {
throw createIllegalException("No news were found with link: " + //$NON-NLS-1$
newsItem.getLinkAsText(), newsItem);
}
} else
equivalentNews = Collections.singletonList(newsItem);
changedNews.addAll(setState(equivalentNews, state, force));
}
} else {
changedNews = setState(news, state, force);
}
for (INews changedNewsItem : changedNews) {
//TODO Investigate why we add the news twice to the event runnable
//(we do the same in the finally block). This is harmless but
//wasteful. Also we should not release the news locks before firing
//the events.
((News) changedNewsItem).acquireReadLockSpecial();
eventRunnable.addCheckedUpdateEvent(createSaveEventTemplate(changedNewsItem));
}
condition.signal();
setStateLock.unlock();
save(changedNews);
fDb.commit();
} catch (Db4oException e) {
throw new PersistenceException(e);
} finally {
if (changedNews != null) {
for (INews changedNewsItem : changedNews) {
((News) changedNewsItem).releaseReadLockSpecial();
eventRunnable.addCheckedUpdateEvent(createSaveEventTemplate(changedNewsItem));
}
}
DBHelper.cleanUpEvents();
fWriteLock.unlock();
}
}
});
try {
condition.awaitUninterruptibly();
} finally {
setStateLock.unlock();
}
eventRunnable.run();
}