⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stringcache.java

📁 业界著名的tomcat服务器的最新6.0的源代码。
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 *  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.tomcat.util.buf;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.TreeMap;

/**
 * This class implements a String cache for ByteChunk and CharChunk.
 *
 * @author Remy Maucherat
 */
public class StringCache {


    private static org.apache.juli.logging.Log log=
        org.apache.juli.logging.LogFactory.getLog( StringCache.class );
    
    
    // ------------------------------------------------------- Static Variables

    
    /**
     * Enabled ?
     */
    protected static boolean byteEnabled = 
        ("true".equals(System.getProperty("tomcat.util.buf.StringCache.byte.enabled", "false")));

    
    protected static boolean charEnabled = 
        ("true".equals(System.getProperty("tomcat.util.buf.StringCache.char.enabled", "false")));

    
    protected static int trainThreshold = 
        Integer.parseInt(System.getProperty("tomcat.util.buf.StringCache.trainThreshold", "20000"));
    

    protected static int cacheSize = 
        Integer.parseInt(System.getProperty("tomcat.util.buf.StringCache.cacheSize", "200"));
    

    protected static int maxStringSize = 
        Integer.parseInt(System.getProperty("tomcat.util.buf.StringCache.maxStringSize", "128"));
    

   /**
     * Statistics hash map for byte chunk.
     */
    protected static HashMap bcStats = new HashMap(cacheSize);

    
    /**
     * toString count for byte chunk.
     */
    protected static int bcCount = 0;
    
    
    /**
     * Cache for byte chunk.
     */
    protected static ByteEntry[] bcCache = null;
    

    /**
     * Statistics hash map for char chunk.
     */
    protected static HashMap ccStats = new HashMap(cacheSize);


    /**
     * toString count for char chunk.
     */
    protected static int ccCount = 0; 
    

    /**
     * Cache for char chunk.
     */
    protected static CharEntry[] ccCache = null;

    
    /**
     * Access count.
     */
    protected static int accessCount = 0;
    

    /**
     * Hit count.
     */
    protected static int hitCount = 0;
    

    // ------------------------------------------------------------ Properties

    
    /**
     * @return Returns the cacheSize.
     */
    public int getCacheSize() {
        return cacheSize;
    }
    
    
    /**
     * @param cacheSize The cacheSize to set.
     */
    public void setCacheSize(int cacheSize) {
        StringCache.cacheSize = cacheSize;
    }

    
    /**
     * @return Returns the enabled.
     */
    public boolean getByteEnabled() {
        return byteEnabled;
    }
    
    
    /**
     * @param byteEnabled The enabled to set.
     */
    public void setByteEnabled(boolean byteEnabled) {
        StringCache.byteEnabled = byteEnabled;
    }
    
    
    /**
     * @return Returns the enabled.
     */
    public boolean getCharEnabled() {
        return charEnabled;
    }
    
    
    /**
     * @param charEnabled The enabled to set.
     */
    public void setCharEnabled(boolean charEnabled) {
        StringCache.charEnabled = charEnabled;
    }
    
    
    /**
     * @return Returns the trainThreshold.
     */
    public int getTrainThreshold() {
        return trainThreshold;
    }
    
    
    /**
     * @param trainThreshold The trainThreshold to set.
     */
    public void setTrainThreshold(int trainThreshold) {
        StringCache.trainThreshold = trainThreshold;
    }

    
    /**
     * @return Returns the accessCount.
     */
    public int getAccessCount() {
        return accessCount;
    }
    
    
    /**
     * @return Returns the hitCount.
     */
    public int getHitCount() {
        return hitCount;
    }

    
    // -------------------------------------------------- Public Static Methods

    
    public void reset() {
        hitCount = 0;
        accessCount = 0;
        synchronized (bcStats) {
            bcCache = null;
            bcCount = 0;
        }
        synchronized (ccStats) {
            ccCache = null;
            ccCount = 0;
        }
    }
    
    
    public static String toString(ByteChunk bc) {

        // If the cache is null, then either caching is disabled, or we're
        // still training
        if (bcCache == null) {
            String value = bc.toStringInternal();
            if (byteEnabled && (value.length() < maxStringSize)) {
                // If training, everything is synced
                synchronized (bcStats) {
                    // If the cache has been generated on a previous invocation
                    // while waiting fot the lock, just return the toString value
                    // we just calculated
                    if (bcCache != null) {
                        return value;
                    }
                    // Two cases: either we just exceeded the train count, in which
                    // case the cache must be created, or we just update the count for
                    // the string
                    if (bcCount > trainThreshold) {
                        long t1 = System.currentTimeMillis();
                        // Sort the entries according to occurrence
                        TreeMap tempMap = new TreeMap();
                        Iterator entries = bcStats.keySet().iterator();
                        while (entries.hasNext()) {
                            ByteEntry entry = (ByteEntry) entries.next();
                            int[] countA = (int[]) bcStats.get(entry);
                            Integer count = new Integer(countA[0]);
                            // Add to the list for that count
                            ArrayList list = (ArrayList) tempMap.get(count);
                            if (list == null) {
                                // Create list
                                list = new ArrayList();
                                tempMap.put(count, list);
                            }
                            list.add(entry);
                        }
                        // Allocate array of the right size
                        int size = bcStats.size();
                        if (size > cacheSize) {
                            size = cacheSize;
                        }
                        ByteEntry[] tempbcCache = new ByteEntry[size];
                        // Fill it up using an alphabetical order
                        // and a dumb insert sort
                        ByteChunk tempChunk = new ByteChunk();
                        int n = 0;
                        while (n < size) {
                            Object key = tempMap.lastKey();
                            ArrayList list = (ArrayList) tempMap.get(key);
                            ByteEntry[] list2 = 
                                (ByteEntry[]) list.toArray(new ByteEntry[list.size()]);
                            for (int i = 0; i < list.size() && n < size; i++) {
                                ByteEntry entry = (ByteEntry) list.get(i);
                                tempChunk.setBytes(entry.name, 0, entry.name.length);
                                int insertPos = findClosest(tempChunk, tempbcCache, n);
                                if (insertPos == n) {
                                    tempbcCache[n + 1] = entry;
                                } else {
                                    System.arraycopy(tempbcCache, insertPos + 1, tempbcCache, 
                                            insertPos + 2, n - insertPos - 1);
                                    tempbcCache[insertPos + 1] = entry;
                                }
                                n++;
                            }
                            tempMap.remove(key);
                        }
                        bcCount = 0;
                        bcStats.clear();
                        bcCache = tempbcCache;
                        if (log.isDebugEnabled()) {
                            long t2 = System.currentTimeMillis();
                            log.debug("ByteCache generation time: " + (t2 - t1) + "ms");
                        }
                    } else {
                        bcCount++;
                        // Allocate new ByteEntry for the lookup
                        ByteEntry entry = new ByteEntry();
                        entry.value = value;
                        int[] count = (int[]) bcStats.get(entry);
                        if (count == null) {
                            int end = bc.getEnd();
                            int start = bc.getStart();
                            // Create byte array and copy bytes
                            entry.name = new byte[bc.getLength()];
                            System.arraycopy(bc.getBuffer(), start, entry.name, 0, end - start);
                            // Set encoding
                            entry.enc = bc.getEncoding();
                            // Initialize occurrence count to one 
                            count = new int[1];
                            count[0] = 1;
                            // Set in the stats hash map
                            bcStats.put(entry, count);
                        } else {
                            count[0] = count[0] + 1;
                        }
                    }
                }
            }
            return value;
        } else {
            accessCount++;
            // Find the corresponding String
            String result = find(bc);
            if (result == null) {
                return bc.toStringInternal();
            }
            // Note: We don't care about safety for the stats
            hitCount++;
            return result;
        }
        
    }


    public static String toString(CharChunk cc) {
        
        // If the cache is null, then either caching is disabled, or we're
        // still training
        if (ccCache == null) {
            String value = cc.toStringInternal();
            if (charEnabled && (value.length() < maxStringSize)) {
                // If training, everything is synced
                synchronized (ccStats) {
                    // If the cache has been generated on a previous invocation
                    // while waiting fot the lock, just return the toString value
                    // we just calculated
                    if (ccCache != null) {
                        return value;

⌨️ 快捷键说明

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