-
 Zitat von Fuerchau
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
-
 Zitat von B.Hauser
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!!!
-
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??
-
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.
-
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 ;-)
-
 Zitat von Tonazzo
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
-
 Zitat von B.Hauser
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.
-
Ist es sinnvoll nach Beendigung der Hauptprogramme (Menü, Submit) die benannte
Aktivierungsgruppe mit RCLACTGRP auch zu beenden oder riskiere ich damit enventuell irgendwelche
Datenverluste.
-
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.
-
Vielen Dank an alle Beteiligten für die gute und schnelle Unterstützung.
-
 Zitat von Tonazzo
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
-
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.
Similar Threads
-
By dschroeder in forum NEWSboard Programmierung
Antworten: 27
Letzter Beitrag: 02-12-14, 10:33
-
By Etherion in forum NEWSboard Programmierung
Antworten: 6
Letzter Beitrag: 30-09-14, 14:36
-
By Etherion in forum NEWSboard Programmierung
Antworten: 2
Letzter Beitrag: 12-08-14, 13:09
-
By Tonazzo in forum NEWSboard Programmierung
Antworten: 5
Letzter Beitrag: 11-03-14, 10:26
-
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
-
Foren-Regeln
|
Erweiterte Foren Suche
Google Foren Suche
Forum & Artikel Update eMail
AS/400 / IBM i
Server Expert Gruppen
Unternehmens IT
|
Kategorien online Artikel
- Big Data, Analytics, BI, MIS
- Cloud, Social Media, Devices
- DMS, Archivierung, Druck
- ERP + Add-ons, Business Software
- Hochverfügbarkeit
- Human Resources, Personal
- IBM Announcements
- IT-Karikaturen
- Leitartikel
- Load`n`go
- Messen, Veranstaltungen
- NEWSolutions Dossiers
- Programmierung
- Security
- Software Development + Change Mgmt.
- Solutions & Provider
- Speicher – Storage
- Strategische Berichte
- Systemmanagement
- Tools, Hot-Tips
Auf dem Laufenden bleiben
|
Bookmarks