Remote Enscribe Java API

Inhalt dieses Dokuments

Der vorliegende Text beschreibt die Installation und die wichtisten Funktionen und Klassen der API (Application Programming Interface) für Remote Enscribe in Java. Remote Enscribe ist ein Paket zum transparenten Zugriff auf HP-NonStop-Dateien und Datenbanken. Remote Enscribe ist auch in C verfügbar.

Beachten Sie auch das Parallelprodukt Remote SQL!

Index


Einführung

Funktionsumfang

Die vorliegende Software Remote Enscribe stellt eine Schnittstelle zwischen beliebigen Java-Clients und dem HP-NonStop-Dateisystem ENSCRIBE her. Sie ist als Client/Server-Paar implementiert, wobei der Client zu 100% in Java realisiert ist. In der vorliegenden Fassung werden folgende Funktionen unterstützt:

Geplante Erweiterungen

Die API ist der C-API sehr ähnlich. Es ist geplant, einige Funktionen zu erweitern, damit sie stärker objektorientiert arbeiten. So liefern die Dateizugriffsfunktionen bei Fehlern einen Returnwert zurück, statt eine Exception zu erzeugen (das Verhalten kann allerdings mit Host.throwException(true) beeinflusst werden.) Auch wird java.io.OutputStream noch nicht unterstützt.

NonStop-Serverprozess RSQLSRV

Die Kommunikation erfolgt über einen Prozess auf dem NonStop-System, der die TCP/IP-Nachrichten in Aufrufe an das Dateisystem weitergibt. Der TCP/IP-LISTNER startet RSQLSRV bei jeder Kommunikationsanforderung automatisch. Der Server wird identisch auch für Remote SQL eingesetzt, für das jetzt auch eine Java-API existiert.


Installation

Installation des NonStop-Gateways RSQLSRV

Der Server RSQLSRV muß auf dem NonStop-System installiert werden. Dazu ist eine Zeile in der Datei PORTCONF der TCP/IP-Konfiguration für den LISTNER einzutragen:

741     $system.rsql.rsqlsrv -p150

Danach ist der LISTNER-Prozess neu zu starten.

Das ausführbare Programm muß im Binärformat auf das NonStop-System, hier im Subvolume $SYSTEM.RSQL kopiert werden und den Filecode 100 erhalten. Soll der Server auch für Remote-SQL-Zugriffe eingesetzt werden, so ist er mit SQLCOMP noch in einen beliebigen SQL-Katalog einzutragen.

Die Portnummer, hier 741, kann frei gewählt werden. Der angegebene Wert ist der Default.

Der Parameter -p150 legt die Priorität des Prozesses auf 150 fest. Andere Werte sind jederzeit möglich. Die korrekte Wahl der Priorität ist eine Maßnahme, um unnötige Systembelastungen durch komplexe Abfragen auf eine Minimum zu reduzieren.

Installation der Java-Klassen

Die Java-Klassen sind im Archiv renscribe.jar gespeichert, das dem Klassenpfad hinzugefügt werden muß. Innerhalb einer IDE wird dies normalerweise im Projekt eingetragen. Auf aktuellen Java-Plattformen, kann der Aufruf mit

java -cp renscribe.jar MyClass

erfolgen. Geben sie den vollständigen Pfad der Jar-Datei an.

Sie können die Datei auch dem System-Klassenpfad, je nach System in der Systemsteuerung (NT, W2K, XP), CONFIG.SYS (OS/2), AUTOEXEC.BAT (W9x) oder dem Benutzerprofil (Unix) hinzufügen. Java ab Version 1.2 unterstützt auch die Speicherung des Jar-Files im Verzeichnis jre\lib\ext unterhalb des Java-Verzeichisses.


Gebrauch

API-Dokumentation

Die vollständige API-Dokumentation liegt im Javadoc-Format vor: Remote Enscribe Java API.

Die wichtigsten Funktionen

Für die folgenden Funktionen müssen sie das Package de.mvcsys.renscribe.* importieren.

Verbindungsaufbau

Zum Aufbau der Verbindung und speichern der Verbindungsdaten legen sie ein de.mvcsys.renscribe.Host-Objekt an:

Host host;

try {
host = new Host( "hpns", 741, "USER.NAME", "geheim" );
} catch( Exception e ) {
System.err.println( "Verbindunsaufbau gescheitert: "
+ e.toString() );
}

Sollte die Verbindung abbrechen, muß sie neu erstellt werden, da auch alle offenen Dateien geschlossen werden. Die Verbindung kann jederzeit mit der disconnect-Methode vorzeitig abgebaut werden.

Verbindungen können auch unter Verwendung der Klasse HostPool verwaltet werden.

Zugriff auf Dateien

Eine Enscribe-Datei (oder auch einen Prozess oder ein Device) öffnen Sie, indem Sie vom beim Verbindungsaufbau erzeugten Host-Objekt host mit open ein de.mvcsys.renscribe.EFile-Objekt anlegen lassen:

EFile file = host.open( "$DATA.DBFILES.CUSTOMER",
"r+",
Host.OPEN_SHARED | Host.OPEN_BUFFERED,
130 );
if ( file == null ) {
System.err.println( "Fehler " + host.errno + " bei open: "
+ host.errorMsg );
}

Auf die so geöffnete Datei können Sie jetzt mit allen Methoden der Klasse EFile zugreifen.

Transaktionssteuerung

Sie können Transaktionen auf dem NonStop-System mit der Methode transact der Klasse Host steuern. Die Parameter Host.TT_BEGIN, Host.TT_COMMIT oder Host.TT_ROLLBACK steuern, ob die Transaktion begonnen, beendet oder abgebrochen wird.

Defines

Defines der Form "=NAME" können mit der Methode loadDefines der Klasse Host gesetzt werden. Das Argument ist ein Befehl aus folgender Liste:

DELETE DEFINE **

Alle Defines löschen.

DELETE DEFINE =<name>

Einzelnes Define löschen.

ADD DEFINE =<name>, <attribut> <wert>, ...

Define hinzufügen (oder ändern, wenn es existiert).

ALTER DEFINE =<name>, <attribut> <wert>, ...

Define ändern.

[OBEY] <Dateiname>

Die Befehle in <Dateiname> auf dem Host werden ausgeführt. Sie müssen der obigen Syntax folgen. Der Befehl OBEY kann auch weggelassen werden. OBEY kann auch rekursiv in der Datei vorkommen.

LOADINFO <Dateiname>

Analysiere die Ausgabe des TACL-Befehls
"INFO/OUT <Dateiname>/ DEFINE"
setze die entsprechenden Defines.

TACL <Befehl>

Der Befehl wird (via system) ausgeführt. Danach wird ein INFO DEFINE Befehl abgesetzt und dessen Ausgabe wie oben analysiert. Das erlaubt zum Beispiel die Verwendung von TACL-Segment-Files.

Pseudodateien

Die Methoden zum Öffnen und Lesen von Dateien erlauben die Verwendung von zwei Pseudo-Dateien: $DEFINES$ zum Lesen der aktuell gesetzten Defines und $FILES$ zum Lesen von Datei- oder Prozessnamen. Die Zeilen sind mit Linefeed getrennt.

Datei

Beispielausgabe (1. Zeile ist Kommentar)

$DEFINES$

<----- Name (24) ------> <Klasse> <Attri> <----------- Wert (34) ---------->
=CTYPEH                  MAP      FILE    \GZE.$SYSTEM.SYSTEM.CTYPEH
=GNSCTLG                 CATALOG  SUBVOL  \GZE.$DEV06.GNSCTLGL

$FILES$

<----------- Name (34) ----------> DevTyp SubDev ObjTyp FilTyp FilCod
\GZE.$DEV03.CUBERSQL.TESTFILE           3     39      0      2   7890
\GZE.$DEV03.CUBERSQL.TESTIN             3     39      0      0    101
\GZE.$DEV03.CUBERSQL.TESTTAB            3     39      2      3      0

Die Informationen können mit Hilfe der seek-Methode eingeschränkt werden.

Datei

Key-Specifier

Bedeutung

$DEFINES$

Host.DEFINES_KEY_NAME

Der Define-Name muss mit dem Key anfangen.

$DEFINES$

Host.DEFINES_KEY_CLASS

Der CLASS-Name muss mit dem Key anfangen.

$DEFINES$

Host.DEFINES_KEY_ATTR

Der Attribut-Name muss mit dem Key anfangen.

$DEFINES$

Host.DEFINES_KEY_VALUE

Der Attribut-Wert muss mit dem Key anfangen.

$FILES$

0

Der Key hat mehrere Felder, die durch Space, Tab oder die folgenden Zeichen getrennt werden: ",;:".

  1. Pattern mit "*" und "?";

  2. Auflösung: -1 (Node) bis 2 (Name), Default ist Node;

  3. Devicetype (3: Disk), Default ist alle;

  4. Subdevice, Default ist alle;

  5. Objecttype (0: File, >0: SQL);

  6. Filetype (siehe EFileInfo);

  7. Filecode (z. B. 101: Editfile).

Ein "*" setzt den Default. Parameter am Ende können weggelassen werden. Die Parameter 3 und 4 können mit "~" anfangen, um sie zu negieren. Die Parameter 5 bis 7 erlauben einen Vergleichsoperator: "=~<>".

Beispiel: "\\GZE.$*.GANSDB*L.* -1 3 * >0" findet alle SQL-Objekte in den entsprechenden Subvolumes und gibt den Node mit aus.

TACL-Befehle

Die Methode system der Klasse Host erlaubt die Ausführung beliebiger TACL-Kommandos. Der Implementierung liegt die Funktion system der C-Bibliothek zugrunde. Diese startet beim ersten Aufruf einen TACL-Prozess mit $RECEIVE als IN und ohne OUT-File. Dieser TACL startet weder TACLLOCL noch TACLCSTM, sie können dies aber selber nachholen. Dem Prozess werden dann alle weiteren system-Aufrufe übergeben.

Es bietet sich an, alle Programme mit expliziter OUT-Datei zu starten und diese Datei dann per API zu lesen.

Beispiel

    /**
* Test
*/
public static void main( String args[] )
throws Exception
{
byte buffer[] = new byte[ 100 ];
int port = 741;
String pass = "?";
if ( args.length > 0 ) {
pass = args[ 0 ];
}
if ( args.length > 1 ) {
port = Integer.parseInt( args[ 1 ] );
}
try {
/*
* Verbindungsaufbau
*/
Host host = new Host( "gze", port, "qa.cube", pass, true );
host.setThrowException( true );
host.startLog( "$TDD" );
/*
* Datei-Info
*/
System.out.println( host.info( "CUBERSQL.TESTFILE" ) );
System.out.println( host.info( "\\gze.$dev05.gnsdbtt.karte" ) );
System.out.println( host.info( "TACLCSTM" ) );
/*
* Datei lesen
*/
EFile ef = host.open( "TACLCSTM", "r",
Host.OPEN_SHARED | Host.OPEN_BUFFERED, 100 );
if ( ef != null ) {
while ( !ef.isEof ) {
int l = ef.read( buffer, buffer.length, READ_NOLOCK );
if ( l == 0 && !ef.isEof ) {
/*
* Fehler
*/
throw new IOException( host.errorMsg );
}
System.out.print( Host.makeString( buffer, 0, l, host.ENCODING ) );
}
// ef.close();
host.closeAll();
}
/*
* Defines
*/
host.loadDefines( "LOADINFO CUBERSQL.DEFLIST" );
ef = host.open( "$DEFINES$", "r", Host.OPEN_BUFFERED, 80 );
if ( ef != null ) {
ef.seek( "SUB", Host.DEFINES_KEY_ATTR, SEEK_GENERIC );
while ( !ef.isEof ) {
int l = ef.read( buffer, buffer.length, READ_NOLOCK );
if ( l == 0 && !ef.isEof ) {
/*
* Fehler
*/
throw new IOException( host.errorMsg );
}
System.out.print( Host.makeString( buffer, 0, l, host.ENCODING ) );
}
ef.close();
}
/*
* Dateiliste
*/
ef = host.open( "$FILES$", "r", Host.OPEN_BUFFERED, 80 );
if ( ef != null ) {
// ef.seek( "\\GZE.$*.GNSDB?L.* -1 3 * >0", 0, SEEK_GENERIC );
ef.seek( "$DEV03.*CUBE*.* -1 3", 0, SEEK_GENERIC );
while ( !ef.isEof ) {
int l = ef.read( buffer, buffer.length, READ_NOLOCK );
if ( l == 0 && !ef.isEof ) {
/*
* Fehler
*/
throw new IOException( host.errorMsg );
}
System.out.print( Host.makeString( buffer, 0, l, host.ENCODING ) );
}
ef.close();
}
/*
* Datei schreiben
*/
ef = host.open( "TESTFILE", "wt", 0, 100 );
if ( ef != null ) {
int result = ef.write( "Test\n" );
System.out.println( "write - result=" + result );
result = ef.write( "ÄÖÜäöüß\n" );
System.out.println( "write - result=" + result );
ef.close();
}
/*
* TACL
*/
host.system( "#push #out" );
host.system( "#set #out $S.#MVC" );
host.system( "#output Hallo" );
host.system( "FILEINFO" );
host.system( "#pop #out" );

host.disconnect();
}
catch ( Exception e ) {
e.printStackTrace();
}
}

[Anfang]