SQLite Server

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
tabellar
User
Beiträge: 186
Registriert: Mittwoch 4. September 2002, 15:28

Leonidas hat geschrieben:Das ist natürlich eine tolle Sache, nur wird sowas schnell kompliziert und je komplizierter, desto schwieriger und aufwendiger zu implementieren. Und Anfällig wird sowas auch gerne.
tabellar hat geschrieben:Also, die Hauptknacknuss ist die Transportschicht zwischen den Services. Wie flexibel muss sie sein, wie schnell, wie stabil, DB Logging? Fremdmodule? :roll:
Naja, die Transportschicht wäre, wenn alle Services auf einem Server laufen, recht stabil. Also mit der flexibilität sollte man auch nicht übertreiben, denn man kann sie ja erweitern, das ist das tolle an Python. Fremdmodule sind zu vermeiden (besonders C-Erweiterungen), aber wenn sie viel helfen ist das auch in Ordnung.
Mit "Transportschicht" habe ich nicht unbedingt damit gemeint, dass die Services auf unterschiedlichen Rechnern laufen, sonder wie der Aufruf von Funktionen innerhalb des Programmes gehandelt wird. Sprich, ob hard codiert oder "etwas flexibler". Also gut, bleiben wir einfach :wink:.

Mich würde eine "Server Schnittstelle" mit asyncore interessieren. Das kann auch ruhig in Richtung SimpleAsyncHTTP Modul gehen... Funktioniert das Senden und Empfangen von "Client Daten", könnte man PySqlite2 als DB API dazwischen schalten (wie Du es ja bereits beim SQLator v0.0.0.1 :wink: schon gemacht hast). Bei Bedarf kann dann ein Programm Paket integriert werden, das die User- und IP Verwaltung übernimmt, z.B. in separaten Tabellen oder in einfachen Text (XML) Files.

Programmteile:
- client/Server Paket (asyncore)
- Kern / Main Paket
- pysqlite2 DB API 2.0 Modul
- user/ip Paket

Hast Du schon asyncore Erfahrungen?

Gruss Tabellar
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

tabellar hat geschrieben:Hast Du schon asyncore Erfahrungen?
Nein, aber ich vermute das wäre auch ein Fall für asynchat.
Ich könnte schon etwas testen, jedoch habe ich mit Netzwerkprogrammierung "am socket" eher schlechte Erfahrungen gemacht.. warscheinlich bin ich zu doof dafür.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
tabellar
User
Beiträge: 186
Registriert: Mittwoch 4. September 2002, 15:28

Die Sache hat mir keine Ruhe gelassen. Ich glaub, wir haben jetzt die kleinste und einfachste Form eines TCP-Socket Deamons :P :

Weitere Schritte:
- Sessionhandling für einzelne Clientanfragen
- Erhöhung des Buffers für Datenübertragungen > 1024 --> [erledigt]
- User Authorizierung
- Command Line Interface (CLI) Befehlssatz festlegen
- Erhöhung der Funktionalität des SQLatorD -> select, asyncore, asynchat, etc.


[SQLatorD]

Code: Alles auswählen

#!/usr/bin/env python
# -*- encoding: latin-1 -*-
"""SQLatorD - the SQLator daemon
2005-06-24: A quick dirty TCP-Socket server for SQLite by Tabellar
2005-06-13: A XML-RPC server for the SQLite database by Leonidas
"""

import socket
from pysqlite2 import dbapi2 as sqlite

class SQLator(object):
   def __init__(self):
       self.port=8082
       self.dbfile="testdb.sqlite"
       try: 
         self.con=sqlite.connect(self.dbfile)
         print "SQLiteDB '" + self.dbfile + "' connected..."
       except:
         print "SQLiteDB " + self.dbfile + " connection failed..."

   def run(self):
       """---"""
       self.run=1
       self.sock=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
       self.sock.bind(("",self.port))
       print "SQLatorD waiting on port:", self.port
       
       while self.run:
           data,addr = self.sock.recvfrom(1024)
           #addr=Tupel ("text",portnr)         
           try:
             result=self.sqlExecute(data)
             print str(result)
             self.sendData(str(result),addr)
           except:
             print "Abfragefehler..."
             self.sendData("Abfragefehler...",addr)
     
   def sqlExecute(self,sql):
       cur=self.con.cursor()
       cur.execute(sql)
       resultList=cur.fetchall()
       self.con.commit()
       return resultList

   def sendData(self,data,addr):
       BUFSIZE = 1024
       while data:
             self.sock.sendto(data[:BUFSIZE], addr)
             data = data[BUFSIZE:]

def main():
    sqls=SQLator()
    sqls.run()

if __name__ == '__main__':
    main()


[SQLatorC]

Code: Alles auswählen

#!/usr/bin/env python
# -*- encoding: latin-1 -*-
"""SQLatorC - the SQLator client
2005-06-24: A TCP-Socket client for the SQLator Daemon by Tabellar   
2005-06-13: A client for the SQLator Daemon, for using SQLite over network by Leonidas
"""

import socket,sys

port = 8082
host = "localhost"
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(("", 0))

intro = """SQLator remote shell
Enter ".help" for instructions"""

def dotparse(command):
    if command == 'quit':
        s.close()
        sys.exit()
    elif command == 'help':
        help()
    else:
        print 'No such command'

def help():
    helptext = {'.help' : 'Show this message', 
        '.quit' : 'Exit this program'}
    for key in helptext.keys():
        print key, helptext[key]
    #print textwrap.wrap(helptext)

def sendQuery(query):
    s.sendto(query, (host, port))
    data=''
    BUFSIZE=1024
    while BUFSIZE==1024:
          sockData=s.recv(1024)
          data=data+sockData
          BUFSIZE=len(sockData)
    return data


def main():
    print intro
    while True:
        query = raw_input('sqlator> ')
        if query.startswith('.'):
            # parse, without the dot
            dotparse(query[1:])
        else:
            print sendQuery(query)


if __name__ == '__main__':
    main()

    
C:\Programme\sqlator>SQLatorD.py
SQLiteDB 'testdb.sqlite' connected...
SQLatorD waiting on port: 8082
[(1, None, 0, u'test Workflow', 1, 0)]
[(1, None, 0, u'test Workflow', 1, 0)]
Gentux1 root # python SQlatorC.py
SQLator remote shell
Enter ".help" for instructions
sqlator> select * from twfInst;
[(1, None, 0, u'test Workflow', 1, 0)]
sqlator>
Ich hätte nie gedacht, dass ich das mal hinbekommen würde ... :P Erste Tests mit Zugriff von Linux auf Win via LAN und Linux auf WIN via VPN funktionierten problemlos... und vor allem ist das ganze auch ganz schön schnell...

Grüsse Tabellar

EDIT:
- SQL Befehle "INSERT, etc." funktionieren (SQL query wird immer commited...)
- Datenpakete > 1024 Bytes können nun übertragen werden (Test 73kB)
Zuletzt geändert von tabellar am Freitag 24. Juni 2005, 19:46, insgesamt 2-mal geändert.
querdenker
User
Beiträge: 424
Registriert: Montag 28. Juli 2003, 16:19
Wohnort: /dev/reality

tabellar hat geschrieben:...Ich bin gerade an einem Thema dran, wo ich einen richtig schnellen, threadsicheren Server mit vielen DB Zugriffen brauchen könnte, aber natürlich in Python. Es geht um "Reaktive Systeme" (EventHandling) und "Workflowmanagement" und entsprechend vielen DB Zugriffen. Vielleicht mach ich dazu mal einen Thread in "Showcase" oder "Ideen" auf. Gibt's vielleicht den einen oder anderen Interessenten ? Ich würd mich freuen :wink: !!!

Tabellar
Bei der Geschichte melde ich mal Interesse an.
Und hab auch noch einen Vorschlag für die DB: FirebirdSQL
Wir haben das DB-System im Dauereinsatz, Installation ist sowohl unter Win* als auch unter Unix einfach und klein (ca 10 MB).
Und die Python-Seite ist mit KInterbasdb auch gut unterstützt.

mfg, querdenker
tabellar
User
Beiträge: 186
Registriert: Mittwoch 4. September 2002, 15:28

querdenker hat geschrieben:Bei der Geschichte melde ich mal Interesse an.
Und hab auch noch einen Vorschlag für die DB: FirebirdSQL
Wir haben das DB-System im Dauereinsatz, Installation ist sowohl unter Win* als auch unter Unix einfach und klein (ca 10 MB).
Und die Python-Seite ist mit KInterbasdb auch gut unterstützt.

mfg, querdenker
Hallo querdenker,

freut mich, dass Du Interesse an der Geschichte hast :wink: . Was speziell würde Dich an den von mir genannten Themen reizen? Firebird habe ich mal eine zeitlang beobachtet, aber nie wirklich eingesetzt. Die DB für das Backend ist auch erst in zweiter Linie von Bedeutung. Wie sagte schon Leonidas: "First get it running. Then make it running good." Ich denke, dass ich die nächsten Tage mal das Projekt im "Ideen" Bereich vorstelle. Das ganze ist ziemlich umfangreich und komplex, aber macht unheimlich viel Spass... :P

Gruss Tabellar
tabellar
User
Beiträge: 186
Registriert: Mittwoch 4. September 2002, 15:28

- SQLatorD kann jetzt Datenpakete > 1024 Bytes versenden.
- SQLatorC kann jetzt Datenpakete > 1024 Bytes empfangen.

Tabellar :wink:
querdenker
User
Beiträge: 424
Registriert: Montag 28. Juli 2003, 16:19
Wohnort: /dev/reality

@tabellar:
Interesse besteht eigentlich in allen 3 Bereichen, d.h. EventManagment, Workflow und DB.

Magst du mir mal ein wenig mehr darüber erzählen?

mfg, querdenker
tabellar
User
Beiträge: 186
Registriert: Mittwoch 4. September 2002, 15:28

querdenker hat geschrieben:@tabellar:
Interesse besteht eigentlich in allen 3 Bereichen, d.h. EventManagment, Workflow und DB.

Magst du mir mal ein wenig mehr darüber erzählen?

mfg, querdenker
@querdenker:
Im Ideen Bereich hab ich mal ein bisschen was geschrieben... :wink:

@Leonidas:
Beim SQLator würdest Du ja gerne die Socket Geschichte mit XML-RPC verbinden. Das würde aber auch bedeuten, dass der Server entsprechende "Objektmethoden" zur Verfügung stellen müsste. Wie und was würdest Du Dir da vorstellen?

Tabellar
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

tabellar hat geschrieben:Beim SQLator würdest Du ja gerne die Socket Geschichte mit XML-RPC verbinden. Das würde aber auch bedeuten, dass der Server entsprechende "Objektmethoden" zur Verfügung stellen müsste. Wie und was würdest Du Dir da vorstellen?
Ich würde vermutlich einfach mal draufloshacken und gucken was gerade nötig ist. Wenn ich mal wieder Zeit habe (und diese Woche ist ziemlich stressig) könnte ich mal versuchen einen Proof-of-Concept zu schreiben.

Ich weiß, das Vorgehen ist vielleicht nicht besonders sauber, jedoch denke ich, dass ich mich so am besten in die Anforderungen und Probleme einarbeiten könnte.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
tabellar
User
Beiträge: 186
Registriert: Mittwoch 4. September 2002, 15:28

Leonidas hat geschrieben:Ich würde vermutlich einfach mal draufloshacken und gucken was gerade nötig ist. Wenn ich mal wieder Zeit habe (und diese Woche ist ziemlich stressig) könnte ich mal versuchen einen Proof-of-Concept zu schreiben.
Ich hab schon mal "etwas" vorgegriffen und eine einfache XML-RPC-Socket Version gebastelt :wink: : Der XML-RPC SQLator verfügt jetzt über eine Objektmethode "selectCurFetchAll", die abgerufen werden kann.

Code: Alles auswählen

#!/usr/bin/env python
# -*- encoding: latin-1 -*-
"""SQLatorD - the SQLator daemon
2005-06-30: A quick dirty XML-RPC Socket Server by Tabellar
2005-06-24: A quick dirty TCP-Socket server for SQLite by Tabellar
2005-06-13: A XML-RPC server for the SQLite database by Leonidas
"""

import socket
import xmlrpclib
from pysqlite2 import dbapi2 as sqlite

class SQLator(object):
   def __init__(self):
       self.port=8082
       self.dbfile="testdb.sqlite"
       try:
         self.con=sqlite.connect(self.dbfile)
         print "SQLiteDB '" + self.dbfile + "' connected..."
       except:
         print "SQLiteDB " + self.dbfile + " connection failed..."

   def run(self):
       """---"""
       self.run=1
       self.mainsock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
       self.mainsock.bind(("",self.port))
       self.mainsock.listen(1) #max 1 Verbindung gleichzeitig 
       print "SQLatorD waiting on port:", self.port
       
       while self.run:
           connection,address=self.mainsock.accept()
           print "Server connected by ",address
           while 1:
               data = connection.recv(1024)
               if not data: break
               print "received: ",data         
               params,method=xmlrpclib.loads(data)
               print "Method:",method
               print "Params:",params
            
               try:
                 if method=="selectCurFetchAll":
                    result=self.selectCurFetchAll(params)
                    response=xmlrpclib.dumps(((str(result[0])),(str(result[1]))),"selectCurFetchAll")
                    connection.send(response)
                 else:
                    connection.send("Methode nicht erkannt")

               except:
                 print "Abfragefehler..."
                 connection.send("Abfragefehler...")
           print "connection closed..."
           connection.close()

   def selectCurFetchAll(self,sqlquery):
       cur=self.con.cursor()
       cur.execute(str(sqlquery[0]))
       resultList=cur.fetchall()
       self.con.commit()
       return resultList


def main():
    sqls=SQLator()
    sqls.run()

if __name__ == '__main__':
    main() 

Code: Alles auswählen

#!/usr/bin/env python
# -*- encoding: latin-1 -*-
"""SQLatorD - the SQLator daemon
2005-06-30: A simple quick dirty XML-RPC Socket Connection by Tabellar
"""

import socket
import xmlrpclib

#socket connection
port = 8082
host = "localhost"
con=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
con.connect((host,port))

#xml-rpc Input
Method="selectCurFetchAll"
Param=("select * from twfInst;")

#xmlrpclib "dumps"
request=xmlrpclib.dumps(((Param),),methodname=Method)

#xml-rpc-String
"""<?xml version='1.0'?>
<methodCall>
 <methodName>selectCurFetchAll</methodName>
  <params>
     <param>
       <value><string>select * from twfInstNode;</string></value>
     </param>
  </params>
</methodCall>"""

#Server XML-RPC Request
con.send(request)

#Server XML-RPC Response
data=con.recv(1024)

#xmlrpclib "loads"
param,method=xmlrpclib.loads(data)

#Print der Daten
print
print "Methode:", method
print "Input  :", Param
for i in param:
    print "Output :", i

#Connection schliessen
con.close()
C:\Programme\sqlator>RPCSQLatorC.py

Methode: selectCurFetchAll
Input : select * from twfInst;
Output : (1, None, 0, u'test Workflow', 1, 0)
Output : (2, None, 0, u'test', 123, 0)
Tabellar
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Damit es nicht heißt ich spucke große Töne habe aber außer ein paar Codezeilen nichts zu bieten, habe ich mich irgendwann zwischen gestern und heute mal darangesetzt und SQLator stark ausgebaut. So habe ich meine Idee verschiedener Server umgesetzt.

Dazu gibt es ein(en) SQLatorB - Backbone/Backend, das die Datenbank öffnet und sie als Pyro-Objekt bereitstellt. Als weitere Ebene kommt SQLatorD - XML-RPC, die XML-RPC Version des Servers, sie entspricht dem Ur-Server, den ich hier vorgestellt habe. Als weiteres Schmankerl kam aber noch der SQLatorD - async hinzu, der alternativ zum XML-RPC Server verwendbar ist. Dieser Server ist eine Art XML-RPC mit persistenten Verbindungen und mit asyncore realisiert.
Zuletzt ist noch ein Client benötigt, dazu schlage ich den SQLatorC vor, dieser kann immernoch per 'echten' XML-RPC auf den Server zugreifen, als auch per async auf den neuen asyncore-Server (benötigt nur socket, die PySQLite-Bindungen sind auf dem Client unnötig).

Ich habe die IPC durch Pyro gelöst, weil Pyro eine Menge sehr praktischer Features hat, die auch in Zukunft praktisch sein könnten (wie z.B. ein Tuplespace). Also wird zum verwenden von SQLator noch Pyro (ich habe version 3.4 verwendet solange 3.5 noch in der Beta-Phase ist) benötigt, ich denke aber, das dies kein allzugroßes Problem sein sollte, denn Pyro ist unter MIT-Lizenz und 100% pures Python, somit kann man es auch zur Not mit ins Tarball packen.

Beim Schreiben des Servers mit asyncore ist mir aufgefallen, dass Sam Rushings Module großartig sind. Ich werde nie wieder einen Server in Python ohne asyncore (oder Twisted) schreiben, denn Event-gesteurte Netzwerkprogrammierung "fühlt" sich einfach viel besser an und die Programme schreiben sich wesentlich besser.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
tabellar
User
Beiträge: 186
Registriert: Mittwoch 4. September 2002, 15:28

Mir kommt das ganze ein bisschen überladen vor :roll: Mir ist noch nicht so ganz klar, warum du hier so viele Frameworks verwendest. Ich hab das ganze mal überflogen, aber noch nicht getestet. Ich bin kein Freund des endlosen Modul-Importierens...

Was genau soll Pyro bewirken? Das SQLatorB öffnet ja die DB und stellt anschliessend eine Pyro Objekt zur Verfügung. Reicht hier nicht einfach das Bereitstellen eines Connection Objektes(von pysqlite)???

Die Asyncore/Asynchat Geschichte im SQLatorD gefällt mir ganz gut. Was mich ein wenig an deiner "allgemeinen XML-RPC" Verwendung stört, ist die allgemeine execute Funktion, die letztendlich die cur.fetchall() des Connection Objektes aufruft. Es gibt aber auch noch andere "Connection.Cursor Funktionen" ... :wink: Die Thematik habe ich bei meiner Socket/XML-RPC Version oben mal aufgezeigt.

Ich finde, das ganze sollte "leichtgewichtig" sein mit nicht zu vielen "import Modulen". Maximal Socket, Asyncore, Asynchat, PySQLite. Eine Alternative dazu wäre auch eine Variante mit SocketServer, Threading und Queue... (Clientverwaltung in jeweils einem eigenen Thread + Lock Mechanismus auf die Single-User-Datenbank ).

Ich muss mir das ganze aber auch noch mal genauer anschauen...
Tabellar
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

tabellar hat geschrieben:Mir kommt das ganze ein bisschen überladen vor :roll: Mir ist noch nicht so ganz klar, warum du hier so viele Frameworks verwendest. Ich hab das ganze mal überflogen, aber noch nicht getestet. Ich bin kein Freund des endlosen Modul-Importierens...
Ich verwende auußer PySQLite nur Pyro und das ist kein C-Modul, somit kann man es auch mit einpacken ohne dass es jegliche Probleme macht (und so groß ist pyro) auch nicht.
tabellar hat geschrieben:Was genau soll Pyro bewirken? Das SQLatorB öffnet ja die DB und stellt anschliessend eine Pyro Objekt zur Verfügung. Reicht hier nicht einfach das Bereitstellen eines Connection Objektes(von pysqlite)???
Theoretisch schon, jedoch können aktuell auch mehrere Server gleichzeitig laufen ohne sich ins gehege zu kommen, mit einem einfach bereitgestellten con-Objekt wäre ich mir da gar nicht so sicher. Außerdem könnte SQLatorB zukünftig auch eine User-Datenbank bereitstellen, die
tabellar hat geschrieben:Die Asyncore/Asynchat Geschichte im SQLatorD gefällt mir ganz gut. Was mich ein wenig an deiner "allgemeinen XML-RPC" Verwendung stört, ist die allgemeine execute Funktion, die letztendlich die cur.fetchall() des Connection Objektes aufruft. Es gibt aber auch noch andere "Connection.Cursor Funktionen" ... :wink: Die Thematik habe ich bei meiner Socket/XML-RPC Version oben mal aufgezeigt.
Ja, das war nur so zum testen ob es geht gedacht und kann sehr schnell korrigiert werden.
tabellar hat geschrieben:Ich finde, das ganze sollte "leichtgewichtig" sein mit nicht zu vielen "import Modulen". Maximal Socket, Asyncore, Asynchat, PySQLite. Eine Alternative dazu wäre auch eine Variante mit SocketServer, Threading und Queue... (Clientverwaltung in jeweils einem eigenen Thread + Lock Mechanismus auf die Single-User-Datenbank ).
Den Socket/Queue und Threading server darfst du gerne schreiben.. womit du zwar die Funktionalität von Pyro kopierst, aber wenn du magst...

Gut dass ich dir nicht noch den xmlrpcd_twisted gezeigt habe, der ist kompatibel zum asyncore Server, benötigt aber noch Twisted *g* (und war dank Pyro und dem LayerServer in einer Stunde fertig).
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
tabellar
User
Beiträge: 186
Registriert: Mittwoch 4. September 2002, 15:28

Leonidas hat geschrieben:
tabellar hat geschrieben:Was genau soll Pyro bewirken? Das SQLatorB öffnet ja die DB und stellt anschliessend eine Pyro Objekt zur Verfügung. Reicht hier nicht einfach das Bereitstellen eines Connection Objektes(von pysqlite)???
Theoretisch schon, jedoch können aktuell auch mehrere Server gleichzeitig laufen ohne sich ins gehege zu kommen, mit einem einfach bereitgestellten con-Objekt wäre ich mir da gar nicht so sicher. Außerdem könnte SQLatorB zukünftig auch eine User-Datenbank bereitstellen
Nun, auch wenn mehrere Server laufen würden, hätten diese auch nur ein "Connection" Objekt, welches sie von PySQLite erhalten. Sprich die Thematik für den Zugriff auf dieselbe DB wird dadurch nicht einfacher, sondern schwerer, weil die DB Zugriffe nicht mehr zentral gehandelt werden.
Leonidas hat geschrieben:Den Socket/Queue und Threading server darfst du gerne schreiben.. womit du zwar die Funktionalität von Pyro kopierst, aber wenn du magst...
Ich hab da schon ein paar ganz gute Beispiele :wink: ... Aber mir geht es gar nicht darum Pyro zu kopieren, sondern die Netzwerk Thematik besser verstehen zu lernen... Dies ist auch der Grund, warum ich mir andere Frameworks nicht gleich zu Nutze machen möchte.
Leonidas hat geschrieben:Gut dass ich dir nicht noch den xmlrpcd_twisted gezeigt habe, der ist kompatibel zum asyncore Server, benötigt aber noch Twisted *g* (und war dank Pyro und dem LayerServer in einer Stunde fertig).
Spassig ist dies ja allemal, und sich die Dinge anzuschauen bringt einen ja auch immer einen Schritt weiter... :P

Tabellar
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

tabellar hat geschrieben:
Leonidas hat geschrieben:
tabellar hat geschrieben:Was genau soll Pyro bewirken? Das SQLatorB öffnet ja die DB und stellt anschliessend eine Pyro Objekt zur Verfügung. Reicht hier nicht einfach das Bereitstellen eines Connection Objektes(von pysqlite)???
Theoretisch schon, jedoch können aktuell auch mehrere Server gleichzeitig laufen ohne sich ins gehege zu kommen, mit einem einfach bereitgestellten con-Objekt wäre ich mir da gar nicht so sicher. Außerdem könnte SQLatorB zukünftig auch eine User-Datenbank bereitstellen
Nun, auch wenn mehrere Server laufen würden, hätten diese auch nur ein "Connection" Objekt, welches sie von PySQLite erhalten. Sprich die Thematik für den Zugriff auf dieselbe DB wird dadurch nicht einfacher, sondern schwerer, weil die DB Zugriffe nicht mehr zentral gehandelt werden.
Doch, die Zugriffe laufen alle über SQLiteB und werden somit zentral gehandhabt.
tabellar hat geschrieben:
Leonidas hat geschrieben:Den Socket/Queue und Threading server darfst du gerne schreiben.. womit du zwar die Funktionalität von Pyro kopierst, aber wenn du magst...
Ich hab da schon ein paar ganz gute Beispiele :wink: ... Aber mir geht es gar nicht darum Pyro zu kopieren, sondern die Netzwerk Thematik besser verstehen zu lernen... Dies ist auch der Grund, warum ich mir andere Frameworks nicht gleich zu Nutze machen möchte.
Naja, ich verwende ganz gerne Sachen die schon funktionieren und sich erprobt haben, besonders wenn man dabei keine Nachteile hat.
tabellar hat geschrieben:
Leonidas hat geschrieben:Gut dass ich dir nicht noch den xmlrpcd_twisted gezeigt habe, der ist kompatibel zum asyncore Server, benötigt aber noch Twisted *g* (und war dank Pyro und dem LayerServer in einer Stunde fertig).
Spassig ist dies ja allemal, und sich die Dinge anzuschauen bringt einen ja auch immer einen Schritt weiter... :P
Okay. Ich stell den online, wenn ich wieder zuhause bin. Du wirst sehen, dass der praktisch genauso funktioniert wie die async-Variante, also auch mit Factories und Protocols und XML-RPC kodierten Aufrufen. War ja auch praktisch ein Async-Port auf Twisted, mehr nicht.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Leonidas hat geschrieben:Okay. Ich stell den online, wenn ich wieder zuhause bin. Du wirst sehen, dass der praktisch genauso funktioniert wie die async-Variante, also auch mit Factories und Protocols und XML-RPC kodierten Aufrufen. War ja auch praktisch ein Async-Port auf Twisted, mehr nicht.
Und den gibts nun hier. Darin wird sogar der LayerServer aus dem async-Server wiederverwendet.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
tabellar
User
Beiträge: 186
Registriert: Mittwoch 4. September 2002, 15:28

Also, ich hab die codes mal angeschaut, aber nicht getestet. Pyro scheint ja recht mächtig zu sein
und hat sein Augenmerk auf im Netzwerk verteilte Objekte gelegt (Pyro=Python Remote Objects).
Proxy, DNS, ... alles an Bord. Auch die auf der HP veröffentlichten Projekte, die Pyro verwenden, hören
sich recht interessant an.

Aber trotzdem, im Falle des SQLator Servers finde ich, dass die ganzen Frameworks nicht unbedingt
notwendig sind. Die Philosphie von SQLite selber ist ja der Minimalismus bei hoher Funktionalität
(sqlite3.dll = 241kB). Also sollte ein SQLite Server meiner Meinung nach auch eher lite sein :roll:.
Ich finde der Server ist das eine, und die Zugriffs API, wie z.B. XML-RPC, oder Python DB API 2.O ist das andere.
Man muss also unterscheiden, was man genau will. Denkbar wäre also, einen einfachen SQLatrorD zu bauen,
der TCP Grundfunktionalität zur Verfügung stellt und auf den über entsprechende, importierte API Module
(SQLatorDXmlRpcAPI, SQLatorDAPI2.0), zugegriffen werden kann.

Ich hab vorgestern mal einen einfachen SQLatorD mit User Authentifizierung gebaut. Der Client meldet sich beim Server an, der Server fragt
nach Username und Passwort, wenn die Daten passen wird die Connection aufrechterhalten und der Client kann entsprechend
mit dem Server kommunizieren... :wink:


Tabellar
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Mit anderen worten, dich stört eigentlich nur Pyro? Na, ich werd mal schauen wie es ohne pyro aussieht, jedoch muss ich zugeben, dass die Features die einem mit Pyro offenstehen wirklich ziemlich interessant sind.

Wie wird es eigentlich bei jabberd gehandhabt? Da ist doch auch der Server mit einer SQL Datenbank verbunden, die noch laufen muss?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
tabellar
User
Beiträge: 186
Registriert: Mittwoch 4. September 2002, 15:28

Leonidas hat geschrieben:Mit anderen worten, dich stört eigentlich nur Pyro? Na, ich werd mal schauen wie es ohne pyro aussieht, jedoch muss ich zugeben, dass die Features die einem mit Pyro offenstehen wirklich ziemlich interessant sind.
Mich stört Pyro nicht, im Gegenteil ... :wink:. Ich finde den Ansatz von Pyro - persistente, verteilte Objekte im Netz - sogar SEHR interessant. Aber nicht im Zusammenhang mit dem SQLatorD... Wenn man das ganze mal rein auf die Serverfunktionalität runterbricht, dann brauchen wir:

- TCP Connection (Kommunikation: Daten send/recv)
- Thread je Client
- PySQLite Connection Objekt je Thread

Alles andere sind Zugaben und Wünsche... :roll:
Leonidas hat geschrieben:Wie wird es eigentlich bei jabberd gehandhabt? Da ist doch auch der Server mit einer SQL Datenbank verbunden, die noch laufen muss?
Da läuft das ganze ein wenig anders. Die jabberd(Backbone) Architektur ist konsequent auf Schnittstellen und Komponenten aufgebaut. Die meisten Komponenten sind über die TCP/Socket Schnittstelle angeschlossen. D.h., Komponente xyz ist als Client mit Adresse (Bsp.:"localhost",10001) mit dem jabberd in Verbindung. Austauschprotokoll ist das "JabberProtokoll" und ist in XML. Beim jabberd heisst die DB Komponente xdb. Über diese Komponente (eine Wrapper Komponente :wink: , laufen die ganzen DB Abfragen (user auth, vcard, etc.). Als DB Backend dienen im Normalfall reine XML DB files :shock: . Ab jabberd2 können aber auch "richtige" RDBMS angehängt werden :wink:.

Tabellar
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Okay, dann hier mal der Async-SQLatorD ohne Pyro:

Code: Alles auswählen

#!/usr/bin/env python
# -*- encoding: latin-1 -*-
"""SQLatorD - the SQLator daemon"""
import socket, asynchat, asyncore, xmlrpclib
from sqlatorb import SQLiteBackbone

class LayerServer(object):
    def __init__(self):
        self.storage = SQLiteBackbone()
        
    def execute(self, query):
        """Gets the query (XML-RPC request),
        decodes it to SQL, executes it, encodes the result
        into XML-RPC and returns it"""
        query = self.rpc_decode(query)
        result = self.storage.execute(query)
        return self.rpc_encode(result)
    
    def rpc_encode(self, data):
        return xmlrpclib.dumps((data,), methodresponse=True)
    
    def rpc_decode(self, data):
        params, methodname = xmlrpclib.loads(data)
        return params[0]
    

class ConnectionFactory(asyncore.dispatcher):
    def __init__(self):
        print 'Booting:'
        self.port = 5888
        print ' - Creating server instance'
        self.server = LayerServer()
        print ' - Calling dispatcher'
        asyncore.dispatcher.__init__(self)
        print ' - Creating socket'
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        print ' - Binding socket to port'
        self.bind(('', self.port))
        print ' - Listening: Booting done.'
        self.listen(5)
    
    def handle_accept(self):
        newSocket, address = self.accept()
        print 'Connected by %s:%d' % address
        ClientProtocol(socket=newSocket, server=self.server)


class ClientProtocol(asynchat.async_chat):
    def __init__(self, socket, server):
        print 'Connection delegated'
        self.server = server
        asynchat.async_chat.__init__(self, socket)
        self.set_terminator('\r\n')
        self.data = ""
    
    def collect_incoming_data(self, data):
        """Collects data got through the socket"""
        self.data += data

    def found_terminator(self):
        print self.data
        result = self.server.execute(self.data)
        self.push(result)
        #self.push(''.join(self.data))
        self.data = ""


def main():
    ConnectionFactory()
    asyncore.loop()

if __name__ == '__main__':
    main()
Der Rest bleibt unverändert, jedoch muss SQLatorB nicht extra gestartet werden (ich weiß, SQLatorB benötigt noch Pyro), und der CLient funktioniert weiterhin ohne jede Änderung.

Ich hatte jetzt keine Lust noch den XML-RPC SQLatorD umzuschreiben, und deinen Tipp, tabellar habe ich immer noch nicht eingebaut.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten