Home

Benchmarks
Historie
Forum
Download
Helpware
Insider
Dokumentation
Kurs
Provider-Infos

Impressum



tdbengine-news vom 19.11.2003


Seit der letzten News ist viel Zeit vergangen. Das liegt aber mitnichten daran, dass sich bei der tdbengine nichts mehr tut, genau das Gegenteil ist der Fall: Es gibt eine neue Version 6.2.9 mit einer ganzen Reihe neuer Features und Möglichkeiten, die weiter unten beschrieben werden.

CGI-Anwendungen ohne Apache-Konfiguration

Bereits in der der Version 6.2.8 (Linux und FreeBSD) war die Option eingebaut, mit direct_scripting direkt ausführbare CGI-Scripten erzeugen zu können. Leider sind die Möglichkeiten, die sich daraus ergeben, nicht klar genug herausgestellt worden: Jetzt kann die tdbengine bei allen Providern eingesetzt werden, die Ihnen Webspace mit freien CGI's zur Verfügung stellen ( Strato, 1und1, PureTec...). Es ist keine Konfiguration des Web-Servers notwendig! Die Sache ist sehr einfach:

1. Legen Sie unterhalb Ihres CGI-Verzeichnisses ein Verzeichnis "tdbengine" an.
2. Kopieren Sie in dieses Verzeichnis alle Dateien der tdbengine
3. Sorgen Sie dafür, dass folgende Dateien ausführbar sind: tdbengine, pdk.prg, scanfile.prg

Das war's auch schon. Wenn Ihre Domain beispielsweise "www.meinedomain.de" heisst ind Ihr CGI-Verzeichnis "cgi-bin", dann sollte jetzt der Aufruf von "http://www.meinedomain.de/cgi-bin/tdbengine/test.prg" das bekannte "Hello world!" in die Browser-Anzeige zaubern.

Hier noch ein Hinweis für Windows-Anwender: Das einfache Kopieren der Datein mittels FTP reicht nicht aus, da in den meisten Fällen derart transpotierte Dateien für alle anderen Anwender ausser dem User selbst nur lesbar sind. Aber nahezu alle bekannten FTP-Klienten können die Zugriffrechte ändern.

Das tdbSQL-Projekt

Thomas Friebel, ein Mitarbeiter der TDB-GmbH, hat das Projekt eines auf der tdbengine basierenden SQL-Servers initiiert und hurtig vorangetrieben. Unter http://tdbsql.sourceforge.net  können Sie den aktuellen Stand des Projekt sehen. Mitarbeiter sind stets willkommen. Besonders spannend an diesem Projekt werden die Schnittstellen zu PHP, Perl und Java sein (gerade hier ist kompetente Mitarbeit gefragt).

Neue Möglichkeiten in der Konfiguration

Die Konfigurationsdatei wird (auf Unix-Systemen) nun in folgenden Verzeichnissen gesucht:

1. Im Verzeichnis, in dem sich das auszuführende Programm befindet
2. Im Verzeichnis, in dem sich die (ausführbare) tdbengine befindet
3. Im Verzeichnis /etc/tdbengine

Auf Windows-Systemen entfällt 3.

errorlog

In der tdbengine.ini kann nun auch der Pfad zur Fehler-Logdatei eingestellt werden:

[globals]
errorlog=/var/log/tdbengine/error_log

cdmode

Mit cdmode=1 in der Abteilung [globals] der tdbengine.ini kann festgelegt werden, dass sämtliche Tabellen im R/O-Modus geöffnet werden, auch wenn im Programm etwas anderes angegeben ist. Textdateien, die zum Schreiben geöffnet werden, werden automatisch zu Ramtexten.

Programminterne Kommunikation über Environment-Variablen

Es gibt nun zusätzlich zum Environment, das vom Betriebssystem zur Verfügung gestellt wird, zwei weitere Variablen, auf die innerhalb eines EASY-Programms zugegriffen werden kann:

TDB_VERSION

Die tdbengine liefert hier String der Form "6.2.9"

TDB_OS

Da gibt es derzeit zwei Antworten:

"unix"  für FreeBSD und Linux
"win32" für Windows

Mit einer (bislang undokumentierten) Spezialform der Funktion GetEnv) kann man auch Variablen für das interne Environment der tdbengine setzen:

GetEnv('set:Varibale=Wert')

Beispiel: GetEnv('set:MEIN_NAME=Hans Mustermann')

In der Folge liefert GetEnv('MEIN_NAME') den String 'Hans Mustermann'. Diese Variable dann solange gültig, bis sie entweder umdefiniert oder aber die tdbengine beendet wird.

Zwei selbstdefinierte Environment-Variablen werden von der tdbengine selbst ausgewertet:

HTTP_PROXY

Der Inhalt dieser Variablen wird verwendet, wenn ein Template von einem entfernten Rechner via http geladen wird, also bei

LoadTemplate('http://...')

Ist die Variable HTTP_PROXY auf die IP-Adresse (oder bekannten Rechnernamen) gesetzt, so wird die Anfrage an diesen geleitet. Der Zugriff eines Web-Servers auf des Web über einen Proxy ist ein gängiges Verfahren, Sicherheitsrisiken zu minimieren.

TDB_SUBST

Diese Variable wird dann ausgewertet, wenn die tdbengine als Server läuft, also die Funktion SERVER aktiv ist. In diesem Fall wird die Funktion CGIWRITETEMPLATE so erweitert, dass vor der Ausgabe des Templates sämtliche Ersetzungen durchgeführt werden, die in der Datei stehen, auf die TDB_SUBST verweist. Diese Datei ist zeilenweise so aufgebaut:

Target;Ersetzung

Statt langer Erklärungen hier ein Beispiel:

Angebommen wir haben folgendes Template:

<html>
<head>
<base href="http://www.tdb-engine.de/">
</head>
<body>
  <img src="http://www-tdb-engine.de/pics/einbild.jpg">
  <h3>Herzlich Willkommen</h3>
  <a href="/scripts/anfang.prg">Zur Einleitung</a><br>
  <a href="/scripts/ende.prg">Zum Ende</a><hr>
</body>
</html>


im aktuellen Verzeichnis gibt es eine Text-Datei 'local' mit folgendem Inhalt:

www.tdb-engine.de;localhost:3444
/scripts/;/cgi-tdb/local/
/anfang.prg";anfang.prg?query=start"

Nach GetEnv('set:HTTP_SUBST=local') gibt die tdbengine das obige Template (mit CGIWriteTemplate) so aus:

<html>
<head>
<base href="http://localhost:3444/">
</head>
<body>
  <img src="http://localhost:3444/pics/einbild.jpg">
  <h3>Herzlich Willkommen</h3>
  <a href="/cgi-tdb/local/anfang.prg?query=start">Zur Einleitung</a><br>
  <a href="/cgi-tdb/local/ende.prg">Zum Ende</a><hr>
</body>
</html>


Alles klar? Zugegeben, es ist kompliziert. Aber die Möglichkeit, die sich aus diesem Feature erschließt, ist einfach überwältigend: Sie können einen bestehenden Internetauftritt (mit dynamischen Inhalten, sonst wäre es ja langweilig) mit ganz wenigen Handgriffen so auf eine CD brennen, dass dieser ohne eine Änderung an den Programmen oder HTML-Seiten sofort von dieser CD läuft. Machen Sie das mal mit irgendeinem anderen Programm (PHP/MySQL, Perl ... )

Neue Funktionen

ReOpenDB

Es gilt ja die Regel, dass man eine Tabelle nur mit den unbedingt benötigten Rechten öffnen sollte. Manchmal kommt es aber vor, dass man ein Tabelle zum Lesen geöffnet hat, und nun will man in diese Tabelle schreiben. Also CloseDB mit anschließendem OpenDB? Diese Lösung hat den Nachteil, dass nach dem CloseDB der alte Tabellenhandle nicht mehr gültig ist und der neu (nach OpenDB) nicht mehr mit dem alten übereinstimmen muss. Um das zu herhindern gibt es nun die Funktion ReOpenDB, das den Tabellenhandle bewahrt und die Tabelle mit neuen Rechten wiederöffnet.

ReOpenDB(db : INTEGER; accessmode : INTEGER) : INTEGER

Zu den zulässigen accesmodes siehe OpenDB.

Ramtext

Ramtext(Filename : STRING; InitSize : INTEGER)

Normalerweise werden Ramtexte mit 16 KByte initialisiert (ausser wenn Sie bei der Erzeugung schon mehr Platz benötigen). Sie wachsen dann bei Bedarf ebenfalls in 16 KByte-Schritten. Mit dieser Funktion kann das geändert werden. Die Initialisierungsgröße kann z.B. gleich wesentlich größer eingestellt werden, damit die automatischen Inkremenierungsschritte unterbleiben, die bei sehr großen Ramtexten zu einem enormen Bedarf an Arbeitsspeicher führen können.


SetAlias

SetAlias(db : INTEGER; Alias : STRING) : INTEGER

Erzeugt einen weiteren Handle für eine bereits geöffnete Tabelle. Die Tabelle kann in Subreports etc. uner dem Alias-Namen angesprochen werden. Die Alias-Tabelle hat einen eigenen Satzpuffer, eine eigene Markierungsliste und eine eigene Zugriffsverwaltung.

f_pos

Liefert die aktuelle Position in einem Stream:

f_pos(hdl : INTEGER) : INTEGER

Beispiel:

VAR hdl : INTEGER = f_open('./test.prg',0)
VAR buf : BYTE[1000]
...
IF hdl>0 THEN
  f_read(hdl,buf[0],10)
  cgiwriteln(str(f_pos(hdl))  // ergibt 10
END


Unix-Timestamps

Unter einem Unix-Timestamp versteht man die Anzahl der Sekunden, die seit Beginn der Unix-Epoche am 1.1.1970 vergangen sind. Werden diese in einer 32-Bit Variablen gespeichert, so ist damit der Bereich von 1970 bis etwa Anfang 2038 abgedeckt. Unix-Timestamps eignen sich sehr gut, Update-Zeiten für Datensätze festzuhalten, wenn eine sekundengenaue Auflösung ausreicht (was in den meisten Fällen wohl zutrifft).

Konstanten vom Typ Unix-Timestamp werden in der Form

DD.MM.YYYY_hh:mm:ss

angegeben (DD = Tag, MM = Monat, YYYY = Jahr, hh = Stunden, mm = Minuten, ss = Sekunden). Wichtig ist hierbei der Unterstrich zwischen Datums- und Zeitangabe.

Folgende Funktionen stehen für Unix-Timestamps zur Verfügung:

UNIX_NOW
Liefert die aktuelle Systemzeit als Unix-Timestamp, also als Anzahl der Sekunden seit dem 1.1.1970
DATETIME_TO_UNIX
Berechnet den Unix-Tmestamp für eine Datums- und Uhrzeitkombination im TDB-Format
UNIX_DATE
Liefert das Datum (im TDB-Format) aus einem Unix-Timestamp
UNIX_TIME
Liefert die Zeit (im TDB-Format) aus einem Unix-Timestamp
UNIXTIME_TO_STR
Konvertiert einen Unix-Timestamp in einen String
STR_TO_UNIXTIME
Konvertiert einen String in einen Unix-Timestamp


Zum Speichern von Unix-Timestamps gibt es den neuen Datentyp "UTIME", der eine 32-Bit-Zahl speichert. GetField und SetField konvertieren derartige Inhalte automatisch:

SetField(db,'edit_date','18.11.2003_14:12:52')
GetField(db,'edit_date') -> "18.11.2003_14:12:52"

Scheller wird es freilich, wenn auf Unix-Timestamps mit den Funktionen SetRField und GetRField zugegriffen wird.

SetRField(db,'edit_date',UNIX_NOW)

IF UNIX_NOW-getrfield(db,'edit_date')<3600 THEN ...
  //  Datensatz wurde innerhalb der letzten Stunde editiert...

Erweiterungen bereits bekannter Funktionen

LoadTemplate via Proxy

Diese interne Erweiterung wurde bereits oben bei HTTP_PROXY  erläutert.

f_open

Bisher wurden Streams (untypisierte Daten) immer im R/W-Modus geöffnet. Das kann manchmal lästig sein, in vielen Fällen ist es aber unnötig. Deshalb gibt es jetzt einen (optionalen) zusätzlichen Parameter, mit dem der Modus festgelegt wird. Näheres siehe in der Supportdatenbank.

Socket- und Streamfunktionen mit direkter Pufferindizierung

Die Funktionen f_read, f_write,  getsock und putsock wurden so erweitert, dass beim Übertragungspuffer nun auch ein Feldindex angegeben werden kann:

VAR buf : CHAR[10000]

f_read(hdl,buf[x],n) : INTEGER

f_read(hdl,buf,n) = f_read(hdl,buf[0],n) // wie bisher


Das Server-Projekt

Die Funktion "server" ist nun auch in der Windows-Version verfügbar, allerdings hier nur als Single-Process-Server. Das sollte aber für die allermeisten Anwendungen keine gravierende Rolle spielen. Und weil diese Variante auch für Linux von Interesse sein kann, ist sie auch hier verfügbar:

server(Port,Prozess,Maxconnections[,Modus]) : INTEGER

Port: TCP-Port für eingehende Verbindungen
Prozess : parameterlose EASY-Prozedur
Maxconnections : maximale Anzahl von Verbindungen (Sockets) für den Server
Modus : 0 (Vorgabe) -> Single-Process, 1 (nur Linux/FreeBSD) -> Multi-Process (forked)

Die Funktion liefert nur dann ein Ergebnis, wenn sie terminiert, was sie eigentlich nicht machen sollte. In diesem Fall ist das Funktionsergebnis der Fehlercode des betriebssystems:

13: Öffnen des privilegierten Ports verboten
98: Port bereits belegt

Die Arbeitsweise:

Wenn "server" ausgeführt wird, wartet die tdbenine auf eingehende TCP-Verbindungen am angegeben Port. Wird eine Verbindung aufgebaut, so wird die angegebene Prozedur ausgeführt. Innerhalb dieser Prozedur sind zwei Handles verfügbar:

TextHandle 128
SocketHandle 128

Beide Handles können zur Kommunikation mit dem Klienten verwendet werden. Allerdings sollte man darauf achten, dass für das Lesen und Schreiben (bzw. Empfangen und Senden) nur jeweils eines der beiden Handles verwendet wird, vorzugsweise das Socket-Handle (weil Textoperationen immer gepuffert werden).

Ist die Funktion server aktiv, so werden alle CGI-Ausgaben (CGIWrite, CGIWriteln, CGIWriteTemplate) auf dem Server-Socket ausgeführt.

Wenn die Prozedur beendet wird, wird die Verbindung zum Klienten beendet und das ganze Spiel beginnt von vorne.

Was kann man damit machen?

Ein Beispiel:  Mini-Web-Server für Einzelplatz- und CD-Applikationen

Hierzu gibt es in Kürze eine eigene Beschreibung im Doku-Bereich.

Viel Erfolg mit der tdbengine wünscht

Ulrich Kern

Newsletter

Anmeldung zum Newsletter:
Name: 
Zusatz: 
EMail: