/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package com.smartitengineering.user.service.impl.cache; import com.google.inject.Inject; import com.google.inject.name.Named; import com.smartitengineering.dao.common.cache.CacheServiceProvider; import com.smartitengineering.dao.common.cache.Lock; import com.smartitengineering.dao.common.cache.Mutex; import com.smartitengineering.dao.common.cache.impl.CacheAPIFactory; import com.smartitengineering.user.domain.Privilege; import com.smartitengineering.user.service.PrivilegeService; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * * @author imyousuf */ public class PrivilegeServiceCacheImpl implements PrivilegeService { @Inject @Named("primaryService") private PrivilegeService primaryService; @Inject private CacheServiceProvider<Long, Privilege> cacheProvider; @Inject private CacheServiceProvider<String, Long> nameCacheProvider; private transient final Logger logger = LoggerFactory.getLogger(getClass()); private final Mutex<Long> mutex = CacheAPIFactory.<Long>getMutex(); @Override public void create(Privilege privilege) { //Simply delegate primaryService.create(privilege); } @Override public void delete(Privilege privilege) { //First update then delete if update successful! try { primaryService.delete(privilege); expireFromCache(privilege); } catch (RuntimeException exception) { logger.info("Could not update thus invalidate cache!", exception); throw exception; } } @Override public void update(Privilege privilege) { //First update then delete if update successful! try { primaryService.update(privilege); expireFromCache(privilege); } catch (RuntimeException exception) { logger.info("Could not update thus invalidate cache!", exception); throw exception; } } @Override public Set<Privilege> getPrivilegesByIds(Long... ids) { return getPrivilegesByIds(Arrays.asList(ids)); } @Override public Set<Privilege> getPrivilegesByIds(List<Long> ids) { if (ids == null || ids.isEmpty()) { return Collections.emptySet(); } Map<Long, Privilege> results = new HashMap<Long, Privilege>(ids.size()); List<Long> missedIds = new ArrayList<Long>(ids); results.putAll(cacheProvider.retrieveFromCache(missedIds)); for (Long id : results.keySet()) { missedIds.remove(id); } Map<Long, Lock<Long>> locks = new HashMap<Long, Lock<Long>>(missedIds.size()); for (Long missedId : missedIds) { boolean attained = false; while (!attained) { try { locks.put(missedId, mutex.acquire(missedId)); attained = true; } catch (Exception ex) { logger.warn("Could not acquire lock for privilege!"); } } } results.putAll(cacheProvider.retrieveFromCache(missedIds)); for (Long id : results.keySet()) { if (missedIds.remove(id)) { mutex.release(locks.get(id)); } } Set<Privilege> fromSource = primaryService.getPrivilegesByIds(missedIds); for (Privilege privilege : fromSource) { putToCache(privilege); results.put(privilege.getId(), privilege); } for (Long id : missedIds) { mutex.release(locks.get(id)); } LinkedHashSet<Privilege> resultSet = new LinkedHashSet<Privilege>(results.size()); for (Long id : ids) { Privilege privilege = results.get(id); if (privilege != null) { resultSet.add(privilege); } } return resultSet; } @Override public Privilege getPrivilegeByOrganizationAndPrivilegeName(String organizationName, String privilegename) { Long id = nameCacheProvider.retrieveFromCache(getNameCacheKey(privilegename, organizationName)); if (id != null) { Set<Privilege> set = getPrivilegesByIds(id); if (set != null && !set.isEmpty()) { return set.iterator().next(); } } return primaryService.getPrivilegeByOrganizationAndPrivilegeName(organizationName, privilegename); } @Override public Collection<Privilege> getPrivilegesByOrganizationNameAndObjectID(String organizationName, String objectID) { return primaryService.getPrivilegesByOrganizationNameAndObjectID(organizationName, objectID); } @Override public Collection<Privilege> getPrivilegesByOrganizationAndUser(String organizationName, String userName) { return primaryService.getPrivilegesByOrganizationAndUser(organizationName, userName); } @Override public Collection<Privilege> getPrivilegesByOrganization(String organization) { return primaryService.getPrivilegesByOrganization(organization); } @Override public void validatePrivilege(Privilege privilege) { primaryService.validatePrivilege(privilege); } private String getNameCacheKey(Privilege privilege) { final String name = privilege.getName(); final String uniqueShortName = privilege.getParentOrganization().getUniqueShortName(); return getNameCacheKey(name, uniqueShortName); } protected String getNameCacheKey(final String name, final String uniqueShortName) { return new StringBuilder("privilege:").append(name).append(':').append(uniqueShortName).toString(); } private void putToCache(Privilege privilege) { cacheProvider.putToCache(privilege.getId(), privilege); nameCacheProvider.putToCache(getNameCacheKey(privilege), privilege.getId()); } private void expireFromCache(Privilege privilege) { if (cacheProvider.containsKey(privilege.getId())) { Set<Privilege> set = getPrivilegesByIds(privilege.getId()); if (set != null && !set.isEmpty()) { nameCacheProvider.expireFromCache(getNameCacheKey(set.iterator().next())); } cacheProvider.expireFromCache(privilege.getId()); } } }