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

swaydb.core.queue.FileLimiter.scala Maven / Gradle / Ivy

There is a newer version: 0.15
Show newest version
/*
 * Copyright (c) 2019 Simer Plaha (@simerplaha)
 *
 * This file is a part of SwayDB.
 *
 * SwayDB is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * SwayDB is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with SwayDB. If not, see .
 */
package swaydb.core.queue

import com.typesafe.scalalogging.LazyLogging
import java.nio.file.Path
import scala.concurrent.ExecutionContext
import scala.concurrent.duration._
import scala.ref.WeakReference
import swaydb.data.IO

private[swaydb] trait FileLimiter {

  def close(file: FileLimiterItem): Unit

  def delete(file: FileLimiterItem): Unit

  def terminate(): Unit

}

private[core] trait FileLimiterItem {
  def path: Path

  def delete(): IO[Unit]

  def close(): IO[Unit]

  def isOpen: Boolean
}

private[core] object FileLimiter extends LazyLogging {

  val empty =
    new FileLimiter {
      override def close(file: FileLimiterItem): Unit = ()
      override def delete(file: FileLimiterItem): Unit = ()
      override def terminate(): Unit = ()
    }

  private sealed trait Action {
    def isDelete: Boolean
  }
  private object Action {
    case class Delete(file: FileLimiterItem) extends Action {
      def isDelete: Boolean = true
    }
    case class Close(file: WeakReference[FileLimiterItem]) extends Action {
      def isDelete: Boolean = false
    }
  }

  def weigher(action: Action) =
    if (action.isDelete) 10 else 1

  def apply(maxSegmentsOpen: Long, delay: FiniteDuration)(implicit ex: ExecutionContext): FileLimiter = {
    lazy val queue = LimitQueue[Action](maxSegmentsOpen, delay, weigher) {
      case Action.Delete(file) =>
        file.delete() onFailureSideEffect {
          error =>
            logger.error(s"Failed to delete file. ${file.path}", error.exception)
        }

      case Action.Close(file) =>
        file.get foreach {
          file =>
            file.close onFailureSideEffect {
              error =>
                logger.error(s"Failed to close file. ${file.path}", error.exception)
            }
        }
    }

    new FileLimiter {

      override def close(file: FileLimiterItem): Unit =
        queue ! Action.Close(new WeakReference[FileLimiterItem](file))

      //Delete should not be a WeakReference because Levels can
      //remove references to the file after eventualDelete is invoked.
      //If the file gets garbage collected due to it being WeakReference before
      //delete on the file is triggered, the physical file will remain on disk.
      override def delete(file: FileLimiterItem): Unit =
        queue ! Action.Delete(file)

      override def terminate(): Unit =
        queue.terminate()
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy