<commit_before>package com.twitter.util.tunable

import java.util.concurrent.ConcurrentHashMap
import java.util.function.BiFunction
import scala.annotation.varargs
import scala.collection.JavaConversions._
import scala.collection.mutable

/**
 * A Map that can be used to access [[Tunable]]s using [[TunableMap.Key]]s.
 */
private[twitter] abstract class TunableMap { self =>

  /**
   * Returns a [[Tunable]] for the given `key.id` in the [[TunableMap]]. If the [[Tunable]] is not
   * of type `T` or a subclass of type `T`, throws a [[ClassCastException]]
   */
  def apply[T](key: TunableMap.Key[T]): Tunable[T]

  /**
   * Returns an Iterator over [[TunableMap.Entry]] for each [[Tunable]] in the map with a value.
   */
  private[tunable] def entries: Iterator[TunableMap.Entry[_]]

  /**
   * Compose this [[TunableMap]] with another [[TunableMap]]. [[Tunables]] retrieved from
   * the composed map prioritize the values of [[Tunables]] in the this map over the other
   * [[TunableMap]].
   */
  def orElse(that: TunableMap): TunableMap = (self, that) match {
    case (NullTunableMap, map) => map
    case (map, NullTunableMap) => map
    case _ => new TunableMap with TunableMap.Composite {
      def apply[T](key: TunableMap.Key[T]): Tunable[T] =
        self(key).orElse(that(key))

      def entries: Iterator[TunableMap.Entry[_]] = {
        val dedupedTunables = mutable.Map.empty[String, TunableMap.Entry[_]]
        that.entries.foreach { case entry@TunableMap.Entry(key, _) =>
          dedupedTunables.put(key.id, entry)
        }

        // entries in `self` take precedence.
        self.entries.foreach { case entry@TunableMap.Entry(key, _) =>
          dedupedTunables.put(key.id, entry)
        }
        dedupedTunables.valuesIterator
      }

      def components: Seq[TunableMap] =
        Seq(self, that)
    }
  }
}

private[twitter] object TunableMap {

  /**
   * A marker interface in support of [[components(TunableMap)]]
   */
  private trait Composite {
    def components: Seq[TunableMap]
  }

  /**
   * Get the component [[TunableMap]]s that make up `tunableMap`. For Composite [[TunableMap]]s,
   * this returns a Seq of the components. Otherwise, it returns a Seq of `tunableMap`.
   * 
   * Used for testing.
   */
  def components(tunableMap: TunableMap): Seq[TunableMap] = {
    tunableMap match {
      case composite: Composite =>
        composite.components.flatMap(components)
      case _ =>
        Seq(tunableMap)
    }
  }

  private case class TypeAndTunable[T](tunableType: Class[T], tunable: Tunable.Mutable[T])

  private[tunable] case class Entry[T](key: TunableMap.Key[T], value: T)

  /**
   * Class used to retrieve a [[Tunable]] with id `id` of type `T`.
   */
  final case class Key[T](id: String, clazz: Class[T])

  /**
   * Create a [[TunableMap]] out of the given [[TunableMap TunableMaps]].
   *
   * If `tunableMaps` is empty, [[NullTunableMap]] will be returned.
   */
  @varargs
  def of(tunableMaps: TunableMap*): TunableMap = {
    val start: TunableMap = NullTunableMap
    tunableMaps.foldLeft(start) { case (acc, tm) =>
      acc.orElse(tm)
    }
  }

  /**
   * A [[TunableMap]] that forwards all calls to `underlying`.
   */
  private[twitter] trait Proxy extends TunableMap {

    protected def underlying: TunableMap

    def apply[T](key: TunableMap.Key[T]): Tunable[T] =
      underlying(key)

    def entries: Iterator[TunableMap.Entry[_]] = underlying.entries
  }

  object Key {
    def apply[T](id: String)(implicit m: Manifest[T]): Key[T] =
      Key[T](id, m.runtimeClass.asInstanceOf[Class[T]])
  }
  
  /**
   * A [[TunableMap]] that can be updated via `put` and `clear` operations. Putting
   * a value for a given `id` will update the current value for the `id`, or create
   * a new [[Tunable]] if it does not exist. The type of the new value must match that of the
   * existing value, or a [[ClassCastException]] will be thrown.
   *
   * `apply` returns a [[Tunable]] for a given [[TunableMap.Key]] and creates it if does not already
   * exist. Updates to the [[TunableMap]] update the underlying [[Tunable]]s; for example, a
   * [[Tunable]] returned from `TunableMap.apply` will produce an updated value when
   * `Tunable.apply()` is called if the [[TunableMap]] is updated. `clear` clears the
   * underlying [[Tunable]] for a given [[TunableMap.Key]] but does not remove it from the map; this
   * has the effect that calling `Tunable.apply()` on a previously retrieved [[Tunable]] produces
   * `None`. This behavior is desirable because a [[Tunable]]'s value may be cleared and re-set,
   * and we want [[Tunable]] applications to see those updates.
   */
  abstract class Mutable extends TunableMap {

    /**
     * Update map to have the contents of `newMap`.
     *
     * Updates to each [[Tunable]] in the map are atomic, but the change
     * is not atomic at the macro level.
     */
    private[tunable] def replace(newMap: TunableMap): Unit = {
      val currEntries = entries.toSeq
      val newEntries = newMap.entries.toSeq

      // clear keys no longer present
      (currEntries.map(_.key).toSet -- newEntries.map(_.key).toSet).foreach { key =>
        clear(key)
      }

      // add/update new tunable values
      newEntries.foreach { case TunableMap.Entry(key, value) =>
        put(key.id, key.clazz, value)
      }
    }

    /**
     * Java-friendly API
     */
    def put[T](id: String, clazz: Class[T], value: T): Key[T]

    /**
     * Put a [[Tunable]] with id `id` and value `value` into the [[TunableMap]]. If the [[Tunable]]
     * for that `id` already exists, update the value to `value`.
     */
    final def put[T](id: String, value: T)(implicit m: Manifest[T]): Key[T] =
      put[T](id, m.runtimeClass.asInstanceOf[Class[T]], value)

    /**
     * Clear a [[Tunable]] in [[TunableMap]]. This does not remove the Tunable from the Map, but
     * rather clears its value such that applying it will produce `None`.
     */
    def clear[T](key: Key[T]): Unit
  }
<commit_msg>twitter-server, util-tunable: Endpoint to update Tunables<commit_after>package com.twitter.util.tunable

import java.util.concurrent.ConcurrentHashMap
import java.util.function.BiFunction
import scala.annotation.varargs
import scala.collection.JavaConversions._
import scala.collection.mutable

/**
 * A Map that can be used to access [[Tunable]]s using [[TunableMap.Key]]s.
 */
private[twitter] abstract class TunableMap { self =>

  /**
   * Returns a [[Tunable]] for the given `key.id` in the [[TunableMap]]. If the [[Tunable]] is not
   * of type `T` or a subclass of type `T`, throws a [[ClassCastException]]
   */
  def apply[T](key: TunableMap.Key[T]): Tunable[T]

  /**
   * Returns an Iterator over [[TunableMap.Entry]] for each [[Tunable]] in the map with a value.
   */
  private[tunable] def entries: Iterator[TunableMap.Entry[_]]

  /**
   * Compose this [[TunableMap]] with another [[TunableMap]]. [[Tunables]] retrieved from
   * the composed map prioritize the values of [[Tunables]] in the this map over the other
   * [[TunableMap]].
   */
  def orElse(that: TunableMap): TunableMap = (self, that) match {
    case (NullTunableMap, map) => map
    case (map, NullTunableMap) => map
    case _ => new TunableMap with TunableMap.Composite {
      def apply[T](key: TunableMap.Key[T]): Tunable[T] =
        self(key).orElse(that(key))

      def entries: Iterator[TunableMap.Entry[_]] = {
        val dedupedTunables = mutable.Map.empty[String, TunableMap.Entry[_]]
        that.entries.foreach { case entry@TunableMap.Entry(key, _) =>
          dedupedTunables.put(key.id, entry)
        }

        // entries in `self` take precedence.
        self.entries.foreach { case entry@TunableMap.Entry(key, _) =>
          dedupedTunables.put(key.id, entry)
        }
        dedupedTunables.valuesIterator
      }

      def components: Seq[TunableMap] =
        Seq(self, that)
    }
  }
}

private[twitter] object TunableMap {

  /**
   * A marker interface in support of [[components(TunableMap)]]
   */
  private trait Composite {
    def components: Seq[TunableMap]
  }

  /**
   * Get the component [[TunableMap]]s that make up `tunableMap`. For Composite [[TunableMap]]s,
   * this returns a Seq of the components. Otherwise, it returns a Seq of `tunableMap`.
   * 
   * Used for testing.
   */
  def components(tunableMap: TunableMap): Seq[TunableMap] =
    tunableMap match {
      case composite: Composite =>
        composite.components.flatMap(components)
      case _ =>
        Seq(tunableMap)
    }
 
  private case class TypeAndTunable[T](tunableType: Class[T], tunable: Tunable.Mutable[T])

  private[tunable] case class Entry[T](key: TunableMap.Key[T], value: T)

  /**
   * Class used to retrieve a [[Tunable]] with id `id` of type `T`.
   */
  final case class Key[T](id: String, clazz: Class[T])

  /**
   * Create a [[TunableMap]] out of the given [[TunableMap TunableMaps]].
   *
   * If `tunableMaps` is empty, [[NullTunableMap]] will be returned.
   */
  @varargs
  def of(tunableMaps: TunableMap*): TunableMap = {
    val start: TunableMap = NullTunableMap
    tunableMaps.foldLeft(start) { case (acc, tm) =>
      acc.orElse(tm)
    }
  }

  /**
   * A [[TunableMap]] that forwards all calls to `underlying`.
   */
  private[twitter] trait Proxy extends TunableMap {

    protected def underlying: TunableMap

    def apply[T](key: TunableMap.Key[T]): Tunable[T] =
      underlying(key)

    def entries: Iterator[TunableMap.Entry[_]] = underlying.entries
  }

  object Key {
    def apply[T](id: String)(implicit m: Manifest[T]): Key[T] =
      Key[T](id, m.runtimeClass.asInstanceOf[Class[T]])
  }
  
  /**
   * A [[TunableMap]] that can be updated via `put` and `clear` operations. Putting
   * a value for a given `id` will update the current value for the `id`, or create
   * a new [[Tunable]] if it does not exist. The type of the new value must match that of the
   * existing value, or a [[ClassCastException]] will be thrown.
   *
   * `apply` returns a [[Tunable]] for a given [[TunableMap.Key]] and creates it if does not already
   * exist. Updates to the [[TunableMap]] update the underlying [[Tunable]]s; for example, a
   * [[Tunable]] returned from `TunableMap.apply` will produce an updated value when
   * `Tunable.apply()` is called if the [[TunableMap]] is updated. `clear` clears the
   * underlying [[Tunable]] for a given [[TunableMap.Key]] but does not remove it from the map; this
   * has the effect that calling `Tunable.apply()` on a previously retrieved [[Tunable]] produces
   * `None`. This behavior is desirable because a [[Tunable]]'s value may be cleared and re-set,
   * and we want [[Tunable]] applications to see those updates.
   */
  abstract class Mutable extends TunableMap {

    /**
     * Update map to have the contents of `newMap`.
     *
     * Updates to each [[Tunable]] in the map are atomic, but the change
     * is not atomic at the macro level.
     */
    private[tunable] def replace(newMap: TunableMap): Unit = {

      // clear keys no longer present
      (entries.map(_.key).toSet -- newMap.entries.map(_.key).toSet).foreach { key =>
        clear(key)
      }

      // add/update new tunable values
      ++= (newMap)
    }

    /**
     * Add all entries in `that` [[TunableMap]] to this [[TunableMap]]. Entries already present in
     * this map are updated. Updates to each [[Tunable]] in the map are atomic, but the change
     * is not atomic at the macro level.
     */
    private[twitter] def ++=(that: TunableMap): Unit =
      that.entries.foreach { case TunableMap.Entry(key, value) =>
        put(key.id, key.clazz, value)
      }

    /**
     * Java-friendly API
     */
    def put[T](id: String, clazz: Class[T], value: T): Key[T]

    /**
     * Put a [[Tunable]] with id `id` and value `value` into the [[TunableMap]]. If the [[Tunable]]
     * for that `id` already exists, update the value to `value`.
     */
    final def put[T](id: String, value: T)(implicit m: Manifest[T]): Key[T] =
      put[T](id, m.runtimeClass.asInstanceOf[Class[T]], value)

    /**
     * Clear a [[Tunable]] in [[TunableMap]]. This does not remove the Tunable from the Map, but
     * rather clears its value such that applying it will produce `None`.
     */
    def clear[T](key: Key[T]): Unit
  }

{'fraction_non_alphanumeric': 0.1295770073881627, 'fraction_numerical': 0.0, 'mean_word_length': 3.0882841022236973, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 4, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7392839', 'n_tokens_mistral': 4101, 'n_tokens_neox': 4027, 'n_words': 1249}