E.4.2 Hauptprogramm des Speichers

#!/usr/users2/diplom/hans/python/python/bin/python
# -------------------------------------------------------------
# Projekt : Digitale Bibliotheken Projekt
# Uni-Frankfurt/M, Professur Telematik und
# verteilte Systeme, Prof. O. Drobnik
# Diplomarbeit, Matzen,Hans, 1997
# Dateiname : speicher.py
# Datum : 03.11.1997
# letzte Änderung :
# Autor : Hans Matzen, 1997, Frankfurt/M, Deutschland
# Sprache : Python v1.4
# Beschreibung : Dies ist das Hauptprogramm der Speicher-
# komponente
#
# Anmerkungen :
#
# -------------------------------------------------------------
 
 
#
# imports
#
from sc_globals import *
import time
import select
import c_bsio
import regex
import string
import c_metadoc
import urllib
import os
import posix
import class_funcs
import pgpy
import sys
import socket
import signal
import c_log
import signalfuncs
import confparse
# Ablaufumgebungen importieren
from py_abl import *
 
# setzte Defaultwerte
MAXBUFF=32768
CONFIG_FILE="speicher.conf"
                 
# verabeitung Kommandozeilenparameter
# pruefe parameter
if len(sys.argv)<2:
    print "Usage: speicher.py <name> [-f <configfile>]"
    sys.exit(1)
 
# hole kommandozeilenparameter
spobjname=sys.argv[1]
try:
    CONFIG_FILE=sys.argv[3]
except:
    pass
 
# installiere Signalhandler
msg=""
def sig_int(a,b):
    global msg
    msg="QUIT"
signal.signal(signal.SIGUSR1,signalfuncs.sig_int)
 
 
# Verarbeite Konfigurationsfile
params=confparse.confparse(CONFIG_FILE)
 
brlist=[]
rcvlist=[]
ctrlist=[]
modlist=[]
mapdict={}
lfile="./sp.log"
i=0
 
while i<len(params):
    el=params[i]
    if el[0]=="RECEIVE_PORT":
        rport=eval(el[1])
        rcvlist.append(rport)
    elif el[0]=="BROKER_ADDRESS":
        baddr=string.split(el[1],",")
        brlist.append(baddr)
    elif el[0]=="CONTROL_PORT":
        cport=eval(el[1])
        ctrlist.append(cport)
    elif el[0]=="LOG_FILE":
        lfile=el[1]
    elif el[0]=="MAP_MODULE":
        mmod=el[1]
        modlist=string.split(mmod,",")
    elif el[0]=="MAP_COMMAND":
        map=string.split(el[1],",")
        mapdict[map[0]]=map[1]
    i=i+1
 
 
# Oeffne Logfile
log=c_log.c_log("Speicher "+spobjname,lfile)
 
log.log("Gestartet")
 
host="localhost"
port=rcvlist[0]
 
# instanziiere Auftragssocket
conn=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
try:
    conn.bind(host,port)
    conn.listen(5)
except:
    log.log("Auftragssocketadresse bereits in Benutzung.")
    log.log("Speicher beendet sich.")
    raise SystemExit
 
# Anmeldung beim Broker
conn1=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# Verbindung aufbauen
try:
    conn1.connect(brlist[0][0],eval(brlist[0][1]))
except:
    log.log("Broker nicht verfuegbar")
    log.log("Speicher beendet sich")
    raise SystemExit
 
# Anmeldung schicken
conn1.send("CMD_CONN "+spobjname+" "+conn.getsockname()[0]+" "+str(conn.getsockname()[1]))
brmsg=conn1.recv(500)
 
# Wurde die Anmdeldung akzeptiert?
if brmsg=="CMD_CONNDENY":
    log.log("Der Broker verweigert die Anmeldung")
    raise SystemExit
else:
    log.log("Anmeldung beim Broker erfolgreich abgeschlossen.")
 
 
# init recv buffer da steht immer
# die letzte empfangene Nachricht drin
msg=""
 
# solange wir nicht beenden sollen werden Auftraege verarbeitet
while msg!="QUIT" and msg!="CMD_EXIT":
    log.log("Warte auf Auftraege an Adresse"+str(conn.getsockname()))
    # warten auf Nachrichten
    activ=select.select([conn.fileno()],[],[])
    # Verbindung aufbauen
    news,newsaddr=conn.accept()
    log.log("Verbindung aufgebaut mit"+str(newsaddr))
 
    # auf Auftrag warten
    msg=""
    msg=news.recv(MAXBUFF)
    log.log("Habe folgenden Auftrag empfangen:")
    log.log(msg)
    log.log("----End of message---")
 
    # konvertiere NAchricht gemaess der definierten Filter
    # im Konfigurationsfile
    msg_parts=string.split(msg," ")
    if mapdict.has_key(msg_parts[0]):
        statement="import "+modlist[0]
        exec statement
        statement="msgnew="+modlist[0]+"."+mapdict[msg_parts[0]]+"(msg)"
        exec statement
 
    # verarbeite eingegangene Nachricht
    # Auftrag parsen (Variable: msg)
    cmd=""
    params=""
    tmpfname=""
    tmpfile=""
    pos1=regex.search(" ",msg)
    if pos1>=0:
        cmd=string.upper(msg[:pos1])
    else:
        cmd=string.upper(msg)
 
    if cmd=="PUT":
        pos2=regex.search("</META>",msg)
        tmpfile=msg[pos1+1:pos2+7]
        tmpfname=class_funcs.get_uniquename()
        fd=c_bsio.c_bsio(tmpfname,"a+")
        fd.open()
        fd.write(tmpfile)
        fd.close()
        params=msg[pos2+8:]
    else:
        params=msg[pos1+1:]
 
 
    # --------------------------------------------------------
    # fuehre Kommando aus
    # --------------------------------------------------------
 
    # --------------------------------------------------------
    # ein neues Dokument soll gespeichert werden
    # --------------------------------------------------------
    if cmd=="PUT":
        # speichern der Metadokument Informationen
        # instanziiere Objekt zum Zugriff auf das Metadokument
        meta=c_metadoc.c_metadoc(tmpfname)
        # hole neue Dokumenten-ID
        newdocid=class_funcs.get_newdocid()
        # baue Verbindung zur Datenbank auf
        main_conn=pgpy.pgconn(DL_PGHOST,DL_PGPORT,DL_DBNAME)
        # ist die DTD des Dokuments schon erfasst?
        dtdnum=class_funcs.get_dtdnum(meta.get_dtd())
 
        # lese Metadaten aus dem Metadokument
        infostr =meta.get_info()
        infostr =infostr[string.find(infostr,">")+1:string.rfind(infostr,"</")]
        propdict=meta.get_property()
        methods=meta.get_methods()
        # bereite SQL Query vor
        dbclass="doc_description"
        query="insert into "+dbclass+" values ("+newdocid+",0,"
        query=query + "'" + propdict["title"] + "',"
        query=query + "'" + propdict["author"] + "',"
        query=query + "'" + propdict["owner"] + "',"
        query=query + "'" + propdict["ident"] + "',"
        query=query + "'" + propdict["pubkey"] + "',"
        query=query + "'" + infostr + "',"+str(dtdnum)+",0,0);"
 
        # fuehre SQL Query aus (speichere Metadaten in der DB)
        main_res=main_conn.exec_query(query)
        erg=main_res.commandstatus()
        # hat alles geklappt?
        if str(erg)[0:6]!="INSERT":
            log.log("Fehler beim Speichern der Metadaten")
 
        # Methoden in der DB speichern
        for j in methods.keys():
            # SQL Query vorbereiten
            dbclass="doc_methods"
            query="insert into "+dbclass+" values ("+newdocid+","
            query=query + "'" + methods[j][0] + "',"
            query=query + "'" + methods[j][1] + "',"
            query=query + "'" + methods[j][2] + "');"
            main_res=main_conn.exec_query(query)
            # und abschicken (eine Methode in DB sspeichern)
            erg=main_res.commandstatus()
            # hat ales geklappt ?
            if str(erg)[0:6]!="INSERT":
                log.log("Fehler beim Speichern der Methode:",j)
 
        # -----------------------------
        # Metadaten speichern ENDE
        # -----------------------------
 
        # Dokumenteninhalt in temporaere Datei ablegen
        datafname=urllib.urlretrieve(meta.get_data()) [0]
 
        #
        # aktiviere Methode
        #
        # ermittle URL der Methode die in zum Aufruf in
        # params uebergeben werden
        if methods.has_key(params):
            methurl=methods[params][1][regex.search("URL:",methods[params][1])+4:]
 
        # hole methode
        methtmpfile,methheader=urllib.urlretrieve(methurl)
 
        # lasse Methode von Ablaufumgebung ausfuehren
        exec_erg=exec_mc(newdocid,methtmpfile,params,datafname)
 
        # pruefe auf fehler und sende ergebnis
        if exec_erg[0:6]=="RESULT":
            log.log("Methode ohne Fehler ausgefuehrt.")
        else:
            log.log("Fehler beim Ausfuehren der Methode.")
        news.send(exec_erg)
 
 
 
    # --------------------------------------------------------
    # eine Dokumentenmethode soll aktiviert werden
    # --------------------------------------------------------
    if cmd=="ACTIVATE":
        # parse Parameter
        import string
        ident=string.split(params," ")[0]
        method=string.split(params," ")[1]
        mparams=string.split(params," ")[2]
        # baue Verbindung zur DB auf und pruefe, ob die
        # Methode exisitiert
        pgc=pgpy.pgconn(DL_PGHOST,DL_PGPORT,DL_DBNAME)
        query="select * from doc_methods where docnr="+str(ident)+" and "
        query=query+" meth_class='"+method+"';"
 
        res=pgc.exec_query(query)
        if res.get_tuple_count()!=0:
            # ermittle Methodenname aus query Ergebnis
            methurl=res.get_fieldvalue(0,2)
            log.log("die Methode steht in ",methurl)
 
            # hole methode
            methtmpfile,methheader=urllib.urlretrieve(methurl)
             
            # lasse Methode von Ablaufumgebung ausfuehren
            exec_erg=exec_mc(ident,methtmpfile,mparams)
 
            # pruefe auf fehler und sende ergebnis
            if exec_erg[0:6]=="RESULT":
                log.log("Methode ohne Fehler ausgefuehrt.")
            else:
                log.log("Fehler beim Ausfuehren der Methode.")
            news.send(exec_erg)
         
        else:
            news.send("Die Methode "+method+" wurde fuer das Dokument mit der ident "+str(ident)+" nicht gefunden.")
          
 
    # --------------------------------------------------------
    # es sollen Informationen ueber die Programmbibliothek
    # geliefert werden
    # --------------------------------------------------------
    if cmd=="INFO":
        import c_info
        info=c_info.c_info()
        erg=info.get_info()
        log.log("Sende Programmbibliothek Informationen.")
        news.send(erg)
 
    # --------------------------------------------------------
    # der Speicher soll sich beenden
    # --------------------------------------------------------
    if cmd=="QUIT":
        log.log("Habe Terminierungskommando erhalten.")
        news.send("Speicher beendet sich.")
        msg="QUIT"
 
    # --------------------------------------------------------
    # Unbekanntes Kommando empfangen
    # --------------------------------------------------------
    if not (cmd in ["PUT","INFO","ACTIVATE","QUIT"]):
        log.log("Kommando nicht erkannt.")
        log.log("Sende Fehlermeldung.")
        news.send("Kommando nicht erkannt.")
 
    log.log("Nachricht wurde verarbeitet.")
 
    time.sleep(2)
    log.log("Schliesse Socket")
    news.close()
    del news
    del newsaddr
     
     
 
log.log("---Speicher normal beendet---")