docnumbercache.java

来自「jsr170接口的java实现。是个apache的开源项目。」· Java 代码 · 共 192 行

JAVA
192
字号
/* * 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.jackrabbit.core.query.lucene;import org.apache.commons.collections.map.LRUMap;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * Implements a Document number cache with a fixed size and a LRU strategy. */final class DocNumberCache {    /**     * Logger instance for this class.     */    private static final Logger log = LoggerFactory.getLogger(DocNumberCache.class);    /**     * Log cache statistics at most every 10 seconds.     */    private static final long LOG_INTERVAL = 1000 * 10;    /**     * The number of cache segments.     */    private static final int CACHE_SEGMENTS = 0x10;    /**     * Mask to calculate segment number.     */    private static final int CACHE_SEGMENTS_MASK = CACHE_SEGMENTS - 1;    /**     * LRU Maps where key=uuid value=reader;docNumber     */    private final LRUMap[] docNumbers = new LRUMap[CACHE_SEGMENTS];    /**     * Timestamp of the last cache statistics log.     */    private long lastLog;    /**     * Cache misses.     */    private long misses;    /**     * Cache accesses;     */    private long accesses;    /**     * Creates a new <code>DocNumberCache</code> with a limiting     * <code>size</code>.     *     * @param size the cache limit.     */    DocNumberCache(int size) {        size = size % CACHE_SEGMENTS;        if (size < 0x40) {            // minimum size is 0x40 * 0x10 = 1024            size = 0x40;        }        for (int i = 0; i < docNumbers.length; i++) {            docNumbers[i] = new LRUMap(size);        }    }    /**     * Puts a document number into the cache using a uuid as key. An entry is     * only overwritten if the according reader is younger than the reader     * associated with the existing entry.     *     * @param uuid the key.     * @param reader the index reader from where the document number was read.     * @param n the document number.     */    void put(String uuid, CachingIndexReader reader, int n) {        LRUMap cacheSegment = docNumbers[getSegmentIndex(uuid.charAt(0))];        synchronized (cacheSegment) {            Entry e = (Entry) cacheSegment.get(uuid);            if (e != null) {                // existing entry                // ignore if reader is older than the one in entry                if (reader.getCreationTick() <= e.reader.getCreationTick()) {                    if (log.isDebugEnabled()) {                        log.debug("Ignoring put(). New entry is not from a newer reader. "                                + "existing: " + e.reader.getCreationTick()                                + ", new: " + reader.getCreationTick());                    }                    e = null;                }            } else {                // entry did not exist                e = new Entry(reader, n);            }            if (e != null) {                cacheSegment.put(uuid, e);            }        }    }    /**     * Returns the cache entry for <code>uuid</code>, or <code>null</code> if     * no entry exists for <code>uuid</code>.     *     * @param uuid the key.     * @return cache entry or <code>null</code>.     */    Entry get(String uuid) {        LRUMap cacheSegment = docNumbers[getSegmentIndex(uuid.charAt(0))];        Entry entry;        synchronized (cacheSegment) {            entry = (Entry) cacheSegment.get(uuid);        }        if (log.isInfoEnabled()) {            accesses++;            if (entry == null) {                misses++;            }            // log at most after 1000 accesses and every 10 seconds            if (accesses > 1000 && System.currentTimeMillis() - lastLog > LOG_INTERVAL) {                long ratio = 100;                if (misses != 0) {                    ratio -= misses * 100L / accesses;                }                StringBuffer statistics = new StringBuffer();                int inUse = 0;                for (int i = 0; i < docNumbers.length; i++) {                    inUse += docNumbers[i].size();                }                statistics.append("size=").append(inUse);                statistics.append("/").append(docNumbers[0].maxSize() * CACHE_SEGMENTS);                statistics.append(", #accesses=").append(accesses);                statistics.append(", #hits=").append((accesses - misses));                statistics.append(", #misses=").append(misses);                statistics.append(", cacheRatio=").append(ratio).append("%");                log.info(statistics.toString());                accesses = 0;                misses = 0;                lastLog = System.currentTimeMillis();            }        }        return entry;    }    /**     * Returns the segment index for character c.     */    private static int getSegmentIndex(char c) {        if (c > '9') {            c += 9;        }        return c & CACHE_SEGMENTS_MASK;    }    public static final class Entry {        /**         * The IndexReader.         */        final CachingIndexReader reader;        /**         * The document number.         */        final int doc;        Entry(CachingIndexReader reader, int doc) {            this.reader = reader;            this.doc = doc;        }    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?