001/* 002 * Copyright 2019 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.core.cache; 017 018import java.util.HashMap; 019import java.util.Map; 020import java.util.function.Function; 021 022import org.slf4j.Logger; 023 024import org.ametys.runtime.i18n.I18nizableText; 025 026/** 027 * A cache represents a store of objects indexed with a key 028 * @param <K> the type of the keys in cache 029 * @param <V> the type of the values in cache 030 */ 031public interface Cache<K, V> 032{ 033 /** 034 * Returns the value associated with {@code key} in this cache if it exist, 035 * obtaining that value from given function if necessary and store it. 036 * @param key the key to get the element 037 * @param function the function to compute the value if key is not present 038 * @return V the value associated with key 039 * @throws CacheException throw CacheException if the key is null or invalid, or if failed to compute the new value 040 */ 041 public V get(K key, Function<K, V> function) throws CacheException; 042 043 /** 044 * Returns the value associated with {@code key} in this cache if it exist 045 * @param key the key to get the element 046 * @return V the value linked to key 047 */ 048 public V get(K key); 049 050 /** 051 * Associates {@code value} with {@code key} in this cache. If the cache 052 * previously contained a value associated with {@code key}, the old value 053 * is replaced by {@code value}. The {@code key} can not be null. 054 * @param key the key to get the element 055 * @param value the value associated with key 056 */ 057 public void put(K key, V value); 058 059 /** 060 * Copies all of the mappings from the specified map to the cache. 061 * @param map map of key/values to be stored in the cache 062 */ 063 public void putAll(Map<K, V> map); 064 065 /** 066 * return true if key is present in cache 067 * @param key the key to be checked 068 * @return true if key is present in cache 069 */ 070 public boolean hasKey(K key); 071 072 /** 073 * Discards any cached value for key {@code key}. 074 * @param key the key to invalidate 075 */ 076 public void invalidate(K key); 077 078 /** 079 * Discards all entries in the cache, without reseting statistics 080 */ 081 public void invalidateAll(); 082 083 /** 084 * Create or reset the whole cache (including statistics) 085 */ 086 public void resetCache(); 087 088 /** 089 * Get all statistics about cache 090 * @return statistic about the cache (hit, miss, evictions...) 091 */ 092 public CacheStats getCacheStats(); 093 094 /** 095 * Get the size the cache take in bytes 096 * @return the size of the cache if it's computable, return 0 otherwise 097 * @throws CacheException throw CacheException if memory size can not be computed 098 */ 099 public long getMemorySize() throws CacheException; 100 101 /** 102 * Get the max size allocated to the cache, in bytes. 103 * This value can be set to Long.MAX_VALUE for infinite cache 104 * @return the max size allocated to the cache 105 */ 106 public long getMaxSize(); 107 108 /** 109 * Get the number of values in cache 110 * @return the number of values in cache 111 */ 112 public long getNumberOfElements(); 113 114 /** 115 * Get the label of cache 116 * @return the label of cache 117 */ 118 public I18nizableText getLabel(); 119 120 /** 121 * Get the description of cache 122 * @return the description of cache 123 */ 124 public I18nizableText getDescription(); 125 126 /** 127 * Get the id of cache 128 * @return the id of cache 129 */ 130 public String getId(); 131 132 /** 133 * Is this cache size computable 134 * @return true if the cache size is computable 135 */ 136 public boolean isComputableSize(); 137 138 /** 139 * Get the cache as a simple Map 140 * @return the Map<K, V> representing the cache 141 */ 142 public Map<K, V> asMap(); 143 144 /** 145 * Get the definition in JSON Map 146 * @param logger Logger to log an error when the size cannot be computed 147 * @return the JSON for the cache 148 */ 149 public default Map<String, Object> toJSONMap(Logger logger) 150 { 151 Map<String, Object> properties = new HashMap<>(); 152 properties.put("id", this.getId()); 153 properties.put("label", this.getLabel()); 154 properties.put("description", this.getDescription()); 155 properties.put("computableSize", this.isComputableSize()); 156 properties.put("access", this.getCacheStats().requestCount()); 157 properties.put("hit", this.getCacheStats().hitCount()); 158 properties.put("hitRate", this.getCacheStats().hitRate()); 159 properties.put("miss", this.getCacheStats().missCount()); 160 properties.put("missRate", this.getCacheStats().missRate()); 161 properties.put("nbElement", this.getNumberOfElements()); 162 properties.put("nbEviction", this.getCacheStats().evictionCount()); 163 try 164 { 165 properties.put("currentSize", this.getMemorySize()); 166 } 167 catch (CacheException e) 168 { 169 logger.error("Unable to compute size of cache: {} - {}", this.getId(), this.getLabel(), e); 170 properties.put("currentSize", -1); 171 } 172 properties.put("maxSize", this.getMaxSize()); 173 return properties; 174 } 175 176}