[NEWSboard IBMi Forum]
Seite 1 von 3 1 2 ... Letzte
  1. #1
    Registriert seit
    Mar 2014
    Beiträge
    33

    Serviceprogramm und Speicher

    Hallo,

    ich habe eine Frage bezüglich Serviceprogramme und Speicher....
    Wir sind gerade dabei alle Dateizugriffe (SQL-Zugriffe) in Serviceprogramme auszulagern.
    Pro Stammdatei gibt es ein Serviceprogramme mit den entsprechenden Prozeduren (SELECT, WRITE, OPENCURSOR, FETCH usw..).

    Der Datenaustausch zwischen dem Serviceprogramm und dem aufrufendem Programmen erfolgt über eine externe Datenstruktur (Aufbau wie entsprechende Datei).
    Das Serviceprogramm übergibt bei Bedarf die komplette Datenstruktur (Datensatz) oder
    wenn gewollt durch GETTER entsprechenden Felder...

    Folgendes ist aufgefallen.
    Werden Prozeduren aus dem Serviceprogramm das erste Mal aufgerufen, ist vor dem Datenzugriff die Datenstruktur im Serviceprogramm leer.
    Nach dem Zugriff werden die Daten an das aufrufende Programm übergeben - dieses danach mit LR beendet. Es werden keine Aktivierungsgruppen beendet und die Bildschirmsession bleibt ebenfalls aktiv.

    Nach einiger Zeit wird nochmal ein Programm aufgerufen, das sich von Prozeduren aus dem Serviceprogramm bedient. Dabei ist aufgefallen, dass die Datenstruktur im Serviceprogramm immer noch mit Daten aus dem ersten Zugriff gefüllt ist?!?
    Liegt das daran, dass das Serviceprogramm nach dem ersten Aufruf im Speicher geblieben ist und gilt dieses innerhalb einer Session oder Systemübergreifend (was ja eigentlich nicht sein kann)??

    Wird die Bildschirmsession zwischen den Aufrufen beendet bzw. nach LR ein "RCLACTGRP ACTGRP(*ELIGIBLE)" abgesetzt ist die DS im Serviceprogramm beim nächsten Aufruf leer...

    Liegen wir da richtig mit unserer Vorgehensweise die Zugriffe auszulagern und muss man was Spezielles beachten - außer die DS vor jedem Zugriff zu clearen...

    P.S.
    Mir ist natürlich auch klar, dass bei einem internen Zugriff auf eine Datei (also ohne Serviceprogramm ) auch der letzte Datensatz im Speicher bleibt – aber nach LR ist alles wieder „sauber“.

    Viele Grüße

  2. #2
    Registriert seit
    Mar 2002
    Beiträge
    5.286
    ... ILE Programme (PGM/SRVPGM) bleiben von der ersten Benutzung bis zum löschen der Activation Group (diese hat Job Scope) im Speicher. Alle globalen Variablen behalten jeweils ihren letzten Inhalt (nennt man auch static storage). Lokaöe Variablen werden jeweils bei Start der Procedure neu angelegt und beim verlassen der Procedure weggeräumt (automatic storage).

    Vom Design her macht ihr alles richtig, der Inhalt des Datensatzes gehört zum Zustand des Moduls, muss also "Gedächtnis" haben und global deklariert werden.

    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/

  3. #3
    Registriert seit
    Feb 2001
    Beiträge
    20.207
    Ein Service-Programm kann auch ACTGRP(*CALLER) haben. Dann wird das Programm eben zusammen mit der ACTGRP des Aufrufers rausgeschmissen.
    Das hat auch den Effekt, dass das Programm mehrfach, eben je ACTGRP, im Speicher liegen kann.
    Zu bedenken ist, dass Serviceprogramme ja von verschiedenen Hauptprogrammen aufgerufen werden und somit SQL-Cursor vom Einen durch Andere zerstört werden können.

    Ein RCLACTGRP ACTGRP(*ELIGIBLE) hat ggf. bei Triggerprogrammen in eigenen ACTGRP's die Auswirkung, dass der Job beendet werden muss.
    Die weitere Ausführung der Trigger ist nicht mehr möglich. Dies könnte jedoch releaseabhängig und durch PTFs behoben sein.
    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

  4. #4
    Registriert seit
    Mar 2002
    Beiträge
    5.286
    Zitat Zitat von Fuerchau Beitrag anzeigen
    Ein Service-Programm kann auch ACTGRP(*CALLER) haben. Dann wird das Programm eben zusammen mit der ACTGRP des Aufrufers rausgeschmissen.
    Das hat auch den Effekt, dass das Programm mehrfach, eben je ACTGRP, im Speicher liegen kann.
    Zu bedenken ist, dass Serviceprogramme ja von verschiedenen Hauptprogrammen aufgerufen werden und somit SQL-Cursor vom Einen durch Andere zerstört werden können.

    Ein RCLACTGRP ACTGRP(*ELIGIBLE) hat ggf. bei Triggerprogrammen in eigenen ACTGRP's die Auswirkung, dass der Job beendet werden muss.
    Die weitere Ausführung der Trigger ist nicht mehr möglich. Dies könnte jedoch releaseabhängig und durch PTFs behoben sein.
    Datenbankmodule, wie vom OP angeführt, müssen ACTGRP(*CALLER), was üblicherweise default ist, haben, sonst wären sie nicht Transaktionsfähig (commit) und der Transaktionsmaster muss eine eigenen benannte ACTGRP oder *NEW haben - dann funzt das auch mit Cursor etc. wie gewollt.

    Bei den Trigger Programmen ist das ähnlich: ein Triggerprogramm in einer eigenen ACTGRP ist ein Kunstfehler, die müssen immer *CALLER haben - trotzdestonichts ist das beschrieben Verhalten für den abstrusen Fall (es gibt immer wieder Leute, die es gerne kompliziert haben) als Bug anzusehen.

    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/

  5. #5
    Registriert seit
    Mar 2014
    Beiträge
    33
    Unsere Serviceprogramme laufen alle unter der Aktivierungsgruppe *CALLER.
    Wir haben auch keine explizite Beendigung einer Aktivierungsgruppe.

    Klassischer Fall:
    Programme werden aus Menüs aufgerufen, benutzen die Serviceprogramme und werden beendet.
    Es sollte doch dann alles unter der Aktivierungsgruppe QILE und entsprechend unter Job Scope laufen oder?

    Zugriffe von anderen Hauptprogrammen und der verschiedenen Benutzer sollten sich doch somit nicht in die Quere kommen - oder habe ich da was missverstanden. Oder verhält sich das Serviceprogramm (inklusive Daten) wie ein Singleton in Java ?!?

  6. #6
    Registriert seit
    Aug 2001
    Beiträge
    2.869
    Zitat Zitat von Fuerchau Beitrag anzeigen
    Ein Service-Programm kann auch ACTGRP(*CALLER) haben. Dann wird das Programm eben zusammen mit der ACTGRP des Aufrufers rausgeschmissen.
    Das hat auch den Effekt, dass das Programm mehrfach, eben je ACTGRP, im Speicher liegen kann.
    Zu bedenken ist, dass Serviceprogramme ja von verschiedenen Hauptprogrammen aufgerufen werden und somit SQL-Cursor vom Einen durch Andere zerstört werden können.
    ... und wenn man Pech hat, wird das Service-Programm, das mit Aktivierungsgruppe *CALLER erstellt wurde von einem Programm aufgerfuen, das ebenfalls mit *CALLER erstellt wurde.
    Wird nun das rufende Programm seinerseits von einem OPM-Programm (RPGIII oder RPGIV, das mit DFTACTGRP *YES erstellt wurde) aufgerufen, läuft alles in der Default-Aktivierungsgruppe und kann nur durch Beendigung des Jobs aus dem Speicher entfernt werden.
    RCLRSC entfernt übrigens weder ein ILE-Programm noch ein Service-Programm aus dem Speicher! Es werden lediglich die in den ILE-(Service-)Programmen geöffneten Dateien geschlossen und der reservierte statische Speicher initialisiert.

    Wird ein Service-Programm (bzw. Prozeduren aus diesem Service-Programm), das Aktivierungsgruppe *CALLER aktiviert wird, von mehereren Programmen mit unterschiedlichen Aktivierungsgruppen aufgerufen, so wird das Service-Programm mehrfach aktiviert.

    Ob der "gleiche" SQL-Cursor mehrfach in unterschiedlichen Aktivierungsgruppen oder in der gleichen Aktivierungsgruppe angesprochen wird, stellt kein Problem dar. Jedes SQL-Statement, das ausgeführt wird, erhält seinen eigenen ODP (Open Data Path). Wird also der gleiche Cursor in mehreren Aktivieru ngsgruppen aktiviert, so werden auch mehrere ODPs geöffnet. Was dabei allerdings zu berücksichtigen ist, ist, dass der FULL OPEN, also das erste Öffnen eines ODPs ein zeitaufwändiger Prozess ist. (Wesentlich zeitaufwändiger als eine Datei für native I/O zu öffnen!)
    Deshalb sollte versucht werden die FULL OPENs bzw. die Anzahl der ODPs zu minimieren.

    Service-Programme, die allerdings Insert/Update/Delete-Prozeduren beinhalten, sollten immer mit Aktivierungsgruppe *CALLER erstellt werden, wegen der Commitment-Steuerung (wird per Default mit Commitmentscope *ACTGRP gestartet!)

    Ein RCLACTGRP ACTGRP(*ELIGIBLE) hat ggf. bei Triggerprogrammen in eigenen ACTGRP's die Auswirkung, dass der Job beendet werden muss.
    Die weitere Ausführung der Trigger ist nicht mehr möglich. Dies könnte jedoch releaseabhängig und durch PTFs behoben sein.
    Von einem RCLACTGRP ACTGRP(*ELIGIBLE) sollte man die Finger lassen und allenfalls in Testumgebungen verwenden.
    Trigger-Programme sollten nicht in benannten Aktivierungsgruppen, sondern in Aktivierungsgruppe *CALLER erstellt werden (SQL-Trigger werden automatisch mit Aktivierungsgruppe *CALLER erstellt).

    Die Probleme mit den Triggern sind i.d.R. hausgemacht, d.h. falsche Aktivierungsgruppen und die Ausführung von RCLRSC und RCLACTGRP *ELIGIBLE, die man auf alle Fälle überdenken sollte.

    Birgitta
    Birgitta Hauser

    Anwendungsmodernisierung, Beratung, Schulungen, Programmierung im Bereich RPG, SQL und Datenbank
    IBM Champion seit 2020 - 4. Jahr in Folge
    Birgitta Hauser - Modernization - Education - Consulting on IBM i

  7. #7
    Registriert seit
    Mar 2002
    Beiträge
    5.286
    Zitat Zitat von Tonazzo Beitrag anzeigen
    Unsere Serviceprogramme laufen alle unter der Aktivierungsgruppe *CALLER.
    Wir haben auch keine explizite Beendigung einer Aktivierungsgruppe.

    Klassischer Fall:
    Programme werden aus Menüs aufgerufen, benutzen die Serviceprogramme und werden beendet.
    Es sollte doch dann alles unter der Aktivierungsgruppe QILE und entsprechend unter Job Scope laufen oder?

    Zugriffe von anderen Hauptprogrammen und der verschiedenen Benutzer sollten sich doch somit nicht in die Quere kommen - oder habe ich da was missverstanden. Oder verhält sich das Serviceprogramm wie ein Singleton in Java ?!?
    ... alles in QILE laufen zu lassen ist nicht sinnvoll, damit ist nicht sichergestellt, dass zwei Programme im Callstack sich gegenseitig den einen Cursor, den sie haben kaputt machen. Besser ist m.E. Name der ACTGRP = Programmname, dann ist jedes Programm für seine abhängigen Cursor selber verantwortlich. Falls über Verzweigungen rekursiv aufgerufen werden könnte, ist *NEW erforderlich.

    Ein wesentlicher Unterschied zwischen der ILE runtime und Java ist, dass sich in Java mehrere Benutzer eine JVM teilen, also gemeinsame Ressourcen (shared Memory) haben, Bei ILE hat jeder Job seine eigene abgeschottete Umgebung, mehrere Jobs haben (aus Benutzersicht) kein shared memory.
    Ein weiterer wesentlicher Unterschied ist, dass ich in Java die Lebensdauer aller Objekte selber kontrolliere, in ILE ist das nur sehr eingeschränkt möglich (erkennt man daran, dass es kein new gibt und die Erzeugung von (runtime) Objekten automatisch passiert (also immer nur eines pro ACTGRP, oder nur kurzlebige := ACTGRP(*NEW)) zudem muss das alles schon zur compiletime festgelegt werden.

    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/

  8. #8
    Registriert seit
    Mar 2002
    Beiträge
    5.286
    Zitat Zitat von B.Hauser Beitrag anzeigen
    Ob der "gleiche" SQL-Cursor mehrfach ... in der gleichen Aktivierungsgruppe angesprochen wird, stellt kein Problem dar.
    ...
    Was dabei allerdings zu berücksichtigen ist, ist, dass der FULL OPEN, also das erste Öffnen eines ODPs ein zeitaufwändiger Prozess ist. (Wesentlich zeitaufwändiger als eine Datei für native I/O zu öffnen!)
    Deshalb sollte versucht werden die FULL OPENs bzw. die Anzahl der ODPs zu minimieren.

    Birgitta
    ... in der gleich Aktivierungsgruppe gibt es jeden Cursor nur einmal, was bei mehrfachen Aufrufen aus unterschiedlichen Programmen entweder dazu führt, dass das zweite Programm diesen nicht neu öffnen kann (Cursorstate not valid), oder dem ersten Prozess den Cursor zerklopft.
    Beim fetch würde sich das dann so auswirken, dass wenn die Programme abwechselnd lesen, jedes Programm nur jeden zweiten Satz zu sehen bekäme.

    Das mit dem full open ist wieder mal nur fast richtig: im richtigen Leben braucht man sich nicht darum zu sorgen:
    - bei sinnigem Index design dauert sowas ein paar Millisekunden
    - die Datenbank macht ohnehin lazy closes, sodass es für die Laufzeit unerheblich ist, ob das 1 oder 3 millisekunden dauert, da die Zeiten für den fetch das dominieren.
    Richtig wäre hier: man muss die Anzahl der fetch Operationen minimieren
    - ein block fetch von 1000 records dauert so lange wie ein single fetch
    - allerdings ist der positioned update soviel schneller als der searched update, dass selbiger dieses bei nicht read only Betrieb bei DB2/400 wieder reinholt.

    D*B

    PS: eine Ergänzung noch:
    - cachen kann Wunder wirken!!!
    AS400 Freeware
    http://www.bender-dv.de
    Mit embedded SQL in RPG auf Datenbanken von ADABAS bis XBASE zugreifen
    http://sourceforge.net/projects/appserver4rpg/

  9. #9
    Registriert seit
    Mar 2014
    Beiträge
    33
    Damit es jetzt nicht zu verwirrend wird, wir gehen dann folgendermaßen vor:

    Umwandlung Triggerprogramme:

    CRTBNDRPG PGM(LIB/TRIGGERPGM)
    SRCFILE(LIB/QTRGSRC)
    SRCMBR(TRIGGERPGM)
    DFTACTGRP(*NO)
    ACTGRP(*CALLER)

    Umwandlung Serviceprogramme:

    CRTSQLRPGI OBJ(LIB/SRVPGM)
    SRCFILE(LIB/QSRVSRC)
    OBJTYPE(*MODULE)

    CRTSRVPGM SRVPGM(LIB/SRVPGM)
    SRCFILE(LIB/QBNDSRC)
    TEXT('Zugriff Stamm')
    ACTGRP(SRVPGM)


    Andere Hauptprogramme, die Serviceprogramme benutzen.
    (Listprogramme, Anzeigeprogramme, Verwaltungsprogramme etc.


    Programm . . . . . . . : DIALOGPGM Bibliothek . . . . . . : LIB
    Eigner . . . . . . .... . .: USER1
    Programmattribut . .: RPGLE
    Detail . . . . . . . . .....: *BASIC


    Informationen zur Programmerstellung:
    Programmerstellungsdatum/-zeit . . . . . . . . : 15.09.15 10:02:20
    Programmart . . . . . . . . . . . . . . . . . : ILE
    Modul der Programmeingangsprozedur . . . . . . : DIALOGPGM
    Bibliothek . . . . . . . . . . . . . . . . . : QTEMP
    Attribut der Aktivierungsgruppe . . . . . . . : QILE
    Gemeinsam benutzte Aktivierungsgruppe . . . . : *NO
    Benutzerprofil . . . . . . . . . . . . . . . . : *USER
    Übernommene Berechtigung verwenden . . . . . . : *YES
    ID des codierten Zeichensatzes (CCSID) . . . . : 65535
    Anzahl der Module . . . . . . . . . . . . . . : 1


    Liegen wir somit richtig??

  10. #10
    Registriert seit
    Jul 2002
    Beiträge
    331
    Eine benannte Activation Group bei einem Service Programm, ist grenzwertig, dort solltet ihr mit *CALLER arbeiten. Die Programme, welche die Service Programm verwenden, können dagegen eher eine benannte Activation group bekommen.

  11. #11
    Registriert seit
    Mar 2014
    Beiträge
    33
    OK dann habe ich H. Bender missverstanden....

    Also Trigger und Serviceprogramme alle in *CALLER

    Und die entsprechenden Hauptprogramme, die verschiedene Serviceprogramme etc. benutzen in
    benannte Activation Group.. PgmName = Name der Activation Group.


    Das sollte es dann aber gewesen sein.... Alles nicht so einfach ;-)

  12. #12
    Registriert seit
    Aug 2001
    Beiträge
    2.869
    Zitat Zitat von Tonazzo Beitrag anzeigen
    Also Trigger und Serviceprogramme alle in *CALLER

    Und die entsprechenden Hauptprogramme, die verschiedene Serviceprogramme etc. benutzen in
    benannte Activation Group.. PgmName = Name der Activation Group.
    Ich würde das etwas eingrenzen:
    1. Programme, die direkt aufgerfuen werden (Menü, Submit) in benannte Aktivierungsgruppen (PGM = Aktivierungsgruppe ist m.E. eine gute Idee).
    2. Trigger in Aktivierungsgruppe *CALLER wegen Commitment Steuerung
    3. Service-Programme mit Insert/Update und Delete-Prozeduren in Aktivierungsgruppe *CALLER
    4. Service-Programme mit universell einsetzbaren Prozeduren, z.B. Datums-Rechnung, String-Funktionen, Prüf-Routinen etc. in eine benannte Aktivierungsgruppe (z.B. Service-Programm-Name = Aktivierungsgruppe).
    Warum sollten auch solche allgemeingültigen Service-Programme x und y Mal aktiviert werden?

    Birgitta
    Birgitta Hauser

    Anwendungsmodernisierung, Beratung, Schulungen, Programmierung im Bereich RPG, SQL und Datenbank
    IBM Champion seit 2020 - 4. Jahr in Folge
    Birgitta Hauser - Modernization - Education - Consulting on IBM i

Similar Threads

  1. User Defined Function in SQL, Datumsübergabe an Serviceprogramm
    By dschroeder in forum NEWSboard Programmierung
    Antworten: 27
    Letzter Beitrag: 02-12-14, 10:33
  2. CLLE als Prozedur ins Serviceprogramm
    By Etherion in forum NEWSboard Programmierung
    Antworten: 6
    Letzter Beitrag: 30-09-14, 14:36
  3. Antworten: 2
    Letzter Beitrag: 12-08-14, 13:09
  4. hinzufügen Prozedur in bestehendes Serviceprogramm
    By Tonazzo in forum NEWSboard Programmierung
    Antworten: 5
    Letzter Beitrag: 11-03-14, 10:26
  5. SQL Funktion ruft Serviceprogramm auf - Parameter übergabe
    By loisl in forum NEWSboard Programmierung
    Antworten: 4
    Letzter Beitrag: 08-11-13, 17:37

Tags for this Thread

Berechtigungen

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