Browse Source

Merge pull request #1538 from zane-techempower/upgrade-clojure-frameworks

[fixes #1515] Upgrade clojure frameworks
Brittany Mazza 10 years ago
parent
commit
1bfa7c2891

+ 1 - 0
frameworks/Clojure/compojure/benchmark_config.json

@@ -6,6 +6,7 @@
       "json_url": "/compojure/json",
       "json_url": "/compojure/json",
       "db_url": "/compojure/db",
       "db_url": "/compojure/db",
       "query_url": "/compojure/db/",
       "query_url": "/compojure/db/",
+      "update_url": "/compojure/updates/",
       "fortune_url": "/compojure/fortune-hiccup",
       "fortune_url": "/compojure/fortune-hiccup",
       "plaintext_url": "/compojure/plaintext",
       "plaintext_url": "/compojure/plaintext",
       "port": 8080,
       "port": 8080,

+ 1 - 2
frameworks/Clojure/compojure/hello/project.clj

@@ -9,8 +9,7 @@
                  [mysql/mysql-connector-java "5.1.6"]
                  [mysql/mysql-connector-java "5.1.6"]
                  [org.clojure/java.jdbc "0.3.0-alpha1"]
                  [org.clojure/java.jdbc "0.3.0-alpha1"]
                  [c3p0/c3p0 "0.9.1.2"]
                  [c3p0/c3p0 "0.9.1.2"]
-                 [hiccup "1.0.4"]
-                 ]
+                 [hiccup "1.0.4"]]
   :plugins [[lein-ring "0.8.10"]]
   :plugins [[lein-ring "0.8.10"]]
   :ring {:handler hello.handler/app}
   :ring {:handler hello.handler/app}
   :profiles
   :profiles

+ 137 - 49
frameworks/Clojure/compojure/hello/src/hello/handler.clj

@@ -13,6 +13,7 @@
             [clojure.java.jdbc :as jdbc]
             [clojure.java.jdbc :as jdbc]
             [clojure.java.jdbc.sql :as sql]))
             [clojure.java.jdbc.sql :as sql]))
 
 
+
 ; Database connection
 ; Database connection
 (defdb db (mysql {:subname "//localhost:3306/hello_world?jdbcCompliantTruncation=false&elideSetAutoCommits=true&useLocalSessionState=true&cachePrepStmts=true&cacheCallableStmts=true&alwaysSendSetIsolation=false&prepStmtCacheSize=4096&cacheServerConfiguration=true&prepStmtCacheSqlLimit=2048&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useUnbufferedInput=false&useReadAheadInput=false&maintainTimeStats=false&useServerPrepStmts&cacheRSMetadata=true"
 (defdb db (mysql {:subname "//localhost:3306/hello_world?jdbcCompliantTruncation=false&elideSetAutoCommits=true&useLocalSessionState=true&cachePrepStmts=true&cacheCallableStmts=true&alwaysSendSetIsolation=false&prepStmtCacheSize=4096&cacheServerConfiguration=true&prepStmtCacheSqlLimit=2048&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useUnbufferedInput=false&useReadAheadInput=false&maintainTimeStats=false&useServerPrepStmts&cacheRSMetadata=true"
                   :user "benchmarkdbuser"
                   :user "benchmarkdbuser"
@@ -22,6 +23,7 @@
                   :maximum-pool-size 256
                   :maximum-pool-size 256
                   }))
                   }))
 
 
+
 ; Set up entity World and the database representation
 ; Set up entity World and the database representation
 (defentity world
 (defentity world
   (pk :id)
   (pk :id)
@@ -29,19 +31,23 @@
   (entity-fields :id :randomNumber)
   (entity-fields :id :randomNumber)
   (database db))
   (database db))
 
 
-; Query a random World record from the database
-(defn get-world []
+
+(defn get-world
+  "Query a random World record from the database"
+  []
   (let [id (inc (rand-int 9999))] ; Num between 1 and 10,000
   (let [id (inc (rand-int 9999))] ; Num between 1 and 10,000
     (select world
     (select world
             (fields :id :randomNumber)
             (fields :id :randomNumber)
             (where {:id id }))))
             (where {:id id }))))
 
 
-; Run the specified number of queries, return the results
-(defn run-queries [queries]
-   (flatten ; Make it a list of maps
-    (take
-     queries ; Number of queries to run
-     (repeatedly get-world))))
+
+(defn run-queries
+  "Run the specified number of queries, return the results"
+  [queries]
+  (flatten ; Make it a list of maps
+    (take queries ; Number of queries to run
+          (repeatedly get-world))))
+
 
 
 ; Database connection for java.jdbc "raw"
 ; Database connection for java.jdbc "raw"
 ; https://github.com/clojure/java.jdbc/blob/master/doc/clojure/java/jdbc/ConnectionPooling.md
 ; https://github.com/clojure/java.jdbc/blob/master/doc/clojure/java/jdbc/ConnectionPooling.md
@@ -52,6 +58,7 @@
    :user "benchmarkdbuser"
    :user "benchmarkdbuser"
    :password "benchmarkdbpass"})
    :password "benchmarkdbpass"})
 
 
+
 (defn pool
 (defn pool
   [spec]
   [spec]
   (let [cpds (doto (ComboPooledDataSource.)
   (let [cpds (doto (ComboPooledDataSource.)
@@ -65,35 +72,42 @@
                (.setMaxIdleTime (* 3 60 60)))]
                (.setMaxIdleTime (* 3 60 60)))]
     {:datasource cpds}))
     {:datasource cpds}))
 
 
+
 (def pooled-db (delay (pool db-spec-mysql-raw)))
 (def pooled-db (delay (pool db-spec-mysql-raw)))
 
 
+
 (defn db-raw [] @pooled-db)
 (defn db-raw [] @pooled-db)
 
 
-; Query a random World record from the database
-(defn get-world-raw []
-  (let [id (inc (rand-int 9999))] ; Num between 1 and 10,000
+
+(defn get-world-raw
+  "Query a random World record from the database"
+  []
+  (let [id (inc (rand-int 9999))]
     (jdbc/with-connection (db-raw)
     (jdbc/with-connection (db-raw)
       ; Set a naming strategy to preserve column name case
       ; Set a naming strategy to preserve column name case
       (jdbc/with-naming-strategy {:keyword identity}
       (jdbc/with-naming-strategy {:keyword identity}
         (jdbc/with-query-results rs [(str "select * from world where id = ?") id]
         (jdbc/with-query-results rs [(str "select * from world where id = ?") id]
           (doall rs))))))
           (doall rs))))))
 
 
-; Run the specified number of queries, return the results
-(defn run-queries-raw [queries]
-   (flatten ; Make it a list of maps
-    (take
-     queries ; Number of queries to run
-     (repeatedly get-world-raw))))
 
 
-(defn get-query-count [queries]
+(defn run-queries-raw
+  "Run the specified number of queries, return the results"
+  [queries]
+  (flatten ; Make it a list of maps
+    (take queries
+          (repeatedly get-world-raw))))
+
+
+(defn get-query-count
   "Parse provided string value of query count, clamping values to between 1 and 500."
   "Parse provided string value of query count, clamping values to between 1 and 500."
-  (let [q (try (Integer/parseInt queries)
+  [queries]
+  (let [n (try (Integer/parseInt queries)
                (catch Exception e 1))] ; default to 1 on parse failure
                (catch Exception e 1))] ; default to 1 on parse failure
-    (if (> q 500)
-      500 ; clamp to 500 max
-      (if (< q 1)
-        1 ; clamp to 1 min
-        q)))) ; otherwise use provided value
+    (cond
+      (< n 1) 1
+      (> n 500) 500
+      :else n)))
+
 
 
 ; Set up entity World and the database representation
 ; Set up entity World and the database representation
 (defentity fortune
 (defentity fortune
@@ -102,19 +116,27 @@
   (entity-fields :id :message)
   (entity-fields :id :message)
   (database db))
   (database db))
 
 
-(defn get-all-fortunes []
+
+(defn get-all-fortunes
   "Query all Fortune records from the database."
   "Query all Fortune records from the database."
-    (select fortune
-            (fields :id :message)))
+  []
+  (select fortune
+          (fields :id :message)))
+
 
 
-(defn get-fortunes []
+(defn get-fortunes
   "Fetch the full list of Fortunes from the database, sort them by the fortune
   "Fetch the full list of Fortunes from the database, sort them by the fortune
-message text, and then return the results."
-  (let [fortunes (conj (get-all-fortunes) {:id 0 :message "Additional fortune added at request time."} )]
+  message text, and then return the results."
+  []
+  (let [fortunes (conj (get-all-fortunes)
+                       {:id 0
+                        :message "Additional fortune added at request time."})]
     (sort-by #(:message %) fortunes)))
     (sort-by #(:message %) fortunes)))
 
 
-(defn fortunes-hiccup [fortunes]
+
+(defn fortunes-hiccup
   "Render the given fortunes to simple HTML using Hiccup."
   "Render the given fortunes to simple HTML using Hiccup."
+  [fortunes]
   (html5
   (html5
    [:head
    [:head
     [:title "Fortunes"]]
     [:title "Fortunes"]]
@@ -129,27 +151,93 @@ message text, and then return the results."
         [:td (escape-html (:message x))]])
         [:td (escape-html (:message x))]])
      ]]))
      ]]))
 
 
-(defn fortunes-enlive [fortunes]
-  "Render the given fortunes to simple HTML using Enlive."
-  "todo")
 
 
-; Define route handlers
+(defn update-and-persist
+  "Changes the :randomNumber of a number of world entities.
+  Persists the changes to sql then returns the updated entities"
+  [queries]
+  (let [results (run-queries queries)]
+    (for [w results]
+      (update-in w [:randomNumber (inc (rand-int 9999))]
+        (update world
+                (set-fields {:randomNumber (:randomNumber w)})
+                (where {:id [:id w]}))))
+    results))
+
+
+(def json-serialization
+  "Test 1: JSON serialization"
+  (response {:message "Hello, World!"}))
+
+
+(def single-query-test
+  "Test 2: Single database query"
+  (-> 1
+      (run-queries)
+      (first)
+      (response)))
+
+
+(defn multiple-query-test
+  "Test 3: Multiple database queries"
+  [queries]
+  (-> queries
+      (get-query-count)
+      (run-queries)
+      (response)))
+
+
+(def single-query-test-raw
+  "Test 2: Single database query (raw)"
+  (-> 1
+      (run-queries-raw)
+      (first)
+      (response)))
+
+
+(defn multiple-query-test-raw
+  "Test 3: Multiple database queries (raw)"
+  [queries]
+  (-> queries
+      (get-query-count)
+      (run-queries-raw)
+      (response)))
+
+
+(def fortune-test
+  "Test 4: Fortunes"
+  (response (fortunes-hiccup (get-fortunes))))
+
+
+(defn db-updates
+  "Test 5: Database updates"
+  [queries]
+  (-> queries
+      (get-query-count)
+      (update-and-persist)
+      (response)))
+
+(def plaintext
+  "Test 6: Plaintext"
+  {:status 200
+   :headers {"Content-Type" "text/plain; charset=utf-8"}
+   :body "Hello, World!"})
+
+
 (defroutes app-routes
 (defroutes app-routes
-  (GET "/" [] "Hello, World!")
-  (GET "/plaintext" []
-       {:status 200
-        :headers {"Content-Type" "text/plain; charset=utf-8"}
-        :body "Hello, World!"})
-  (GET "/json" [] (response {:message "Hello, World!"}))
-  (GET "/db" [] (response (first (run-queries 1))))
-  (GET "/db/:queries" [queries] (response (run-queries (get-query-count queries))))
-  (GET "/dbraw" [] (response (first (run-queries-raw 1))))
-  (GET "/dbraw/:queries" [queries] (response (run-queries-raw (get-query-count queries))))
-  (GET "/fortune" [] (response (get-fortunes)))
-  (GET "/fortune-hiccup" [] (fortunes-hiccup (get-fortunes)))
-  (GET "/fortune-enlive" [] (fortunes-enlive (get-fortunes)))
+  (GET "/"                 [] "Hello, World!")
+  (GET "/json"             [] json-serialization)
+  (GET "/db"               [] single-query-test)
+  (GET "/db/:queries"      [queries] (multiple-query-test queries))
+  (GET "/dbraw"            [] single-query-test-raw)
+  (GET "/dbraw/:queries"   [queries] (multiple-query-test-raw queries))
+  (GET "/fortunes"         [] (response (get-fortunes))) ; Raw json of fortunes
+  (GET "/fortune-hiccup"   [] fortune-test)
+  (GET "/updates/:queries" [queries] (db-updates queries))
+  (GET "/plaintext"        [] plaintext)
   (route/not-found "Not Found"))
   (route/not-found "Not Found"))
 
 
-; Format responses as JSON
+
 (def app
 (def app
+  "Format responses as JSON"
   (wrap-json-response app-routes))
   (wrap-json-response app-routes))

+ 12 - 7
frameworks/Clojure/compojure/setup.sh

@@ -2,17 +2,22 @@
 
 
 source $IROOT/java7.installed
 source $IROOT/java7.installed
 
 
-export RESIN_HOME=${IROOT}/resin-4.0.41
-export LEIN_HOME=$IROOT/lein
+source $IROOT/lein.installed
 
 
-# Path vars must be set here
-export PATH="$JAVA_HOME/bin:$PATH"
+export RESIN_HOME=${IROOT}/resin-4.0.41
 
 
 sed -i 's|:subname "//.*:3306|:subname "//'"${DBHOST}"':3306|g' hello/src/hello/handler.clj
 sed -i 's|:subname "//.*:3306|:subname "//'"${DBHOST}"':3306|g' hello/src/hello/handler.clj
 
 
 cd hello
 cd hello
-$LEIN_HOME/bin/lein clean
-$LEIN_HOME/bin/lein ring uberwar
+lein clean
+lein ring uberwar
 rm -rf $RESIN_HOME/webapps/*
 rm -rf $RESIN_HOME/webapps/*
 cp target/hello-compojure-standalone.war $RESIN_HOME/webapps/compojure.war
 cp target/hello-compojure-standalone.war $RESIN_HOME/webapps/compojure.war
-$RESIN_HOME/bin/resinctl start
+
+$RESIN_HOME/bin/resinctl start
+
+# preform an initial request to warm up the server
+# initial requests were taking >15 seconds, causing fails in the tests
+echo "Sleeping, then executing an initial request to ensure server is in a responsive state"
+sleep 30
+curl -m 60 http://localhost:8080/compojure/ > /dev/null 2>&1

+ 6 - 3
frameworks/Clojure/http-kit/benchmark_config.json

@@ -3,9 +3,12 @@
   "tests": [{
   "tests": [{
     "default": {
     "default": {
       "setup_file": "setup",
       "setup_file": "setup",
-      "json_url": "/http-kit/json",
-      "db_url": "/http-kit/db",
-      "query_url": "/http-kit/db/",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/queries/",
+      "fortune_url": "/fortunes",
+      "update_url": "/updates/",
+      "plaintext_url": "/plaintext",
       "port": 8080,
       "port": 8080,
       "approach": "Realistic",
       "approach": "Realistic",
       "classification": "Platform",
       "classification": "Platform",

+ 10 - 2
frameworks/Clojure/http-kit/hello/project.clj

@@ -6,9 +6,17 @@
                  [ring/ring-json "0.2.0"]
                  [ring/ring-json "0.2.0"]
                  [org.clojure/tools.cli "0.2.1"]
                  [org.clojure/tools.cli "0.2.1"]
                  [http-kit/dbcp "0.1.0"]
                  [http-kit/dbcp "0.1.0"]
-                 [http-kit "2.0.1"]
+                 [http-kit "2.1.18"]
                  [log4j "1.2.15" :exclusions [javax.mail/mail javax.jms/jms com.sun.jdmk/jmxtools com.sun.jmx/jmxri]]
                  [log4j "1.2.15" :exclusions [javax.mail/mail javax.jms/jms com.sun.jdmk/jmxtools com.sun.jmx/jmxri]]
-                 [mysql/mysql-connector-java "5.1.6"]]
+                 ; [ch.qos.logback/logback-classic "1.1.2" :exclusions [org.slf4j/slf4j-api]]
+                 ; [org.slf4j/jul-to-slf4j "1.7.7"]
+                 ; [org.slf4j/jcl-over-slf4j "1.7.7"]
+                 ; [org.slf4j/log4j-over-slf4j "1.7.7"]
+                 [org.clojure/data.json "0.2.5"]
+                 [org.clojure/java.jdbc "0.3.6"]
+                 [korma "0.4.0"]
+                 [mysql/mysql-connector-java "5.1.6"]
+                 [hiccup "1.0.4"]]
   :main hello.handler
   :main hello.handler
   :aot [hello.handler]
   :aot [hello.handler]
   :uberjar-name "http-kit-standalone.jar"
   :uberjar-name "http-kit-standalone.jar"

+ 182 - 47
frameworks/Clojure/http-kit/hello/src/hello/handler.clj

@@ -1,72 +1,207 @@
 (ns hello.handler
 (ns hello.handler
   (:gen-class)
   (:gen-class)
+  (:import com.mchange.v2.c3p0.ComboPooledDataSource)
   (:use compojure.core
   (:use compojure.core
         ring.middleware.json
         ring.middleware.json
         org.httpkit.server
         org.httpkit.server
         [clojure.tools.cli :only [cli]]
         [clojure.tools.cli :only [cli]]
-        ring.util.response)
+        korma.db
+        korma.core
+        hiccup.core
+        hiccup.util
+        hiccup.page)
   (:require [compojure.handler :as handler]
   (:require [compojure.handler :as handler]
-            [org.httpkit.dbcp :as db]
-            [compojure.route :as route]))
-
-;;; convert to int
-(defn to-int [s] (cond
-                  (string? s) (Integer/parseInt s)
-                  (instance? Integer s) s
-                  (instance? Long s) (.intValue ^Long s)
-                  :else 0))
-
-;; Query a random World record from the database
-(defn get-world []
-  (let [id (inc (rand-int 9999))] ; Num between 1 and 10,000
-    ; Set a naming strategy to preserve column name case
-    (clojure.java.jdbc/with-naming-strategy {:keyword identity}
-      (db/query "select * from world where id = ?" id))))
-
-;; Run the specified number of queries, return the results
-(defn run-queries [queries]
-   (flatten ; Make it a list of maps
-    (take
-     queries ; Number of queries to run
-     (repeatedly get-world))))
-
-(defn get-query-count [queries]
-  "Parse provided string value of query count, clamping values to between 1 and 500."
-  (let [q (try (Integer/parseInt queries)
+            [compojure.route :as route]
+            [ring.util.response :as ring-resp]
+            [clojure.data.json :as json]
+            [clojure.java.jdbc :as jdbc]))
+
+
+(defn parse-port [s] 
+  "Convert stringy port number int. Defaults to 8080."
+  (cond
+    (string? s) (Integer/parseInt s)
+    (instance? Integer s) s
+    (instance? Long s) (.intValue ^Long s)
+    :else 8080))
+
+
+;; MySQL connection
+(defdb mysql-db
+  (mysql {
+    :classname "com.mysql.jdbc.Driver"
+    :subprotocol "mysql"
+    :subname "//127.0.0.1:3306/hello_world"
+    :user "benchmarkdbuser"
+    :password "benchmarkdbpass"
+    ;;OPTIONAL KEYS
+    :delimiters "" ;; remove delimiters
+    :maximum-pool-size 256}))
+
+
+;; Set up entity World and the database representation
+(defentity world
+  (pk :id)
+  (table :world)
+  (entity-fields :id :randomNumber) ;; Default fields for select
+  (database mysql-db))
+
+
+(defn sanitize-queries-param
+  "Sanitizes the `queries` parameter. Caps the value between 1 and 500.
+  Invalid (stringy) values become 1"
+  [queries]
+  (let [n (try (Integer/parseInt queries)
                (catch Exception e 1))] ; default to 1 on parse failure
                (catch Exception e 1))] ; default to 1 on parse failure
-    (if (> q 500)
-      500 ; clamp to 500 max
-      (if (< q 1)
-        1 ; clamp to 1 min
-        q)))) ; otherwise use provided value
+    (cond
+      (< n 1) 1
+      (> n 500) 500
+      :else n)))
+
+
+(defn random-world
+  "Query a random World record from the database"
+  []
+  (let [id (inc (rand-int 9999))] ; Num between 1 and 10,000
+    (select world
+            (where {:id id }))))
+
+
+(defn run-queries
+  "Run query repeatedly -- Always returns an array"
+  [queries]
+  (flatten (take queries (repeatedly random-world))))
+
+; Set up entity Fortune and the database representation
+(defentity fortune
+  (pk :id)
+  (table :fortune)
+  (entity-fields :id :message)
+  (database mysql-db))
+
+
+(defn get-all-fortunes
+  "Query all Fortune records from the database."
+  []
+  (select fortune
+          (fields :id :message)))
+
+
+(defn get-fortunes
+  "Fetch the full list of Fortunes from the database, sort them by the fortune
+  message text, and then return the results."
+  []
+  (sort-by #(:message %)
+    (conj
+      (get-all-fortunes)
+      { :id 0 :message "Additional fortune added at request time." })))
+
+
+(defn fortunes-hiccup
+  "Render the given fortunes to simple HTML using Hiccup."
+  [fortunes]
+  (html5
+   [:head
+    [:title "Fortunes"]]
+   [:body
+    [:table
+     [:tr
+      [:th "id"]
+      [:th "message"]]
+     (for [x fortunes]
+       [:tr
+        [:td (:id x)]
+        [:td (escape-html (:message x))]])
+     ]]))
+
+
+(defn update-and-persist
+  "Changes the :randomNumber of a number of world entities.
+  Persists the changes to sql then returns the updated entities"
+  [queries]
+  (let [results (-> queries
+                    (sanitize-queries-param)
+                    (run-queries))]
+    (for [w results]
+      (update-in w [:randomNumber (inc (rand-int 9999))]
+        (update world
+                (set-fields {:randomNumber (:randomNumber w)})
+                (where {:id [:id w]}))))
+    results))
+
+
+(def json-serialization
+  "Test 1: JSON serialization"
+  (ring-resp/response {:message "Hello, World!"}))
+
+
+(def single-query-test
+  "Test 2: Single database query"
+  (ring-resp/response (first (run-queries 1))))
+
+
+(defn multiple-queries-test
+  "Test 3: Multiple database queries"
+  [queries]
+  (-> queries
+      (sanitize-queries-param)
+      (run-queries)
+      (ring-resp/response)
+      (ring-resp/content-type "application/json")))
+
+
+(def fortune-test
+  "Test 4: Fortunes"
+  (->
+    (get-fortunes)
+    (fortunes-hiccup)
+    (ring-resp/response)
+    (ring-resp/content-type "text/html")))
+
+
+(defn db-updates
+  "Test 5: Database updates"
+  [queries]
+  (-> queries
+      (update-and-persist)
+      (ring-resp/response)))
+
+
+(def plaintext
+  "Test 6: Plaintext"
+  (->
+    (ring-resp/response "Hello, World!")
+    (ring-resp/content-type "text/plain")))
+
 
 
 ;; Define route handlers
 ;; Define route handlers
 (defroutes app-routes
 (defroutes app-routes
-  (GET "/http-kit/" [] "Hello, World!")
-  (GET "/http-kit/json" [] (response {:message "Hello, World!"}))
-  (GET "/http-kit/db" []
-       (response (first (run-queries 1))))
-  (GET "/http-kit/db/:queries" [queries]
-       (response (run-queries (get-query-count queries))))
+  (GET "/"                 [] "Hello, World!")
+  (GET "/json"             [] json-serialization)
+  (GET "/db"               [] single-query-test)
+  (GET "/queries/:queries" [queries] (multiple-queries-test queries))
+  (GET "/fortunes"         [] fortune-test)
+  (GET "/updates/:queries" [queries] (db-updates queries))
+  (GET "/plaintext"        [] plaintext)
   (route/not-found "Not Found"))
   (route/not-found "Not Found"))
 
 
 
 
-(defn start-server [{:keys [port db-host]}]
-  (db/use-database! (str "jdbc:mysql://" db-host "/hello_world?jdbcCompliantTruncation=false&elideSetAutoCommits=true&useLocalSessionState=true&cachePrepStmts=true&cacheCallableStmts=true&alwaysSendSetIsolation=false&prepStmtCacheSize=4096&cacheServerConfiguration=true&prepStmtCacheSqlLimit=2048&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useUnbufferedInput=false&useReadAheadInput=false&maintainTimeStats=false&useServerPrepStmts&cacheRSMetadata=true")
-                    "benchmarkdbuser"
-                    "benchmarkdbpass")
+(defn start-server [{:keys [port]}]
   ;; Format responses as JSON
   ;; Format responses as JSON
   (let [handler (wrap-json-response app-routes)
   (let [handler (wrap-json-response app-routes)
         cpu (.availableProcessors (Runtime/getRuntime))]
         cpu (.availableProcessors (Runtime/getRuntime))]
     ;; double worker threads should increase database access performance
     ;; double worker threads should increase database access performance
-    (run-server handler {:port port :thread (* 2 cpu)})
+    (run-server handler {:port port
+                         :thread (* 2 cpu)})
     (println (str "http-kit server listens at :" port))))
     (println (str "http-kit server listens at :" port))))
 
 
+
 (defn -main [& args]
 (defn -main [& args]
   (let [[options _ banner]
   (let [[options _ banner]
         (cli args
         (cli args
-             ["-p" "--port" "Port to listen" :default 8080 :parse-fn to-int]
-             ["--db-host" "MySQL database host" :default "localhost"]
+             ["-p" "--port" "Port to listen" :default 8080 :parse-fn parse-port]
              ["--[no-]help" "Print this help"])]
              ["--[no-]help" "Print this help"])]
-    (when (:help options) (println banner) (System/exit 0))
+    (when (:help options)
+          (println banner)
+          (System/exit 0))
     (start-server options)))
     (start-server options)))

+ 9 - 5
frameworks/Clojure/http-kit/setup.sh

@@ -1,13 +1,17 @@
 #!/bin/bash
 #!/bin/bash
 source $IROOT/java7.installed
 source $IROOT/java7.installed
-export LEIN_HOME=$IROOT/lein
+source $IROOT/lein.installed
+
+
+# Update db host in the source file
+sed -i 's|:subname "//.*:3306|:subname "//'"${DBHOST}"':3306|g' hello/src/hello/handler.clj
 
 
 cd hello
 cd hello
-$LEIN_HOME/bin/lein clean
-$LEIN_HOME/bin/lein deps
+lein clean
+lein deps
 rm -rf target
 rm -rf target
 # pack all dependencies into a single jar: target/http-kit-standalone.jar
 # pack all dependencies into a single jar: target/http-kit-standalone.jar
-$LEIN_HOME/bin/lein uberjar
+lein uberjar
 # -server is much faster
 # -server is much faster
 # 'lein run' passes '-client -XX:+TieredCompilation -XX:TieredStopAtLevel=1' which make it starts fast, but runs slow
 # 'lein run' passes '-client -XX:+TieredCompilation -XX:TieredStopAtLevel=1' which make it starts fast, but runs slow
-$JAVA_HOME/bin/java -server -jar target/http-kit-standalone.jar --db-host ${DBHOST} &
+java -server -jar target/http-kit-standalone.jar  &

+ 1 - 0
frameworks/Clojure/luminus/benchmark_config.json

@@ -7,6 +7,7 @@
       "db_url": "/luminus/db",
       "db_url": "/luminus/db",
       "query_url": "/luminus/db/",
       "query_url": "/luminus/db/",
       "fortune_url": "/luminus/fortune",
       "fortune_url": "/luminus/fortune",
+      "update_url": "/luminus/update/",
       "plaintext_url": "/luminus/plaintext",
       "plaintext_url": "/luminus/plaintext",
       "port": 8080,
       "port": 8080,
       "approach": "Realistic",
       "approach": "Realistic",

+ 4 - 0
frameworks/Clojure/luminus/hello/src/hello/handler.clj

@@ -6,13 +6,16 @@
             [taoensso.timbre :as timbre]
             [taoensso.timbre :as timbre]
             [taoensso.timbre.appenders.rotor :as rotor]))
             [taoensso.timbre.appenders.rotor :as rotor]))
 
 
+
 (defroutes app-routes
 (defroutes app-routes
   (route/resources "/")
   (route/resources "/")
   (route/not-found "Not Found"))
   (route/not-found "Not Found"))
 
 
+
 (defn destroy []
 (defn destroy []
   (timbre/info "picture-gallery is shutting down"))
   (timbre/info "picture-gallery is shutting down"))
 
 
+
 (defn init
 (defn init
   "init will be called once when
   "init will be called once when
    app is deployed as a servlet on
    app is deployed as a servlet on
@@ -33,6 +36,7 @@
 
 
   (timbre/info "hello started successfully"))
   (timbre/info "hello started successfully"))
 
 
+
 (defn destroy
 (defn destroy
   "destroy will be called when your application
   "destroy will be called when your application
    shuts down, put any clean up code here"
    shuts down, put any clean up code here"

+ 44 - 22
frameworks/Clojure/luminus/hello/src/hello/models/db.clj

@@ -12,15 +12,19 @@
   (entity-fields :id :randomNumber)
   (entity-fields :id :randomNumber)
   (database db))
   (database db))
 
 
-; Query a random World record from the database
-(defn get-world []
+
+(defn get-world
+  "Query a random World record from the database"
+  []
   (let [id (inc (rand-int 9999))] ; Num between 1 and 10,000
   (let [id (inc (rand-int 9999))] ; Num between 1 and 10,000
     (select world
     (select world
             (fields :id :randomNumber)
             (fields :id :randomNumber)
             (where {:id id }))))
             (where {:id id }))))
 
 
-; Query a random World record from the database
-(defn get-world-raw []
+
+(defn get-world-raw
+  "Query a random World record from the database"
+  []
   (let [id (inc (rand-int 9999))] ; Num between 1 and 10,000
   (let [id (inc (rand-int 9999))] ; Num between 1 and 10,000
     (jdbc/with-connection (db-raw)
     (jdbc/with-connection (db-raw)
       ; Set a naming strategy to preserve column name case
       ; Set a naming strategy to preserve column name case
@@ -28,19 +32,21 @@
         (jdbc/with-query-results rs [(str "select * from world where id = ?") id]
         (jdbc/with-query-results rs [(str "select * from world where id = ?") id]
           (doall rs))))))
           (doall rs))))))
 
 
-; Run the specified number of queries, return the results
-(defn run-queries [queries]
-   (flatten ; Make it a list of maps
-    (take
-     queries ; Number of queries to run
-     (repeatedly get-world))))
 
 
-; Run the specified number of queries, return the results
+(defn run-queries
+  "Run the specified number of queries, return the results"
+  [queries]
+  (flatten ; Make it a list of maps
+    (take queries
+          (repeatedly get-world))))
+
+
 (defn run-queries-raw [queries]
 (defn run-queries-raw [queries]
-   (flatten ; Make it a list of maps
-    (take
-     queries ; Number of queries to run
-     (repeatedly get-world-raw))))
+  "Run the specified number of queries, return the results"
+  (flatten ; Make it a list of maps
+    (take queries
+          (repeatedly get-world-raw))))
+
 
 
 (defn get-query-count [queries]
 (defn get-query-count [queries]
   "Parse provided string value of query count, clamping values to between 1 and 500."
   "Parse provided string value of query count, clamping values to between 1 and 500."
@@ -60,13 +66,29 @@
   (entity-fields :id :message)
   (entity-fields :id :message)
   (database db))
   (database db))
 
 
-(defn get-all-fortunes []
+
+(def get-all-fortunes
   "Query all Fortune records from the database."
   "Query all Fortune records from the database."
-    (select fortune
-            (fields :id :message)))
+  (select fortune
+          (fields :id :message)))
+
 
 
-(defn get-fortunes []
-  "Fetch the full list of Fortunes from the database, sort them by the fortune
-   message text, and then return the results."
-  (let [fortunes (conj (get-all-fortunes) {:id 0 :message "Additional fortune added at request time."} )]
+(def get-fortunes
+  "Fetch the full list of Fortunes from the database. Insert an additional fortune at runtime.
+  Then sort all by fortune message text. Return the results."
+  (let [fortunes (conj get-all-fortunes
+                       {:id 0 :message "Additional fortune added at request time."})]
     (sort-by :message fortunes)))
     (sort-by :message fortunes)))
+
+
+(defn update-and-persist
+  "Changes the :randomNumber of a number of world entities.
+  Persists the changes to sql then returns the updated entities"
+  [queries]
+  (let [results (run-queries queries)]
+    (for [w results]
+      (update-in w [:randomNumber (inc (rand-int 9999))]
+        (update world
+                (set-fields {:randomNumber (:randomNumber w)})
+                (where {:id [:id w]}))))
+    results))

+ 68 - 12
frameworks/Clojure/luminus/hello/src/hello/routes/home.clj

@@ -4,16 +4,72 @@
   (:require [hello.views.layout :as layout]
   (:require [hello.views.layout :as layout]
             [noir.response :as response]))
             [noir.response :as response]))
 
 
-(defroutes home-routes
-  (GET "/" [] "Hello, World!")
-  (GET "/plaintext" []
-       {:status 200
-        :headers {"Content-Type" "text/plain; charset=utf-8"}
-        :body "Hello, World!"})
-  (GET "/json" [] (response/json {:message "Hello, World!"}))
-  (GET "/db" [] (response/json (first (run-queries 1))))
-  (GET "/db/:queries" [queries] (response/json (run-queries (get-query-count queries))))
-  (GET "/dbraw" [] (response/json (first (run-queries-raw 1))))
-  (GET "/dbraw/:queries" [queries] (response/json (run-queries-raw (get-query-count queries))))  
-  (GET "/fortune" [] (layout/render "home.html" {:messages (get-fortunes)})))
 
 
+(def json-serialization
+  "Test 1: JSON serialization"
+  (response/json {:message "Hello, World!"}))
+
+
+(def single-query-test
+  "Test 2: Single database query"
+  (response/json (first (run-queries 1))))
+
+
+(defn multiple-query-test
+  "Test 3: Multiple database query"
+  [queries]
+  (-> queries
+      (get-query-count)
+      (run-queries)
+      (response/json)))
+
+
+(def single-query-test-raw
+  "Test 2: Single database query (raw)"
+  (-> 1
+      (run-queries-raw)
+      (first)
+      (response/json)))
+
+
+(defn multiple-query-test-raw
+  "Test 3: Multiple database query (raw)"
+  [queries]
+  (-> queries
+      (get-query-count)
+      (run-queries-raw)
+      (response/json)))
+
+
+(def fortunes
+  "Test 4: Fortunes"
+  (layout/render "home.html"
+                 {:messages get-fortunes}))
+
+
+(defn db-update
+  "Test 5: Database updates"
+  [queries]
+  (-> queries
+      (get-query-count)
+      (update-and-persist)
+      (response/json)))
+
+
+(def plaintext
+  "Test 6: Plaintext"
+  {:status 200
+   :headers {"Content-Type" "text/plain; charset=utf-8"}
+   :body "Hello, World!"})
+
+
+(defroutes home-routes
+  (GET "/"                [] "Hello, World!")
+  (GET "/plaintext"       [] plaintext)
+  (GET "/json"            [] json-serialization)
+  (GET "/db"              [] single-query-test)
+  (GET "/db/:queries"     [queries] (multiple-query-test queries))
+  (GET "/dbraw"           [] single-query-test-raw)
+  (GET "/dbraw/:queries"  [queries] (multiple-query-test-raw queries))
+  (GET "/fortune"         [] fortunes)
+  (GET "/update/:queries" [queries] (db-update queries)))

+ 5 - 2
frameworks/Clojure/luminus/setup.sh

@@ -1,6 +1,9 @@
 #!/bin/bash
 #!/bin/bash
 
 
 source $IROOT/java7.installed
 source $IROOT/java7.installed
+
+source $IROOT/lein.installed
+
 export RESIN_HOME=${IROOT}/resin-4.0.41
 export RESIN_HOME=${IROOT}/resin-4.0.41
 
 
 # Path vars must be set here
 # Path vars must be set here
@@ -9,8 +12,8 @@ export PATH="$JAVA_HOME/bin:$PATH"
 sed -i 's|:subname "//.*:3306|:subname "//'"${DBHOST}"':3306|g' hello/src/hello/models/schema.clj
 sed -i 's|:subname "//.*:3306|:subname "//'"${DBHOST}"':3306|g' hello/src/hello/models/schema.clj
 
 
 cd hello
 cd hello
-$IROOT/lein/bin/lein clean
-$IROOT/lein/bin/lein ring uberwar
+lein clean
+lein ring uberwar
 rm -rf $RESIN_HOME/webapps/*
 rm -rf $RESIN_HOME/webapps/*
 cp target/hello-luminus-standalone.war $RESIN_HOME/webapps/luminus.war
 cp target/hello-luminus-standalone.war $RESIN_HOME/webapps/luminus.war
 $RESIN_HOME/bin/resinctl start
 $RESIN_HOME/bin/resinctl start

+ 36 - 28
frameworks/Clojure/pedestal/src/pedestal/service.clj

@@ -41,11 +41,12 @@
   (database mysql-db))
   (database mysql-db))
 
 
 
 
-(defn random-world []
+(defn random-world
   "Query a random World record from the database"
   "Query a random World record from the database"
+  []
   (let [id (inc (rand-int 9999))] ; Num between 1 and 10,000
   (let [id (inc (rand-int 9999))] ; Num between 1 and 10,000
     (select world
     (select world
-      (where {:id id }))))
+            (where {:id id }))))
 
 
 
 
 (defn run-queries
 (defn run-queries
@@ -62,26 +63,27 @@
 
 
 (defn sanitizeQueriesParam
 (defn sanitizeQueriesParam
   "Sanitizes the `queries` parameter. Caps the value between 1 and 500.
   "Sanitizes the `queries` parameter. Caps the value between 1 and 500.
-Invalid (stringy) values become 1"
+  Invalid (stringy) values become 1"
   [request]
   [request]
-  (let [queries (-> request :params :queries)]
-    (let [n
-      (if (= (re-find #"\A-?\d+" queries) nil)
-        1
-        (Integer/parseInt queries))]
-    (cond
-      (< n 1) 1
-      (> n 500) 500
-      :else n))))
+  (let [queries (-> request
+                    :params
+                    :queries)]
+    (if-let [n (if (= (re-find #"\A-?\d+" queries) nil)
+                   1
+                   (Integer/parseInt queries))]
+      (cond
+        (< n 1) 1
+        (> n 500) 500
+        :else n))))
 
 
 
 
 (defn multiple-query-test
 (defn multiple-query-test
   "Test 3: Multiple database queries"
   "Test 3: Multiple database queries"
   [request]
   [request]
   (-> request
   (-> request
-    (sanitizeQueriesParam)
-    (run-queries)
-    (bootstrap/json-response)))
+      (sanitizeQueriesParam)
+      (run-queries)
+      (bootstrap/json-response)))
 
 
 
 
 ; Set up entity Fortune and the database representation
 ; Set up entity Fortune and the database representation
@@ -92,23 +94,26 @@ Invalid (stringy) values become 1"
   (database mysql-db))
   (database mysql-db))
 
 
 
 
-(defn get-all-fortunes []
+(defn get-all-fortunes
   "Query all Fortune records from the database."
   "Query all Fortune records from the database."
+  []
   (select fortune
   (select fortune
-    (fields :id :message)))
+          (fields :id :message)))
 
 
 
 
-(defn get-fortunes []
+(defn get-fortunes
   "Fetch the full list of Fortunes from the database, sort them by the fortune
   "Fetch the full list of Fortunes from the database, sort them by the fortune
-message text, and then return the results."
+  message text, and then return the results."
+  []
   (sort-by #(:message %)
   (sort-by #(:message %)
     (conj
     (conj
       (get-all-fortunes)
       (get-all-fortunes)
       { :id 0 :message "Additional fortune added at request time." })))
       { :id 0 :message "Additional fortune added at request time." })))
 
 
 
 
-(defn fortunes-hiccup [fortunes]
+(defn fortunes-hiccup
   "Render the given fortunes to simple HTML using Hiccup."
   "Render the given fortunes to simple HTML using Hiccup."
+  [fortunes]
   (html5
   (html5
    [:head
    [:head
     [:title "Fortunes"]]
     [:title "Fortunes"]]
@@ -124,8 +129,9 @@ message text, and then return the results."
      ]]))
      ]]))
 
 
 
 
-(defn fortune-test [request]
+(defn fortune-test
   "Test 4: Fortunes"
   "Test 4: Fortunes"
+  [request]
   (->
   (->
     (get-fortunes)
     (get-fortunes)
     (fortunes-hiccup)
     (fortunes-hiccup)
@@ -136,23 +142,25 @@ message text, and then return the results."
 
 
 (defn update-and-persist
 (defn update-and-persist
   "Changes the :randomNumber of a number of world entities.
   "Changes the :randomNumber of a number of world entities.
-Persists the changes to sql then returns the updated entities"
+  Persists the changes to sql then returns the updated entities"
   [request]
   [request]
-  (let [results (-> request (sanitizeQueriesParam) (run-queries))]
+  (let [results (-> request
+                    (sanitizeQueriesParam)
+                    (run-queries))]
     (for [w results]
     (for [w results]
       (update-in w [:randomNumber (inc (rand-int 9999))]
       (update-in w [:randomNumber (inc (rand-int 9999))]
         (update world
         (update world
-          (set-fields {:randomNumber (:randomNumber w)})
-          (where {:id [:id w]}))))
-  results))
+                (set-fields {:randomNumber (:randomNumber w)})
+                (where {:id [:id w]}))))
+    results))
 
 
 
 
 (defn db-updates
 (defn db-updates
   "Test 5: Database updates"
   "Test 5: Database updates"
   [request]
   [request]
   (-> request
   (-> request
-    (update-and-persist)
-    (bootstrap/json-response)))
+      (update-and-persist)
+      (bootstrap/json-response)))
 
 
 
 
 (defn plaintext
 (defn plaintext

+ 1 - 2
toolset/benchmark/test_types/framework_test_type.py

@@ -77,9 +77,8 @@ class FrameworkTestType:
   def _curl_body(self, url):
   def _curl_body(self, url):
     '''Downloads a URL and returns the HTTP body'''
     '''Downloads a URL and returns the HTTP body'''
     # Use -m 15 to make curl stop trying after 15sec.
     # Use -m 15 to make curl stop trying after 15sec.
-    # Use -i to output response with headers
     # Don't use -f so that the HTTP response code is ignored.
     # Don't use -f so that the HTTP response code is ignored.
-    # Use -sS to hide progress bar, but show errors.
+    # Use -s to hide progress bar
     # Get response body
     # Get response body
     p = subprocess.Popen(["curl", "-m", "15", "-s", url], stdout=PIPE, stderr=PIPE)
     p = subprocess.Popen(["curl", "-m", "15", "-s", url], stdout=PIPE, stderr=PIPE)
     (out, err) = p.communicate()
     (out, err) = p.communicate()