<commit_before>package scorex.crypto.ads.merkle

import java.io.File

import org.mapdb.{DBMaker, HTreeMap, Serializer}
import scorex.crypto.ads.Storage
import scorex.crypto.hash.CryptographicHash
import scorex.utils.ScorexLogging

import scala.util.{Failure, Success, Try}

class TreeStorage[HashFunction <: CryptographicHash](fileName: String, levels: Int)
  extends Storage[(Int, Long), Array[Byte]] with ScorexLogging {

  import TreeStorage._

  type Digest = HashFunction#Digest

  private val dbs =
    (0 to levels) map { n: Int =>
      DBMaker.fileDB(new File(fileName + n + ".mapDB"))
        .fileMmapEnableIfSupported()
        .closeOnJvmShutdown()
        .checksumEnable()
        .make()
    }

  private val maps: Map[Int, HTreeMap[Long, Digest]] = {
    val t = (0 to levels) map { n: Int =>
      val m: HTreeMap[Long, Digest] = dbs(n).hashMapCreate("map_" + n)
        .keySerializer(Serializer.LONG)
        .valueSerializer(Serializer.BYTE_ARRAY)
        .makeOrGet()
      n -> m
    }
    t.toMap
  }

  override def set(key: Key, value: Digest): Unit = Try {
    maps(key._1.asInstanceOf[Int]).put(key._2, value)
  }.recoverWith { case t: Throwable =>
    log.warn("Failed to set key:" + key, t)
    Failure(t)
  }

  override def close(): Unit = {
    commit()
    dbs.foreach(_.close())
  }

  override def commit(): Unit = dbs.foreach(_.commit())

  override def get(key: Key): Option[Digest] = Try(maps(key._1).get(key._2)) match {
    case Success(v) =>
      Option(v)

    case Failure(e) =>
      if (key._1 == 0) log.debug("Unable to load key for level 0: " + key)
      None
  }
}

object TreeStorage {
  type Level = Int
  type Position = Long
  type Key = (Level, Position)
}
<commit_msg>concrete typing in Storage parametrization<commit_after>package scorex.crypto.ads.merkle

import java.io.File

import org.mapdb.{DBMaker, HTreeMap, Serializer}
import scorex.crypto.ads.Storage
import scorex.crypto.hash.CryptographicHash
import scorex.utils.ScorexLogging

import scala.util.{Failure, Success, Try}

class TreeStorage[HashFunction <: CryptographicHash](fileName: String, levels: Int)
  extends Storage[(TreeStorage.Level, TreeStorage.Position), HashFunction#Digest] with ScorexLogging {

  import TreeStorage._

  type Digest = HashFunction#Digest

  private val dbs =
    (0 to levels) map { n: Int =>
      DBMaker.fileDB(new File(fileName + n + ".mapDB"))
        .fileMmapEnableIfSupported()
        .closeOnJvmShutdown()
        .checksumEnable()
        .make()
    }

  private val maps: Map[Int, HTreeMap[Long, Digest]] = {
    val t = (0 to levels) map { n: Int =>
      val m: HTreeMap[Long, Digest] = dbs(n).hashMapCreate("map_" + n)
        .keySerializer(Serializer.LONG)
        .valueSerializer(Serializer.BYTE_ARRAY)
        .makeOrGet()
      n -> m
    }
    t.toMap
  }

  override def set(key: Key, value: Digest): Unit = Try {
    maps(key._1.asInstanceOf[Int]).put(key._2, value)
  }.recoverWith { case t: Throwable =>
    log.warn("Failed to set key:" + key, t)
    Failure(t)
  }

  override def close(): Unit = {
    commit()
    dbs.foreach(_.close())
  }

  override def commit(): Unit = dbs.foreach(_.commit())

  override def get(key: Key): Option[Digest] = Try(maps(key._1).get(key._2)) match {
    case Success(v) =>
      Option(v)

    case Failure(e) =>
      if (key._1 == 0) log.debug("Unable to load key for level 0: " + key)
      None
  }
}

object TreeStorage {
  type Level = Int
  type Position = Long
  type Key = (Level, Position)
}

{'fraction_non_alphanumeric': 0.1327836224054592, 'fraction_numerical': 0.005117998294000569, 'mean_word_length': 3.1146198830409357, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, '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': '1459776', 'n_tokens_mistral': 1209, 'n_tokens_neox': 1180, 'n_words': 296}