Browse Source

db test working

Keith Newman 10 năm trước cách đây
mục cha
commit
68bb9af5d3

+ 93 - 11
frameworks/Python/cherrypy/app.py

@@ -1,18 +1,100 @@
-#!/usr/bin/env python
+import os
+from functools import partial
+from operator import attrgetter
+from random import randint
+import json
+
 import cherrypy
+from sqlalchemy.ext.declarative import declarative_base
+from sqlalchemy import Column
+from sqlalchemy.types import String, Integer
+
+Base = declarative_base()
+
+class Fortune(Base):
+  __tablename__ = "fortune"
+
+  id = Column(Integer, primary_key = True)
+  message = Column(String)
+
+class World(Base):
+  __tablename__ = "world"
+
+  id = Column(Integer, primary_key = True)
+  randomNumber = Column(Integer)
+
+  def serialize(self):
+    return {
+      'id' : self.id,
+      'randomNumber' : self.randomNumber
+    }
 
 class CherryPyBenchmark(object):
 
-    @cherrypy.expose
-    @cherrypy.tools.json_out()
-    def json(self):
-        cherrypy.response.headers["Content-Type"] = "application/json"
-        json_message = {"message": "Hello, world!"}
-        return json_message  
+  @cherrypy.expose
+  @cherrypy.tools.json_out()
+  def json(self):
+    cherrypy.response.headers["Content-Type"] = "application/json"
+    json_message = {"message" : "Hello, world!"}
+    return json_message
 
-    @cherrypy.expose    
-    def plaintext(self):
-        return "Hello, world!"
+
+  @cherrypy.expose
+  def plaintext(self):
+    return "Hello, world!"
+
+  @cherrypy.expose
+  @cherrypy.tools.json_out()
+  def db(self):
+    cherrypy.response.headers["Content-Type"] = "application/json"
+    wid = randint(1, 10000)
+    world = cherrypy.request.db.query(World).get(wid).serialize()
+    return world
+
+  @cherrypy.expose
+  @cherrypy.tools.json_out()
+  def queries(self, queries=1):
+    num_queries = int(queries)
+    if num_queries < 1:
+      num_queries = 1
+    if num_queries > 500:
+      num_queries = 500
+
+    rp = partial(randint, 1, 10000)
+    get = cherrypy.request.db.query(World).get
+    worlds = [get(rp()).serialize() for _ in xrange(num_queries)]
+    return worlds
+
+  @cherrypy.expose
+  @cherrypy.tools.json_out()
+  def updates(self, queries=1):
+    cherrypy.response.headers["Content-Type"] = "application/json"
+    num_queries = int(queries)
+    if num_queries < 1:
+      num_queries = 1
+    if num_queries > 500:
+      num_queries = 500
+
+    worlds = []
+    rp = partial(randint, 1, 10000)
+    ids = [rp() for _ in xrange(num_queries)]
+    ids.sort() # To avoid deadlock
+    for id in ids:
+      world = cherrypy.request.db.query(World).get(id)
+      world.randomNumber = rp()
+      worlds.append(world.serialize())
+    return worlds
 
 if __name__ == "__main__":
-    cherrypy.quickstart(CherryPyBenchmark())
+    print "HELLOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO~~~~~~~~~~~~~~"
+    # Register the SQLAlchemy plugin
+    from saplugin import SAEnginePlugin
+    DBDRIVER = 'mysql'
+    DBHOSTNAME = os.environ.get('DBHOST', 'localhost')  
+    DATABASE_URI = '%s://benchmarkdbuser:benchmarkdbpass@%s:3306/hello_world?charset=utf8' % (DBDRIVER, DBHOSTNAME)
+    SAEnginePlugin(cherrypy.engine, DATABASE_URI).subscribe()
+
+    # Register the SQLAlchemy tool
+    from satool import SATool
+    cherrypy.tools.db = SATool()
+    cherrypy.quickstart(CherryPyBenchmark(), '', {'/': {'tools.db.on': True}})

+ 6 - 0
frameworks/Python/cherrypy/benchmark_config

@@ -4,6 +4,9 @@
     "default": {
       "setup_file": "setup",
       "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/queries?quries=",
+      "update_url": "/updates?queries=",
       "plaintext_url": "/plaintext",
       "port": 8080,
       "approach": "Realistic",
@@ -22,6 +25,9 @@
      "py3": {
       "setup_file": "setup_py3",
       "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/queries?quries=",
+      "update_url": "/updates?queries=",
       "plaintext_url": "/plaintext",
       "port": 8080,
       "approach": "Realistic",

+ 1 - 1
frameworks/Python/cherrypy/install.sh

@@ -7,5 +7,5 @@ fw_depends python2 python3
 
 $PY2_PIP install --install-option="--prefix=${PY2_ROOT}" -r $TROOT/requirements.txt
 
-$PY3_PIP install --install-option="--prefix=${PY3_ROOT}" -r $TROOT/requirements.txt
+#$PY3_PIP install --install-option="--prefix=${PY3_ROOT}" -r $TROOT/requirements.txt
 

+ 3 - 0
frameworks/Python/cherrypy/requirements.txt

@@ -1 +1,4 @@
 cherrypy==3.6.0
+SQLAlchemy==0.9.9
+mysqlclient==1.3.1
+MySQL-python==1.2.5

+ 61 - 0
frameworks/Python/cherrypy/saplugin.py

@@ -0,0 +1,61 @@
+import cherrypy
+from cherrypy.process import wspbus, plugins
+from sqlalchemy import create_engine
+from sqlalchemy.orm import scoped_session, sessionmaker
+
+__all__ = ['SAEnginePlugin']
+        
+class SAEnginePlugin(plugins.SimplePlugin):
+    def __init__(self, bus, connection_string=None):
+        """
+        The plugin is registered to the CherryPy engine and therefore
+        is part of the bus (the engine *is* a bus) registery.
+ 
+        We use this plugin to create the SA engine. At the same time,
+        when the plugin starts we create the tables into the database
+        using the mapped class of the global metadata.
+        """
+        plugins.SimplePlugin.__init__(self, bus)
+        self.sa_engine = None
+        self.connection_string = connection_string
+        self.session = scoped_session(sessionmaker(autoflush=True,
+                                                   autocommit=False))
+ 
+    def start(self):
+        self.bus.log('Starting up DB access')
+        self.sa_engine = create_engine(self.connection_string, echo=False)
+        self.bus.subscribe("bind-session", self.bind)
+        self.bus.subscribe("commit-session", self.commit)
+ 
+    def stop(self):
+        self.bus.log('Stopping down DB access')
+        self.bus.unsubscribe("bind-session", self.bind)
+        self.bus.unsubscribe("commit-session", self.commit)
+        if self.sa_engine:
+            self.sa_engine.dispose()
+            self.sa_engine = None
+ 
+    def bind(self):
+        """
+        Whenever this plugin receives the 'bind-session' command, it applies
+        this method and to bind the current session to the engine.
+
+        It then returns the session to the caller.
+        """
+        self.session.configure(bind=self.sa_engine)
+        return self.session
+
+    def commit(self):
+        """
+        Commits the current transaction or rollbacks if an error occurs.
+
+        In all cases, the current session is unbound and therefore
+        not usable any longer.
+        """
+        try:
+            self.session.commit()
+        except:
+            self.session.rollback()  
+            raise
+        finally:
+            self.session.remove()

+ 46 - 0
frameworks/Python/cherrypy/satool.py

@@ -0,0 +1,46 @@
+import cherrypy
+
+__all__ = ['SATool']
+
+class SATool(cherrypy.Tool):
+    def __init__(self):
+        """
+        The SA tool is responsible for associating a SA session
+        to the SA engine and attaching it to the current request.
+        Since we are running in a multithreaded application,
+        we use the scoped_session that will create a session
+        on a per thread basis so that you don't worry about
+        concurrency on the session object itself.
+ 
+        This tools binds a session to the engine each time
+        a requests starts and commits/rollbacks whenever
+        the request terminates.
+        """
+        cherrypy.Tool.__init__(self, 'on_start_resource',
+                               self.bind_session,
+                               priority=20)
+ 
+    def _setup(self):
+        cherrypy.Tool._setup(self)
+        cherrypy.request.hooks.attach('on_end_resource',
+                                      self.commit_transaction,
+                                      priority=80)
+ 
+    def bind_session(self):
+        """
+        Attaches a session to the request's scope by requesting
+        the SA plugin to bind a session to the SA engine.
+        """
+        session = cherrypy.engine.publish('bind-session').pop()
+        cherrypy.request.db = session
+ 
+    def commit_transaction(self):
+        """
+        Commits the current transaction or rolls back
+        if an error occurs. Removes the session handle
+        from the request's scope.
+        """
+        if not hasattr(cherrypy.request, 'db'):
+            return
+        cherrypy.request.db = None
+        cherrypy.engine.publish('commit-session')