/******************************************************************************* * Copyright (c) 2011 Arapiki Solutions Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * "Peter Smith <psmith@arapiki.com>" - initial API and * implementation and/or initial documentation *******************************************************************************/ package com.buildml.model.types; import com.buildml.utils.types.LRULinkedHashMap; /** * A PathNameCache is used as means of caching the most commonly used content * in the "files" database table, rather than accessing the database every time * there's a need to get information. In particular, this cache stores the following * relationship: * <p> * <parentPathId, childPathName> maps to <childPathId, childPathType> * <p> * It's an extremely common operation to look up a child's path ID, given the * parent's ID and the child's name, so this has to be optimized. * <p> * An LRU algorithm is used so that only the most recent N mappings are kept (to * avoid endless growth of the cache). * * @author "Peter Smith <psmith@arapiki.com>" */ public class PathNameCache { /*=====================================================================================* * FIELDS *=====================================================================================*/ /** * The customized HashMap that will automatically remove the least recently accessed * item once the cache fills up. */ private LRULinkedHashMap<PathNameCacheKey, PathNameCacheValue> map; /*=====================================================================================* * NESTED CLASSES *=====================================================================================*/ /** * This nested class is used as the "key" in the PathNameCache. It simply contains * the parent's path ID (int) and the child's path name (String). Given that it's used * as the key in a hash table, we need custom-written equals() and hashCode() methods. */ public class PathNameCacheKey { /** The parent's path ID. */ private int parentPathId; /** The child's path name. */ private String childPathName; /** * Create a new PathNameCacheKey object. * * @param parentPathId The parent's path ID. * @param childPathName The child's path name. */ public PathNameCacheKey(int parentPathId, String childPathName) { this.parentPathId = parentPathId; this.childPathName = childPathName; } /** * Return the parent's path ID. * @return The parent's path ID. */ public int getParentPathId() { return parentPathId; } /** * Return the child's path name. * @return The child's path name. */ public String getChildPathName() { return childPathName; } /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (!(obj instanceof PathNameCacheKey)) { return false; } PathNameCacheKey keyObj = (PathNameCacheKey)obj; return (parentPathId == keyObj.parentPathId) && (childPathName.equals(keyObj.childPathName)); } /* (non-Javadoc) * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return parentPathId + childPathName.hashCode(); } } /*-------------------------------------------------------------------------------------*/ /** * This nested class is used as the "value" of the cache. The value * is a pair consisting of <childPathId, childType>, where childType is * the ordinal value of a FileMgr.PathType value. */ public class PathNameCacheValue { /** The child's path ID. */ private int childPathId; /** The child's type (directory, file, etc). */ private int childType; /** * Create a new PathNameCacheValue object. * * @param childPathId The child's path ID. * @param childType The child's type (directory, file, etc). */ public PathNameCacheValue(int childPathId, int childType) { this.childPathId = childPathId; this.childType = childType; } /** * Return the child's path ID. * @return The child's path ID. */ public int getChildPathId() { return childPathId; } /** * Return the child's type. * @return The child's type. */ public int getChildType() { return childType; } } /*=====================================================================================* * CONSTRUCTORS *=====================================================================================*/ /** * Constructor for the PathNameCache class. * * @param maxSize the maximum number of items to hold in the cache. */ public PathNameCache(int maxSize) { map = new LRULinkedHashMap<PathNameCacheKey, PathNameCacheValue>(maxSize); } /*=====================================================================================* * PUBLIC METHODS *=====================================================================================*/ /** * Clear the cache, removing all stored items and reseting the size to 0. */ public void clear() { map.clear(); } /*-------------------------------------------------------------------------------------*/ /** * Given a parent Path ID number and the child's path name look up the value in * the cache. * * @param parentPathId The parent's path (directory) ID number. * @param childPathName The name of the path within the parent's directory * @return a PathNameCacheValue object containing the cache mapping, or null if * the mapping isn't in the cache. */ public PathNameCacheValue get(int parentPathId, String childPathName) { PathNameCacheKey key = new PathNameCacheKey(parentPathId, childPathName); return map.get(key); } /*-------------------------------------------------------------------------------------*/ /** * Add a new mapping to the cache. * * @param parentPathId The parent's path ID (actually, a directory ID). * @param childPathName The name of the path within that parent's directory. * @param childPathId The child's path ID to be used as the target of the mapping. * @param childType What type is the child (file, directory, etc), to be used as * the target of the mapping. */ public void put(int parentPathId, String childPathName, int childPathId, int childType) { PathNameCacheKey key = new PathNameCacheKey(parentPathId, childPathName); PathNameCacheValue value = new PathNameCacheValue(childPathId, childType); map.put(key, value); } /*-------------------------------------------------------------------------------------*/ /** * Remove an existing mapping from the cache. * * @param parentPathId The parent's path (directory) ID number. * @param childPathName The name of the path within the parent's directory */ public void remove(int parentPathId, String childPathName) { PathNameCacheKey key = new PathNameCacheKey(parentPathId, childPathName); map.remove(key); } /*-------------------------------------------------------------------------------------*/ }