瀏覽代碼

Merge remote-tracking branch 'TechEmpower/master' into master2

ikkez 11 年之前
父節點
當前提交
be626c6094
共有 100 個文件被更改,包括 3136 次插入410 次删除
  1. 61 4
      .gitignore
  2. 53 0
      HttpListener/HttpListener/Program.cs
  3. 65 10
      HttpListener/benchmark_config
  4. 1 0
      HttpListener/install.sh
  5. 20 2
      HttpListener/setup.ps1
  6. 4 4
      HttpListener/setup.py
  7. 13 0
      HttpListener/source_code
  8. 24 0
      LICENSE
  9. 290 271
      README.md
  10. 6 0
      WeberFramework/.gitignore
  11. 2 0
      WeberFramework/README.md
  12. 24 0
      WeberFramework/benchmark_config
  13. 3 0
      WeberFramework/install.sh
  14. 0 0
      WeberFramework/lang/.gitkeep
  15. 18 0
      WeberFramework/lib/app.ex
  16. 36 0
      WeberFramework/lib/config.ex
  17. 0 0
      WeberFramework/lib/controllers/.keep
  18. 13 0
      WeberFramework/lib/controllers/main.ex
  19. 0 0
      WeberFramework/lib/helpers/.keep
  20. 0 0
      WeberFramework/lib/models/.keep
  21. 9 0
      WeberFramework/lib/route.ex
  22. 0 0
      WeberFramework/lib/views/.keep
  23. 235 0
      WeberFramework/lib/views/Main.html
  24. 0 0
      WeberFramework/lib/views/layout/.keep
  25. 24 0
      WeberFramework/mix.exs
  26. 0 0
      WeberFramework/public/css/.keep
  27. 0 0
      WeberFramework/public/img/.keep
  28. 二進制
      WeberFramework/public/img/favicon.ico
  29. 235 0
      WeberFramework/public/index.html
  30. 0 0
      WeberFramework/public/js/.keep
  31. 18 0
      WeberFramework/setup_weber.py
  32. 7 0
      WeberFramework/start.sh
  33. 7 0
      WeberFramework/test/WeberFramework_test.exs
  34. 1 0
      WeberFramework/test/test_helper.exs
  35. 28 0
      activeweb/README.md
  36. 0 0
      activeweb/__init__.py
  37. 2 0
      activeweb/bash_profile.sh
  38. 45 0
      activeweb/benchmark_config
  39. 3 0
      activeweb/install.sh
  40. 115 0
      activeweb/pom.xml
  41. 4 0
      activeweb/scripts/README
  42. 1 0
      activeweb/scripts/instrument.sh
  43. 33 0
      activeweb/setup.py
  44. 14 0
      activeweb/source_code
  45. 31 0
      activeweb/src/main/java/app/config/AppBootstrap.java
  46. 39 0
      activeweb/src/main/java/app/config/AppControllerConfig.java
  47. 50 0
      activeweb/src/main/java/app/config/DbConfig.java
  48. 30 0
      activeweb/src/main/java/app/config/FreeMarkerConfig.java
  49. 32 0
      activeweb/src/main/java/app/config/RouteConfig.java
  50. 39 0
      activeweb/src/main/java/app/controllers/DatabaseController.java
  51. 41 0
      activeweb/src/main/java/app/controllers/FortunesController.java
  52. 26 0
      activeweb/src/main/java/app/controllers/HomeController.java
  53. 49 0
      activeweb/src/main/java/app/controllers/JsonController.java
  54. 35 0
      activeweb/src/main/java/app/controllers/PlaintextController.java
  55. 71 0
      activeweb/src/main/java/app/controllers/QueriesController.java
  56. 38 0
      activeweb/src/main/java/app/controllers/UpdatesController.java
  57. 31 0
      activeweb/src/main/java/app/models/Fortune.java
  58. 30 0
      activeweb/src/main/java/app/models/World.java
  59. 4 0
      activeweb/src/main/webapp/WEB-INF/jetty-env.xml
  60. 15 0
      activeweb/src/main/webapp/WEB-INF/resin-web.xml
  61. 20 0
      activeweb/src/main/webapp/WEB-INF/views/fortunes/index.ftl
  62. 24 0
      activeweb/src/main/webapp/WEB-INF/views/home/index.ftl
  63. 23 0
      activeweb/src/main/webapp/WEB-INF/views/layouts/default_layout.ftl
  64. 3 0
      activeweb/src/main/webapp/WEB-INF/views/layouts/footer.ftl
  65. 4 0
      activeweb/src/main/webapp/WEB-INF/views/layouts/header.ftl
  66. 7 0
      activeweb/src/main/webapp/WEB-INF/views/queries/index.ftl
  67. 3 0
      activeweb/src/main/webapp/WEB-INF/views/system/404.ftl
  68. 18 0
      activeweb/src/main/webapp/WEB-INF/views/system/error.ftl
  69. 30 0
      activeweb/src/main/webapp/WEB-INF/web.xml
  70. 74 0
      activeweb/src/main/webapp/css/main.css
  71. 88 0
      activeweb/src/main/webapp/js/aw.js
  72. 154 0
      activeweb/src/main/webapp/js/jquery-1.4.2.min.js
  73. 46 0
      activeweb/src/test/java/app/controllers/DatabaseControllerSpec.java
  74. 45 0
      activeweb/src/test/java/app/controllers/JsonControllerSpec.java
  75. 48 0
      activeweb/src/test/java/app/controllers/JsonHelper.java
  76. 65 10
      aspnet-stripped/benchmark_config
  77. 3 0
      aspnet-stripped/install.sh
  78. 19 1
      aspnet-stripped/setup_iis.ps1
  79. 4 4
      aspnet-stripped/setup_iis.py
  80. 14 0
      aspnet-stripped/source_code
  81. 8 10
      aspnet/README.md
  82. 234 28
      aspnet/benchmark_config
  83. 3 0
      aspnet/install.sh
  84. 二進制
      aspnet/lib/.nuget/NuGet.exe
  85. 2 2
      aspnet/lib/.nuget/NuGet.targets
  86. 7 7
      aspnet/lib/packages.config
  87. 1 1
      aspnet/nginx.conf
  88. 21 3
      aspnet/setup_iis.ps1
  89. 4 4
      aspnet/setup_iis.py
  90. 19 11
      aspnet/setup_nginx.py
  91. 7 7
      aspnet/setup_xsp.py
  92. 24 0
      aspnet/source_code
  93. 13 13
      aspnet/src/Benchmarks.AspNet.csproj
  94. 4 4
      aspnet/src/Web.config
  95. 15 1
      beego/benchmark_config
  96. 3 0
      beego/install.sh
  97. 10 9
      beego/setup.py
  98. 2 0
      beego/source_code
  99. 61 4
      beego/src/hello/hello.go
  100. 31 0
      benchmark.cfg.example

+ 61 - 4
.gitignore

@@ -1,10 +1,14 @@
 .DS_Store
-*.pyc
-installs/
+installs
 *.log
-*.lock
 node_modules/
-*.war
+
+# eclipse
+.classpath
+.project
+.settings
+
+# maven
 target/
 *.out
 *.class
@@ -12,6 +16,59 @@ mods/
 /.settings
 /.buildpath
 /.project
+*/src/main/java/META-INF/
+*.versionsBackup
+bin/
+
+# common junk
+*.log
+*.swp
+*.diff
+*.patch
+*/bin/
+
+# intellij
 *.iml
+*.ipr
+*.iws
 .idea/
 .hsenv/
+azure.err
+php-kohana/application/logs/
+php-fuel/fuel/app/logs/
+results/
+benchmark.cfg
+
+# Mac filesystem dust
+.DS_Store
+
+# pmd
+.pmdruleset
+.pmd
+
+# netbeans
+/nbproject
+
+# vim
+.*.sw[a-p]
+
+# merge tooling
+*.orig
+
+# maven
+*.versionsBackup
+*.releaseBackup
+
+# python-isms
+*.pyc
+
+# java / ruby stuff
+*.lock
+*.war
+
+# go
+go/pkg/*
+beego/pkg/*
+
+# urweb
+urweb/*.exe

+ 53 - 0
HttpListener/HttpListener/Program.cs

@@ -12,6 +12,8 @@ using System.Web.Script.Serialization;
 using MongoDB.Driver.Builders;
 
 using Benchmarks.AspNet.Models;
+using System.Reflection;
+using System.Runtime.InteropServices;
 
 namespace HttpListener
 {
@@ -111,6 +113,10 @@ namespace HttpListener
             {
                 listener.Start();
 
+                // Increase the HTTP.SYS backlog queue from the default of 1000 to 65535.
+                // To verify that this works, run `netsh http show servicestate`.
+                Network.Utils.HttpApi.SetRequestQueueLength(listener, 65535);
+
                 for (;;)
                 {
                     HttpListenerContext context = null;
@@ -401,3 +407,50 @@ namespace HttpListener
         }
     }
 }
+
+// Adapted from:
+// http://stackoverflow.com/questions/15417062/changing-http-sys-kernel-queue-limit-when-using-net-httplistener
+namespace Network.Utils
+{
+    public static class HttpApi
+    {
+        public static void SetRequestQueueLength(System.Net.HttpListener listener, uint len)
+        {
+            var listenerType = typeof(System.Net.HttpListener);
+            var requestQueueHandleProperty = listenerType.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance).First(p => p.Name == "RequestQueueHandle");
+
+            var requestQueueHandle = (CriticalHandle)requestQueueHandleProperty.GetValue(listener);
+            var result = HttpSetRequestQueueProperty(requestQueueHandle, HTTP_SERVER_PROPERTY.HttpServerQueueLengthProperty, ref len, (uint)Marshal.SizeOf(len), 0, IntPtr.Zero);
+
+            if (result != 0)
+            {
+                throw new HttpListenerException((int)result);
+            }
+        }
+
+        internal enum HTTP_SERVER_PROPERTY
+        {
+            HttpServerAuthenticationProperty,
+            HttpServerLoggingProperty,
+            HttpServerQosProperty,
+            HttpServerTimeoutsProperty,
+            HttpServerQueueLengthProperty,
+            HttpServerStateProperty,
+            HttpServer503VerbosityProperty,
+            HttpServerBindingProperty,
+            HttpServerExtendedAuthenticationProperty,
+            HttpServerListenEndpointProperty,
+            HttpServerChannelBindProperty,
+            HttpServerProtectionLevelProperty,
+        }
+
+        [DllImport("httpapi.dll", CallingConvention = CallingConvention.StdCall)]
+        internal static extern uint HttpSetRequestQueueProperty(
+            CriticalHandle requestQueueHandle,
+            HTTP_SERVER_PROPERTY serverProperty,
+            ref uint pPropertyInfo,
+            uint propertyInfoLength,
+            uint reserved,
+            IntPtr pReserved);
+    }
+}

+ 65 - 10
HttpListener/benchmark_config

@@ -3,51 +3,106 @@
   "tests": [{
     "default": {
       "setup_file": "setup",
-      "os": "nt",
       "json_url": "/json",
       "plaintext_url": "/plaintext",
       "port": 8080,
-      "sort": 150
+      "approach": "Realistic",
+      "classification": "Platform",
+      "database": "None",
+      "framework": "http-listener",
+      "language": "C#",
+      "orm": "Raw",
+      "platform": "NET",
+      "webserver": "HTTP.sys",
+      "os": "Windows",
+      "database_os": "Linux",
+      "display_name": "http-listener",
+      "notes": "",
+      "versus": ""
     },
     "mysql-raw": {
       "setup_file": "setup",
-      "os": "nt",
       "db_url": "/db?provider=mysql",
       "query_url": "/db?provider=mysql&queries=",
       "fortune_url": "/fortunes?provider=mysql",
       "update_url": "/updates?provider=mysql&queries=",
       "port": 8080,
-      "sort": 151
+      "approach": "Realistic",
+      "classification": "Platform",
+      "database": "MySQL",
+      "framework": "http-listener",
+      "language": "C#",
+      "orm": "Raw",
+      "platform": "NET",
+      "webserver": "HTTP.sys",
+      "os": "Windows",
+      "database_os": "Linux",
+      "display_name": "http-listener",
+      "notes": "",
+      "versus": "http-listener"
     },
     "postgresql-raw": {
       "setup_file": "setup",
-      "os": "nt",
       "db_url": "/db?provider=postgresql",
       "query_url": "/db?provider=postgresql&queries=",
       "fortune_url": "/fortunes?provider=postgresql",
       "update_url": "/updates?provider=postgresql&queries=",
       "port": 8080,
-      "sort": 152
+      "approach": "Realistic",
+      "classification": "Platform",
+      "database": "Postgres",
+      "framework": "http-listener",
+      "language": "C#",
+      "orm": "Raw",
+      "platform": "NET",
+      "webserver": "HTTP.sys",
+      "os": "Windows",
+      "database_os": "Linux",
+      "display_name": "http-listener",
+      "notes": "",
+      "versus": "http-listener"
     },
     "mongodb-raw": {
       "setup_file": "setup",
-      "os": "nt",
       "db_url": "/mongodbdb",
       "query_url": "/mongodbdb?queries=",
       "fortune_url": "/mongodbfortunes",
       "update_url": "/mongodbupdates?queries=",
       "port": 8080,
-      "sort": 153
+      "approach": "Realistic",
+      "classification": "Platform",
+      "database": "MongoDB",
+      "framework": "http-listener",
+      "language": "C#",
+      "orm": "Raw",
+      "platform": "NET",
+      "webserver": "HTTP.sys",
+      "os": "Windows",
+      "database_os": "Linux",
+      "display_name": "http-listener",
+      "notes": "",
+      "versus": "http-listener"
     },
     "sqlserver-raw": {
       "setup_file": "setup",
-      "os": "nt",
       "db_url": "/db?provider=sqlserver",
       "query_url": "/db?provider=sqlserver&queries=",
       "fortune_url": "/fortunes?provider=sqlserver",
       "update_url": "/updates?provider=sqlserver&queries=",
       "port": 8080,
-      "sort": 154
+      "approach": "Realistic",
+      "classification": "Platform",
+      "database": "SQLServer",
+      "framework": "http-listener",
+      "language": "C#",
+      "orm": "Raw",
+      "platform": "NET",
+      "webserver": "HTTP.sys",
+      "os": "Windows",
+      "database_os": "Windows",
+      "display_name": "http-listener",
+      "notes": "",
+      "versus": "http-listener"
     }
   }]
 }

+ 1 - 0
HttpListener/install.sh

@@ -0,0 +1 @@
+#!/bin/bash

+ 20 - 2
HttpListener/setup.ps1

@@ -1,14 +1,32 @@
 param($action)
 
+$ErrorActionPreference = 'Stop'
+
+# From http://zduck.com/2012/powershell-batch-files-exit-codes/
+function Exec
+{
+    [CmdletBinding()]
+    param (
+        [Parameter(Position=0, Mandatory=1)]
+        [scriptblock]$Command,
+        [Parameter(Position=1, Mandatory=0)]
+        [string]$ErrorMessage = "Execution of command failed.`n$Command"
+    )
+    & $Command
+    if ($LastExitCode -ne 0) {
+        throw "Exec: $ErrorMessage"
+    }
+}
+
 $root = "C:\FrameworkBenchmarks\HttpListener"
 $msbuild = "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe"
 
 # Stop
-Stop-Process -Name HttpListener -ErrorAction SilentlyContinue
+Get-Process | Where-Object { $_.Name -ieq "HttpListener" } | Stop-Process
 
 if ($action -eq 'start') {
     # Build the project
-    &$msbuild "$root\HttpListener.sln" /p:DownloadNuGetExe=true /p:RequireRestoreConsent=false /p:Configuration=Release /t:Rebuild
+    Exec { & $msbuild "$root\HttpListener.sln" /p:DownloadNuGetExe=true /p:RequireRestoreConsent=false /p:Configuration=Release /t:Rebuild }
     
     Start-Process "$root\HttpListener\bin\Release\HttpListener.exe"
 }

+ 4 - 4
HttpListener/setup.py

@@ -3,20 +3,20 @@ import sys
 import setup_util
 import os
 
-def start(args):
+def start(args, logfile, errfile):
   if os.name != 'nt':
     return 1
   
   try:
     setup_util.replace_text("HttpListener/HttpListener/App.config", "localhost", args.database_host)
-    subprocess.check_call("powershell -File setup.ps1 start", cwd="HttpListener")
+    subprocess.check_call("powershell -Command .\\setup.ps1 start", cwd="HttpListener", stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1
 
-def stop():
+def stop(logfile, errfile):
   if os.name != 'nt':
     return 0
   
-  subprocess.Popen("powershell -File setup.ps1 stop", cwd="HttpListener")
+  subprocess.check_call("powershell -Command .\\setup.ps1 stop", cwd="HttpListener", stderr=errfile, stdout=logfile)
   return 0

+ 13 - 0
HttpListener/source_code

@@ -0,0 +1,13 @@
+./HttpListener/HttpListener/
+./HttpListener/HttpListener/Models
+./HttpListener/HttpListener/Models/Fortune.cs
+./HttpListener/HttpListener/Models/MongoDB.cs
+./HttpListener/HttpListener/Models/World.cs
+./HttpListener/HttpListener/Fortunes.generated.cs
+./HttpListener/HttpListener/Fortunes.cshtml
+./HttpListener/HttpListener/HttpListener.csproj
+./HttpListener/HttpListener/Program.cs
+./HttpListener/HttpListener/packages.config
+./HttpListener/HttpListener/App.config
+./HttpListener/HttpListener/Properties
+./HttpListener/HttpListener/Properties/AssemblyInfo.cs

+ 24 - 0
LICENSE

@@ -0,0 +1,24 @@
+Copyright (c) 2013, TechEmpower, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the TechEmpower, Inc. nor the names of its
+      contributors may be used to endorse or promote products derived from
+      this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL TECHEMPOWER, INC. BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 290 - 271
README.md

@@ -6,172 +6,164 @@ Read more and see the results of our tests on Amazon EC2 and physical hardware a
 
 Join in the conversation at our Google Group: https://groups.google.com/forum/?fromgroups=#!forum/framework-benchmarks
 
-## Running the test suite
-
-We ran our tests using two dedicated i7 2600k machines as well as two EC2 m1.large instances. Below you will find instructions on how to replicate our tests using either EC2 or your own dedicated machines.
-
-###EC2 Instructions
-
-#### 1. Create EC2 Instances
-
-Create two EC2 instances running Ubuntu Server 12.04.1 LTS 64-bit. We tested on m1.large instances, but feel free to experiment with different configurations. Give the instance that will act as the application server more then the default 8GB of disk capacity (we used 20GB).
-
-##### Security Group
-
-When propmted to create a security group for the instances, here are the ports that you'll need to open.
-
-* 22 (SSH)
-* 8080 (Most of the tests run on 8080)
-* 3306 (MySQL)
-* 5432 (PostgreSQL)
-* 9000 (Play Framework)
-* 27017 (MongoDB)
-* 3000 (yesod)
-* 8000 (snap)
-* 16969 (cpoll)
-
-
-#### 2. Setting up the servers
-
-To coordinate the tests via scripting, the servers need to be able to work together. So once the instances are running, the first thing you'll want to do is copy your ssh key to the application server instance so that you can ssh between the two machines:
-
-	sftp -i path-to-pem-file ubuntu@server-instance-ip
-	put path-to-pem-file .ssh/
-	exit
-
-Now ssh into the server instance and clone the latest from this repository (the scripts we use to run the tests expect that you'll clone the repository into your home directory):
-
-	ssh -i path-to-pem-file ubuntu@server-instance-ip
-	yes | sudo apt-get install git-core
-	git clone https://github.com/TechEmpower/FrameworkBenchmarks.git
-	cd FrameworkBenchmarks
-
-Next, we're going to setup the servers with all the necessary software:
-
-	./run-tests.py -s server-private-ip -c client-private-ip -i path-to-pem --install-software --list-tests
-    source ~/.bash_profile
-    # For your first time through the tests, set the ulimit for open files
-    ulimit -n 8192
-    # Most software is installed autormatically by the script, but running the mongo command below from 
-    # the install script was causing some errors. For now this needs to be run manually.
-    cd installs/jruby-rack && rvm jruby-1.7.4 do jruby -S bundle exec rake clean gem SKIP_SPECS=true
-    cd target && rvm jruby-1.7.4 do gem install jruby-rack-1.2.0.SNAPSHOT.gem
-    cd ../../..
-    cd installs && curl -sS https://getcomposer.org/installer | php -- --install-dir=bin
-    cd ..
-    sudo apt-get remove --purge openjdk-6-jre openjdk-6-jre-headless
-	  mongo --host client-private-ip < config/create.js
-
-Assuming the above finished without error, we're ready to start the test suite:
-
-	nohup ./run-tests.py -s server-private-ip -c client-private-ip -i path-to-pem --max-threads number-of-cores &
-
-For the number-of-cores parameter, you will need to know your application server's core count. For example, Amazon EC2 large instances have 2 cores.
-
-This script will run the full set of tests. Results of all the tests will output to ~/FrameworkBenchmarks/results/ec2/*timestamp*. If you use a different configuration than two m1.large instances, please use the --name option to name the results appropriately.
-
-	nohup ./run-tests.py -s server-private-ip -c client-private-ip -i path-to-pem --max-threads cores --name ec2-servertype-clienttype &
-
-So if you were running an m1.large and an m1.medium, it would look like this:
-
-	nohup ./run-tests.py -s server-private-ip -c client-private-ip -i path-to-pem --max-threads cores --name ec2-m1.large-m1.medium &
-
-This will allow us to differentiate results.
-
-Be aware that on Large instances, if you include the slower frameworks (and they are included by default), the total runtime of a full suite of tests can be measured in days, not just hours. The EC2 bill isn't going to break the bank, but it's also not going to be chump change.
-
-### Dedicated Hardware Instructions
-
-If you have two servers or workstations lying around, then you can install and run the tests on physical hardware. Please be aware that these setup instructions can overwrite software and settings, It's best to follow these instructions on clean hardware. We assume that both machines are running Ubuntu Server 12.04 64-bit.
-
-#### 1. Prerequisites
-
-Before you get started, there are a couple of steps you can take to make running the tests easier on yourself. Since the tests can run for several hours, it helps to set everything up so that once the tests are running, you can leave the machines unattended and don't need to be around to enter ssh or sudo passwords.
-
-1. Setup an ssh key for the client machine
-2. Edit your sudoers file so that you do not need to enter your password for sudo access
-
-#### 2. Setting up the servers
-
-As it currently stands, the script that runs the tests makes some assumptions about where the code is placed, we assume that the FrameworkBenchmarks repository will be located in your home directory.
-
-Check out the latest from github:
-
-	cd ~
-	git clone https://github.com/TechEmpower/FrameworkBenchmarks.git
-	cd FrameworkBenchmarks
-
-Next, we're going to setup the servers with all the necessary software:
-
-	./run-tests.py -s server-ip -c client-ip -i path-to-ssh-key --install-software --list-tests
-    source ~/.bash_profile
-    # For your first time through the tests, set the ulimit for open files
-    # Most software is installed autormatically by the script, but running the mongo command below from
-    # the install script was causing some errors. For now this needs to be run manually.
-    cd installs/jruby-rack && rvm jruby-1.7.4 do jruby -S bundle exec rake clean gem SKIP_SPECS=true
-    cd target && rvm jruby-1.7.4 do gem install jruby-rack-1.2.0.SNAPSHOT.gem
-    cd ../../..
-    cd installs && curl -sS https://getcomposer.org/installer | php -- --install-dir=bin
-    cd ..
-    sudo apt-get remove --purge openjdk-6-jre openjdk-6-jre-headless
-    mongo --host client-ip < config/create.js
-
-Assuming this finished without error, we're ready to start the test suite:
-
-	nohup ./run-tests.py -s server-ip -c client-ip -i path-to-ssh-key --max-threads cores --name unique-machine-name &
-
-This will run the full set of tests. Results of all the tests will output to ~/FrameworkBenchmarks/results/unique-machine-name/*timestamp*.
-
-### Windows Instructions
-Generously provided by [@pdonald](https://github.com/pdonald)
-
-Server installation scripts for Windows Server 2012 R2 on Amazon EC2.
-
-Instructions:
-
-* Create an instance from the `Microsoft Windows Server 2012 Base` image on Amazon EC2
-* Connect to it via Remote Desktop
-* Copy `installer-bootstrap.ps1` from this repo to the server (for files CTRL-C + CTRL-V works alright)
-* Copy your client private key too while you're at it
-* Right click on the installer script and select `Run with PowerShell`
-* It will ask something, just hit enter
-* It will install git and then launch `installer.ps1` from the repo which will install everything else
-* Installation shouldn't take more than 5 to 10 minutes
-* Then you have a working console: try `python`, `git`, `ssh`, `curl`, `node` etc. everything works + PowerShell goodies
-
-The client/database machine is still assumed to be a Linux box, you can install just the client software via
-
-    python run-tests.py -s server-ip -c client-ip -i "C:\Users\Administrator\Desktop\client.key" --install-software --install client --list-tests
+### Prerequisites
+
+Before starting setup, all the required hosts must be provisioned, with the respective operating system and required software installed, and with connectivity for remote management (SSH on Linux, RDP and WinRM on Windows).
+
+Refer to [Benchmark Suite Deployment README file](toolset/deployment/README.md) for the provisioning procedures documentation.
+
+### App, load, and database servers
+
+**NOTE:** If testing a pull request or doing development, it is usually adequate to only use one computer. In that case, your server, client, and database IPs will be 127.0.0.1
+
+#### Installing the Framework Benchmark App Server
+
+* Install [Ubuntu 14.04](http://www.ubuntu.com/download/server) with username `tfb`. Ensure that OpenSSH is selected when you install. If not, run the following command
+```bash
+$ sudo apt-get install openssh-server
+```
+* If Ubuntu is already installed, run the following command and follow the prompts.
+```bash
+$ sudo adduser tfb
+$ sudo usermod -a -G sudo tfb
+```
+* Log in as `tfb`
+* Fully update **NOTE**: If you update the kernel (linux-firmware), it is generally a good idea to reboot aftewards.
+```bash
+$ sudo apt-get update && sudo apt-get upgrade
+```
+* Run the command: `sudo visudo`
+* Change line 20 in from `%sudo   ALL=(ALL:ALL) ALL` to `%sudo   ALL=NOPASSWD: ALL`
+* Run the following **(Don't enter a password, just hit enter when the prompt pops up)**. **NOTE** This is still necessary if the client and database are on the same computer as the server
+```bash
+$ ssh-keygen
+$ ssh-copy-id <database ip>
+$ ssh-copy-id <client ip>
+```
+* Install git and clone the Framework Benchmarks repository
+```bash
+$ sudo apt-get install git
+$ cd ~
+$ git clone https://github.com/TechEmpower/FrameworkBenchmarks.git
+$ cd FrameworkBenchmarks
+```
+* Install the server software. This will take a long time
+```bash
+$ nohup python toolset/run-tests.py -s <server hostname/ip> -c <client hostname/ip> -u tfb --install-software --install server --list-tests &
+```
+* If you want to view the process of installing, do the following. The session can be interrupted easily so no need to worry about keeping a connection.
+```bash
+$ tail -f nohup.out
+```
+* Reboot when the install is done
+* Edit your ~/.bashrc file to change the following
+ * Change `TFB_SERVER_HOST=<ip address>` to the server's IP address
+ * Change `TFB_CLIENT_HOST=<ip address>` to the client's ip address
+ * Change `TFB_DATABASE_HOST=<ip address>` to the database's ip address.
+ * Change `TFB_CLIENT_IDENTITY_FILE=<path>` to the id file you specified when you ran ssh-keygen (probably /home/tfb/.ssh/id_rsa if you don't know what it is)
+ * Run the command `source ~/.bashrc`
+* If you are setting up any other servers, do so before proceeding.
+* Run the following commands
+```bash
+cd ~/FrameworkBenchmarks
+source ~/.bash_profile
+# For your first time through the tests, set the ulimit for open files
+ulimit -n 8192
+# Most software is installed automatically by the script, but running the mongo command below from
+# the install script was causing some errors. For now this needs to be run manually.
+cd installs && curl -sS https://getcomposer.org/installer | php -- --install-dir=bin
+cd ..
+sudo apt-get remove --purge openjdk-6-jre openjdk-6-jre-headless
+# Change database-private-ip to the database ip
+mongo --host database-private-ip < config/create.js
+```
+* Before running the tests, do the following
+```bash
+$ source ~/.bashrc
+```
+
+---
+
+#### Installing the Framework Benchmark Database Server
+
+* Install [Ubuntu 14.04](http://www.ubuntu.com/download/server) with username `tfb`
+* Log in as `tfb`
+* Fully update **NOTE**: If you update the kernel (linux-firmware), it is generally a good idea to reboot aftewards.
+```bash
+$ sudo apt-get update && sudo apt-get upgrade
+```
+* Run the command: `sudo visudo`
+* Change line 20 in from `%sudo   ALL=(ALL:ALL) ALL` to `%sudo   ALL=NOPASSWD: ALL`
+* On the app server, run the following from the FrameworkBenchmark directory (this should only take a small amount of time, several minutes or so):
+```bash
+$ toolset/run-tests.py --install-software --install database --list-tests
+```
+
+---
+
+#### Installing the Framework Benchmark Load Server
+
+* Install [Ubuntu 14.04](http://www.ubuntu.com/download/server) with username `tfb`
+* Log in as `tfb`
+* Fully update **NOTE**: If you update the kernel (linux-firmware), it is generally a good idea to reboot aftewards.
+```bash
+$ sudo apt-get update && sudo apt-get upgrade
+```
+* Run the command: `sudo visudo`
+* Change line 20 in from `%sudo   ALL=(ALL:ALL) ALL` to `%sudo   ALL=NOPASSWD: ALL`
+* On the app server, run the following from the FrameworkBenchmark directory (this should only take a small amount of time, several minutes or so):
+```bash
+$ toolset/run-tests.py --install-software --install client --list-tests
+```
+
+You can validate that the setup worked by running a smoke test like this:
+
+    toolset/run-tests.py --max-threads 1 --name smoketest --test servlet-raw --type all -m verify
+
+This should run the verification step for a single framework.
+
+---
+
+#### Windows server setup
+
+* Connect to the Windows server via Remote Desktop.
+* Copy `installer-bootstrap.ps1` from "toolset/setup/windows" to the server (use CTRL-C and CTRL-V).
+* Copy your Linux client private key too.
+* Right click on the installer script and select `Run with PowerShell`.
+* Press Enter to confirm.
+* It will install git and then launch `installer.ps1` from the repository, which will install everything else.
+* The installation takes about 20 minutes.
+* Then you have a working console: try `python`, `git`, `ssh`, `curl`, `node` etc. and verify that everything works + PowerShell goodies.
+
+The client/database machine is still assumed to be a Linux box. You can install just the client software via
+
+    python toolset\run-tests.py -s server-private-ip -c client-private-ip -i "C:\Users\Administrator\Desktop\client.key" --install-software --install client --list-tests
+
+but this step is not required if you already installed the Linux server and client as described above.
 
 Now you can run tests:
 
-    python run-tests.py -s server-ip -c client-ip -i "C:\Users\Administrator\Desktop\client.key" --max-threads 2 --duration 30 --sleep 5 --name win --test aspnet --type all
+    python toolset\run-tests.py -s server-private-ip -c client-private-ip -i "C:\Users\Administrator\Desktop\client.key" --max-threads 2 --duration 30 --sleep 5 --name win --test aspnet --type all
 
+---
 
-### SQL Server on Windows Instructions
+#### SQL Server setup
 
-Server installation scripts for Windows Server 2012 with SQL Server 2012 Standard on Amazon EC2.
+* Connect to the SQL Server host via Remote Desktop.
+* Run a `Command Prompt` as Administrator.
+* Enter this command:
 
-Instructions:
+        powershell -ExecutionPolicy Bypass -Command "iex (New-Object Net.WebClient).DownloadString('https://raw.github.com/TechEmpower/FrameworkBenchmarks/master/toolset/setup/sqlserver/setup-sqlserver-bootstrap.ps1')"
 
-* Create an instance from the [Windows Server 2012 RTM English 64-bit SQL 2012 Standard](https://aws.amazon.com/amis/amazon-ebs-backed-windows-server-2012-rtm-english-64-bit-sql-2012-standard) image on Amazon EC2
-* Connect to it via Remote Desktop
-* Run a `Command Prompt` as Administrator
-* Enter `powershell -ExecutionPolicy Bypass -Command "iex (New-Object Net.WebClient).DownloadString('https://raw.github.com/TechEmpower/FrameworkBenchmarks/master/setup-sqlserver-bootstrap.ps1')"`
 * This will configure SQL Server, the Windows Firewall, and populate the database.
 
-Now, when running `python run-tests.py`, just add `-d <ip of SQL Server instance>`. This works for the (Windows Server-based) `aspnet-sqlserver-raw` and `aspnet-sqlserver-entityframework` tests.
+Now, when running `run-tests.py`, just add `-d <ip of SQL Server instance>`. This works for the (Windows Server-based) `aspnet-sqlserver-raw` and `aspnet-sqlserver-entityframework` tests.
 
+---
 
-## Result Files
-
-After a test run, the directory ~/FrameworkBenchmarks/results/machine-name/timestamp will contains all the result files. In this folder are four files: three CSV files, one for each of the test types (json, db, query), and a single results.json file that contains all the results as well as some additional information. The results.json file is what we use to drive our blog post, and may or may not be useful to you. There are three subdirectories: one for each of the test types (json, db, query), each of these directories contain the raw weighttp results for each framework.
-
-## Benchmarking a Single Test
-
-If you are making changes to any of the tests, or you simply want to verify a single test, you can run the script with the --test flag. For example, if you only wanted to run the JRuby tests:
+## Running the test suite
 
-	nohup ./run-tests.py -s server-ip -c client-ip -i path-to-ssh-key --max-threads cores --name unique-machine-name --test rack-jruby sinatra-jruby rails-jruby
+We ran our tests using three dedicated i7 2600k machines, three EC2 m1.large instances, and three servers from Peak Hosting
 
 ## Updating Tests
 
@@ -187,7 +179,7 @@ Also, if you do change the dependency of any test, please update the README file
 
 If you would like to update any of the software used, again, please be as specific as possible, while we still install some software via apt-get and don't specify a version, we would like to have as much control over the versions as possible.
 
-The main file that installs all the software is in installer.py. It's broken up into two sections, server software and client software.
+The main file that installs all the software is in `toolset/setup/linux/installer.py`. It's broken up into two sections, server software and client software.
 
 Additionally, it may be necessary to update the setup.py file in the framework's directory to use this new version.
 
@@ -201,143 +193,170 @@ When adding a new framework or new test to an existing framework, please follow
 * Update/add [setup file](#setup-files)
 * When creating a database test, please use the MySQL table hello_world.World, or the MongoDB collection hello_world.world
 
-There are three different tests that we currently run:
+### The Tests
 
-* JSON Response
-* Database (single query)
-* Database (multiple query)
+For descriptions of the test types that we run against each framework, see the [test requirements section of the Results web site](http://www.techempower.com/benchmarks/#section=code).
 
-The single query database test can be treated as a special case of the multiple query test with the query-count parameter set to 1.
-
-### JSON Response
-
-This test needs to follow the following conventions:
-
-* The message object should be instantiated as a new object for each request.
-* The test should use a JSON serializer to render the newly instantiated object to JSON.
-* Set the response Content-Type to application/json.
-* The response should be {"message": "Hello, World!"}
-* White space in the response does not matter.
-
-Pseudo-code:
-
-	obj = { message : "Hello, World!" }
-	render json.encode(obj)
-
-### Database (single query)
-
-This test will:
-
-* Access a database table or collection named "World" that is known to contain 10,000 rows/entries.
-* Query for a single row from the table or collection using a randomly generated id (the ids range from 1 to 10,000).
-* Set the response Content-Type to application/json.
-* Serialize the row to JSON and send the resulting string as the response.
-
-By convention, if the test does not use an ORM, and instead uses the raw database connectivity provided by the platform (e.g., JDBC), we append a "-raw" to the test name in the [benchmark_config](#the-benchmark_config-file) file.  For example, "php-raw".
-
-Pseudo-code:
-
-	random_id = random(1, 10000)
-	world = World.find(random_id)
-	render json.encode(world)
-
-### Database (multiple queries)
-
-This test is very similar to the single query test, and in some cases it will be implemented using the same code. A URL parameter is made available to specify the number of queries to run per request. The response is a list of objects resulting from the queries for random rows.
-
-Pseudo-code:
+## The benchmark_config File
 
-	number_of_queries = get("queries")
-	worlds = []
-	for i = 0; i < number_of_queries; i++
-        random_id = random(1, 10000)
-        worlds[i] = World.find(random_id)
-	render json.encode(worlds)
+The benchmark_config file is used by our scripts to both identify the available tests and to extract metadata describing each test.
 
-## The benchmark_config File
+This file should exist at the root of the test directory.
 
-The benchmark_config file is used by our run script to identify the available tests to be run. This file should exist at the root of the test directory. Here is its basic structure:
+Here is the basic structure of benchmark_config, using the Compojure framework as an example.  Compojure has two test *permutations*, which are identified as the "tests" list in the JSON structure below.
 
-	{
-      "framework": "my-framework",
+    {
+      "framework": "compojure",
       "tests": [{
         "default": {
-          "setup_file": "setup.py"
-          "json_url": "/json",
-          "db_url": "/db",
-          "query_url": "/db?queries=",
+          "setup_file": "setup",
+          "json_url": "/compojure/json",
+          "db_url": "/compojure/db/1",
+          "query_url": "/compojure/db/",
+          "fortune_url": "/compojure/fortune-hiccup",
+          "plaintext_url": "/compojure/plaintext",
           "port": 8080,
-          "sort": 32
-      }, {
-        "alternative": {
-          "setup_file": "alternate_setup.py"
-          "json_url": "/json",
-          "db_url": "/db",
-          "query_url": "/db?queries=",
+          "approach": "Realistic",
+          "classification": "Micro",
+          "database": "MySQL",
+          "framework": "compojure",
+          "language": "Clojure",
+          "orm": "Micro",
+          "platform": "Servlet",
+          "webserver": "Resin",
+          "os": "Linux",
+          "database_os": "Linux",
+          "display_name": "compojure",
+          "notes": "",
+          "versus": "servlet"
+        },
+        "raw": {
+          "setup_file": "setup",
+          "db_url": "/compojure/dbraw/1",
+          "query_url": "/compojure/dbraw/",
           "port": 8080,
-          "sort": 33
+          "approach": "Realistic",
+          "classification": "Micro",
+          "database": "MySQL",
+          "framework": "compojure",
+          "language": "Clojure",
+          "orm": "Raw",
+          "platform": "Servlet",
+          "webserver": "Resin",
+          "os": "Linux",
+          "database_os": "Linux",
+          "display_name": "compojure-raw",
+          "notes": "",
+          "versus": "servlet"
         }
       }]
-	}
+    }
 
 * framework: Specifies the framework name.
-* tests: An array of tests that can be run for this framework. In most cases, this contains a single element for the "default" test, but additional tests can be specified.
+* tests: An list of tests that can be run for this framework. In many cases, this contains a single element for the "default" test, but additional tests can be specified.  Each test name must be unique when concatenated with the framework name.
   * setup_file: The location of the [setup file](#setup-files) that can start and stop the test. By convention this is just setup.py.
-  * json_url (optional): The relative URL path to the JSON test
-  * db_url (optional): The relative URL path to the database test
-  * query_url (optional): The relative URL path to the variable query test. The URL must be set up so that an integer can be applied to the end of the url to specify the number of queries to run, i.e. /db?queries= or /db/
-  * port: The port the server is listneing on
-  * sort: The sort order. This is important for our own blog post which relies on consistent ordering of the frameworks. You can get the next available sort order by running:
-    ./run-tests.py --next-sort
+  * json_url (optional): The URI to the JSON test, typically `/json`
+  * db_url (optional): The URI to the database test, typically `/db`
+  * query_url (optional): The URI to the variable query test. The URI must be set up so that an integer can be applied to the end of the URI to specify the number of queries to run.  For example, "/query?queries=" (to yield /query?queries=20" or "/query/" to yield "/query/20".
+  * fortune_url (optional): the URI to the fortunes test, typically `/fortune`
+  * update_url (optional): the URI to the updates test, setup in a manner similar to the query_url described above.
+  * plaintext_url (optional): the URI of the plaintext test, typically `/plaintext`
+  * port: The port the server is listening on
+  * approach (metadata): `Realistic` or `Stripped` (see results web site for description of all metadata attributes)
+  * classification (metadata): `Full`, `Micro`, or `Platform`
+  * database (metadata): `MySQL`, `Postgres`, `MongoDB`, `SQLServer`, or `None`
+  * framework (metadata): name of the framework
+  * language (metadata): name of the language
+  * orm (metadata): `Full`, `Micro`, or `Raw`
+  * platform (metadata): name of the platform
+  * webserver (metadata): name of the web-server (also referred to as the "front-end server")
+  * os (metadata): The application server's operating system, `Linux` or `Windows`
+  * database_os (metadata): The database server's operating system, `Linux` or `Windows`
+  * display_name (metadata): How to render this test permutation's name in the results web site.  Some permutation names can be really long, so the display_name is provided in order to provide something more succinct.
+  * versus (optional): The name of another test (elsewhere in this project) that is a subset of this framework.  This allows for the generation of the framework efficiency chart in the results web site.  For example, Compojure is compared to "servlet" since Compojure is built on the Servlets platform.
+
+### Testing on both Windows and Linux
+
+If your framework and platform can execute on both Windows and Linux, we encourage you to specify tests for both operating systems.  This increases the amount of testing you should do before submitting your pull-request, however, so we understand if you start with just one of the two.
+
+The steps involved are:
+
+* Assuming you have implemeneted the Linux test already, add a new test permutation to your `benchmark_config` file for the Windows test (or vice-versa).  When the benchmark script runs on Linux, it skips tests where the Application Operating System (`os` in the file) is specified as Linux.  When running on Windows, it skips tests where the `os` field is Linux.
+* Add the necessary tweaks to your [setup file](#setup-files) to start and stop on the new operating system.  See, for example, [the script for Go](https://github.com/TechEmpower/FrameworkBenchmarks/blob/master/go/setup.py).
+* Test on Windows and Linux to make sure everything works as expected.
 
 ## Setup Files
 
 The setup file is responsible for starting and stopping the test. This script is responsible for (among other things):
 
-* Setting the database host to the correct IP
-* Compiling/packaging the code
+* Modifying the framework's configuration to point to the correct database host
+* Compiling and/or packaging the code
 * Starting the server
 * Stopping the server
 
-The setup file is a python file that contains a start() and a stop() function. Here is an example of Wicket's setup file.
-
-	import subprocess
-	import sys
-	import setup_util
-
-	##################################################
-	# start(args)
-	#
-	# Starts the server for Wicket
-	# returns 0 if everything completes, 1 otherwise
-	##################################################
-	def start(args):
-
-    # setting the database url
-    setup_util.replace_text("wicket/src/main/webapp/WEB-INF/resin-web.xml", "mysql:\/\/.*:3306", "mysql://" + args.database_host + ":3306")
-
-    # 1. Compile and package
-    # 2. Clean out possible old tests
-    # 3. Copy package to Resin's webapp directory
-    # 4. Start resin
-    try:
-      subprocess.check_call("mvn clean compile war:war", shell=True, cwd="wicket")
-      subprocess.check_call("rm -rf $RESIN_HOME/webapps/*", shell=True)
-      subprocess.check_call("cp wicket/target/hellowicket-1.0-SNAPSHOT.war $RESIN_HOME/webapps/wicket.war", shell=True)
-      subprocess.check_call("$RESIN_HOME/bin/resinctl start", shell=True)
-      return 0
-    except subprocess.CalledProcessError:
-      return 1
-
-	##################################################
-	# stop()
-	#
-	# Stops the server for Wicket
-	# returns 0 if everything completes, 1 otherwise
-	##################################################
-	def stop():
-    try:
-      subprocess.check_call("$RESIN_HOME/bin/resinctl shutdown", shell=True)
-      return 0
-    except subprocess.CalledProcessError:
-      return 1
+The setup file is a python script that contains a start() and a stop() function.  The start function should build the source, make any necessary changes to the framework's configuration, and then start the server.  The stop function should shutdown the server, including all sub-processes as applicable.
+
+### Configuring database connectivity in start()
+
+By convention, the configuration files used by a framework should specify the database server as `localhost` so that developing tests in a single-machine environment can be done in an ad hoc fashion, without using the benchmark scripts.
+
+When running a benchmark script, the script needs to modify each framework's configuration so that the framework connects to a database host provided as a command line argument.  In order to do this, use setup_util.replace_text() to make necessary modifications prior to starting the server.
+
+For example:
+
+```python
+setup_util.replace_text("wicket/src/main/webapp/WEB-INF/resin-web.xml", "mysql:\/\/.*:3306", "mysql://" + args.database_host + ":3306")
+```
+
+Using `localhost` in the raw configuration file is not a requirement as long as the `replace_text` call properly injects the database host provided to the benchmarker toolset as a command line argument.
+
+### A full example
+
+Here is an example of Wicket's setup file.
+
+```python
+import subprocess
+import sys
+import setup_util
+
+##################################################
+# start(args, logfile, errfile)
+#
+# Starts the server for Wicket
+# returns 0 if everything completes, 1 otherwise
+##################################################
+def start(args, logfile, errfile):
+
+# setting the database url
+setup_util.replace_text("wicket/src/main/webapp/WEB-INF/resin-web.xml", "mysql:\/\/.*:3306", "mysql://" + args.database_host + ":3306")
+
+# 1. Compile and package
+# 2. Clean out possible old tests
+# 3. Copy package to Resin's webapp directory
+# 4. Start resin
+try:
+  subprocess.check_call("mvn clean compile war:war", shell=True, cwd="wicket", stderr=errfile, stdout=logfile)
+  subprocess.check_call("rm -rf $RESIN_HOME/webapps/*", shell=True, stderr=errfile, stdout=logfile)
+  subprocess.check_call("cp wicket/target/hellowicket-1.0-SNAPSHOT.war $RESIN_HOME/webapps/wicket.war", shell=True, stderr=errfile, stdout=logfile)
+  subprocess.check_call("$RESIN_HOME/bin/resinctl start", shell=True, stderr=errfile, stdout=logfile)
+  return 0
+except subprocess.CalledProcessError:
+  return 1
+
+##################################################
+# stop(logfile, errfile)
+#
+# Stops the server for Wicket
+# returns 0 if everything completes, 1 otherwise
+##################################################
+def stop(logfile):
+try:
+  subprocess.check_call("$RESIN_HOME/bin/resinctl shutdown", shell=True, stderr=errfile, stdout=logfile)
+  return 0
+except subprocess.CalledProcessError:
+  return 1
+```
+      
+### A tool to generate your setup file ###
+ 
+A contributor named [@kpacha](https://github.com/kpacha) has built a pure JavaScript tool for generating the `setup.py` file for a new framework via an in-browser form.  Check out his [FrameworkBenchmarks Setup Builder](http://kpacha.github.io/FrameworkBenchmarks-setup-builder/).

+ 6 - 0
WeberFramework/.gitignore

@@ -0,0 +1,6 @@
+/ebin
+/deps
+erl_crash.dump
+/tmp
+_build
+/logs

+ 2 - 0
WeberFramework/README.md

@@ -0,0 +1,2 @@
+WeberFramework
+=====

+ 24 - 0
WeberFramework/benchmark_config

@@ -0,0 +1,24 @@
+{
+  "framework": "weber",
+  "tests": [{
+    "default": {
+      "setup_file": "setup_weber",
+      "json_url": "/json",
+      "plaintext_url": "/plaintext",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Platform",
+      "database": "Postgres",
+      "framework": "weber",
+      "language": "Elixir",
+      "orm": "Raw",
+      "platform": "Cowboy",
+      "webserver": "Cowboy",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "weber",
+      "notes": "",
+      "versus": "",
+      "skip": "false"
+  }}]
+}

+ 3 - 0
WeberFramework/install.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+fw_depends weber elixir

+ 0 - 0
go/pkg/.gitkeep → WeberFramework/lang/.gitkeep


+ 18 - 0
WeberFramework/lib/app.ex

@@ -0,0 +1,18 @@
+defmodule WeberFramework do
+
+  require Weber.Templates.ViewsLoader
+  
+  def start(_type, _args) do
+    # Set resources
+    Weber.Templates.ViewsLoader.set_up_resources(File.cwd!)
+    # compile all views
+    Weber.Templates.ViewsLoader.compile_views(File.cwd!)
+    # start weber application
+    Weber.run_weber
+  end
+
+  def stop(_state) do
+    :ok
+  end
+  
+end

+ 36 - 0
WeberFramework/lib/config.ex

@@ -0,0 +1,36 @@
+defmodule Config do 
+
+  def config do
+    [webserver: 
+      [http_host: "localhost", 
+       http_port: 8080,
+       acceptors: 100,
+       ssl: false,
+       cacertfile_path: "",
+       certfile_path: "",
+       keyfile_path: ""
+      ],
+    ws: 
+      [ws_port: 8080,
+       ws_mod: :Handler
+      ],
+    use_internationalization: false,
+    localization:
+      [default_locale: :en_US,
+       use_locales: [:en_US]
+      ],
+    use_sessions: false,
+    session:
+      [max_age: 1440
+      ],
+    db:
+      [
+        db_host: "",
+        db_port: 5000,
+        db_username: "",
+        db_password: ""
+      ],
+    ]
+  end
+
+end

+ 0 - 0
django-stripped/__init__.py → WeberFramework/lib/controllers/.keep


+ 13 - 0
WeberFramework/lib/controllers/main.ex

@@ -0,0 +1,13 @@
+defmodule WeberFramework.Main do
+  
+  use Weber.Controller
+
+  def action_json(_, _) do
+    {:json, [message: "Hello, world!"], [{"Content-type", "application/json"}]}
+  end
+
+  def action_text(_, _) do
+  	{:text, "Hello, world!", [{"Content-type", "text/plain"}]}
+  end
+
+end

+ 0 - 0
django-stripped/hello/hello/__init__.py → WeberFramework/lib/helpers/.keep


+ 0 - 0
django-stripped/hello/world/__init__.py → WeberFramework/lib/models/.keep


+ 9 - 0
WeberFramework/lib/route.ex

@@ -0,0 +1,9 @@
+defmodule Route do
+
+  import Weber.Route
+  require Weber.Route
+  
+  route on("GET", "/json", :WeberFramework.Main, :action_json)
+     |> on("GET", "/plaintext", :WeberFramework.Main, :action_text)
+
+end

+ 0 - 0
WeberFramework/lib/views/.keep


+ 235 - 0
WeberFramework/lib/views/Main.html

@@ -0,0 +1,235 @@
+<!DOCTYPE html>
+<html itemscope itemtype="http://schema.org/WebPage" lang="en">
+
+<head>
+  <meta charset="utf-8">
+  <title>Welcome to Weber!</title>
+  <link href="img/favicon.ico" rel="shortcut icon" type="image/vnd.microsoft.icon">
+
+  <style>
+    /* Reset */
+    * {
+      margin: 0;
+      padding: 0;
+    }
+
+    /* Default */
+    body {
+      font: normal 13px proxima-nova, sans-serif;
+      color: #666;
+    }
+
+    a {
+      color: #4c0066;
+    }
+
+    code, pre {
+      background: #f9f9f9;
+      border: 1px solid #ddd;
+      border-radius: 3px;
+      display: block;
+      font-family: monospace;
+      margin: 5px 0;
+      padding: 20px 0 20px 30px;
+      white-space: pre;
+    }
+
+    blockquote {
+      background: #f9f9f9;
+      border-left: 10px solid #eee;
+      border-radius: 3px;
+      color: #888;
+      margin: 20px 0 20px 20px;
+      padding: 10px 12px;
+      quotes: "\201C""\201D""\2018""\2019";
+    }
+
+    blockquote:before {
+      color: #ccc;
+      content: open-quote;
+      font-size: 55px;
+      line-height: 1px;
+      margin-right: 15px;
+      vertical-align: -25px;
+    }
+
+    blockquote p {
+      display: inline;
+    }
+
+    p {
+      font-size: 120%;
+      line-height: 25px;
+      margin: 10px 0;
+    }
+
+    /* Classes */
+    .content {
+      margin: 0 auto;
+      padding: 0 10px;
+      width: 960px;
+    }
+
+    /* Structure */
+    header:after, main:after,
+    header:before, main:before {
+      content: " ";
+      display: table;
+    }
+
+    header:after, main:after {
+      clear: both;
+    }
+
+    header {
+      background: #4c0066;
+      height: 150px;
+      margin-bottom: 50px;
+    }
+
+    header .logo {
+      border-radius: 100%;
+      display: block;
+      float: left;
+      padding-top: 25px;
+    }
+
+    header .title {
+      color: #fff;
+      float: left;
+      line-height: 30px;
+      margin: 101px 0 0;
+      text-align: right;
+      width: 660px;
+    }
+
+    header .title h1 {
+      font-size: 100px;
+    }
+
+    main .guide {
+      float: right;
+      width: 610px;
+    }
+
+    main .guide article {
+      margin-bottom: 50px;
+    }
+
+    main .guide h3 {
+      color: #4c0066;
+      font-size: 150%;
+      text-transform: uppercase;
+    }
+
+    main aside {
+      float: left;
+      margin-right: 50px;
+      width: 300px;
+    }
+
+    .sidebar-box {
+      margin: 25px 20px;
+    }
+
+    .sidebar-box h3 {
+      font-size: 110%;
+      margin-bottom: 5px;
+      text-transform: uppercase;
+    }
+
+    .sidebar-box p {
+      font-size: 90%;
+      line-height: 100%;
+      margin: 0;
+    }
+
+    .sidebar-box ol {
+      background: #f9f9f9;
+      border: 1px solid #eee;
+      border-radius: 3px;
+      list-style: none;
+    }
+    
+    .sidebar-box ol a {
+      border-bottom: 1px solid #eee;
+      display: block;
+      padding: 10px 10px;
+      text-decoration: none;
+    }
+    
+    .sidebar-box ol li:last-child a {
+      border-bottom: none;
+    }
+
+    .sidebar-box ol a:hover {
+      background: #f5f5f5;
+    }
+
+    li {
+      margin-left: 20px;
+      font-size: 120%;
+    }
+
+    h4 {
+      font-size: 120%;
+    }
+
+
+  </style>
+</head>
+
+<body>
+  <header role="banner">
+    <div class="content">
+      <a class="logo" href="http://0xAX.github.io/weber" target="_blank">
+        <svg height="300" width="300" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+          <g>
+            <circle cx="150" cy="150" fill="#4c0066" r="147" stroke="#ffffff" stroke-width="6" />
+            <path d="M191.75,213.42l34.57-126.24c2.39-8.71-4.36-15.78-15.08-15.78c-10.721,0-21.02,7.06-23.01,15.78l-28.82,126.24c-1.99,8.71,3.47,15.78,12.21,15.78C180.35,229.2,189.359,222.141,191.75,213.42z" fill="#ffffff" />
+            <path d="M148.77,213.42l26.74-126.24c1.85-8.71-5.289-15.78-15.939-15.78c-10.66,0-20.47,7.06-21.92,15.78l-21.03,126.24c-1.45,8.71,4.41,15.78,13.09,15.78S146.92,222.141,148.77,213.42z" fill="#ffffff" />
+            <path d="M106.05,213.45l4.78-31.511c1.33-8.689-5.28-15.739-14.76-15.739c-9.47,0-17.9,7.05-18.82,15.739l-3.36,31.511c-0.92,8.7,5.36,15.75,14.05,15.75C96.62,229.2,104.73,222.15,106.05,213.45z" fill="#ffffff" />
+          </g>
+        </svg>
+      </a>
+
+      <div class="title">
+        <h1 style="margin-top: -20px;">Weber</h1>
+      </div>
+    </div>
+  </header>
+
+  <main class="content" role="main">
+    <div class="guide">
+      <article id="getting-started">
+        <h3>Getting started</h3>
+        <p>Welcome to the default <a href="https://github.com/0xAX/weber">Weber's</a> page. Weber is a MVC Rails like web framework which was built with <a href="http://elixir-lang.org/">Elixir</a> programming language. Build web applications quickly and efficiently as possible. Let's build Web with Elixir.</p>
+        <h4>Weber features:</h4>
+        <br/>
+        <ul>
+          <li>MVC web framework;</li>
+          <li>New project generation;</li>
+          <li>Json generation with exjson;</li>
+          <li>Websocket support;</li>
+          <li>HTML helpers;</li>
+          <li>Site internationalization</li>
+          <li>Sessions support;</li>
+          <li>and many more</li>
+        </ul>
+      </article>
+    </div>
+    
+    <aside role="contentinfo">
+      <div class="sidebar-box">
+        <h3>Links</h3>
+        <ol>
+          <li><a href="https://github.com/0xAX/weber">Weber source code</a></li>
+          <li><a href="http://0xax.github.io/weber/index.html">Weber site</a></li>
+          <li><a href="http://elixir-lang.org/">Elixir</a></li>
+        </ol>
+      </div>
+    </aside>
+  </main>
+</body>
+
+</html>

+ 0 - 0
WeberFramework/lib/views/layout/.keep


+ 24 - 0
WeberFramework/mix.exs

@@ -0,0 +1,24 @@
+defmodule WeberFramework.Mixfile do
+  use Mix.Project
+
+  def project do
+    [ 
+      app: :WeberFramework,
+      version: "0.0.1",
+      deps: deps
+    ]
+  end
+
+  def application do
+    [
+      applications: [],
+      mod: {WeberFramework, []}
+    ]
+  end
+
+  defp deps do
+    [ 
+      { :weber, github: "0xAX/weber" } 
+    ]
+  end
+end

+ 0 - 0
WeberFramework/public/css/.keep


+ 0 - 0
WeberFramework/public/img/.keep


二進制
WeberFramework/public/img/favicon.ico


+ 235 - 0
WeberFramework/public/index.html

@@ -0,0 +1,235 @@
+<!DOCTYPE html>
+<html itemscope itemtype="http://schema.org/WebPage" lang="en">
+
+<head>
+  <meta charset="utf-8">
+  <title>Welcome to Weber!</title>
+  <link href="img/favicon.ico" rel="shortcut icon" type="image/vnd.microsoft.icon">
+
+  <style>
+    /* Reset */
+    * {
+      margin: 0;
+      padding: 0;
+    }
+
+    /* Default */
+    body {
+      font: normal 13px proxima-nova, sans-serif;
+      color: #666;
+    }
+
+    a {
+      color: #4c0066;
+    }
+
+    code, pre {
+      background: #f9f9f9;
+      border: 1px solid #ddd;
+      border-radius: 3px;
+      display: block;
+      font-family: monospace;
+      margin: 5px 0;
+      padding: 20px 0 20px 30px;
+      white-space: pre;
+    }
+
+    blockquote {
+      background: #f9f9f9;
+      border-left: 10px solid #eee;
+      border-radius: 3px;
+      color: #888;
+      margin: 20px 0 20px 20px;
+      padding: 10px 12px;
+      quotes: "\201C""\201D""\2018""\2019";
+    }
+
+    blockquote:before {
+      color: #ccc;
+      content: open-quote;
+      font-size: 55px;
+      line-height: 1px;
+      margin-right: 15px;
+      vertical-align: -25px;
+    }
+
+    blockquote p {
+      display: inline;
+    }
+
+    p {
+      font-size: 120%;
+      line-height: 25px;
+      margin: 10px 0;
+    }
+
+    /* Classes */
+    .content {
+      margin: 0 auto;
+      padding: 0 10px;
+      width: 960px;
+    }
+
+    /* Structure */
+    header:after, main:after,
+    header:before, main:before {
+      content: " ";
+      display: table;
+    }
+
+    header:after, main:after {
+      clear: both;
+    }
+
+    header {
+      background: #4c0066;
+      height: 150px;
+      margin-bottom: 50px;
+    }
+
+    header .logo {
+      border-radius: 100%;
+      display: block;
+      float: left;
+      padding-top: 25px;
+    }
+
+    header .title {
+      color: #fff;
+      float: left;
+      line-height: 30px;
+      margin: 101px 0 0;
+      text-align: right;
+      width: 660px;
+    }
+
+    header .title h1 {
+      font-size: 100px;
+    }
+
+    main .guide {
+      float: right;
+      width: 610px;
+    }
+
+    main .guide article {
+      margin-bottom: 50px;
+    }
+
+    main .guide h3 {
+      color: #4c0066;
+      font-size: 150%;
+      text-transform: uppercase;
+    }
+
+    main aside {
+      float: left;
+      margin-right: 50px;
+      width: 300px;
+    }
+
+    .sidebar-box {
+      margin: 25px 20px;
+    }
+
+    .sidebar-box h3 {
+      font-size: 110%;
+      margin-bottom: 5px;
+      text-transform: uppercase;
+    }
+
+    .sidebar-box p {
+      font-size: 90%;
+      line-height: 100%;
+      margin: 0;
+    }
+
+    .sidebar-box ol {
+      background: #f9f9f9;
+      border: 1px solid #eee;
+      border-radius: 3px;
+      list-style: none;
+    }
+    
+    .sidebar-box ol a {
+      border-bottom: 1px solid #eee;
+      display: block;
+      padding: 10px 10px;
+      text-decoration: none;
+    }
+    
+    .sidebar-box ol li:last-child a {
+      border-bottom: none;
+    }
+
+    .sidebar-box ol a:hover {
+      background: #f5f5f5;
+    }
+
+    li {
+      margin-left: 20px;
+      font-size: 120%;
+    }
+
+    h4 {
+      font-size: 120%;
+    }
+
+
+  </style>
+</head>
+
+<body>
+  <header role="banner">
+    <div class="content">
+      <a class="logo" href="http://0xAX.github.io/weber" target="_blank">
+        <svg height="300" width="300" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+          <g>
+            <circle cx="150" cy="150" fill="#4c0066" r="147" stroke="#ffffff" stroke-width="6" />
+            <path d="M191.75,213.42l34.57-126.24c2.39-8.71-4.36-15.78-15.08-15.78c-10.721,0-21.02,7.06-23.01,15.78l-28.82,126.24c-1.99,8.71,3.47,15.78,12.21,15.78C180.35,229.2,189.359,222.141,191.75,213.42z" fill="#ffffff" />
+            <path d="M148.77,213.42l26.74-126.24c1.85-8.71-5.289-15.78-15.939-15.78c-10.66,0-20.47,7.06-21.92,15.78l-21.03,126.24c-1.45,8.71,4.41,15.78,13.09,15.78S146.92,222.141,148.77,213.42z" fill="#ffffff" />
+            <path d="M106.05,213.45l4.78-31.511c1.33-8.689-5.28-15.739-14.76-15.739c-9.47,0-17.9,7.05-18.82,15.739l-3.36,31.511c-0.92,8.7,5.36,15.75,14.05,15.75C96.62,229.2,104.73,222.15,106.05,213.45z" fill="#ffffff" />
+          </g>
+        </svg>
+      </a>
+
+      <div class="title">
+        <h1 style="margin-top: -20px;">Weber</h1>
+      </div>
+    </div>
+  </header>
+
+  <main class="content" role="main">
+    <div class="guide">
+      <article id="getting-started">
+        <h3>Getting started</h3>
+        <p>Welcome to the default <a href="https://github.com/0xAX/weber">Weber's</a> page. Weber is a MVC Rails like web framework which was built with <a href="http://elixir-lang.org/">Elixir</a> programming language. Build web applications quickly and efficiently as possible. Let's build Web with Elixir.</p>
+        <h4>Weber features:</h4>
+        <br/>
+        <ul>
+          <li>MVC web framework;</li>
+          <li>New project generation;</li>
+          <li>Json generation with exjson;</li>
+          <li>Websocket support;</li>
+          <li>HTML helpers;</li>
+          <li>Site internationalization</li>
+          <li>Sessions support;</li>
+          <li>and many more</li>
+        </ul>
+      </article>
+    </div>
+    
+    <aside role="contentinfo">
+      <div class="sidebar-box">
+        <h3>Links</h3>
+        <ol>
+          <li><a href="https://github.com/0xAX/weber">Weber source code</a></li>
+          <li><a href="http://0xax.github.io/weber/index.html">Weber site</a></li>
+          <li><a href="http://elixir-lang.org/">Elixir</a></li>
+        </ol>
+      </div>
+    </aside>
+  </main>
+</body>
+
+</html>

+ 0 - 0
WeberFramework/public/js/.keep


+ 18 - 0
WeberFramework/setup_weber.py

@@ -0,0 +1,18 @@
+import sys
+import subprocess
+
+def start(args, logfile, errfile):
+    try:
+        subprocess.check_call("mix deps.get", cwd="WeberFramework", shell=True, stderr=errfile, stdout=logfile)
+        subprocess.check_call("mix compile --all --force", cwd="WeberFramework", shell=True, stderr=errfile, stdout=logfile)
+        subprocess.check_call("./start.sh", cwd="WeberFramework", shell=True, stderr=errfile, stdout=logfile)
+        return 0
+    except subprocess.CalledProcessError:
+        return 1
+ 
+def stop(logfile, errfile):
+    try:
+        subprocess.check_call("killall beam", shell=True, cwd="/usr/bin")
+        return 0
+    except subprocess.CalledProcessError:
+        return 1

+ 7 - 0
WeberFramework/start.sh

@@ -0,0 +1,7 @@
+#!/usr/bin/env sh
+
+if [ ! -f deps ]; then
+  mix deps.get && mix compile
+fi
+
+exec elixir --detached -S mix run --no-halt

+ 7 - 0
WeberFramework/test/WeberFramework_test.exs

@@ -0,0 +1,7 @@
+defmodule WeberFrameworkTest do
+  use ExUnit.Case
+
+  test "the truth" do
+    assert(true)
+  end
+end

+ 1 - 0
WeberFramework/test/test_helper.exs

@@ -0,0 +1 @@
+ExUnit.start

+ 28 - 0
activeweb/README.md

@@ -0,0 +1,28 @@
+ActiveWeb Benchmark App
+========================
+This is a Framework Benchmark Test for ActiveWeb
+
+For more information, please see:
+
+* http://www.techempower.com/benchmarks/
+* http://javalite.io
+
+How to start locally
+=========================
+
+1. Execute this script against local MySQL DB:
+
+    https://github.com/TechEmpower/FrameworkBenchmarks/blob/master/config/create.sql
+
+2. Start application:
+
+```
+    export ACTIVE_ENV=local
+    mvn jetty:run
+```
+
+3. Access this URL with browser:
+
+    http://localhost:8080/activeweb-benchmark/
+
+

+ 0 - 0
activeweb/__init__.py


+ 2 - 0
activeweb/bash_profile.sh

@@ -0,0 +1,2 @@
+export JAVA_HOME=/usr/lib/jvm/java-1.7.0-openjdk-amd64
+export RESIN_HOME=${IROOT}/resin-4.0.36

+ 45 - 0
activeweb/benchmark_config

@@ -0,0 +1,45 @@
+{
+  "framework": "activeweb",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/activeweb/json",
+      "plaintext_url": "/activeweb/plaintext",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Platform",
+      "database": "None",
+      "framework": "activeweb",
+      "language": "Java",
+      "orm": "Raw",
+      "platform": "ActiveWeb",
+      "webserver": "Resin",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "ActiveWeb",
+      "notes": "",
+      "versus": "servlet"
+    },
+    "raw": {
+      "setup_file": "setup",
+      "db_url": "/activeweb/db",
+      "query_url": "/activeweb/queries?queries=",
+      "fortune_url": "/activeweb/fortunes",
+      "update_url": "/activeweb/updates?queries=",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Platform",
+      "database": "MySQL",
+      "framework": "ActiveWeb",
+      "language": "Java",
+      "orm": "Raw",
+      "platform": "ActiveWeb",
+      "webserver": "Resin",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "activeweb",
+      "notes": "",
+      "versus": "servlet"
+    }
+  }]
+}

+ 3 - 0
activeweb/install.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+fw_depends java resin

+ 115 - 0
activeweb/pom.xml

@@ -0,0 +1,115 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>org.javalite</groupId>
+    <artifactId>activeweb-benchmark</artifactId>
+    <packaging>war</packaging>
+    <version>1.1-SNAPSHOT</version>
+    <name>ActiveWeb Benchmark App</name>
+
+    <properties>
+        <activeweb.version>1.9</activeweb.version>
+    </properties>
+
+    <build>
+        <finalName>activeweb</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>2.14.1</version>
+                <configuration>
+                    <reportFormat>brief</reportFormat>
+                    <trimStackTrace>true</trimStackTrace>
+                    <useFile>false</useFile>
+                    <includes>
+                        <include>**/*Spec*.java</include>
+                        <include>**/*Test*.java</include>
+                    </includes>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.1</version>
+                <configuration>
+                    <source>1.7</source>
+                    <target>1.7</target>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.mortbay.jetty</groupId>
+                <artifactId>maven-jetty-plugin</artifactId>
+                <version>6.1.22</version>
+                <configuration>
+                    <scanIntervalSeconds>0</scanIntervalSeconds>
+                    <connectors>
+                        <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
+                            <port>8080</port>
+                            <maxIdleTime>1000</maxIdleTime>
+                        </connector>
+                    </connectors>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.javalite</groupId>
+                <artifactId>activejdbc-instrumentation</artifactId>
+                <version>1.4.9</version>
+                <executions>
+                    <execution>
+                        <phase>process-classes</phase>
+                        <goals>
+                            <goal>instrument</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.8.1</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.javalite</groupId>
+            <artifactId>activeweb</artifactId>
+            <version>${activeweb.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.javalite</groupId>
+            <artifactId>activeweb-testing</artifactId>
+            <version>${activeweb.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <version>5.1.25</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-simple</artifactId>
+            <version>1.7.5</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-core</artifactId>
+            <version>2.3.1</version>
+        </dependency>
+
+        <dependency>
+          <groupId>com.fasterxml.jackson.core</groupId>
+          <artifactId>jackson-databind</artifactId>
+          <version>2.3.1</version>
+        </dependency>
+
+    </dependencies>
+</project>

+ 4 - 0
activeweb/scripts/README

@@ -0,0 +1,4 @@
+All scripts are intended to be run from a root directory:
+
+$./scripts/instrument.sh
+

+ 1 - 0
activeweb/scripts/instrument.sh

@@ -0,0 +1 @@
+mvn -o clean process-classes

+ 33 - 0
activeweb/setup.py

@@ -0,0 +1,33 @@
+
+import subprocess
+import sys
+import os
+import setup_util
+
+def start(args, logfile, errfile):
+  setup_util.replace_text("activeweb/src/main/webapp/WEB-INF/resin-web.xml", "localhost", args.database_host)
+  setup_util.replace_text("activeweb/src/main/java/app/config/DbConfig.java", "localhost", args.database_host)
+
+  try:
+    subprocess.check_call("mvn clean  package", shell=True, cwd="activeweb", stderr=errfile, stdout=logfile)
+    if os.name == 'nt':
+      subprocess.check_call("rmdir /s /q C:\\Java\\resin\\webapps", shell=True, stderr=errfile, stdout=logfile)
+      subprocess.check_call("mkdir C:\\Java\\resin\\webapps", shell=True, stderr=errfile, stdout=logfile)
+      subprocess.check_call("cp activeweb\\target\\activeweb.war C:\\Java\\resin\\webapps\\activeweb.war", shell=True, stderr=errfile, stdout=logfile)
+      subprocess.check_call("C:\\Java\\resin\\bin\\start.bat", shell=True, stderr=errfile, stdout=logfile)
+      return 0
+    subprocess.check_call("rm -rf $RESIN_HOME/webapps/*", shell=True, stderr=errfile, stdout=logfile)
+    subprocess.check_call("cp activeweb/target/activeweb.war $RESIN_HOME/webapps/", shell=True, stderr=errfile, stdout=logfile)
+    subprocess.check_call("$RESIN_HOME/bin/resinctl start", shell=True, stderr=errfile, stdout=logfile)
+    return 0
+  except subprocess.CalledProcessError:
+    return 1
+def stop(logfile, errfile):
+  try:
+    if os.name == 'nt':
+      subprocess.check_call("C:\\Java\\resin\\bin\\stop.bat", shell=True, stderr=errfile, stdout=logfile)
+      return 0
+    subprocess.check_call("$RESIN_HOME/bin/resinctl shutdown", shell=True, stderr=errfile, stdout=logfile)
+    return 0
+  except subprocess.CalledProcessError:
+    return 1

+ 14 - 0
activeweb/source_code

@@ -0,0 +1,14 @@
+./src/main/java/app/config/AppControllerConfig.java
+./src/main/java/app/config/RouteConfig.java
+./src/main/java/app/config/FreeMarkerConfig.java
+./src/main/java/app/config/DbConfig.java
+./src/main/java/app/config/AppBootstrap.java
+./src/main/java/app/models/World.java
+./src/main/java/app/models/Fortune.java
+./src/main/java/app/controllers/PlaintextController.java
+./src/main/java/app/controllers/JsonController.java
+./src/main/java/app/controllers/DatabaseController.java
+./src/main/java/app/controllers/FortunesController.java
+./src/main/java/app/controllers/QueriesController.java
+./src/main/java/app/controllers/HomeController.java
+./src/main/java/app/controllers/UpdatesController.java

+ 31 - 0
activeweb/src/main/java/app/config/AppBootstrap.java

@@ -0,0 +1,31 @@
+/*
+Copyright 2009-2010 Igor Polevoy 
+
+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 app.config;
+
+import org.javalite.activeweb.AppContext;
+import org.javalite.activeweb.Bootstrap;
+
+import com.google.inject.Guice;
+import org.javalite.activeweb.Configuration;
+
+/**
+ * @author Igor Polevoy
+ */
+public class AppBootstrap extends Bootstrap {
+    public void init(AppContext context) {
+        Configuration.setUseDefaultLayoutForErrors(true);
+    }
+}

+ 39 - 0
activeweb/src/main/java/app/config/AppControllerConfig.java

@@ -0,0 +1,39 @@
+/*
+Copyright 2009-2010 Igor Polevoy 
+
+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 app.config;
+
+
+import app.controllers.DatabaseController;
+import app.controllers.FortunesController;
+import app.controllers.QueriesController;
+import app.controllers.UpdatesController;
+import org.javalite.activeweb.AbstractControllerConfig;
+import org.javalite.activeweb.AppContext;
+import org.javalite.activeweb.controller_filters.DBConnectionFilter;
+
+
+/**
+ * @author Igor Polevoy
+ */
+public class AppControllerConfig extends AbstractControllerConfig {
+
+    public void init(AppContext context) {
+//        addGlobalFilters(new TimingFilter()); for speed - not sure how logging is configured
+
+        add(new DBConnectionFilter()).to(DatabaseController.class, QueriesController.class,
+                FortunesController.class, UpdatesController.class);
+    }
+}

+ 50 - 0
activeweb/src/main/java/app/config/DbConfig.java

@@ -0,0 +1,50 @@
+/*
+Copyright 2009-2010 Igor Polevoy 
+
+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 app.config;
+
+import org.javalite.activeweb.AbstractDBConfig;
+import org.javalite.activeweb.AppContext;
+
+/**
+ * @author Igor Polevoy
+ */
+public class DbConfig extends AbstractDBConfig {
+    public void init(AppContext context) {
+
+        String jdbcParams = "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";
+
+        environment("development").jndi("java:comp/env/jdbc/hello_world");
+
+        //need to set ACTIVE_ENV=local to run on dev box.
+        environment("local").jdbc("com.mysql.jdbc.Driver", "jdbc:mysql://localhost/hello_world?" + jdbcParams, "benchmarkdbuser", "benchmarkdbpass");
+
+        environment("development").testing().jdbc("com.mysql.jdbc.Driver", "jdbc:mysql://localhost/hello_world?" + jdbcParams, "benchmarkdbuser", "benchmarkdbpass");
+    }
+}

+ 30 - 0
activeweb/src/main/java/app/config/FreeMarkerConfig.java

@@ -0,0 +1,30 @@
+/*
+Copyright 2009-2010 Igor Polevoy 
+
+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 app.config;
+
+import org.javalite.activeweb.freemarker.AbstractFreeMarkerConfig;
+
+/**
+ * @author Igor Polevoy
+ */
+public class FreeMarkerConfig extends org.javalite.activeweb.freemarker.AbstractFreeMarkerConfig {
+    @Override
+    public void init() {
+        //this is to override a strange FreeMarker default processing of numbers 
+        getConfiguration().setNumberFormat("0.##");
+    }
+}

+ 32 - 0
activeweb/src/main/java/app/config/RouteConfig.java

@@ -0,0 +1,32 @@
+/*
+Copyright 2009-2010 Igor Polevoy 
+
+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. 
+*/
+
+/**
+ * @author Igor Polevoy: 1/9/14 11:26 PM
+ */
+
+package app.config;
+
+import app.controllers.DatabaseController;
+import org.javalite.activeweb.AbstractRouteConfig;
+import org.javalite.activeweb.AppContext;
+
+public class RouteConfig extends AbstractRouteConfig {
+    @Override
+    public void init(AppContext appContext) {
+        route("/db").to(DatabaseController.class);
+    }
+}

+ 39 - 0
activeweb/src/main/java/app/controllers/DatabaseController.java

@@ -0,0 +1,39 @@
+/*
+Copyright 2009-2010 Igor Polevoy 
+
+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. 
+*/
+
+/**
+ * @author Igor Polevoy: 12/18/13 4:36 PM
+ */
+
+package app.controllers;
+
+import app.models.World;
+import org.javalite.activeweb.AppController;
+
+import java.util.Date;
+import java.util.Random;
+import java.util.concurrent.ThreadLocalRandom;
+
+public class DatabaseController extends AppController {
+    public void index() {
+
+        String json = World.findById(ThreadLocalRandom.current().nextInt(10000)).toJson(false, "id", "randomNumber");
+
+        respond(json).contentType("application/json")
+                .header("Content-Length", String.valueOf(json.length()))
+                .header("Date", new Date().toString());
+    }
+}

+ 41 - 0
activeweb/src/main/java/app/controllers/FortunesController.java

@@ -0,0 +1,41 @@
+/*
+Copyright 2009-2010 Igor Polevoy 
+
+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. 
+*/
+
+/**
+ * @author Igor Polevoy: 12/18/13 9:11 PM
+ */
+
+package app.controllers;
+
+import app.models.Fortune;
+import org.javalite.activeweb.AppController;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+
+public class FortunesController extends AppController {
+
+    public void index() {
+        List<Fortune> dbFortunes = Fortune.findAll();
+        List<Fortune> fortunes = new ArrayList<Fortune>(dbFortunes);
+        fortunes.add((Fortune) Fortune.create("id", 0, "message", "Additional fortune added at request time."));
+        Collections.sort(fortunes);
+        view("fortunes", fortunes);
+        render().noLayout();
+    }
+}

+ 26 - 0
activeweb/src/main/java/app/controllers/HomeController.java

@@ -0,0 +1,26 @@
+/*
+Copyright 2009-2010 Igor Polevoy 
+
+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 app.controllers;
+
+import org.javalite.activeweb.AppController;
+
+/**
+ * @author Igor Polevoy
+ */
+public class HomeController extends AppController {
+    public void index(){}
+}

+ 49 - 0
activeweb/src/main/java/app/controllers/JsonController.java

@@ -0,0 +1,49 @@
+/*
+Copyright 2009-2010 Igor Polevoy 
+
+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. 
+*/
+
+/**
+ * @author Igor Polevoy: 12/18/13 3:51 PM
+ */
+
+package app.controllers;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.javalite.activeweb.AppController;
+
+import java.io.IOException;
+import java.util.Date;
+
+public class JsonController extends AppController {
+    public void index() throws IOException {
+        String json = new ObjectMapper().writeValueAsString(new Message("Hello, World!"));
+        respond(json)
+                .contentType("application/json")
+                .header("Content-Length", String.valueOf(json.length()))
+                .header("Date", new Date().toString());
+    }
+
+    public static final class Message {
+        private final String message;
+
+        private Message(String message) {
+            this.message = message;
+        }
+
+        public String getMessage() {
+            return message;
+        }
+    }
+}

+ 35 - 0
activeweb/src/main/java/app/controllers/PlaintextController.java

@@ -0,0 +1,35 @@
+/*
+Copyright 2009-2010 Igor Polevoy 
+
+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. 
+*/
+
+/**
+ * @author Igor Polevoy: 12/19/13 1:23 AM
+ */
+
+package app.controllers;
+
+import org.javalite.activeweb.AppController;
+
+import java.util.Date;
+
+public class PlaintextController extends AppController {
+    public void index() {
+        String message = "Hello, World!";
+        respond(message)
+                .contentType("text/plain")
+                .header("Content-Length", String.valueOf(message.length()))
+                .header("Date", new Date().toString());
+    }
+}

+ 71 - 0
activeweb/src/main/java/app/controllers/QueriesController.java

@@ -0,0 +1,71 @@
+/*
+Copyright 2009-2010 Igor Polevoy 
+
+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. 
+*/
+
+/**
+ * @author Igor Polevoy: 12/18/13 4:36 PM
+ */
+
+package app.controllers;
+
+import app.models.World;
+import org.javalite.activeweb.AppController;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.ThreadLocalRandom;
+
+public class QueriesController extends AppController {
+
+    public void index() {
+
+        view("worlds", getWorlds());
+        render().contentType("application/json").header("Date", new Date().toString());
+    }
+
+    protected List<World> getWorlds() {
+        int number = getQueries();
+        List<World> worlds = new ArrayList<>(number);
+        for (int i = 0; i < number; i++) {
+            worlds.add(World.<World>findById(randomNumber()));
+        }
+        return worlds;
+    }
+
+    public int getQueries() {
+        int queries;
+        try {
+            queries = Integer.parseInt(param("queries"));
+        } catch (Exception e) {
+            queries = 1;
+        }
+        if (queries > 500) {
+            queries = 500;
+        } else if (queries < 1) {
+            queries = 1;
+        }
+        return queries;
+    }
+    protected int randomNumber(){
+        return ThreadLocalRandom.current().nextInt(10000) + 1;
+    }
+
+    @Override
+    protected String getLayout() {
+        return null;
+    }
+}

+ 38 - 0
activeweb/src/main/java/app/controllers/UpdatesController.java

@@ -0,0 +1,38 @@
+/*
+Copyright 2009-2010 Igor Polevoy 
+
+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. 
+*/
+
+/**
+ * @author Igor Polevoy: 12/18/13 9:51 PM
+ */
+
+package app.controllers;
+
+import app.models.World;
+import org.javalite.activeweb.AppController;
+
+import java.util.List;
+import java.util.concurrent.ThreadLocalRandom;
+
+public class UpdatesController extends QueriesController {
+    public void index() {
+        List<World> worlds = getWorlds();
+        for (World world : worlds) {
+            world.set("randomNumber", randomNumber()).saveIt();
+        }
+        view("worlds", worlds);
+        render("/queries/index"); //same template
+    }
+}

+ 31 - 0
activeweb/src/main/java/app/models/Fortune.java

@@ -0,0 +1,31 @@
+/*
+Copyright 2009-2010 Igor Polevoy 
+
+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. 
+*/
+
+/**
+ * @author Igor Polevoy: 12/18/13 9:12 PM
+ */
+
+package app.models;
+
+import org.javalite.activejdbc.Model;
+import org.javalite.activejdbc.annotations.Table;
+
+@Table("Fortune")
+public class Fortune extends Model implements Comparable<Fortune> {
+    public int compareTo(Fortune other) {
+        return getString("message").compareTo(other.getString("message"));
+    }
+}

+ 30 - 0
activeweb/src/main/java/app/models/World.java

@@ -0,0 +1,30 @@
+/*
+Copyright 2009-2010 Igor Polevoy 
+
+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. 
+*/
+
+/**
+ * @author Igor Polevoy: 12/18/13 4:32 PM
+ */
+
+package app.models;
+
+import org.javalite.activejdbc.Model;
+import org.javalite.activejdbc.annotations.Table;
+
+
+@Table("World")
+public class World extends Model {
+
+}

+ 4 - 0
activeweb/src/main/webapp/WEB-INF/jetty-env.xml

@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
+<Configure class="org.mortbay.jetty.webapp.WebAppContext">    
+</Configure>

+ 15 - 0
activeweb/src/main/webapp/WEB-INF/resin-web.xml

@@ -0,0 +1,15 @@
+<web-app xmlns="http://caucho.com/ns/resin">
+
+<database jndi-name='jdbc/hello_world'>
+  <driver>
+    <type>com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource</type>
+    <url>jdbc:mysql://localhost:3306/hello_world?jdbcCompliantTruncation=false&amp;elideSetAutoCommits=true&amp;useLocalSessionState=true&amp;cachePrepStmts=true&amp;cacheCallableStmts=true&amp;alwaysSendSetIsolation=false&amp;prepStmtCacheSize=4096&amp;cacheServerConfiguration=true&amp;prepStmtCacheSqlLimit=2048&amp;zeroDateTimeBehavior=convertToNull&amp;traceProtocol=false&amp;useUnbufferedInput=false&amp;useReadAheadInput=false&amp;maintainTimeStats=false&amp;useServerPrepStmts&amp;cacheRSMetadata=true</url>
+    <user>benchmarkdbuser</user>
+    <password>benchmarkdbpass</password>
+    <useUnicode/>
+  </driver>
+</database>
+
+
+</web-app>
+

+ 20 - 0
activeweb/src/main/webapp/WEB-INF/views/fortunes/index.ftl

@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head><title>Fortunes</title></head>
+<body>
+<table>
+    <tr>
+        <th>id</th>
+        <th>message</th>
+    </tr>
+
+<#list fortunes as fortune>
+    <tr>
+        <td>${fortune.id}</td>
+        <td>${fortune.message?html}</td>
+    </tr>
+</#list>
+
+</table>
+</body>
+</html>

+ 24 - 0
activeweb/src/main/webapp/WEB-INF/views/home/index.ftl

@@ -0,0 +1,24 @@
+<h1>Available tests:</h1>
+
+<ul>
+    <li>
+        <a href="json">Test type 1: JSON serialization /json</a>
+    </li>
+    <li>
+        <a href="db">Test type 2: Single database query</a>
+    </li>
+    <li>
+        <a href="queries?queries=100">Test type 3: Multiple database queries</a>
+    </li>
+    <li>
+        <a href="fortunes">Test type 4: Fortunes</a>
+    </li>
+    <li>
+        <a href="updates?queries=40">Test type 5: Database updates</a>
+    </li>
+    <li>
+        <a href="plaintext">Test type 6: Plaintext</a>
+    </li>
+</ul>
+
+

+ 23 - 0
activeweb/src/main/webapp/WEB-INF/views/layouts/default_layout.ftl

@@ -0,0 +1,23 @@
+<#setting url_escaping_charset='ISO-8859-1'>
+
+<html>
+<head>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+    <LINK href="${context_path}/css/main.css" rel="stylesheet" type="text/css"/>
+    <script src="${context_path}/js/jquery-1.4.2.min.js" type="text/javascript"></script>
+    <script src="${context_path}/js/aw.js" type="text/javascript"></script>
+    <title>ActiveWeb - <@yield to="title"/></title>
+</head>
+<body>
+
+<div class="main">
+<#include "header.ftl" >
+    <div class="content">
+    ${page_content}
+    </div>
+<#include "footer.ftl" >
+</div>
+
+</body>
+
+</html>

+ 3 - 0
activeweb/src/main/webapp/WEB-INF/views/layouts/footer.ftl

@@ -0,0 +1,3 @@
+<div class='footer'>
+    <p>2010 - 2013 Active Web. No Rights Reserved.</p>
+</div>

+ 4 - 0
activeweb/src/main/webapp/WEB-INF/views/layouts/header.ftl

@@ -0,0 +1,4 @@
+<div class="header">
+    <h1><a href="${context_path}">ActiveWeb Benchmark Application</a></h1>
+</div>
+

+ 7 - 0
activeweb/src/main/webapp/WEB-INF/views/queries/index.ftl

@@ -0,0 +1,7 @@
+<@compress single_line=true>
+[<#list worlds as w>
+{"id":${w.id},"randomNumber":${w.randomNumber}}
+<#if w_has_next>,</#if>
+</#list>
+]
+</@compress>

+ 3 - 0
activeweb/src/main/webapp/WEB-INF/views/system/404.ftl

@@ -0,0 +1,3 @@
+<@content for="title">404 Not Found</@content>
+<h2>404 - Resource Not Found</h2>
+${message!}

+ 18 - 0
activeweb/src/main/webapp/WEB-INF/views/system/error.ftl

@@ -0,0 +1,18 @@
+Error:<br/>
+<pre>
+${message}
+</pre>
+<script type="text/javascript">
+    function show() {
+        document.getElementById("stack_trace").removeAttribute("style");
+    }
+</script>
+
+<br/>
+<a id="show_link" href="#" onclick='show();'>See Stack Trace</a>
+
+<div id="stack_trace" style="display:none">
+<pre>
+${stack_trace}
+</pre>
+</div>

+ 30 - 0
activeweb/src/main/webapp/WEB-INF/web.xml

@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+
+
+    <display-name>activeweb</display-name>
+
+    <filter>
+        <filter-name>dispatcher</filter-name>
+        <filter-class>org.javalite.activeweb.RequestDispatcher</filter-class>
+        <init-param>
+            <param-name>exclusions</param-name>
+            <param-value>css,images,.js</param-value>
+        </init-param>
+        <init-param>
+            <param-name>encoding</param-name>
+            <param-value>UTF-8</param-value>
+        </init-param>
+
+        <init-param>
+            <param-name>root_controller</param-name>
+            <param-value>home</param-value>
+        </init-param>
+    </filter>
+
+    <filter-mapping>
+        <filter-name>dispatcher</filter-name>
+        <url-pattern>/*</url-pattern>
+    </filter-mapping>
+</web-app>

+ 74 - 0
activeweb/src/main/webapp/css/main.css

@@ -0,0 +1,74 @@
+@charset "UTF-8";
+/* CSS Document */
+
+*{
+	margin:0;
+	padding:0;
+}
+
+html, body{
+	background:white;
+}
+
+a{
+	text-decoration:none;
+	outline:none;
+}
+
+a:hover{
+	text-decoration:underline;
+}
+
+p{
+	margin:10px 0;
+	line-height:16px;
+}
+
+
+.header{
+    background-color:#fafad2;
+    padding:20px;
+}
+
+.main{
+    padding:20px
+}
+
+.content{
+    padding:20px;
+}
+
+.error{
+    color:red;
+}
+
+.error_message{
+    background-color:#ffb6c1;
+
+    margin-top:10px;
+    margin-bottom:10px;
+    height:0;
+}
+
+.message{
+    background-color:#7fffd4;
+    
+    margin-top:10px;
+    margin-bottom:10px;
+}
+
+.footer{
+    background-color:#fafad2;
+    padding:20px;
+}
+
+ul{
+    margin: 20px;
+}
+
+
+table tr td{
+    background-color:#dcdcdc;
+    padding:10px;
+}
+

+ 88 - 0
activeweb/src/main/webapp/js/aw.js

@@ -0,0 +1,88 @@
+/*
+ Copyright 2009-2010 Igor Polevoy
+
+ 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.
+ */
+
+/*
+ This file is a collection of unobtrusive JS that binds to link_to generated anchors typical for Ajax calls.
+
+ author: Igor Polevoy
+ */
+
+$(document).ready(function() {
+    $('a[data-link]').bind('click', function() {
+        var anchor = $(this);
+        var destination = anchor.attr("data-destination");
+        var formId = anchor.attr("data-form");
+        var href = anchor.attr("href");
+        var _method = anchor.attr("data-method");
+        var before = anchor.attr("data-before");
+        var after = anchor.attr("data-after");
+        var beforeArg = anchor.attr("data-before-arg");
+        var afterArg = anchor.attr("data-after-arg");
+        var error = anchor.attr("data-error");
+
+        var confirmMessage = anchor.attr("data-confirm");
+
+        if(confirmMessage != null ){
+            if(!confirm(confirmMessage)){
+                return false;
+            }
+        }
+
+        //not Ajax
+        if(destination == null && before == null && after == null && (_method == null || _method.toLowerCase() == "get")){
+            return true;
+        }
+
+        if (_method == null) {
+            _method = "get";
+        }
+        var type;
+        if (_method.toLowerCase() == "get") {
+            type = "get";
+        } else if (_method.toLowerCase() == "post"
+                || _method.toLowerCase() == "put"
+                || _method.toLowerCase() == "delete") {
+            type = "post";
+        }
+
+        var data = "_method=" + _method;
+        if (formId != null) {
+            data += "&" + $("#" + formId).serialize();
+        }
+
+        if(before != null){
+            eval(before)(beforeArg);
+        }
+
+
+        $.ajax({ url: href, data: data, type:type,
+            success: function(data) {
+                if (after != null)
+                    eval(after)(afterArg, data);
+
+                if (destination != null)
+                    $("#" + destination).html(data);
+            },
+            error: function(xhr, status, errorThrown) {
+                if(error != null){
+                    eval(error)(xhr.status, xhr.responseText );
+                }
+            }
+        });
+
+        return false;
+    });
+});

+ 154 - 0
activeweb/src/main/webapp/js/jquery-1.4.2.min.js

@@ -0,0 +1,154 @@
+/*!
+ * jQuery JavaScript Library v1.4.2
+ * http://jquery.com/
+ *
+ * Copyright 2010, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ * Copyright 2010, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Sat Feb 13 22:33:48 2010 -0500
+ */
+(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o<i;o++)e(a[o],b,f?d.call(a[o],o,e(a[o],b)):d,j);return a}return i?
+e(a[0],b):w}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function na(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function oa(a){var b,d=[],f=[],e=arguments,j,i,o,k,n,r;i=c.data(this,"events");if(!(a.liveFired===this||!i||!i.live||a.button&&a.type==="click")){a.liveFired=this;var u=i.live.slice(0);for(k=0;k<u.length;k++){i=u[k];i.origType.replace(O,"")===a.type?f.push(i.selector):u.splice(k--,1)}j=c(a.target).closest(f,a.currentTarget);n=0;for(r=
+j.length;n<r;n++)for(k=0;k<u.length;k++){i=u[k];if(j[n].selector===i.selector){o=j[n].elem;f=null;if(i.preType==="mouseenter"||i.preType==="mouseleave")f=c(a.relatedTarget).closest(i.selector)[0];if(!f||f!==o)d.push({elem:o,handleObj:i})}}n=0;for(r=d.length;n<r;n++){j=d[n];a.currentTarget=j.elem;a.data=j.handleObj.data;a.handleObj=j.handleObj;if(j.handleObj.origHandler.apply(j.elem,e)===false){b=false;break}}return b}}function pa(a,b){return"live."+(a&&a!=="*"?a+".":"")+b.replace(/\./g,"`").replace(/ /g,
+"&")}function qa(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function ra(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var j in f)for(var i in f[j])c.event.add(this,j,f[j][i],f[j][i].data)}}})}function sa(a,b,d){var f,e,j;b=b&&b[0]?b[0].ownerDocument||b[0]:s;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===s&&!ta.test(a[0])&&(c.support.checkClone||!ua.test(a[0]))){e=
+true;if(j=c.fragments[a[0]])if(j!==1)f=j}if(!f){f=b.createDocumentFragment();c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=j?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(va.concat.apply([],va.slice(0,b)),function(){d[this]=a});return d}function wa(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Ra=A.jQuery,Sa=A.$,s=A.document,T,Ta=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/,
+Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&&
+(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this,
+a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b===
+"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,
+function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(j in e){i=a[j];o=e[j];if(a!==o)if(f&&o&&(c.isPlainObject(o)||c.isArray(o))){i=i&&(c.isPlainObject(i)||
+c.isArray(i))?i:c.isArray(o)?[]:{};a[j]=c.extend(f,i,o)}else if(o!==w)a[j]=o}return a};c.extend({noConflict:function(a){A.$=Sa;if(a)A.jQuery=Ra;return c},isReady:false,ready:function(){if(!c.isReady){if(!s.body)return setTimeout(c.ready,13);c.isReady=true;if(Q){for(var a,b=0;a=Q[b++];)a.call(s,c);Q=null}c.fn.triggerHandler&&c(s).triggerHandler("ready")}},bindReady:function(){if(!xa){xa=true;if(s.readyState==="complete")return c.ready();if(s.addEventListener){s.addEventListener("DOMContentLoaded",
+L,false);A.addEventListener("load",c.ready,false)}else if(s.attachEvent){s.attachEvent("onreadystatechange",L);A.attachEvent("onload",c.ready);var a=false;try{a=A.frameElement==null}catch(b){}s.documentElement.doScroll&&a&&ma()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,
+"isPrototypeOf"))return false;var b;for(b in a);return b===w||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false;return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;a=c.trim(a);if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return A.JSON&&A.JSON.parse?A.JSON.parse(a):(new Function("return "+
+a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Va.test(a)){var b=s.getElementsByTagName("head")[0]||s.documentElement,d=s.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(s.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,j=a.length,i=j===w||c.isFunction(a);if(d)if(i)for(f in a){if(b.apply(a[f],
+d)===false)break}else for(;e<j;){if(b.apply(a[e++],d)===false)break}else if(i)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=a[0];e<j&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Wa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===
+a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==w;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,j=a.length;e<j;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,j=0,i=a.length;j<i;j++){e=b(a[j],j,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=w}else if(b&&
+!c.isFunction(b)){d=b;b=w}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});P=c.uaMatch(P);if(P.browser){c.browser[P.browser]=true;c.browser.version=P.version}if(c.browser.webkit)c.browser.safari=
+true;if(ya)c.inArray=function(a,b){return ya.call(b,a)};T=c(s);if(s.addEventListener)L=function(){s.removeEventListener("DOMContentLoaded",L,false);c.ready()};else if(s.attachEvent)L=function(){if(s.readyState==="complete"){s.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=s.documentElement,b=s.createElement("script"),d=s.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML="   <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
+var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,
+parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent=
+false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n=
+s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,
+applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando];
+else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,
+a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===
+w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i,
+cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className){for(var j=" "+e.className+" ",
+i=e.className,o=0,k=b.length;o<k;o++)if(j.indexOf(" "+b[o]+" ")<0)i+=" "+b[o];e.className=c.trim(i)}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(k){var n=c(this);n.removeClass(a.call(this,k,n.attr("class")))});if(a&&typeof a==="string"||a===w)for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var j=(" "+e.className+" ").replace(Aa," "),i=0,o=b.length;i<o;i++)j=j.replace(" "+b[i]+" ",
+" ");e.className=c.trim(j)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var j=c(this);j.toggleClass(a.call(this,e,j.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,j=0,i=c(this),o=b,k=a.split(ca);e=k[j++];){o=f?o:!i.hasClass(e);i[o?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=
+this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(Aa," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j<d;j++){var i=
+e[j];if(i.selected){a=c(i).val();if(b)return a;f.push(a)}}return f}if(Ba.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Za,"")}return w}var o=c.isFunction(a);return this.each(function(k){var n=c(this),r=a;if(this.nodeType===1){if(o)r=a.call(this,k,n.val());if(typeof r==="number")r+="";if(c.isArray(r)&&Ba.test(this.type))this.checked=c.inArray(n.val(),r)>=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected=
+c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");
+a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g,
+function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split(".");
+k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a),
+C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B<r.length;B++){u=r[B];if(d.guid===u.guid){if(i||k.test(u.namespace)){f==null&&r.splice(B--,1);n.remove&&n.remove.call(a,u)}if(f!=
+null)break}}if(r.length===0||f!=null&&r.length===1){if(!n.teardown||n.teardown.call(a,o)===false)Ca(a,e,z.handle);delete C[e]}}else for(var B=0;B<r.length;B++){u=r[B];if(i||k.test(u.namespace)){c.event.remove(a,n,u.handler,B);r.splice(B--,1)}}}if(c.isEmptyObject(C)){if(b=z.handle)b.elem=null;delete z.events;delete z.handle;c.isEmptyObject(z)&&c.removeData(a)}}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=
+e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&&
+f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;
+if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e<j;e++){var i=d[e];if(b||f.test(i.namespace)){a.handler=i.handler;a.data=i.data;a.handleObj=i;i=i.handler.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
+fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
+d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,a.origType,c.extend({},a,{handler:oa}))},remove:function(a){var b=true,d=a.origType.replace(O,"");c.each(c.data(this,
+"events").live||[],function(){if(d===this.origType.replace(O,""))return b=false});b&&c.event.remove(this,a.origType,oa)}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};var Ca=s.removeEventListener?function(a,b,d){a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=
+a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,
+isImmediatePropagationStopped:Y};var Da=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},Ea=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ea:Da,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ea:Da)}}});if(!c.support.submitBubbles)c.event.special.submit=
+{setup:function(){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length)return na("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13)return na("submit",this,arguments)})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};
+if(!c.support.changeBubbles){var da=/textarea|input|select/i,ea,Fa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",
+e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,
+"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,
+d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j<o;j++)c.event.add(this[j],d,i,f)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&
+!a.preventDefault)for(var d in a)this.unbind(d,a[d]);else{d=0;for(var f=this.length;d<f;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,f){return this.live(b,d,f,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},
+toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Ga={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e,j){var i,o=0,k,n,r=j||this.selector,
+u=j?this:c(this.context);if(c.isFunction(f)){e=f;f=w}for(d=(d||"").split(" ");(i=d[o++])!=null;){j=O.exec(i);k="";if(j){k=j[0];i=i.replace(O,"")}if(i==="hover")d.push("mouseenter"+k,"mouseleave"+k);else{n=i;if(i==="focus"||i==="blur"){d.push(Ga[i]+k);i+=k}else i=(Ga[i]||i)+k;b==="live"?u.each(function(){c.event.add(this,pa(i,r),{data:f,selector:r,handler:e,origType:i,origHandler:e,preType:n})}):u.unbind(pa(i,r),e)}}return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),
+function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});A.attachEvent&&!A.addEventListener&&A.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});(function(){function a(g){for(var h="",l,m=0;g[m];m++){l=g[m];if(l.nodeType===3||l.nodeType===4)h+=l.nodeValue;else if(l.nodeType!==8)h+=a(l.childNodes)}return h}function b(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];
+if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=l;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}m[q]=y}}}function d(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=l;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(k.filter(h,[t]).length>0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
+e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift();
+t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D||
+g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};k.matches=function(g,h){return k(g,null,null,h)};k.find=function(g,h,l){var m,q;if(!g)return[];
+for(var p=0,v=n.order.length;p<v;p++){var t=n.order[p];if(q=n.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");m=n.find[t](q,h,l);if(m!=null){g=g.replace(n.match[t],"");break}}}}m||(m=h.getElementsByTagName("*"));return{set:m,expr:g}};k.filter=function(g,h,l,m){for(var q=g,p=[],v=h,t,y,S=h&&h[0]&&x(h[0]);g&&h.length;){for(var H in n.filter)if((t=n.leftMatch[H].exec(g))!=null&&t[2]){var M=n.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-
+1)!=="\\"){if(v===p)p=[];if(n.preFilter[H])if(t=n.preFilter[H](t,v,l,p,m,S)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=v[U])!=null;U++)if(D){I=M(D,t,U,v);var Ha=m^!!I;if(l&&I!=null)if(Ha)y=true;else v[U]=false;else if(Ha){p.push(D);y=true}}if(I!==w){l||(v=p);g=g.replace(n.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)k.error(g);else break;q=g}return v};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var n=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
+CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},
+relative:{"+":function(g,h){var l=typeof h==="string",m=l&&!/\W/.test(h);l=l&&!m;if(m)h=h.toLowerCase();m=0;for(var q=g.length,p;m<q;m++)if(p=g[m]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[m]=l||p&&p.nodeName.toLowerCase()===h?p||false:p===h}l&&k.filter(h,g,true)},">":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m<q;m++){var p=g[m];if(p){l=p.parentNode;g[m]=l.nodeName.toLowerCase()===h?l:false}}}else{m=0;for(q=g.length;m<q;m++)if(p=g[m])g[m]=
+l?p.parentNode:p.parentNode===h;l&&k.filter(h,g,true)}},"":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("parentNode",h,m,g,p,l)},"~":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,m,g,p,l)}},find:{ID:function(g,h,l){if(typeof h.getElementById!=="undefined"&&!l)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var l=[];
+h=h.getElementsByName(g[1]);for(var m=0,q=h.length;m<q;m++)h[m].getAttribute("name")===g[1]&&l.push(h[m]);return l.length===0?null:l}},TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,l,m,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var v;(v=h[p])!=null;p++)if(v)if(q^(v.className&&(" "+v.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},
+CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m,
+g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},
+text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},
+setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return h<l[3]-0},gt:function(g,h,l){return h>l[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=
+h[3];l=0;for(m=h.length;l<m;l++)if(h[l]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+q)},CHILD:function(g,h){var l=h[1],m=g;switch(l){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(l==="first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":l=h[2];var q=h[3];if(l===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var v=0;for(m=p.firstChild;m;m=
+m.nextSibling)if(m.nodeType===1)m.nodeIndex=++v;p.sizcache=h}g=g.nodeIndex-q;return l===0?g===0:g%l===0&&g/l>=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m===
+"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g,
+h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l<m;l++)h.push(g[l]);else for(l=0;g[l];l++)h.push(g[l]);return h}}var B;if(s.documentElement.compareDocumentPosition)B=function(g,h){if(!g.compareDocumentPosition||
+!h.compareDocumentPosition){if(g==h)i=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===h?0:1;if(g===0)i=true;return g};else if("sourceIndex"in s.documentElement)B=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)i=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)i=true;return g};else if(s.createRange)B=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)i=true;return g.ownerDocument?-1:1}var l=g.ownerDocument.createRange(),m=
+h.ownerDocument.createRange();l.setStart(g,0);l.setEnd(g,0);m.setStart(h,0);m.setEnd(h,0);g=l.compareBoundaryPoints(Range.START_TO_END,m);if(g===0)i=true;return g};(function(){var g=s.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&&
+q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML="<a href='#'></a>";
+if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}();
+(function(){var g=s.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}:
+function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)k(g,h[q],l);return k.filter(m,l)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=a;c.isXMLDoc=x;c.contains=E})();var eb=/Until$/,fb=/^(?:parents|prevUntil|prevAll)/,
+gb=/,/;R=Array.prototype.slice;var Ia=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,j){return!!b.call(e,j,e)===d});else if(b.nodeType)return c.grep(a,function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Ua.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;
+c.find(a,this[f],b);if(f>0)for(var j=d;j<b.length;j++)for(var i=0;i<d;i++)if(b[i]===b[j]){b.splice(j--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ia(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ia(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j=
+{},i;if(f&&a.length){e=0;for(var o=a.length;e<o;e++){i=a[e];j[i]||(j[i]=c.expr.match.POS.test(i)?c(i,b||this.context):i)}for(;f&&f.ownerDocument&&f!==b;){for(i in j){e=j[i];if(e.jquery?e.index(f)>-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a===
+"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",
+d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?
+a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType===
+1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/<tbody/i,jb=/<|&#?\w+;/,ta=/<script|<object|<embed|<option|<style/i,ua=/checked\s*(?:[^=]|=\s*.checked.)/i,Ma=function(a,b,d){return hb.test(d)?
+a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
+c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
+wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
+prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
+this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
+return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja,
+""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var j=c(this),i=j.html();j.empty().append(function(){return a.call(this,e,i)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&
+this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this,b,f))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(u){return c.nodeName(u,"table")?u.getElementsByTagName("tbody")[0]||
+u.appendChild(u.ownerDocument.createElement("tbody")):u}var e,j,i=a[0],o=[],k;if(!c.support.checkClone&&arguments.length===3&&typeof i==="string"&&ua.test(i))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(i))return this.each(function(u){var z=c(this);a[0]=i.call(this,u,b?z.html():w);z.domManip(a,b,d)});if(this[0]){e=i&&i.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:sa(a,this,o);k=e.fragment;if(j=k.childNodes.length===
+1?(k=k.firstChild):k.firstChild){b=b&&c.nodeName(j,"tr");for(var n=0,r=this.length;n<r;n++)d.call(b?f(this[n],j):this[n],n>0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]);
+return this}else{e=0;for(var j=d.length;e<j;e++){var i=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["",
+""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]==="<table>"&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e=
+c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]?
+c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja=
+function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=
+Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,
+"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=
+a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=
+a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=/<script(.|\s)*?\/script>/gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!==
+"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("<div />").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this},
+serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),
+function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,
+global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&
+e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)?
+"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===
+false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B=
+false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since",
+c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E||
+d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x);
+g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===
+1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b===
+"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional;
+if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");
+this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(la[d])f=la[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],
+"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},
+animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var j=c.extend({},e),i,o=this.nodeType===1&&c(this).is(":hidden"),k=this;for(i in a){var n=i.replace(ia,ja);if(i!==n){a[n]=a[i];delete a[i];i=n}if(a[i]==="hide"&&o||a[i]==="show"&&!o)return j.complete.call(this);if((i==="height"||i==="width")&&this.style){j.display=c.css(this,"display");j.overflow=this.style.overflow}if(c.isArray(a[i])){(j.specialEasing=
+j.specialEasing||{})[i]=a[i][1];a[i]=a[i][0]}}if(j.overflow!=null)this.style.overflow="hidden";j.curAnim=c.extend({},a);c.each(a,function(r,u){var z=new c.fx(k,j,r);if(Ab.test(u))z[u==="toggle"?o?"show":"hide":u](a);else{var C=Bb.exec(u),B=z.cur(true)||0;if(C){u=parseFloat(C[2]);var E=C[3]||"px";if(E!=="px"){k.style[r]=(u||1)+E;B=(u||1)/z.cur(true)*B;k.style[r]=B+E}if(C[1])u=(C[1]==="-="?-1:1)*u+B;z.custom(B,u,E)}else z.custom(B,u,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);
+this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration===
+"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||
+c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;
+this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=
+this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,
+e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||
+c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in s.documentElement?
+function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=
+this[0];if(a)return this.each(function(r){c.offset.setOffset(this,a,r)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=b,e=b.ownerDocument,j,i=e.documentElement,o=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var k=b.offsetTop,n=b.offsetLeft;(b=b.parentNode)&&b!==o&&b!==i;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;j=e?e.getComputedStyle(b,null):b.currentStyle;
+k-=b.scrollTop;n-=b.scrollLeft;if(b===d){k+=b.offsetTop;n+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&j.overflow!=="visible"){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=j}if(f.position==="relative"||f.position==="static"){k+=o.offsetTop;n+=o.offsetLeft}if(c.offset.supportsFixedPosition&&
+f.position==="fixed"){k+=Math.max(i.scrollTop,o.scrollTop);n+=Math.max(i.scrollLeft,o.scrollLeft)}return{top:k,left:n}};c.offset={initialize:function(){var a=s.body,b=s.createElement("div"),d,f,e,j=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
+a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b);
+c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,
+d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-
+f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset":
+"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in
+e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window);

+ 46 - 0
activeweb/src/test/java/app/controllers/DatabaseControllerSpec.java

@@ -0,0 +1,46 @@
+/*
+Copyright 2009-2010 Igor Polevoy 
+
+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. 
+*/
+
+/**
+ * @author Igor Polevoy: 12/18/13 4:42 PM
+ */
+
+package app.controllers;
+
+
+import org.javalite.activeweb.DBControllerSpec;
+import org.junit.Test;
+
+import java.util.Map;
+
+public class DatabaseControllerSpec extends DBControllerSpec {
+
+    @Test
+    public void shouldRenderOneRecord(){
+
+        //execute controller
+        request().get("index");
+
+        //process result
+        Map result = JsonHelper.toMap(responseContent());
+
+        //test result
+        a(result.size()).shouldBeEqual(2);
+        a(result.get("id")).shouldNotBeNull();
+        a(result.get("randomNumber")).shouldNotBeNull();
+        a(contentType()).shouldBeEqual("application/json");
+    }
+}

+ 45 - 0
activeweb/src/test/java/app/controllers/JsonControllerSpec.java

@@ -0,0 +1,45 @@
+/*
+Copyright 2009-2010 Igor Polevoy 
+
+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. 
+*/
+
+/**
+ * @author Igor Polevoy: 12/18/13 3:59 PM
+ */
+
+package app.controllers;
+
+import org.javalite.activeweb.Configuration;
+import org.javalite.activeweb.ControllerSpec;
+import org.junit.Test;
+
+import java.util.Map;
+
+public class JsonControllerSpec extends ControllerSpec {
+
+    @Test
+    public void shouldRenderMessage() {
+
+        System.out.println("ACTIVE_ENV value ============>>>>" + Configuration.getEnv());
+        //execute controller
+        request().get("index");
+
+        //process result
+        Map result = JsonHelper.toMap(responseContent());
+
+        //test result
+        a(result.get("message")).shouldBeEqual("Hello, World!");
+        a(contentType()).shouldBeEqual("application/json");
+    }
+}

+ 48 - 0
activeweb/src/test/java/app/controllers/JsonHelper.java

@@ -0,0 +1,48 @@
+/*
+Copyright 2009-2010 Igor Polevoy 
+
+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. 
+*/
+
+/**
+ * @author Igor Polevoy: 12/18/13 4:02 PM
+ */
+
+package app.controllers;
+
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import java.io.IOException;
+import java.util.Map;
+
+public class JsonHelper {
+
+    public static Map toMap(String json) {
+        ObjectMapper mapper = new ObjectMapper();
+        try {
+            return mapper.readValue(json, Map.class);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static Map[] toMaps(String json) {
+        ObjectMapper mapper = new ObjectMapper();
+        try {
+            return mapper.readValue(json, Map[].class);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+}

+ 65 - 10
aspnet-stripped/benchmark_config

@@ -3,51 +3,106 @@
   "tests": [{
     "default": {
       "setup_file": "setup_iis",
-      "os": "nt",
       "json_url": "/json",
       "plaintext_url": "/plaintext",
       "port": 8080,
-      "sort": 134
+      "approach": "Stripped",
+      "classification": "Fullstack",
+      "database": "None",
+      "framework": "aspnet",
+      "language": "C#",
+      "orm": "Raw",
+      "platform": "NET",
+      "webserver": "IIS",
+      "os": "Windows",
+      "database_os": "Linux",
+      "display_name": "aspnet-stripped",
+      "notes": "",
+      "versus": ""
     },
     "mysql-raw": {
       "setup_file": "setup_iis",
-      "os": "nt",
       "db_url": "/db?provider=mysql",
       "query_url": "/db?provider=mysql&queries=",
       "fortune_url": "/fortunes?provider=mysql",
       "update_url": "/updates?provider=mysql&queries=",
       "port": 8080,
-      "sort": 135
+      "approach": "Stripped",
+      "classification": "Fullstack",
+      "database": "MySQL",
+      "framework": "aspnet",
+      "language": "C#",
+      "orm": "Raw",
+      "platform": "NET",
+      "webserver": "IIS",
+      "os": "Windows",
+      "database_os": "Linux",
+      "display_name": "aspnet-stripped-raw",
+      "notes": "",
+      "versus": ""
     },
     "postgresql-raw": {
       "setup_file": "setup_iis",
-      "os": "nt",
       "db_url": "/db?provider=postgresql",
       "query_url": "/db?provider=postgresql&queries=",
       "fortune_url": "/fortunes?provider=postgresql",
       "update_url": "/updates?provider=postgresql&queries=",
       "port": 8080,
-      "sort": 136
+      "approach": "Stripped",
+      "classification": "Fullstack",
+      "database": "Postgres",
+      "framework": "aspnet",
+      "language": "C#",
+      "orm": "Raw",
+      "platform": "NET",
+      "webserver": "IIS",
+      "os": "Windows",
+      "database_os": "Linux",
+      "display_name": "aspnet-stripped-raw",
+      "notes": "",
+      "versus": ""
     },
     "mongodb-raw": {
       "setup_file": "setup_iis",
-      "os": "nt",
       "db_url": "/mongodbdb",
       "query_url": "/mongodbdb?queries=",
       "fortune_url": "/mongodbfortunes",
       "update_url": "/mongodbupdates?queries=",
       "port": 8080,
-      "sort": 137
+      "approach": "Stripped",
+      "classification": "Fullstack",
+      "database": "MongoDB",
+      "framework": "aspnet",
+      "language": "C#",
+      "orm": "Raw",
+      "platform": "NET",
+      "webserver": "IIS",
+      "os": "Windows",
+      "database_os": "Linux",
+      "display_name": "aspnet-stripped-raw",
+      "notes": "",
+      "versus": ""
     },
     "sqlserver-raw": {
       "setup_file": "setup_iis",
-      "os": "nt",
       "db_url": "/db?provider=sqlserver",
       "query_url": "/db?provider=sqlserver&queries=",
       "fortune_url": "/fortunes?provider=sqlserver",
       "update_url": "/updates?provider=sqlserver&queries=",
       "port": 8080,
-      "sort": 138
+      "approach": "Stripped",
+      "classification": "Fullstack",
+      "database": "SQLServer",
+      "framework": "aspnet",
+      "language": "C#",
+      "orm": "Raw",
+      "platform": "NET",
+      "webserver": "IIS",
+      "os": "Windows",
+      "database_os": "Windows",
+      "display_name": "aspnet-stripped-raw",
+      "notes": "",
+      "versus": ""
     }
   }]
 }

+ 3 - 0
aspnet-stripped/install.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+fw_depends mono

+ 19 - 1
aspnet-stripped/setup_iis.ps1

@@ -1,5 +1,23 @@
 param($action)
 
+$ErrorActionPreference = 'Stop'
+
+# From http://zduck.com/2012/powershell-batch-files-exit-codes/
+function Exec
+{
+    [CmdletBinding()]
+    param (
+        [Parameter(Position=0, Mandatory=1)]
+        [scriptblock]$Command,
+        [Parameter(Position=1, Mandatory=0)]
+        [string]$ErrorMessage = "Execution of command failed.`n$Command"
+    )
+    & $Command
+    if ($LastExitCode -ne 0) {
+        throw "Exec: $ErrorMessage"
+    }
+}
+
 $source = "C:\FrameworkBenchmarks\aspnet-stripped\src"
 
 # Stop
@@ -8,7 +26,7 @@ if (Get-WebSite -Name Benchmarks) { Remove-WebSite -Name Benchmarks }
 if ($action -eq 'start') {
     # Because we don't use msbuild to compile the code, we do this all manually.
     
-    & .\NuGet.exe install -o src\packages src\packages.config
+    Exec { & .\NuGet.exe install -o src\packages src\packages.config }
 
     if (-Not (Test-Path src\bin)) { New-Item -Path src\bin -ItemType directory | Out-Null }
 

+ 4 - 4
aspnet-stripped/setup_iis.py

@@ -3,20 +3,20 @@ import sys
 import setup_util
 import os
 
-def start(args):
+def start(args, logfile, errfile):
   if os.name != 'nt':
     return 1
   
   try:
     setup_util.replace_text("aspnet-stripped/src/Web.config", "localhost", args.database_host)
-    subprocess.check_call("powershell -File setup_iis.ps1 start", cwd="aspnet-stripped")
+    subprocess.check_call("powershell -Command .\\setup_iis.ps1 start", cwd="aspnet-stripped", stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1
 
-def stop():
+def stop(logfile, errfile):
   if os.name != 'nt':
     return 0
   
-  subprocess.Popen("powershell -File setup_iis.ps1 stop", cwd="aspnet-stripped")
+  subprocess.check_call("powershell -Command .\\setup_iis.ps1 stop", cwd="aspnet-stripped", stderr=errfile, stdout=logfile)
   return 0

+ 14 - 0
aspnet-stripped/source_code

@@ -0,0 +1,14 @@
+./aspnet-stripped/src/App_Code/
+./aspnet-stripped/src/App_Code/MyModule.cs
+./aspnet-stripped/src/App_Code/UpdatesHandler.cs
+./aspnet-stripped/src/App_Code/FortunesPage.cs
+./aspnet-stripped/src/App_Code/Models
+./aspnet-stripped/src/App_Code/Models/Fortune.cs
+./aspnet-stripped/src/App_Code/Models/MongoDB.cs
+./aspnet-stripped/src/App_Code/Models/World.cs
+./aspnet-stripped/src/App_Code/Common.cs
+./aspnet-stripped/src/App_Code/MongoDBHandlers.cs
+./aspnet-stripped/src/App_Code/PlaintextHandler.cs
+./aspnet-stripped/src/App_Code/DbHandler.cs
+./aspnet-stripped/src/App_Code/JsonHandler.cs
+./aspnet-stripped/src/App_Code/NoAspxHandlerFactory.cs

+ 8 - 10
aspnet/README.md

@@ -18,12 +18,12 @@
 **Platforms**
 
 * .NET Framework 4.5 (Windows)
-* Mono 3.0.10 (Linux)
+* Mono 3.2.1 (Linux)
 
 **Web Servers**
 
 * IIS 8 (Windows)
-* XSP 2.11.0.0 (3.0?) (Linux)
+* XSP latest (Linux)
 * nginx 1.4.1 & XSP FastCGI (Linux)
 
 **Web Stack**
@@ -34,22 +34,21 @@
 **Databases**
 
 * MySQL Connector/Net 6.7.2-beta ([custom build](https://github.com/pdonald/mysql-connector-net))
-* Npgsql 2.0.12 ([custom build](https://github.com/pdonald/Npgsql2))
-* Entity Framework 6.0.0-alpha3
-* Mongo C# Driver 1.8.1
-* SqlClient Data Provider for SQL Server
+* Npgsql 2.0.13-beta1
+* Entity Framework 6.0.0-beta1
+* Mongo C# Driver 1.8.2
 
 **Developer Tools**
 
-* Visual Studio 2012 Update 2
+* Visual Studio 2012
 
 ## Mono Installation
 
-    sudo apt-get install build-essential autoconf automake libtool zlib1g-dev git
+    sudo apt-get install git-core build-essential autoconf automake libtool zlib1g-dev pkg-config
 
     git clone git://github.com/mono/mono
     cd mono
-    git checkout mono-3.0.10
+    git checkout mono-3.2.1
     ./autogen.sh --prefix=/usr/local
     make get-monolite-latest
     make EXTERNAL_MCS=${PWD}/mcs/class/lib/monolite/gmcs.exe
@@ -59,7 +58,6 @@
 
     git clone git://github.com/mono/xsp
     cd xsp
-    git checkout 3.0
     ./autogen.sh --prefix=/usr/local
     make
     sudo make install

+ 234 - 28
aspnet/benchmark_config

@@ -3,114 +3,260 @@
   "tests": [{
     "default": {
       "setup_file": "setup_iis",
-      "os": "nt",
       "json_url": "/json/default",
       "plaintext_url": "/plaintext",
       "port": 8080,
-      "sort": 90
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "None",
+      "framework": "aspnet-mvc",
+      "language": "C#",
+      "orm": "Raw",
+      "platform": "NET",
+      "webserver": "IIS",
+      "os": "Windows",
+      "database_os": "Linux",
+      "display_name": "aspnet",
+      "notes": "",
+      "versus": ""
     },
     "jsonnet": {
       "setup_file": "setup_iis",
-      "os": "nt",
       "json_url": "/json/jsonnet",
       "port": 8080,
-      "sort": 138
+      "approach": "Realistic",
+      "classification": "Platform",
+      "database": "None",
+      "framework": "aspnet",
+      "language": "C#",
+      "orm": "Raw",
+      "platform": "NET",
+      "webserver": "IIS",
+      "os": "Windows",
+      "database_os": "Linux",
+      "display_name": "aspnet-jsonnet",
+      "notes": "",
+      "versus": ""
     },
     "servicestack": {
       "setup_file": "setup_iis",
-      "os": "nt",
       "json_url": "/json/servicestack",
       "port": 8080,
-      "sort": 139
+      "approach": "Realistic",
+      "classification": "Platform",
+      "database": "None",
+      "framework": "aspnet",
+      "language": "C#",
+      "orm": "Raw",
+      "platform": "NET",
+      "webserver": "IIS",
+      "os": "Windows",
+      "database_os": "Linux",
+      "display_name": "aspnet-svcstk",
+      "notes": "",
+      "versus": ""
     },
     "mysql-raw": {
       "setup_file": "setup_iis",
-      "os": "nt",
       "db_url": "/ado/mysql",
       "query_url": "/ado/mysql?queries=",
       "fortune_url": "/ado/mysql/fortunes",
       "update_url": "/ado/mysql/update?queries=",
       "port": 8080,
-      "sort": 91
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "MySQL",
+      "framework": "aspnet-mvc",
+      "language": "C#",
+      "orm": "Raw",
+      "platform": "NET",
+      "webserver": "IIS",
+      "os": "Windows",
+      "database_os": "Linux",
+      "display_name": "aspnet-mvc-raw",
+      "notes": "",
+      "versus": ""
     },
     "postgresql-raw": {
       "setup_file": "setup_iis",
-      "os": "nt",
       "db_url": "/ado/postgresql",
       "query_url": "/ado/postgresql?queries=",
       "fortune_url": "/ado/postgresql/fortunes",
       "update_url": "/ado/postgresql/update?queries=",
       "port": 8080,
-      "sort": 92
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "Postgres",
+      "framework": "aspnet-mvc",
+      "language": "C#",
+      "orm": "Raw",
+      "platform": "NET",
+      "webserver": "IIS",
+      "os": "Windows",
+      "database_os": "Linux",
+      "display_name": "aspnet-mvc-raw",
+      "notes": "",
+      "versus": ""
     },
     "mongodb-raw": {
       "setup_file": "setup_iis",
-      "os": "nt",
       "db_url": "/mongodb",
       "query_url": "/mongodb?queries=",
       "fortune_url": "/mongodb/fortunes",
       "update_url": "/mongodb/update?queries=",
       "port": 8080,
-      "sort": 93
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "MongoDB",
+      "framework": "aspnet-mvc",
+      "language": "C#",
+      "orm": "Raw",
+      "platform": "NET",
+      "webserver": "IIS",
+      "os": "Windows",
+      "database_os": "Linux",
+      "display_name": "aspnet-mvc-raw",
+      "notes": "",
+      "versus": ""
     },
     "sqlserver-raw": {
       "setup_file": "setup_iis",
-      "os": "nt",
       "db_url": "/ado/sqlserver",
       "query_url": "/ado/sqlserver?queries=",
       "fortune_url": "/ado/sqlserver/fortunes",
       "update_url": "/ado/sqlserver/update?queries=",
       "port": 8080,
-      "sort": 94
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "SQLServer",
+      "framework": "aspnet-mvc",
+      "language": "C#",
+      "orm": "Raw",
+      "platform": "NET",
+      "webserver": "IIS",
+      "os": "Windows",
+      "database_os": "Windows",
+      "display_name": "aspnet-mvc-raw",
+      "notes": "",
+      "versus": ""
     },
     "mysql-entityframework": {
       "setup_file": "setup_iis",
-      "os": "nt",
       "db_url": "/entityframework/mysql",
       "query_url": "/entityframework/mysql?queries=",
       "fortune_url": "/entityframework/mysql/fortunes",
       "update_url": "/entityframework/mysql/update?queries=",
       "port": 8080,
-      "sort": 95
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "MySQL",
+      "framework": "aspnet-mvc",
+      "language": "C#",
+      "orm": "Full",
+      "platform": "NET",
+      "webserver": "IIS",
+      "os": "Windows",
+      "database_os": "Linux",
+      "display_name": "aspnet-mvc",
+      "notes": "",
+      "versus": ""
     },
     "postgresql-entityframework": {
       "setup_file": "setup_iis",
-      "os": "nt",
       "db_url": "/entityframework/postgresql",
       "query_url": "/entityframework/postgresql?queries=",
       "fortune_url": "/entityframework/postgresql/fortunes",
       "update_url": "/entityframework/postgresql/update?queries=",
       "port": 8080,
-      "sort": 96
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "Postgres",
+      "framework": "aspnet-mvc",
+      "language": "C#",
+      "orm": "Full",
+      "platform": "NET",
+      "webserver": "IIS",
+      "os": "Windows",
+      "database_os": "Linux",
+      "display_name": "aspnet-mvc",
+      "notes": "",
+      "versus": ""
     },
     "sqlserver-entityframework": {
       "setup_file": "setup_iis",
-      "os": "nt",
       "db_url": "/entityframework/sqlserver",
       "query_url": "/entityframework/sqlserver?queries=",
       "fortune_url": "/entityframework/sqlserver/fortunes",
       "update_url": "/entityframework/sqlserver/update?queries=",
       "port": 8080,
-      "sort": 97
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "SQLServer",
+      "framework": "aspnet-mvc",
+      "language": "C#",
+      "orm": "Full",
+      "platform": "NET",
+      "webserver": "IIS",
+      "os": "Windows",
+      "database_os": "Windows",
+      "display_name": "aspnet-mvc",
+      "notes": "",
+      "versus": ""
     },
     "mono": {
       "setup_file": "setup_nginx",
       "json_url": "/json/default",
       "plaintext_url": "/plaintext",
       "port": 8080,
-      "sort": 100
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "None",
+      "framework": "aspnet-mvc",
+      "language": "C#",
+      "orm": "Raw",
+      "platform": "Mono",
+      "webserver": "nginx",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "aspnet-mvc-mono",
+      "notes": "",
+      "versus": ""
     },
     "mono-jsonnet": {
       "setup_file": "setup_nginx",
       "json_url": "/json/jsonnet",
       "port": 8080,
-      "sort": 136
+      "approach": "Realistic",
+      "classification": "Platform",
+      "database": "None",
+      "framework": "aspnet",
+      "language": "C#",
+      "orm": "Raw",
+      "platform": "Mono",
+      "webserver": "nginx",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "aspnet-jsonnet-mono",
+      "notes": "",
+      "versus": ""
     },
     "mono-servicestack": {
       "setup_file": "setup_nginx",
       "json_url": "/json/servicestack",
       "port": 8080,
-      "sort": 140
+      "approach": "Realistic",
+      "classification": "Platform",
+      "database": "None",
+      "framework": "aspnet",
+      "language": "C#",
+      "orm": "Raw",
+      "platform": "Mono",
+      "webserver": "nginx",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "aspnet-svcstk-mono",
+      "notes": "",
+      "versus": ""
     },
     "mono-mysql-raw": {
       "setup_file": "setup_nginx",
@@ -119,7 +265,19 @@
       "fortune_url": "/ado/mysql/fortunes",
       "update_url": "/ado/mysql/update?queries=",
       "port": 8080,
-      "sort": 101
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "MySQL",
+      "framework": "aspnet-mvc",
+      "language": "C#",
+      "orm": "Raw",
+      "platform": "Mono",
+      "webserver": "nginx",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "aspnet-mvc-mono-raw",
+      "notes": "",
+      "versus": ""
     },
     "mono-postgresql-raw": {
       "setup_file": "setup_nginx",
@@ -128,7 +286,19 @@
       "fortune_url": "/ado/postgresql/fortunes",
       "update_url": "/ado/postgresql/update?queries=",
       "port": 8080,
-      "sort": 102
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "Postgres",
+      "framework": "aspnet-mvc",
+      "language": "C#",
+      "orm": "Raw",
+      "platform": "Mono",
+      "webserver": "nginx",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "aspnet-mvc-mono-raw",
+      "notes": "",
+      "versus": ""
     },
     "mono-mongodb-raw": {
       "setup_file": "setup_nginx",
@@ -137,7 +307,19 @@
       "fortune_url": "/mongodb/fortunes",
       "update_url": "/mongodb/update?queries=",
       "port": 8080,
-      "sort": 103
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "MongoDB",
+      "framework": "aspnet-mvc",
+      "language": "C#",
+      "orm": "Raw",
+      "platform": "Mono",
+      "webserver": "nginx",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "aspnet-mvc-mono-raw",
+      "notes": "",
+      "versus": ""
     },
     "mono-mysql-entityframework": {
       "setup_file": "setup_nginx",
@@ -146,7 +328,19 @@
       "fortune_url": "/entityframework/mysql/fortunes",
       "update_url": "/entityframework/mysql/update?queries=",
       "port": 8080,
-      "sort": 104
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "MySQL",
+      "framework": "aspnet-mvc",
+      "language": "C#",
+      "orm": "Full",
+      "platform": "Mono",
+      "webserver": "nginx",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "aspnet-mvc-mono",
+      "notes": "Entity framework",
+      "versus": ""
     },
     "mono-postgresql-entityframework": {
       "setup_file": "setup_nginx",
@@ -155,7 +349,19 @@
       "fortune_url": "/entityframework/postgresql/fortunes",
       "update_url": "/entityframework/postgresql/update?queries=",
       "port": 8080,
-      "sort": 105
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "Postgres",
+      "framework": "aspnet-mvc",
+      "language": "C#",
+      "orm": "Full",
+      "platform": "Mono",
+      "webserver": "nginx",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "aspnet-mvc-mono",
+      "notes": "Entity framework",
+      "versus": ""
     }
   }]
 }

+ 3 - 0
aspnet/install.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+fw_depends mono

二進制
aspnet/lib/.nuget/NuGet.exe


+ 2 - 2
aspnet/lib/.nuget/NuGet.targets

@@ -45,7 +45,7 @@
         <PackageSources Condition=" $(PackageSources) == '' ">@(PackageSource)</PackageSources>
         
         <NuGetCommand Condition=" '$(OS)' == 'Windows_NT'">"$(NuGetExePath)"</NuGetCommand>
-        <NuGetCommand Condition=" '$(OS)' != 'Windows_NT' ">mono --runtime=v4.0.30319 $(NuGetExePath)</NuGetCommand>
+        <NuGetCommand Condition=" '$(OS)' != 'Windows_NT' ">mono $(NuGetExePath)</NuGetCommand>
 
         <PackageOutputDir Condition="$(PackageOutputDir) == ''">$(TargetDir.Trim('\\'))</PackageOutputDir>
         
@@ -132,4 +132,4 @@
             </Code>
         </Task>
     </UsingTask>
-</Project>
+</Project>

+ 7 - 7
aspnet/lib/packages.config

@@ -1,14 +1,14 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="EntityFramework" version="6.0.0-alpha3" targetFramework="net45" />
-  <package id="Microsoft.AspNet.Mvc" version="4.0.20710.0" targetFramework="net45" />
-  <package id="Microsoft.AspNet.Razor" version="2.0.20715.0" targetFramework="net45" />
-  <package id="Microsoft.AspNet.WebPages" version="2.0.20710.0" targetFramework="net45" />
+  <package id="EntityFramework" version="6.0.0-beta1" targetFramework="net45" />
+  <package id="Microsoft.AspNet.Mvc" version="4.0.30506.0" targetFramework="net45" />
+  <package id="Microsoft.AspNet.Razor" version="2.0.30506.0" targetFramework="net45" />
+  <package id="Microsoft.AspNet.WebPages" version="2.0.30506.0" targetFramework="net45" />
   <package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net45" />
   <package id="MSBuild.Microsoft.VisualStudio.Web.targets" version="11.0.2.1" />
-  <package id="mongocsharpdriver" version="1.8.1" targetFramework="net45" />
+  <package id="mongocsharpdriver" version="1.8.2" targetFramework="net45" />
   <package id="MySql.Data.Entity" version="6.7.2-beta-ef6" targetFramework="net45" />
-  <package id="Npgsql.EF6" version="2.0.12-pre4" targetFramework="net45" />
+  <package id="Npgsql" version="2.0.13-beta1" targetFramework="net45" />
   <package id="Newtonsoft.Json" version="5.0.6" targetFramework="net45" />
-  <package id="ServiceStack.Text" version="3.9.48" targetFramework="net45" />
+  <package id="ServiceStack.Text" version="3.9.56" targetFramework="net45" />
 </packages>

+ 1 - 1
aspnet/nginx.conf

@@ -1,6 +1,6 @@
 # worker_processes n;
 pid /tmp/nginx.pid;
-error_log /dev/null crit;
+error_log stderr error;
 
 events {
     worker_connections 8192;

+ 21 - 3
aspnet/setup_iis.ps1

@@ -1,5 +1,23 @@
 param($action)
 
+$ErrorActionPreference = 'Stop'
+
+# From http://zduck.com/2012/powershell-batch-files-exit-codes/
+function Exec
+{
+    [CmdletBinding()]
+    param (
+        [Parameter(Position=0, Mandatory=1)]
+        [scriptblock]$Command,
+        [Parameter(Position=1, Mandatory=0)]
+        [string]$ErrorMessage = "Execution of command failed.`n$Command"
+    )
+    & $Command
+    if ($LastExitCode -ne 0) {
+        throw "Exec: $ErrorMessage"
+    }
+}
+
 $wwwroot = "C:\FrameworkBenchmarks\aspnet\www"
 $source = "C:\FrameworkBenchmarks\aspnet\src"
 $msbuild = "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe"
@@ -15,7 +33,7 @@ if ($action -eq 'start') {
     New-WebSite -Name Benchmarks -Port 8080 -PhysicalPath $wwwroot
     
     # Build the project
-    &$msbuild "$source\Benchmarks.AspNet.csproj" /t:RestorePackages
-    &$msbuild "$source\Benchmarks.AspNet.csproj" /p:Configuration=Release /p:Platform=x64 /t:Clean
-    &$msbuild "$source\Benchmarks.AspNet.csproj" /p:Configuration=Release /p:Platform=x64 /p:DeployOnBuild=true /p:PublishProfile=IIS
+    Exec { & $msbuild "$source\Benchmarks.AspNet.csproj" /t:RestorePackages }
+    Exec { & $msbuild "$source\Benchmarks.AspNet.csproj" /p:Configuration=Release /p:Platform=x64 /t:Clean }
+    Exec { & $msbuild "$source\Benchmarks.AspNet.csproj" /p:Configuration=Release /p:Platform=x64 /p:DeployOnBuild=true /p:PublishProfile=IIS }
 }

+ 4 - 4
aspnet/setup_iis.py

@@ -3,20 +3,20 @@ import sys
 import setup_util
 import os
 
-def start(args):
+def start(args, logfile, errfile):
   if os.name != 'nt':
     return 1
   
   try:
     setup_util.replace_text("aspnet/src/Web.config", "localhost", args.database_host)
-    subprocess.check_call("powershell -File setup_iis.ps1 start", cwd="aspnet")
+    subprocess.check_call("powershell -Command .\\setup_iis.ps1 start", cwd="aspnet", stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1
 
-def stop():
+def stop(logfile, errfile):
   if os.name != 'nt':
     return 0
   
-  subprocess.Popen("powershell -File setup_iis.ps1 stop", cwd="aspnet")
+  subprocess.check_call("powershell -Command .\\setup_iis.ps1 stop", cwd="aspnet", stderr=errfile, stdout=logfile)
   return 0

+ 19 - 11
aspnet/setup_nginx.py

@@ -6,7 +6,7 @@ import os
 root = os.getcwd() + "/aspnet"
 app = root + "/src"
 
-def start(args):
+def start(args, logfile, errfile):
   if os.name == 'nt':
     return 1
   
@@ -14,27 +14,35 @@ def start(args):
 
   try:
     # build
-    subprocess.check_call("rm -rf bin obj", shell=True, cwd=app)
-    subprocess.check_call("xbuild /p:Configuration=Release", shell=True, cwd=app)
-    subprocess.check_call("sudo chown -R $USER:$USER /usr/local/etc/mono", shell=True)
+    subprocess.check_call("rm -rf bin obj", shell=True, cwd=app, stderr=errfile, stdout=logfile)
+    subprocess.check_call("xbuild /p:Configuration=Release", shell=True, cwd=app, stderr=errfile, stdout=logfile)
+    subprocess.check_call("sudo chown -R $USER:$USER /usr/local/etc/mono", shell=True, stderr=errfile, stdout=logfile)
     
     # nginx
     workers = 'worker_processes ' + str(args.max_threads) + ';'
-    subprocess.check_call('echo "upstream mono {\n' + ';\n'.join('\tserver 127.0.0.1:' + str(port) for port in range(9001, 9001 + args.max_threads)) + ';\n}" > ' + root + '/nginx.upstream.conf', shell=True);
-    subprocess.check_call('sudo /usr/local/nginx/sbin/nginx -c ' + root + '/nginx.conf -g "' + workers + '"', shell=True)
+    subprocess.check_call('echo "upstream mono {\n' + ';\n'.join('\tserver 127.0.0.1:' + str(port) for port in range(9001, 9001 + args.max_threads)) + ';\n}" > ' + root + '/nginx.upstream.conf', shell=True, stderr=errfile, stdout=logfile);
+    subprocess.check_call('sudo /usr/local/nginx/sbin/nginx -c ' + root + '/nginx.conf -g "' + workers + '"', shell=True, stderr=errfile, stdout=logfile)
     
     # fastcgi
     for port in range(9001, 9001 + args.max_threads):
-      subprocess.Popen("MONO_OPTIONS=--gc=sgen fastcgi-mono-server4 /applications=/:. /socket=tcp:127.0.0.1:" + str(port) + " &", shell=True, cwd=app)
+      subprocess.Popen("MONO_OPTIONS=--gc=sgen fastcgi-mono-server4 /applications=/:. /socket=tcp:127.0.0.1:" + str(port) + " &", shell=True, cwd=app, stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1
 
-def stop():
+def stop(logfile, errfile):
   if os.name == 'nt':
     return 0
   
-  subprocess.check_call("sudo /usr/local/nginx/sbin/nginx -c " + root + "/nginx.conf -s stop", shell=True)
-  subprocess.check_call("rm -f " + root + "/nginx.upstream.conf", shell=True)
-  subprocess.check_call("pkill -9 mono-sgen", shell=True)
+  subprocess.check_call("sudo /usr/local/nginx/sbin/nginx -c " + root + "/nginx.conf -s stop", shell=True, stderr=errfile, stdout=logfile)
+  subprocess.check_call("rm -f " + root + "/nginx.upstream.conf", shell=True, stderr=errfile, stdout=logfile)
+  #
+  # stop mono
+  #
+  p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
+  out, err = p.communicate()
+  for line in out.splitlines():
+    if 'mono-server' in line:
+      pid = int(line.split(None, 2)[1])
+      os.kill(pid, 15)
   return 0

+ 7 - 7
aspnet/setup_xsp.py

@@ -3,22 +3,22 @@ import sys
 import setup_util
 import os
 
-def start(args):
+def start(args, logfile, errfile):
   if os.name == 'nt':
     return 1
   
   setup_util.replace_text("aspnet/src/Web.config", "localhost", args.database_host)
 
   try:
-    subprocess.check_call("rm -rf bin obj", shell=True, cwd="aspnet/src")
-    subprocess.check_call("xbuild /p:Configuration=Release", shell=True, cwd="aspnet/src")
-    subprocess.check_call("sudo chown -R ubuntu:ubuntu /usr/local/etc/mono", shell=True)
-    subprocess.Popen("MONO_OPTIONS=--gc=sgen xsp4 --nonstop", shell=True, cwd="aspnet/src")
+    subprocess.check_call("rm -rf bin obj", shell=True, cwd="aspnet/src", stderr=errfile, stdout=logfile)
+    subprocess.check_call("xbuild /p:Configuration=Release", shell=True, cwd="aspnet/src", stderr=errfile, stdout=logfile)
+    subprocess.check_call("sudo chown -R ubuntu:ubuntu /usr/local/etc/mono", shell=True, stderr=errfile, stdout=logfile)
+    subprocess.Popen("MONO_OPTIONS=--gc=sgen xsp4 --nonstop", shell=True, cwd="aspnet/src", stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1
 
-def stop():
+def stop(logfile, errfile):
   if os.name == 'nt':
     return 0
   
@@ -28,7 +28,7 @@ def stop():
     if 'xsp4' in line:
       pid = int(line.split(None, 2)[1])
       try:
-        os.kill(pid, 9)
+        os.kill(pid, 15)
       except OSError:
         pass
   return 0

+ 24 - 0
aspnet/source_code

@@ -0,0 +1,24 @@
+./aspnet/src
+./aspnet/src/Benchmarks.sln
+./aspnet/src/Models
+./aspnet/src/Models/Fortune.cs
+./aspnet/src/Models/EntityFramework.cs
+./aspnet/src/Models/MongoDB.cs
+./aspnet/src/Models/World.cs
+./aspnet/src/Web.config
+./aspnet/src/Application.cs
+./aspnet/src/Controllers
+./aspnet/src/Controllers/JsonController.cs
+./aspnet/src/Controllers/MongoDBController.cs
+./aspnet/src/Controllers/EntityFrameworkController.cs
+./aspnet/src/Controllers/HomeController.cs
+./aspnet/src/Controllers/PlaintextController.cs
+./aspnet/src/Controllers/AdoController.cs
+./aspnet/src/Benchmarks.AspNet.csproj
+./aspnet/src/Views
+./aspnet/src/Views/Web.config
+./aspnet/src/Views/Fortunes.cshtml
+./aspnet/src/Views/Index.cshtml
+./aspnet/src/Properties
+./aspnet/src/Properties/PublishProfiles
+./aspnet/src/Properties/PublishProfiles/IIS.pubxml

+ 13 - 13
aspnet/src/Benchmarks.AspNet.csproj

@@ -45,27 +45,27 @@
     <Reference Include="System.Web.Extensions" />
     <Reference Include="System.Web.Mvc">
       <Private>True</Private>
-      <HintPath>..\lib\Microsoft.AspNet.Mvc.4.0.20710.0\lib\net40\System.Web.Mvc.dll</HintPath>
+      <HintPath>..\lib\Microsoft.AspNet.Mvc.4.0.30506.0\lib\net40\System.Web.Mvc.dll</HintPath>
     </Reference>
     <Reference Include="System.Web.Helpers">
       <Private>True</Private>
-      <HintPath>..\lib\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.Helpers.dll</HintPath>
+      <HintPath>..\lib\Microsoft.AspNet.WebPages.2.0.30506.0\lib\net40\System.Web.Helpers.dll</HintPath>
     </Reference>
     <Reference Include="System.Web.Razor">
       <Private>True</Private>
-      <HintPath>..\lib\Microsoft.AspNet.Razor.2.0.20715.0\lib\net40\System.Web.Razor.dll</HintPath>
+      <HintPath>..\lib\Microsoft.AspNet.Razor.2.0.30506.0\lib\net40\System.Web.Razor.dll</HintPath>
     </Reference>
     <Reference Include="System.Web.WebPages">
       <Private>True</Private>
-      <HintPath>..\lib\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.dll</HintPath>
+      <HintPath>..\lib\Microsoft.AspNet.WebPages.2.0.30506.0\lib\net40\System.Web.WebPages.dll</HintPath>
     </Reference>
     <Reference Include="System.Web.WebPages.Deployment">
       <Private>True</Private>
-      <HintPath>..\lib\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.Deployment.dll</HintPath>
+      <HintPath>..\lib\Microsoft.AspNet.WebPages.2.0.30506.0\lib\net40\System.Web.WebPages.Deployment.dll</HintPath>
     </Reference>
     <Reference Include="System.Web.WebPages.Razor">
       <Private>True</Private>
-      <HintPath>..\lib\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.Razor.dll</HintPath>
+      <HintPath>..\lib\Microsoft.AspNet.WebPages.2.0.30506.0\lib\net40\System.Web.WebPages.Razor.dll</HintPath>
     </Reference>
     <Reference Include="Microsoft.Web.Infrastructure">
       <Private>True</Private>
@@ -75,15 +75,15 @@
       <HintPath>..\lib\Newtonsoft.Json.5.0.6\lib\net45\Newtonsoft.Json.dll</HintPath>
     </Reference>
     <Reference Include="ServiceStack.Text">
-      <HintPath>..\lib\ServiceStack.Text.3.9.48\lib\net35\ServiceStack.Text.dll</HintPath>
+      <HintPath>..\lib\ServiceStack.Text.3.9.56\lib\net35\ServiceStack.Text.dll</HintPath>
     </Reference>
     <Reference Include="EntityFramework">
       <Private>True</Private>
-      <HintPath>..\lib\EntityFramework.6.0.0-alpha3\lib\net45\EntityFramework.dll</HintPath>
+      <HintPath>..\lib\EntityFramework.6.0.0-beta1\lib\net45\EntityFramework.dll</HintPath>
     </Reference>
     <Reference Include="EntityFramework">
       <Private>True</Private>
-      <HintPath>..\lib\EntityFramework.6.0.0-alpha3\lib\net45\EntityFramework.SqlServer.dll</HintPath>
+      <HintPath>..\lib\EntityFramework.6.0.0-beta1\lib\net45\EntityFramework.SqlServer.dll</HintPath>
     </Reference>
     <Reference Include="MySql">
       <Private>True</Private>
@@ -95,19 +95,19 @@
     </Reference>
     <Reference Include="Npgsql">
       <Private>True</Private>
-      <HintPath>..\lib\Npgsql.EF6.2.0.12-pre4\lib\net45\Npgsql.dll</HintPath>
+      <HintPath>..\lib\Npgsql.2.0.13-beta1\lib\net45\Npgsql.dll</HintPath>
     </Reference>
     <Reference Include="Npgsql">
       <Private>True</Private>
-      <HintPath>..\lib\Npgsql.EF6.2.0.12-pre4\lib\net45\Mono.Security.dll</HintPath>
+      <HintPath>..\lib\Npgsql.2.0.13-beta1\lib\net45\Mono.Security.dll</HintPath>
     </Reference>
     <Reference Include="MongoDB">
       <Private>True</Private>
-      <HintPath>..\lib\mongocsharpdriver.1.8.1\lib\net35\MongoDB.Bson.dll</HintPath>
+      <HintPath>..\lib\mongocsharpdriver.1.8.2\lib\net35\MongoDB.Bson.dll</HintPath>
     </Reference>
     <Reference Include="MongoDB">
       <Private>True</Private>
-      <HintPath>..\lib\mongocsharpdriver.1.8.1\lib\net35\MongoDB.Driver.dll</HintPath>
+      <HintPath>..\lib\mongocsharpdriver.1.8.2\lib\net35\MongoDB.Driver.dll</HintPath>
     </Reference>
   </ItemGroup>
   <ItemGroup>

+ 4 - 4
aspnet/src/Web.config

@@ -16,15 +16,15 @@
     <DbProviderFactories>
       <clear/>
       <add name="MySql.Data.MySqlClient" description="Data Provider for MySQL" invariant="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.7.2.0"/>
-      <add name="Npgsql" description="Data Provider for PostgreSQL" invariant="Npgsql" type="Npgsql.NpgsqlFactory, Npgsql, Version=2.0.12.0"/>
-      <add name="SqlClient Data Provider" description=".Net Framework Data Provider for SqlServer" invariant="System.Data.SqlClient" type="System.Data.SqlClient.SqlClientFactory, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
+      <add name="Npgsql" description="Data Provider for PostgreSQL" invariant="Npgsql" type="Npgsql.NpgsqlFactory, Npgsql, Version=2.0.13.91"/>
+      <add name="System.Data.SqlClient" description="Data Provider for Microsoft SQL Server" invariant="System.Data.SqlClient" type="System.Data.SqlClient.SqlClientFactory, System.Data, Version=4.0.0.0"/>
     </DbProviderFactories>
   </system.data>
   <!-- Entity Framework -->
   <entityFramework>
     <providers>
       <provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity, Version=6.7.2.0"/>
-      <provider invariantName="Npgsql" type="Npgsql.NpgsqlServices, Npgsql, Version=2.0.12.0"/>
+      <provider invariantName="Npgsql" type="Npgsql.NpgsqlServices, Npgsql, Version=2.0.13.91"/>
       <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
     </providers>
   </entityFramework>
@@ -59,4 +59,4 @@
       <add name="Framework Benchmarks" type="Benchmarks.AspNet.Application"/>
     </httpModules>
   </system.web>
-</configuration>
+</configuration>

+ 15 - 1
beego/benchmark_config

@@ -4,8 +4,22 @@
     "default": {
       "setup_file": "setup",
       "json_url": "/json",
+      "db_url": "/db",
+      "plaintext_url": "/plaintext",
       "port": 8080,
-      "sort": 119
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "MySQL",
+      "framework": "beego",
+      "language": "Go",
+      "orm": "beego ORM",
+      "platform": "Go",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "beego",
+      "notes": "",
+      "versus": "go"
     }
   }]
 }

+ 3 - 0
beego/install.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+fw_depends go

+ 10 - 9
beego/setup.py

@@ -3,23 +3,24 @@ import subprocess
 import sys
 import os
 
-def start(args):
+def start(args, logfile, errfile):
   if os.name == 'nt':
-    subprocess.call("set GOPATH=C:\\FrameworkBenchmarks\\beego&&go get ./...", shell=True, cwd="beego")
-    subprocess.Popen("setup.bat", shell=True, cwd="beego")
+    subprocess.call("set GOPATH=C:\\FrameworkBenchmarks\\beego&&go get ./...", shell=True, cwd="beego", stderr=errfile, stdout=logfile)
+    subprocess.Popen("setup.bat", shell=True, cwd="beego", stderr=errfile, stdout=logfile)
     return 0
-  subprocess.call("go get ./...", shell=True, cwd="beego")
-  subprocess.Popen("go run src/hello/hello.go".rsplit(" "), cwd="beego")
+  os.environ["GOPATH"] = os.path.expanduser('~/FrameworkBenchmarks/beego')
+  subprocess.call("go get ./...", shell=True, cwd="beego", stderr=errfile, stdout=logfile)
+  subprocess.Popen("go run src/hello/hello.go".rsplit(" "), cwd="beego", stderr=errfile, stdout=logfile)
   return 0
-def stop():
+def stop(logfile, errfile):
   if os.name == 'nt':
-    subprocess.call("taskkill /f /im go.exe > NUL", shell=True)
-    subprocess.call("taskkill /f /im hello.exe > NUL", shell=True)
+    subprocess.call("taskkill /f /im go.exe > NUL", shell=True, stderr=errfile, stdout=logfile)
+    subprocess.call("taskkill /f /im hello.exe > NUL", shell=True, stderr=errfile, stdout=logfile)
     return 0
   p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
   out, err = p.communicate()
   for line in out.splitlines():
     if 'hello' in line:
       pid = int(line.split(None, 2)[1])
-      os.kill(pid, 9)
+      os.kill(pid, 15)
   return 0

+ 2 - 0
beego/source_code

@@ -0,0 +1,2 @@
+./beego/src/hello/
+./beego/src/hello/hello.go

+ 61 - 4
beego/src/hello/hello.go

@@ -1,12 +1,36 @@
 package main
 
 import (
+	"log"
+	"math/rand"
 	"github.com/astaxie/beego"
-	"runtime"
+	"github.com/astaxie/beego/orm"
+
+	_ "github.com/go-sql-driver/mysql"
+	//"runtime"
+)
+
+const (
+	// Database
+	connectionString   = "benchmarkdbuser:benchmarkdbpass@tcp(localhost:3306)/hello_world"
+	worldRowCount      = 10000
+	macIdleConnection  = 30
+	maxConnectionCount = 256
+
+	helloWorldString = "Hello, World!"
+)
+
+var (
+	helloWorldBytes = []byte(helloWorldString)
 )
 
 type MessageStruct struct {
-	Message string
+	Message string `json:"message"`
+}
+
+type World struct {
+	Id           uint16 `orm:"pk" json:"id"`
+	RandomNumber uint16 `orm:"column(randomNumber)" json:"randomNumber"`
 }
 
 type JsonController struct {
@@ -14,13 +38,46 @@ type JsonController struct {
 }
 
 func (this *JsonController) Get() {
-	m := MessageStruct{"Hello, world"}
+	m := MessageStruct{"Hello, World!"}
 	this.Data["json"] = &m
 	this.ServeJson()
 }
 
+type PlaintextController struct {
+	beego.Controller
+}
+
+func (this *PlaintextController) Get() {
+	this.Ctx.Output.Header("Content-Type", "text/plain")
+	this.Ctx.Output.Body(helloWorldBytes)
+}
+
+type DBController struct {
+	beego.Controller
+}
+
+func (this *DBController) Get() {
+	o := orm.NewOrm()
+	w := World{Id: uint16(rand.Intn(worldRowCount) + 1)}
+	err := o.Read(&w)
+	if err != nil {
+		log.Fatalf("Error read world row: %s", err.Error())
+	}
+	this.Data["json"] = &w
+	this.ServeJson()
+}
+
 func main() {
-	runtime.GOMAXPROCS(runtime.NumCPU())
+	//don't need this set, beego default set it
+	//runtime.GOMAXPROCS(runtime.NumCPU())
+	beego.RunMode = "prod"
 	beego.Router("/json", &JsonController{})
+	beego.Router("/db", &DBController{})
+	beego.Router("/plaintext", &PlaintextController{})
 	beego.Run()
 }
+
+func init() {
+	orm.RegisterModel(new(World))
+	orm.RegisterDataBase("default", "mysql", connectionString, macIdleConnection, maxConnectionCount)
+}

+ 31 - 0
benchmark.cfg.example

@@ -0,0 +1,31 @@
+[Defaults]
+# Available Keys: 
+# client_host='localhost'
+# client_identity_file=None
+# client_user=None
+# database_host=None
+# database_identity_file=None
+# database_os='linux'
+# database_user=None
+# duration=60
+# exclude=None
+# install='all'
+# install_error_action='continue'
+# install_software=False
+# list_test_metadata=False
+# list_tests=False
+# max_concurrency=256
+# max_queries=20
+# max_threads=8
+# mode='benchmark'
+# name='ec2'
+# os='linux'
+# parse=None
+# password_prompt=False
+# query_interval=5
+# server_host='localhost'
+# sleep=60
+# starting_concurrency=8
+# test=None
+# type='all'
+# verbose=True

部分文件因文件數量過多而無法顯示