/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.apache.ambari.logfeeder.input.cache; import com.google.common.collect.EvictingQueue; import java.util.LinkedHashMap; import java.util.Map; /** * LRU cache for handle de-duplications per input files. * It won't put already existing entries into the cache map if de-duplication interval not higher then a specific value * or if the new value is the most recently used one (in case of lastDedupEnabled is true) */ public class LRUCache { private final LinkedHashMap<String, Long> keyValueMap; private final String fileName; private final long dedupInterval; private final boolean lastDedupEnabled; private final EvictingQueue<String> mostRecentLogs; public LRUCache(final int limit, final String fileName, final long dedupInterval, boolean lastDedupEnabled) { this.fileName = fileName; this.dedupInterval = dedupInterval; this.lastDedupEnabled = lastDedupEnabled; this.mostRecentLogs = EvictingQueue.create(1); // for now, we will just store 1 mru entry keyValueMap = new LinkedHashMap<String, Long>(16, 0.75f, true) { @Override protected boolean removeEldestEntry(final Map.Entry<String, Long> eldest) { return size() > limit; } }; } public boolean isEntryReplaceable(String key, Long value) { boolean result = true; Long existingValue = keyValueMap.get(key); if (existingValue == null) { result = true; } else if (lastDedupEnabled && mostRecentLogs.contains(key)) { // TODO: get peek element if mostRecentLogs will contain more than 1 element result = false; } else if (Math.abs(value - existingValue) < dedupInterval) { result = false; } mostRecentLogs.add(key); return result; } public void put(String key, Long value) { if (isEntryReplaceable(key, value)) { keyValueMap.put(key, value); } } public Long get(String key) { mostRecentLogs.add(key); return keyValueMap.get(key); } public String getMRUKey() { return mostRecentLogs.peek(); } public int size() { return keyValueMap.size(); } public long getDedupInterval() { return dedupInterval; } public boolean containsKey(String key) { return keyValueMap.containsKey(key); } public String getFileName() { return this.fileName; } public boolean isLastDedupEnabled() { return lastDedupEnabled; } }