cache-lru

CachingPolicy.java

public enum CachingPolicy {
  THROUGH("through"), AROUND("around"), BEHIND("behind");

  private String policy;

  private CachingPolicy(String policy) {
    this.policy = policy;
  }

  public String getPolicy() {
    return policy;
  }
}
LruCache.java

public class LruCache {

  class Node {
    String userId;
    UserAccount userAccount;
    Node previous;
    Node next;

    public Node(String userId, UserAccount userAccount) {
      this.userId = userId;
      this.userAccount = userAccount;
    }
  }

  int capacity;
  Map<String, Node> cache = new HashMap<>();
  Node head;
  Node end;

  public LruCache(int capacity) {
    this.capacity = capacity;
  }

  /**
   * Get user account
   */
  public UserAccount get(String userId) {
    if (cache.containsKey(userId)) {
      Node node = cache.get(userId);
      remove(node);
      setHead(node);
      return node.userAccount;
    }
    return null;
  }

  /**
   *
   * Remove node from linked list.
   */
  public void remove(Node node) {
    if (node.previous != null) {
      node.previous.next = node.next;
    } else {
      head = node.next;
    }
    if (node.next != null) {
      node.next.previous = node.previous;
    } else {
      end = node.previous;
    }
  }

  /**
   *
   * Move node to the front of the list.
   */
  public void setHead(Node node) {
    node.next = head;
    node.previous = null;
    if (head != null) {
      head.previous = node;
    }
    head = node;
    if (end == null) {
      end = head;
    }
  }

  /**
   * Set user account
   */
  public void set(String userId, UserAccount userAccount) {
    if (cache.containsKey(userId)) {
      Node old = cache.get(userId);
      old.userAccount = userAccount;
      remove(old);
      setHead(old);
    } else {
      Node newNode = new Node(userId, userAccount);
      if (cache.size() >= capacity) {
        System.out.println("# Cache is FULL! Removing " + end.userId + " from cache...");
        cache.remove(end.userId); // remove LRU data from cache.
        remove(end);
        setHead(newNode);
      } else {
        setHead(newNode);
      }
      cache.put(userId, newNode);
    }
  }

  public boolean contains(String userId) {
    return cache.containsKey(userId);
  }

  /**
   * Invalidate cache for user
   */
  public void invalidate(String userId) {
    System.out.println("# " + userId + " has been updated! Removing older version from cache...");
    Node toBeRemoved = cache.get(userId);
    remove(toBeRemoved);
    cache.remove(userId);
  }

  public boolean isFull() {
    return cache.size() >= capacity;
  }

  public UserAccount getLruData() {
    return end.userAccount;
  }

  /**
   * Clear cache
   */
  public void clear() {
    head = null;
    end = null;
    cache.clear();
  }

  /**
   *
   * Returns cache data in list form.
   */
  public List<UserAccount> getCacheDataInListForm() {
    ArrayList<UserAccount> listOfCacheData = new ArrayList<>();
    Node temp = head;
    while (temp != null) {
      listOfCacheData.add(temp.userAccount);
      temp = temp.next;
    }
    return listOfCacheData;
  }

  /**
   * Set cache capacity
   */
  public void setCapacity(int newCapacity) {
    if (capacity > newCapacity) {
      clear(); // Behavior can be modified to accommodate for decrease in cache size. For now, we'll
               // just clear the cache.
    } else {
      this.capacity = newCapacity;
    }
  }
}
CacheStore.java

public class CacheStore {

  static LruCache cache;

  private CacheStore() {
  }

  /**
   * Init cache capacity
   */
  public static void initCapacity(int capacity) {
    if (null == cache) {
      cache = new LruCache(capacity);
    } else {
      cache.setCapacity(capacity);
    }
  }

  /**
   * Get user account using read-through cache
   */
  public static UserAccount readThrough(String userId) {
    if (cache.contains(userId)) {
      System.out.println("# Cache Hit!");
      return cache.get(userId);
    }
    System.out.println("# Cache Miss!");
    UserAccount userAccount = DbManager.readFromDb(userId);
    cache.set(userId, userAccount);
    return userAccount;
  }

  /**
   * Get user account using write-through cache
   */
  public static void writeThrough(UserAccount userAccount) {
    if (cache.contains(userAccount.getUserId())) {
      DbManager.updateDb(userAccount);
    } else {
      DbManager.writeToDb(userAccount);
    }
    cache.set(userAccount.getUserId(), userAccount);
  }

  /**
   * Get user account using write-around cache
   */
  public static void writeAround(UserAccount userAccount) {
    if (cache.contains(userAccount.getUserId())) {
      DbManager.updateDb(userAccount);
      cache.invalidate(userAccount.getUserId()); // Cache data has been updated -- remove older
                                                 // version from cache.
    } else {
      DbManager.writeToDb(userAccount);
    }
  }

  /**
   * Get user account using read-through cache with write-back policy
   */
  public static UserAccount readThroughWithWriteBackPolicy(String userId) {
    if (cache.contains(userId)) {
      System.out.println("# Cache Hit!");
      return cache.get(userId);
    }
    System.out.println("# Cache Miss!");
    UserAccount userAccount = DbManager.readFromDb(userId);
    if (cache.isFull()) {
      System.out.println("# Cache is FULL! Writing LRU data to DB...");
      UserAccount toBeWrittenToDb = cache.getLruData();
      DbManager.upsertDb(toBeWrittenToDb);
    }
    cache.set(userId, userAccount);
    return userAccount;
  }

  /**
   * Set user account
   */
  public static void writeBehind(UserAccount userAccount) {
    if (cache.isFull() && !cache.contains(userAccount.getUserId())) {
      System.out.println("# Cache is FULL! Writing LRU data to DB...");
      UserAccount toBeWrittenToDb = cache.getLruData();
      DbManager.upsertDb(toBeWrittenToDb);
    }
    cache.set(userAccount.getUserId(), userAccount);
  }

  /**
   * Clears cache
   */
  public static void clearCache() {
    if (null != cache) {
      cache.clear();
    }
  }

  /**
   * Writes remaining content in the cache into the DB.
   */
  public static void flushCache() {
    System.out.println("# flushCache...");
    if (null == cache) {
      return;
    }
    List<UserAccount> listOfUserAccounts = cache.getCacheDataInListForm();
    for (UserAccount userAccount : listOfUserAccounts) {
      DbManager.upsertDb(userAccount);
    }
  }

  /**
   * Print user accounts
   */
  public static String print() {
    List<UserAccount> listOfUserAccounts = cache.getCacheDataInListForm();
    StringBuilder sb = new StringBuilder();
    sb.append("\n--CACHE CONTENT--\n");
    for (UserAccount userAccount : listOfUserAccounts) {
      sb.append(userAccount.toString() + "\n");
    }
    sb.append("----\n");
    return sb.toString();
  }
}

猜你喜欢

转载自zhuzhaoyong.iteye.com/blog/2294037