Skip to content

Instantly share code, notes, and snippets.

@frgomes
Last active January 5, 2016 17:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save frgomes/f027f696299c624666f3 to your computer and use it in GitHub Desktop.
Save frgomes/f027f696299c624666f3 to your computer and use it in GitHub Desktop.
Scala - cache2k with underlying file storage
import net.jcip.annotations.NotThreadSafe
import org.cache2k.impl.ClockProPlusCache
type ImageType = Array[Byte]
class CacheSource(dir: java.io.File)
extends org.cache2k.CacheSource[String, ImageType] {
import java.nio.file.Files
import javax.imageio.ImageIO
override def get(key: String): ImageType = {
val path = dir.toPath.resolve(key.concat(".png"))
if (Files.exists(path)) {
toBytes(ImageIO.read(path.toFile))
} else {
throw new RuntimeException(s"Cannot find image identified by ${key}")
}
}
def put(key: String, value: ImageType): Option[ImageType] =
if(value!=null){
val file = dir.toPath.resolve(key.concat(".png")).toFile
ImageIO.write(Screencaster.toImage(value), "png", file)
Some(value)
} else {
None:Option[ImageType]
}
private def toBytes(image: BufferedImage): ImageType = {
val bo = new ByteArrayOutputStream()
ImageIO.write(image, "png", bo)
bo.close()
bo.toByteArray
}
}
@NotThreadSafe
class Cache(val cacheDir: String, val cacheSize: Int) {
import java.io.File
private val dir: File = open
private val source = new CacheSource(dir)
private val images =
org.cache2k.CacheBuilder
.newCache(classOf[String], classOf[ImageType])
.name(dir.getName)
.maxSize(cacheSize)
.implementation(classOf[ClockProPlusCache[String, ImageType]])
.source(source)
.build
/** Returns the value associated with `key`, or None if non-existent. */
def get(key: String): Option[ImageType] = {
val value = images.get(key)
if(value != null) Some(value) else None:Option[ImageType]
}
/** Inserts or updates Updates the `value` associated to a `key`. */
def put(key: String, value: ImageType) : Option[ImageType] =
if(value != null) {
val existing = images.peek(key)
if(existing != null) Some(existing) else source.put(key, value)
} else {
images.remove(key)
None:Option[ImageType]
}
/** Creates the cache directory. */
def open(): java.io.File = {
val dir = new File(cacheDir.replace("~", System.getProperty("user.home")))
if(dir.isDirectory) dir else {
if(dir.mkdirs()) dir else {
throw new RuntimeException(s"cannot create cache ${dir.getAbsolutePath}")
}
}
}
/** Closes the cache and ensures that all transient data is flushed onto the underlying persistence storage. */
def close(): Unit = images.close()
/** Purges the cache. */
def purge(): Unit = images.purge()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment