Browse Source

Split play-scala into play-scala and play-scala-anorm

The directory was previously called 'play-scala' and the display name
was 'play-scala-anorm'. They are now split as follows:
* a non-database part with a directory and display names of
  'play-scala' and 'play-scala-windows'.
* a database/anorm part with a directory and display names of
  'play-scala-anorm' and `play-scala-anorm-windows'.
Rich Dougherty 11 years ago
parent
commit
85b62f389b

+ 1 - 0
.travis.yml

@@ -102,6 +102,7 @@ env:
     - TESTDIR=play-java-ebean
     - TESTDIR=play-java-ebean
     - TESTDIR=play-java-jpa
     - TESTDIR=play-java-jpa
     - TESTDIR=play-scala
     - TESTDIR=play-scala
+    - TESTDIR=play-scala-anorm
     - TESTDIR=play-scala-mongodb
     - TESTDIR=play-scala-mongodb
     - TESTDIR=play-slick
     - TESTDIR=play-slick
     - TESTDIR=pyramid
     - TESTDIR=pyramid

+ 33 - 0
play-scala-anorm/.gitignore

@@ -0,0 +1,33 @@
+logs
+project/project
+project/target
+public
+target
+test
+tmp
+.history
+dist
+conf/evolutions
+
+# Ignore all dotfiles...
+.*
+# except for .gitignore
+!.gitignore
+
+# Ignore Play! working directory #
+db
+eclipse
+lib
+log
+logs
+modules
+precompiled
+project/project
+project/target
+target
+tmp
+test-result
+server.pid
+*.iml
+*.eml
+

+ 20 - 0
play-scala-anorm/README.md

@@ -0,0 +1,20 @@
+#Play Benchmarking Test
+
+This is the Play portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+### Data-Store/Database Mapping Test
+
+* [Database test controller](app/controllers/Application.scala)
+* [Database test model](app/models/World.scala)
+
+## Infrastructure Software Versions
+The tests were run with:
+
+* [Java OpenJDK 1.7.0_09](http://openjdk.java.net/)
+* [Play 2](http://http://www.playframework.com/)
+
+## Test URLs
+
+### Data-Store/Database Mapping Test
+
+http://localhost/db?queries=5

+ 0 - 0
play-scala-anorm/__init__.py


+ 88 - 0
play-scala-anorm/app/controllers/Application.scala

@@ -0,0 +1,88 @@
+package controllers
+
+import play.api.Play.current
+import play.api.mvc._
+import play.api.libs.json.Json
+import java.util.concurrent._
+import scala.concurrent._
+import models.{World, Fortune}
+import utils._
+import scala.concurrent.Future
+
+import play.api.libs.concurrent.Execution.Implicits._
+import play.core.NamedThreadFactory
+
+object Application extends Controller {
+
+  private val MaxQueriesPerRequest = 20
+  private val TestDatabaseRows = 10000
+
+  private val partitionCount = current.configuration.getInt("db.default.partitionCount").getOrElse(2)
+  private val maxConnections =
+    partitionCount * current.configuration.getInt("db.default.maxConnectionsPerPartition").getOrElse(5)
+  private val minConnections =
+    partitionCount * current.configuration.getInt("db.default.minConnectionsPerPartition").getOrElse(5)
+
+  private val tpe = new ThreadPoolExecutor(minConnections, maxConnections,
+    0L, TimeUnit.MILLISECONDS,
+    new LinkedBlockingQueue[Runnable](),
+    new NamedThreadFactory("dbEc"))
+  private val dbEc = ExecutionContext.fromExecutorService(tpe)
+
+  // A predicate for checking our ability to service database requests is determined by ensuring that the request
+  // queue doesn't fill up beyond a certain threshold. For convenience we use the max number of connections * the max
+  // # of db requests per web request to determine this threshold. It is a rough check as we don't know how many
+  // queries we're going to make or what other threads are running in parallel etc. Nevertheless, the check is
+  // adequate in order to throttle the acceptance of requests to the size of the pool.
+  def isDbAvailable: Boolean = tpe.getQueue.size() < maxConnections * MaxQueriesPerRequest
+
+  def db(queries: Int) = PredicatedAction(isDbAvailable, ServiceUnavailable) {
+    Action.async {
+      val random = ThreadLocalRandom.current()
+
+      val worlds = Future.sequence((for {
+        _ <- 1 to queries
+      } yield Future(World.findById(random.nextInt(TestDatabaseRows) + 1))(dbEc)
+        ).toList)
+
+      worlds map {
+        w => Ok(Json.toJson(w))
+      }
+    }
+  }
+
+  def fortunes() = PredicatedAction(isDbAvailable, ServiceUnavailable) {
+    Action.async {
+      Future(Fortune.getAll())(dbEc).map { fs =>
+        val fortunes =  Fortune(0.toLong, "Additional fortune added at request time.") +: fs
+        Ok(views.html.fortune(fortunes))
+      }
+    }
+  }
+
+  def update(queries: Int) = PredicatedAction(isDbAvailable, ServiceUnavailable) {
+    Action.async {
+      val random = ThreadLocalRandom.current()
+
+      val boundsCheckedQueries = queries match {
+        case q if q > 500 => 500
+        case q if q <   1 => 1
+        case _ => queries
+      }
+
+      val worlds = Future.sequence((for {
+        _ <- 1 to boundsCheckedQueries
+      } yield Future {
+          val world = World.findById(random.nextInt(TestDatabaseRows) + 1)
+          val updatedWorld = world.copy(randomNumber = random.nextInt(TestDatabaseRows) + 1)
+          World.updateRandom(updatedWorld)
+          updatedWorld
+        }(dbEc)
+      ).toList)
+
+      worlds.map {
+        w => Ok(Json.toJson(w)).withHeaders("Server" -> "Netty")
+      }
+    }
+  }
+}

+ 0 - 0
play-scala/app/models/Fortune.scala → play-scala-anorm/app/models/Fortune.scala


+ 0 - 0
play-scala/app/models/World.scala → play-scala-anorm/app/models/World.scala


+ 0 - 0
play-scala/app/utils/PredicatedAction.scala → play-scala-anorm/app/utils/PredicatedAction.scala


+ 0 - 0
play-scala/app/views/fortune.scala.html → play-scala-anorm/app/views/fortune.scala.html


+ 0 - 0
play-scala/app/views/main.scala.html → play-scala-anorm/app/views/main.scala.html


+ 47 - 0
play-scala-anorm/benchmark_config

@@ -0,0 +1,47 @@
+{
+  "framework": "play-scala-anorm",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "db_url": "/db",
+      "query_url": "/db?queries=",
+      "fortune_url": "/fortunes",
+      "update_url": "/update?queries=",
+      "port": 9000,
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "MySQL",
+      "framework": "play2",
+      "language": "Scala",
+      "orm": "Full",
+      "platform": "Netty",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "play-scala-anorm",
+      "notes": "",
+      "versus": "netty"
+    },
+    "windows-default": {
+      "setup_file": "setup",
+      "db_url": "/db",
+      "query_url": "/db?queries=",
+      "fortune_url": "/fortunes",
+      "update_url": "/update?queries=",
+      "port": 9000,
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "MySQL",
+      "framework": "play2",
+      "language": "Scala",
+      "orm": "Full",
+      "platform": "Netty",
+      "webserver": "None",
+      "os": "Windows",
+      "database_os": "Linux",
+      "display_name": "play-scala-anorm-windows",
+      "notes": "",
+      "versus": "netty"
+    }
+  }]
+}

+ 9 - 0
play-scala-anorm/build.sbt

@@ -0,0 +1,9 @@
+name := "play-scala-anorm"
+
+version := "1.0-SNAPSHOT"
+
+libraryDependencies ++= Seq(jdbc, anorm, "mysql" % "mysql-connector-java" % "5.1.22")
+
+dependencyOverrides += "com.jolbox" % "bonecp" % "0.7.1.RELEASE"
+
+playScalaSettings

+ 66 - 0
play-scala-anorm/conf/application.conf

@@ -0,0 +1,66 @@
+# This is the main configuration file for the application.
+# ~~~~~
+
+# Secret key
+# ~~~~~
+# The secret key is used to secure cryptographics functions.
+# If you deploy your application to several instances be sure to use the same key!
+application.secret="RItx1I:80?W@]8GAtPDuF8Ydd3mXM85p/<7og]Q;uBOdijQAauRDgu73B6`wQP59"
+
+# The application languages
+# ~~~~~
+application.langs="en"
+
+# Global object class
+# ~~~~~
+# Define the Global object class for this application.
+# Default to Global in the root package.
+# global=Global
+
+# Database configuration
+# ~~~~~ 
+# You can declare as many datasources as you want.
+# By convention, the default datasource is named `default`
+#
+#db.default.driver=org.h2.Driver
+#db.default.url="jdbc:h2:mem:play"
+#db.default.user=sa
+# db.default.password=
+#
+# You can expose this datasource via JNDI if needed (Useful for JPA)
+# db.default.jndiName=DefaultDS
+db.default.driver= com.mysql.jdbc.Driver
+db.default.url="jdbc:mysql://localhost:3306/hello_world?jdbcCompliantTruncation=false&elideSetAutoCommits=true&useLocalSessionState=true&cachePrepStmts=true&cacheCallableStmts=true&alwaysSendSetIsolation=false&prepStmtCacheSize=4096&cacheServerConfiguration=true&prepStmtCacheSqlLimit=2048&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useUnbufferedInput=false&useReadAheadInput=false&maintainTimeStats=false&useServerPrepStmts&cacheRSMetadata=true"
+db.default.user=benchmarkdbuser
+db.default.password=benchmarkdbpass
+db.default.jndiName=DefaultDS
+
+db.default.partitionCount=4
+
+# The number of connections to create per partition. Setting this to 
+# 5 with 3 partitions means you will have 15 unique connections to the 
+# database. Note that BoneCP will not create all these connections in 
+# one go but rather start off with minConnectionsPerPartition and 
+# gradually increase connections as required.
+db.default.maxConnectionsPerPartition=64
+
+# The number of initial connections, per partition.
+db.default.minConnectionsPerPartition=64
+
+# Evolutions
+# ~~~~~
+# You can disable evolutions if needed
+# evolutionplugin=disabled
+
+# Logger
+# ~~~~~
+# You can also configure logback (http://logback.qos.ch/), by providing a logger.xml file in the conf directory .
+
+# Root logger:
+logger.root=ERROR
+
+# Logger used by the framework:
+logger.play=ERROR
+
+# Logger provided to your application:
+logger.application=ERROR

+ 11 - 0
play-scala-anorm/conf/routes

@@ -0,0 +1,11 @@
+# Routes
+# This file defines all application routes (Higher priority routes first)
+# ~~~~
+
+# Home page
+GET     /db                             controllers.Application.db(queries: Int ?= 1)
+GET     /fortunes                       controllers.Application.fortunes
+GET     /update                         controllers.Application.update(queries: Int ?= 1)
+
+# Map static resources from the /public folder to the /assets URL path
+GET     /assets/*file                   controllers.Assets.at(path="/public", file)

+ 1 - 0
play-scala-anorm/project/build.properties

@@ -0,0 +1 @@
+sbt.version=0.13.0

+ 8 - 0
play-scala-anorm/project/plugins.sbt

@@ -0,0 +1,8 @@
+// Comment to get more information during initialization
+logLevel := Level.Warn
+
+// The Typesafe repository 
+resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
+
+// Use the Play sbt plugin for Play projects
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.2.0")

+ 33 - 0
play-scala-anorm/setup.py

@@ -0,0 +1,33 @@
+import setup_util
+import subprocess
+import os
+
+def start(args, logfile, errfile):
+  kill_running_process() # Kill the running process and delete the 
+                         # RUNNING_PID file (if any). With any luck no 
+                         # new process has picked up the same PID.
+
+  play_cmd = "play"
+  if args.os.lower() == "windows":
+    play_cmd = "play.bat"
+  
+  setup_util.replace_text("play-scala/conf/application.conf", "jdbc:mysql:\/\/.*:3306", "jdbc:mysql://" + args.database_host + ":3306")
+  subprocess.Popen([play_cmd,"start"], stdin=subprocess.PIPE, cwd="play-scala-anorm", stderr=errfile, stdout=logfile)
+  return 0
+
+def stop(logfile, errfile):
+  kill_running_process()  
+  return 0
+
+def kill_running_process():
+  try:
+    with open("./play-scala-anorm/RUNNING_PID") as f:
+      pid = int(f.read())
+      os.kill(pid, 15)
+  except:
+  	pass
+
+  try:
+    os.remove("play-scala-anorm/RUNNING_PID")
+  except OSError:
+    pass  

+ 11 - 0
play-scala-anorm/source_code

@@ -0,0 +1,11 @@
+./play-scala/app/
+./play-scala/app/controllers
+./play-scala/app/controllers/Application.scala
+./play-scala/app/views
+./play-scala/app/views/main.scala.html
+./play-scala/app/views/fortune.scala.html
+./play-scala/app/utils
+./play-scala/app/utils/PredicatedAction.scala
+./play-scala/app/models
+./play-scala/app/models/Fortune.scala
+./play-scala/app/models/World.scala

+ 2 - 11
play-scala/README.md

@@ -6,22 +6,13 @@ This is the Play portion of a [benchmarking test suite](../) comparing a variety
 
 
 * [JSON test source](app/controllers/Application.scala)
 * [JSON test source](app/controllers/Application.scala)
 
 
-### Data-Store/Database Mapping Test
-
-* [Database test controller](app/controllers/Application.scala)
-* [Database test model](app/models/World.scala)
-
 ## Infrastructure Software Versions
 ## Infrastructure Software Versions
 The tests were run with:
 The tests were run with:
 
 
 * [Java OpenJDK 1.7.0_09](http://openjdk.java.net/)
 * [Java OpenJDK 1.7.0_09](http://openjdk.java.net/)
-* [Play 2.1.0](http://http://www.playframework.com/)
+* [Play 2](http://http://www.playframework.com/)
 
 
 ## Test URLs
 ## Test URLs
 ### JSON Encoding Test
 ### JSON Encoding Test
 
 
-http://localhost/json
-
-### Data-Store/Database Mapping Test
-
-http://localhost/db?queries=5
+http://localhost/json

+ 0 - 81
play-scala/app/controllers/Application.scala

@@ -1,93 +1,12 @@
 package controllers
 package controllers
 
 
-import play.api.Play.current
 import play.api.mvc._
 import play.api.mvc._
 import play.api.libs.json.Json
 import play.api.libs.json.Json
-import java.util.concurrent._
-import scala.concurrent._
-import models.{World, Fortune}
-import utils._
-import scala.concurrent.Future
-
-import play.api.libs.concurrent.Execution.Implicits._
-import play.core.NamedThreadFactory
 
 
 object Application extends Controller {
 object Application extends Controller {
 
 
-  private val MaxQueriesPerRequest = 20
-  private val TestDatabaseRows = 10000
-
-  private val partitionCount = current.configuration.getInt("db.default.partitionCount").getOrElse(2)
-  private val maxConnections =
-    partitionCount * current.configuration.getInt("db.default.maxConnectionsPerPartition").getOrElse(5)
-  private val minConnections =
-    partitionCount * current.configuration.getInt("db.default.minConnectionsPerPartition").getOrElse(5)
-
-  private val tpe = new ThreadPoolExecutor(minConnections, maxConnections,
-    0L, TimeUnit.MILLISECONDS,
-    new LinkedBlockingQueue[Runnable](),
-    new NamedThreadFactory("dbEc"))
-  private val dbEc = ExecutionContext.fromExecutorService(tpe)
-
-  // A predicate for checking our ability to service database requests is determined by ensuring that the request
-  // queue doesn't fill up beyond a certain threshold. For convenience we use the max number of connections * the max
-  // # of db requests per web request to determine this threshold. It is a rough check as we don't know how many
-  // queries we're going to make or what other threads are running in parallel etc. Nevertheless, the check is
-  // adequate in order to throttle the acceptance of requests to the size of the pool.
-  def isDbAvailable: Boolean = tpe.getQueue.size() < maxConnections * MaxQueriesPerRequest
-
-
   def json() = Action {
   def json() = Action {
     Ok(Json.obj("message" -> "Hello, World!"))
     Ok(Json.obj("message" -> "Hello, World!"))
   }
   }
 
 
-  def db(queries: Int) = PredicatedAction(isDbAvailable, ServiceUnavailable) {
-    Action.async {
-      val random = ThreadLocalRandom.current()
-
-      val worlds = Future.sequence((for {
-        _ <- 1 to queries
-      } yield Future(World.findById(random.nextInt(TestDatabaseRows) + 1))(dbEc)
-        ).toList)
-
-      worlds map {
-        w => Ok(Json.toJson(w))
-      }
-    }
-  }
-
-  def fortunes() = PredicatedAction(isDbAvailable, ServiceUnavailable) {
-    Action.async {
-      Future(Fortune.getAll())(dbEc).map { fs =>
-        val fortunes =  Fortune(0.toLong, "Additional fortune added at request time.") +: fs
-        Ok(views.html.fortune(fortunes))
-      }
-    }
-  }
-
-  def update(queries: Int) = PredicatedAction(isDbAvailable, ServiceUnavailable) {
-    Action.async {
-      val random = ThreadLocalRandom.current()
-
-      val boundsCheckedQueries = queries match {
-        case q if q > 500 => 500
-        case q if q <   1 => 1
-        case _ => queries
-      }
-
-      val worlds = Future.sequence((for {
-        _ <- 1 to boundsCheckedQueries
-      } yield Future {
-          val world = World.findById(random.nextInt(TestDatabaseRows) + 1)
-          val updatedWorld = world.copy(randomNumber = random.nextInt(TestDatabaseRows) + 1)
-          World.updateRandom(updatedWorld)
-          updatedWorld
-        }(dbEc)
-      ).toList)
-
-      worlds.map {
-        w => Ok(Json.toJson(w)).withHeaders("Server" -> "Netty")
-      }
-    }
-  }
 }
 }

+ 4 - 12
play-scala/benchmark_config

@@ -4,14 +4,10 @@
     "default": {
     "default": {
       "setup_file": "setup",
       "setup_file": "setup",
       "json_url": "/json",
       "json_url": "/json",
-      "db_url": "/db",
-      "query_url": "/db?queries=",
-      "fortune_url": "/fortunes",
-      "update_url": "/update?queries=",
       "port": 9000,
       "port": 9000,
       "approach": "Realistic",
       "approach": "Realistic",
       "classification": "Fullstack",
       "classification": "Fullstack",
-      "database": "MySQL",
+      "database": "None",
       "framework": "play2",
       "framework": "play2",
       "language": "Scala",
       "language": "Scala",
       "orm": "Full",
       "orm": "Full",
@@ -19,21 +15,17 @@
       "webserver": "None",
       "webserver": "None",
       "os": "Linux",
       "os": "Linux",
       "database_os": "Linux",
       "database_os": "Linux",
-      "display_name": "play-scala-anorm",
+      "display_name": "play-scala",
       "notes": "",
       "notes": "",
       "versus": "netty"
       "versus": "netty"
     },
     },
     "windows-default": {
     "windows-default": {
       "setup_file": "setup",
       "setup_file": "setup",
       "json_url": "/json",
       "json_url": "/json",
-      "db_url": "/db",
-      "query_url": "/db?queries=",
-      "fortune_url": "/fortunes",
-      "update_url": "/update?queries=",
       "port": 9000,
       "port": 9000,
       "approach": "Realistic",
       "approach": "Realistic",
       "classification": "Fullstack",
       "classification": "Fullstack",
-      "database": "MySQL",
+      "database": "None",
       "framework": "play2",
       "framework": "play2",
       "language": "Scala",
       "language": "Scala",
       "orm": "Full",
       "orm": "Full",
@@ -41,7 +33,7 @@
       "webserver": "None",
       "webserver": "None",
       "os": "Windows",
       "os": "Windows",
       "database_os": "Linux",
       "database_os": "Linux",
-      "display_name": "play-scala-anorm",
+      "display_name": "play-scala-windows",
       "notes": "",
       "notes": "",
       "versus": "netty"
       "versus": "netty"
     }
     }

+ 0 - 4
play-scala/build.sbt

@@ -2,8 +2,4 @@ name := "play-scala"
 
 
 version := "1.0-SNAPSHOT"
 version := "1.0-SNAPSHOT"
 
 
-libraryDependencies ++= Seq(jdbc, anorm, "mysql" % "mysql-connector-java" % "5.1.22")
-
-dependencyOverrides += "com.jolbox" % "bonecp" % "0.7.1.RELEASE"
-
 playScalaSettings
 playScalaSettings

+ 0 - 35
play-scala/conf/application.conf

@@ -17,41 +17,6 @@ application.langs="en"
 # Default to Global in the root package.
 # Default to Global in the root package.
 # global=Global
 # global=Global
 
 
-# Database configuration
-# ~~~~~ 
-# You can declare as many datasources as you want.
-# By convention, the default datasource is named `default`
-#
-#db.default.driver=org.h2.Driver
-#db.default.url="jdbc:h2:mem:play"
-#db.default.user=sa
-# db.default.password=
-#
-# You can expose this datasource via JNDI if needed (Useful for JPA)
-# db.default.jndiName=DefaultDS
-db.default.driver= com.mysql.jdbc.Driver
-db.default.url="jdbc:mysql://localhost:3306/hello_world?jdbcCompliantTruncation=false&elideSetAutoCommits=true&useLocalSessionState=true&cachePrepStmts=true&cacheCallableStmts=true&alwaysSendSetIsolation=false&prepStmtCacheSize=4096&cacheServerConfiguration=true&prepStmtCacheSqlLimit=2048&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useUnbufferedInput=false&useReadAheadInput=false&maintainTimeStats=false&useServerPrepStmts&cacheRSMetadata=true"
-db.default.user=benchmarkdbuser
-db.default.password=benchmarkdbpass
-db.default.jndiName=DefaultDS
-
-db.default.partitionCount=4
-
-# The number of connections to create per partition. Setting this to 
-# 5 with 3 partitions means you will have 15 unique connections to the 
-# database. Note that BoneCP will not create all these connections in 
-# one go but rather start off with minConnectionsPerPartition and 
-# gradually increase connections as required.
-db.default.maxConnectionsPerPartition=64
-
-# The number of initial connections, per partition.
-db.default.minConnectionsPerPartition=64
-
-# Evolutions
-# ~~~~~
-# You can disable evolutions if needed
-# evolutionplugin=disabled
-
 # Logger
 # Logger
 # ~~~~~
 # ~~~~~
 # You can also configure logback (http://logback.qos.ch/), by providing a logger.xml file in the conf directory .
 # You can also configure logback (http://logback.qos.ch/), by providing a logger.xml file in the conf directory .

+ 0 - 3
play-scala/conf/routes

@@ -4,9 +4,6 @@
 
 
 # Home page
 # Home page
 GET     /json                           controllers.Application.json
 GET     /json                           controllers.Application.json
-GET     /db                             controllers.Application.db(queries: Int ?= 1)
-GET     /fortunes                       controllers.Application.fortunes
-GET     /update                         controllers.Application.update(queries: Int ?= 1)
 
 
 # Map static resources from the /public folder to the /assets URL path
 # Map static resources from the /public folder to the /assets URL path
 GET     /assets/*file                   controllers.Assets.at(path="/public", file)
 GET     /assets/*file                   controllers.Assets.at(path="/public", file)

+ 0 - 1
play-scala/setup.py

@@ -11,7 +11,6 @@ def start(args, logfile, errfile):
   if args.os.lower() == "windows":
   if args.os.lower() == "windows":
     play_cmd = "play.bat"
     play_cmd = "play.bat"
   
   
-  setup_util.replace_text("play-scala/conf/application.conf", "jdbc:mysql:\/\/.*:3306", "jdbc:mysql://" + args.database_host + ":3306")
   subprocess.Popen([play_cmd,"start"], stdin=subprocess.PIPE, cwd="play-scala", stderr=errfile, stdout=logfile)
   subprocess.Popen([play_cmd,"start"], stdin=subprocess.PIPE, cwd="play-scala", stderr=errfile, stdout=logfile)
   return 0
   return 0