Merge pull request #171 from Athou/jklm

Use jkeylockmanager for entry update locking
This commit is contained in:
Athou
2013-05-24 03:04:03 -07:00
4 changed files with 31 additions and 78 deletions

View File

@@ -1,69 +0,0 @@
package com.commafeed.backend;
import java.lang.ref.WeakReference;
import java.util.WeakHashMap;
// A map that creates and stores lock objects for arbitrary keys values.
// Lock objects which are no longer referenced are automatically released during garbage collection.
// Author: Christian d'Heureuse, www.source-code.biz
// Based on IdMutexProvider by McDowell, http://illegalargumentexception.blogspot.ch/2008/04/java-synchronizing-on-transient-id.html
// See also http://stackoverflow.com/questions/5639870/simple-java-name-based-locks
public class LockMap<KEY> {
private WeakHashMap<KeyWrapper<KEY>, WeakReference<KeyWrapper<KEY>>> map;
public LockMap() {
map = new WeakHashMap<KeyWrapper<KEY>, WeakReference<KeyWrapper<KEY>>>();
}
// Returns a lock object for the specified key.
public synchronized Object get(KEY key) {
if (key == null) {
throw new NullPointerException();
}
KeyWrapper<KEY> newKeyWrapper = new KeyWrapper<KEY>(key);
WeakReference<KeyWrapper<KEY>> ref = map.get(newKeyWrapper);
KeyWrapper<KEY> oldKeyWrapper = (ref == null) ? null : ref.get();
if (oldKeyWrapper != null) {
return oldKeyWrapper;
}
map.put(newKeyWrapper,
new WeakReference<KeyWrapper<KEY>>(newKeyWrapper));
return newKeyWrapper;
}
// Returns the number of used entries in the map.
public synchronized int size() {
return map.size();
}
// KeyWrapper wraps a key value and is used in three ways:
// - as the key for the internal WeakHashMap
// - as the value for the internal WeakHashMap, additionally wrapped in a
// WeakReference
// - as the lock object associated to the key
private static class KeyWrapper<KEY> {
private KEY key;
private int hashCode;
public KeyWrapper(KEY key) {
this.key = key;
hashCode = key.hashCode();
}
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof KeyWrapper) {
return ((KeyWrapper<?>) obj).key.equals(key);
}
return false;
}
public int hashCode() {
return hashCode;
}
}
} // end class LockMap

View File

@@ -14,7 +14,6 @@ import javax.inject.Singleton;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.commafeed.backend.LockMap;
import com.commafeed.backend.dao.FeedDAO;
import com.commafeed.backend.dao.FeedSubscriptionDAO;
import com.commafeed.backend.model.ApplicationSettings;
@@ -26,13 +25,17 @@ import com.commafeed.backend.pubsubhubbub.SubscriptionHandler;
import com.commafeed.backend.services.ApplicationSettingsService;
import com.commafeed.backend.services.FeedUpdateService;
import de.jkeylockmanager.manager.KeyLockManager;
import de.jkeylockmanager.manager.KeyLockManagers;
import de.jkeylockmanager.manager.LockCallback;
@Singleton
public class FeedRefreshUpdater {
protected static Logger log = LoggerFactory
.getLogger(FeedRefreshUpdater.class);
private static LockMap<String> lockMap = new LockMap<String>();
private static final KeyLockManager lockManager = KeyLockManagers.newLock();
@Inject
FeedUpdateService feedUpdateService;
@@ -107,11 +110,14 @@ public class FeedRefreshUpdater {
}
private void updateEntry(Feed feed, FeedEntry entry,
List<FeedSubscription> subscriptions) {
synchronized (lockMap.get(entry.getGuid())) {
feedUpdateService.updateEntry(feed, entry, subscriptions);
}
private void updateEntry(final Feed feed, final FeedEntry entry,
final List<FeedSubscription> subscriptions) {
lockManager.executeLocked(entry.getGuid(), new LockCallback() {
@Override
public void doInLock() throws Exception {
feedUpdateService.updateEntry(feed, entry, subscriptions);
}
});
}
private void handlePubSub(final Feed feed) {

View File

@@ -46,8 +46,9 @@ public class UserService {
PasswordEncryptionService encryptionService;
public User login(String name, String password) {
Preconditions.checkNotNull(name);
Preconditions.checkNotNull(password);
if (name == null || password == null) {
return null;
}
User user = userDAO.findByName(name);
if (user != null && !user.isDisabled()) {