Coverage Report - com.allanbank.mongodb.bson.io.StringEncoderCache
 
Classes in this File Line Coverage Branch Coverage Complexity
StringEncoderCache
86%
19/22
100%
6/6
1.75
 
 1  
 /*
 2  
  * #%L
 3  
  * StringEncoder.java - mongodb-async-driver - Allanbank Consulting, Inc.
 4  
  * %%
 5  
  * Copyright (C) 2011 - 2014 Allanbank Consulting, Inc.
 6  
  * %%
 7  
  * Licensed under the Apache License, Version 2.0 (the "License");
 8  
  * you may not use this file except in compliance with the License.
 9  
  * You may obtain a copy of the License at
 10  
  * 
 11  
  *      http://www.apache.org/licenses/LICENSE-2.0
 12  
  * 
 13  
  * Unless required by applicable law or agreed to in writing, software
 14  
  * distributed under the License is distributed on an "AS IS" BASIS,
 15  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 16  
  * See the License for the specific language governing permissions and
 17  
  * limitations under the License.
 18  
  * #L%
 19  
  */
 20  
 
 21  
 package com.allanbank.mongodb.bson.io;
 22  
 
 23  
 import java.util.Collections;
 24  
 import java.util.HashMap;
 25  
 import java.util.List;
 26  
 import java.util.Map;
 27  
 import java.util.SortedMap;
 28  
 
 29  
 /**
 30  
  * StringEncoderCache provides the ability to cache the encoding of a string to
 31  
  * speed the writing of strings.
 32  
  * <p>
 33  
  * This class is thread safe. Thread safety is achieved by maintaining two data
 34  
  * structures. The first is a map of seen strings to the number of times the
 35  
  * string has been seen. The map is maintained by the base class:
 36  
  * {@link AbstractStringCache}. The second structure is a simple map of the
 37  
  * cached {@link String} to the encoded {@code byte[]}. The map has no locking
 38  
  * or synchronization since it is read-only after construction.
 39  
  * </p>
 40  
  * 
 41  
  * @api.no This class is <b>NOT</b> part of the drivers API. This class may be
 42  
  *         mutated in incompatible ways between any two releases of the driver.
 43  
  * @copyright 2014, Allanbank Consulting, Inc., All Rights Reserved
 44  
  */
 45  
 public class StringEncoderCache extends AbstractStringCache {
 46  
 
 47  
     /** The cache of strings to bytes. */
 48  
     private Map<String, byte[]> myCache;
 49  
 
 50  
     /**
 51  
      * Creates a new StringEncoder.
 52  
      */
 53  3482
     public StringEncoderCache() {
 54  3482
         myCache = Collections.emptyMap();
 55  
 
 56  3482
         myMaxCacheLength = DEFAULT_MAX_CACHE_LENGTH;
 57  3482
         myMaxCachEntries = DEFAULT_MAX_CACHE_ENTRIES;
 58  3482
     }
 59  
 
 60  
     /**
 61  
      * Looks in the cache for encoded bytes for the specified string.
 62  
      * 
 63  
      * @param string
 64  
      *            The string value to find the cached bytes for.
 65  
      * @return The cached bytes for the string. May be <code>null</code>.
 66  
      */
 67  
     public byte[] find(final String string) {
 68  117032
         return myCache.get(string);
 69  
     }
 70  
 
 71  
     /**
 72  
      * Clears the cache.
 73  
      */
 74  
     @Override
 75  
     protected void clear() {
 76  0
         myCache = Collections.emptyMap();
 77  0
         super.clear();
 78  0
     }
 79  
 
 80  
     /**
 81  
      * Rebuilds the cache from the current collection of seen entries.
 82  
      */
 83  
     @Override
 84  
     protected void rebuildCache() {
 85  2074
         final SortedMap<Integer, List<SeenString>> order = buildCacheGroups();
 86  
 
 87  
         // Rebuild the cache.
 88  2074
         int count = 0;
 89  2074
         final Map<String, byte[]> cache = new HashMap<String, byte[]>(
 90  
                 (int) Math.ceil(Math.min(order.size(), myMaxCachEntries) / 0.75));
 91  2074
         for (final List<SeenString> seenAtCount : order.values()) {
 92  2240
             for (final SeenString seen : seenAtCount) {
 93  4741
                 if (count < myMaxCachEntries) {
 94  4668
                     cache.put(seen.getValue(), seen.getBytes());
 95  4668
                     count += 1;
 96  
                 }
 97  
                 else {
 98  73
                     mySeen.remove(seen.getValue());
 99  
                 }
 100  4741
             }
 101  2240
         }
 102  
 
 103  2074
         myCache = cache;
 104  2074
     }
 105  
 }