/* * Copyright (c) 2009-2011 Lockheed Martin Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.eurekastreams.server.persistence.mappers.cache; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.persistence.Query; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eurekastreams.server.domain.DomainGroup; import org.eurekastreams.server.domain.EntityCacheUpdater; import org.eurekastreams.server.persistence.mappers.stream.CachedDomainMapper; import org.eurekastreams.server.persistence.strategies.DomainGroupQueryStrategy; import org.eurekastreams.server.search.modelview.DomainGroupModelView; import org.hibernate.CacheMode; import org.hibernate.Criteria; import org.hibernate.ScrollMode; import org.hibernate.ScrollableResults; /** * Cache loader for Groups. * * @deprecated This is only still around until it can be refactored out of the unit tests. New cache warming and * EntityCacheUpdaters are in place in production code. */ @Deprecated public class DomainGroupCacheLoader extends CachedDomainMapper implements EntityCacheUpdater<DomainGroup> { /** * Logger instance. */ private Log log = LogFactory.getLog(DomainGroupCacheLoader.class); /** * Fetch size. */ private static final int FETCH_SIZE = 100; /** * Strategy for querying a domain group model view from the database. */ private DomainGroupQueryStrategy domainGroupQueryStrategy; /** * Constructor. * * @param inDomainGroupQueryStrategy * the person query strategy to set. */ public DomainGroupCacheLoader(final DomainGroupQueryStrategy inDomainGroupQueryStrategy) { domainGroupQueryStrategy = inDomainGroupQueryStrategy; } /** * Initialize the Domain Group hierarchy cache - intended to run on system start-up. */ public void initialize() { log.info("Initializing the Domain Group Cache"); queryAllDomainGroups(); queryAllCoordinators(); queryAllFollowers(); } /** * Query all domain groups, loading them in the cache. */ private void queryAllDomainGroups() { long start = System.currentTimeMillis(); log.info("Loading up all domain groups with a single query"); Criteria criteria = domainGroupQueryStrategy.getCriteria(getHibernateSession()); // page the data criteria.setFetchSize(FETCH_SIZE); criteria.setCacheMode(CacheMode.IGNORE); ScrollableResults scroll = criteria.scroll(ScrollMode.FORWARD_ONLY); // loop through the results and store in cache long recordCounter = 0; while (scroll.next()) { if (++recordCounter % FETCH_SIZE == 0) { log.info("Loading " + recordCounter + "th domainGroup record, clearing session."); getHibernateSession().clear(); } DomainGroupModelView result = (DomainGroupModelView) scroll.get(0); getCache().set(CacheKeys.GROUP_BY_ID + result.getEntityId(), result); getCache().set(CacheKeys.GROUP_BY_SHORT_NAME + result.getShortName(), result.getEntityId()); } log.info("Completed loading all domain groups in " + (System.currentTimeMillis() - start) + " milliseconds."); } /** * Load up all coordinators for all domain groups, updating the cache. */ @SuppressWarnings("unchecked") private void queryAllCoordinators() { log.info("Loading up all coordinators for all groups."); long start = System.currentTimeMillis(); // single query to get all coordinator->group String queryString = "SELECT p.id, g.id FROM Person p, DomainGroup g " + " WHERE p member of g.coordinators"; Query query = getEntityManager().createQuery(queryString); List<Object[]> results = query.getResultList(); log.info("Found " + results.size() + " coordinators in " + (System.currentTimeMillis() - start) + " milliseconds. Populating cache now."); // loop across the results, storing them all locally log.info("Grouping coordinators by DomainGroup."); Map<Long, List<Long>> groupCoordinators = new HashMap<Long, List<Long>>(); for (Object[] result : results) { Long coordinatorId = (Long) result[0]; Long groupId = (Long) result[1]; if (!groupCoordinators.containsKey(groupId)) { groupCoordinators.put(groupId, new ArrayList<Long>()); } groupCoordinators.get(groupId).add(coordinatorId); } log.info("Writing cache for each DomainGroup."); // loop across the lists, pushing them to cache for (Long groupId : groupCoordinators.keySet()) { getCache().setList(CacheKeys.COORDINATOR_PERSON_IDS_BY_GROUP_ID + groupId, groupCoordinators.get(groupId)); } log.info("Completed coordinator cache loading in " + (System.currentTimeMillis() - start) + " milliseconds."); } /** * Load up all followers for all domain groups, updating the cache. This assumes that the group cache was just * cleared and re-populated without any followers. */ @SuppressWarnings("unchecked") private void queryAllFollowers() { // single query to get all follower->group String queryString = "SELECT f.pk.followerId, f.pk.followingId from GroupFollower f"; Query query = getEntityManager().createQuery(queryString); List<Object[]> results = query.getResultList(); storeResultsInCache(results, CacheKeys.FOLLOWERS_BY_GROUP, CacheKeys.GROUPS_FOLLOWED_BY_PERSON); } /** * Domain Group updater implementation - fired when an existing domain group entity is updated. * * @param inUpdatedDomainGroup * the domain group just updated */ @Override public void onPostUpdate(final DomainGroup inUpdatedDomainGroup) { if (log.isInfoEnabled()) { log.info("DomainGroup.onPostUpdate - removing group #" + inUpdatedDomainGroup.getId() + " from cache"); } getCache().delete(CacheKeys.GROUP_BY_ID + inUpdatedDomainGroup.getId()); } /** * Domain Group persist implementation - fired when a new domain group entity is persisted. * * @param inDomainGroup * the domainGroup just persisted */ @Override public void onPostPersist(final DomainGroup inDomainGroup) { if (log.isInfoEnabled()) { log.info("DomainGroup.onPostPersist - group with shortName " + inDomainGroup.getShortName() + " - doing nothing."); } // no-op - cache will be loaded when someone requests this domain group } }