Package com.gistlabs.mechanize.cache.inMemory

Source Code of com.gistlabs.mechanize.cache.inMemory.InMemoryHttpCache

/**
* Copyright (C) 2012-2014 Gist Labs, LLC. (http://gistlabs.com)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package com.gistlabs.mechanize.cache.inMemory;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicLong;

import com.gistlabs.mechanize.cache.api.CacheEntry;
import com.gistlabs.mechanize.cache.api.HttpCache;

/**
* An in-memory HttpCache, by default capped to 64MB of response content. (This only counts the entity length).
* @author jheintz
*
*/
public class InMemoryHttpCache implements HttpCache {
  final ConcurrentMap<String,CacheEntry> cache = new ConcurrentHashMap<String,CacheEntry>(1024);
  final ConcurrentLinkedQueue<String> uriFifo = new ConcurrentLinkedQueue<String>();
  final long maxBytes;
  final AtomicLong currentBytes = new AtomicLong(0);

  public InMemoryHttpCache() {
    this(64);
  }

  public InMemoryHttpCache(final int numberOfMegabytes) {
    maxBytes = 1024 * 1024 * numberOfMegabytes;
  }

  @Override
  public String toString() {
    return String.format("InMemoryHttpCache[current=%skb]", currentBytes.get()/1024);
  }

  @Override
  public CacheEntry get(final String uri) {
    CacheEntry entry = cache.get(uri);

    if (entry!=null) { // refresh LRU
      entry.getResponse().setHeader("Via", "mechanize");
      uriFifo.remove(uri);
      uriFifo.offer(uri);
    }


    return entry;
  }

  @Override
  public void remove(final String uri) {
    CacheEntry removed = cache.remove(uri);
    uriFifo.remove(uri);

    if (removed!=null)
      currentBytes.addAndGet(-getByteCount(removed));
  }

  @Override
  public boolean putIfAbsent(final String uri, final CacheEntry maybe) {
    if (!ensureCapacity(getByteCount(maybe)))
      return false; // and don't cache

    CacheEntry previous = cache.putIfAbsent(uri, maybe);

    currentBytes.addAndGet(getByteCount(maybe) - getByteCount(previous));
    return true;
  }

  @Override
  public boolean replace(final String uri, final CacheEntry cachedValue, final CacheEntry maybe) {
    if (!ensureCapacity(getByteCount(maybe))) {
      remove(uri);
      return false; // and don't cache
    }

    boolean replaced = cache.replace(uri, cachedValue, maybe);

    if (replaced)
      currentBytes.addAndGet(getByteCount(maybe)-getByteCount(cachedValue));

    return true;
  }

  protected boolean ensureCapacity(final long byteCount) {
    if (byteCount>maxBytes)
      return false;

    while(currentBytes.get()+byteCount > maxBytes)
      remove(uriFifo.poll());

    return true;
  }

  /**
   * null safe get byte count helper
   *
   * @param entry
   * @return
   */
  protected long getByteCount(final CacheEntry entry) {
    return entry==null ? 0 : entry.byteCount();
  }
}
TOP

Related Classes of com.gistlabs.mechanize.cache.inMemory.InMemoryHttpCache

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.