All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.launchdarkly.client.InMemoryFeatureStore Maven / Gradle / Ivy

There is a newer version: 4.61
Show newest version
package com.launchdarkly.client;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * A thread-safe, versioned store for {@link FeatureFlag} objects and related data based on a
 * {@link HashMap}. This is the default implementation of {@link FeatureStore}.
 */
public class InMemoryFeatureStore implements FeatureStore {
  private static final Logger logger = LoggerFactory.getLogger(InMemoryFeatureStore.class);

  private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
  private final Map, Map> allData = new HashMap<>();
  private volatile boolean initialized = false;

  @Override
  public  T get(VersionedDataKind kind, String key) {
    try {
      lock.readLock().lock();
      Map items = allData.get(kind);
      if (items == null) {
        logger.debug("[get] no objects exist for \"{}\". Returning null", kind.getNamespace());
        return null;
      }
      Object o = items.get(key);
      if (o == null) {
        logger.debug("[get] Key: {} not found in \"{}\". Returning null", key, kind.getNamespace());
        return null;
      }
      if (!kind.getItemClass().isInstance(o)) {
        logger.warn("[get] Unexpected object class {} found for key: {} in \"{}\". Returning null",
            o.getClass().getName(), key, kind.getNamespace());
        return null;
      }
      T item = kind.getItemClass().cast(o);
      if (item.isDeleted()) {
        logger.debug("[get] Key: {} has been deleted. Returning null", key);
        return null;
      }
      logger.debug("[get] Key: {} with version: {} found in \"{}\".", key, item.getVersion(), kind.getNamespace());
      return item;
    } finally {
      lock.readLock().unlock();
    }
  }

  @Override
  public  Map all(VersionedDataKind kind) {
    try {
      lock.readLock().lock();
      Map fs = new HashMap<>();
      Map items = allData.get(kind);
      if (items != null) {
        for (Map.Entry entry : items.entrySet()) {
          if (!entry.getValue().isDeleted()) {
            fs.put(entry.getKey(), kind.getItemClass().cast(entry.getValue()));
          }
        }
      }
      return fs;
    } finally {
      lock.readLock().unlock();
    }
  }

  @SuppressWarnings("unchecked")
  @Override
  public void init(Map, Map> allData) {
    try {
      lock.writeLock().lock();
      this.allData.clear();
      for (Map.Entry, Map> entry: allData.entrySet()) {
        this.allData.put(entry.getKey(), (Map)entry.getValue());
      }
      initialized = true;
    } finally {
      lock.writeLock().unlock();
    }
  }

  @Override
  public  void delete(VersionedDataKind kind, String key, int version) {
    try {
      lock.writeLock().lock();
      Map items = allData.get(kind);
      if (items == null) {
        items = new HashMap<>();
        allData.put(kind, items);
      }
      VersionedData item = items.get(key);
      if (item == null || item.getVersion() < version) {
        items.put(key, kind.makeDeletedItem(key, version));
      }
    } finally {
      lock.writeLock().unlock();
    }
  }

  @Override
  public  void upsert(VersionedDataKind kind, T item) {
    try {
      lock.writeLock().lock();
      Map items = (Map) allData.get(kind);
      if (items == null) {
        items = new HashMap<>();
        allData.put(kind, items);
      }
      VersionedData old = items.get(item.getKey());

      if (old == null || old.getVersion() < item.getVersion()) {
        items.put(item.getKey(), item);
      }
    } finally {
      lock.writeLock().unlock();
    }
  }

  @Override
  public boolean initialized() {
    return initialized;
  }

  /**
   * Does nothing; this class does not have any resources to release
   *
   * @throws IOException will never happen
   */
  @Override
  public void close() throws IOException {
    return;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy