/* * Copyright (c) 2010 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.List; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eurekastreams.server.persistence.mappers.stream.CachedDomainMapper; /** * Cache updater - scaffolding for paged bulk updates of cache by IDs. * * @param <CachedItemType> * the type of item we're retrieving and updating in cache * @param <UpdateInfoType> * the type of object the caller will pass into execute() and we'll * pass into updateCachedEntity */ public abstract class UpdateCachedItemsByIds<CachedItemType, UpdateInfoType> extends CachedDomainMapper { /** * Logger. */ private Log log = LogFactory.getLog(UpdateCachedItemsByIds.class); /** * The batch size for getting cached items. */ private Integer batchSize; /** * Constructor. * * @param inBatchSize * the batch size for getting items from cache. */ public UpdateCachedItemsByIds(final Integer inBatchSize) { batchSize = inBatchSize; } /** * Update cached items by their ids. * * @param inCachedDbIds * list of ids of cached items to update in cache * @param inUpdateInfo * the info passed into updateCachedEntity for all items that * need to be updated */ @SuppressWarnings("unchecked") public void execute(final List<Long> inCachedDbIds, final UpdateInfoType inUpdateInfo) { int batchStartingIndex = 0; int listSize = inCachedDbIds.size(); log.info("Updating " + listSize + " cached objects for " + getCacheKeyPrefix()); while (batchStartingIndex < listSize) { int toIndex = batchStartingIndex + batchSize; if (toIndex >= listSize) { toIndex = listSize; } log.info("Fetching batch of cached objects for " + getCacheKeyPrefix() + " from input collection from indices " + batchStartingIndex + " to " + (toIndex - 1) + " and batch size " + batchSize); // make the multiget request to the cache List<Long> batch = inCachedDbIds.subList(batchStartingIndex, toIndex); List<String> keys = new ArrayList<String>(batchSize); for (Long objectId : batch) { keys.add(getCacheKeyPrefix() + objectId); } // get the batch of objects from cache Map<String, CachedItemType> cachedItems = (Map<String, CachedItemType>) getCache() .multiGet(keys); // loop across and update the cached objects - loop across the // results we found in cache, not the IDs we were looking for // because we only need to update objects that are // already in cache for (String cacheKey : cachedItems.keySet()) { CachedItemType cachedItem = cachedItems.get(cacheKey); if (updateCachedEntity(cachedItem, inUpdateInfo)) { getCache().set(cacheKey, cachedItem); } } batchStartingIndex = toIndex; } } /** * Get the cache key prefix. * * @return the cache key prefix */ protected abstract String getCacheKeyPrefix(); /** * Update the input cached item with the update info that was passed into * the execute() method by the caller. * * @param inCachedItem * the item to update * @param inUpdateInfo * object passed into execute from caller, used to update the * cached item * @return whether or not the cached item changed */ protected abstract Boolean updateCachedEntity( final CachedItemType inCachedItem, UpdateInfoType inUpdateInfo); }