cachedfilestorage.scala

来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 124 行

SCALA
124
字号
/*                     __                                               *\**     ________ ___   / /  ___     Scala API                            ****    / __/ __// _ | / /  / _ |    (c) 2002-2007, LAMP/EPFL             ****  __\ \/ /__/ __ |/ /__/ __ |    http://scala-lang.org/               **** /____/\___/_/ |_/____/_/ | |                                         ****                          |/                                          **\*                                                                      */// $Id: CachedFileStorage.scala 14634 2008-04-12 00:56:51Z emir $package scala.xml.persistentimport java.io.{File, FileOutputStream} import java.nio.ByteBufferimport java.nio.channels.Channels /** <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 java.lang.Thread with scala.util.logging.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.elements  }    /** 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 }</nodes>    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  }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?