[NEWSboard IBMi Forum]
  1. #1
    Registriert seit
    Feb 2018
    Beiträge
    7

    api QSPGETSP mit SPFR0300, wie bekommt man aus dem userspace etwas ausgelesen?

    hallo allerseits,

    habe gerade etwas zeit zum basteln und wollte mal userspace-auslesen üben.
    habe dazu einen userspace erstellt und mit dem API QSPGETSP vermutlich auch befüllt, also es sollten sich nun print-Daten einer existierenden spoolfile darin befinden.
    über diverse quellen habe ich auch das aufsetzen und auslesen eines userspaces ins Programm kopiert, aber es tut sich NIX. falsch, es kommt diese Fehlermeldung:
    MCH0601
    Space offset X'00000000' or X'0000000000000000' is outside current limit
    for object @USERSPACE.

    bevor ich nun meinen code hier reinkopiere erst mal eine frage: hat irgendjemand hier aus dem Forum jemals schon mal spooldaten über api ausgelesen?

    im Internet weisen alle auf den cpysplf hin, interessiert mich alles für diesen trainingsfall nicht. ich möchte rein aus übungszwecken das ding mal mit APIs umsetzen. die Daten, die der userspace auswerfen soll, möchte ich nur mal zum spaß mit dsply anzeigen, mehr nicht.

    merci im voraus!!!
    //karin

    PS: mit der doku kann ich leider nicht viel anfangen, die print-Daten zum Format SPFR0300 sind so umständlich dokumentiert, verstehe nur Bahnhof. vielleicht kann mir da jemand mit einem Beispiel helfen?

  2. #2
    Registriert seit
    Feb 2001
    Beiträge
    20.206
    Nun, dazu gibt es die USRSPC-API's (den Link findest du bestimmt;-).
    Mittels QUSCRTUS lege ich einen USRSPC erst mal an (ich weiß nämlich nicht, ob das Spool-API dies tut).
    Nun gibt es das QUSRTVUS-API um die Daten auszulesen.
    Am Einfachsten ist es allerdings, im RPGle mit Pointern umzugehen als mit dem API.
    Per QUSPTRUS bekommst du einen Pointer für direkten Zugriff auf das USRSPC-Objekt:

    dMyUsPtr *
    dMyUsHDR ds based(MyUsPtr)

    In MyUsHdr kannst du die Felder anlog der API-Beschreibung definieren.

    Nun nimm als Beispiel die Adresse "Offset to First Buffer":

    dMyFrstBptr *
    dMyBuffer ds based(MyFrstBptr)

    Mittels "eval MyFrstBptr = MyUsPtr + OffsetfBuffer" weist du die Adresse zu und hast Zugriff auf den Puffer des 1. Satzes.
    Da die Informationen geschachtelt sind, ist es eine Rechnerei mitr den ganzen Adressen, aber doch relativ einfach, da du für jeden Typ der Information eine Based-DS nehmen kannst und den dazugehörigen Pointer über den Basis-Ptr und die relative Adresse ermitteln kannst.
    Dienstleistungen? Die gibt es hier: http://www.fuerchau.de
    Das Excel-AddIn: https://www.ftsolutions.de/index.php/downloads
    BI? Da war doch noch was: http://www.ftsolutions.de

  3. #3
    Registriert seit
    Feb 2018
    Beiträge
    7
    Zitat Zitat von Fuerchau Beitrag anzeigen
    ....
    Mittels "eval MyFrstBptr = MyUsPtr + OffsetfBuffer" weist du die Adresse zu und hast Zugriff auf den Puffer des 1. Satzes.
    ....
    yepp, das habe ich alles. die entscheidende stelle, wo es bei mir hakt, und da habe ich vermutlich einen Denkfehler oder was auch immer, ist die stelle, wo ich auf den puffer zugreife.
    sieht so aus mein Programm

    if open_spoolfile();
    if create_userspace();
    // Befüllen des User Space
    fill_userspace();
    // Zugriff auf User Space
    GetPointer(USERSPACENAME:UserSpacePointer);
    //User Space Informationen verarbeiten
    For UserSpaceCounter = 1 to ListHeader.Count;
    FieldPointer = UserSpacePointer + ListHeader.Offset
    + (ListHeader.Size * (UserSpaceCounter - 1));
    // irgendwas mit den Daten machen
    dsplytext = 'DS_SPFR0300.PRINT_DATA= '
    + %editc(DS_SPFR0300.PRINT_DATA:'X') ;
    dsply dsplytext ;
    endfor;
    // Userspace löschen
    delete_userspace();
    endif;
    Close_spoolfile();
    endif;


    das befüllen sieht so aus (vielleicht etwas übel geschrieben, aber ich arbeite viel mit DSen)
    ds_QSPGETSP.Spooled_file_handle
    = ds_QSPOPNSP.Spooled_file_handle_returned;
    ds_QSPGETSP.Qualified_user_space_name = USERSPACENAME;
    ds_QSPGETSP.Format_name = 'SPFR0300';
    ds_QSPGETSP.Ordinal_number_of_buffer_to_be_read = 8;
    ds_QSPGETSP.End_of_open_spooled_file = '*ERROR';
    clear ds_Error_code_ERRC0100;
    ds_QSPGETSP.Error_code = ds_Error_code_ERRC0100;
    // Einlesen Spoolfile in den Userspace
    QSPGETSP(ds_QSPGETSP.Spooled_file_handle
    : ds_QSPGETSP.Qualified_user_space_name
    : ds_QSPGETSP.Format_name
    : ds_QSPGETSP.Ordinal_number_of_buffer_to_be_read
    : ds_QSPGETSP.End_of_open_spooled_file
    : ds_QSPGETSP.Error_code
    );

    die Routinen create_userspace(), getpointer(...) und delete_userspace() sehen so aus, als würden sie ordnungsgemäß laufen

    hier noch ein paar variablen :

    dcl-s UserSpacePointer Pointer;
    dcl-s FieldPointer Pointer;
    Dcl-Ds ListHeader Based(UserSpacePointer) Qualified;
    Offset Int(10) Pos(125);
    Count Int(10) Pos(133);
    Size Int(10) Pos(137);
    End-Ds;
    Dcl-Ds ds_SPFR0300 Based(FieldPointer) Qualified;
    print_data int(10) pos(1); end-ds;
    Dcl-S UserSpaceCounter uns(20) inz;
    Dcl-S dsplytext char(50) inz;


    wenn ich nun mein Programm laufen lasse, kommen diese Meldungen:

    call testspoolf parm('jobname' 'user' '887773' 'TESTSPOOLF' '000001')
    Ownership of object @USERSPACE in QTEMP type *USRSPC changed.
    DSPLY DS_SPFR0300.PRINT_DATA= 0000000000
    Space offset X'00000000' or X'0000000000000000' is outside current limit
    for object @USERSPACE.
    End of requests.

    ich weiß nicht so recht, wie ich den puffer behandeln soll... oder ob im userspace wirklich was drinsteht (wie kann man das prüfen?)

    lg karin

  4. #4
    Registriert seit
    Jul 2002
    Beiträge
    218
    moin,

    da gab es mal einen Befehl dspusrspc in der Bibl. TAATOOL

  5. #5
    Registriert seit
    Feb 2001
    Beiträge
    20.206
    Die TAATOOLS gibt es (leider) nicht mehr, allerdings kann man sich da auch mit DMPOBJ/DMPSYSOBJ behelfen.
    Ggf. ein Grundsätzlicher Fehler:
    Die RPG-Zählung bei Positionen in der DS "POS(nn)" beginnt bei 1, die relative Position zu einer Adresse bei 0. Die API-Strukturen beginnen ebenso bei 0.
    Ich hoffe, du hast dies berücksichtigt.

    Beim Aufruf des Spool-API's gibt es eine Error-Struktur, die man korrekt definieren muss um einen Fehler mitzubekommen. In diesem Fall ist das API bereits gescheitert und im USRSPC steht halt nichts.

    ErrorStru DS <= nur schematisch;-)
    AvailBytes bin(4) inz(%size(ErrorStru))
    ProvBytes bin(4) inz(0)
    ErrorId char(7) inz <= CPFxxxx
    unused char(1) inz
    ErrorData char(512) inz <= eigentlich beliebig, Daten zur CPF

    Wenn du
    clear ds_Error_code_ERRC0100;
    ausführst, löscht du ebenso auch AvailBytes und kein API gibt einen Fehler zurück noch wird einer ausgelöst.
    Dies ist vollkommen unnötig.
    Ist nach dem API-Call ProvBytes > 0, dann ist ein Fehler aufgetreten, ansonsten sollten Daten im USRSPC stehen.

    Auch dieses ist falsch:
    FieldPointer = UserSpacePointer + ListHeader.Offset + (ListHeader.Size * (UserSpaceCounter - 1));
    Wenn du die Strukturen ansiehst, so enthält jeder Eintrag seine eigene Länge.
    Somit bekommt der Fieldpointer die 1. Adresse und muss um die Länge der Beschreibung verschoben werden. Die Anzahl der Einträge steht dann im Header, das ist korrekt.
    Dienstleistungen? Die gibt es hier: http://www.fuerchau.de
    Das Excel-AddIn: https://www.ftsolutions.de/index.php/downloads
    BI? Da war doch noch was: http://www.ftsolutions.de

  6. #6
    Registriert seit
    Feb 2018
    Beiträge
    7
    hallo allerseits,

    taatool hab ich hier, dspusrspc -> super!!
    boardmittel dmpobj -> DANKE!!!

    jetzt weiß ich zumindest, daß der userspace korrekt gefüllt ist

    werde mich nun den restlichen fehlern widmen...

    die ds_Error_code_ERRC0100 ist gemäß ibm-doku erstellt, müßte zumindest einigermaßen richtig sein, wenngleich ich das mit dem clear noch nicht verstanden habe warum ich den nicht machen soll. ich dachte, in der error steht dann nach dem prozeduraufruf ein fehler drin, wenn er zurückkommt? und aus Gewohnheit mache ich die felder vor dem prozeduraufruf leer. (nicht gut??)

    dcl-ds ds_Error_code_ERRC0100 qualified ;
    Bytes_provided int(10) Inz(%size(ds_Error_code_ERRC0100));
    Bytes_available int(10) inz;
    Exception_ID char(7);
    Reserved char(1);
    Exception_data varchar(128); -------------> änder ich gleich auf 512
    end-ds;

    zum rest:

    ich vermute, daß die logik, wie ich den fieldpointer errechne, noch nicht richtig ist. könnte daran liegen, daß ich dieses code-schnipsel kopiert habe aus einem Programm, das einen userspace mit völlig anderen Daten ausliest, wo das halt so paßt, hier aber halt eben nicht. werde weiter forschen :-)

    lg karin
    Last edited by karin; 07-02-18 at 10:08. Grund: korrektur

  7. #7
    Registriert seit
    Nov 2003
    Beiträge
    2.304
    DSPF und EDTF können übrigens auch mit Benutzerbereichen umgehen:

    DSPF STMF('/QSYS.LIB/Bibliothek.LIB/Name.USRSPC')
    EDTF STMF('/QSYS.LIB/Bibliothek.LIB/Name.USRSPC')

    Zu den Fehler-Formaten:
    Die Inhalt der einzelnen Felder der Fehler-Formate sind hier im Detail beschrieben.

  8. #8
    Registriert seit
    Feb 2001
    Beiträge
    20.206
    Ein Clear initialisiert mit dem Default.
    Ein Reset initialisiert mit den Werten, die durch INZ oder in der *INZSR festgelegt ist.

    Mit "Bytes_provided" teilst du dem API mit, wie lang der Puffer ist, den du im Fehlerfall eben zur Verfügung stellst.
    Nach dem Clear initialisiert du mit 0, also wir die Errorstruktur nicht gefüllt.

    Bei manchen API's kann man die Errorstruktur auch weglassen. In diesem Fall wird eine Escape-Message gesendet, die mit einer Monitor-Gruppe überwacht werden kann.

    Die Länge der Exception_data ist vollkommen egal, es kommt halt auf die möglichen Fehler-ID's und die verwendeten Datenfelder an (siehe DSPMSGD, Felddefinitionen).
    Willst du die Daten gar nicht auswerten, kann man das Feld auch weglassen.
    D.h., die Minimal-Struktur ist 16 Bytes.

    DMPOBJ/EDTF können eben auch Hex anzeigen, so dass man die Strukturen mit den relativen Adressen sich genauer anschauen kann.
    Dienstleistungen? Die gibt es hier: http://www.fuerchau.de
    Das Excel-AddIn: https://www.ftsolutions.de/index.php/downloads
    BI? Da war doch noch was: http://www.ftsolutions.de

  9. #9
    Registriert seit
    Feb 2018
    Beiträge
    7
    ok, ich habe jetzt ein Ergebnis hinbekommen, nicht schön, aber übungszweck erfüllt.
    fehler war tatsächlich die Adressierung des userspaces, diese habe ich geändert und nun sieht es schon ganz gut aus. ich kann die Inhalte des userspace z.b. mit DSPLY anzeigen, mehr brauche ich erst mal nicht.

    nun müßte ich noch eine sinnvolle schleife bauen und irgendwas sinnvolles mit dem userspace machen. hhm. wie ziemlich viele leute im Internet schon angedeutet haben, die spooldaten stehen nicht vollends brauchbar im userspace, jetzt müßte man Steuerzeichen rausfieseln und ähnliches. ist mir aber für den übungszweck nicht förderlich, lasse ich also erst mal bleiben.

    zumal ich das zusammenspiel von buffern, sizes und Offsets (beim spool-API Satzart SPFR0300) noch nicht durchdrungen habe. die logischen Erklärungen passen nicht zum DSPLY-Ergebnis, da muß es wohl noch ein paar kniffe geben, die sich mir nicht erschließen.

    lange rede kurzer sinn: ich habe einiges dazugelernt und bekomme nun wenigstens ein ordentliches grundgerüst für API-Verwendung hin, das war die grundidee der Übung.

    danke für alle hinweise!!
    lg karin

  10. #10
    Registriert seit
    Mar 2002
    Beiträge
    5.286
    ... einfacher geht es mit verfügbaren Komponenten (wer die bei sich reinkopiert, hat da etwas nicht verstanden!). Siehe: http://bender-dv.de/Snippets.html#APILIST

    D*B
    AS400 Freeware
    http://www.bender-dv.de
    Mit embedded SQL in RPG auf Datenbanken von ADABAS bis XBASE zugreifen
    http://sourceforge.net/projects/appserver4rpg/

  11. #11
    Registriert seit
    Oct 2013
    Beiträge
    171
    Für SCS gibt es eigentlich keinen vernünftigen Grund, CPYSPLF nicht zu verwenden.
    Und AFPDS/IPDS ist derart kompliziert, da hört sich jeder Spaß auf.
    Sprich: ich würde mir eine andere API-Thematik zum Spielen suchen.

Similar Threads

  1. Woher bekommt der QZDASOINIT seine Libl ?
    By dschroeder in forum IBM i Hauptforum
    Antworten: 16
    Letzter Beitrag: 17-03-16, 13:42
  2. NEWSboard linux - Brauchen wir so etwas?
    By Burgy Zapp in forum Intern - Hilfe - Feedback - Tests-Forum
    Antworten: 8
    Letzter Beitrag: 02-03-07, 13:24
  3. sagt jemanden TCPIP DATBASE SERVER etwas?
    By delphix in forum IBM i Hauptforum
    Antworten: 3
    Letzter Beitrag: 28-12-01, 16:18

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • You may not post attachments
  • You may not edit your posts
  •