Browse Source

Merge pull request #902 from idlewan/nimrod_nawak

Nimrod and nawak fixes
Alexander Schneider 11 years ago
parent
commit
7da822e469

+ 68 - 0
nawak/app.nim

@@ -0,0 +1,68 @@
+import strtabs, strutils, math, algorithm
+import nawak_mongrel, jdump
+import fortunes_tmpl
+when defined(postgre_model):
+    import model_postgre
+
+get "/json":
+    var j: THello
+    j.message = "Hello, World!"
+    # jdump serialize the tuples of the model as json
+    return response(jdump(j), "application/json")
+
+get "/plaintext":
+    return response("Hello, World!", "text/plain")
+
+get "/db":
+    let w = getWorld(random(10_000)+1)
+    return response(jdump(w), "application/json")
+
+get "/fortunes":
+    var fortunes = getAllFortunes()
+    let new_fortune: TFortune =
+        (id: 0,
+         message: "Additional fortune added at request time.")
+    fortunes.add new_fortune
+    sort(fortunes, proc(x, y: TFortune): int =
+        return cmp(x.message, y.message))
+
+    return response(fortunes_tmpl(fortunes), "text/html; charset=utf-8")
+
+
+proc limit_queries(query_params: PStringTable): int =
+    result = 1
+    if query_params.hasKey("queries"):
+        try:
+            result = parseInt(query_params["queries"])
+        except EInvalidValue: discard
+        # clamp the number of queries
+        if result < 1: result = 1
+        elif result > 500: result = 500
+
+get "/queries":
+    let queries = limit_queries(request.query)
+
+    var world: seq[TWorld]
+    world.newSeq(queries)
+    for i in 0.. <queries:
+        world[i] = getWorld random(10_000) + 1
+    return response(jdump(world), "application/json")
+
+get "/updates":
+    let queries = limit_queries(request.query)
+
+    var world: seq[TWorld]
+    world.newSeq(queries)
+    for i in 0.. <queries:
+        world[i] = getWorld(random(10_000) + 1)
+        world[i].randomNumber = random(10_000) + 1
+        updateWorld world[i]
+
+    return response(jdump(world), "application/json")
+
+custom_page 404:
+    # customize the content of the 404 page
+    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)

+ 1 - 1
nawak/fortunes_tmpl.nim

@@ -1,6 +1,6 @@
 #! stdtmpl | standard
 #import lib/escape
-#from nawak_app import TFortune
+#import model
 #proc fortunes_tmpl*(fortunes: openArray[TFortune]): string =
 #  result = ""
 <!DOCTYPE html>

+ 3 - 0
nawak/model.nim

@@ -0,0 +1,3 @@
+type THello* = tuple[message: string]
+type TWorld* = tuple[id: int, randomNumber: int]
+type TFortune* = tuple[id: int, message: string]

+ 43 - 0
nawak/model_postgre.nim

@@ -0,0 +1,43 @@
+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 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"
+
+var db {.threadvar.}: TDbConn
+var qworld_prepared {.threadvar.}: TPreparedId
+var qfortunes_prepared {.threadvar.}: TPreparedId
+var qupdates_prepared {.threadvar.}: TPreparedId
+
+proc init_db*() {.procvar.} =
+    db = open("", "benchmarkdbuser", "benchmarkdbpass",
+              "host=localhost port=5432 dbname=hello_world")
+    # prepare queries
+    qworld_prepared = db.prepare("world", qworld, 1)
+    qfortunes_prepared = db.prepare("fortunes", qfortunes, 0)
+    qupdates_prepared = db.prepare("updates", qupdates, 2)
+
+
+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)
+    result.id = parseInt(row[0])
+    result.randomNumber = parseInt(row[1])
+
+proc updateWorld*(w: TWorld) =
+    db.Exec(qupdates_prepared, $w.randomNumber, $w.id)
+
+proc getAllFortunes*(): seq[TFortune] =
+    let rows = db.getAllPRows(qfortunes_prepared)
+    result.newSeq(rows.len)
+    for j, row in rows.pairs:
+        result[j] = (row[0].parseInt, row[1])

+ 0 - 103
nawak/nawak_app.nim

@@ -1,103 +0,0 @@
-import strtabs, strutils, math, algorithm
-import nawak_mongrel, jdump
-
-# 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
-
-type THello = tuple[message: string]
-type TWorld = tuple[id: int, randomNumber: int]
-type TFortune* = tuple[id: int, message: string]
-
-proc unrowTWorld(x: TRow): TWorld =
-    result.id = parseInt(x[0])
-    result.randomNumber = parseInt(x[1])
-proc unrowTFortune(x: TRow): TFortune =
-    return (x[0].parseInt, x[1])
-
-import fortunes_tmpl  # Needs TFortune to be defined first
-
-var db = open("", "benchmarkdbuser", "benchmarkdbpass", "host=localhost port=5432 dbname=hello_world")
-
-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"
-
-# prepare queries
-let qworld_prepared = db.prepare("world", qworld, 1)
-let qfortunes_prepared = db.prepare("fortunes", qfortunes, 0)
-let qupdates_prepared = db.prepare("updates", qupdates, 2)
-
-
-get "/json":
-    var j: THello
-    j.message = "Hello, World!"
-    # jdump serialize any tuple as json
-    return response(jdump(j), "application/json")
-
-get "/plaintext":
-    return response("Hello, World!", "text/plain")
-
-
-get "/db":
-    let row = db.getPRow(qworld_prepared, random(10_000)+1)
-    var r = unrowTWorld(row)
-    return response(jdump(r), "application/json")
-
-#get "/db_unprepared":
-#    ## Yes, prepared queries are faster than unprepared ones
-#    var r = unrowTWorld( db.getRow(qworld, random(10_000) + 1) )
-#    return response(jdump(r), "application/json")
-
-get "/queries":
-    var queries = 1
-    if request.query.hasKey("queries"):
-        try:
-            queries = parseInt(request.query["queries"])
-        except EInvalidValue: discard
-        if queries < 1: queries = 1
-        elif queries > 500: queries = 500
-
-    var world: seq[TWorld]
-    world.newSeq(queries)
-    for i in 0.. <queries:
-        let row = db.getPRow(qworld_prepared, random(10_000) + 1)
-        world[i] = unrowTWorld(row)
-    return response(jdump(world), "application/json")
-
-get "/fortunes":
-    let rows = db.getAllPRows(qfortunes_prepared)
-    var fortunes: seq[TFortune]
-    fortunes.newSeq(rows.len)
-    for j, row in rows.pairs:
-        fortunes[j] = unrowTFortune(row)
-    let new_fortune: TFortune = (id: 0,
-                                 message: "Additional fortune added at request time.")
-    fortunes.add new_fortune
-    sort(fortunes, proc(x, y: TFortune): int =
-        return cmp(x.message, y.message))
-
-    return response(fortunes_tmpl(fortunes), "text/html; charset=utf-8")
-
-get "/updates":
-    var queries = 1
-    if request.query.hasKey("queries"):
-        try:
-            queries = parseInt(request.query["queries"])
-        except EInvalidValue: discard
-        if queries < 1: queries = 1
-        elif queries > 500: queries = 500
-
-    var world: seq[TWorld]
-    world.newSeq(queries)
-    for i in 0.. <queries:
-        world[i] = unrowTWorld(db.getPRow(qworld_prepared, random(10_000) + 1))
-        world[i].randomNumber = random(10_000) + 1
-        db.Exec(qupdates_prepared, $world[i].randomNumber, $world[i].id)
-
-    return response(jdump(world), "application/json")
-
-
-run()

+ 9 - 8
nawak/setup.py

@@ -7,18 +7,19 @@ from os.path import expanduser
 home = expanduser("~")
 
 def start(args, logfile, errfile):
+  setup_util.replace_text("nawak/model_postgre.nim", "host=.* port=5432",
+                          "host=" + args.database_host + " port=5432")
   # compile the app
-  setup_util.replace_text("nawak/nawak_app.nim", "host=.* port=5432", "host=" + args.database_host + " port=5432")
-  subprocess.check_call("nimrod c -d:release --path:../installs/nawak/nawak nawak_app.nim",
-                        shell=True, cwd="nawak", stderr=errfile, stdout=logfile)
+  subprocess.check_call(
+      "nimrod c --threads:on -d:release -d:postgre_model --path:../installs/nawak/nawak -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)
-  subprocess.check_call("m2sh load -config mongrel2.conf", shell=True, cwd="nawak/conf", stderr=errfile, stdout=logfile)
+  subprocess.check_call("sudo m2sh load -config mongrel2.conf", shell=True, cwd="nawak/conf", stderr=errfile, stdout=logfile)
   subprocess.check_call("sudo m2sh start -name test", shell=True, cwd="nawak/conf", stderr=errfile, stdout=logfile)
   
-  for i in range(1, 43):
-    # launch workers
-    subprocess.Popen("./nawak_app " + str(i), shell=True, cwd="nawak", stderr=errfile, stdout=logfile)
+  # launch workers
+  subprocess.Popen("./nawak_postgre", shell=True, cwd="nawak", stderr=errfile, stdout=logfile)
   return 0
 
 def stop(logfile, errfile):
@@ -32,7 +33,7 @@ def stop(logfile, errfile):
   p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
   out, err = p.communicate()
   for line in out.splitlines():
-    if 'nawak_app' in line:
+    if 'nawak_postgre' in line:
       try:
         pid = int(line.split(None, 2)[1])
         os.kill(pid, 15)

+ 3 - 2
toolset/setup/linux/languages/nimrod.sh

@@ -5,11 +5,11 @@ RETCODE=$(fw_exists nimrod/bin/nimrod)
 
 test -d nimrod || git clone git://github.com/Araq/Nimrod.git nimrod
 cd nimrod 
-git checkout 987ac2439a87d74838233a7b188e4db340495ee5
+git checkout 887a1ebe688a01259263ad6e11c9061cfc940456
 test -d csources || git clone git://github.com/nimrod-code/csources.git
 
 cd csources
-git checkout 704015887981932c78a033dd5ede623b2ad6ae27
+git checkout 0a6e5758ed16bf906fcfdb9e64086edd9b60c5c0
 chmod +x build.sh
 ./build.sh
 
@@ -20,3 +20,4 @@ RETCODE=$(fw_exists nimrod/koch)
 cd nimrod
 bin/nimrod c koch
 ./koch boot -d:release
+sudo ./koch install /usr/bin

+ 3 - 3
toolset/setup/linux/webservers/mongrel2.sh

@@ -8,6 +8,9 @@ fw_depends zeromq
 # Dependencies
 sudo apt-get install -y sqlite3 libsqlite3-dev uuid uuid-runtime uuid-dev
 
+# Update linker cache
+sudo ldconfig -v
+
 fw_get https://github.com/zedshaw/mongrel2/tarball/v1.8.1 -O mongrel2.tar.gz
 fw_untar mongrel2.tar.gz
 
@@ -21,6 +24,3 @@ mv -f zmq_compat.h mongrel2/src/
 cd mongrel2
 make clean all
 sudo make install
-
-# Update linker cache
-sudo ldconfig -v