From 98e2821b38a775737e42a2479a6bc65107210859 Mon Sep 17 00:00:00 2001 From: Elliot Kroo Date: Thu, 11 Mar 2010 15:21:30 -0800 Subject: reorganizing the first level of folders (trunk/branch folders are not the git way :) --- infrastructure/net.appjet.oui/servermodel.scala | 209 ++++++++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 infrastructure/net.appjet.oui/servermodel.scala (limited to 'infrastructure/net.appjet.oui/servermodel.scala') diff --git a/infrastructure/net.appjet.oui/servermodel.scala b/infrastructure/net.appjet.oui/servermodel.scala new file mode 100644 index 0000000..1e2363f --- /dev/null +++ b/infrastructure/net.appjet.oui/servermodel.scala @@ -0,0 +1,209 @@ +/** + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS-IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.appjet.oui; + +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import scala.collection.mutable.{HashSet, SynchronizedSet}; +import java.util.concurrent.ConcurrentHashMap; + +import net.appjet.bodylock.{BodyLock, JSCompileException}; + +object ScopeReuseManager { + // reset handling. + // val filesToWatch = new ConcurrentHashMap[CachedFile, Unit]; + // def watch(libs: DiskLibrary*) { + // for(lib <- libs) { + // filesToWatch.put(lib,()); + // } + // } + val t = new java.util.TimerTask { + def run() { + try { + // val t1 = System.currentTimeMillis; + // var doReset = false; + // val libIter = filesToWatch.keySet.iterator; + // while (libIter.hasNext) { + // if (libIter.next.hasBeenModified) { + // doReset = true; + // } + // } + // val t2 = System.currentTimeMillis; + // val elapsedMs = (t2 -t1).toInt; + // if (elapsedMs >= 500) { + // eventlog(Map( + // "type" -> "event", + // "event" -> "scopereusefilewatcher-slowtask", + // "elapsedMs" -> elapsedMs + // )); + // } + if (FileCache.testFiles()) { + reset(); + } + } catch { + case e => e.printStackTrace(); + } + } + } + val timerPeriod = if (! config.devMode) 5000 else 500; + val timer = new java.util.Timer(true); + timer.schedule(t, timerPeriod, timerPeriod); + + // scope handling + val mainLib = new VariableDiskLibrary("main.js"); + val preambleLib = new FixedDiskLibrary(new SpecialJarOrNotFile(config.ajstdlibHome, "preamble.js")); + val postambleLib = new FixedDiskLibrary(new SpecialJarOrNotFile(config.ajstdlibHome, "postamble.js")); + def mainExecutable = mainLib.executable; + def preambleExecutable = preambleLib.executable; + def postambleExecutable = postambleLib.executable; + + val mainGlobalScope = BodyLock.newScope; + + val nextId = new AtomicLong(0); + val freeRunners = new ConcurrentLinkedQueue[Runner](); + var lastReset = new AtomicLong(0); + val resetLock = new ReentrantReadWriteLock(true); + def readLocked[E](block: => E): E = { + resetLock.readLock().lock(); + try { + block; + } finally { + resetLock.readLock().unlock(); + } + } + def writeLocked[E](block: => E): E = { + resetLock.writeLock().lock(); + try { + block; + } finally { + resetLock.writeLock().unlock(); + } + } + + case class Runner(val globalScope: org.mozilla.javascript.Scriptable) { + var count = 0; + val created = timekeeper.time; + val id = nextId.incrementAndGet(); + val mainScope = BodyLock.subScope(globalScope); + var reuseOk = true; + var trace: Option[Array[StackTraceElement]] = None; + override def finalize() { + trace.foreach(t => eventlog(Map( + "type" -> "error", + "error" -> "unreleased runner", + "runnerId" -> id, + "trace" -> t.mkString("\n")))); + super.finalize(); + } + val attributes = new scala.collection.mutable.HashMap[String, Object]; + } + + def newRunner = { + // watch(mainLib, preambleLib, postambleLib); + val startTime = System.currentTimeMillis(); + val scope = BodyLock.subScope(mainGlobalScope); + val r = Runner(scope); + ExecutionContextUtils.withContext(ExecutionContext(null, null, r)) { +// scope.put("_appjetcontext_", scope, ); + preambleExecutable.execute(scope); + mainExecutable.execute(r.mainScope); + postambleExecutable.execute(scope); + val endTime = System.currentTimeMillis(); + eventlog(Map( + "type" -> "event", + "event" -> "runner-created", + "latency" -> (endTime - startTime).toString(), + "runnerId" -> r.id)); + } + r; + } + + def getRunner = readLocked { + val runner = freeRunners.poll(); + if (runner == null) { + newRunner; + } else { + if (config.devMode) { + runner.trace = Some(Thread.currentThread().getStackTrace()); + } + runner; + } + } + + def getEmpty(block: Runner => Unit): Runner = readLocked { + // watch(preambleLib, postambleLib); + val scope = BodyLock.newScope; + val r = Runner(scope); +// scope.put("_appjetcontext_", scope, ExecutionContext(null, null, r)); + ExecutionContextUtils.withContext(ExecutionContext(null, null, r)) { + preambleExecutable.execute(scope); + block(r); + postambleExecutable.execute(scope); + } + r; + } + + def getEmpty: Runner = getEmpty(r => {}); + + def freeRunner(r: Runner) { + r.trace = None; + if (r.reuseOk && r.created > lastReset.get()) { + freeRunners.offer(r); + } else { + if (r.reuseOk) { + eventlog(Map( + "type" -> "event", + "event" -> "runner-discarded", + "runnerId" -> r.id)); + } else { + eventlog(Map( + "type" -> "event", + "event" -> "runner-retired", + "runnerId" -> r.id)); + } + } + } + + lazy val resetExecutable = (new FixedDiskLibrary(new SpecialJarOrNotFile(config.ajstdlibHome, "onreset.js"))).executable; + def runOnReset() { + execution.runOutOfBand(resetExecutable, "Reset", None, { error => + error match { + case e: JSCompileException => { } + case e: Throwable => { exceptionlog(e); } + case (sc: Int, msg: String) => { exceptionlog("Reset failed: "+msg); } + case x => exceptionlog("Reset failed: "+String.valueOf(x)); + } + }); + } + + def reset() = writeLocked { + eventlog(Map( + "type" -> "event", + "event" -> "files-reset")); + // filesToWatch.clear(); + lastReset.set(timekeeper.time); + freeRunners.clear(); + runOnReset(); + } + + eventlog(Map( + "type" -> "event", + "event" -> "server-restart")); +} + -- cgit v1.2.3