|
Scala example source code file (CachedFileStorage.scala)
The Scala CachedFileStorage.scala source code/* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** \* */ package scala.xml package persistent import java.io.{ File, FileOutputStream } import java.nio.ByteBuffer import java.nio.channels.Channels import java.lang.Thread import scala.util.logging.Logged import scala.collection.Iterator /** <p> * Mutable storage of immutable xml trees. Everything is kept in memory, * with a thread periodically checking for changes and writing to file. * To ensure atomicity, two files are used, filename1 and '$'+filename1. * The implementation switches between the two, deleting the older one * after a complete dump of the database has been written. * </p> * * @author Burak Emir */ abstract class CachedFileStorage(private val file1: File) extends Thread with Logged { private val file2 = new File(file1.getParent, file1.getName+"$") /** either equals file1 or file2, references the next file in which updates will be stored */ private var theFile: File = null private def switch() = { theFile = if (theFile == file1) file2 else file1; } /** this storage modified since last modification check */ protected var dirty = false /** period between modification checks, in milliseconds */ protected val interval = 1000 /** finds and loads the storage file. subclasses should call this method * prior to any other, but only once, to obtain the initial sequence of nodes. */ protected def initialNodes: Iterator[Node] = (file1.exists, file2.exists) match { case (false,false) => theFile = file1 Iterator.empty case (true, true ) if (file1.lastModified < file2.lastModified) => theFile = file2 load case (true, _ ) => theFile = file1 load case _ => theFile = file2 load } /** returns an iterator over the nodes in this storage */ def nodes: Iterator[Node] /** adds a node, setting this.dirty to true as a side effect */ def += (e: Node): Unit /** removes a tree, setting this.dirty to true as a side effect */ def -= (e: Node): Unit /* loads and parses XML from file */ private def load: Iterator[Node] = { import scala.io.Source import scala.xml.parsing.ConstructingParser log("[load]\nloading "+theFile) val src = Source.fromFile(theFile) log("parsing "+theFile) val res = ConstructingParser.fromSource(src,false).document.docElem(0) switch log("[load done]") res.child.iterator } /** saves the XML to file */ private def save() = if (this.dirty) { log("[save]\ndeleting "+theFile); theFile.delete(); log("creating new "+theFile); theFile.createNewFile(); val fos = new FileOutputStream(theFile) val c = fos.getChannel() // @todo: optimize val storageNode = <nodes>{ nodes.toList } val w = Channels.newWriter(c, "utf-8") XML.write(w, storageNode, "utf-8", true, null) log("writing to "+theFile); w.close c.close fos.close dirty = false switch log("[save done]") } /** run method of the thread. remember to use start() to start a thread, not run. */ override def run = { log("[run]\nstarting storage thread, checking every "+interval+" ms"); while(true) { Thread.sleep( this.interval ); save } } /** forces writing of contents to the file, even if there has not been any update. */ def flush() = { this.dirty = true; save } } Other Scala examples (source code examples)Here is a short list of links related to this Scala CachedFileStorage.scala source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.