Browse Source

Merge remote-tracking branch 'upstream/master'

Donovan Muller 10 years ago
parent
commit
f2de5ea342
91 changed files with 974 additions and 1703 deletions
  1. 120 2
      README.md
  2. 3 3
      benchmark.cfg.example
  3. 8 2
      config/benchmark_profile
  4. 7 7
      frameworks/C++/ULib/README.md
  5. 1 1
      frameworks/C++/ULib/bash_profile.sh
  6. 28 6
      frameworks/C++/ULib/benchmark_config
  7. 19 10
      frameworks/C++/ULib/install.sh
  8. 19 31
      frameworks/C++/ULib/setup.py
  9. 3 3
      frameworks/C++/ULib/source_code
  10. 23 81
      frameworks/C++/ULib/src/db.usp
  11. 70 70
      frameworks/C++/ULib/src/fortune.h
  12. 68 0
      frameworks/C++/ULib/src/fortune.usp
  13. 0 153
      frameworks/C++/ULib/src/fortunes.usp
  14. 6 59
      frameworks/C++/ULib/src/json.usp
  15. 0 50
      frameworks/C++/ULib/src/plaintext.usp
  16. 0 160
      frameworks/C++/ULib/src/queries.usp
  17. 93 0
      frameworks/C++/ULib/src/query.usp
  18. 109 0
      frameworks/C++/ULib/src/update.usp
  19. 0 184
      frameworks/C++/ULib/src/updates.usp
  20. 58 58
      frameworks/C++/ULib/src/world.h
  21. 2 2
      frameworks/C++/treefrog/setup-thread.py
  22. 2 2
      frameworks/C++/treefrog/setup.py
  23. 1 1
      frameworks/C++/wt/install.sh
  24. 1 1
      frameworks/Erlang/cowboy/install.sh
  25. BIN
      frameworks/Erlang/cowboy/rebar
  26. 2 2
      frameworks/Erlang/cowboy/setup_erlang.py
  27. 1 1
      frameworks/Erlang/elli/install.sh
  28. BIN
      frameworks/Erlang/elli/rebar
  29. 1 1
      frameworks/Erlang/elli/rebar.config
  30. 3 2
      frameworks/Erlang/elli/setup_erlang.py
  31. 7 0
      frameworks/Go/beego/bash_profile.sh
  32. 0 1
      frameworks/Go/beego/setup.py
  33. 7 0
      frameworks/Go/gin/bash_profile.sh
  34. 1 1
      frameworks/Go/go/bash_profile.sh
  35. 0 1
      frameworks/Go/go/setup.py
  36. 7 0
      frameworks/Go/gorail/bash_profile.sh
  37. 3 0
      frameworks/Go/gorail/install.sh
  38. 0 1
      frameworks/Go/gorail/setup.py
  39. 7 0
      frameworks/Go/revel-qbs/bash_profile.sh
  40. 1 2
      frameworks/Go/revel-qbs/setup.py
  41. 7 0
      frameworks/Go/revel/bash_profile.sh
  42. 1 2
      frameworks/Go/revel/setup.py
  43. 7 0
      frameworks/Go/webgo/bash_profile.sh
  44. 0 1
      frameworks/Go/webgo/setup.py
  45. 30 8
      frameworks/Java/dropwizard-mongodb/src/main/java/com/example/helloworld/resources/WorldResource.java
  46. 14 4
      frameworks/Java/dropwizard/src/main/java/com/example/helloworld/resources/TextResource.java
  47. 31 4
      frameworks/Java/dropwizard/src/main/java/com/example/helloworld/resources/WorldResource.java
  48. 1 1
      frameworks/Java/grizzly-bm/setup.py
  49. 1 1
      frameworks/Java/grizzly-jersey/pom.xml
  50. 1 1
      frameworks/Java/play1siena/conf/dependencies.yml
  51. 1 1
      frameworks/Java/play1siena/install.sh
  52. 1 1
      frameworks/Java/play1siena/modules/siena-2.0.6
  53. 4 1
      frameworks/Java/servlet/src/main/java/hello/FortunesServlet.java
  54. 9 3
      frameworks/Java/spring/src/main/java/com/techempower/spring/web/WorldDatabaseController.java
  55. 3 2
      frameworks/Lua/leda/app.lua
  56. 4 7
      frameworks/Lua/leda/install.sh
  57. 1 0
      frameworks/Nimrod/jester/bash_profile.sh
  58. 3 2
      frameworks/Nimrod/jester/config/nginx.conf
  59. 9 7
      frameworks/Nimrod/jester/hello.nim
  60. 1 1
      frameworks/Nimrod/jester/install.sh
  61. 2 2
      frameworks/Nimrod/jester/setup.py
  62. 0 1
      frameworks/Nimrod/jester/source_code
  63. 14 3
      frameworks/Nimrod/nawak/app.nim
  64. 1 0
      frameworks/Nimrod/nawak/bash_profile.sh
  65. 1 7
      frameworks/Nimrod/nawak/conf/mongrel2.conf
  66. 1 1
      frameworks/Nimrod/nawak/fortunes_tmpl.nim
  67. 1 1
      frameworks/Nimrod/nawak/install.sh
  68. 0 271
      frameworks/Nimrod/nawak/lib/db_postgres_redone.nim
  69. 0 33
      frameworks/Nimrod/nawak/lib/escape.nim
  70. 0 352
      frameworks/Nimrod/nawak/lib/postgres_redone.nim
  71. 10 17
      frameworks/Nimrod/nawak/model_postgre.nim
  72. 0 1
      frameworks/Nimrod/nawak/model_redis.nim
  73. 8 3
      frameworks/Nimrod/nawak/setup.py
  74. 8 3
      frameworks/Nimrod/nawak/setup_redis.py
  75. 1 1
      frameworks/Scala/play-activate-mysql/setup.py
  76. 12 6
      toolset/benchmark/benchmarker.py
  77. 1 1
      toolset/benchmark/framework_test.py
  78. 6 6
      toolset/benchmark/test_types/db_type.py
  79. 8 8
      toolset/benchmark/test_types/query_type.py
  80. 1 1
      toolset/benchmark/utils.py
  81. 1 1
      toolset/run-ci.py
  82. 11 4
      toolset/run-tests.py
  83. 23 12
      toolset/setup/linux/database.sh
  84. 4 3
      toolset/setup/linux/frameworks/jester.sh
  85. 5 1
      toolset/setup/linux/frameworks/nawak.sh
  86. 1 1
      toolset/setup/linux/frameworks/siena.sh
  87. 5 5
      toolset/setup/linux/frameworks/wt.sh
  88. 20 12
      toolset/setup/linux/languages/nimrod.sh
  89. 1 1
      toolset/setup/linux/setup_util.py
  90. 12 0
      toolset/setup/linux/systools/rebar.sh
  91. 6 0
      toolset/setup/linux/webservers/apache.sh

+ 120 - 2
README.md

@@ -96,13 +96,118 @@ Note: environment variables can also be used for a number of the arguments.
 
 ## Installation Basics
 
+In order for SSH to work appropriately, the user on **each machine** will need to be 
+set up to have passwordless sudo access.
+
+**Setting up the `user`**
+
+```bash
+$ sudo vim /etc/sudoers
+```
+
+You will need to change the line that reads `%sudo   ALL=(ALL:ALL) ALL` to 
+`%sudo   ALL=(ALL:ALL) NOPASSWD: ALL`. You should be able to exit your shell, ssh 
+back in and perform `sudo ls` without being prompted for a password.
+
+**NOTE** Again, you will have to do this on every machine: server, database, client.
+
+**Setting up SSH**
+
+You will need to also be able to SSH onto each of the 3 machines from any of the
+3 machines and not be prompted for a password. We use an identity file and authorized_keys
+file to accomplish this.
+
+```bash
+$ ssh-keygen -t rsa
+```
+
+This will prompt you for various inputs; leave them all blank and just hit 'enter'.
+Next, you will want to allow connections identified via that key signature, so add
+it to your authorized keys.
+
+```bash
+$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
+$ chmod 600 ~/.ssh/authorized_keys
+```
+
+Next, you will need these exact same files to exist on the other 2 machines.
+If you properly set up your user account on all 3 machines, then this will not prompt
+you for a password (if it does, go back to "Setting up the `user`" and fix it).
+
+```bash
+# Set up the database machine for SSH
+$ cat ~/.ssh/id_rsa.pub | ssh [your user]@[database ip] 'cat >> .ssh/authorized_keys'
+$ scp ~/.ssh/id_rsa [your user]@[databse ip]:~/.ssh/id_rsa
+$ scp ~/.ssh/id_rsa.pub [your user]@[database ip]:~/.ssh/id_rsa.pub
+# Set up the client machine for SSH
+$ cat ~/.ssh/id_rsa.pub | ssh [your user]@[client ip] 'cat >> .ssh/authorized_keys'
+$ scp ~/.ssh/id_rsa [your user]@[client ip]:~/.ssh/id_rsa
+$ scp ~/.ssh/id_rsa.pub [your user]@[client ip]:~/.ssh/id_rsa.pub
+```
+
+Now, test it all out, you should be able to execute all of the following without
+being prompted for a password. **NOTE** The first time you SSH to these machines
+(read: in this step) you will be prompted to accept the signature - do it.
+
+```bash
+# Test your database SSH setup
+$ ssh [database ip]
+# Accept the signature
+# You are connected to the database machine!
+$ sudo ls
+# This should NOT prompt for a password and list the directory's contents
+# If this is not true, go back to "Setting up the `user`" and fix it
+$ exit
+# Test your client SSH setup
+$ ssh [client ip]
+# Accept the signature
+# You are connected to the client machine!
+$ sudo ls
+# We also need to test that we can SSH back to the server machine
+$ ssh [server ip]
+# Accept the signature
+# You are connected to the server machine!
+$ sudo ls
+# If this works, you are golden!
+$ exit
+# Back on client
+$ exit
+# Back on initial ssh connection to server machine
+```
+
+**Setting up prerequisites**
+
+The suite requires that a few libraries and applications are installed in order to run.
+First, clone our repository.
+
+```bash
+$ git clone https://github.com/TechEmpower/FrameworkBenchmarks.git
+$ sudo pip install -r FrameworkBenchmarks/config/python_requirements.txt
+```
+
 To install TFB components onto the various servers, you must provide
 basic login details for each server (e.g. usernames, IP addresses, 
 private key files). While these details can all be passed 
 using command line flags, it's easier to use a configuration 
 file and avoid having huge flag lists in your commands. 
-The examples in this section assume you have created a configuration 
-file containing login details for the various servers. 
+
+```bash
+$ cd FrameworkBenchmarks
+$ cp benchmark.cfg.example benchmark.cfg
+$ vim benchmark.cfg
+```
+
+You will need to change, at a minimum, the following:
+
+* `client_host` Set this to the IP address of your client machine
+* `client_identity_file` Set to `/home/[username]/.ssh/id_rsa`
+* `client_user` Set to your username
+* `database_host` Set this to the IP address of your database machine
+* `database_identity_file` Set to `/home/[username]/.ssh/id_rsa`
+* `database_user` Set to your username
+* `server_host` Set this to the IP address of your server machine
+
+At this point, you should be ready to install the suite.
 
 We use the `--install-only` flag in our examples to 
 prevent launching tests at this stage. All of these commands 
@@ -124,6 +229,19 @@ $ toolset/run-tests.py --install database --install-only
 
 **Setting up the `app server`**
 
+At this point, you should be able to run a benchmark of the entire
+suite or selectively run individual benchmarks. Additionally, you
+can test your setup by running a verification on one of the stable
+frameworks. Since we wrote it, we tend to test with `gemini`:
+
+```bash
+$ toolset/run-tests.py --mode verify --test gemini
+```
+
+You can find the results for this verification step under the directory:
+`results/ec2/latest/logs/gemini`. There should be an `err` and an `out`
+file.
+
 You can choose to selectively install components by using the 
 `--test` and `--exclude` flags. 
 

+ 3 - 3
benchmark.cfg.example

@@ -12,9 +12,9 @@ exclude=None
 install=server
 install_error_action=continue
 install_strategy=unified
-#install_only=True
-#list_test_metadata=True
-#list_tests=True
+install_only=False
+list_test_metadata=False
+list_tests=False
 concurrency_levels=[8, 16, 32, 64, 128, 256]
 query_levels=[1, 5,10,15,20]
 threads=8

+ 8 - 2
config/benchmark_profile

@@ -10,12 +10,18 @@ else
 fi
 IROOT=${FWROOT}/installs
 
+# Determine which OS we are using and set the appropriate variables
+source /etc/lsb-release
+export TFB_DISTRIB_ID=$DISTRIB_ID
+export TFB_DISTRIB_RELEASE=$DISTRIB_RELEASE
+export TFB_DISTRIB_CODENAME=$DISTRIB_CODENAME
+export TFB_DISTRIB_DESCRIPTION=$DISTRIB_DESCRIPTION
+
+
 export JAVA_HOME=/usr/lib/jvm/java-1.7.0-openjdk-amd64
 export RESIN_HOME=${IROOT}/resin-4.0.41
 export GRAILS_HOME=${IROOT}/grails-2.4.2
 export VERTX_HOME=${IROOT}/vert.x-2.1.1
-export GOROOT=${IROOT}/go
-export GOPATH=${FWROOT}/go:${FWROOT}/webgo:${FWROOT}/revel
 export TOMCAT_HOME=${IROOT}/apache-tomcat-7.0.35
 export NODE_HOME=${IROOT}/node-v0.10.8-linux-x64
 export PLAY_HOME=${IROOT}/play-2.2.0

+ 7 - 7
frameworks/C++/ULib/README.md

@@ -12,15 +12,15 @@ This is the ULib portion of a [benchmarking test suite](https://github.com/TechE
 
 ### Variable Query Test
 
-* [Variable Query test source](src/queries.usp)
+* [Variable Query test source](src/query.usp)
 
 ### Fortune Query Test
 
-* [Fortune Query test source](src/fortunes.usp)
+* [Fortune Query test source](src/fortune.usp)
 
 ### Variable Query (update) Test
 
-* [Variable Query (update) test source](src/updates.usp)
+* [Variable Query (update) test source](src/update.usp)
 
 ### Plaintext Test
 
@@ -29,7 +29,7 @@ This is the ULib portion of a [benchmarking test suite](https://github.com/TechE
 ## Infrastructure Software Versions
 The tests were run with:
 
-* [ULib Version 1.4.1](https://github.com/stefanocasazza/ULib/archive/v1.4.1.tar.gz)
+* [ULib Version 1.4.2](https://github.com/stefanocasazza/ULib/archive/v1.4.2.tar.gz)
 
 Output
 ======
@@ -58,7 +58,7 @@ Content-Type: application/json; charset=UTF-8
 {"id":6227,"randomNumber":8489}
 ```
 
-[/queries?queries=10](http://www.techempower.com/benchmarks/#section=query)
+[/query?queries=10](http://www.techempower.com/benchmarks/#section=query)
 -------------------
 ```
 HTTP/1.1 200 OK
@@ -70,7 +70,7 @@ Content-Type: application/json; charset=UTF-8
 [{"id":6851,"randomNumber":7598},{"id":3968,"randomNumber":7325},{"id":8159,"randomNumber":348},{"id":9560,"randomNumber":7333},{"id":9938,"randomNumber":9080},{"id":1598,"randomNumber":1623},{"id":3280,"randomNumber":8707},{"id":4521,"randomNumber":6063},{"id":8173,"randomNumber":3690},{"id":3648,"randomNumber":8803}]
 ```
 
-[/fortunes](http://www.techempower.com/benchmarks/#section=fortune)
+[/fortune](http://www.techempower.com/benchmarks/#section=fortune)
 ---------
 ```
 HTTP/1.1 200 OK
@@ -82,7 +82,7 @@ Content-Length: 1227
 <!doctype html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr><tr><td>11</td><td>&lt;script&gt;alert(&quot;This should not be displayed in a browser alert box.&quot;);&lt;/script&gt;</td></tr><tr><td>4</td><td>A bad random number generator: 1, 1, 1, 1, 1, 4.33e+67, 1, 1, 1</td></tr><tr><td>5</td><td>A computer program does what you tell it to do, not what you want it to do.</td></tr><tr><td>2</td><td>A computer scientist is someone who fixes things that aren&apos;t broken.</td></tr><tr><td>8</td><td>A list is only as strong as its weakest link. — Donald Knuth</td></tr><tr><td>0</td><td>Additional fortune added at request time.</td></tr><tr><td>3</td><td>After enough decimal places, nobody gives a damn.</td></tr><tr><td>7</td><td>Any program that runs right is obsolete.</td></tr><tr><td>10</td><td>Computers make very fast, very accurate mistakes.</td></tr><tr><td>6</td><td>Emacs is a nice operating system, but I prefer UNIX. — Tom Christaensen</td></tr><tr><td>9</td><td>Feature: A bug with seniority.</td></tr><tr><td>1</td><td>fortune: No such file or directory</td></tr><tr><td>12</td><td>フレームワークのベンチマーク</td></tr></table></body></html>
 ```
 
-[/updates?queries=10](http://www.techempower.com/benchmarks/#section=update)
+[/update?queries=10](http://www.techempower.com/benchmarks/#section=update)
 -------------------
 ```
 HTTP/1.1 200 OK

+ 1 - 1
frameworks/C++/ULib/bash_profile.sh

@@ -11,6 +11,6 @@
 #    . $FWROOT/toolset/setup/linux/bash_functions.sh && 
 #    . $FWROOT/ULib/install.sh (cwd=$FWROOT//installs)
 #---------------------------------------------------------------------------------------------------------
-export ULIB_VERSION=1.4.1
+export ULIB_VERSION=1.4.2
 export ULIB_ROOT=$IROOT/ULib
 export ULIB_DOCUMENT_ROOT=${ULIB_ROOT}/ULIB_DOCUMENT_ROOT

+ 28 - 6
frameworks/C++/ULib/benchmark_config

@@ -1,23 +1,45 @@
 {
   "framework": "ULib",
   "tests": [{
-    "default": {
+    "sqlite": {
       "setup_file": "setup",
       "json_url": "/json",
       "db_url": "/db",
-      "query_url": "/queries?queries=",
-      "fortune_url": "/fortunes",
-      "update_url": "/updates?queries=",
+      "query_url": "/query?queries=",
+      "fortune_url": "/fortune",
       "plaintext_url": "/plaintext",
       "port": 8080,
       "approach": "Realistic",
-      "classification": "Fullstack",
+      "classification": "Platform",
+      "database": "SQLite",
+      "framework": "ULib",
+      "language": "C++",
+      "orm": "Micro",
+      "platform": "ULib",
+      "webserver": "userver_tcp",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "ULib",
+      "notes": "",
+      "versus": ""
+    },
+    "mysql": {
+      "setup_file": "setup",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/query?queries=",
+      "fortune_url": "/fortune",
+      "plaintext_url": "/plaintext",
+      "update_url": "/update?queries=",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Platform",
       "database": "MySQL",
       "framework": "ULib",
       "language": "C++",
       "orm": "Micro",
       "platform": "ULib",
-      "webserver": "None",
+      "webserver": "userver_tcp",
       "os": "Linux",
       "database_os": "Linux",
       "display_name": "ULib",

+ 19 - 10
frameworks/C++/ULib/install.sh

@@ -2,7 +2,8 @@
 
 # install.sh
 # --------------------------------------------------------------------------------------------------------
-# toolset/run-tests.py --install server --test ULib --type all --verbose
+# toolset/run-tests.py --install server --test ULib-mysql  --type all --verbose
+# toolset/run-tests.py --install server --test ULib-sqlite --type all --verbose
 # --------------------------------------------------------------------------------------------------------
 # TROOT - Path of this test's directory
 # IROOT - Path of this test's install directory ($FWROOT/installs or $FWROOT/installs/pertest/<test-name>)
@@ -15,11 +16,18 @@
 #    . $FWROOT/ULib/install.sh (cwd=$FWROOT//installs)
 # --------------------------------------------------------------------------------------------------------
 
-# Chekc if ULib is already installed
-RETCODE=$(fw_exists ulib-${ULIB_VERSION}.installed)
+# Check if ULib is already installed
+ULIB_INSTALLED_FILE="${IROOT}/ULib-${ULIB_VERSION}.installed"
+RETCODE=$(fw_exists ${ULIB_INSTALLED_FILE})
 [ ! "$RETCODE" == 0 ] || { return 0; }
 
+# ULib is only built during installation as a dependency sanity check
+#sudo apt-get update
+ sudo apt-get install libmysqlclient-dev libsqlite3-dev
+
 # Create a run directory for ULIB
+[ ! -e ${ULIB_INSTALLED_FILE} -a -d ${IROOT}/ULib ] && rm -rf ${IROOT}/ULib*
+
 if [ ! -d "$ULIB_ROOT" ]; then
   mkdir -p $ULIB_ROOT
 fi
@@ -42,7 +50,7 @@ fi
 # 1. Download ULib
 cd $IROOT
 fw_get -O ULib-${ULIB_VERSION}.tar.gz https://github.com/stefanocasazza/ULib/archive/v${ULIB_VERSION}.tar.gz 
-fw_untar ULib-${ULIB_VERSION}.tar.gz
+fw_untar  ULib-${ULIB_VERSION}.tar.gz
 
 # 2. Compile application (userver_tcp)
 
@@ -51,19 +59,18 @@ cd ULib-$ULIB_VERSION
 # AVOID "configure: error: newly created file is older than distributed files! Check your system clock"
 find . -exec touch {} \;
 
-LIBS="-lssl -lcrypto -lz" \
 ./configure --prefix=$ULIB_ROOT \
             --disable-static \
-            --with-mysql \
+            --with-mysql --with-sqlite3 \
             --without-ssl --without-pcre --without-expat \
             --without-libz --without-libuuid --without-magic \
-            --enable-static-orm-driver=mysql --enable-static-server-plugin=http
+            --enable-static-orm-driver='mysql sqlite' --enable-static-server-plugin=http
 #           --enable-debug \
 make install
 
 # 3. Compile usp pages for benchmark
 cd src/ulib/net/server/plugin/usp
-make db.la fortunes.la json.la plaintext.la queries.la updates.la
+make db.la fortune.la json.la plaintext.la query.la update.la
 
 # Check that compilation worked
 if [ ! -e .libs/db.so ]; then
@@ -71,7 +78,9 @@ if [ ! -e .libs/db.so ]; then
 fi
 
 mkdir -p $ULIB_DOCUMENT_ROOT
-cp .libs/db.so .libs/fortunes.so .libs/json.so .libs/plaintext.so .libs/queries.so .libs/updates.so $ULIB_DOCUMENT_ROOT
+cp .libs/db.so .libs/fortune.so .libs/json.so .libs/plaintext.so .libs/query.so .libs/update.so $ULIB_DOCUMENT_ROOT
 
 cd $IROOT
-touch ulib-${ULIB_VERSION}.installed 
+cp -r ULib-1.4.2/tests/examples/benchmark/FrameworkBenchmarks/ULib/db $ULIB_ROOT
+
+touch ${ULIB_INSTALLED_FILE}

+ 19 - 31
frameworks/C++/ULib/setup.py

@@ -5,50 +5,38 @@ import setup_util
 import subprocess
 import multiprocessing
 
-def start(args, logfile, errfile):
-
-  fwroot = args.fwroot
+def get_env_for_database(args):
+  if args.database == 'MySQL':
+     driver = 'mysql'
+     dbname = 'hello_world'
+  else:
+     driver = 'sqlite'
+     dbname = os.environ['ULIB_ROOT'] + '/db/%.*s'
+  return {
+      'UMEMPOOL': '135,0,0,34,8465,129,-17,-22,41',
+      'ORM_DRIVER': driver,
+      'ORM_OPTION': "host=" + args.database_host + " user=benchmarkdbuser password=benchmarkdbpass character-set=utf8 dbname=" + dbname
+    }
 
+def start(args, logfile, errfile):
   try:
-    ulib_root = subprocess.check_output('printf $ULIB_ROOT', shell=True, stderr=errfile)
-
+    ulib_root = os.environ['ULIB_ROOT']
     fcfg = ulib_root + "/benchmark.cfg"
-
-    # 1. Change ULib Server configuration
-
-    # I don't understand if the two approach are different...
-    #threads = str(args.max_threads)
-    PROCS = str(multiprocessing.cpu_count())
-    setup_util.replace_text(fcfg, "PREFORK_CHILD .*", "PREFORK_CHILD " + PROCS)
-
     fprg = ulib_root + "/bin/userver_tcp"
-
+    # 1. Change ULib Server configuration
+    setup_util.replace_text(fcfg, "PREFORK_CHILD .*", "PREFORK_CHILD " + str(multiprocessing.cpu_count()))
     # 2. Start ULib Server (userver_tcp)
-    logfile.write("ULib: trying to start server %s -c %s\n" % (fprg, fcfg))
-
-    # sudo mysqlcheck -v -r -A -u benchmarkdbuser -p
-    os.putenv("ORM_DRIVER","mysql")
-    os.putenv("ORM_OPTION","host=" + args.database_host + " user=benchmarkdbuser password=benchmarkdbpass dbname=hello_world")
-    os.putenv("UMEMPOOL", "1583,1507,-19,45,16458,523,-27,-14,27")
-
-    # Run in the background, but keep stdout/stderr for easy debugging
-    subprocess.Popen( "%s -c %s" % (fprg, fcfg), shell=True, stdout=logfile, stderr=errfile)
-    # subprocess.Popen("UTRACE=\"0 50M\" " + fprg + " -c " + fcfg, shell=True, stdout=logfile, stderr=errfile)
-
-    logfile.write("ULib: server STARTED\n")
+    subprocess.Popen( "%s -c %s" % (fprg, fcfg), shell=True, stdout=logfile, stderr=errfile, env = get_env_for_database(args))
     return 0
   except subprocess.CalledProcessError:
     return 1
 
 def stop(logfile, errfile):
   try:
-    logfile.write( "ULib: setup.py STOP\n")
-
-
     # Stop ULib Server (userver_tcp)
     subprocess.check_call("kill -TERM $( cat $ULIB_ROOT/userver_tcp.pid )", shell=True, stderr=errfile, stdout=logfile)
-    time.sleep(2);
-    p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
+    time.sleep(3);
+    p = subprocess.Popen(['pgrep', 'userver_tcp'], stdout=subprocess.PIPE)
     out, err = p.communicate()
     for line in out.splitlines():
        if 'userver_tcp' in line:

+ 3 - 3
frameworks/C++/ULib/source_code

@@ -2,7 +2,7 @@
 ./src/world.h
 ./src/json.usp
 ./src/fortune.h
-./src/queries.usp
-./src/updates.usp
-./src/fortunes.usp
+./src/query.usp
+./src/update.usp
+./src/fortune.usp
 ./src/plaintext.usp

+ 23 - 81
frameworks/C++/ULib/src/db.usp

@@ -1,106 +1,48 @@
-<!--#
-Test 2: Single database query
-
-This test exercises the framework's object-relational mapper (ORM), random number generator, database driver, and database connection pool.
-
-Requirements
-
-1.  For every request, a single row from a World table must be retrieved from a database table. 
-
-2.  The recommended URI is /db.
-
-3.  The schema for World is id (int, primary key) and randomNumber (int).
-
-4.  The World table is known to contain 10,000 rows.
-
-5.  The row retrieved must be selected by its id using a random number generator (ids range from 1 to 10,000).
-
-6.  The row should be converted to an object using an object-relational mapping (ORM) tool.
-    Tests that do not use an ORM will be identified with the suffix "raw," meaning they use the platform's raw database connectivity.
-
-7.  The object (or database row, if an ORM is not used) must be serialized to JSON.
-
-8.  The response content length should be approximately 32 bytes.
-
-9.  The response content type must be set to application/json.
-
-10. The response headers must include either Content-Length or Transfer-Encoding.
-
-11. The response headers must include Server and Date.
-
-12. Use of an in-memory cache of World objects or rows by the application is not permitted.
-
-13. Use of prepared statements for SQL database tests (e.g., for MySQL) is encouraged but not required.
-
-14. gzip compression is not permitted.
-
-15. Server support for HTTP Keep-Alive is strongly encouraged but not required.
-
-16. If HTTP Keep-Alive is enabled, no maximum Keep-Alive timeout is specified by this test.
-
-17. The request handler will be exercised at concurrency levels ranging from 8 to 256.
-
-18. The request handler will be exercised using GET requests.
-
-Example request:
-
-GET /db HTTP/1.1
-Host: server
-User-Agent: Mozilla/5.0 (X11; Linux x86_64) Gecko/20130501 Firefox/30.0 AppleWebKit/600.00 Chrome/30.0.0000.0 Trident/10.0 Safari/600.00
-Cookie: uid=12345678901234567890; __utma=1.1234567890.1234567890.1234567890.1234567890.12; wd=2560x1600
-Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
-Accept-Language: en-US,en;q=0.5
-Connection: keep-alive
-
-Example response:
-
-HTTP/1.1 200 OK
-Content-Type: application/json; charset=UTF-8
-Content-Length: 32
-Server: Example
-Date: Wed, 17 Apr 2013 12:00:00 GMT
-{"id":3217,"randomNumber":2149}
--->
 <!--#declaration
 #include "world.h"
 
 #define AS_cpoll_cppsp_DO
 
 #ifndef AS_cpoll_cppsp_DO
-static UValue*	pvalue;
+static UValue* pvalue;
 #endif
-static World*			 pworld_db;
-static UOrmSession*	 psql_db;
+static World*         pworld_db;
+static UOrmSession*   psql_db;
 static UOrmStatement* pstmt_db;
 
 static void usp_init_db()
 {
-	U_TRACE(5, "::usp_init_db()")
+   U_TRACE(5, "::usp_init_db()")
+
+   pworld_db = U_NEW(World);
 
-	psql_db	= U_NEW(UOrmSession(U_CONSTANT_TO_PARAM("hello_world")));
-	pstmt_db	= U_NEW(UOrmStatement(*psql_db, U_CONSTANT_TO_PARAM("SELECT randomNumber FROM World WHERE id = ?")));
+#ifndef AS_cpoll_cppsp_DO
+   pvalue = U_NEW(UValue(OBJECT_VALUE));
+#endif
+}
 
-	if (pstmt_db == 0) U_ERROR("usp_init_db(): we cound't connect to db, exiting...");
+static void usp_fork_db()
+{
+   U_TRACE(5, "::usp_fork_db()")
 
-	pworld_db = U_NEW(World);
+   psql_db  = U_NEW(UOrmSession(U_CONSTANT_TO_PARAM("hello_world")));
+   pstmt_db = U_NEW(UOrmStatement(*psql_db, U_CONSTANT_TO_PARAM("SELECT randomNumber FROM World WHERE id = ?")));
 
-	pstmt_db->use( pworld_db->id);
-	pstmt_db->into(pworld_db->randomNumber);
+   if (pstmt_db == 0) U_ERROR("usp_fork_db(): we cound't connect to db, exiting...");
 
-#ifndef AS_cpoll_cppsp_DO
-	pvalue = U_NEW(UValue(OBJECT_VALUE));
-#endif
+   pstmt_db->use( pworld_db->id);
+   pstmt_db->into(pworld_db->randomNumber);
 }
 
 static void usp_end_db()
 {
-	U_TRACE(5, "::usp_end_db()")
+   U_TRACE(5, "::usp_end_db()")
 
-	delete pstmt_db;
-	delete psql_db;
-	delete pworld_db;
+   delete pstmt_db;
+   delete psql_db;
+   delete pworld_db;
 #ifndef AS_cpoll_cppsp_DO
-	delete pvalue;
+   delete pvalue;
 #endif
 }
 -->

+ 70 - 70
frameworks/C++/ULib/src/fortune.h

@@ -8,116 +8,116 @@
 
 class Fortune {
 public:
-	// Check for memory error
-	U_MEMORY_TEST
+   // Check for memory error
+   U_MEMORY_TEST
 
-	// Allocator e Deallocator
-	U_MEMORY_ALLOCATOR
-	U_MEMORY_DEALLOCATOR
+   // Allocator e Deallocator
+   U_MEMORY_ALLOCATOR
+   U_MEMORY_DEALLOCATOR
 
-	int id;
-	UString message;
+   int id;
+   UString message;
 
-	// CONSTRUCTOR
+   // CONSTRUCTOR
 
-	Fortune()
-		{
-		U_TRACE_REGISTER_OBJECT(5, Fortune, "")
-		}
+   Fortune()
+      {
+      U_TRACE_REGISTER_OBJECT(5, Fortune, "")
+      }
 
-	Fortune(int _id, const UString& _message) : id(_id), message(_message)
-		{
-		U_TRACE_REGISTER_OBJECT(5, Fortune, "%d,%.*S", _id, U_STRING_TO_TRACE(_message))
-		}
+   Fortune(int _id, const UString& _message) : id(_id), message(_message)
+      {
+      U_TRACE_REGISTER_OBJECT(5, Fortune, "%d,%.*S", _id, U_STRING_TO_TRACE(_message))
+      }
 
-	Fortune(const Fortune& f) : id(f.id), message((void*)U_STRING_TO_PARAM(f.message))
-		{
-		U_TRACE_REGISTER_OBJECT(5, Fortune, "%p", &f)
+   Fortune(const Fortune& f) : id(f.id), message((void*)U_STRING_TO_PARAM(f.message))
+      {
+      U_TRACE_REGISTER_OBJECT(5, Fortune, "%p", &f)
 
-		U_MEMORY_TEST_COPY(f)
-		}
+      U_MEMORY_TEST_COPY(f)
+      }
 
-	~Fortune()
-		{
-		U_TRACE_UNREGISTER_OBJECT(5, Fortune)
-		}
+   ~Fortune()
+      {
+      U_TRACE_UNREGISTER_OBJECT(5, Fortune)
+      }
 
-	// SERVICE
+   // SERVICE
 
-	bool operator<(const Fortune& other) const { return cmp_obj(&message, &other.message); }
+   bool operator<(const Fortune& other) const { return cmp_obj(&message, &other.message); }
 
-	static int cmp_obj(const void* a, const void* b)
-		{
-		U_TRACE(5, "Fortune::cmp_obj(%p,%p)", a, b)
+   static int cmp_obj(const void* a, const void* b)
+      {
+      U_TRACE(5, "Fortune::cmp_obj(%p,%p)", a, b)
 
-		return (*(const Fortune**)a)->message.compare((*(const Fortune**)b)->message);
-		}
+      return (*(const Fortune**)a)->message.compare((*(const Fortune**)b)->message);
+      }
 
 #ifdef DEBUG
-	const char* dump(bool breset) const
-		{
-		*UObjectIO::os << "id               " << id				   << '\n'
-							<< "message (UString " << (void*)&message << ')';
+   const char* dump(bool breset) const
+      {
+      *UObjectIO::os << "id               " << id              << '\n'
+                     << "message (UString " << (void*)&message << ')';
 
-		if (breset)
-			{
-			UObjectIO::output();
+      if (breset)
+         {
+         UObjectIO::output();
 
-			return UObjectIO::buffer_output;
-			}
+         return UObjectIO::buffer_output;
+         }
 
-		return 0;
-		}
+      return 0;
+      }
 #endif
 
 private:
-	Fortune& operator=(const Fortune&) { return *this; }
+   Fortune& operator=(const Fortune&) { return *this; }
 };
 
 // ORM TEMPLATE SPECIALIZATIONS
 
 template <> class U_EXPORT UOrmTypeHandler<Fortune> : public UOrmTypeHandler_Base {
 public:
-	explicit UOrmTypeHandler(Fortune& val) : UOrmTypeHandler_Base(&val) {}
+   explicit UOrmTypeHandler(Fortune& val) : UOrmTypeHandler_Base(&val) {}
 
-	void bindParam(UOrmStatement* stmt) const
-		{
-		U_TRACE(0, "UOrmTypeHandler<Fortune>::bindParam(%p)", stmt)
+   void bindParam(UOrmStatement* stmt) const
+      {
+      U_TRACE(0, "UOrmTypeHandler<Fortune>::bindParam(%p)", stmt)
 
-		stmt->bindParam(U_ORM_TYPE_HANDLER(Fortune, id,		  int));
-		stmt->bindParam(U_ORM_TYPE_HANDLER(Fortune, message, UString));
-		}
+      stmt->bindParam(U_ORM_TYPE_HANDLER(Fortune, id,      int));
+      stmt->bindParam(U_ORM_TYPE_HANDLER(Fortune, message, UString));
+      }
 
-	void bindResult(UOrmStatement* stmt)
-		{
-		U_TRACE(0, "UOrmTypeHandler<Fortune>::bindResult(%p)", stmt)
+   void bindResult(UOrmStatement* stmt)
+      {
+      U_TRACE(0, "UOrmTypeHandler<Fortune>::bindResult(%p)", stmt)
 
-		stmt->bindResult(U_ORM_TYPE_HANDLER(Fortune, id,		int));
-		stmt->bindResult(U_ORM_TYPE_HANDLER(Fortune, message, UString));
-		}
+      stmt->bindResult(U_ORM_TYPE_HANDLER(Fortune, id,      int));
+      stmt->bindResult(U_ORM_TYPE_HANDLER(Fortune, message, UString));
+      }
 };
 
 // JSON TEMPLATE SPECIALIZATIONS
 
 template <> class U_EXPORT UJsonTypeHandler<Fortune> : public UJsonTypeHandler_Base {
 public:
-	explicit UJsonTypeHandler(Fortune& val) : UJsonTypeHandler_Base(&val) {}
+   explicit UJsonTypeHandler(Fortune& val) : UJsonTypeHandler_Base(&val) {}
 
-	void toJSON(UValue& json)
-		{
-		U_TRACE(0, "UJsonTypeHandler<Fortune>::toJSON(%p)", &json)
+   void toJSON(UValue& json)
+      {
+      U_TRACE(0, "UJsonTypeHandler<Fortune>::toJSON(%p)", &json)
 
-		json.toJSON(U_JSON_TYPE_HANDLER(Fortune, id,		  int));
-		json.toJSON(U_JSON_TYPE_HANDLER(Fortune, message, UString));
-		}
+      json.toJSON(U_JSON_TYPE_HANDLER(Fortune, id,      int));
+      json.toJSON(U_JSON_TYPE_HANDLER(Fortune, message, UString));
+      }
 
-	void fromJSON(UValue& json)
-		{
-		U_TRACE(0, "UJsonTypeHandler<Fortune>::fromJSON(%p)", &json)
+   void fromJSON(UValue& json)
+      {
+      U_TRACE(0, "UJsonTypeHandler<Fortune>::fromJSON(%p)", &json)
 
-		json.fromJSON(U_JSON_TYPE_HANDLER(Fortune, id,		 int));
-		json.fromJSON(U_JSON_TYPE_HANDLER(Fortune, message, UString));
-		}
+      json.fromJSON(U_JSON_TYPE_HANDLER(Fortune, id,      int));
+      json.fromJSON(U_JSON_TYPE_HANDLER(Fortune, message, UString));
+      }
 };
 
 #endif

+ 68 - 0
frameworks/C++/ULib/src/fortune.usp

@@ -0,0 +1,68 @@
+<!--#declaration
+#include "fortune.h"
+
+static UOrmSession*       psql_fortune;
+static UOrmStatement*     pstmt_fortune;
+static Fortune*           pfortune;
+static UString*           pmessage;
+static UVector<Fortune*>* pvfortune;
+
+static void usp_init_fortune()
+{
+   U_TRACE(5, "::usp_init_fortune()")
+
+   pfortune  = U_NEW(Fortune);
+   pvfortune = U_NEW(UVector<Fortune*>);
+   pmessage  = U_NEW(U_STRING_FROM_CONSTANT("Additional fortune added at request time."));
+}
+
+static void usp_fork_fortune()
+{
+   U_TRACE(5, "::usp_fork_fortune()")
+
+   psql_fortune  = U_NEW(UOrmSession(U_CONSTANT_TO_PARAM("fortune")));
+   pstmt_fortune = U_NEW(UOrmStatement(*psql_fortune, U_CONSTANT_TO_PARAM("SELECT id, message FROM Fortune")));
+
+   if (pstmt_fortune == 0) U_ERROR("usp_fork_fortune(): we cound't connect to db, exiting...");
+
+   pstmt_fortune->into(*pfortune);
+}
+
+static void usp_end_fortune()
+{
+   U_TRACE(5, "::usp_end_fortune()")
+
+   delete pstmt_fortune;
+   delete psql_fortune;
+   delete pvfortune;
+   delete pfortune;
+   delete pmessage;
+}
+-->
+<!doctype html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr><!--#code
+Fortune* elem;
+unsigned char encoded[1024];
+
+pstmt_fortune->execute();
+
+     pvfortune->push_back(U_NEW(Fortune(0, *pmessage)));
+do { pvfortune->push_back(U_NEW(Fortune(*pfortune))); } while (pstmt_fortune->nextRow());
+
+pvfortune->sort(Fortune::cmp_obj);
+
+for (uint32_t i = 0, n = pvfortune->size(); i < n; ++i)
+   {
+   elem = (*pvfortune)[i];
+
+   (void) u_xml_encode((const unsigned char*)U_STRING_TO_PARAM(elem->message), encoded);
+
+   USP_PRINTF_ADD(
+      "<tr>"
+      "<td>%d</td>"
+      "<td>%s</td>"
+      "</tr>",
+      elem->id, encoded);
+   }
+
+pvfortune->clear();
+--></table></body></html>

+ 0 - 153
frameworks/C++/ULib/src/fortunes.usp

@@ -1,153 +0,0 @@
-<!--#
-Test 4: Fortunes
-
-This test exercises the ORM, database connectivity, dynamic-size collections,
-sorting, server-side templates, XSS countermeasures, and character encoding.
-
-Requirements
-
-1.  The recommended URI is /fortunes.
-
-2.  A Fortune database table contains a dozen Unix-style fortune-cookie messages.
-
-3.  The schema for Fortune is id (int, primary key) and message (varchar).
-
-4.  Using an ORM, all Fortune objects must be fetched from the Fortune table, and placed into a list data structure.
-    Tests that do not use an ORM will be classified as "raw" meaning they use the platform's raw database connectivity.
-
-5.  The list data structure must be a dynamic-size or equivalent and should not be dimensioned using foreknowledge of
-    the row-count of the database table.
-
-6.  Within the scope of the request, a new Fortune object must be constructed and added to the list. This confirms that
-    the data structure is dynamic-sized. The new fortune is not persisted to the database; it is ephemeral for the scope of the request.
-
-7.  The new Fortune's message must be "Additional fortune added at request time."
-
-8.  The list of Fortune objects must be sorted by the order of the message field. No ORDER BY clause is permitted in the
-    database query (ordering within the query would be of negligible value anyway since a newly instantiated Fortune is
-	 added to the list prior to sorting).
-
-9.  The sorted list must be provided to a server-side template and rendered to simple HTML (see below for minimum template).
-    The resulting HTML table displays each Fortune's id number and message text.
-
-10. This test does not include external assets (CSS, JavaScript); a later test type will include assets.
-
-11. The HTML generated by the template must be sent as a response.
-
-12. Be aware that the message text fields are stored as UTF-8 and one of the fortune cookie messages is in Japanese.
-
-13. The resulting HTML must be delivered using UTF-8 encoding.
-
-14. The Japanese fortune cookie message must be displayed correctly.
-
-15. Be aware that at least one of the message text fields includes a <script> tag.
-
-16. The server-side template must assume the message text cannot be trusted and must escape the message text properly.
-
-17. The implementation is encouraged to use best practices for templates such as layout inheritence, separate header and
-    footer files, and so on. However, this is not required. We request that implementations do not manage assets (JavaScript,
-	 CSS, images). We are deferring asset management until we can craft a more suitable test.
-
-18. The response content type must be set to text/html.
-
-19. The response headers must include either Content-Length or Transfer-Encoding.
-
-20. The response headers must include Server and Date.
-
-21. Use of an in-memory cache of Fortune objects or rows by the application is not permitted.
-
-22. Use of prepared statements for SQL database tests (e.g., for MySQL) is encouraged but not required.
-
-23. gzip compression is not permitted.
-
-24. Server support for HTTP Keep-Alive is strongly encouraged but not required.
-
-25. If HTTP Keep-Alive is enabled, no maximum Keep-Alive timeout is specified by this test.
-
-26. The request handler will be exercised at concurrency levels ranging from 8 to 256.
-
-27. The request handler will be exercised using GET requests.
-
-Example request:
-
-GET /fortunes HTTP/1.1
-Host: server
-User-Agent: Mozilla/5.0 (X11; Linux x86_64) Gecko/20130501 Firefox/30.0 AppleWebKit/600.00 Chrome/30.0.0000.0 Trident/10.0 Safari/600.00
-Cookie: uid=12345678901234567890; __utma=1.1234567890.1234567890.1234567890.1234567890.12; wd=2560x1600
-Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
-Accept-Language: en-US,en;q=0.5
-Connection: keep-alive
-
-Example response:
-
-HTTP/1.1 200 OK
-Content-Length: 1190
-Content-Type: text/html; charset=UTF-8
-Server: Example
-Date: Wed, 17 Apr 2013 12:00:00 GMT
-
-<!doctype html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr><tr><td>11</td><td>&lt;script&gt;alert(&quot;This should not be displayed in a browser alert box.&quot;);&lt;/script&gt;</td></tr><tr><td>4</td><td>A bad random number generator: 1, 1, 1, 1, 1, 4.33e+67, 1, 1, 1</td></tr><tr><td>5</td><td>A computer program does what you tell it to do, not what you want it to do.</td></tr><tr><td>2</td><td>A computer scientist is someone who fixes things that aren't broken.</td></tr><tr><td>8</td><td>A list is only as strong as its weakest link. â Donald Knuth</td></tr><tr><td>0</td><td>Additional fortune added at request time.</td></tr><tr><td>3</td><td>After enough decimal places, nobody gives a damn.</td></tr><tr><td>7</td><td>Any program that runs right is obsolete.</td></tr><tr><td>10</td><td>Computers make very fast, very accurate mistakes.</td></tr><tr><td>6</td><td>Emacs is a nice operating system, but I prefer UNIX. â Tom Christaensen</td></tr><tr><td>9</td><td>Feature: A bug with seniority.</td></tr><tr><td>1</td><td>fortune: No such file or directory</td></tr><tr><td>12</td><td>ã¬ã¼ãã¯ã¼ã¯ã®ãã³ããã¼ã¯</td></tr></table></body></html>
--->
-<!--#declaration
-#include "fortune.h"
-
-static UOrmSession*		  psql_fortune;
-static UOrmStatement*	  pstmt_fortune;
-static Fortune*			  pfortune;
-static UString*           pmessage;
-static UVector<Fortune*>* pvfortune;
-
-static void usp_init_fortunes()
-{
-	U_TRACE(5, "::usp_init_fortunes()")
-
-	psql_fortune  = U_NEW(UOrmSession(U_CONSTANT_TO_PARAM("fortune")));
-	pstmt_fortune = U_NEW(UOrmStatement(*psql_fortune, U_CONSTANT_TO_PARAM("SELECT id, message FROM Fortune")));
-
-	if (pstmt_fortune == 0) U_ERROR("usp_init_fortunes(): we cound't connect to db, exiting...");
-
-	pfortune  = U_NEW(Fortune);
-	pvfortune = U_NEW(UVector<Fortune*>);
-	pmessage  = U_NEW(U_STRING_FROM_CONSTANT("Additional fortune added at request time."));
-
-	pstmt_fortune->into(*pfortune);
-}
-
-static void usp_end_fortunes()
-{
-	U_TRACE(5, "::usp_end_fortunes()")
-
-	delete pstmt_fortune;
-	delete psql_fortune;
-	delete pvfortune;
-	delete pfortune;
-	delete pmessage;
-}
--->
-<!doctype html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr><!--#code
-Fortune* elem;
-unsigned char encoded[1024];
-
-pstmt_fortune->execute();
-
-	  pvfortune->push_back(U_NEW(Fortune(0, *pmessage)));
-do	{ pvfortune->push_back(U_NEW(Fortune(*pfortune))); } while (pstmt_fortune->nextRow());
-
-pvfortune->sort(Fortune::cmp_obj);
-
-for (uint32_t i = 0, n = pvfortune->size(); i < n; ++i)
-	{
-	elem = (*pvfortune)[i];
-
-	(void) u_xml_encode((const unsigned char*)U_STRING_TO_PARAM(elem->message), encoded);
-
-	USP_PRINTF_ADD(
-		"<tr>"
-		"<td>%d</td>"
-		"<td>%s</td>"
-		"</tr>",
-		elem->id, encoded);
-	}
-
-pvfortune->clear();
---></table></body></html>

+ 6 - 59
frameworks/C++/ULib/src/json.usp

@@ -1,74 +1,21 @@
-<!--#
-Test 1: JSON serialization
-
-This test exercises the framework fundamentals including keep-alive support, request routing, request header
-parsing, object instantiation, JSON serialization, response header generation, and request count throughput.
-
-Requirements
-
-1.  For each request, an object mapping the key message to Hello, World! must be instantiated.
-
-2.  The recommended URI is /json.
-
-3.  A JSON serializer must be used to convert the object to JSON.
-
-4.  The response text must be {"message":"Hello, World!"}, but white-space variations are acceptable.
-
-5.  The response content length should be approximately 28 bytes.
-
-6.  The response content type must be set to application/json.
-
-7.  The response headers must include either Content-Length or Transfer-Encoding.
-
-8.  The response headers must include Server and Date.
-
-9.  gzip compression is not permitted.
-
-10. Server support for HTTP Keep-Alive is strongly encouraged but not required.
-
-11. If HTTP Keep-Alive is enabled, no maximum Keep-Alive timeout is specified by this test.
-
-12. The request handler will be exercised at concurrency levels ranging from 8 to 256.
-
-13. The request handler will be exercised using GET requests.
-
-Example request:
-
-GET /json HTTP/1.1
-Host: server
-User-Agent: Mozilla/5.0 (X11; Linux x86_64) Gecko/20130501 Firefox/30.0 AppleWebKit/600.00 Chrome/30.0.0000.0 Trident/10.0 Safari/600.00
-Cookie: uid=12345678901234567890; __utma=1.1234567890.1234567890.1234567890.1234567890.12; wd=2560x1600
-Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
-Accept-Language: en-US,en;q=0.5
-Connection: keep-alive
-
-Example response:
-
-HTTP/1.1 200 OK
-Content-Type: application/json; charset=UTF-8
-Content-Length: 28
-Server: Example
-Date: Wed, 17 Apr 2013 12:00:00 GMT
-{"message":"Hello, World!"}
--->
 <!--#declaration
 static UString* pkey;
 static UString* pvalue;
 
 static void usp_init_json()
 {
-	U_TRACE(5, "::usp_init_json()")
+   U_TRACE(5, "::usp_init_json()")
 
-	pkey   = U_NEW(U_STRING_FROM_CONSTANT("message"));
-	pvalue = U_NEW(U_STRING_FROM_CONSTANT("Hello, World!"));
+   pkey   = U_NEW(U_STRING_FROM_CONSTANT("message"));
+   pvalue = U_NEW(U_STRING_FROM_CONSTANT("Hello, World!"));
 }
 
 static void usp_end_json()
 {
-	U_TRACE(5, "::usp_end_json()")
+   U_TRACE(5, "::usp_end_json()")
 
-	delete pkey;
-	delete pvalue;
+   delete pkey;
+   delete pvalue;
 }
 -->
 <!--#header

+ 0 - 50
frameworks/C++/ULib/src/plaintext.usp

@@ -1,51 +1 @@
-<!--#
-Test 6: Plaintext
-
-This test is an exercise of the request-routing fundamentals only, designed to demonstrate the capacity of
-high-performance platforms in particular. The response payload is still small, meaning good performance is
-still necessary in order to saturate the gigabit Ethernet of the test environment.
-
-Requirements
-
-1.  The recommended URI is /plaintext.
-
-2.  The response content type must be set to text/plain.
-
-3.  The response body must be Hello, World!.
-
-4.  The response headers must include either Content-Length or Transfer-Encoding.
-
-5.  The response headers must include Server and Date.
-
-6.  gzip compression is not permitted.
-
-7.  Server support for HTTP Keep-Alive is strongly encouraged but not required.
-
-8.  Server support for HTTP pipelining is strongly encouraged but not required.
-
-9.  If HTTP Keep-Alive is enabled, no maximum Keep-Alive timeout is specified by this test.
-
-10. The request handler will be exercised at 256, 1024, 4096, and 16,384 concurrency.
-
-11. The request handler will be exercised using GET requests.
-
-Example request:
-
-GET /plaintext HTTP/1.1
-Host: server
-User-Agent: Mozilla/5.0 (X11; Linux x86_64) Gecko/20130501 Firefox/30.0 AppleWebKit/600.00 Chrome/30.0.0000.0 Trident/10.0 Safari/600.00
-Cookie: uid=12345678901234567890; __utma=1.1234567890.1234567890.1234567890.1234567890.12; wd=2560x1600
-Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
-Accept-Language: en-US,en;q=0.5
-Connection: keep-alive
-
-Example response:
-
-HTTP/1.1 200 OK
-Content-Length: 15
-Content-Type: text/plain; charset=UTF-8
-Server: Example
-Date: Wed, 17 Apr 2013 12:00:00 GMT
-Hello, World!
--->
 Hello, World!

+ 0 - 160
frameworks/C++/ULib/src/queries.usp

@@ -1,160 +0,0 @@
-<!--#
-Test 3: Multiple database queries
-
-This test is a variation of Test #2 and also uses the World table. Multiple rows are fetched to more dramatically
-punish the database driver and connection pool. At the highest queries-per-request tested (20), this test demonstrates
-all frameworks' convergence toward zero requests-per-second as database activity increases.
-
-Requirements
-
-1.  For every request, an integer query string parameter named queries must be retrieved from the request.
-	 The parameter specifies the number of database queries to execute in preparing the HTTP response (see below).
-
-2.  The recommended URI is /queries.
-
-3.  The queries parameter must be bounded to between 1 and 500. If the parameter is missing, is not an integer,
-	 or is an integer less than 1, the value should be interpreted as 1; if greater than 500, the value should be interpreted as 500.
-
-3.  The schema for World is id (int, primary key) and randomNumber (int).
-
-4.  The request handler must retrieve a set of World objects, equal in count to the queries parameter, from the World database table.
-
-5.  Each row must be selected randomly in the same fashion as the single database query test (Test #2 above).
-
-6.  Since this test is designed to exercise multiple queries, each row must be selected individually by a query.
-	 It is not acceptable to retrieve all required rows using a SELECT ... WHERE id IN (...) clause.
-
-7.  Each World object must be added to a list or array.
-
-8.  The list or array must be serialized to JSON and sent as a response.
-
-9.  The response content type must be set to application/json.
-
-10. The response headers must include either Content-Length or Transfer-Encoding.
-
-11. The response headers must include Server and Date.
-
-12. Use of an in-memory cache of World objects or rows by the application is not permitted.
-
-13. Use of prepared statements for SQL database tests (e.g., for MySQL) is encouraged but not required.
-
-14. gzip compression is not permitted.
-
-15. Server support for HTTP Keep-Alive is strongly encouraged but not required.
-
-16. If HTTP Keep-Alive is enabled, no maximum Keep-Alive timeout is specified by this test.
-
-17. The request handler will be exercised at 256 concurrency only.
-
-18. The request handler will be exercised with query counts of 1, 5, 10, 15, and 20.
-
-19. The request handler will be exercised using GET requests.
-
-Example request:
-
-GET /queries?queries=10 HTTP/1.1
-Host: server
-User-Agent: Mozilla/5.0 (X11; Linux x86_64) Gecko/20130501 Firefox/30.0 AppleWebKit/600.00 Chrome/30.0.0000.0 Trident/10.0 Safari/600.00
-Cookie: uid=12345678901234567890; __utma=1.1234567890.1234567890.1234567890.1234567890.12; wd=2560x1600
-Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
-Accept-Language: en-US,en;q=0.5
-Connection: keep-alive
-
-Example response:
-
-HTTP/1.1 200 OK
-Content-Type: application/json; charset=UTF-8
-Content-Length: 315
-Server: Example
-Date: Wed, 17 Apr 2013 12:00:00 GMT
-
-[{"id":4174,"randomNumber":331},{"id":51,"randomNumber":6544},{"id":4462,"randomNumber":952},{"id":2221,"randomNumber":532},{"id":9276,"randomNumber":3097},{"id":3056,"randomNumber":7293},{"id":6964,"randomNumber":620},{"id":675,"randomNumber":6601},{"id":8414,"randomNumber":6569},{"id":2753,"randomNumber":4065}]
--->
-<!--#declaration
-#include "world.h"
-
-#define AS_cpoll_cppsp_DO
-
-#ifndef AS_cpoll_cppsp_DO
-static UValue*	pvalue;
-#endif
-static UOrmSession*		psql_queries;
-static UOrmStatement*	pstmt_queries;
-static World*				pworld_queries;
-static UVector<World*>* pvworld_queries;
-
-static void usp_init_queries()
-{
-	U_TRACE(5, "::usp_init_queries()")
-
-	psql_queries  = U_NEW(UOrmSession(U_CONSTANT_TO_PARAM("hello_world")));
-	pstmt_queries = U_NEW(UOrmStatement(*psql_queries, U_CONSTANT_TO_PARAM("SELECT randomNumber FROM World WHERE id = ?")));
-
-	if (pstmt_queries == 0) U_ERROR("usp_init_queries(): we cound't connect to db, exiting...");
-
-	pworld_queries  = U_NEW(World);
-	pvworld_queries = U_NEW(UVector<World*>(500));
-
-	pstmt_queries->use( pworld_queries->id);
-	pstmt_queries->into(pworld_queries->randomNumber);
-
-#ifndef AS_cpoll_cppsp_DO
-	pvalue = U_NEW(UValue(ARRAY_VALUE));
-#endif
-}
-
-static void usp_end_queries()
-{
-	U_TRACE(5, "::usp_end_queries()")
-
-	delete pstmt_queries;
-	delete psql_queries;
-	delete pvworld_queries;
-	delete pworld_queries;
-#ifndef AS_cpoll_cppsp_DO
-	delete pvalue;
-#endif
-}
--->
-<!--#args
-queries;
--->
-<!--#header
-Content-Type: application/json; charset=UTF-8
--->
-<!--#code
-int i = 0, num_queries = queries.strtol();
-
-	  if (num_queries <   1) num_queries = 1;
-else if (num_queries > 500) num_queries = 500;
-
-#ifdef AS_cpoll_cppsp_DO
-USP_PUTS_CHAR('[');
-#endif
-
-while (true)
-	{
-	pworld_queries->id = u_get_num_random(10000);
-
-	pstmt_queries->execute();
-
-#ifdef AS_cpoll_cppsp_DO
-	USP_PRINTF("{\"id\":%d,\"randomNumber\":%d}", pworld_queries->id, pworld_queries->randomNumber);
-#endif
-
-	pvworld_queries->push_back(U_NEW(World(*pworld_queries)));
-
-	if (++i == num_queries) break;
-
-#ifdef AS_cpoll_cppsp_DO
-	USP_PUTS_CHAR(',');
-#endif
-	}
-
-#ifdef AS_cpoll_cppsp_DO
-USP_PUTS_CHAR(']');
-#else
-USP_JSON_stringify(*pvalue, UVector<World*>, *pvworld_queries);
-#endif
-pvworld_queries->clear();
--->

+ 93 - 0
frameworks/C++/ULib/src/query.usp

@@ -0,0 +1,93 @@
+<!--#declaration
+#include "world.h"
+
+#define AS_cpoll_cppsp_DO
+
+#ifndef AS_cpoll_cppsp_DO
+static UValue* pvalue;
+#endif
+static UOrmSession*     psql_query;
+static UOrmStatement*   pstmt_query;
+static World*           pworld_query;
+static UVector<World*>* pvworld_query;
+
+static void usp_init_query()
+{
+   U_TRACE(5, "::usp_init_query()")
+
+   pworld_query  = U_NEW(World);
+   pvworld_query = U_NEW(UVector<World*>(500));
+
+#ifndef AS_cpoll_cppsp_DO
+   pvalue = U_NEW(UValue(ARRAY_VALUE));
+#endif
+}
+
+static void usp_fork_query()
+{
+   U_TRACE(5, "::usp_fork_query()")
+
+   psql_query  = U_NEW(UOrmSession(U_CONSTANT_TO_PARAM("hello_world")));
+   pstmt_query = U_NEW(UOrmStatement(*psql_query, U_CONSTANT_TO_PARAM("SELECT randomNumber FROM World WHERE id = ?")));
+
+   if (pstmt_queries == 0) U_ERROR("usp_fork_query(): we cound't connect to db, exiting...");
+
+   pstmt_query->use( pworld_query->id);
+   pstmt_query->into(pworld_query->randomNumber);
+}
+
+static void usp_end_query()
+{
+   U_TRACE(5, "::usp_end_query()")
+
+   delete pstmt_query;
+   delete psql_query;
+   delete pvworld_query;
+   delete pworld_query;
+#ifndef AS_cpoll_cppsp_DO
+   delete pvalue;
+#endif
+}
+-->
+<!--#args
+queries;
+-->
+<!--#header
+Content-Type: application/json; charset=UTF-8
+-->
+<!--#code
+int i = 0, num_queries = queries.strtol();
+
+     if (num_queries <   1) num_queries = 1;
+else if (num_queries > 500) num_queries = 500;
+
+#ifdef AS_cpoll_cppsp_DO
+USP_PUTS_CHAR('[');
+#endif
+
+while (true)
+   {
+   pworld_query->id = u_get_num_random(10000);
+
+   pstmt_query->execute();
+
+#ifdef AS_cpoll_cppsp_DO
+   USP_PRINTF("{\"id\":%d,\"randomNumber\":%d}", pworld_query->id, pworld_query->randomNumber);
+#endif
+
+   pvworld_query->push_back(U_NEW(World(*pworld_query)));
+
+   if (++i == num_query) break;
+
+#ifdef AS_cpoll_cppsp_DO
+   USP_PUTS_CHAR(',');
+#endif
+   }
+
+#ifdef AS_cpoll_cppsp_DO
+USP_PUTS_CHAR(']');
+#else
+USP_JSON_stringify(*pvalue, UVector<World*>, *pvworld_query);
+#endif
+pvworld_query->clear();
+-->

+ 109 - 0
frameworks/C++/ULib/src/update.usp

@@ -0,0 +1,109 @@
+<!--#declaration
+#include "world.h"
+
+#define AS_cpoll_cppsp_DO
+
+#ifndef AS_cpoll_cppsp_DO
+static UValue* pvalue;
+#endif
+static UOrmSession*     psql_update;
+static UOrmStatement*   pstmt1;
+static UOrmStatement*   pstmt2;
+static World*           pworld_update;
+static UVector<World*>* pvworld_update;
+
+static void usp_init_update()
+{
+   U_TRACE(5, "::usp_init_update()")
+
+   pworld_update  = U_NEW(World);
+   pvworld_update = U_NEW(UVector<World*>(500));
+
+#ifndef AS_cpoll_cppsp_DO
+   pvalue = U_NEW(UValue(ARRAY_VALUE));
+#endif
+}
+
+static void usp_fork_update()
+{
+   U_TRACE(5, "::usp_fork_update()")
+
+   psql_update = U_NEW(UOrmSession(U_CONSTANT_TO_PARAM("hello_world")));
+
+   pstmt1 = U_NEW(UOrmStatement(*psql_update, U_CONSTANT_TO_PARAM("SELECT randomNumber FROM World WHERE id = ?")));
+   pstmt2 = U_NEW(UOrmStatement(*psql_update, U_CONSTANT_TO_PARAM("UPDATE World SET randomNumber = ? WHERE id = ?")));
+
+   if (pstmt1 == 0 ||
+       pstmt2 == 0)
+      {
+      U_ERROR("usp_fork_update(): we cound't connect to db, exiting...");
+      }
+
+   pstmt1->use( pworld_update->id);
+   pstmt1->into(pworld_update->randomNumber);
+   pstmt2->use( pworld_update->randomNumber, pworld_update->id);
+}
+
+static void usp_end_update()
+{
+   U_TRACE(5, "::usp_end_update()")
+
+   delete pstmt1;
+   delete pstmt2;
+   delete psql_update;
+   delete pvworld_update;
+   delete pworld_update;
+#ifndef AS_cpoll_cppsp_DO
+   delete pvalue;
+#endif
+}
+-->
+<!--#args
+queries;
+-->
+<!--#header
+Content-Type: application/json; charset=UTF-8
+-->
+<!--#code
+int i = 0, num_queries = queries.strtol();
+
+     if (num_queries <   1) num_queries = 1;
+else if (num_queries > 500) num_queries = 500;
+
+#ifdef AS_cpoll_cppsp_DO
+USP_PUTS_CHAR('[');
+#endif
+
+while (true)
+   {
+   pworld_update->id = u_get_num_random(10000);
+
+   pstmt1->execute();
+
+   U_INTERNAL_DUMP("pworld_update->randomNumber = %d", pworld_update->randomNumber)
+
+   pworld_update->randomNumber = u_get_num_random(10000);
+
+   pstmt2->execute();
+
+#ifdef AS_cpoll_cppsp_DO
+   USP_PRINTF("{\"id\":%d,\"randomNumber\":%d}", pworld_update->id, pworld_update->randomNumber);
+#endif
+
+   pvworld_update->push_back(U_NEW(World(*pworld_update)));
+
+   if (++i == num_queries) break;
+
+#ifdef AS_cpoll_cppsp_DO
+   USP_PUTS_CHAR(',');
+#endif
+   }
+
+#ifdef AS_cpoll_cppsp_DO
+USP_PUTS_CHAR(']');
+#else
+USP_JSON_stringify(*pvalue, UVector<World*>, *pvworld_update);
+#endif
+
+pvworld_update->clear();
+-->

+ 0 - 184
frameworks/C++/ULib/src/updates.usp

@@ -1,184 +0,0 @@
-<!--#
-Test 5: Database updates
-
-This test is a variation of Test #3 that exercises the ORM's persistence of
-objects and the database driver's performance at running UPDATE statements or similar.
-
-Requirements
-
-1.  The recommended URI is /updates.
-
-2.  For every request, an integer query string parameter named queries must be retrieved from the request.
-    The parameter specifies the number of rows to fetch and update in preparing the HTTP response (see below).
-
-3.  The queries parameter must be bounded to between 1 and 500. If the parameter is missing, is not an integer,
-	 or is an integer less than 1, the value should be interpreted as 1; if greater than 500, the value should be interpreted as 500.
-
-3.  The schema for World is id (int, primary key) and randomNumber (int).
-
-4.  The request handler must retrieve a set of World objects, equal in count to the queries parameter, from the World database table.
-
-5.  Each row must be selected randomly in the same fashion as the single database query test (Test #2 above).
-
-6.  At least the randomNumber field must be read from the database result set.
-
-7.  Each World object must have its randomNumber field updated to a new random integer between 1 and 10000.
-
-8.  Each World object must be persisted to the database with its new randomNumber value.
-
-9.  Use of batch updates is acceptable but not required.
-
-10. Use of transactions is acceptable but not required.
-
-11. For raw tests (that is, tests without an ORM), each updated row must receive a unique new randomNumber value.
-    It is not acceptable to change the randomNumber value of all rows to the same random number using an UPDATE ... WHERE id IN (...) clause.
-
-12. Each World object must be added to a list or array.
-
-13. The list or array must be serialized to JSON and sent as a response.
-
-14. The response content type must be set to application/json.
-
-15. The response headers must include either Content-Length or Transfer-Encoding.
-
-16. The response headers must include Server and Date.
-
-17. Use of an in-memory cache of World objects or rows by the application is not permitted.
-
-18. Use of prepared statements for SQL database tests (e.g., for MySQL) is encouraged but not required.
-
-19. gzip compression is not permitted.
-
-20. Server support for HTTP Keep-Alive is strongly encouraged but not required.
-
-21. If HTTP Keep-Alive is enabled, no maximum Keep-Alive timeout is specified by this test.
-
-22. The request handler will be exercised at 256 concurrency only.
-
-23. The request handler will be exercised with query counts of 1, 5, 10, 15, and 20.
-
-24. The request handler will be exercised using GET requests.
-
-Example request:
-
-GET /updates?queries=10 HTTP/1.1
-Host: server
-User-Agent: Mozilla/5.0 (X11; Linux x86_64) Gecko/20130501 Firefox/30.0 AppleWebKit/600.00 Chrome/30.0.0000.0 Trident/10.0 Safari/600.00
-Cookie: uid=12345678901234567890; __utma=1.1234567890.1234567890.1234567890.1234567890.12; wd=2560x1600
-Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
-Accept-Language: en-US,en;q=0.5
-Connection: keep-alive
-
-Example response:
-
-HTTP/1.1 200 OK
-Content-Type: application/json; charset=UTF-8
-Content-Length: 315
-Server: Example
-Date: Wed, 17 Apr 2013 12:00:00 GMT
-
-[{"id":4174,"randomNumber":331},{"id":51,"randomNumber":6544},{"id":4462,"randomNumber":952},{"id":2221,"randomNumber":532},{"id":9276,"randomNumber":3097},{"id":3056,"randomNumber":7293},{"id":6964,"randomNumber":620},{"id":675,"randomNumber":6601},{"id":8414,"randomNumber":6569},{"id":2753,"randomNumber":4065}]
--->
-<!--#declaration
-#include "world.h"
-
-#define AS_cpoll_cppsp_DO
-
-#ifndef AS_cpoll_cppsp_DO
-static UValue*	pvalue;
-#endif
-static UOrmSession*		psql_updates;
-static UOrmStatement*	pstmt1;
-static UOrmStatement*	pstmt2;
-static World*				pworld_updates;
-static UVector<World*>* pvworld_updates;
-
-static void usp_init_updates()
-{
-	U_TRACE(5, "::usp_init_updates()")
-
-	psql_updates = U_NEW(UOrmSession(U_CONSTANT_TO_PARAM("hello_world")));
-	pstmt1		 = U_NEW(UOrmStatement(*psql_updates, U_CONSTANT_TO_PARAM("SELECT randomNumber FROM World WHERE id = ?")));
-	pstmt2		 = U_NEW(UOrmStatement(*psql_updates, U_CONSTANT_TO_PARAM("UPDATE World SET randomNumber = ? WHERE id = ?")));
-
-	if (pstmt1 == 0 ||
-		 pstmt2 == 0)
-		{
-		U_ERROR("usp_init_updates(): we cound't connect to db, exiting...");
-		}
-
-	pworld_updates  = U_NEW(World);
-	pvworld_updates = U_NEW(UVector<World*>(500));
-
-	pstmt1->use( pworld_updates->id);
-	pstmt1->into(pworld_updates->randomNumber);
-	pstmt2->use( pworld_updates->randomNumber, pworld_updates->id);
-
-#ifndef AS_cpoll_cppsp_DO
-	pvalue = U_NEW(UValue(ARRAY_VALUE));
-#endif
-}
-
-static void usp_end_updates()
-{
-	U_TRACE(5, "::usp_end_updates()")
-
-	delete pstmt1;
-	delete pstmt2;
-	delete psql_updates;
-	delete pvworld_updates;
-	delete pworld_updates;
-#ifndef AS_cpoll_cppsp_DO
-	delete pvalue;
-#endif
-}
--->
-<!--#args
-queries;
--->
-<!--#header
-Content-Type: application/json; charset=UTF-8
--->
-<!--#code
-int i = 0, num_queries = queries.strtol();
-
-	  if (num_queries <   1) num_queries = 1;
-else if (num_queries > 500) num_queries = 500;
-
-#ifdef AS_cpoll_cppsp_DO
-USP_PUTS_CHAR('[');
-#endif
-
-while (true)
-	{
-	pworld_updates->id = u_get_num_random(10000);
-
-	pstmt1->execute();
-
-	U_INTERNAL_DUMP("pworld_updates->randomNumber = %d", pworld_updates->randomNumber)
-
-	pworld_updates->randomNumber = u_get_num_random(10000);
-
-	pstmt2->execute();
-
-#ifdef AS_cpoll_cppsp_DO
-	USP_PRINTF("{\"id\":%d,\"randomNumber\":%d}", pworld_updates->id, pworld_updates->randomNumber);
-#endif
-
-	pvworld_updates->push_back(U_NEW(World(*pworld_updates)));
-
-	if (++i == num_queries) break;
-
-#ifdef AS_cpoll_cppsp_DO
-	USP_PUTS_CHAR(',');
-#endif
-	}
-
-#ifdef AS_cpoll_cppsp_DO
-USP_PUTS_CHAR(']');
-#else
-USP_JSON_stringify(*pvalue, UVector<World*>, *pvworld_updates);
-#endif
-
-pvworld_updates->clear();
--->

+ 58 - 58
frameworks/C++/ULib/src/world.h

@@ -8,99 +8,99 @@
 
 class World {
 public:
-	// Check for memory error
-	U_MEMORY_TEST
+   // Check for memory error
+   U_MEMORY_TEST
 
-	// Allocator e Deallocator
-	U_MEMORY_ALLOCATOR
-	U_MEMORY_DEALLOCATOR
+   // Allocator e Deallocator
+   U_MEMORY_ALLOCATOR
+   U_MEMORY_DEALLOCATOR
 
-	int id, randomNumber;
+   int id, randomNumber;
 
-	// CONSTRUCTOR
+   // CONSTRUCTOR
 
-	World()
-		{
-		U_TRACE_REGISTER_OBJECT(5, World, "")
-		}
+   World()
+      {
+      U_TRACE_REGISTER_OBJECT(5, World, "")
+      }
 
-	World(const World& w) : id(w.id), randomNumber(w.randomNumber)
-		{
-		U_TRACE_REGISTER_OBJECT(5, World, "%p", &w)
+   World(const World& w) : id(w.id), randomNumber(w.randomNumber)
+      {
+      U_TRACE_REGISTER_OBJECT(5, World, "%p", &w)
 
-		U_MEMORY_TEST_COPY(w)
-		}
+      U_MEMORY_TEST_COPY(w)
+      }
 
-	~World()
-		{
-		U_TRACE_UNREGISTER_OBJECT(5, World)
-		}
+   ~World()
+      {
+      U_TRACE_UNREGISTER_OBJECT(5, World)
+      }
 
 #ifdef DEBUG
-	const char* dump(bool breset) const
-		{
-		*UObjectIO::os << "id           " << id				<< '\n'
-							<< "randomNumber " << randomNumber;
+   const char* dump(bool breset) const
+      {
+      *UObjectIO::os << "id           " << id            << '\n'
+                     << "randomNumber " << randomNumber;
 
-		if (breset)
-			{
-			UObjectIO::output();
+      if (breset)
+         {
+         UObjectIO::output();
 
-			return UObjectIO::buffer_output;
-			}
+         return UObjectIO::buffer_output;
+         }
 
-		return 0;
-		}
+      return 0;
+      }
 #endif
 
 private:
-	World& operator=(const World&) { return *this; }
+   World& operator=(const World&) { return *this; }
 };
 
 // ORM TEMPLATE SPECIALIZATIONS
 
 template <> class U_EXPORT UOrmTypeHandler<World> : public UOrmTypeHandler_Base {
 public:
-	explicit UOrmTypeHandler(World& val) : UOrmTypeHandler_Base(&val) {}
+   explicit UOrmTypeHandler(World& val) : UOrmTypeHandler_Base(&val) {}
 
-	void bindParam(UOrmStatement* stmt) const
-		{
-		U_TRACE(0, "UOrmTypeHandler<World>::bindParam(%p)", stmt)
+   void bindParam(UOrmStatement* stmt) const
+      {
+      U_TRACE(0, "UOrmTypeHandler<World>::bindParam(%p)", stmt)
 
-		stmt->bindParam(U_ORM_TYPE_HANDLER(World, id,				int));
-		stmt->bindParam(U_ORM_TYPE_HANDLER(World, randomNumber,	int));
-		}
+      stmt->bindParam(U_ORM_TYPE_HANDLER(World, id,            int));
+      stmt->bindParam(U_ORM_TYPE_HANDLER(World, randomNumber,  int));
+      }
 
-	void bindResult(UOrmStatement* stmt)
-		{
-		U_TRACE(0, "UOrmTypeHandler<World>::bindResult(%p)", stmt)
+   void bindResult(UOrmStatement* stmt)
+      {
+      U_TRACE(0, "UOrmTypeHandler<World>::bindResult(%p)", stmt)
 
-		stmt->bindResult(U_ORM_TYPE_HANDLER(World, id,				int));
-		stmt->bindResult(U_ORM_TYPE_HANDLER(World, randomNumber,	int));
-		}
+      stmt->bindResult(U_ORM_TYPE_HANDLER(World, id,           int));
+      stmt->bindResult(U_ORM_TYPE_HANDLER(World, randomNumber, int));
+      }
 };
 
 // JSON TEMPLATE SPECIALIZATIONS
 
 template <> class U_EXPORT UJsonTypeHandler<World> : public UJsonTypeHandler_Base {
 public:
-	explicit UJsonTypeHandler(World& val) : UJsonTypeHandler_Base(&val) {}
+   explicit UJsonTypeHandler(World& val) : UJsonTypeHandler_Base(&val) {}
 
-	void toJSON(UValue& json)
-		{
-		U_TRACE(0, "UJsonTypeHandler<World>::toJSON(%p)", &json)
+   void toJSON(UValue& json)
+      {
+      U_TRACE(0, "UJsonTypeHandler<World>::toJSON(%p)", &json)
 
-		json.toJSON(U_JSON_TYPE_HANDLER(World, id,				int));
-		json.toJSON(U_JSON_TYPE_HANDLER(World, randomNumber,	int));
-		}
+      json.toJSON(U_JSON_TYPE_HANDLER(World, id,            int));
+      json.toJSON(U_JSON_TYPE_HANDLER(World, randomNumber,  int));
+      }
 
-	void fromJSON(UValue& json)
-		{
-		U_TRACE(0, "UJsonTypeHandler<World>::fromJSON(%p)", &json)
+   void fromJSON(UValue& json)
+      {
+      U_TRACE(0, "UJsonTypeHandler<World>::fromJSON(%p)", &json)
 
-		json.fromJSON(U_JSON_TYPE_HANDLER(World, id,				 int));
-		json.fromJSON(U_JSON_TYPE_HANDLER(World, randomNumber, int));
-		}
+      json.fromJSON(U_JSON_TYPE_HANDLER(World, id,           int));
+      json.fromJSON(U_JSON_TYPE_HANDLER(World, randomNumber, int));
+      }
 };
 
 #endif

+ 2 - 2
frameworks/C++/treefrog/setup-thread.py

@@ -22,7 +22,7 @@ def start(args, logfile, errfile):
     subprocess.check_call("make clean", shell=True, cwd="treefrog", stderr=errfile, stdout=logfile)
     subprocess.check_call("make -j8", shell=True, cwd="treefrog", stderr=errfile, stdout=logfile)
     subprocess.check_call("rm -f log/*.log", shell=True, cwd="treefrog", stderr=errfile, stdout=logfile)
-    subprocess.check_call("treefrog -d " + home + "/FrameworkBenchmarks/treefrog", shell=True, stderr=errfile, stdout=logfile)
+    subprocess.check_call("treefrog -d $TROOT", shell=True, stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1
@@ -32,7 +32,7 @@ def start(args, logfile, errfile):
 ##############
 def stop(logfile, errfile):
   try:
-    subprocess.call("treefrog -k abort " + home + "/FrameworkBenchmarks/treefrog", shell=True, stderr=errfile, stdout=logfile)
+    subprocess.call("treefrog -k abort $TROOT", shell=True, stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1

+ 2 - 2
frameworks/C++/treefrog/setup.py

@@ -22,7 +22,7 @@ def start(args, logfile, errfile):
     subprocess.check_call("make clean", shell=True, cwd="treefrog", stderr=errfile, stdout=logfile)
     subprocess.check_call("make -j8", shell=True, cwd="treefrog", stderr=errfile, stdout=logfile)
     subprocess.check_call("rm -f log/*.log", shell=True, cwd="treefrog", stderr=errfile, stdout=logfile)
-    subprocess.check_call("treefrog -d " + home + "/FrameworkBenchmarks/treefrog", shell=True, stderr=errfile, stdout=logfile)
+    subprocess.check_call("treefrog -d $TROOT", shell=True, stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1
@@ -32,7 +32,7 @@ def start(args, logfile, errfile):
 ##############
 def stop(logfile, errfile):
   try:
-    subprocess.call("treefrog -k abort " + home + "/FrameworkBenchmarks/treefrog", shell=True, stderr=errfile, stdout=logfile)
+    subprocess.call("treefrog -k abort $TROOT", shell=True, stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1

+ 1 - 1
frameworks/C++/wt/install.sh

@@ -1,3 +1,3 @@
 #!/bin/bash
 
-fw_depends wt
+fw_depends apache wt

+ 1 - 1
frameworks/Erlang/cowboy/install.sh

@@ -1,3 +1,3 @@
 #!/bin/bash
 
-fw_depends erlang
+fw_depends erlang rebar

BIN
frameworks/Erlang/cowboy/rebar


+ 2 - 2
frameworks/Erlang/cowboy/setup_erlang.py

@@ -7,8 +7,8 @@ def start(args, logfile, errfile):
 
   try:
     subprocess.check_call("rm -rf deps/*", shell=True, cwd="cowboy", stderr=errfile, stdout=logfile)
-    subprocess.check_call("./rebar get-deps", shell=True, cwd="cowboy", stderr=errfile, stdout=logfile)
-    subprocess.check_call("./rebar compile", shell=True, cwd="cowboy", stderr=errfile, stdout=logfile)
+    subprocess.check_call("$IROOT/rebar/rebar get-deps", shell=True, cwd="cowboy", stderr=errfile, stdout=logfile)
+    subprocess.check_call("$IROOT/rebar/rebar compile", shell=True, cwd="cowboy", stderr=errfile, stdout=logfile)
     subprocess.check_call("erl -pa ebin deps/*/ebin +sbwt very_long +swt very_low -s hello_world -noshell -detached", shell=True, cwd="cowboy", stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:

+ 1 - 1
frameworks/Erlang/elli/install.sh

@@ -1,3 +1,3 @@
 #!/bin/bash
 
-fw_depends erlang
+fw_depends erlang rebar

BIN
frameworks/Erlang/elli/rebar


+ 1 - 1
frameworks/Erlang/elli/rebar.config

@@ -1,6 +1,6 @@
 {deps,
  [
-  {jiffy, ".*", {git, "https://github.com/davisp/jiffy.git", {tag, "0.8.3"}}},
+  {jiffy, ".*", {git, "https://github.com/davisp/jiffy.git", {tag, "0.8.5"}}},
   {emysql, ".*", {git, "https://github.com/Eonblast/Emysql.git"}},
   {elli, "", {git, "git://github.com/knutin/elli.git"}}
  ]}.

+ 3 - 2
frameworks/Erlang/elli/setup_erlang.py

@@ -6,8 +6,9 @@ def start(args, logfile, errfile):
   setup_util.replace_text("elli/src/elli_bench_sup.erl", "\"benchmarkdbpass\", \".*\", 3306", "\"benchmarkdbpass\", \"" + args.database_host + "\", 3306")
   
   try:
-    subprocess.check_call("./rebar get-deps", shell=True, cwd="elli", stderr=errfile, stdout=logfile)
-    subprocess.check_call("./rebar compile", shell=True, cwd="elli", stderr=errfile, stdout=logfile)
+    subprocess.check_call("rm -rf deps/*", shell=True, cwd="elli", stderr=errfile, stdout=logfile)
+    subprocess.check_call("$IROOT/rebar/rebar get-deps", shell=True, cwd="elli", stderr=errfile, stdout=logfile)
+    subprocess.check_call("$IROOT/rebar/rebar compile", shell=True, cwd="elli", stderr=errfile, stdout=logfile)
     # adding +K true seemed to actually slow performance
     subprocess.check_call("erl -pa ebin deps/*/ebin +sbwt very_long +swt very_low -s elli_bench -noshell -detached", shell=True, cwd="elli", stderr=errfile, stdout=logfile)
     return 0

+ 7 - 0
frameworks/Go/beego/bash_profile.sh

@@ -0,0 +1,7 @@
+# Set the root of our go installation
+export GOROOT=${IROOT}/go
+
+# Where to find the go executable
+export PATH="$GOROOT/bin:$PATH"
+
+export GOPATH=${TROOT}

+ 0 - 1
frameworks/Go/beego/setup.py

@@ -8,7 +8,6 @@ def start(args, logfile, errfile):
     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
-  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

+ 7 - 0
frameworks/Go/gin/bash_profile.sh

@@ -0,0 +1,7 @@
+# Set the root of our go installation
+export GOROOT=${IROOT}/go
+
+# Where to find the go executable
+export PATH="$GOROOT/bin:$PATH"
+
+export GOPATH=${TROOT}

+ 1 - 1
frameworks/Go/go/bash_profile.sh

@@ -4,4 +4,4 @@ export GOROOT=${IROOT}/go
 # Where to find the go executable
 export PATH="$GOROOT/bin:$PATH"
 
-export GOPATH=${FWROOT}/go
+export GOPATH=${TROOT}

+ 0 - 1
frameworks/Go/go/setup.py

@@ -12,7 +12,6 @@ def start(args, logfile, errfile):
     subprocess.call("set GOPATH=C:\\FrameworkBenchmarks\\go&& go get ./...", shell=True, cwd="go", stderr=errfile, stdout=logfile)
     subprocess.Popen("setup.bat", shell=True, cwd="go", stderr=errfile, stdout=logfile) 
     return 0
-  # os.environ["GOPATH"] = os.path.expanduser('~/FrameworkBenchmarks/go')
   subprocess.call("go get ./...", shell=True, cwd="go", stderr=errfile, stdout=logfile) 
   subprocess.Popen("go run src/hello/hello.go".rsplit(" "), cwd="go", stderr=errfile, stdout=logfile)
   return 0

+ 7 - 0
frameworks/Go/gorail/bash_profile.sh

@@ -0,0 +1,7 @@
+# Set the root of our go installation
+export GOROOT=${IROOT}/go
+
+# Where to find the go executable
+export PATH="$GOROOT/bin:$PATH"
+
+export GOPATH=${TROOT}

+ 3 - 0
frameworks/Go/gorail/install.sh

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

+ 0 - 1
frameworks/Go/gorail/setup.py

@@ -12,7 +12,6 @@ def start(args, logfile, errfile):
     subprocess.call("set GOPATH=C:\\FrameworkBenchmarks\\gorail&& go get ./...", shell=True, cwd="go", stderr=errfile, stdout=logfile)
     subprocess.Popen("setup.bat", shell=True, cwd="go", stderr=errfile, stdout=logfile) 
     return 0
-  os.environ["GOPATH"] = os.path.expanduser('~/FrameworkBenchmarks/gorail')
   subprocess.call("go get -u github.com/gorail/core", shell=True, cwd="gorail", stderr=errfile, stdout=logfile)
   subprocess.call("go get ./...", shell=True, cwd="go", stderr=errfile, stdout=logfile) 
   subprocess.Popen("go run src/hello/hello.go".rsplit(" "), cwd="go", stderr=errfile, stdout=logfile)

+ 7 - 0
frameworks/Go/revel-qbs/bash_profile.sh

@@ -0,0 +1,7 @@
+# Set the root of our go installation
+export GOROOT=${IROOT}/go
+
+# Where to find the go executable
+export PATH="$GOROOT/bin:$PATH"
+
+export GOPATH=${TROOT}

+ 1 - 2
frameworks/Go/revel-qbs/setup.py

@@ -15,7 +15,6 @@ def start(args, logfile, errfile):
     subprocess.call(r"go build -o bin\revel.exe github.com/robfig/revel/revel", shell=True, cwd=CWD, env=env, stderr=errfile, stdout=logfile)
     subprocess.Popen(r"bin\revel.exe run benchmark prod".rsplit(" "), shell=True, cwd=CWD, env=env, stderr=errfile, stdout=logfile)
     return 0
-  os.environ["GOPATH"] = os.path.expanduser('~/FrameworkBenchmarks/revel-qbs')
   subprocess.call("go get -u github.com/robfig/revel/revel github.com/coocood/qbs", shell=True, cwd=CWD, stderr=errfile, stdout=logfile)
   subprocess.call("go build -o bin/revel github.com/robfig/revel/revel", shell=True, cwd=CWD, stderr=errfile, stdout=logfile)
   subprocess.Popen("bin/revel run benchmark prod".rsplit(" "), cwd=CWD, stderr=errfile, stdout=logfile)
@@ -29,7 +28,7 @@ def stop(logfile, errfile):
   p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
   out, err = p.communicate()
   for line in out.splitlines():
-    if 'revel' in line and 'run-tests' not in line:
+    if 'revel' in line and 'run-tests' not in line and 'run-ci' not in line:
       pid = int(line.split(None, 2)[1])
       os.kill(pid, 15)
   return 0

+ 7 - 0
frameworks/Go/revel/bash_profile.sh

@@ -0,0 +1,7 @@
+# Set the root of our go installation
+export GOROOT=${IROOT}/go
+
+# Where to find the go executable
+export PATH="$GOROOT/bin:$PATH"
+
+export GOPATH=${TROOT}

+ 1 - 2
frameworks/Go/revel/setup.py

@@ -15,7 +15,6 @@ def start(args, logfile, errfile):
     subprocess.call(r"go build -o bin\revel.exe github.com/robfig/revel/revel", shell=True, cwd="revel", env=env, stderr=errfile, stdout=logfile)
     subprocess.Popen(r"bin\revel.exe run benchmark prod".rsplit(" "), shell=True, cwd="revel", env=env, stderr=errfile, stdout=logfile)
     return 0
-  os.environ["GOPATH"] = os.path.expanduser('~/FrameworkBenchmarks/revel')
   subprocess.call("go get -u github.com/robfig/revel/revel", shell=True, cwd="revel", stderr=errfile, stdout=logfile)
   subprocess.call("go build -o bin/revel github.com/robfig/revel/revel", shell=True, cwd="revel", stderr=errfile, stdout=logfile)
   subprocess.Popen("bin/revel run benchmark prod".rsplit(" "), cwd="revel", stderr=errfile, stdout=logfile)
@@ -29,7 +28,7 @@ def stop(logfile, errfile):
   p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
   out, err = p.communicate()
   for line in out.splitlines():
-    if 'revel' in line and 'run-tests' not in line:
+    if 'revel' in line and 'run-tests' not in line and 'run-ci' not in line:
       pid = int(line.split(None, 2)[1])
       os.kill(pid, 15)
   return 0

+ 7 - 0
frameworks/Go/webgo/bash_profile.sh

@@ -0,0 +1,7 @@
+# Set the root of our go installation
+export GOROOT=${IROOT}/go
+
+# Where to find the go executable
+export PATH="$GOROOT/bin:$PATH"
+
+export GOPATH=${TROOT}

+ 0 - 1
frameworks/Go/webgo/setup.py

@@ -8,7 +8,6 @@ def start(args, logfile, errfile):
     subprocess.call("set GOPATH=C:\\FrameworkBenchmarks\\webgo&&go get ./...", shell=True, cwd="webgo", stderr=errfile, stdout=logfile)
     subprocess.Popen("setup.bat", shell=True, cwd="webgo", stderr=errfile, stdout=logfile) 
     return 0
-  os.environ["GOPATH"] = os.path.expanduser('~/FrameworkBenchmarks/webgo')
   subprocess.call("go get ./...", shell=True, cwd="webgo", stderr=errfile, stdout=logfile)
   subprocess.Popen("go run src/hello/hello.go".rsplit(" "), cwd="webgo", stderr=errfile, stdout=logfile)
   return 0

+ 30 - 8
frameworks/Java/dropwizard-mongodb/src/main/java/com/example/helloworld/resources/WorldResource.java

@@ -13,6 +13,7 @@ import org.mongojack.JacksonDBCollection;
 
 import com.example.helloworld.core.World;
 import com.google.common.base.Optional;
+import com.google.common.primitives.Ints;
 import com.mongodb.BasicDBObject;
 import com.mongodb.DBObject;
 
@@ -29,18 +30,39 @@ public class WorldResource
   }
 
   @GET
-  public World[] dbTest(@QueryParam("queries") Optional<Integer> queries)
+  public Object dbTest(@QueryParam("queries") Optional<String> queries)
   {
-    final int totalQueries = queries.or(1);
-    final World[] worlds = new World[queries.or(1)];
     final Random random = new Random(System.currentTimeMillis());
-
+    if (!queries.isPresent()) 
+    {
+      DBObject query = new BasicDBObject();
+      query.put("_id", (random.nextInt(10000) + 1));
+      DBCursor<World> dbCursor = collection.find(query);
+      return (dbCursor.hasNext()) ? dbCursor.next() : null;
+    }
+    Integer totalQueries = Ints.tryParse(queries.orNull());
+    if (totalQueries != null) 
+    {
+      if (totalQueries > 500) 
+      {
+        totalQueries = 500;
+      }
+      else if (totalQueries < 1) 
+      {
+        totalQueries = 1;
+      }
+    } 
+    else 
+    {
+      totalQueries = 1;
+    }
+    final World[] worlds = new World[totalQueries];
     for (int i = 0; i < totalQueries; i++)
     {
-    	DBObject query = new BasicDBObject();
-    	query.put("_id", (random.nextInt(10000) + 1));
-    	DBCursor<World> dbCursor = collection.find(query);
-        worlds[i] = (dbCursor.hasNext()) ? dbCursor.next() : null;
+      DBObject query = new BasicDBObject();
+      query.put("_id", (random.nextInt(10000) + 1));
+      DBCursor<World> dbCursor = collection.find(query);
+      worlds[i] = (dbCursor.hasNext()) ? dbCursor.next() : null;
     }
     return worlds;
   }

+ 14 - 4
frameworks/Java/dropwizard/src/main/java/com/example/helloworld/resources/TextResource.java

@@ -8,9 +8,19 @@ import javax.ws.rs.core.MediaType;
 @Path("/plaintext")
 @Produces(MediaType.TEXT_PLAIN)
 public class TextResource {
+	private static final String MESSAGE = "Hello, World!";
+	private static final byte[] buffer;
 
-    @GET
-    public String sayHello() {
-        return "Hello, World!";
-    }
+	static {
+		try {
+			buffer = MESSAGE.getBytes("US-ASCII");
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	@GET
+	public byte[] sayHello() {
+		return buffer;
+	}
 }

+ 31 - 4
frameworks/Java/dropwizard/src/main/java/com/example/helloworld/resources/WorldResource.java

@@ -3,6 +3,7 @@ package com.example.helloworld.resources;
 import com.example.helloworld.db.WorldDAO;
 import com.example.helloworld.db.model.World;
 import com.google.common.base.Optional;
+import com.google.common.primitives.Ints;
 import io.dropwizard.hibernate.UnitOfWork;
 
 import javax.ws.rs.GET;
@@ -26,8 +27,24 @@ public class WorldResource {
 
     @GET
     @UnitOfWork
-    public World[] dbTest(@QueryParam("queries") Optional<Integer> queries) {
-        final int totalQueries = queries.or(1); // TODO: Should be bound [1,500]
+    public Object dbTest(@QueryParam("queries") Optional<String> queries) {
+        if (!queries.isPresent()) {
+            final long worldId = RANDOM.nextInt(10_000) + 1;
+            return worldDAO.findById(worldId).orNull();
+        }
+
+        Integer totalQueries = Ints.tryParse(queries.orNull());
+        if (totalQueries != null) {
+            if (totalQueries > 500) {
+                totalQueries = 500;
+            } else if (totalQueries < 1) {
+                totalQueries = 1;
+            }
+        } else {
+            totalQueries = 1;
+        }
+
+        
         final World[] worlds = new World[totalQueries];
 
         // TODO: Is parallelising this cheating?
@@ -42,8 +59,18 @@ public class WorldResource {
     @GET
     @Path("/update")
     @UnitOfWork
-    public World[] updateTest(@QueryParam("queries") Optional<Integer> queries) {
-        final int totalQueries = queries.or(1); // TODO: Should be bound [1,500]
+    public World[] updateTest(@QueryParam("queries") Optional<String> queries) {
+        Integer totalQueries = Ints.tryParse(queries.orNull());
+        if (totalQueries != null) {
+            if (totalQueries > 500) {
+                totalQueries = 500;
+            } else if (totalQueries < 1) {
+                totalQueries = 1;
+            }
+        } else {
+            totalQueries = 1;
+        }
+
         final World[] worlds = new World[totalQueries];
 
         // TODO: Is parallelising this cheating?

+ 1 - 1
frameworks/Java/grizzly-bm/setup.py

@@ -14,7 +14,7 @@ def stop(logfile, errfile):
   p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
   out, err = p.communicate()
   for line in out.splitlines():
-    if 'grizzly-bm' in line:
+    if 'grizzly-bm' in line and 'run-tests' not in line and 'run-ci' not in line:
       pid = int(line.split(None, 2)[1])
       os.kill(pid, 15)
   return 0

+ 1 - 1
frameworks/Java/grizzly-jersey/pom.xml

@@ -112,7 +112,7 @@
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-shade-plugin</artifactId>
-        <version>2.0</version>
+        <version>2.1</version>
         <executions>
           <execution>
             <phase>package</phase>

+ 1 - 1
frameworks/Java/play1siena/conf/dependencies.yml

@@ -2,4 +2,4 @@
 
 require:
     - play
-    - play -> siena 2.0.7
+    - play -> siena 2.0.6

+ 1 - 1
frameworks/Java/play1siena/install.sh

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

+ 1 - 1
frameworks/Java/play1siena/modules/siena-2.0.6

@@ -1 +1 @@
-../installs/play-1.2.5/modules/siena-2.0.6
+../../../installs/play-1.2.5/modules/siena-2.0.6

+ 4 - 1
frameworks/Java/servlet/src/main/java/hello/FortunesServlet.java

@@ -19,6 +19,8 @@ public class FortunesServlet extends HttpServlet
   
   // Database details.
   private static final String DB_QUERY = "SELECT * FROM Fortune";
+  private static final String UTF8 = "UTF-8";
+  private static final String CONTENT_TYPE_HTML_UTF8 = "text/html;charset=UTF-8";
 
   // Database connection pool.
   @Resource(name="jdbc/hello_world")
@@ -29,7 +31,8 @@ public class FortunesServlet extends HttpServlet
       throws ServletException, IOException
   {
     // Set content type to JSON
-    res.setHeader(Common.HEADER_CONTENT_TYPE, Common.CONTENT_TYPE_HTML);
+    res.setCharacterEncoding(UTF8);
+    res.setContentType(CONTENT_TYPE_HTML_UTF8);
 
     final List<Fortune> fortunes = new ArrayList<>();
     

+ 9 - 3
frameworks/Java/spring/src/main/java/com/techempower/spring/web/WorldDatabaseController.java

@@ -28,7 +28,7 @@ final class WorldDatabaseController {
 	}
 
 	@RequestMapping(value = "/queries", produces = "application/json")
-	List<World> multipleQueries(@RequestParam("queries") Integer rawQueryCount) {
+	List<World> multipleQueries(@RequestParam(value="queries", required=false, defaultValue="1") String rawQueryCount) {
 		Integer queryCount = boundQueryCount(rawQueryCount);
 
 		List<World> worlds = new ArrayList<World>(queryCount);
@@ -42,7 +42,7 @@ final class WorldDatabaseController {
 	}
 
 	@RequestMapping(value = "/updates", produces = "application/json")
-	List<World> updateQueries(@RequestParam(value="queries", required=false, defaultValue="1") Integer rawQueryCount) {
+	List<World> updateQueries(@RequestParam(value="queries", required=false, defaultValue="1") String rawQueryCount) {
 		Integer queryCount = boundQueryCount(rawQueryCount);
 
 		List<World> worlds = new ArrayList<World>(queryCount);
@@ -58,7 +58,13 @@ final class WorldDatabaseController {
 		return worlds;
 	}
 
-	private Integer boundQueryCount(final Integer raw) {
+	private Integer boundQueryCount(final String rawString) {
+                Integer raw;
+                try {
+                       raw = Integer.parseInt(rawString);
+                } catch (NumberFormatException e) {
+                       raw = null;
+                } 
 		if (raw == null || raw < 1) {
 			return 1;
 		} else if (raw > 500) {

+ 3 - 2
frameworks/Lua/leda/app.lua

@@ -1,7 +1,7 @@
-local http = require('leda.http')
+local http = require('leda.server.http')
 local json = require('cjson')
 
-local server = http.Server(8080, '')
+local server = http(8080, 'localhost')
 
 server.request = function(server, request, response)
     local url = request:url() 
@@ -11,4 +11,5 @@ server.request = function(server, request, response)
     elseif url:find('/plaintext') then    
         response.body =  'Hello, World!'
     end
+    response:send()
 end

+ 4 - 7
frameworks/Lua/leda/install.sh

@@ -4,12 +4,9 @@ fw_depends lua
 
 sudo luarocks install lua-cjson
 
-wget -O leda.tar.gz http://sergeyzavadski.github.io/leda/releases/leda-0.5.4/leda-0.5.4.tar.gz 
-fw_untar leda.tar.gz
-cd leda-0.5.4
-
+git clone https://github.com/sergeyzavadski/leda.git
+cd leda
+git checkout d1d805877c506e34d23d5aac2b27608c192695d3
 ./configure
 make 
-sudo make install
-cd .. 
-mv leda-0.5.4 leda
+sudo make install

+ 1 - 0
frameworks/Nimrod/jester/bash_profile.sh

@@ -0,0 +1 @@
+export JESTER_PATH=${IROOT}/jester

+ 3 - 2
frameworks/Nimrod/jester/config/nginx.conf

@@ -71,8 +71,9 @@ http {
     #try_files $uri/index.html $uri.html $uri @app;
 
     location / {
-      include /usr/local/nginx/conf/scgi_params;
-      scgi_pass nimrod;
+      #include /usr/local/nginx/conf/scgi_params;
+      #scgi_pass nimrod;
+      proxy_pass http://nimrod;
     }
 
   }

+ 9 - 7
frameworks/Nimrod/jester/hello.nim

@@ -1,9 +1,11 @@
-import jester, strtabs, json, asyncio, sockets, os, strutils
+import jester, strtabs, json, asyncdispatch, os, strutils
 
-get "/json":
-  var obj = %{"message": %"Hello, World!"}
-  resp($obj, "application/json")
+let port = Port(paramStr(1).parseInt)
+let settings = newSettings(port=port, http=true)
 
-var disp = newDispatcher()
-disp.register(port = TPort(paramStr(1).parseInt), http=false)
-while disp.poll(): nil
+routes:
+  get "/json":
+    var obj = %{"message": %"Hello, World!"}
+    resp($obj, "application/json")
+
+runForever()

+ 1 - 1
frameworks/Nimrod/jester/install.sh

@@ -1,3 +1,3 @@
 #!/bin/bash
 
-fw_depends jester nimrod nginx 
+fw_depends nimrod nginx jester

+ 2 - 2
frameworks/Nimrod/jester/setup.py

@@ -7,8 +7,8 @@ from os.path import expanduser
 home = expanduser("~")
 
 def start(args, logfile, errfile):
-  subprocess.check_call("nimrod c -d:release --path:../installs/jester/jester hello.nim", shell=True, cwd="jester", stderr=errfile, stdout=logfile)
-  subprocess.check_call("sudo /usr/local/nginx/sbin/nginx -c " + home + "/FrameworkBenchmarks/jester/config/nginx.conf", shell=True, stderr=errfile, stdout=logfile)
+  subprocess.check_call("nim c -d:release --path:$JESTER_PATH hello.nim", shell=True, cwd="jester", stderr=errfile, stdout=logfile)
+  subprocess.check_call("sudo /usr/local/nginx/sbin/nginx -c $TROOT/config/nginx.conf", shell=True, stderr=errfile, stdout=logfile)
   
   for i in range(0, 8):
     subprocess.Popen("./hello 900" + str(i), shell=True, cwd="jester", stderr=errfile, stdout=logfile)

+ 0 - 1
frameworks/Nimrod/jester/source_code

@@ -1 +0,0 @@
-./jester/hello.nim

+ 14 - 3
frameworks/Nimrod/nawak/app.nim

@@ -1,6 +1,8 @@
-import strtabs, strutils, math, algorithm
+import os, strtabs, strutils, math, algorithm
 import nawak_mongrel, jdump
-import fortunes_tmpl
+import model, fortunes_tmpl
+when not defined(postgre_model) xor defined(redis_model):
+    {.error: "please pass either -d:postgre_model or -d:redis_model to the compiler".}
 when defined(postgre_model):
     import model_postgre
 when defined(redis_model):
@@ -67,4 +69,13 @@ custom_page 404:
     return response(404, """Nah, I've got nothing.<br>
                             Here's a <b>404 Page Not Found</b> error for you.""")
 
-run(init=init_db, nb_threads=256)
+var nb_workers = 32
+if paramCount() > 0:
+    try:
+        nb_workers = paramStr(1).parseInt
+    except ValueError:
+        echo "Usage: app [number of workers]"
+        echo "       Will start with 32 workers by default"
+echo "Starting with " & $nb_workers & " workers"
+
+run(init=init_db, nb_threads=nb_workers)

+ 1 - 0
frameworks/Nimrod/nawak/bash_profile.sh

@@ -0,0 +1 @@
+export NAWAK_PATH=${IROOT}/nawak

+ 1 - 7
frameworks/Nimrod/nawak/conf/mongrel2.conf

@@ -1,10 +1,8 @@
 # this is the minimal config required for mongrel2
 micro_framework = Handler(
                           send_spec='tcp://127.0.0.1:9999',
-                          #send_spec='ipc:///tmp/requests.mongrel.ipc',
                           send_ident='0138a43-micro-nimrod',
                           recv_spec='tcp://127.0.0.1:9998',
-                          #recv_spec='ipc:///tmp/responses.mongrel.ipc',
                           #protocol='tnetstring', # default to json
                           recv_ident='')
 
@@ -25,10 +23,6 @@ main = Server(
 )
 
 settings = {"zeromq.threads": 1,
-            "disable.access_logging": 1,
-            "limits.min_ping": 0,
-            "limits.min_write_rate": 0,
-            "limits.min_read_rate": 0,
-            "limits.kill_limit": 2}
+            "disable.access_logging": 1}
 
 servers = [main]

+ 1 - 1
frameworks/Nimrod/nawak/fortunes_tmpl.nim

@@ -1,5 +1,5 @@
 #! stdtmpl | standard
-#import lib/escape
+#from xmltree import escape
 #import model
 #proc fortunes_tmpl*(fortunes: openArray[TFortune]): string =
 #  result = ""

+ 1 - 1
frameworks/Nimrod/nawak/install.sh

@@ -1,3 +1,3 @@
 #!/bin/bash
 
-fw_depends nawak nimrod mongrel2
+fw_depends nimrod mongrel2 nawak

+ 0 - 271
frameworks/Nimrod/nawak/lib/db_postgres_redone.nim

@@ -1,271 +0,0 @@
-#
-#
-#            Nimrod's Runtime Library
-#        (c) Copyright 2012 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-## A higher level `PostgreSQL`:idx: database wrapper. This interface 
-## is implemented for other databases too.
-
-import strutils, postgres_redone
-
-type
-  TDbConn* = PPGconn   ## encapsulates a database connection
-  TRow* = seq[string]  ## a row of a dataset. NULL database values will be
-                       ## transformed always to the empty string.
-  EDb* = object of EIO ## exception that is raised if a database error occurs
-  
-  TSqlQuery* = distinct string ## an SQL query string
-  TPreparedId* = distinct string ## a identifier for the prepared queries
-
-  FDb* = object of FIO ## effect that denotes a database operation
-  FReadDb* = object of FDB   ## effect that denotes a read operation
-  FWriteDb* = object of FDB  ## effect that denotes a write operation
-  
-proc sql*(query: string): TSqlQuery {.noSideEffect, inline.} =  
-  ## constructs a TSqlQuery from the string `query`. This is supposed to be 
-  ## used as a raw-string-literal modifier:
-  ## ``sql"update user set counter = counter + 1"``
-  ##
-  ## If assertions are turned off, it does nothing. If assertions are turned 
-  ## on, later versions will check the string for valid syntax.
-  result = TSqlQuery(query)
- 
-proc dbError*(db: TDbConn) {.noreturn.} = 
-  ## raises an EDb exception.
-  var e: ref EDb
-  new(e)
-  e.msg = $PQerrorMessage(db)
-  raise e
-
-proc dbError*(msg: string) {.noreturn.} = 
-  ## raises an EDb exception with message `msg`.
-  var e: ref EDb
-  new(e)
-  e.msg = msg
-  raise e
-
-proc dbQuote(s: string): string =
-  result = "'"
-  for c in items(s):
-    if c == '\'': add(result, "''")
-    else: add(result, c)
-  add(result, '\'')
-
-proc dbFormat(formatstr: TSqlQuery, args: varargs[string]): string =
-  result = ""
-  var a = 0
-  for c in items(string(formatstr)):
-    if c == '?':
-      add(result, dbQuote(args[a]))
-      inc(a)
-    else: 
-      add(result, c)
-  
-proc TryExec*(db: TDbConn, query: TSqlQuery, 
-              args: varargs[string, `$`]): bool {.tags: [FReadDB, FWriteDb].} =
-  ## tries to execute the query and returns true if successful, false otherwise.
-  var q = dbFormat(query, args)
-  var res = PQExec(db, q)
-  result = PQresultStatus(res) == PGRES_COMMAND_OK
-  PQclear(res)
-
-proc ExecNo*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]) {.
-  tags: [FReadDB, FWriteDb].} =
-  ## executes the query and raises EDB if not successful.
-  var q = dbFormat(query, args)
-  var res = PQExec(db, q)
-  if PQresultStatus(res) != PGRES_COMMAND_OK: dbError(db)
-  PQclear(res)
-
-var nullPOid: POid
-var nowhere: ptr int32
-proc Exec*(db: TDbConn, stmtName: TPreparedId,
-          args: varargs[string]) {.tags: [FReadDB, FWriteDb].} =
-    var arr = allocCStringArray(args)
-
-    var res = PQexecPrepared(db, stmtName.string, int32(args.len), arr,
-                            nowhere, nowhere, 0)
-
-    deallocCStringArray(arr)
-    if PQResultStatus(res) != PGRES_COMMAND_OK: dbError(db)
-    PQclear(res)
-
-  
-proc newRow(L: int): TRow =
-  newSeq(result, L)
-  for i in 0..L-1: result[i] = ""
-  
-proc setupQueryNo(db: TDbConn, query: TSqlQuery, 
-                args: varargs[string]): PPGresult = 
-  var q = dbFormat(query, args)
-  result = PQExec(db, q)
-  if PQresultStatus(result) != PGRES_TUPLES_OK: dbError(db)
-
-
-proc setupQuery(db: TDbConn, query: string,
-                args: varargs[string]): PPGresult =
-    # read this for details:
-    # http://www.postgresql.org/docs/9.3/interactive/libpq-exec.html
-    var arr = allocCStringArray(args)
-
-    result = PQexecParams(db, query, int32(args.len), nullPOid, arr, nowhere, nowhere, 0)
-
-    deallocCStringArray(arr)
-    if PQResultStatus(result) != PGRES_TUPLES_OK: dbError(db)
-
-proc setupPQuery(db: TDbConn, stmtName: TPreparedId,
-                args: varargs[string]): PPGresult =
-    var arr = allocCStringArray(args)
-
-    result = PQexecPrepared(db, stmtName.string, int32(args.len), arr,
-                            nowhere, nowhere, 0)
-
-    deallocCStringArray(arr)
-    if PQResultStatus(result) != PGRES_TUPLES_OK: dbError(db)
-
-proc prepare*(db: TDbConn; stmtName, query: string; nParams: int): TPreparedId =
-    var res = PQprepare(db, stmtName, query, int32(nParams), nullPOid)
-    if PQResultStatus(res) != PGRES_COMMAND_OK: dbError(db)
-    return TPreparedId(stmtName)
-   
-proc setRow(res: PPGresult, r: var TRow, line, cols: int32) =
-  for col in 0..cols-1:
-    setLen(r[col], 0)
-    var x = PQgetvalue(res, line, col)
-    add(r[col], x)
-
-iterator FastPRows*(db: TDbConn, stmtName: TPreparedId,
-                   args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
-  ## executes the query and iterates over the result dataset. This is very 
-  ## fast, but potenially dangerous: If the for-loop-body executes another
-  ## query, the results can be undefined. For Postgres it is safe though.
-  var res = setupPQuery(db, stmtName, args)
-  var L = PQnfields(res)
-  var result = newRow(L)
-  for i in 0..PQntuples(res)-1:
-    setRow(res, result, i, L)
-    yield result
-  PQclear(res)
-
-iterator FastRows*(db: TDbConn, query: string,
-                   args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
-  ## executes the query and iterates over the result dataset. This is very 
-  ## fast, but potenially dangerous: If the for-loop-body executes another
-  ## query, the results can be undefined. For Postgres it is safe though.
-  var res = setupQuery(db, query, args)
-  var L = PQnfields(res)
-  var result = newRow(L)
-  for i in 0..PQntuples(res)-1:
-    setRow(res, result, i, L)
-    yield result
-  PQclear(res)
-
-proc getPRow*(db: TDbConn, stmtName: TPreparedId,
-              args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
-    var res = setupPQuery(db, stmtName, args)
-    var L = PQnfields(res)
-    result = newRow(L)
-    setRow(res, result, 0, L)
-    PQclear(res)
-
-proc getRow*(db: TDbConn, query: string,
-             args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
-  ## retrieves a single row. If the query doesn't return any rows, this proc
-  ## will return a TRow with empty strings for each column.
-  var res = setupQuery(db, query, args)
-  var L = PQnfields(res)
-  result = newRow(L)
-  setRow(res, result, 0, L)
-  PQclear(res)
-
-proc GetAllPRows*(db: TDbConn, stmtName: TPreparedId,
-                 args: varargs[string, `$`]): seq[TRow] {.tags: [FReadDB].} =
-  ## executes the query and returns the whole result dataset.
-  result = @[]
-  for r in FastPRows(db, stmtName, args):
-    result.add(r)
-
-proc GetAllRows*(db: TDbConn, query: string, 
-                 args: varargs[string, `$`]): seq[TRow] {.tags: [FReadDB].} =
-  ## executes the query and returns the whole result dataset.
-  result = @[]
-  for r in FastRows(db, query, args):
-    result.add(r)
-
-iterator Rows*(db: TDbConn, query: string, 
-               args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
-  ## same as `FastRows`, but slower and safe.
-  for r in items(GetAllRows(db, query, args)): yield r
-
-proc GetValue*(db: TDbConn, query: string, 
-               args: varargs[string, `$`]): string {.tags: [FReadDB].} = 
-  ## executes the query and returns the first column of the first row of the
-  ## result dataset. Returns "" if the dataset contains no rows or the database
-  ## value is NULL.
-  var x = PQgetvalue(setupQuery(db, query, args), 0, 0)
-  result = if isNil(x): "" else: $x
-  
-proc TryInsertID*(db: TDbConn, query: string, 
-                  args: varargs[string, `$`]): int64  {.tags: [FWriteDb].}=
-  ## executes the query (typically "INSERT") and returns the 
-  ## generated ID for the row or -1 in case of an error. For Postgre this adds
-  ## ``RETURNING id`` to the query, so it only works if your primary key is
-  ## named ``id``. 
-  var x = PQgetvalue(setupQuery(db, query & " RETURNING id", 
-    args), 0, 0)
-  if not isNil(x):
-    result = ParseBiggestInt($x)
-  else:
-    result = -1
-
-proc InsertID*(db: TDbConn, query: string, 
-               args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} =
-  ## executes the query (typically "INSERT") and returns the 
-  ## generated ID for the row. For Postgre this adds
-  ## ``RETURNING id`` to the query, so it only works if your primary key is
-  ## named ``id``. 
-  result = TryInsertID(db, query, args)
-  if result < 0: dbError(db)
-  
-proc ExecAffectedRows*(db: TDbConn, query: TSqlQuery, 
-                       args: varargs[string, `$`]): int64 {.tags: [
-                       FReadDB, FWriteDb].} = 
-  ## executes the query (typically "UPDATE") and returns the
-  ## number of affected rows.
-  var q = dbFormat(query, args)
-  var res = PQExec(db, q)
-  if PQresultStatus(res) != PGRES_COMMAND_OK: dbError(db)
-  result = parseBiggestInt($PQcmdTuples(res))
-  PQclear(res)
-
-proc Close*(db: TDbConn) {.tags: [FDb].} = 
-  ## closes the database connection.
-  if db != nil: PQfinish(db)
-
-proc Open*(connection, user, password, database: string): TDbConn {.
-  tags: [FDb].} =
-  ## opens a database connection. Raises `EDb` if the connection could not
-  ## be established.
-  ##
-  ## Clients can also use Postgres keyword/value connection strings to
-  ## connect.
-  ##
-  ## Example:
-  ##
-  ## .. code-block:: nimrod
-  ##
-  ##      con = Open("", "", "", "host=localhost port=5432 dbname=mydb")
-  ##
-  ## See http://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING
-  ## for more information.
-  ##
-  ## Note that the connection parameter is not used but exists to maintain
-  ## the nimrod db api.
-  result = PQsetdbLogin(nil, nil, nil, nil, database, user, password)
-  if PQStatus(result) != CONNECTION_OK: dbError(result) # result = nil
-
-

+ 0 - 33
frameworks/Nimrod/nawak/lib/escape.nim

@@ -1,33 +0,0 @@
-# from Nimrod's Runtime Library - xmltree
-# (c) Copyright 2012 Andreas Rumpf
-# Modifications by Erwan Ameil
-
-proc addEscaped*(result: var string, s: string) = 
-  ## same as ``result.add(escape(s))``, but more efficient.
-  for c in items(s):
-    case c
-    of '<': result.add("&lt;")
-    of '>': result.add("&gt;")
-    of '&': result.add("&amp;")
-    of '"': result.add("&quot;")
-    of '\'': result.add("&#x27;")
-    of '/': result.add("&#x2F;")
-    else: result.add(c)
-
-proc escape*(s: string): string = 
-  ## escapes `s` for inclusion into an XML document. 
-  ## Escapes these characters:
-  ##
-  ## ------------    -------------------
-  ## char            is converted to
-  ## ------------    -------------------
-  ##  ``<``          ``&lt;``
-  ##  ``>``          ``&gt;``
-  ##  ``&``          ``&amp;``
-  ##  ``"``          ``&quot;``
-  ##  ``'``          ``&#x27;``
-  ##  ``/``          ``&#x2F;``
-  ## ------------    -------------------
-  result = newStringOfCap(s.len)
-  addEscaped(result, s)
- 

+ 0 - 352
frameworks/Nimrod/nawak/lib/postgres_redone.nim

@@ -1,352 +0,0 @@
-# This module contains the definitions for structures and externs for
-# functions used by frontend postgres applications. It is based on
-# Postgresql's libpq-fe.h.
-#
-# It is for postgreSQL version 7.4 and higher with support for the v3.0
-# connection-protocol.
-#
-
-{.deadCodeElim: on.}
-
-when defined(windows): 
-  const 
-    dllName = "libpq.dll"
-elif defined(macosx): 
-  const 
-    dllName = "libpq.dylib"
-else: 
-  const 
-    dllName = "libpq.so(.5|)"
-type 
-  POid* = ptr Oid
-  Oid* = int32
-
-const 
-  ERROR_MSG_LENGTH* = 4096
-  CMDSTATUS_LEN* = 40
-
-type 
-  TSockAddr* = array[1..112, int8]
-  TPGresAttDesc*{.pure, final.} = object 
-    name*: cstring
-    adtid*: Oid
-    adtsize*: int
-
-  PPGresAttDesc* = ptr TPGresAttDesc
-  PPPGresAttDesc* = ptr PPGresAttDesc
-  TPGresAttValue*{.pure, final.} = object 
-    length*: int32
-    value*: cstring
-
-  PPGresAttValue* = ptr TPGresAttValue
-  PPPGresAttValue* = ptr PPGresAttValue
-  PExecStatusType* = ptr TExecStatusType
-  TExecStatusType* = enum 
-    PGRES_EMPTY_QUERY = 0, PGRES_COMMAND_OK, PGRES_TUPLES_OK, PGRES_COPY_OUT, 
-    PGRES_COPY_IN, PGRES_BAD_RESPONSE, PGRES_NONFATAL_ERROR, PGRES_FATAL_ERROR
-  TPGlobjfuncs*{.pure, final.} = object 
-    fn_lo_open*: Oid
-    fn_lo_close*: Oid
-    fn_lo_creat*: Oid
-    fn_lo_unlink*: Oid
-    fn_lo_lseek*: Oid
-    fn_lo_tell*: Oid
-    fn_lo_read*: Oid
-    fn_lo_write*: Oid
-
-  PPGlobjfuncs* = ptr TPGlobjfuncs
-  PConnStatusType* = ptr TConnStatusType
-  TConnStatusType* = enum 
-    CONNECTION_OK, CONNECTION_BAD, CONNECTION_STARTED, CONNECTION_MADE, 
-    CONNECTION_AWAITING_RESPONSE, CONNECTION_AUTH_OK, CONNECTION_SETENV, 
-    CONNECTION_SSL_STARTUP, CONNECTION_NEEDED
-  TPGconn*{.pure, final.} = object 
-    pghost*: cstring
-    pgtty*: cstring
-    pgport*: cstring
-    pgoptions*: cstring
-    dbName*: cstring
-    status*: TConnStatusType
-    errorMessage*: array[0..(ERROR_MSG_LENGTH) - 1, char]
-    Pfin*: TFile
-    Pfout*: TFile
-    Pfdebug*: TFile
-    sock*: int32
-    laddr*: TSockAddr
-    raddr*: TSockAddr
-    salt*: array[0..(2) - 1, char]
-    asyncNotifyWaiting*: int32
-    notifyList*: pointer
-    pguser*: cstring
-    pgpass*: cstring
-    lobjfuncs*: PPGlobjfuncs
-
-  PPGconn* = ptr TPGconn
-  TPGresult*{.pure, final.} = object 
-    ntups*: int32
-    numAttributes*: int32
-    attDescs*: PPGresAttDesc
-    tuples*: PPPGresAttValue
-    tupArrSize*: int32
-    resultStatus*: TExecStatusType
-    cmdStatus*: array[0..(CMDSTATUS_LEN) - 1, char]
-    binary*: int32
-    conn*: PPGconn
-
-  PPGresult* = ptr TPGresult
-  PPostgresPollingStatusType* = ptr PostgresPollingStatusType
-  PostgresPollingStatusType* = enum 
-    PGRES_POLLING_FAILED = 0, PGRES_POLLING_READING, PGRES_POLLING_WRITING, 
-    PGRES_POLLING_OK, PGRES_POLLING_ACTIVE
-  PPGTransactionStatusType* = ptr PGTransactionStatusType
-  PGTransactionStatusType* = enum 
-    PQTRANS_IDLE, PQTRANS_ACTIVE, PQTRANS_INTRANS, PQTRANS_INERROR, 
-    PQTRANS_UNKNOWN
-  PPGVerbosity* = ptr PGVerbosity
-  PGVerbosity* = enum 
-    PQERRORS_TERSE, PQERRORS_DEFAULT, PQERRORS_VERBOSE
-  PpgNotify* = ptr pgNotify
-  pgNotify*{.pure, final.} = object 
-    relname*: cstring
-    be_pid*: int32
-    extra*: cstring
-
-  PQnoticeReceiver* = proc (arg: pointer, res: PPGresult){.cdecl.}
-  PQnoticeProcessor* = proc (arg: pointer, message: cstring){.cdecl.}
-  Ppqbool* = ptr pqbool
-  pqbool* = char
-  P_PQprintOpt* = ptr PQprintOpt
-  PQprintOpt*{.pure, final.} = object 
-    header*: pqbool
-    align*: pqbool
-    standard*: pqbool
-    html3*: pqbool
-    expanded*: pqbool
-    pager*: pqbool
-    fieldSep*: cstring
-    tableOpt*: cstring
-    caption*: cstring
-    fieldName*: ptr cstring
-
-  P_PQconninfoOption* = ptr PQconninfoOption
-  PQconninfoOption*{.pure, final.} = object 
-    keyword*: cstring
-    envvar*: cstring
-    compiled*: cstring
-    val*: cstring
-    label*: cstring
-    dispchar*: cstring
-    dispsize*: int32
-
-  PPQArgBlock* = ptr PQArgBlock
-  PQArgBlock*{.pure, final.} = object 
-    length*: int32
-    isint*: int32
-    p*: pointer
-
-
-proc PQconnectStart*(conninfo: cstring): PPGconn{.cdecl, dynlib: dllName, 
-    importc: "PQconnectStart".}
-proc PQconnectPoll*(conn: PPGconn): PostgresPollingStatusType{.cdecl, 
-    dynlib: dllName, importc: "PQconnectPoll".}
-proc PQconnectdb*(conninfo: cstring): PPGconn{.cdecl, dynlib: dllName, 
-    importc: "PQconnectdb".}
-proc PQsetdbLogin*(pghost: cstring, pgport: cstring, pgoptions: cstring, 
-                   pgtty: cstring, dbName: cstring, login: cstring, pwd: cstring): PPGconn{.
-    cdecl, dynlib: dllName, importc: "PQsetdbLogin".}
-proc PQsetdb*(M_PGHOST, M_PGPORT, M_PGOPT, M_PGTTY, M_DBNAME: cstring): ppgconn
-proc PQfinish*(conn: PPGconn){.cdecl, dynlib: dllName, importc: "PQfinish".}
-proc PQconndefaults*(): PPQconninfoOption{.cdecl, dynlib: dllName, 
-    importc: "PQconndefaults".}
-proc PQconninfoFree*(connOptions: PPQconninfoOption){.cdecl, dynlib: dllName, 
-    importc: "PQconninfoFree".}
-proc PQresetStart*(conn: PPGconn): int32{.cdecl, dynlib: dllName, 
-    importc: "PQresetStart".}
-proc PQresetPoll*(conn: PPGconn): PostgresPollingStatusType{.cdecl, 
-    dynlib: dllName, importc: "PQresetPoll".}
-proc PQreset*(conn: PPGconn){.cdecl, dynlib: dllName, importc: "PQreset".}
-proc PQrequestCancel*(conn: PPGconn): int32{.cdecl, dynlib: dllName, 
-    importc: "PQrequestCancel".}
-proc PQdb*(conn: PPGconn): cstring{.cdecl, dynlib: dllName, importc: "PQdb".}
-proc PQuser*(conn: PPGconn): cstring{.cdecl, dynlib: dllName, importc: "PQuser".}
-proc PQpass*(conn: PPGconn): cstring{.cdecl, dynlib: dllName, importc: "PQpass".}
-proc PQhost*(conn: PPGconn): cstring{.cdecl, dynlib: dllName, importc: "PQhost".}
-proc PQport*(conn: PPGconn): cstring{.cdecl, dynlib: dllName, importc: "PQport".}
-proc PQtty*(conn: PPGconn): cstring{.cdecl, dynlib: dllName, importc: "PQtty".}
-proc PQoptions*(conn: PPGconn): cstring{.cdecl, dynlib: dllName, 
-    importc: "PQoptions".}
-proc PQstatus*(conn: PPGconn): TConnStatusType{.cdecl, dynlib: dllName, 
-    importc: "PQstatus".}
-proc PQtransactionStatus*(conn: PPGconn): PGTransactionStatusType{.cdecl, 
-    dynlib: dllName, importc: "PQtransactionStatus".}
-proc PQparameterStatus*(conn: PPGconn, paramName: cstring): cstring{.cdecl, 
-    dynlib: dllName, importc: "PQparameterStatus".}
-proc PQprotocolVersion*(conn: PPGconn): int32{.cdecl, dynlib: dllName, 
-    importc: "PQprotocolVersion".}
-proc PQerrorMessage*(conn: PPGconn): cstring{.cdecl, dynlib: dllName, 
-    importc: "PQerrorMessage".}
-proc PQsocket*(conn: PPGconn): int32{.cdecl, dynlib: dllName, 
-                                      importc: "PQsocket".}
-proc PQbackendPID*(conn: PPGconn): int32{.cdecl, dynlib: dllName, 
-    importc: "PQbackendPID".}
-proc PQclientEncoding*(conn: PPGconn): int32{.cdecl, dynlib: dllName, 
-    importc: "PQclientEncoding".}
-proc PQsetClientEncoding*(conn: PPGconn, encoding: cstring): int32{.cdecl, 
-    dynlib: dllName, importc: "PQsetClientEncoding".}
-when defined(USE_SSL): 
-  # Get the SSL structure associated with a connection  
-  proc PQgetssl*(conn: PPGconn): PSSL{.cdecl, dynlib: dllName, 
-                                       importc: "PQgetssl".}
-proc PQsetErrorVerbosity*(conn: PPGconn, verbosity: PGVerbosity): PGVerbosity{.
-    cdecl, dynlib: dllName, importc: "PQsetErrorVerbosity".}
-proc PQtrace*(conn: PPGconn, debug_port: TFile){.cdecl, dynlib: dllName, 
-    importc: "PQtrace".}
-proc PQuntrace*(conn: PPGconn){.cdecl, dynlib: dllName, importc: "PQuntrace".}
-proc PQsetNoticeReceiver*(conn: PPGconn, theProc: PQnoticeReceiver, arg: pointer): PQnoticeReceiver{.
-    cdecl, dynlib: dllName, importc: "PQsetNoticeReceiver".}
-proc PQsetNoticeProcessor*(conn: PPGconn, theProc: PQnoticeProcessor, 
-                           arg: pointer): PQnoticeProcessor{.cdecl, 
-    dynlib: dllName, importc: "PQsetNoticeProcessor".}
-proc PQexec*(conn: PPGconn, query: cstring): PPGresult{.cdecl, dynlib: dllName, 
-    importc: "PQexec".}
-proc PQexecParams*(conn: PPGconn, command: cstring, nParams: int32, 
-                   paramTypes: POid, paramValues: cstringArray, 
-                   paramLengths, paramFormats: ptr int32, resultFormat: int32): PPGresult{.
-    cdecl, dynlib: dllName, importc: "PQexecParams".}
-proc PQprepare*(conn: PPGconn, stmtName, query: cstring, nParams: int32,
-    paramTypes: POid): PPGresult{.cdecl, dynlib: dllName, importc: "PQprepare".}
-proc PQexecPrepared*(conn: PPGconn, stmtName: cstring, nParams: int32, 
-                     paramValues: cstringArray, 
-                     paramLengths, paramFormats: ptr int32, resultFormat: int32): PPGresult{.
-    cdecl, dynlib: dllName, importc: "PQexecPrepared".}
-proc PQsendQuery*(conn: PPGconn, query: cstring): int32{.cdecl, dynlib: dllName, 
-    importc: "PQsendQuery".}
-proc PQsendQueryParams*(conn: PPGconn, command: cstring, nParams: int32, 
-                        paramTypes: POid, paramValues: cstringArray, 
-                        paramLengths, paramFormats: ptr int32, 
-                        resultFormat: int32): int32{.cdecl, dynlib: dllName, 
-    importc: "PQsendQueryParams".}
-proc PQsendQueryPrepared*(conn: PPGconn, stmtName: cstring, nParams: int32, 
-                          paramValues: cstringArray, 
-                          paramLengths, paramFormats: ptr int32, 
-                          resultFormat: int32): int32{.cdecl, dynlib: dllName, 
-    importc: "PQsendQueryPrepared".}
-proc PQgetResult*(conn: PPGconn): PPGresult{.cdecl, dynlib: dllName, 
-    importc: "PQgetResult".}
-proc PQisBusy*(conn: PPGconn): int32{.cdecl, dynlib: dllName, 
-                                      importc: "PQisBusy".}
-proc PQconsumeInput*(conn: PPGconn): int32{.cdecl, dynlib: dllName, 
-    importc: "PQconsumeInput".}
-proc PQnotifies*(conn: PPGconn): PPGnotify{.cdecl, dynlib: dllName, 
-    importc: "PQnotifies".}
-proc PQputCopyData*(conn: PPGconn, buffer: cstring, nbytes: int32): int32{.
-    cdecl, dynlib: dllName, importc: "PQputCopyData".}
-proc PQputCopyEnd*(conn: PPGconn, errormsg: cstring): int32{.cdecl, 
-    dynlib: dllName, importc: "PQputCopyEnd".}
-proc PQgetCopyData*(conn: PPGconn, buffer: cstringArray, async: int32): int32{.
-    cdecl, dynlib: dllName, importc: "PQgetCopyData".}
-proc PQgetline*(conn: PPGconn, str: cstring, len: int32): int32{.cdecl, 
-    dynlib: dllName, importc: "PQgetline".}
-proc PQputline*(conn: PPGconn, str: cstring): int32{.cdecl, dynlib: dllName, 
-    importc: "PQputline".}
-proc PQgetlineAsync*(conn: PPGconn, buffer: cstring, bufsize: int32): int32{.
-    cdecl, dynlib: dllName, importc: "PQgetlineAsync".}
-proc PQputnbytes*(conn: PPGconn, buffer: cstring, nbytes: int32): int32{.cdecl, 
-    dynlib: dllName, importc: "PQputnbytes".}
-proc PQendcopy*(conn: PPGconn): int32{.cdecl, dynlib: dllName, 
-                                       importc: "PQendcopy".}
-proc PQsetnonblocking*(conn: PPGconn, arg: int32): int32{.cdecl, 
-    dynlib: dllName, importc: "PQsetnonblocking".}
-proc PQisnonblocking*(conn: PPGconn): int32{.cdecl, dynlib: dllName, 
-    importc: "PQisnonblocking".}
-proc PQflush*(conn: PPGconn): int32{.cdecl, dynlib: dllName, importc: "PQflush".}
-proc PQfn*(conn: PPGconn, fnid: int32, result_buf, result_len: ptr int32, 
-           result_is_int: int32, args: PPQArgBlock, nargs: int32): PPGresult{.
-    cdecl, dynlib: dllName, importc: "PQfn".}
-proc PQresultStatus*(res: PPGresult): TExecStatusType{.cdecl, dynlib: dllName, 
-    importc: "PQresultStatus".}
-proc PQresStatus*(status: TExecStatusType): cstring{.cdecl, dynlib: dllName, 
-    importc: "PQresStatus".}
-proc PQresultErrorMessage*(res: PPGresult): cstring{.cdecl, dynlib: dllName, 
-    importc: "PQresultErrorMessage".}
-proc PQresultErrorField*(res: PPGresult, fieldcode: int32): cstring{.cdecl, 
-    dynlib: dllName, importc: "PQresultErrorField".}
-proc PQntuples*(res: PPGresult): int32{.cdecl, dynlib: dllName, 
-                                        importc: "PQntuples".}
-proc PQnfields*(res: PPGresult): int32{.cdecl, dynlib: dllName, 
-                                        importc: "PQnfields".}
-proc PQbinaryTuples*(res: PPGresult): int32{.cdecl, dynlib: dllName, 
-    importc: "PQbinaryTuples".}
-proc PQfname*(res: PPGresult, field_num: int32): cstring{.cdecl, 
-    dynlib: dllName, importc: "PQfname".}
-proc PQfnumber*(res: PPGresult, field_name: cstring): int32{.cdecl, 
-    dynlib: dllName, importc: "PQfnumber".}
-proc PQftable*(res: PPGresult, field_num: int32): Oid{.cdecl, dynlib: dllName, 
-    importc: "PQftable".}
-proc PQftablecol*(res: PPGresult, field_num: int32): int32{.cdecl, 
-    dynlib: dllName, importc: "PQftablecol".}
-proc PQfformat*(res: PPGresult, field_num: int32): int32{.cdecl, 
-    dynlib: dllName, importc: "PQfformat".}
-proc PQftype*(res: PPGresult, field_num: int32): Oid{.cdecl, dynlib: dllName, 
-    importc: "PQftype".}
-proc PQfsize*(res: PPGresult, field_num: int32): int32{.cdecl, dynlib: dllName, 
-    importc: "PQfsize".}
-proc PQfmod*(res: PPGresult, field_num: int32): int32{.cdecl, dynlib: dllName, 
-    importc: "PQfmod".}
-proc PQcmdStatus*(res: PPGresult): cstring{.cdecl, dynlib: dllName, 
-    importc: "PQcmdStatus".}
-proc PQoidStatus*(res: PPGresult): cstring{.cdecl, dynlib: dllName, 
-    importc: "PQoidStatus".}
-proc PQoidValue*(res: PPGresult): Oid{.cdecl, dynlib: dllName, 
-                                       importc: "PQoidValue".}
-proc PQcmdTuples*(res: PPGresult): cstring{.cdecl, dynlib: dllName, 
-    importc: "PQcmdTuples".}
-proc PQgetvalue*(res: PPGresult, tup_num: int32, field_num: int32): cstring{.
-    cdecl, dynlib: dllName, importc: "PQgetvalue".}
-proc PQgetlength*(res: PPGresult, tup_num: int32, field_num: int32): int32{.
-    cdecl, dynlib: dllName, importc: "PQgetlength".}
-proc PQgetisnull*(res: PPGresult, tup_num: int32, field_num: int32): int32{.
-    cdecl, dynlib: dllName, importc: "PQgetisnull".}
-proc PQclear*(res: PPGresult){.cdecl, dynlib: dllName, importc: "PQclear".}
-proc PQfreemem*(p: pointer){.cdecl, dynlib: dllName, importc: "PQfreemem".}
-proc PQmakeEmptyPGresult*(conn: PPGconn, status: TExecStatusType): PPGresult{.
-    cdecl, dynlib: dllName, importc: "PQmakeEmptyPGresult".}
-proc PQescapeString*(till, `from`: cstring, len: int): int{.cdecl, 
-    dynlib: dllName, importc: "PQescapeString".}
-proc PQescapeBytea*(bintext: cstring, binlen: int, bytealen: var int): cstring{.
-    cdecl, dynlib: dllName, importc: "PQescapeBytea".}
-proc PQunescapeBytea*(strtext: cstring, retbuflen: var int): cstring{.cdecl, 
-    dynlib: dllName, importc: "PQunescapeBytea".}
-proc PQprint*(fout: TFile, res: PPGresult, ps: PPQprintOpt){.cdecl, 
-    dynlib: dllName, importc: "PQprint".}
-proc PQdisplayTuples*(res: PPGresult, fp: TFile, fillAlign: int32, 
-                      fieldSep: cstring, printHeader: int32, quiet: int32){.
-    cdecl, dynlib: dllName, importc: "PQdisplayTuples".}
-proc PQprintTuples*(res: PPGresult, fout: TFile, printAttName: int32, 
-                    terseOutput: int32, width: int32){.cdecl, dynlib: dllName, 
-    importc: "PQprintTuples".}
-proc lo_open*(conn: PPGconn, lobjId: Oid, mode: int32): int32{.cdecl, 
-    dynlib: dllName, importc: "lo_open".}
-proc lo_close*(conn: PPGconn, fd: int32): int32{.cdecl, dynlib: dllName, 
-    importc: "lo_close".}
-proc lo_read*(conn: PPGconn, fd: int32, buf: cstring, length: int): int32{.
-    cdecl, dynlib: dllName, importc: "lo_read".}
-proc lo_write*(conn: PPGconn, fd: int32, buf: cstring, length: int): int32{.
-    cdecl, dynlib: dllName, importc: "lo_write".}
-proc lo_lseek*(conn: PPGconn, fd: int32, offset: int32, whence: int32): int32{.
-    cdecl, dynlib: dllName, importc: "lo_lseek".}
-proc lo_creat*(conn: PPGconn, mode: int32): Oid{.cdecl, dynlib: dllName, 
-    importc: "lo_creat".}
-proc lo_tell*(conn: PPGconn, fd: int32): int32{.cdecl, dynlib: dllName, 
-    importc: "lo_tell".}
-proc lo_unlink*(conn: PPGconn, lobjId: Oid): int32{.cdecl, dynlib: dllName, 
-    importc: "lo_unlink".}
-proc lo_import*(conn: PPGconn, filename: cstring): Oid{.cdecl, dynlib: dllName, 
-    importc: "lo_import".}
-proc lo_export*(conn: PPGconn, lobjId: Oid, filename: cstring): int32{.cdecl, 
-    dynlib: dllName, importc: "lo_export".}
-proc PQmblen*(s: cstring, encoding: int32): int32{.cdecl, dynlib: dllName, 
-    importc: "PQmblen".}
-proc PQenv2encoding*(): int32{.cdecl, dynlib: dllName, importc: "PQenv2encoding".}
-proc PQsetdb(M_PGHOST, M_PGPORT, M_PGOPT, M_PGTTY, M_DBNAME: cstring): ppgconn = 
-  result = PQsetdbLogin(M_PGHOST, M_PGPORT, M_PGOPT, M_PGTTY, M_DBNAME, "", "")

+ 10 - 17
frameworks/Nimrod/nawak/model_postgre.nim

@@ -1,21 +1,14 @@
-import strutils
-# The following import belongs to the stdlib, but has been updated to support
-# queries with parameters (that are safer to counter SQL injections) and
-# prepared queries.
-# It will be merged eventually. For now, I included it in the repository.
-import lib/db_postgres_redone
-
+import strutils, db_postgres
 import model
-export model
 
-const qworld = "SELECT id, randomNumber FROM World WHERE id = $1"
-const qfortunes = "SELECT id, message FROM Fortune"
-const qupdates = "UPDATE World SET randomNumber = $1 WHERE id = $2"
+const qworld = sql"SELECT id, randomNumber FROM World WHERE id = $1"
+const qfortunes = sql"SELECT id, message FROM Fortune"
+const qupdates = sql"UPDATE World SET randomNumber = $1 WHERE id = $2"
 
 var db {.threadvar.}: TDbConn
-var qworld_prepared {.threadvar.}: TPreparedId
-var qfortunes_prepared {.threadvar.}: TPreparedId
-var qupdates_prepared {.threadvar.}: TPreparedId
+var qworld_prepared {.threadvar.}: TSqlPrepared
+var qfortunes_prepared {.threadvar.}: TSqlPrepared
+var qupdates_prepared {.threadvar.}: TSqlPrepared
 
 proc init_db*() {.procvar.} =
     db = open("", "benchmarkdbuser", "benchmarkdbpass",
@@ -29,15 +22,15 @@ proc init_db*() {.procvar.} =
 proc getWorld*(n: int): TWorld =
     #let row = db.getRow(qworld, n)
     ## Yes, prepared queries are faster than unprepared ones
-    let row = db.getPRow(qworld_prepared, n)
+    let row = db.getRow(qworld_prepared, n)
     result.id = parseInt(row[0])
     result.randomNumber = parseInt(row[1])
 
 proc updateWorld*(w: TWorld) =
-    db.Exec(qupdates_prepared, $w.randomNumber, $w.id)
+    db.exec(qupdates_prepared, $w.randomNumber, $w.id)
 
 proc getAllFortunes*(): seq[TFortune] =
-    let rows = db.getAllPRows(qfortunes_prepared)
+    let rows = db.getAllRows(qfortunes_prepared)
     result.newSeq(rows.len)
     for j, row in rows.pairs:
         result[j] = (row[0].parseInt, row[1])

+ 0 - 1
frameworks/Nimrod/nawak/model_redis.nim

@@ -1,6 +1,5 @@
 import strutils, redis
 import model
-export model
 
 var db {.threadvar.}: TRedis
 

+ 8 - 3
frameworks/Nimrod/nawak/setup.py

@@ -11,7 +11,7 @@ def start(args, logfile, errfile):
                           "host=" + args.database_host + " port=5432")
   # compile the app
   subprocess.check_call(
-      "nimrod c --threads:on -d:release -d:postgre_model --path:../installs/nawak/nawak -o:nawak_postgre app.nim",
+      "nim c --threads:on -d:release -d:postgre_model --path:$NAWAK_PATH -o:nawak_postgre app.nim",
       shell=True, cwd="nawak", stderr=errfile, stdout=logfile)
   # launch mongrel2
   subprocess.check_call("mkdir -p run logs tmp", shell=True, cwd="nawak/conf", stderr=errfile, stdout=logfile)
@@ -19,7 +19,12 @@ def start(args, logfile, errfile):
   subprocess.check_call("sudo m2sh start -name test", shell=True, cwd="nawak/conf", stderr=errfile, stdout=logfile)
   
   # launch workers
-  subprocess.Popen("./nawak_postgre", shell=True, cwd="nawak", stderr=errfile, stdout=logfile)
+  if os.environ.get("TRAVIS"):
+    nb_workers = 32
+  else:
+    nb_workers = 256
+  subprocess.Popen("./nawak_postgre " + str(nb_workers),
+                   shell=True, cwd="nawak", stderr=errfile, stdout=logfile)
   return 0
 
 def stop(logfile, errfile):
@@ -27,7 +32,7 @@ def stop(logfile, errfile):
 
   try:
     subprocess.check_call("sudo m2sh stop -every", shell=True, cwd="nawak/conf", stderr=errfile, stdout=logfile)
-  except:
+  except Exception:
     ret = 1
 
   p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)

+ 8 - 3
frameworks/Nimrod/nawak/setup_redis.py

@@ -12,7 +12,7 @@ def start(args, logfile, errfile):
                           'open(host="' + args.database_host + '")')
   # compile the app
   subprocess.check_call(
-      "nimrod c --threads:on -d:release -d:redis_model --path:../installs/nawak/nawak -o:nawak_redis app.nim",
+      "nim c --threads:on -d:release -d:redis_model --path:$NAWAK_PATH -o:nawak_redis app.nim",
       shell=True, cwd="nawak", stderr=errfile, stdout=logfile)
   # launch mongrel2
   subprocess.check_call("mkdir -p run logs tmp", shell=True, cwd="nawak/conf", stderr=errfile, stdout=logfile)
@@ -20,7 +20,12 @@ def start(args, logfile, errfile):
   subprocess.check_call("sudo m2sh start -name test", shell=True, cwd="nawak/conf", stderr=errfile, stdout=logfile)
   
   # launch workers
-  subprocess.Popen("./nawak_redis", shell=True, cwd="nawak", stderr=errfile, stdout=logfile)
+  if os.environ.get("TRAVIS"):
+    nb_workers = 32
+  else:
+    nb_workers = 256
+  subprocess.Popen("./nawak_redis " + str(nb_workers),
+                   shell=True, cwd="nawak", stderr=errfile, stdout=logfile)
   return 0
 
 def stop(logfile, errfile):
@@ -28,7 +33,7 @@ def stop(logfile, errfile):
 
   try:
     subprocess.check_call("sudo m2sh stop -every", shell=True, cwd="nawak/conf", stderr=errfile, stdout=logfile)
-  except:
+  except Exception:
     ret = 1
 
   p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)

+ 1 - 1
frameworks/Scala/play-activate-mysql/setup.py

@@ -26,7 +26,7 @@ def stop(logfile, errfile):
     with open("./play-activate-mysql/target/universal/play-activate-mysql-1.0-SNAPSHOT/RUNNING_PID") as f:
       pid = int(f.read())
       os.kill(pid,15)
-  except:
+  except Exception:
     return 1
 
   try:

+ 12 - 6
toolset/benchmark/benchmarker.py

@@ -494,7 +494,7 @@ class Benchmarker:
 
     try:
       os.makedirs(os.path.join(self.latest_results_directory, 'logs', "{name}".format(name=test.name)))
-    except:
+    except Exception:
       pass
     with open(os.path.join(self.latest_results_directory, 'logs', "{name}".format(name=test.name), 'out.txt'), 'w') as out, \
          open(os.path.join(self.latest_results_directory, 'logs', "{name}".format(name=test.name), 'err.txt'), 'w') as err:
@@ -599,8 +599,7 @@ class Benchmarker:
             err.write(header("Error: Port %s was not released by stop %s" % (test.port, test.name)))
             err.flush()
             self.__write_intermediate_results(test.name, "port " + str(test.port) + " was not released by stop")
-
-          return exit_with_code(1)
+            return exit_with_code(1)
 
         out.write(header("Stopped %s" % test.name))
         out.flush()
@@ -662,7 +661,7 @@ class Benchmarker:
       s.bind(("", port))
       # If we get here, we were able to bind successfully,
       # which means the port is free.
-    except:
+    except Exception:
       # If we get an exception, it might be because the port is still bound
       # which would be bad, or maybe it is a privileged port (<1024) and we
       # are not running as root, or maybe the server is gone, but sockets are
@@ -673,7 +672,7 @@ class Benchmarker:
         # If we get here, we were able to connect to something, which means
         # that the port is still bound.
         return True
-      except:
+      except Exception:
         # An exception means that we couldn't connect, so a server probably
         # isn't still running on the port.
         pass
@@ -701,6 +700,13 @@ class Benchmarker:
           continue
 
         if port > 6000:
+          try:
+            # Never try to kill pid 0; bad form old chap.
+            if int(pid) == 0:
+              continue
+          except Exception:
+            # Trying to kill a non-number? Silly.
+            continue
           ps = subprocess.Popen(['ps','p',pid], stdout=subprocess.PIPE)
           (out_6000, err_6000) = ps.communicate()
           err.write(textwrap.dedent(
@@ -940,7 +946,7 @@ class Benchmarker:
     
 
     args['max_threads'] = args['threads']
-    args['max_concurrency'] = str(max(args['concurrency_levels']))
+    args['max_concurrency'] = max(args['concurrency_levels'])
 
     self.__dict__.update(args)
     # pprint(self.__dict__)

+ 1 - 1
toolset/benchmark/framework_test.py

@@ -296,7 +296,7 @@ class FrameworkTest:
         with open(output_file, 'w'):
           pass
 
-      if test.passed:
+      if not test.failed:
         if test_type == 'plaintext': # One special case
           remote_script = self.__generate_concurrency_script(test.get_url(), self.port, test.accept_header, levels=[256,1024,4096,16384], pipeline="16")
         elif test.requires_db:

+ 6 - 6
toolset/benchmark/test_types/db_type.py

@@ -53,7 +53,7 @@ class DBTestType(FrameworkTestType):
     else:
       return problems
 
-  def _verifyObject(self, db_object, url):
+  def _verifyObject(self, db_object, url, max_infraction='fail'):
     '''Ensure the passed item is a JSON object with 
     keys 'id' and 'randomNumber' mapping to ints. 
     Separate method allows the QueryTestType to 
@@ -65,15 +65,15 @@ class DBTestType(FrameworkTestType):
       got = str(db_object)[:20]
       if len(str(db_object)) > 20:
         got = str(db_object)[:17] + '...'
-      return ('fail', "Expected a JSON object, got '%s' instead" % got, url)
+      return [(max_infraction, "Expected a JSON object, got '%s' instead" % got, url)]
 
     # Make keys case insensitive
     db_object = {k.lower(): v for k,v in db_object.iteritems()}
 
     if "id" not in db_object:
-      problems.append( ('fail', "Response has no 'id' key", url) ) 
+      problems.append( (max_infraction, "Response has no 'id' key", url) ) 
     if "randomnumber" not in db_object:
-      problems.append( ('fail', "Response has no 'randomNumber' key", url) )
+      problems.append( (max_infraction, "Response has no 'randomNumber' key", url) )
     
     # Ensure we can continue on to use these keys
     if "id" not in db_object or "randomnumber" not in db_object:
@@ -82,12 +82,12 @@ class DBTestType(FrameworkTestType):
     try:
       float(db_object["id"])
     except ValueError as ve:
-      problems.append( ('fail', "Response key 'id' does not map to a number - %s" % ve, url) ) 
+      problems.append( (max_infraction, "Response key 'id' does not map to a number - %s" % ve, url) ) 
 
     try:
       float(db_object["randomnumber"])
     except ValueError as ve:
-      problems.append( ('fail', "Response key 'randomNumber' does not map to a number - %s" % ve, url) ) 
+      problems.append( (max_infraction, "Response key 'randomNumber' does not map to a number - %s" % ve, url) ) 
 
     if type(db_object["id"]) != int:
       problems.append( ('warn', '''Response key 'id' contains extra quotations or decimal points.

+ 8 - 8
toolset/benchmark/test_types/query_type.py

@@ -51,22 +51,22 @@ class QueryTestType(DBTestType):
     else:
       return problems
 
-  def _verifyQueryList(self, expectedLength, body, url, incorrect_length_response='fail'):
+  def _verifyQueryList(self, expectedLength, body, url, max_infraction='fail'):
     '''Validates high-level structure (array length, object 
       types, etc) before calling into DBTestType to 
       validate a few individual JSON objects'''
 
     # Empty response
     if body is None:
-      return [('fail','No response', url)]
+      return [(max_infraction,'No response', url)]
     elif len(body) == 0:
-      return [('fail','Empty Response', url)]
+      return [(max_infraction,'Empty Response', url)]
   
     # Valid JSON? 
     try: 
       response = json.loads(body)
     except ValueError as ve:
-      return [('fail',"Invalid JSON - %s" % ve, url)]
+      return [(max_infraction,"Invalid JSON - %s" % ve, url)]
 
     problems = []
 
@@ -74,23 +74,23 @@ class QueryTestType(DBTestType):
       problems.append(('warn','Top-level JSON is an object, not an array', url))
 
       # Verify the one object they gave us before returning
-      problems += self._verifyObject(response, url)
+      problems += self._verifyObject(response, url, max_infraction)
 
       return problems
 
     if any(type(item) != dict for item in response):
-      problems.append(('fail','All items JSON array must be JSON objects', url))
+      problems.append((max_infraction,'All items JSON array must be JSON objects', url))
 
     # For some edge cases we only warn
     if len(response) != expectedLength:
-      problems.append((incorrect_length_response,
+      problems.append((max_infraction,
         "JSON array length of %s != expected length of %s" % (len(response), expectedLength), 
         url))
 
     # verify individual objects
     maxBadObjects = 5
     for item in response:
-      obj_ok = self._verifyObject(item, url)
+      obj_ok = self._verifyObject(item, url, max_infraction)
       if len(obj_ok) > 0:
         maxBadObjects -=  1
         problems += obj_ok

+ 1 - 1
toolset/benchmark/utils.py

@@ -43,7 +43,7 @@ def gather_tests(include = [], exclude=[], benchmarker=None):
     for k,v in defaults.iteritems():
       try:
         defaults[k] = literal_eval(v)
-      except:
+      except Exception:
         pass
 
     # Ensure we only run the __init__ method of Benchmarker

+ 1 - 1
toolset/run-ci.py

@@ -444,7 +444,7 @@ if __name__ == "__main__":
     log.warning("Environment key missing, are you running inside Travis-CI?")
     print traceback.format_exc()
     retcode = 1
-  except:
+  except Exception:
     log.critical("Unknown error")
     print traceback.format_exc()
     retcode = 1

+ 11 - 4
toolset/run-tests.py

@@ -11,6 +11,7 @@ from pprint import pprint
 from benchmark.benchmarker import Benchmarker
 from setup.linux.unbuffered import Unbuffered
 from setup.linux import setup_util
+from ast import literal_eval
 
 # Enable cross-platform colored output
 from colorama import init
@@ -80,6 +81,12 @@ def main(argv=None):
             config = ConfigParser.SafeConfigParser()
             config.read([os.getcwd() + '/' + args.conf_file])
             defaults = dict(config.items("Defaults"))
+            # Convert strings into proper python types
+            for k,v in defaults.iteritems():
+                try:
+                    defaults[k] = literal_eval(v)
+                except Exception:
+                    pass
     except IOError:
         if args.conf_file != 'benchmark.cfg':
             print 'Configuration file not found!'
@@ -98,7 +105,7 @@ def main(argv=None):
     maxThreads = 8
     try:
         maxThreads = multiprocessing.cpu_count()
-    except:
+    except Exception:
         pass
 
     ##########################################################
@@ -185,13 +192,13 @@ def main(argv=None):
     # Run the benchmarker in the specified mode
     #   Do not use benchmarker variables for these checks, 
     #   they are either str or bool based on the python version
-    if (type(args.list_tests) is str and args.list_tests.lower() == 'true') or (type(args.list_tests) is bool and args.list_tests):
+    if args.list_tests:
       benchmarker.run_list_tests()
-    elif (type(args.list_test_metadata) is str and args.list_test_metadata.lower() == 'true') or (type(args.list_test_metadata) is bool and args.list_test_metadata):
+    elif args.list_test_metadata:
       benchmarker.run_list_test_metadata()
     elif args.parse != None:
       benchmarker.parse_timestamp()
-    elif not ((type(args.install_only) is str and args.install_only.lower() == 'true') or (type(args.install_only) is bool and args.install_only)):
+    elif not args.install_only:
       return benchmarker.run()
 
 if __name__ == "__main__":

+ 23 - 12
toolset/setup/linux/database.sh

@@ -26,6 +26,12 @@ export DB_HOST={database_host}
 set -x
 export DEBIAN_FRONTEND=noninteractive
 
+source /etc/lsb-release
+export TFB_DISTRIB_ID=$DISTRIB_ID
+export TFB_DISTRIB_RELEASE=$DISTRIB_RELEASE
+export TFB_DISTRIB_CODENAME=$DISTRIB_CODENAME
+export TFB_DISTRIB_DESCRIPTION=$DISTRIB_DESCRIPTION
+
 ##############################
 # Prerequisites
 ##############################
@@ -42,8 +48,6 @@ sudo apt-get -y install -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::=
     redis-server      `# Installs 2.4 or 2.6, based on Ubuntu version` \
     lsb-core          `# Ensure that lsb_release can be used`
 
-CODENAME=$(lsb_release -sc)
-
 sudo sh -c "echo '*               -    nofile          65535' >> /etc/security/limits.conf"
 
 # Create a user-owned directory for our databases
@@ -72,6 +76,8 @@ sudo mv mysql.conf /etc/init/mysql.conf
 sudo mv /etc/mysql/my.cnf /etc/mysql/my.cnf.orig
 sudo mv my.cnf /etc/mysql/my.cnf
 
+sudo rm -rf /ssd/mysql
+sudo rm -rf /ssd/log/mysql
 sudo cp -R -p /var/lib/mysql /ssd/
 sudo cp -R -p /var/log/mysql /ssd/log
 sudo cp usr.sbin.mysqld /etc/apparmor.d/
@@ -86,7 +92,7 @@ rm create.sql
 # Postgres
 ##############################
 echo "Setting up Postgres database"
-if [ "$CODENAME" == "precise" ]; then
+if [ "$TFB_DISTRIB_CODENAME" == "precise" ]; then
   echo "WARNING: Force upgrading Postgres for Ubuntu 12.04"
   sudo apt-get remove -y postgresql postgresql-9.1 postgresql-client-9.1
 
@@ -94,21 +100,24 @@ if [ "$CODENAME" == "precise" ]; then
   wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
   sudo apt-get update
   sudo apt-get install -y postgresql-9.3 postgresql-client-9.3
-  sudo -u postgres -H /etc/init.d/postgresql start
+  sudo /etc/init.d/postgresql start
 fi
-
-sudo -u postgres psql template1 < create-postgres-database.sql
-sudo -u benchmarkdbuser psql hello_world < create-postgres.sql
-rm create-postgres-database.sql create-postgres.sql
-
-sudo -u postgres -H /etc/init.d/postgresql stop
+sudo /etc/init.d/postgresql stop
 sudo mv postgresql.conf /etc/postgresql/9.3/main/postgresql.conf
 sudo mv pg_hba.conf /etc/postgresql/9.3/main/pg_hba.conf
 
+sudo rm -rf /ssd/postgresql
 sudo cp -R -p /var/lib/postgresql/9.3/main /ssd/postgresql
-sudo -u postgres -H /etc/init.d/postgresql start
 sudo mv 60-postgresql-shm.conf /etc/sysctl.d/60-postgresql-shm.conf
 
+sudo /etc/init.d/postgresql start
+
+sudo -u postgres psql template1 < create-postgres-database.sql
+sudo -u benchmarkdbuser psql hello_world < create-postgres.sql
+rm create-postgres-database.sql create-postgres.sql
+
+sudo /etc/init.d/postgresql restart
+
 ##############################
 # MongoDB
 #
@@ -125,6 +134,8 @@ sudo service mongod stop
 sudo mv /etc/mongodb.conf /etc/mongodb.conf.orig
 sudo cp mongodb.conf /etc/mongodb.conf
 sudo mv mongodb.conf /etc/mongod.conf
+sudo rm -rf /ssd/mongodb
+sudo rm -rf /ssd/log/mongodb
 sudo cp -R -p /var/lib/mongodb /ssd/
 sudo cp -R -p /var/log/mongodb /ssd/log/
 sudo service mongod start
@@ -165,7 +176,7 @@ rm -rf apache-cassandra-*-bin.tar.gz cassandra
 # Redis
 ##############################
 echo "Setting up Redis database"
-if [ "$CODENAME" == "precise" ]; then
+if [ "$TFB_DISTRIB_CODENAME" == "precise" ]; then
   echo "WARNING: Downgrading Redis configuration for Ubuntu 12.04"
 
   # On 12.04, Redis 2.4 is installed. It doesn't support 

+ 4 - 3
toolset/setup/linux/frameworks/jester.sh

@@ -3,6 +3,7 @@
 RETCODE=$(fw_exists jester)
 [ ! "$RETCODE" == 0 ] || { return 0; }
 
-git clone git://github.com/dom96/jester.git jester/jester
-cd jester/jester
-git checkout ad154e05dd93367ebd8fad9a5dc2016b67121763
+git clone git://github.com/dom96/jester.git jester
+cd jester
+# most recent commit in branch new-async as of 2014-10-31
+git checkout 3e77ce753293b523004dfdaebd2fb195217f30f0

+ 5 - 1
toolset/setup/linux/frameworks/nawak.sh

@@ -5,4 +5,8 @@ RETCODE=$(fw_exists nawak)
 
 git clone git://github.com/idlewan/nawak.git nawak
 cd nawak
-git checkout 5e56d718ff327c58cbdca14d44abc327f752681d
+# version 0.3.0 (2014-11-02)
+git checkout b34b0b5077541ae9671957452a70e2578894d3a8
+
+nimble update
+nimble install

+ 1 - 1
toolset/setup/linux/frameworks/siena.sh

@@ -4,4 +4,4 @@ RETCODE=$(fw_exists play-1.2.5/modules/siena-2.0.6)
 [ ! "$RETCODE" == 0 ] || { return 0; }
 
 fw_depends play1
-yes | play-1.2.5/play1 install siena
+yes | play-1.2.5/play1 install siena-2.0.6

+ 5 - 5
toolset/setup/linux/frameworks/wt.sh

@@ -20,10 +20,9 @@ RETCODE=$(fw_exists wt)
 
 # Instead of compiling from source, just use apt to install onto 
 # host machine
-source /etc/lsb-release
-if [ "$DISTRIB_RELEASE" -eq "14.04" ]; then
+if [ "$TFB_DISTRIB_CODENAME" == "trusty" ]; then
     sudo apt-get -y install libboost1.54-all-dev
-else
+elif [ "$TFB_DISTRIB_CODENAME" == "precise" ]; then
     sudo apt-get -y install libboost1.48-all-dev
 fi
 
@@ -35,6 +34,7 @@ mkdir -p build
 cd build
 cmake .. -DWT_CPP_11_MODE=-std=c++0x -DCMAKE_BUILD_TYPE=Release \
   -DCMAKE_INSTALL_PREFIX=${IROOT}/wt -DCONFIGDIR=${IROOT}/wt/etc \
-  -DCMAKE_CXX_COMPILER=$(which g++-4.8)
+  -DCMAKE_CXX_COMPILER=$(which g++-4.8) -DDESTDIR=${IROOT}/wt \
+  -DWEBUSER=$(id -u -n) -DWEBGROUP=$(id -g -n)
 make
-make install
+make install

+ 20 - 12
toolset/setup/linux/languages/nimrod.sh

@@ -1,23 +1,31 @@
 #!/bin/bash
 
-RETCODE=$(fw_exists nimrod/bin/nimrod)
+RETCODE=$(fw_exists $IROOT/nim.installed)
 [ ! "$RETCODE" == 0 ] || { return 0; }
 
 test -d nimrod || git clone git://github.com/Araq/Nimrod.git nimrod
 cd nimrod 
-git checkout 887a1ebe688a01259263ad6e11c9061cfc940456
-test -d csources || git clone git://github.com/nimrod-code/csources.git
+# post version 0.9.6 - most recent as of 2014-10-31
+git checkout bbb16713c1bbc266cb8d69f262cc302641e361c4
 
+test -d csources || git clone git://github.com/nimrod-code/csources.git
 cd csources
-git checkout 0a6e5758ed16bf906fcfdb9e64086edd9b60c5c0
-chmod +x build.sh
-./build.sh
-
-cd ../..
-RETCODE=$(fw_exists nimrod/koch)
-[ ! "$RETCODE" == 0 ] || { return 0; }
+# post version 0.9.6 - most recent as of 2014-10-31
+git checkout b0bcf88e26730b23d22e2663adf1babb05bd5a71
+sh build.sh
+cd ..
 
-cd nimrod
 bin/nimrod c koch
+
+# bootstrapping nim's compiler
 ./koch boot -d:release
-sudo ./koch install /usr/bin
+
+# nim's package manager
+test -d nimble || git clone git://github.com/nimrod-code/nimble.git
+cd nimble
+# post version 0.4.0 - most recent as of 2014-10-31
+git checkout ecd78e0e0300a8178db320d83014d3eb47a89b4c
+../bin/nim c src/nimble
+mv src/nimble ../bin/
+
+touch $IROOT/nim.installed

+ 1 - 1
toolset/setup/linux/setup_util.py

@@ -62,7 +62,7 @@ def replace_environ(config=None, root=None, print_result=False, command='true'):
                     os.environ[key]=mini_environ[key]
                 else:
                     os.environ[key]=value    
-            except:
+            except Exception:
                 if not line: # Don't warn for empty line
                     continue 
                 print "WARN: Line '%s' from '%s' is not an environment variable" % (line, config)

+ 12 - 0
toolset/setup/linux/systools/rebar.sh

@@ -0,0 +1,12 @@
+#!/bin/bash
+
+RETCODE=$(fw_exists $IROOT/rebar.installed)
+[ ! "$RETCODE" == 0 ] || { return 0; }
+
+fw_get https://github.com/rebar/rebar/archive/2.5.1.tar.gz -O rebar-2.5.1.tar.gz
+fw_untar rebar-2.5.1.tar.gz
+mv rebar-2.5.1 rebar
+cd rebar
+./bootstrap
+
+touch $IROOT/rebar.installed

+ 6 - 0
toolset/setup/linux/webservers/apache.sh

@@ -0,0 +1,6 @@
+#!/bin/bash
+
+sudo apt-get install -y apache2
+
+# Stop Apache; it starts after it is installed
+sudo /etc/init.d/apache2 stop