[NEWSboard IBMi Forum]
Seite 1 von 2 1 2 Letzte

Hybrid View

  1. #1
    Registriert seit
    Aug 2001
    Beiträge
    2.942
    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 - 5. Jahr in Folge
    Birgitta Hauser - Modernization - Education - Consulting on IBM i

  2. #2
    Registriert seit
    Mar 2002
    Beiträge
    5.389
    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/

  3. #3
    Registriert seit
    Mar 2014
    Beiträge
    35
    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??

  4. #4
    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.

  5. #5
    Registriert seit
    Mar 2014
    Beiträge
    35
    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 ;-)

  6. #6
    Registriert seit
    Aug 2001
    Beiträge
    2.942
    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 - 5. Jahr in Folge
    Birgitta Hauser - Modernization - Education - Consulting on IBM i

  7. #7
    Registriert seit
    Jul 2002
    Beiträge
    331
    Zitat Zitat von B.Hauser Beitrag anzeigen
    Ich würde das etwas eingrenzen:
    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
    Schon richtig, aber wenn man beginnt mit Activation Groups zu arbeiten, finde ich persönlich, kann man auf die paar Millisekunden und das doppelte laden durchaus hinweg sehen. Sollte man an dieser Stelle Fehler machen, kann am Ende das ganze Projekt scheitern. Erst mal Erfahrungen sammeln und dann die Services identifizieren, die "Zustandslos" sein können und dann diese in eine benannte Group packen.... macht die Sache gerade am Anfang einen Tick leichte.

  8. #8
    Registriert seit
    Mar 2014
    Beiträge
    35
    Ist es sinnvoll nach Beendigung der Hauptprogramme (Menü, Submit) die benannte
    Aktivierungsgruppe mit RCLACTGRP auch zu beenden oder riskiere ich damit enventuell irgendwelche
    Datenverluste.

  9. #9
    Registriert seit
    Jul 2002
    Beiträge
    331
    Wenn der Job zu Ende ist, ist es egal was in der Activation Group läuft, da sich die Activation Group nur auf den Job bezieht.
    Wenn der Job nach der Beendigung weiter läuft, kann man das ruhig machen...es schadet zumindest nichts. Allerdings weiß ich nicht, wie es sich verhält, wenn man dann wieder in das Hauptprogramm geht, da kennen sich andere hier besser aus. Ich glaube aber bei erneuten Aufruf, geht alles wieder von vorne los....
    Aber Vorsicht, bei CL - Programmen die einen OVR benutzen muss der Overscope auf *JOB gesetzt werden, sonst bekommt man an der Stelle ein paar Problem.

  10. #10
    Registriert seit
    Mar 2014
    Beiträge
    35
    Vielen Dank an alle Beteiligten für die gute und schnelle Unterstützung.

  11. #11
    Registriert seit
    Mar 2002
    Beiträge
    5.389
    Zitat Zitat von Tonazzo Beitrag anzeigen
    Ist es sinnvoll nach Beendigung der Hauptprogramme (Menü, Submit) die benannte
    Aktivierungsgruppe mit RCLACTGRP auch zu beenden oder riskiere ich damit enventuell irgendwelche
    Datenverluste.
    ... den Effekt kannst Du billiger haben, wenn Du die Programme mit ACTGRP(*NEW) wandelst. Beim SBMJOB wird der Job beendet und damit alles automatisch abgebaut.

    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/

  12. #12
    Registriert seit
    Feb 2001
    Beiträge
    20.785
    ACTGRP(*NEW) wird automatisch aufgelöst, wenn das oberste Programm returniert. Dabei ist es unerheblich, ob *INLR *on oder *off ist.
    *New ist ggf. erforderlich wenn man Programme (ohne nomain) rekursiv aufruft und eigene Commit-Grenzen braucht.
    Der Nachteil sind sicherlich die getrennten Commit-Definitionen, da hat jede ACTGRP seine Eigene.
    Wird *NEW z.B. aufgelöst, wird automatisch ein Rollback durchgeführt.
    Trigger in eigene ACTGRP's zu stellen macht manchmal schon Sinn, liegt aber halt an der Aufgabenstellung zumal diese ja im Rollbackfall auch wieder aufgerufen werden.

    Eine eigene ACTGRP lohnt sich z.B. für einen "Sperrservice" der über mehrere Commit-Grenzen bestehen bleiben muss. Dies geht mit dann mit diversen Satzsperren die mit MyLock(Key)/MyUnlock(Key) aufgerufen werden können und automatisch bei Jobende rausfliegen (war irgendwann mal Dieters Vorschlag).

    Diverse benannte ACTGRP's machen also durchaus Sinn.

    Es gibt z.B. auch 2 DFTACTGRP's, die 1. ist für Systemprogramme, die 2. für eigene Programme. Da nützt auch *CALLER nichts, die 1. ist einfach tabu.
    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

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
  •